editor.rs

    1#![allow(unused)]
    2mod blink_manager;
    3pub mod display_map;
    4mod editor_settings;
    5mod element;
    6mod inlay_hint_cache;
    7
    8mod git;
    9mod highlight_matching_bracket;
   10mod hover_popover;
   11pub mod items;
   12mod link_go_to_definition;
   13mod mouse_context_menu;
   14pub mod movement;
   15mod persistence;
   16pub mod scroll;
   17pub mod selections_collection;
   18
   19#[cfg(test)]
   20mod editor_tests;
   21#[cfg(any(test, feature = "test-support"))]
   22pub mod test;
   23use ::git::diff::DiffHunk;
   24use aho_corasick::AhoCorasick;
   25use anyhow::{anyhow, Context as _, Result};
   26use blink_manager::BlinkManager;
   27use client::{ClickhouseEvent, Client, Collaborator, ParticipantIndex, TelemetrySettings};
   28use clock::ReplicaId;
   29use collections::{BTreeMap, Bound, HashMap, HashSet, VecDeque};
   30use convert_case::{Case, Casing};
   31use copilot::Copilot;
   32pub use display_map::DisplayPoint;
   33use display_map::*;
   34pub use editor_settings::EditorSettings;
   35pub use element::{
   36    Cursor, EditorElement, HighlightedRange, HighlightedRangeLine, LineWithInvisibles,
   37};
   38use futures::FutureExt;
   39use fuzzy::{StringMatch, StringMatchCandidate};
   40use git::diff_hunk_to_display;
   41use gpui::{
   42    action, actions, div, point, prelude::*, px, relative, rems, size, uniform_list, AnyElement,
   43    AppContext, AsyncWindowContext, BackgroundExecutor, Bounds, ClipboardItem, Component, Context,
   44    EventEmitter, FocusHandle, FontFeatures, FontStyle, FontWeight, HighlightStyle, Hsla,
   45    InputHandler, KeyContext, Model, MouseButton, ParentComponent, Pixels, Render, Styled,
   46    Subscription, Task, TextStyle, UniformListScrollHandle, View, ViewContext, VisualContext,
   47    WeakView, WindowContext,
   48};
   49use highlight_matching_bracket::refresh_matching_bracket_highlights;
   50use hover_popover::{hide_hover, HoverState};
   51use inlay_hint_cache::{InlayHintCache, InlaySplice, InvalidationStrategy};
   52pub use items::MAX_TAB_TITLE_LEN;
   53use itertools::Itertools;
   54pub use language::{char_kind, CharKind};
   55use language::{
   56    language_settings::{self, all_language_settings, InlayHintSettings},
   57    point_from_lsp, AutoindentMode, BracketPair, Buffer, CodeAction, Completion, CursorShape,
   58    Diagnostic, IndentKind, IndentSize, Language, LanguageRegistry, LanguageServerName,
   59    OffsetRangeExt, Point, Selection, SelectionGoal, TransactionId,
   60};
   61use lazy_static::lazy_static;
   62use link_go_to_definition::{GoToDefinitionLink, InlayHighlight, LinkGoToDefinitionState};
   63use lsp::{DiagnosticSeverity, Documentation, LanguageServerId};
   64use movement::TextLayoutDetails;
   65use multi_buffer::ToOffsetUtf16;
   66pub use multi_buffer::{
   67    Anchor, AnchorRangeExt, ExcerptId, ExcerptRange, MultiBuffer, MultiBufferSnapshot, ToOffset,
   68    ToPoint,
   69};
   70use ordered_float::OrderedFloat;
   71use parking_lot::{Mutex, RwLock};
   72use project::{FormatTrigger, Location, Project, ProjectPath, ProjectTransaction};
   73use rand::prelude::*;
   74use rpc::proto::*;
   75use scroll::{
   76    autoscroll::Autoscroll, OngoingScroll, ScrollAnchor, ScrollManager, ScrollbarAutoHide,
   77};
   78use selections_collection::{resolve_multiple, MutableSelectionsCollection, SelectionsCollection};
   79use serde::{Deserialize, Serialize};
   80use settings::{Settings, SettingsStore};
   81use smallvec::SmallVec;
   82use snippet::Snippet;
   83use std::{
   84    any::TypeId,
   85    borrow::Cow,
   86    cmp::{self, Ordering, Reverse},
   87    mem,
   88    num::NonZeroU32,
   89    ops::{ControlFlow, Deref, DerefMut, Range, RangeInclusive},
   90    path::Path,
   91    sync::Arc,
   92    time::{Duration, Instant},
   93};
   94pub use sum_tree::Bias;
   95use sum_tree::TreeMap;
   96use text::{OffsetUtf16, Rope};
   97use theme::{
   98    ActiveTheme, DiagnosticStyle, PlayerColor, SyntaxTheme, Theme, ThemeColors, ThemeSettings,
   99};
  100use ui::{v_stack, HighlightedLabel, IconButton, StyledExt, Tooltip};
  101use util::{post_inc, RangeExt, ResultExt, TryFutureExt};
  102use workspace::{
  103    item::{ItemEvent, ItemHandle},
  104    searchable::SearchEvent,
  105    ItemNavHistory, SplitDirection, ViewId, Workspace,
  106};
  107
  108const CURSOR_BLINK_INTERVAL: Duration = Duration::from_millis(500);
  109const MAX_LINE_LEN: usize = 1024;
  110const MIN_NAVIGATION_HISTORY_ROW_DELTA: i64 = 10;
  111const MAX_SELECTION_HISTORY_LEN: usize = 1024;
  112const COPILOT_DEBOUNCE_TIMEOUT: Duration = Duration::from_millis(75);
  113pub const CODE_ACTIONS_DEBOUNCE_TIMEOUT: Duration = Duration::from_millis(250);
  114pub const DOCUMENT_HIGHLIGHTS_DEBOUNCE_TIMEOUT: Duration = Duration::from_millis(75);
  115
  116pub const FORMAT_TIMEOUT: Duration = Duration::from_secs(2);
  117
  118// pub fn render_parsed_markdown<Tag: 'static>(
  119//     parsed: &language::ParsedMarkdown,
  120//     editor_style: &EditorStyle,
  121//     workspace: Option<WeakView<Workspace>>,
  122//     cx: &mut ViewContext<Editor>,
  123// ) -> Text {
  124//     enum RenderedMarkdown {}
  125
  126//     let parsed = parsed.clone();
  127//     let view_id = cx.view_id();
  128//     let code_span_background_color = editor_style.document_highlight_read_background;
  129
  130//     let mut region_id = 0;
  131
  132//     todo!()
  133//     // Text::new(parsed.text, editor_style.text.clone())
  134//     //     .with_highlights(
  135//     //         parsed
  136//     //             .highlights
  137//     //             .iter()
  138//     //             .filter_map(|(range, highlight)| {
  139//     //                 let highlight = highlight.to_highlight_style(&editor_style.syntax)?;
  140//     //                 Some((range.clone(), highlight))
  141//     //             })
  142//     //             .collect::<Vec<_>>(),
  143//     //     )
  144//     //     .with_custom_runs(parsed.region_ranges, move |ix, bounds, cx| {
  145//     //         region_id += 1;
  146//     //         let region = parsed.regions[ix].clone();
  147
  148//     //         if let Some(link) = region.link {
  149//     //             cx.scene().push_cursor_region(CursorRegion {
  150//     //                 bounds,
  151//     //                 style: CursorStyle::PointingHand,
  152//     //             });
  153//     //             cx.scene().push_mouse_region(
  154//     //                 MouseRegion::new::<(RenderedMarkdown, Tag)>(view_id, region_id, bounds)
  155//     //                     .on_down::<Editor, _>(MouseButton::Left, move |_, _, cx| match &link {
  156//     //                         markdown::Link::Web { url } => cx.platform().open_url(url),
  157//     //                         markdown::Link::Path { path } => {
  158//     //                             if let Some(workspace) = &workspace {
  159//     //                                 _ = workspace.update(cx, |workspace, cx| {
  160//     //                                     workspace.open_abs_path(path.clone(), false, cx).detach();
  161//     //                                 });
  162//     //                             }
  163//     //                         }
  164//     //                     }),
  165//     //             );
  166//     //         }
  167
  168//     //         if region.code {
  169//     //             cx.draw_quad(Quad {
  170//     //                 bounds,
  171//     //                 background: Some(code_span_background_color),
  172//     //                 corner_radii: (2.0).into(),
  173//     //                 order: todo!(),
  174//     //                 content_mask: todo!(),
  175//     //                 border_color: todo!(),
  176//     //                 border_widths: todo!(),
  177//     //             });
  178//     //         }
  179//     //     })
  180//     //     .with_soft_wrap(true)
  181// }
  182
  183#[action]
  184pub struct SelectNext {
  185    #[serde(default)]
  186    pub replace_newest: bool,
  187}
  188
  189#[action]
  190pub struct SelectPrevious {
  191    #[serde(default)]
  192    pub replace_newest: bool,
  193}
  194
  195#[action]
  196pub struct SelectAllMatches {
  197    #[serde(default)]
  198    pub replace_newest: bool,
  199}
  200
  201#[action]
  202pub struct SelectToBeginningOfLine {
  203    #[serde(default)]
  204    stop_at_soft_wraps: bool,
  205}
  206
  207#[action]
  208pub struct MovePageUp {
  209    #[serde(default)]
  210    center_cursor: bool,
  211}
  212
  213#[action]
  214pub struct MovePageDown {
  215    #[serde(default)]
  216    center_cursor: bool,
  217}
  218
  219#[action]
  220pub struct SelectToEndOfLine {
  221    #[serde(default)]
  222    stop_at_soft_wraps: bool,
  223}
  224
  225#[action]
  226pub struct ToggleCodeActions {
  227    #[serde(default)]
  228    pub deployed_from_indicator: bool,
  229}
  230
  231#[action]
  232pub struct ConfirmCompletion {
  233    #[serde(default)]
  234    pub item_ix: Option<usize>,
  235}
  236
  237#[action]
  238pub struct ConfirmCodeAction {
  239    #[serde(default)]
  240    pub item_ix: Option<usize>,
  241}
  242
  243#[action]
  244pub struct ToggleComments {
  245    #[serde(default)]
  246    pub advance_downwards: bool,
  247}
  248
  249#[action]
  250pub struct FoldAt {
  251    pub buffer_row: u32,
  252}
  253
  254#[action]
  255pub struct UnfoldAt {
  256    pub buffer_row: u32,
  257}
  258
  259#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
  260pub enum InlayId {
  261    Suggestion(usize),
  262    Hint(usize),
  263}
  264
  265impl InlayId {
  266    fn id(&self) -> usize {
  267        match self {
  268            Self::Suggestion(id) => *id,
  269            Self::Hint(id) => *id,
  270        }
  271    }
  272}
  273
  274actions!(
  275    AddSelectionAbove,
  276    AddSelectionBelow,
  277    Backspace,
  278    Cancel,
  279    ConfirmRename,
  280    ContextMenuFirst,
  281    ContextMenuLast,
  282    ContextMenuNext,
  283    ContextMenuPrev,
  284    ConvertToKebabCase,
  285    ConvertToLowerCamelCase,
  286    ConvertToLowerCase,
  287    ConvertToSnakeCase,
  288    ConvertToTitleCase,
  289    ConvertToUpperCamelCase,
  290    ConvertToUpperCase,
  291    Copy,
  292    CopyHighlightJson,
  293    CopyPath,
  294    CopyRelativePath,
  295    Cut,
  296    CutToEndOfLine,
  297    Delete,
  298    DeleteLine,
  299    DeleteToBeginningOfLine,
  300    DeleteToEndOfLine,
  301    DeleteToNextSubwordEnd,
  302    DeleteToNextWordEnd,
  303    DeleteToPreviousSubwordStart,
  304    DeleteToPreviousWordStart,
  305    DuplicateLine,
  306    FindAllReferences,
  307    Fold,
  308    FoldSelectedRanges,
  309    Format,
  310    GoToDefinition,
  311    GoToDefinitionSplit,
  312    GoToDiagnostic,
  313    GoToHunk,
  314    GoToPrevDiagnostic,
  315    GoToPrevHunk,
  316    GoToTypeDefinition,
  317    GoToTypeDefinitionSplit,
  318    HalfPageDown,
  319    HalfPageUp,
  320    Hover,
  321    Indent,
  322    JoinLines,
  323    LineDown,
  324    LineUp,
  325    MoveDown,
  326    MoveLeft,
  327    MoveLineDown,
  328    MoveLineUp,
  329    MoveRight,
  330    MoveToBeginning,
  331    MoveToBeginningOfLine,
  332    MoveToEnclosingBracket,
  333    MoveToEnd,
  334    MoveToEndOfLine,
  335    MoveToEndOfParagraph,
  336    MoveToNextSubwordEnd,
  337    MoveToNextWordEnd,
  338    MoveToPreviousSubwordStart,
  339    MoveToPreviousWordStart,
  340    MoveToStartOfParagraph,
  341    MoveUp,
  342    Newline,
  343    NewlineAbove,
  344    NewlineBelow,
  345    NextScreen,
  346    OpenExcerpts,
  347    Outdent,
  348    PageDown,
  349    PageUp,
  350    Paste,
  351    Redo,
  352    RedoSelection,
  353    Rename,
  354    RestartLanguageServer,
  355    RevealInFinder,
  356    ReverseLines,
  357    ScrollCursorBottom,
  358    ScrollCursorCenter,
  359    ScrollCursorTop,
  360    SelectAll,
  361    SelectDown,
  362    SelectLargerSyntaxNode,
  363    SelectLeft,
  364    SelectLine,
  365    SelectRight,
  366    SelectSmallerSyntaxNode,
  367    SelectToBeginning,
  368    SelectToEnd,
  369    SelectToEndOfParagraph,
  370    SelectToNextSubwordEnd,
  371    SelectToNextWordEnd,
  372    SelectToPreviousSubwordStart,
  373    SelectToPreviousWordStart,
  374    SelectToStartOfParagraph,
  375    SelectUp,
  376    ShowCharacterPalette,
  377    ShowCompletions,
  378    ShuffleLines,
  379    SortLinesCaseInsensitive,
  380    SortLinesCaseSensitive,
  381    SplitSelectionIntoLines,
  382    Tab,
  383    TabPrev,
  384    ToggleInlayHints,
  385    ToggleSoftWrap,
  386    Transpose,
  387    Undo,
  388    UndoSelection,
  389    UnfoldLines,
  390);
  391
  392enum DocumentHighlightRead {}
  393enum DocumentHighlightWrite {}
  394enum InputComposition {}
  395
  396#[derive(Copy, Clone, PartialEq, Eq)]
  397pub enum Direction {
  398    Prev,
  399    Next,
  400}
  401
  402pub fn init_settings(cx: &mut AppContext) {
  403    EditorSettings::register(cx);
  404}
  405
  406pub fn init(cx: &mut AppContext) {
  407    init_settings(cx);
  408    // cx.register_action_type(Editor::new_file);
  409    // cx.register_action_type(Editor::new_file_in_direction);
  410    // cx.register_action_type(Editor::cancel);
  411    // cx.register_action_type(Editor::newline);
  412    // cx.register_action_type(Editor::newline_above);
  413    // cx.register_action_type(Editor::newline_below);
  414    // cx.register_action_type(Editor::backspace);
  415    // cx.register_action_type(Editor::delete);
  416    // cx.register_action_type(Editor::tab);
  417    // cx.register_action_type(Editor::tab_prev);
  418    // cx.register_action_type(Editor::indent);
  419    // cx.register_action_type(Editor::outdent);
  420    // cx.register_action_type(Editor::delete_line);
  421    // cx.register_action_type(Editor::join_lines);
  422    // cx.register_action_type(Editor::sort_lines_case_sensitive);
  423    // cx.register_action_type(Editor::sort_lines_case_insensitive);
  424    // cx.register_action_type(Editor::reverse_lines);
  425    // cx.register_action_type(Editor::shuffle_lines);
  426    // cx.register_action_type(Editor::convert_to_upper_case);
  427    // cx.register_action_type(Editor::convert_to_lower_case);
  428    // cx.register_action_type(Editor::convert_to_title_case);
  429    // cx.register_action_type(Editor::convert_to_snake_case);
  430    // cx.register_action_type(Editor::convert_to_kebab_case);
  431    // cx.register_action_type(Editor::convert_to_upper_camel_case);
  432    // cx.register_action_type(Editor::convert_to_lower_camel_case);
  433    // cx.register_action_type(Editor::delete_to_previous_word_start);
  434    // cx.register_action_type(Editor::delete_to_previous_subword_start);
  435    // cx.register_action_type(Editor::delete_to_next_word_end);
  436    // cx.register_action_type(Editor::delete_to_next_subword_end);
  437    // cx.register_action_type(Editor::delete_to_beginning_of_line);
  438    // cx.register_action_type(Editor::delete_to_end_of_line);
  439    // cx.register_action_type(Editor::cut_to_end_of_line);
  440    // cx.register_action_type(Editor::duplicate_line);
  441    // cx.register_action_type(Editor::move_line_up);
  442    // cx.register_action_type(Editor::move_line_down);
  443    // cx.register_action_type(Editor::transpose);
  444    // cx.register_action_type(Editor::cut);
  445    // cx.register_action_type(Editor::copy);
  446    // cx.register_action_type(Editor::paste);
  447    // cx.register_action_type(Editor::undo);
  448    // cx.register_action_type(Editor::redo);
  449    // cx.register_action_type(Editor::move_page_up);
  450    // cx.register_action_type::<MoveDown>();
  451    // cx.register_action_type(Editor::move_page_down);
  452    // cx.register_action_type(Editor::next_screen);
  453    // cx.register_action_type::<MoveLeft>();
  454    // cx.register_action_type::<MoveRight>();
  455    // cx.register_action_type(Editor::move_to_previous_word_start);
  456    // cx.register_action_type(Editor::move_to_previous_subword_start);
  457    // cx.register_action_type(Editor::move_to_next_word_end);
  458    // cx.register_action_type(Editor::move_to_next_subword_end);
  459    // cx.register_action_type(Editor::move_to_beginning_of_line);
  460    // cx.register_action_type(Editor::move_to_end_of_line);
  461    // cx.register_action_type(Editor::move_to_start_of_paragraph);
  462    // cx.register_action_type(Editor::move_to_end_of_paragraph);
  463    // cx.register_action_type(Editor::move_to_beginning);
  464    // cx.register_action_type(Editor::move_to_end);
  465    // cx.register_action_type(Editor::select_up);
  466    // cx.register_action_type(Editor::select_down);
  467    // cx.register_action_type(Editor::select_left);
  468    // cx.register_action_type(Editor::select_right);
  469    // cx.register_action_type(Editor::select_to_previous_word_start);
  470    // cx.register_action_type(Editor::select_to_previous_subword_start);
  471    // cx.register_action_type(Editor::select_to_next_word_end);
  472    // cx.register_action_type(Editor::select_to_next_subword_end);
  473    // cx.register_action_type(Editor::select_to_beginning_of_line);
  474    // cx.register_action_type(Editor::select_to_end_of_line);
  475    // cx.register_action_type(Editor::select_to_start_of_paragraph);
  476    // cx.register_action_type(Editor::select_to_end_of_paragraph);
  477    // cx.register_action_type(Editor::select_to_beginning);
  478    // cx.register_action_type(Editor::select_to_end);
  479    // cx.register_action_type(Editor::select_all);
  480    // cx.register_action_type(Editor::select_all_matches);
  481    // cx.register_action_type(Editor::select_line);
  482    // cx.register_action_type(Editor::split_selection_into_lines);
  483    // cx.register_action_type(Editor::add_selection_above);
  484    // cx.register_action_type(Editor::add_selection_below);
  485    // cx.register_action_type(Editor::select_next);
  486    // cx.register_action_type(Editor::select_previous);
  487    // cx.register_action_type(Editor::toggle_comments);
  488    // cx.register_action_type(Editor::select_larger_syntax_node);
  489    // cx.register_action_type(Editor::select_smaller_syntax_node);
  490    // cx.register_action_type(Editor::move_to_enclosing_bracket);
  491    // cx.register_action_type(Editor::undo_selection);
  492    // cx.register_action_type(Editor::redo_selection);
  493    // cx.register_action_type(Editor::go_to_diagnostic);
  494    // cx.register_action_type(Editor::go_to_prev_diagnostic);
  495    // cx.register_action_type(Editor::go_to_hunk);
  496    // cx.register_action_type(Editor::go_to_prev_hunk);
  497    // cx.register_action_type(Editor::go_to_definition);
  498    // cx.register_action_type(Editor::go_to_definition_split);
  499    // cx.register_action_type(Editor::go_to_type_definition);
  500    // cx.register_action_type(Editor::go_to_type_definition_split);
  501    // cx.register_action_type(Editor::fold);
  502    // cx.register_action_type(Editor::fold_at);
  503    // cx.register_action_type(Editor::unfold_lines);
  504    // cx.register_action_type(Editor::unfold_at);
  505    // cx.register_action_type(Editor::gutter_hover);
  506    // cx.register_action_type(Editor::fold_selected_ranges);
  507    // cx.register_action_type(Editor::show_completions);
  508    // cx.register_action_type(Editor::toggle_code_actions);
  509    // cx.register_action_type(Editor::open_excerpts);
  510    // cx.register_action_type(Editor::toggle_soft_wrap);
  511    // cx.register_action_type(Editor::toggle_inlay_hints);
  512    // cx.register_action_type(Editor::reveal_in_finder);
  513    // cx.register_action_type(Editor::copy_path);
  514    // cx.register_action_type(Editor::copy_relative_path);
  515    // cx.register_action_type(Editor::copy_highlight_json);
  516    // cx.add_async_action(Editor::format);
  517    // cx.register_action_type(Editor::restart_language_server);
  518    // cx.register_action_type(Editor::show_character_palette);
  519    // cx.add_async_action(Editor::confirm_completion);
  520    // cx.add_async_action(Editor::confirm_code_action);
  521    // cx.add_async_action(Editor::rename);
  522    // cx.add_async_action(Editor::confirm_rename);
  523    // cx.add_async_action(Editor::find_all_references);
  524    // cx.register_action_type(Editor::next_copilot_suggestion);
  525    // cx.register_action_type(Editor::previous_copilot_suggestion);
  526    // cx.register_action_type(Editor::copilot_suggest);
  527    // cx.register_action_type(Editor::context_menu_first);
  528    // cx.register_action_type(Editor::context_menu_prev);
  529    // cx.register_action_type(Editor::context_menu_next);
  530    // cx.register_action_type(Editor::context_menu_last);
  531
  532    hover_popover::init(cx);
  533
  534    workspace::register_project_item::<Editor>(cx);
  535    workspace::register_followable_item::<Editor>(cx);
  536    workspace::register_deserializable_item::<Editor>(cx);
  537}
  538
  539trait InvalidationRegion {
  540    fn ranges(&self) -> &[Range<Anchor>];
  541}
  542
  543#[derive(Clone, Debug, PartialEq)]
  544pub enum SelectPhase {
  545    Begin {
  546        position: DisplayPoint,
  547        add: bool,
  548        click_count: usize,
  549    },
  550    BeginColumnar {
  551        position: DisplayPoint,
  552        goal_column: u32,
  553    },
  554    Extend {
  555        position: DisplayPoint,
  556        click_count: usize,
  557    },
  558    Update {
  559        position: DisplayPoint,
  560        goal_column: u32,
  561        scroll_position: gpui::Point<f32>,
  562    },
  563    End,
  564}
  565
  566#[derive(Clone, Debug)]
  567pub enum SelectMode {
  568    Character,
  569    Word(Range<Anchor>),
  570    Line(Range<Anchor>),
  571    All,
  572}
  573
  574#[derive(Copy, Clone, PartialEq, Eq, Debug)]
  575pub enum EditorMode {
  576    SingleLine,
  577    AutoHeight { max_lines: usize },
  578    Full,
  579}
  580
  581#[derive(Clone, Debug)]
  582pub enum SoftWrap {
  583    None,
  584    EditorWidth,
  585    Column(u32),
  586}
  587
  588#[derive(Clone)]
  589pub struct EditorStyle {
  590    pub background: Hsla,
  591    pub local_player: PlayerColor,
  592    pub text: TextStyle,
  593    pub scrollbar_width: Pixels,
  594    pub syntax: Arc<SyntaxTheme>,
  595    pub diagnostic_style: DiagnosticStyle,
  596}
  597
  598type CompletionId = usize;
  599
  600// type GetFieldEditorTheme = dyn Fn(&theme::Theme) -> theme::FieldEditor;
  601// type OverrideTextStyle = dyn Fn(&EditorStyle) -> Option<HighlightStyle>;
  602
  603type BackgroundHighlight = (fn(&ThemeColors) -> Hsla, Vec<Range<Anchor>>);
  604type InlayBackgroundHighlight = (fn(&ThemeColors) -> Hsla, Vec<InlayHighlight>);
  605
  606pub struct Editor {
  607    handle: WeakView<Self>,
  608    focus_handle: FocusHandle,
  609    buffer: Model<MultiBuffer>,
  610    display_map: Model<DisplayMap>,
  611    pub selections: SelectionsCollection,
  612    pub scroll_manager: ScrollManager,
  613    columnar_selection_tail: Option<Anchor>,
  614    add_selections_state: Option<AddSelectionsState>,
  615    select_next_state: Option<SelectNextState>,
  616    select_prev_state: Option<SelectNextState>,
  617    selection_history: SelectionHistory,
  618    autoclose_regions: Vec<AutocloseRegion>,
  619    snippet_stack: InvalidationStack<SnippetState>,
  620    select_larger_syntax_node_stack: Vec<Box<[Selection<usize>]>>,
  621    ime_transaction: Option<TransactionId>,
  622    active_diagnostics: Option<ActiveDiagnosticGroup>,
  623    soft_wrap_mode_override: Option<language_settings::SoftWrap>,
  624    // get_field_editor_theme: Option<Arc<GetFieldEditorTheme>>,
  625    // override_text_style: Option<Box<OverrideTextStyle>>,
  626    project: Option<Model<Project>>,
  627    collaboration_hub: Option<Box<dyn CollaborationHub>>,
  628    blink_manager: Model<BlinkManager>,
  629    pub show_local_selections: bool,
  630    mode: EditorMode,
  631    show_gutter: bool,
  632    show_wrap_guides: Option<bool>,
  633    placeholder_text: Option<Arc<str>>,
  634    highlighted_rows: Option<Range<u32>>,
  635    background_highlights: BTreeMap<TypeId, BackgroundHighlight>,
  636    inlay_background_highlights: TreeMap<Option<TypeId>, InlayBackgroundHighlight>,
  637    nav_history: Option<ItemNavHistory>,
  638    context_menu: RwLock<Option<ContextMenu>>,
  639    // mouse_context_menu: View<context_menu::ContextMenu>,
  640    completion_tasks: Vec<(CompletionId, Task<Option<()>>)>,
  641    next_completion_id: CompletionId,
  642    available_code_actions: Option<(Model<Buffer>, Arc<[CodeAction]>)>,
  643    code_actions_task: Option<Task<()>>,
  644    document_highlights_task: Option<Task<()>>,
  645    pending_rename: Option<RenameState>,
  646    searchable: bool,
  647    cursor_shape: CursorShape,
  648    collapse_matches: bool,
  649    autoindent_mode: Option<AutoindentMode>,
  650    workspace: Option<(WeakView<Workspace>, i64)>,
  651    keymap_context_layers: BTreeMap<TypeId, KeyContext>,
  652    input_enabled: bool,
  653    read_only: bool,
  654    leader_peer_id: Option<PeerId>,
  655    remote_id: Option<ViewId>,
  656    hover_state: HoverState,
  657    gutter_hovered: bool,
  658    link_go_to_definition_state: LinkGoToDefinitionState,
  659    copilot_state: CopilotState,
  660    inlay_hint_cache: InlayHintCache,
  661    next_inlay_id: usize,
  662    _subscriptions: Vec<Subscription>,
  663    pixel_position_of_newest_cursor: Option<gpui::Point<Pixels>>,
  664    gutter_width: Pixels,
  665    style: Option<EditorStyle>,
  666}
  667
  668pub struct EditorSnapshot {
  669    pub mode: EditorMode,
  670    pub show_gutter: bool,
  671    pub display_snapshot: DisplaySnapshot,
  672    pub placeholder_text: Option<Arc<str>>,
  673    is_focused: bool,
  674    scroll_anchor: ScrollAnchor,
  675    ongoing_scroll: OngoingScroll,
  676}
  677
  678pub struct RemoteSelection {
  679    pub replica_id: ReplicaId,
  680    pub selection: Selection<Anchor>,
  681    pub cursor_shape: CursorShape,
  682    pub peer_id: PeerId,
  683    pub line_mode: bool,
  684    pub participant_index: Option<ParticipantIndex>,
  685}
  686
  687#[derive(Clone, Debug)]
  688struct SelectionHistoryEntry {
  689    selections: Arc<[Selection<Anchor>]>,
  690    select_next_state: Option<SelectNextState>,
  691    select_prev_state: Option<SelectNextState>,
  692    add_selections_state: Option<AddSelectionsState>,
  693}
  694
  695enum SelectionHistoryMode {
  696    Normal,
  697    Undoing,
  698    Redoing,
  699}
  700
  701impl Default for SelectionHistoryMode {
  702    fn default() -> Self {
  703        Self::Normal
  704    }
  705}
  706
  707#[derive(Default)]
  708struct SelectionHistory {
  709    #[allow(clippy::type_complexity)]
  710    selections_by_transaction:
  711        HashMap<TransactionId, (Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)>,
  712    mode: SelectionHistoryMode,
  713    undo_stack: VecDeque<SelectionHistoryEntry>,
  714    redo_stack: VecDeque<SelectionHistoryEntry>,
  715}
  716
  717impl SelectionHistory {
  718    fn insert_transaction(
  719        &mut self,
  720        transaction_id: TransactionId,
  721        selections: Arc<[Selection<Anchor>]>,
  722    ) {
  723        self.selections_by_transaction
  724            .insert(transaction_id, (selections, None));
  725    }
  726
  727    #[allow(clippy::type_complexity)]
  728    fn transaction(
  729        &self,
  730        transaction_id: TransactionId,
  731    ) -> Option<&(Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)> {
  732        self.selections_by_transaction.get(&transaction_id)
  733    }
  734
  735    #[allow(clippy::type_complexity)]
  736    fn transaction_mut(
  737        &mut self,
  738        transaction_id: TransactionId,
  739    ) -> Option<&mut (Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)> {
  740        self.selections_by_transaction.get_mut(&transaction_id)
  741    }
  742
  743    fn push(&mut self, entry: SelectionHistoryEntry) {
  744        if !entry.selections.is_empty() {
  745            match self.mode {
  746                SelectionHistoryMode::Normal => {
  747                    self.push_undo(entry);
  748                    self.redo_stack.clear();
  749                }
  750                SelectionHistoryMode::Undoing => self.push_redo(entry),
  751                SelectionHistoryMode::Redoing => self.push_undo(entry),
  752            }
  753        }
  754    }
  755
  756    fn push_undo(&mut self, entry: SelectionHistoryEntry) {
  757        if self
  758            .undo_stack
  759            .back()
  760            .map_or(true, |e| e.selections != entry.selections)
  761        {
  762            self.undo_stack.push_back(entry);
  763            if self.undo_stack.len() > MAX_SELECTION_HISTORY_LEN {
  764                self.undo_stack.pop_front();
  765            }
  766        }
  767    }
  768
  769    fn push_redo(&mut self, entry: SelectionHistoryEntry) {
  770        if self
  771            .redo_stack
  772            .back()
  773            .map_or(true, |e| e.selections != entry.selections)
  774        {
  775            self.redo_stack.push_back(entry);
  776            if self.redo_stack.len() > MAX_SELECTION_HISTORY_LEN {
  777                self.redo_stack.pop_front();
  778            }
  779        }
  780    }
  781}
  782
  783#[derive(Clone, Debug)]
  784struct AddSelectionsState {
  785    above: bool,
  786    stack: Vec<usize>,
  787}
  788
  789#[derive(Clone)]
  790struct SelectNextState {
  791    query: AhoCorasick,
  792    wordwise: bool,
  793    done: bool,
  794}
  795
  796impl std::fmt::Debug for SelectNextState {
  797    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  798        f.debug_struct(std::any::type_name::<Self>())
  799            .field("wordwise", &self.wordwise)
  800            .field("done", &self.done)
  801            .finish()
  802    }
  803}
  804
  805#[derive(Debug)]
  806struct AutocloseRegion {
  807    selection_id: usize,
  808    range: Range<Anchor>,
  809    pair: BracketPair,
  810}
  811
  812#[derive(Debug)]
  813struct SnippetState {
  814    ranges: Vec<Vec<Range<Anchor>>>,
  815    active_index: usize,
  816}
  817
  818pub struct RenameState {
  819    pub range: Range<Anchor>,
  820    pub old_name: Arc<str>,
  821    pub editor: View<Editor>,
  822    block_id: BlockId,
  823}
  824
  825struct InvalidationStack<T>(Vec<T>);
  826
  827enum ContextMenu {
  828    Completions(CompletionsMenu),
  829    CodeActions(CodeActionsMenu),
  830}
  831
  832impl ContextMenu {
  833    fn select_first(
  834        &mut self,
  835        project: Option<&Model<Project>>,
  836        cx: &mut ViewContext<Editor>,
  837    ) -> bool {
  838        if self.visible() {
  839            match self {
  840                ContextMenu::Completions(menu) => menu.select_first(project, cx),
  841                ContextMenu::CodeActions(menu) => menu.select_first(cx),
  842            }
  843            true
  844        } else {
  845            false
  846        }
  847    }
  848
  849    fn select_prev(
  850        &mut self,
  851        project: Option<&Model<Project>>,
  852        cx: &mut ViewContext<Editor>,
  853    ) -> bool {
  854        if self.visible() {
  855            match self {
  856                ContextMenu::Completions(menu) => menu.select_prev(project, cx),
  857                ContextMenu::CodeActions(menu) => menu.select_prev(cx),
  858            }
  859            true
  860        } else {
  861            false
  862        }
  863    }
  864
  865    fn select_next(
  866        &mut self,
  867        project: Option<&Model<Project>>,
  868        cx: &mut ViewContext<Editor>,
  869    ) -> bool {
  870        if self.visible() {
  871            match self {
  872                ContextMenu::Completions(menu) => menu.select_next(project, cx),
  873                ContextMenu::CodeActions(menu) => menu.select_next(cx),
  874            }
  875            true
  876        } else {
  877            false
  878        }
  879    }
  880
  881    fn select_last(
  882        &mut self,
  883        project: Option<&Model<Project>>,
  884        cx: &mut ViewContext<Editor>,
  885    ) -> bool {
  886        if self.visible() {
  887            match self {
  888                ContextMenu::Completions(menu) => menu.select_last(project, cx),
  889                ContextMenu::CodeActions(menu) => menu.select_last(cx),
  890            }
  891            true
  892        } else {
  893            false
  894        }
  895    }
  896
  897    fn visible(&self) -> bool {
  898        match self {
  899            ContextMenu::Completions(menu) => menu.visible(),
  900            ContextMenu::CodeActions(menu) => menu.visible(),
  901        }
  902    }
  903
  904    fn render(
  905        &self,
  906        cursor_position: DisplayPoint,
  907        style: &EditorStyle,
  908        workspace: Option<WeakView<Workspace>>,
  909        cx: &mut ViewContext<Editor>,
  910    ) -> (DisplayPoint, AnyElement<Editor>) {
  911        match self {
  912            ContextMenu::Completions(menu) => (cursor_position, menu.render(style, workspace, cx)),
  913            ContextMenu::CodeActions(menu) => menu.render(cursor_position, style, cx),
  914        }
  915    }
  916}
  917
  918#[derive(Clone)]
  919struct CompletionsMenu {
  920    id: CompletionId,
  921    initial_position: Anchor,
  922    buffer: Model<Buffer>,
  923    completions: Arc<RwLock<Box<[Completion]>>>,
  924    match_candidates: Arc<[StringMatchCandidate]>,
  925    matches: Arc<[StringMatch]>,
  926    selected_item: usize,
  927    scroll_handle: UniformListScrollHandle,
  928}
  929
  930impl CompletionsMenu {
  931    fn select_first(&mut self, project: Option<&Model<Project>>, cx: &mut ViewContext<Editor>) {
  932        self.selected_item = 0;
  933        self.scroll_handle.scroll_to_item(self.selected_item);
  934        self.attempt_resolve_selected_completion_documentation(project, cx);
  935        cx.notify();
  936    }
  937
  938    fn select_prev(&mut self, project: Option<&Model<Project>>, cx: &mut ViewContext<Editor>) {
  939        if self.selected_item > 0 {
  940            self.selected_item -= 1;
  941        } else {
  942            self.selected_item = self.matches.len() - 1;
  943        }
  944        self.scroll_handle.scroll_to_item(self.selected_item);
  945        self.attempt_resolve_selected_completion_documentation(project, cx);
  946        cx.notify();
  947    }
  948
  949    fn select_next(&mut self, project: Option<&Model<Project>>, cx: &mut ViewContext<Editor>) {
  950        if self.selected_item + 1 < self.matches.len() {
  951            self.selected_item += 1;
  952        } else {
  953            self.selected_item = 0;
  954        }
  955        self.scroll_handle.scroll_to_item(self.selected_item);
  956        self.attempt_resolve_selected_completion_documentation(project, cx);
  957        cx.notify();
  958    }
  959
  960    fn select_last(&mut self, project: Option<&Model<Project>>, cx: &mut ViewContext<Editor>) {
  961        self.selected_item = self.matches.len() - 1;
  962        self.scroll_handle.scroll_to_item(self.selected_item);
  963        self.attempt_resolve_selected_completion_documentation(project, cx);
  964        cx.notify();
  965    }
  966
  967    fn pre_resolve_completion_documentation(
  968        &self,
  969        project: Option<Model<Project>>,
  970        cx: &mut ViewContext<Editor>,
  971    ) {
  972        // todo!("implementation below ");
  973    }
  974    // ) {
  975    //     let settings = EditorSettings::get_global(cx);
  976    //     if !settings.show_completion_documentation {
  977    //         return;
  978    //     }
  979
  980    //     let Some(project) = project else {
  981    //         return;
  982    //     };
  983    //     let client = project.read(cx).client();
  984    //     let language_registry = project.read(cx).languages().clone();
  985
  986    //     let is_remote = project.read(cx).is_remote();
  987    //     let project_id = project.read(cx).remote_id();
  988
  989    //     let completions = self.completions.clone();
  990    //     let completion_indices: Vec<_> = self.matches.iter().map(|m| m.candidate_id).collect();
  991
  992    //     cx.spawn(move |this, mut cx| async move {
  993    //         if is_remote {
  994    //             let Some(project_id) = project_id else {
  995    //                 log::error!("Remote project without remote_id");
  996    //                 return;
  997    //             };
  998
  999    //             for completion_index in completion_indices {
 1000    //                 let completions_guard = completions.read();
 1001    //                 let completion = &completions_guard[completion_index];
 1002    //                 if completion.documentation.is_some() {
 1003    //                     continue;
 1004    //                 }
 1005
 1006    //                 let server_id = completion.server_id;
 1007    //                 let completion = completion.lsp_completion.clone();
 1008    //                 drop(completions_guard);
 1009
 1010    //                 Self::resolve_completion_documentation_remote(
 1011    //                     project_id,
 1012    //                     server_id,
 1013    //                     completions.clone(),
 1014    //                     completion_index,
 1015    //                     completion,
 1016    //                     client.clone(),
 1017    //                     language_registry.clone(),
 1018    //                 )
 1019    //                 .await;
 1020
 1021    //                 _ = this.update(&mut cx, |_, cx| cx.notify());
 1022    //             }
 1023    //         } else {
 1024    //             for completion_index in completion_indices {
 1025    //                 let completions_guard = completions.read();
 1026    //                 let completion = &completions_guard[completion_index];
 1027    //                 if completion.documentation.is_some() {
 1028    //                     continue;
 1029    //                 }
 1030
 1031    //                 let server_id = completion.server_id;
 1032    //                 let completion = completion.lsp_completion.clone();
 1033    //                 drop(completions_guard);
 1034
 1035    //                 let server = project.read_with(&mut cx, |project, _| {
 1036    //                     project.language_server_for_id(server_id)
 1037    //                 });
 1038    //                 let Some(server) = server else {
 1039    //                     return;
 1040    //                 };
 1041
 1042    //                 Self::resolve_completion_documentation_local(
 1043    //                     server,
 1044    //                     completions.clone(),
 1045    //                     completion_index,
 1046    //                     completion,
 1047    //                     language_registry.clone(),
 1048    //                 )
 1049    //                 .await;
 1050
 1051    //                 _ = this.update(&mut cx, |_, cx| cx.notify());
 1052    //             }
 1053    //         }
 1054    //     })
 1055    //     .detach();
 1056    // }
 1057
 1058    fn attempt_resolve_selected_completion_documentation(
 1059        &mut self,
 1060        project: Option<&Model<Project>>,
 1061        cx: &mut ViewContext<Editor>,
 1062    ) {
 1063        let settings = EditorSettings::get_global(cx);
 1064        if !settings.show_completion_documentation {
 1065            return;
 1066        }
 1067
 1068        let completion_index = self.matches[self.selected_item].candidate_id;
 1069        let Some(project) = project else {
 1070            return;
 1071        };
 1072        let language_registry = project.read(cx).languages().clone();
 1073
 1074        let completions = self.completions.clone();
 1075        let completions_guard = completions.read();
 1076        let completion = &completions_guard[completion_index];
 1077        // todo!()
 1078        // if completion.documentation.is_some() {
 1079        //     return;
 1080        // }
 1081
 1082        let server_id = completion.server_id;
 1083        let completion = completion.lsp_completion.clone();
 1084        drop(completions_guard);
 1085
 1086        if project.read(cx).is_remote() {
 1087            let Some(project_id) = project.read(cx).remote_id() else {
 1088                log::error!("Remote project without remote_id");
 1089                return;
 1090            };
 1091
 1092            let client = project.read(cx).client();
 1093
 1094            cx.spawn(move |this, mut cx| async move {
 1095                Self::resolve_completion_documentation_remote(
 1096                    project_id,
 1097                    server_id,
 1098                    completions.clone(),
 1099                    completion_index,
 1100                    completion,
 1101                    client,
 1102                    language_registry.clone(),
 1103                )
 1104                .await;
 1105
 1106                _ = this.update(&mut cx, |_, cx| cx.notify());
 1107            })
 1108            .detach();
 1109        } else {
 1110            let Some(server) = project.read(cx).language_server_for_id(server_id) else {
 1111                return;
 1112            };
 1113
 1114            cx.spawn(move |this, mut cx| async move {
 1115                Self::resolve_completion_documentation_local(
 1116                    server,
 1117                    completions,
 1118                    completion_index,
 1119                    completion,
 1120                    language_registry,
 1121                )
 1122                .await;
 1123
 1124                _ = this.update(&mut cx, |_, cx| cx.notify());
 1125            })
 1126            .detach();
 1127        }
 1128    }
 1129
 1130    async fn resolve_completion_documentation_remote(
 1131        project_id: u64,
 1132        server_id: LanguageServerId,
 1133        completions: Arc<RwLock<Box<[Completion]>>>,
 1134        completion_index: usize,
 1135        completion: lsp::CompletionItem,
 1136        client: Arc<Client>,
 1137        language_registry: Arc<LanguageRegistry>,
 1138    ) {
 1139        // todo!()
 1140        // let request = proto::ResolveCompletionDocumentation {
 1141        //     project_id,
 1142        //     language_server_id: server_id.0 as u64,
 1143        //     lsp_completion: serde_json::to_string(&completion).unwrap().into_bytes(),
 1144        // };
 1145
 1146        // let Some(response) = client
 1147        //     .request(request)
 1148        //     .await
 1149        //     .context("completion documentation resolve proto request")
 1150        //     .log_err()
 1151        // else {
 1152        //     return;
 1153        // };
 1154
 1155        // if response.text.is_empty() {
 1156        //     let mut completions = completions.write();
 1157        //     let completion = &mut completions[completion_index];
 1158        //     completion.documentation = Some(Documentation::Undocumented);
 1159        // }
 1160
 1161        // let documentation = if response.is_markdown {
 1162        //     Documentation::MultiLineMarkdown(
 1163        //         markdown::parse_markdown(&response.text, &language_registry, None).await,
 1164        //     )
 1165        // } else if response.text.lines().count() <= 1 {
 1166        //     Documentation::SingleLine(response.text)
 1167        // } else {
 1168        //     Documentation::MultiLinePlainText(response.text)
 1169        // };
 1170
 1171        // let mut completions = completions.write();
 1172        // let completion = &mut completions[completion_index];
 1173        // completion.documentation = Some(documentation);
 1174    }
 1175
 1176    async fn resolve_completion_documentation_local(
 1177        server: Arc<lsp::LanguageServer>,
 1178        completions: Arc<RwLock<Box<[Completion]>>>,
 1179        completion_index: usize,
 1180        completion: lsp::CompletionItem,
 1181        language_registry: Arc<LanguageRegistry>,
 1182    ) {
 1183        // todo!()
 1184        // let can_resolve = server
 1185        //     .capabilities()
 1186        //     .completion_provider
 1187        //     .as_ref()
 1188        //     .and_then(|options| options.resolve_provider)
 1189        //     .unwrap_or(false);
 1190        // if !can_resolve {
 1191        //     return;
 1192        // }
 1193
 1194        // let request = server.request::<lsp::request::ResolveCompletionItem>(completion);
 1195        // let Some(completion_item) = request.await.log_err() else {
 1196        //     return;
 1197        // };
 1198
 1199        // if let Some(lsp_documentation) = completion_item.documentation {
 1200        //     let documentation = language::prepare_completion_documentation(
 1201        //         &lsp_documentation,
 1202        //         &language_registry,
 1203        //         None, // TODO: Try to reasonably work out which language the completion is for
 1204        //     )
 1205        //     .await;
 1206
 1207        //     let mut completions = completions.write();
 1208        //     let completion = &mut completions[completion_index];
 1209        //     completion.documentation = Some(documentation);
 1210        // } else {
 1211        //     let mut completions = completions.write();
 1212        //     let completion = &mut completions[completion_index];
 1213        //     completion.documentation = Some(Documentation::Undocumented);
 1214        // }
 1215    }
 1216
 1217    fn visible(&self) -> bool {
 1218        !self.matches.is_empty()
 1219    }
 1220
 1221    fn render(
 1222        &self,
 1223        style: &EditorStyle,
 1224        workspace: Option<WeakView<Workspace>>,
 1225        cx: &mut ViewContext<Editor>,
 1226    ) -> AnyElement<Editor> {
 1227        todo!("old implementation below")
 1228    }
 1229
 1230    //     enum CompletionTag {}
 1231
 1232    //     let settings = EditorSettings>(cx);
 1233    //     let show_completion_documentation = settings.show_completion_documentation;
 1234
 1235    //     let widest_completion_ix = self
 1236    //         .matches
 1237    //         .iter()
 1238    //         .enumerate()
 1239    //         .max_by_key(|(_, mat)| {
 1240    //             let completions = self.completions.read();
 1241    //             let completion = &completions[mat.candidate_id];
 1242    //             let documentation = &completion.documentation;
 1243
 1244    //             let mut len = completion.label.text.chars().count();
 1245    //             if let Some(Documentation::SingleLine(text)) = documentation {
 1246    //                 if show_completion_documentation {
 1247    //                     len += text.chars().count();
 1248    //                 }
 1249    //             }
 1250
 1251    //             len
 1252    //         })
 1253    //         .map(|(ix, _)| ix);
 1254
 1255    //     let completions = self.completions.clone();
 1256    //     let matches = self.matches.clone();
 1257    //     let selected_item = self.selected_item;
 1258
 1259    //     let list = UniformList::new(self.list.clone(), matches.len(), cx, {
 1260    //         let style = style.clone();
 1261    //         move |_, range, items, cx| {
 1262    //             let start_ix = range.start;
 1263    //             let completions_guard = completions.read();
 1264
 1265    //             for (ix, mat) in matches[range].iter().enumerate() {
 1266    //                 let item_ix = start_ix + ix;
 1267    //                 let candidate_id = mat.candidate_id;
 1268    //                 let completion = &completions_guard[candidate_id];
 1269
 1270    //                 let documentation = if show_completion_documentation {
 1271    //                     &completion.documentation
 1272    //                 } else {
 1273    //                     &None
 1274    //                 };
 1275
 1276    //                 items.push(
 1277    //                     MouseEventHandler::new::<CompletionTag, _>(
 1278    //                         mat.candidate_id,
 1279    //                         cx,
 1280    //                         |state, _| {
 1281    //                             let item_style = if item_ix == selected_item {
 1282    //                                 style.autocomplete.selected_item
 1283    //                             } else if state.hovered() {
 1284    //                                 style.autocomplete.hovered_item
 1285    //                             } else {
 1286    //                                 style.autocomplete.item
 1287    //                             };
 1288
 1289    //                             let completion_label =
 1290    //                                 Text::new(completion.label.text.clone(), style.text.clone())
 1291    //                                     .with_soft_wrap(false)
 1292    //                                     .with_highlights(
 1293    //                                         combine_syntax_and_fuzzy_match_highlights(
 1294    //                                             &completion.label.text,
 1295    //                                             style.text.color.into(),
 1296    //                                             styled_runs_for_code_label(
 1297    //                                                 &completion.label,
 1298    //                                                 &style.syntax,
 1299    //                                             ),
 1300    //                                             &mat.positions,
 1301    //                                         ),
 1302    //                                     );
 1303
 1304    //                             if let Some(Documentation::SingleLine(text)) = documentation {
 1305    //                                 Flex::row()
 1306    //                                     .with_child(completion_label)
 1307    //                                     .with_children((|| {
 1308    //                                         let text_style = TextStyle {
 1309    //                                             color: style.autocomplete.inline_docs_color,
 1310    //                                             font_size: style.text.font_size
 1311    //                                                 * style.autocomplete.inline_docs_size_percent,
 1312    //                                             ..style.text.clone()
 1313    //                                         };
 1314
 1315    //                                         let label = Text::new(text.clone(), text_style)
 1316    //                                             .aligned()
 1317    //                                             .constrained()
 1318    //                                             .dynamically(move |constraint, _, _| {
 1319    //                                                 gpui::SizeConstraint {
 1320    //                                                     min: constraint.min,
 1321    //                                                     max: vec2f(
 1322    //                                                         constraint.max.x(),
 1323    //                                                         constraint.min.y(),
 1324    //                                                     ),
 1325    //                                                 }
 1326    //                                             });
 1327
 1328    //                                         if Some(item_ix) == widest_completion_ix {
 1329    //                                             Some(
 1330    //                                                 label
 1331    //                                                     .contained()
 1332    //                                                     .with_style(
 1333    //                                                         style
 1334    //                                                             .autocomplete
 1335    //                                                             .inline_docs_container,
 1336    //                                                     )
 1337    //                                                     .into_any(),
 1338    //                                             )
 1339    //                                         } else {
 1340    //                                             Some(label.flex_float().into_any())
 1341    //                                         }
 1342    //                                     })())
 1343    //                                     .into_any()
 1344    //                             } else {
 1345    //                                 completion_label.into_any()
 1346    //                             }
 1347    //                             .contained()
 1348    //                             .with_style(item_style)
 1349    //                             .constrained()
 1350    //                             .dynamically(
 1351    //                                 move |constraint, _, _| {
 1352    //                                     if Some(item_ix) == widest_completion_ix {
 1353    //                                         constraint
 1354    //                                     } else {
 1355    //                                         gpui::SizeConstraint {
 1356    //                                             min: constraint.min,
 1357    //                                             max: constraint.min,
 1358    //                                         }
 1359    //                                     }
 1360    //                                 },
 1361    //                             )
 1362    //                         },
 1363    //                     )
 1364    //                     .with_cursor_style(CursorStyle::PointingHand)
 1365    //                     .on_down(MouseButton::Left, move |_, this, cx| {
 1366    //                         this.confirm_completion(
 1367    //                             &ConfirmCompletion {
 1368    //                                 item_ix: Some(item_ix),
 1369    //                             },
 1370    //                             cx,
 1371    //                         )
 1372    //                         .map(|task| task.detach());
 1373    //                     })
 1374    //                     .constrained()
 1375    //                     .with_min_width(style.autocomplete.completion_min_width)
 1376    //                     .with_max_width(style.autocomplete.completion_max_width)
 1377    //                     .into_any(),
 1378    //                 );
 1379    //             }
 1380    //         }
 1381    //     })
 1382    //     .with_width_from_item(widest_completion_ix);
 1383
 1384    //     enum MultiLineDocumentation {}
 1385
 1386    //     Flex::row()
 1387    //         .with_child(list.flex(1., false))
 1388    //         .with_children({
 1389    //             let mat = &self.matches[selected_item];
 1390    //             let completions = self.completions.read();
 1391    //             let completion = &completions[mat.candidate_id];
 1392    //             let documentation = &completion.documentation;
 1393
 1394    //             match documentation {
 1395    //                 Some(Documentation::MultiLinePlainText(text)) => Some(
 1396    //                     Flex::column()
 1397    //                         .scrollable::<MultiLineDocumentation>(0, None, cx)
 1398    //                         .with_child(
 1399    //                             Text::new(text.clone(), style.text.clone()).with_soft_wrap(true),
 1400    //                         )
 1401    //                         .contained()
 1402    //                         .with_style(style.autocomplete.alongside_docs_container)
 1403    //                         .constrained()
 1404    //                         .with_max_width(style.autocomplete.alongside_docs_max_width)
 1405    //                         .flex(1., false),
 1406    //                 ),
 1407
 1408    //                 Some(Documentation::MultiLineMarkdown(parsed)) => Some(
 1409    //                     Flex::column()
 1410    //                         .scrollable::<MultiLineDocumentation>(0, None, cx)
 1411    //                         .with_child(render_parsed_markdown::<MultiLineDocumentation>(
 1412    //                             parsed, &style, workspace, cx,
 1413    //                         ))
 1414    //                         .contained()
 1415    //                         .with_style(style.autocomplete.alongside_docs_container)
 1416    //                         .constrained()
 1417    //                         .with_max_width(style.autocomplete.alongside_docs_max_width)
 1418    //                         .flex(1., false),
 1419    //                 ),
 1420
 1421    //                 _ => None,
 1422    //             }
 1423    //         })
 1424    //         .contained()
 1425    //         .with_style(style.autocomplete.container)
 1426    //         .into_any()
 1427    // }
 1428
 1429    pub async fn filter(&mut self, query: Option<&str>, executor: BackgroundExecutor) {
 1430        let mut matches = if let Some(query) = query {
 1431            fuzzy::match_strings(
 1432                &self.match_candidates,
 1433                query,
 1434                query.chars().any(|c| c.is_uppercase()),
 1435                100,
 1436                &Default::default(),
 1437                executor,
 1438            )
 1439            .await
 1440        } else {
 1441            self.match_candidates
 1442                .iter()
 1443                .enumerate()
 1444                .map(|(candidate_id, candidate)| StringMatch {
 1445                    candidate_id,
 1446                    score: Default::default(),
 1447                    positions: Default::default(),
 1448                    string: candidate.string.clone(),
 1449                })
 1450                .collect()
 1451        };
 1452
 1453        // Remove all candidates where the query's start does not match the start of any word in the candidate
 1454        if let Some(query) = query {
 1455            if let Some(query_start) = query.chars().next() {
 1456                matches.retain(|string_match| {
 1457                    split_words(&string_match.string).any(|word| {
 1458                        // Check that the first codepoint of the word as lowercase matches the first
 1459                        // codepoint of the query as lowercase
 1460                        word.chars()
 1461                            .flat_map(|codepoint| codepoint.to_lowercase())
 1462                            .zip(query_start.to_lowercase())
 1463                            .all(|(word_cp, query_cp)| word_cp == query_cp)
 1464                    })
 1465                });
 1466            }
 1467        }
 1468
 1469        let completions = self.completions.read();
 1470        matches.sort_unstable_by_key(|mat| {
 1471            let completion = &completions[mat.candidate_id];
 1472            (
 1473                completion.lsp_completion.sort_text.as_ref(),
 1474                Reverse(OrderedFloat(mat.score)),
 1475                completion.sort_key(),
 1476            )
 1477        });
 1478        drop(completions);
 1479
 1480        for mat in &mut matches {
 1481            let completions = self.completions.read();
 1482            let filter_start = completions[mat.candidate_id].label.filter_range.start;
 1483            for position in &mut mat.positions {
 1484                *position += filter_start;
 1485            }
 1486        }
 1487
 1488        self.matches = matches.into();
 1489        self.selected_item = 0;
 1490    }
 1491}
 1492
 1493#[derive(Clone)]
 1494struct CodeActionsMenu {
 1495    actions: Arc<[CodeAction]>,
 1496    buffer: Model<Buffer>,
 1497    selected_item: usize,
 1498    scroll_handle: UniformListScrollHandle,
 1499    deployed_from_indicator: bool,
 1500}
 1501
 1502impl CodeActionsMenu {
 1503    fn select_first(&mut self, cx: &mut ViewContext<Editor>) {
 1504        self.selected_item = 0;
 1505        self.scroll_handle.scroll_to_item(self.selected_item);
 1506        cx.notify()
 1507    }
 1508
 1509    fn select_prev(&mut self, cx: &mut ViewContext<Editor>) {
 1510        if self.selected_item > 0 {
 1511            self.selected_item -= 1;
 1512        } else {
 1513            self.selected_item = self.actions.len() - 1;
 1514        }
 1515        self.scroll_handle.scroll_to_item(self.selected_item);
 1516        cx.notify();
 1517    }
 1518
 1519    fn select_next(&mut self, cx: &mut ViewContext<Editor>) {
 1520        if self.selected_item + 1 < self.actions.len() {
 1521            self.selected_item += 1;
 1522        } else {
 1523            self.selected_item = 0;
 1524        }
 1525        self.scroll_handle.scroll_to_item(self.selected_item);
 1526        cx.notify();
 1527    }
 1528
 1529    fn select_last(&mut self, cx: &mut ViewContext<Editor>) {
 1530        self.selected_item = self.actions.len() - 1;
 1531        self.scroll_handle.scroll_to_item(self.selected_item);
 1532        cx.notify()
 1533    }
 1534
 1535    fn visible(&self) -> bool {
 1536        !self.actions.is_empty()
 1537    }
 1538
 1539    fn render(
 1540        &self,
 1541        mut cursor_position: DisplayPoint,
 1542        style: &EditorStyle,
 1543        cx: &mut ViewContext<Editor>,
 1544    ) -> (DisplayPoint, AnyElement<Editor>) {
 1545        let actions = self.actions.clone();
 1546        let selected_item = self.selected_item;
 1547        let element = uniform_list(
 1548            "code_actions_menu",
 1549            self.actions.len(),
 1550            move |editor, range, cx| {
 1551                actions[range.clone()]
 1552                    .iter()
 1553                    .enumerate()
 1554                    .map(|(ix, action)| {
 1555                        let item_ix = range.start + ix;
 1556                        let selected = selected_item == item_ix;
 1557                        let colors = cx.theme().colors();
 1558                        div()
 1559                            .px_2()
 1560                            .text_ui()
 1561                            .text_color(colors.text)
 1562                            .when(selected, |style| {
 1563                                style
 1564                                    .bg(colors.element_active)
 1565                                    .text_color(colors.text_accent)
 1566                            })
 1567                            .hover(|style| {
 1568                                style
 1569                                    .bg(colors.element_hover)
 1570                                    .text_color(colors.text_accent)
 1571                            })
 1572                            .on_mouse_down(MouseButton::Left, move |editor: &mut Editor, _, cx| {
 1573                                cx.stop_propagation();
 1574                                editor
 1575                                    .confirm_code_action(
 1576                                        &ConfirmCodeAction {
 1577                                            item_ix: Some(item_ix),
 1578                                        },
 1579                                        cx,
 1580                                    )
 1581                                    .map(|task| task.detach_and_log_err(cx));
 1582                            })
 1583                            .child(action.lsp_action.title.clone())
 1584                    })
 1585                    .collect()
 1586            },
 1587        )
 1588        .elevation_1(cx)
 1589        .px_2()
 1590        .py_1()
 1591        .with_width_from_item(
 1592            self.actions
 1593                .iter()
 1594                .enumerate()
 1595                .max_by_key(|(_, action)| action.lsp_action.title.chars().count())
 1596                .map(|(ix, _)| ix),
 1597        )
 1598        .render();
 1599
 1600        if self.deployed_from_indicator {
 1601            *cursor_position.column_mut() = 0;
 1602        }
 1603
 1604        (cursor_position, element)
 1605    }
 1606}
 1607
 1608pub struct CopilotState {
 1609    excerpt_id: Option<ExcerptId>,
 1610    pending_refresh: Task<Option<()>>,
 1611    pending_cycling_refresh: Task<Option<()>>,
 1612    cycled: bool,
 1613    completions: Vec<copilot::Completion>,
 1614    active_completion_index: usize,
 1615    suggestion: Option<Inlay>,
 1616}
 1617
 1618impl Default for CopilotState {
 1619    fn default() -> Self {
 1620        Self {
 1621            excerpt_id: None,
 1622            pending_cycling_refresh: Task::ready(Some(())),
 1623            pending_refresh: Task::ready(Some(())),
 1624            completions: Default::default(),
 1625            active_completion_index: 0,
 1626            cycled: false,
 1627            suggestion: None,
 1628        }
 1629    }
 1630}
 1631
 1632impl CopilotState {
 1633    fn active_completion(&self) -> Option<&copilot::Completion> {
 1634        self.completions.get(self.active_completion_index)
 1635    }
 1636
 1637    fn text_for_active_completion(
 1638        &self,
 1639        cursor: Anchor,
 1640        buffer: &MultiBufferSnapshot,
 1641    ) -> Option<&str> {
 1642        use language::ToOffset as _;
 1643
 1644        let completion = self.active_completion()?;
 1645        let excerpt_id = self.excerpt_id?;
 1646        let completion_buffer = buffer.buffer_for_excerpt(excerpt_id)?;
 1647        if excerpt_id != cursor.excerpt_id
 1648            || !completion.range.start.is_valid(completion_buffer)
 1649            || !completion.range.end.is_valid(completion_buffer)
 1650        {
 1651            return None;
 1652        }
 1653
 1654        let mut completion_range = completion.range.to_offset(&completion_buffer);
 1655        let prefix_len = Self::common_prefix(
 1656            completion_buffer.chars_for_range(completion_range.clone()),
 1657            completion.text.chars(),
 1658        );
 1659        completion_range.start += prefix_len;
 1660        let suffix_len = Self::common_prefix(
 1661            completion_buffer.reversed_chars_for_range(completion_range.clone()),
 1662            completion.text[prefix_len..].chars().rev(),
 1663        );
 1664        completion_range.end = completion_range.end.saturating_sub(suffix_len);
 1665
 1666        if completion_range.is_empty()
 1667            && completion_range.start == cursor.text_anchor.to_offset(&completion_buffer)
 1668        {
 1669            Some(&completion.text[prefix_len..completion.text.len() - suffix_len])
 1670        } else {
 1671            None
 1672        }
 1673    }
 1674
 1675    fn cycle_completions(&mut self, direction: Direction) {
 1676        match direction {
 1677            Direction::Prev => {
 1678                self.active_completion_index = if self.active_completion_index == 0 {
 1679                    self.completions.len().saturating_sub(1)
 1680                } else {
 1681                    self.active_completion_index - 1
 1682                };
 1683            }
 1684            Direction::Next => {
 1685                if self.completions.len() == 0 {
 1686                    self.active_completion_index = 0
 1687                } else {
 1688                    self.active_completion_index =
 1689                        (self.active_completion_index + 1) % self.completions.len();
 1690                }
 1691            }
 1692        }
 1693    }
 1694
 1695    fn push_completion(&mut self, new_completion: copilot::Completion) {
 1696        for completion in &self.completions {
 1697            if completion.text == new_completion.text && completion.range == new_completion.range {
 1698                return;
 1699            }
 1700        }
 1701        self.completions.push(new_completion);
 1702    }
 1703
 1704    fn common_prefix<T1: Iterator<Item = char>, T2: Iterator<Item = char>>(a: T1, b: T2) -> usize {
 1705        a.zip(b)
 1706            .take_while(|(a, b)| a == b)
 1707            .map(|(a, _)| a.len_utf8())
 1708            .sum()
 1709    }
 1710}
 1711
 1712#[derive(Debug)]
 1713struct ActiveDiagnosticGroup {
 1714    primary_range: Range<Anchor>,
 1715    primary_message: String,
 1716    blocks: HashMap<BlockId, Diagnostic>,
 1717    is_valid: bool,
 1718}
 1719
 1720#[derive(Serialize, Deserialize)]
 1721pub struct ClipboardSelection {
 1722    pub len: usize,
 1723    pub is_entire_line: bool,
 1724    pub first_line_indent: u32,
 1725}
 1726
 1727#[derive(Debug)]
 1728pub struct NavigationData {
 1729    cursor_anchor: Anchor,
 1730    cursor_position: Point,
 1731    scroll_anchor: ScrollAnchor,
 1732    scroll_top_row: u32,
 1733}
 1734
 1735pub struct EditorCreated(pub View<Editor>);
 1736
 1737enum GotoDefinitionKind {
 1738    Symbol,
 1739    Type,
 1740}
 1741
 1742#[derive(Debug, Clone)]
 1743enum InlayHintRefreshReason {
 1744    Toggle(bool),
 1745    SettingsChange(InlayHintSettings),
 1746    NewLinesShown,
 1747    BufferEdited(HashSet<Arc<Language>>),
 1748    RefreshRequested,
 1749    ExcerptsRemoved(Vec<ExcerptId>),
 1750}
 1751impl InlayHintRefreshReason {
 1752    fn description(&self) -> &'static str {
 1753        match self {
 1754            Self::Toggle(_) => "toggle",
 1755            Self::SettingsChange(_) => "settings change",
 1756            Self::NewLinesShown => "new lines shown",
 1757            Self::BufferEdited(_) => "buffer edited",
 1758            Self::RefreshRequested => "refresh requested",
 1759            Self::ExcerptsRemoved(_) => "excerpts removed",
 1760        }
 1761    }
 1762}
 1763
 1764impl Editor {
 1765    pub fn single_line(cx: &mut ViewContext<Self>) -> Self {
 1766        let buffer = cx.build_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), String::new()));
 1767        let buffer = cx.build_model(|cx| MultiBuffer::singleton(buffer, cx));
 1768        Self::new(EditorMode::SingleLine, buffer, None, cx)
 1769    }
 1770
 1771    //     pub fn multi_line(
 1772    //         field_editor_style: Option<Arc<GetFieldEditorTheme>>,
 1773    //         cx: &mut ViewContext<Self>,
 1774    //     ) -> Self {
 1775    //         let buffer = cx.build_model(|cx| Buffer::new(0, cx.model_id() as u64, String::new()));
 1776    //         let buffer = cx.build_model(|cx| MultiBuffer::singleton(buffer, cx));
 1777    //         Self::new(EditorMode::Full, buffer, None, field_editor_style, cx)
 1778    //     }
 1779
 1780    //     pub fn auto_height(
 1781    //         max_lines: usize,
 1782    //         field_editor_style: Option<Arc<GetFieldEditorTheme>>,
 1783    //         cx: &mut ViewContext<Self>,
 1784    //     ) -> Self {
 1785    //         let buffer = cx.build_model(|cx| Buffer::new(0, cx.model_id() as u64, String::new()));
 1786    //         let buffer = cx.build_model(|cx| MultiBuffer::singleton(buffer, cx));
 1787    //         Self::new(
 1788    //             EditorMode::AutoHeight { max_lines },
 1789    //             buffer,
 1790    //             None,
 1791    //             field_editor_style,
 1792    //             cx,
 1793    //         )
 1794    //     }
 1795
 1796    pub fn for_buffer(
 1797        buffer: Model<Buffer>,
 1798        project: Option<Model<Project>>,
 1799        cx: &mut ViewContext<Self>,
 1800    ) -> Self {
 1801        let buffer = cx.build_model(|cx| MultiBuffer::singleton(buffer, cx));
 1802        Self::new(EditorMode::Full, buffer, project, cx)
 1803    }
 1804
 1805    pub fn for_multibuffer(
 1806        buffer: Model<MultiBuffer>,
 1807        project: Option<Model<Project>>,
 1808        cx: &mut ViewContext<Self>,
 1809    ) -> Self {
 1810        Self::new(EditorMode::Full, buffer, project, cx)
 1811    }
 1812
 1813    pub fn clone(&self, cx: &mut ViewContext<Self>) -> Self {
 1814        let mut clone = Self::new(
 1815            self.mode,
 1816            self.buffer.clone(),
 1817            self.project.clone(),
 1818            // todo!
 1819            // self.get_field_editor_theme.clone(),
 1820            cx,
 1821        );
 1822        self.display_map.update(cx, |display_map, cx| {
 1823            let snapshot = display_map.snapshot(cx);
 1824            clone.display_map.update(cx, |display_map, cx| {
 1825                display_map.set_state(&snapshot, cx);
 1826            });
 1827        });
 1828        clone.selections.clone_state(&self.selections);
 1829        clone.scroll_manager.clone_state(&self.scroll_manager);
 1830        clone.searchable = self.searchable;
 1831        clone
 1832    }
 1833
 1834    fn new(
 1835        mode: EditorMode,
 1836        buffer: Model<MultiBuffer>,
 1837        project: Option<Model<Project>>,
 1838        // todo!()
 1839        // get_field_editor_theme: Option<Arc<GetFieldEditorTheme>>,
 1840        cx: &mut ViewContext<Self>,
 1841    ) -> Self {
 1842        // let editor_view_id = cx.view_id();
 1843        let style = cx.text_style();
 1844        let font_size = style.font_size.to_pixels(cx.rem_size());
 1845        let display_map = cx.build_model(|cx| {
 1846            // todo!()
 1847            // let settings = settings::get::<ThemeSettings>(cx);
 1848            // let style = build_style(settings, get_field_editor_theme.as_deref(), None, cx);
 1849            DisplayMap::new(buffer.clone(), style.font(), font_size, None, 2, 1, cx)
 1850        });
 1851
 1852        let selections = SelectionsCollection::new(display_map.clone(), buffer.clone());
 1853
 1854        let blink_manager = cx.build_model(|cx| BlinkManager::new(CURSOR_BLINK_INTERVAL, cx));
 1855
 1856        let soft_wrap_mode_override =
 1857            (mode == EditorMode::SingleLine).then(|| language_settings::SoftWrap::None);
 1858
 1859        let mut project_subscriptions = Vec::new();
 1860        if mode == EditorMode::Full {
 1861            if let Some(project) = project.as_ref() {
 1862                if buffer.read(cx).is_singleton() {
 1863                    project_subscriptions.push(cx.observe(project, |_, _, cx| {
 1864                        cx.emit(ItemEvent::UpdateTab);
 1865                        cx.emit(ItemEvent::UpdateBreadcrumbs);
 1866                    }));
 1867                }
 1868                project_subscriptions.push(cx.subscribe(project, |editor, _, event, cx| {
 1869                    if let project::Event::RefreshInlayHints = event {
 1870                        editor.refresh_inlay_hints(InlayHintRefreshReason::RefreshRequested, cx);
 1871                    };
 1872                }));
 1873            }
 1874        }
 1875
 1876        let inlay_hint_settings = inlay_hint_settings(
 1877            selections.newest_anchor().head(),
 1878            &buffer.read(cx).snapshot(cx),
 1879            cx,
 1880        );
 1881
 1882        let focus_handle = cx.focus_handle();
 1883        cx.on_focus(&focus_handle, Self::handle_focus).detach();
 1884        cx.on_blur(&focus_handle, Self::handle_blur).detach();
 1885
 1886        let mut this = Self {
 1887            handle: cx.view().downgrade(),
 1888            focus_handle,
 1889            buffer: buffer.clone(),
 1890            display_map: display_map.clone(),
 1891            selections,
 1892            scroll_manager: ScrollManager::new(),
 1893            columnar_selection_tail: None,
 1894            add_selections_state: None,
 1895            select_next_state: None,
 1896            select_prev_state: None,
 1897            selection_history: Default::default(),
 1898            autoclose_regions: Default::default(),
 1899            snippet_stack: Default::default(),
 1900            select_larger_syntax_node_stack: Vec::new(),
 1901            ime_transaction: Default::default(),
 1902            active_diagnostics: None,
 1903            soft_wrap_mode_override,
 1904            // get_field_editor_theme,
 1905            collaboration_hub: project.clone().map(|project| Box::new(project) as _),
 1906            project,
 1907            blink_manager: blink_manager.clone(),
 1908            show_local_selections: true,
 1909            mode,
 1910            show_gutter: mode == EditorMode::Full,
 1911            show_wrap_guides: None,
 1912            placeholder_text: None,
 1913            highlighted_rows: None,
 1914            background_highlights: Default::default(),
 1915            inlay_background_highlights: Default::default(),
 1916            nav_history: None,
 1917            context_menu: RwLock::new(None),
 1918            // mouse_context_menu: cx
 1919            //     .add_view(|cx| context_menu::ContextMenu::new(editor_view_id, cx)),
 1920            completion_tasks: Default::default(),
 1921            next_completion_id: 0,
 1922            next_inlay_id: 0,
 1923            available_code_actions: Default::default(),
 1924            code_actions_task: Default::default(),
 1925            document_highlights_task: Default::default(),
 1926            pending_rename: Default::default(),
 1927            searchable: true,
 1928            // override_text_style: None,
 1929            cursor_shape: Default::default(),
 1930            autoindent_mode: Some(AutoindentMode::EachLine),
 1931            collapse_matches: false,
 1932            workspace: None,
 1933            keymap_context_layers: Default::default(),
 1934            input_enabled: true,
 1935            read_only: false,
 1936            leader_peer_id: None,
 1937            remote_id: None,
 1938            hover_state: Default::default(),
 1939            link_go_to_definition_state: Default::default(),
 1940            copilot_state: Default::default(),
 1941            inlay_hint_cache: InlayHintCache::new(inlay_hint_settings),
 1942            gutter_hovered: false,
 1943            pixel_position_of_newest_cursor: None,
 1944            gutter_width: Default::default(),
 1945            style: None,
 1946            _subscriptions: vec![
 1947                cx.observe(&buffer, Self::on_buffer_changed),
 1948                cx.subscribe(&buffer, Self::on_buffer_event),
 1949                cx.observe(&display_map, Self::on_display_map_changed),
 1950                cx.observe(&blink_manager, |_, _, cx| cx.notify()),
 1951                cx.observe_global::<SettingsStore>(Self::settings_changed),
 1952                cx.observe_window_activation(|editor, cx| {
 1953                    let active = cx.is_window_active();
 1954                    editor.blink_manager.update(cx, |blink_manager, cx| {
 1955                        if active {
 1956                            blink_manager.enable(cx);
 1957                        } else {
 1958                            blink_manager.show_cursor(cx);
 1959                            blink_manager.disable(cx);
 1960                        }
 1961                    });
 1962                }),
 1963            ],
 1964        };
 1965
 1966        this._subscriptions.extend(project_subscriptions);
 1967
 1968        this.end_selection(cx);
 1969        this.scroll_manager.show_scrollbar(cx);
 1970
 1971        // todo!("use a different mechanism")
 1972        // let editor_created_event = EditorCreated(cx.handle());
 1973        // cx.emit_global(editor_created_event);
 1974
 1975        if mode == EditorMode::Full {
 1976            let should_auto_hide_scrollbars = cx.should_auto_hide_scrollbars();
 1977            cx.set_global(ScrollbarAutoHide(should_auto_hide_scrollbars));
 1978        }
 1979
 1980        this.report_editor_event("open", None, cx);
 1981        this
 1982    }
 1983
 1984    fn dispatch_context(&self, cx: &AppContext) -> KeyContext {
 1985        let mut dispatch_context = KeyContext::default();
 1986        dispatch_context.add("Editor");
 1987        let mode = match self.mode {
 1988            EditorMode::SingleLine => "single_line",
 1989            EditorMode::AutoHeight { .. } => "auto_height",
 1990            EditorMode::Full => "full",
 1991        };
 1992        dispatch_context.set("mode", mode);
 1993        if self.pending_rename.is_some() {
 1994            dispatch_context.add("renaming");
 1995        }
 1996        if self.context_menu_visible() {
 1997            match self.context_menu.read().as_ref() {
 1998                Some(ContextMenu::Completions(_)) => {
 1999                    dispatch_context.add("menu");
 2000                    dispatch_context.add("showing_completions")
 2001                }
 2002                Some(ContextMenu::CodeActions(_)) => {
 2003                    dispatch_context.add("menu");
 2004                    dispatch_context.add("showing_code_actions")
 2005                }
 2006                None => {}
 2007            }
 2008        }
 2009
 2010        for layer in self.keymap_context_layers.values() {
 2011            dispatch_context.extend(layer);
 2012        }
 2013
 2014        if let Some(extension) = self
 2015            .buffer
 2016            .read(cx)
 2017            .as_singleton()
 2018            .and_then(|buffer| buffer.read(cx).file()?.path().extension()?.to_str())
 2019        {
 2020            dispatch_context.set("extension", extension.to_string());
 2021        }
 2022
 2023        dispatch_context
 2024    }
 2025
 2026    pub fn new_file(
 2027        workspace: &mut Workspace,
 2028        _: &workspace::NewFile,
 2029        cx: &mut ViewContext<Workspace>,
 2030    ) {
 2031        let project = workspace.project().clone();
 2032        if project.read(cx).is_remote() {
 2033            cx.propagate();
 2034        } else if let Some(buffer) = project
 2035            .update(cx, |project, cx| project.create_buffer("", None, cx))
 2036            .log_err()
 2037        {
 2038            workspace.add_item(
 2039                Box::new(cx.build_view(|cx| Editor::for_buffer(buffer, Some(project.clone()), cx))),
 2040                cx,
 2041            );
 2042        }
 2043    }
 2044
 2045    //     pub fn new_file_in_direction(
 2046    //         workspace: &mut Workspace,
 2047    //         action: &workspace::NewFileInDirection,
 2048    //         cx: &mut ViewContext<Workspace>,
 2049    //     ) {
 2050    //         let project = workspace.project().clone();
 2051    //         if project.read(cx).is_remote() {
 2052    //             cx.propagate();
 2053    //         } else if let Some(buffer) = project
 2054    //             .update(cx, |project, cx| project.create_buffer("", None, cx))
 2055    //             .log_err()
 2056    //         {
 2057    //             workspace.split_item(
 2058    //                 action.0,
 2059    //                 Box::new(cx.add_view(|cx| Editor::for_buffer(buffer, Some(project.clone()), cx))),
 2060    //                 cx,
 2061    //             );
 2062    //         }
 2063    //     }
 2064
 2065    pub fn replica_id(&self, cx: &AppContext) -> ReplicaId {
 2066        self.buffer.read(cx).replica_id()
 2067    }
 2068
 2069    //     pub fn leader_peer_id(&self) -> Option<PeerId> {
 2070    //         self.leader_peer_id
 2071    //     }
 2072
 2073    pub fn buffer(&self) -> &Model<MultiBuffer> {
 2074        &self.buffer
 2075    }
 2076
 2077    fn workspace(&self) -> Option<View<Workspace>> {
 2078        self.workspace.as_ref()?.0.upgrade()
 2079    }
 2080
 2081    pub fn title<'a>(&self, cx: &'a AppContext) -> Cow<'a, str> {
 2082        self.buffer().read(cx).title(cx)
 2083    }
 2084
 2085    pub fn snapshot(&mut self, cx: &mut WindowContext) -> EditorSnapshot {
 2086        EditorSnapshot {
 2087            mode: self.mode,
 2088            show_gutter: self.show_gutter,
 2089            display_snapshot: self.display_map.update(cx, |map, cx| map.snapshot(cx)),
 2090            scroll_anchor: self.scroll_manager.anchor(),
 2091            ongoing_scroll: self.scroll_manager.ongoing_scroll(),
 2092            placeholder_text: self.placeholder_text.clone(),
 2093            is_focused: self.focus_handle.is_focused(cx),
 2094        }
 2095    }
 2096
 2097    //     pub fn language_at<'a, T: ToOffset>(
 2098    //         &self,
 2099    //         point: T,
 2100    //         cx: &'a AppContext,
 2101    //     ) -> Option<Arc<Language>> {
 2102    //         self.buffer.read(cx).language_at(point, cx)
 2103    //     }
 2104
 2105    //     pub fn file_at<'a, T: ToOffset>(&self, point: T, cx: &'a AppContext) -> Option<Arc<dyn File>> {
 2106    //         self.buffer.read(cx).read(cx).file_at(point).cloned()
 2107    //     }
 2108
 2109    //     pub fn active_excerpt(
 2110    //         &self,
 2111    //         cx: &AppContext,
 2112    //     ) -> Option<(ExcerptId, Model<Buffer>, Range<text::Anchor>)> {
 2113    //         self.buffer
 2114    //             .read(cx)
 2115    //             .excerpt_containing(self.selections.newest_anchor().head(), cx)
 2116    //     }
 2117
 2118    //     pub fn style(&self, cx: &AppContext) -> EditorStyle {
 2119    //         build_style(
 2120    //             settings::get::<ThemeSettings>(cx),
 2121    //             self.get_field_editor_theme.as_deref(),
 2122    //             self.override_text_style.as_deref(),
 2123    //             cx,
 2124    //         )
 2125    //     }
 2126
 2127    pub fn mode(&self) -> EditorMode {
 2128        self.mode
 2129    }
 2130
 2131    pub fn collaboration_hub(&self) -> Option<&dyn CollaborationHub> {
 2132        self.collaboration_hub.as_deref()
 2133    }
 2134
 2135    pub fn set_collaboration_hub(&mut self, hub: Box<dyn CollaborationHub>) {
 2136        self.collaboration_hub = Some(hub);
 2137    }
 2138
 2139    pub fn set_placeholder_text(
 2140        &mut self,
 2141        placeholder_text: impl Into<Arc<str>>,
 2142        cx: &mut ViewContext<Self>,
 2143    ) {
 2144        self.placeholder_text = Some(placeholder_text.into());
 2145        cx.notify();
 2146    }
 2147
 2148    //     pub fn set_cursor_shape(&mut self, cursor_shape: CursorShape, cx: &mut ViewContext<Self>) {
 2149    //         self.cursor_shape = cursor_shape;
 2150    //         cx.notify();
 2151    //     }
 2152
 2153    //     pub fn set_collapse_matches(&mut self, collapse_matches: bool) {
 2154    //         self.collapse_matches = collapse_matches;
 2155    //     }
 2156
 2157    pub fn range_for_match<T: std::marker::Copy>(&self, range: &Range<T>) -> Range<T> {
 2158        if self.collapse_matches {
 2159            return range.start..range.start;
 2160        }
 2161        range.clone()
 2162    }
 2163
 2164    //     pub fn set_clip_at_line_ends(&mut self, clip: bool, cx: &mut ViewContext<Self>) {
 2165    //         if self.display_map.read(cx).clip_at_line_ends != clip {
 2166    //             self.display_map
 2167    //                 .update(cx, |map, _| map.clip_at_line_ends = clip);
 2168    //         }
 2169    //     }
 2170
 2171    //     pub fn set_keymap_context_layer<Tag: 'static>(
 2172    //         &mut self,
 2173    //         context: KeymapContext,
 2174    //         cx: &mut ViewContext<Self>,
 2175    //     ) {
 2176    //         self.keymap_context_layers
 2177    //             .insert(TypeId::of::<Tag>(), context);
 2178    //         cx.notify();
 2179    //     }
 2180
 2181    //     pub fn remove_keymap_context_layer<Tag: 'static>(&mut self, cx: &mut ViewContext<Self>) {
 2182    //         self.keymap_context_layers.remove(&TypeId::of::<Tag>());
 2183    //         cx.notify();
 2184    //     }
 2185
 2186    //     pub fn set_input_enabled(&mut self, input_enabled: bool) {
 2187    //         self.input_enabled = input_enabled;
 2188    //     }
 2189
 2190    //     pub fn set_autoindent(&mut self, autoindent: bool) {
 2191    //         if autoindent {
 2192    //             self.autoindent_mode = Some(AutoindentMode::EachLine);
 2193    //         } else {
 2194    //             self.autoindent_mode = None;
 2195    //         }
 2196    //     }
 2197
 2198    //     pub fn read_only(&self) -> bool {
 2199    //         self.read_only
 2200    //     }
 2201
 2202    //     pub fn set_read_only(&mut self, read_only: bool) {
 2203    //         self.read_only = read_only;
 2204    //     }
 2205
 2206    //     pub fn set_field_editor_style(
 2207    //         &mut self,
 2208    //         style: Option<Arc<GetFieldEditorTheme>>,
 2209    //         cx: &mut ViewContext<Self>,
 2210    //     ) {
 2211    //         self.get_field_editor_theme = style;
 2212    //         cx.notify();
 2213    //     }
 2214
 2215    fn selections_did_change(
 2216        &mut self,
 2217        local: bool,
 2218        old_cursor_position: &Anchor,
 2219        cx: &mut ViewContext<Self>,
 2220    ) {
 2221        if self.focus_handle.is_focused(cx) && self.leader_peer_id.is_none() {
 2222            self.buffer.update(cx, |buffer, cx| {
 2223                buffer.set_active_selections(
 2224                    &self.selections.disjoint_anchors(),
 2225                    self.selections.line_mode,
 2226                    self.cursor_shape,
 2227                    cx,
 2228                )
 2229            });
 2230        }
 2231
 2232        let display_map = self
 2233            .display_map
 2234            .update(cx, |display_map, cx| display_map.snapshot(cx));
 2235        let buffer = &display_map.buffer_snapshot;
 2236        self.add_selections_state = None;
 2237        self.select_next_state = None;
 2238        self.select_prev_state = None;
 2239        self.select_larger_syntax_node_stack.clear();
 2240        self.invalidate_autoclose_regions(&self.selections.disjoint_anchors(), buffer);
 2241        self.snippet_stack
 2242            .invalidate(&self.selections.disjoint_anchors(), buffer);
 2243        self.take_rename(false, cx);
 2244
 2245        let new_cursor_position = self.selections.newest_anchor().head();
 2246
 2247        self.push_to_nav_history(
 2248            old_cursor_position.clone(),
 2249            Some(new_cursor_position.to_point(buffer)),
 2250            cx,
 2251        );
 2252
 2253        if local {
 2254            let new_cursor_position = self.selections.newest_anchor().head();
 2255            let mut context_menu = self.context_menu.write();
 2256            let completion_menu = match context_menu.as_ref() {
 2257                Some(ContextMenu::Completions(menu)) => Some(menu),
 2258
 2259                _ => {
 2260                    *context_menu = None;
 2261                    None
 2262                }
 2263            };
 2264
 2265            if let Some(completion_menu) = completion_menu {
 2266                let cursor_position = new_cursor_position.to_offset(buffer);
 2267                let (word_range, kind) =
 2268                    buffer.surrounding_word(completion_menu.initial_position.clone());
 2269                if kind == Some(CharKind::Word)
 2270                    && word_range.to_inclusive().contains(&cursor_position)
 2271                {
 2272                    let mut completion_menu = completion_menu.clone();
 2273                    drop(context_menu);
 2274
 2275                    let query = Self::completion_query(buffer, cursor_position);
 2276                    cx.spawn(move |this, mut cx| async move {
 2277                        completion_menu
 2278                            .filter(query.as_deref(), cx.background_executor().clone())
 2279                            .await;
 2280
 2281                        this.update(&mut cx, |this, cx| {
 2282                            let mut context_menu = this.context_menu.write();
 2283                            let Some(ContextMenu::Completions(menu)) = context_menu.as_ref() else {
 2284                                return;
 2285                            };
 2286
 2287                            if menu.id > completion_menu.id {
 2288                                return;
 2289                            }
 2290
 2291                            *context_menu = Some(ContextMenu::Completions(completion_menu));
 2292                            drop(context_menu);
 2293                            cx.notify();
 2294                        })
 2295                    })
 2296                    .detach();
 2297
 2298                    self.show_completions(&ShowCompletions, cx);
 2299                } else {
 2300                    drop(context_menu);
 2301                    self.hide_context_menu(cx);
 2302                }
 2303            } else {
 2304                drop(context_menu);
 2305            }
 2306
 2307            hide_hover(self, cx);
 2308
 2309            if old_cursor_position.to_display_point(&display_map).row()
 2310                != new_cursor_position.to_display_point(&display_map).row()
 2311            {
 2312                self.available_code_actions.take();
 2313            }
 2314            self.refresh_code_actions(cx);
 2315            self.refresh_document_highlights(cx);
 2316            refresh_matching_bracket_highlights(self, cx);
 2317            self.discard_copilot_suggestion(cx);
 2318        }
 2319
 2320        self.blink_manager.update(cx, BlinkManager::pause_blinking);
 2321        cx.emit(Event::SelectionsChanged { local });
 2322
 2323        if self.selections.disjoint_anchors().len() == 1 {
 2324            cx.emit(SearchEvent::ActiveMatchChanged)
 2325        }
 2326
 2327        if local {
 2328            cx.emit(ItemEvent::UpdateBreadcrumbs);
 2329        }
 2330
 2331        cx.notify();
 2332    }
 2333
 2334    pub fn change_selections<R>(
 2335        &mut self,
 2336        autoscroll: Option<Autoscroll>,
 2337        cx: &mut ViewContext<Self>,
 2338        change: impl FnOnce(&mut MutableSelectionsCollection<'_>) -> R,
 2339    ) -> R {
 2340        let old_cursor_position = self.selections.newest_anchor().head();
 2341        self.push_to_selection_history();
 2342
 2343        let (changed, result) = self.selections.change_with(cx, change);
 2344
 2345        if changed {
 2346            if let Some(autoscroll) = autoscroll {
 2347                self.request_autoscroll(autoscroll, cx);
 2348            }
 2349            self.selections_did_change(true, &old_cursor_position, cx);
 2350        }
 2351
 2352        result
 2353    }
 2354
 2355    pub fn edit<I, S, T>(&mut self, edits: I, cx: &mut ViewContext<Self>)
 2356    where
 2357        I: IntoIterator<Item = (Range<S>, T)>,
 2358        S: ToOffset,
 2359        T: Into<Arc<str>>,
 2360    {
 2361        if self.read_only {
 2362            return;
 2363        }
 2364
 2365        self.buffer
 2366            .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
 2367    }
 2368
 2369    pub fn edit_with_autoindent<I, S, T>(&mut self, edits: I, cx: &mut ViewContext<Self>)
 2370    where
 2371        I: IntoIterator<Item = (Range<S>, T)>,
 2372        S: ToOffset,
 2373        T: Into<Arc<str>>,
 2374    {
 2375        if self.read_only {
 2376            return;
 2377        }
 2378
 2379        self.buffer.update(cx, |buffer, cx| {
 2380            buffer.edit(edits, self.autoindent_mode.clone(), cx)
 2381        });
 2382    }
 2383
 2384    pub fn edit_with_block_indent<I, S, T>(
 2385        &mut self,
 2386        edits: I,
 2387        original_indent_columns: Vec<u32>,
 2388        cx: &mut ViewContext<Self>,
 2389    ) where
 2390        I: IntoIterator<Item = (Range<S>, T)>,
 2391        S: ToOffset,
 2392        T: Into<Arc<str>>,
 2393    {
 2394        if self.read_only {
 2395            return;
 2396        }
 2397
 2398        self.buffer.update(cx, |buffer, cx| {
 2399            buffer.edit(
 2400                edits,
 2401                Some(AutoindentMode::Block {
 2402                    original_indent_columns,
 2403                }),
 2404                cx,
 2405            )
 2406        });
 2407    }
 2408
 2409    fn select(&mut self, phase: SelectPhase, cx: &mut ViewContext<Self>) {
 2410        self.hide_context_menu(cx);
 2411
 2412        match phase {
 2413            SelectPhase::Begin {
 2414                position,
 2415                add,
 2416                click_count,
 2417            } => self.begin_selection(position, add, click_count, cx),
 2418            SelectPhase::BeginColumnar {
 2419                position,
 2420                goal_column,
 2421            } => self.begin_columnar_selection(position, goal_column, cx),
 2422            SelectPhase::Extend {
 2423                position,
 2424                click_count,
 2425            } => self.extend_selection(position, click_count, cx),
 2426            SelectPhase::Update {
 2427                position,
 2428                goal_column,
 2429                scroll_position,
 2430            } => self.update_selection(position, goal_column, scroll_position, cx),
 2431            SelectPhase::End => self.end_selection(cx),
 2432        }
 2433    }
 2434
 2435    fn extend_selection(
 2436        &mut self,
 2437        position: DisplayPoint,
 2438        click_count: usize,
 2439        cx: &mut ViewContext<Self>,
 2440    ) {
 2441        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 2442        let tail = self.selections.newest::<usize>(cx).tail();
 2443        self.begin_selection(position, false, click_count, cx);
 2444
 2445        let position = position.to_offset(&display_map, Bias::Left);
 2446        let tail_anchor = display_map.buffer_snapshot.anchor_before(tail);
 2447
 2448        let mut pending_selection = self
 2449            .selections
 2450            .pending_anchor()
 2451            .expect("extend_selection not called with pending selection");
 2452        if position >= tail {
 2453            pending_selection.start = tail_anchor;
 2454        } else {
 2455            pending_selection.end = tail_anchor;
 2456            pending_selection.reversed = true;
 2457        }
 2458
 2459        let mut pending_mode = self.selections.pending_mode().unwrap();
 2460        match &mut pending_mode {
 2461            SelectMode::Word(range) | SelectMode::Line(range) => *range = tail_anchor..tail_anchor,
 2462            _ => {}
 2463        }
 2464
 2465        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 2466            s.set_pending(pending_selection, pending_mode)
 2467        });
 2468    }
 2469
 2470    fn begin_selection(
 2471        &mut self,
 2472        position: DisplayPoint,
 2473        add: bool,
 2474        click_count: usize,
 2475        cx: &mut ViewContext<Self>,
 2476    ) {
 2477        if !self.focus_handle.is_focused(cx) {
 2478            cx.focus(&self.focus_handle);
 2479        }
 2480
 2481        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 2482        let buffer = &display_map.buffer_snapshot;
 2483        let newest_selection = self.selections.newest_anchor().clone();
 2484        let position = display_map.clip_point(position, Bias::Left);
 2485
 2486        let start;
 2487        let end;
 2488        let mode;
 2489        let auto_scroll;
 2490        match click_count {
 2491            1 => {
 2492                start = buffer.anchor_before(position.to_point(&display_map));
 2493                end = start.clone();
 2494                mode = SelectMode::Character;
 2495                auto_scroll = true;
 2496            }
 2497            2 => {
 2498                let range = movement::surrounding_word(&display_map, position);
 2499                start = buffer.anchor_before(range.start.to_point(&display_map));
 2500                end = buffer.anchor_before(range.end.to_point(&display_map));
 2501                mode = SelectMode::Word(start.clone()..end.clone());
 2502                auto_scroll = true;
 2503            }
 2504            3 => {
 2505                let position = display_map
 2506                    .clip_point(position, Bias::Left)
 2507                    .to_point(&display_map);
 2508                let line_start = display_map.prev_line_boundary(position).0;
 2509                let next_line_start = buffer.clip_point(
 2510                    display_map.next_line_boundary(position).0 + Point::new(1, 0),
 2511                    Bias::Left,
 2512                );
 2513                start = buffer.anchor_before(line_start);
 2514                end = buffer.anchor_before(next_line_start);
 2515                mode = SelectMode::Line(start.clone()..end.clone());
 2516                auto_scroll = true;
 2517            }
 2518            _ => {
 2519                start = buffer.anchor_before(0);
 2520                end = buffer.anchor_before(buffer.len());
 2521                mode = SelectMode::All;
 2522                auto_scroll = false;
 2523            }
 2524        }
 2525
 2526        self.change_selections(auto_scroll.then(|| Autoscroll::newest()), cx, |s| {
 2527            if !add {
 2528                s.clear_disjoint();
 2529            } else if click_count > 1 {
 2530                s.delete(newest_selection.id)
 2531            }
 2532
 2533            s.set_pending_anchor_range(start..end, mode);
 2534        });
 2535    }
 2536
 2537    fn begin_columnar_selection(
 2538        &mut self,
 2539        position: DisplayPoint,
 2540        goal_column: u32,
 2541        cx: &mut ViewContext<Self>,
 2542    ) {
 2543        if !self.focus_handle.is_focused(cx) {
 2544            cx.focus(&self.focus_handle);
 2545        }
 2546
 2547        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 2548        let tail = self.selections.newest::<Point>(cx).tail();
 2549        self.columnar_selection_tail = Some(display_map.buffer_snapshot.anchor_before(tail));
 2550
 2551        self.select_columns(
 2552            tail.to_display_point(&display_map),
 2553            position,
 2554            goal_column,
 2555            &display_map,
 2556            cx,
 2557        );
 2558    }
 2559
 2560    fn update_selection(
 2561        &mut self,
 2562        position: DisplayPoint,
 2563        goal_column: u32,
 2564        scroll_position: gpui::Point<f32>,
 2565        cx: &mut ViewContext<Self>,
 2566    ) {
 2567        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 2568
 2569        if let Some(tail) = self.columnar_selection_tail.as_ref() {
 2570            let tail = tail.to_display_point(&display_map);
 2571            self.select_columns(tail, position, goal_column, &display_map, cx);
 2572        } else if let Some(mut pending) = self.selections.pending_anchor() {
 2573            let buffer = self.buffer.read(cx).snapshot(cx);
 2574            let head;
 2575            let tail;
 2576            let mode = self.selections.pending_mode().unwrap();
 2577            match &mode {
 2578                SelectMode::Character => {
 2579                    head = position.to_point(&display_map);
 2580                    tail = pending.tail().to_point(&buffer);
 2581                }
 2582                SelectMode::Word(original_range) => {
 2583                    let original_display_range = original_range.start.to_display_point(&display_map)
 2584                        ..original_range.end.to_display_point(&display_map);
 2585                    let original_buffer_range = original_display_range.start.to_point(&display_map)
 2586                        ..original_display_range.end.to_point(&display_map);
 2587                    if movement::is_inside_word(&display_map, position)
 2588                        || original_display_range.contains(&position)
 2589                    {
 2590                        let word_range = movement::surrounding_word(&display_map, position);
 2591                        if word_range.start < original_display_range.start {
 2592                            head = word_range.start.to_point(&display_map);
 2593                        } else {
 2594                            head = word_range.end.to_point(&display_map);
 2595                        }
 2596                    } else {
 2597                        head = position.to_point(&display_map);
 2598                    }
 2599
 2600                    if head <= original_buffer_range.start {
 2601                        tail = original_buffer_range.end;
 2602                    } else {
 2603                        tail = original_buffer_range.start;
 2604                    }
 2605                }
 2606                SelectMode::Line(original_range) => {
 2607                    let original_range = original_range.to_point(&display_map.buffer_snapshot);
 2608
 2609                    let position = display_map
 2610                        .clip_point(position, Bias::Left)
 2611                        .to_point(&display_map);
 2612                    let line_start = display_map.prev_line_boundary(position).0;
 2613                    let next_line_start = buffer.clip_point(
 2614                        display_map.next_line_boundary(position).0 + Point::new(1, 0),
 2615                        Bias::Left,
 2616                    );
 2617
 2618                    if line_start < original_range.start {
 2619                        head = line_start
 2620                    } else {
 2621                        head = next_line_start
 2622                    }
 2623
 2624                    if head <= original_range.start {
 2625                        tail = original_range.end;
 2626                    } else {
 2627                        tail = original_range.start;
 2628                    }
 2629                }
 2630                SelectMode::All => {
 2631                    return;
 2632                }
 2633            };
 2634
 2635            if head < tail {
 2636                pending.start = buffer.anchor_before(head);
 2637                pending.end = buffer.anchor_before(tail);
 2638                pending.reversed = true;
 2639            } else {
 2640                pending.start = buffer.anchor_before(tail);
 2641                pending.end = buffer.anchor_before(head);
 2642                pending.reversed = false;
 2643            }
 2644
 2645            self.change_selections(None, cx, |s| {
 2646                s.set_pending(pending, mode);
 2647            });
 2648        } else {
 2649            log::error!("update_selection dispatched with no pending selection");
 2650            return;
 2651        }
 2652
 2653        self.set_scroll_position(scroll_position, cx);
 2654        cx.notify();
 2655    }
 2656
 2657    fn end_selection(&mut self, cx: &mut ViewContext<Self>) {
 2658        self.columnar_selection_tail.take();
 2659        if self.selections.pending_anchor().is_some() {
 2660            let selections = self.selections.all::<usize>(cx);
 2661            self.change_selections(None, cx, |s| {
 2662                s.select(selections);
 2663                s.clear_pending();
 2664            });
 2665        }
 2666    }
 2667
 2668    fn select_columns(
 2669        &mut self,
 2670        tail: DisplayPoint,
 2671        head: DisplayPoint,
 2672        goal_column: u32,
 2673        display_map: &DisplaySnapshot,
 2674        cx: &mut ViewContext<Self>,
 2675    ) {
 2676        let start_row = cmp::min(tail.row(), head.row());
 2677        let end_row = cmp::max(tail.row(), head.row());
 2678        let start_column = cmp::min(tail.column(), goal_column);
 2679        let end_column = cmp::max(tail.column(), goal_column);
 2680        let reversed = start_column < tail.column();
 2681
 2682        let selection_ranges = (start_row..=end_row)
 2683            .filter_map(|row| {
 2684                if start_column <= display_map.line_len(row) && !display_map.is_block_line(row) {
 2685                    let start = display_map
 2686                        .clip_point(DisplayPoint::new(row, start_column), Bias::Left)
 2687                        .to_point(display_map);
 2688                    let end = display_map
 2689                        .clip_point(DisplayPoint::new(row, end_column), Bias::Right)
 2690                        .to_point(display_map);
 2691                    if reversed {
 2692                        Some(end..start)
 2693                    } else {
 2694                        Some(start..end)
 2695                    }
 2696                } else {
 2697                    None
 2698                }
 2699            })
 2700            .collect::<Vec<_>>();
 2701
 2702        self.change_selections(None, cx, |s| {
 2703            s.select_ranges(selection_ranges);
 2704        });
 2705        cx.notify();
 2706    }
 2707
 2708    pub fn has_pending_nonempty_selection(&self) -> bool {
 2709        let pending_nonempty_selection = match self.selections.pending_anchor() {
 2710            Some(Selection { start, end, .. }) => start != end,
 2711            None => false,
 2712        };
 2713        pending_nonempty_selection || self.columnar_selection_tail.is_some()
 2714    }
 2715
 2716    pub fn has_pending_selection(&self) -> bool {
 2717        self.selections.pending_anchor().is_some() || self.columnar_selection_tail.is_some()
 2718    }
 2719
 2720    pub fn cancel(&mut self, _: &Cancel, cx: &mut ViewContext<Self>) {
 2721        if self.take_rename(false, cx).is_some() {
 2722            return;
 2723        }
 2724
 2725        if hide_hover(self, cx) {
 2726            return;
 2727        }
 2728
 2729        if self.hide_context_menu(cx).is_some() {
 2730            return;
 2731        }
 2732
 2733        if self.discard_copilot_suggestion(cx) {
 2734            return;
 2735        }
 2736
 2737        if self.snippet_stack.pop().is_some() {
 2738            return;
 2739        }
 2740
 2741        if self.mode == EditorMode::Full {
 2742            if self.active_diagnostics.is_some() {
 2743                self.dismiss_diagnostics(cx);
 2744                return;
 2745            }
 2746
 2747            if self.change_selections(Some(Autoscroll::fit()), cx, |s| s.try_cancel()) {
 2748                return;
 2749            }
 2750        }
 2751
 2752        cx.propagate();
 2753    }
 2754
 2755    pub fn handle_input(&mut self, text: &str, cx: &mut ViewContext<Self>) {
 2756        let text: Arc<str> = text.into();
 2757
 2758        if self.read_only {
 2759            return;
 2760        }
 2761
 2762        let selections = self.selections.all_adjusted(cx);
 2763        let mut brace_inserted = false;
 2764        let mut edits = Vec::new();
 2765        let mut new_selections = Vec::with_capacity(selections.len());
 2766        let mut new_autoclose_regions = Vec::new();
 2767        let snapshot = self.buffer.read(cx).read(cx);
 2768
 2769        for (selection, autoclose_region) in
 2770            self.selections_with_autoclose_regions(selections, &snapshot)
 2771        {
 2772            if let Some(scope) = snapshot.language_scope_at(selection.head()) {
 2773                // Determine if the inserted text matches the opening or closing
 2774                // bracket of any of this language's bracket pairs.
 2775                let mut bracket_pair = None;
 2776                let mut is_bracket_pair_start = false;
 2777                if !text.is_empty() {
 2778                    // `text` can be empty when an user is using IME (e.g. Chinese Wubi Simplified)
 2779                    //  and they are removing the character that triggered IME popup.
 2780                    for (pair, enabled) in scope.brackets() {
 2781                        if enabled && pair.close && pair.start.ends_with(text.as_ref()) {
 2782                            bracket_pair = Some(pair.clone());
 2783                            is_bracket_pair_start = true;
 2784                            break;
 2785                        } else if pair.end.as_str() == text.as_ref() {
 2786                            bracket_pair = Some(pair.clone());
 2787                            break;
 2788                        }
 2789                    }
 2790                }
 2791
 2792                if let Some(bracket_pair) = bracket_pair {
 2793                    if selection.is_empty() {
 2794                        if is_bracket_pair_start {
 2795                            let prefix_len = bracket_pair.start.len() - text.len();
 2796
 2797                            // If the inserted text is a suffix of an opening bracket and the
 2798                            // selection is preceded by the rest of the opening bracket, then
 2799                            // insert the closing bracket.
 2800                            let following_text_allows_autoclose = snapshot
 2801                                .chars_at(selection.start)
 2802                                .next()
 2803                                .map_or(true, |c| scope.should_autoclose_before(c));
 2804                            let preceding_text_matches_prefix = prefix_len == 0
 2805                                || (selection.start.column >= (prefix_len as u32)
 2806                                    && snapshot.contains_str_at(
 2807                                        Point::new(
 2808                                            selection.start.row,
 2809                                            selection.start.column - (prefix_len as u32),
 2810                                        ),
 2811                                        &bracket_pair.start[..prefix_len],
 2812                                    ));
 2813                            if following_text_allows_autoclose && preceding_text_matches_prefix {
 2814                                let anchor = snapshot.anchor_before(selection.end);
 2815                                new_selections.push((selection.map(|_| anchor), text.len()));
 2816                                new_autoclose_regions.push((
 2817                                    anchor,
 2818                                    text.len(),
 2819                                    selection.id,
 2820                                    bracket_pair.clone(),
 2821                                ));
 2822                                edits.push((
 2823                                    selection.range(),
 2824                                    format!("{}{}", text, bracket_pair.end).into(),
 2825                                ));
 2826                                brace_inserted = true;
 2827                                continue;
 2828                            }
 2829                        }
 2830
 2831                        if let Some(region) = autoclose_region {
 2832                            // If the selection is followed by an auto-inserted closing bracket,
 2833                            // then don't insert that closing bracket again; just move the selection
 2834                            // past the closing bracket.
 2835                            let should_skip = selection.end == region.range.end.to_point(&snapshot)
 2836                                && text.as_ref() == region.pair.end.as_str();
 2837                            if should_skip {
 2838                                let anchor = snapshot.anchor_after(selection.end);
 2839                                new_selections
 2840                                    .push((selection.map(|_| anchor), region.pair.end.len()));
 2841                                continue;
 2842                            }
 2843                        }
 2844                    }
 2845                    // If an opening bracket is 1 character long and is typed while
 2846                    // text is selected, then surround that text with the bracket pair.
 2847                    else if is_bracket_pair_start && bracket_pair.start.chars().count() == 1 {
 2848                        edits.push((selection.start..selection.start, text.clone()));
 2849                        edits.push((
 2850                            selection.end..selection.end,
 2851                            bracket_pair.end.as_str().into(),
 2852                        ));
 2853                        brace_inserted = true;
 2854                        new_selections.push((
 2855                            Selection {
 2856                                id: selection.id,
 2857                                start: snapshot.anchor_after(selection.start),
 2858                                end: snapshot.anchor_before(selection.end),
 2859                                reversed: selection.reversed,
 2860                                goal: selection.goal,
 2861                            },
 2862                            0,
 2863                        ));
 2864                        continue;
 2865                    }
 2866                }
 2867            }
 2868
 2869            // If not handling any auto-close operation, then just replace the selected
 2870            // text with the given input and move the selection to the end of the
 2871            // newly inserted text.
 2872            let anchor = snapshot.anchor_after(selection.end);
 2873            new_selections.push((selection.map(|_| anchor), 0));
 2874            edits.push((selection.start..selection.end, text.clone()));
 2875        }
 2876
 2877        drop(snapshot);
 2878        self.transact(cx, |this, cx| {
 2879            this.buffer.update(cx, |buffer, cx| {
 2880                buffer.edit(edits, this.autoindent_mode.clone(), cx);
 2881            });
 2882
 2883            let new_anchor_selections = new_selections.iter().map(|e| &e.0);
 2884            let new_selection_deltas = new_selections.iter().map(|e| e.1);
 2885            let snapshot = this.buffer.read(cx).read(cx);
 2886            let new_selections = resolve_multiple::<usize, _>(new_anchor_selections, &snapshot)
 2887                .zip(new_selection_deltas)
 2888                .map(|(selection, delta)| Selection {
 2889                    id: selection.id,
 2890                    start: selection.start + delta,
 2891                    end: selection.end + delta,
 2892                    reversed: selection.reversed,
 2893                    goal: SelectionGoal::None,
 2894                })
 2895                .collect::<Vec<_>>();
 2896
 2897            let mut i = 0;
 2898            for (position, delta, selection_id, pair) in new_autoclose_regions {
 2899                let position = position.to_offset(&snapshot) + delta;
 2900                let start = snapshot.anchor_before(position);
 2901                let end = snapshot.anchor_after(position);
 2902                while let Some(existing_state) = this.autoclose_regions.get(i) {
 2903                    match existing_state.range.start.cmp(&start, &snapshot) {
 2904                        Ordering::Less => i += 1,
 2905                        Ordering::Greater => break,
 2906                        Ordering::Equal => match end.cmp(&existing_state.range.end, &snapshot) {
 2907                            Ordering::Less => i += 1,
 2908                            Ordering::Equal => break,
 2909                            Ordering::Greater => break,
 2910                        },
 2911                    }
 2912                }
 2913                this.autoclose_regions.insert(
 2914                    i,
 2915                    AutocloseRegion {
 2916                        selection_id,
 2917                        range: start..end,
 2918                        pair,
 2919                    },
 2920                );
 2921            }
 2922
 2923            drop(snapshot);
 2924            let had_active_copilot_suggestion = this.has_active_copilot_suggestion(cx);
 2925            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(new_selections));
 2926
 2927            if !brace_inserted && EditorSettings::get_global(cx).use_on_type_format {
 2928                if let Some(on_type_format_task) =
 2929                    this.trigger_on_type_formatting(text.to_string(), cx)
 2930                {
 2931                    on_type_format_task.detach_and_log_err(cx);
 2932                }
 2933            }
 2934
 2935            if had_active_copilot_suggestion {
 2936                this.refresh_copilot_suggestions(true, cx);
 2937                if !this.has_active_copilot_suggestion(cx) {
 2938                    this.trigger_completion_on_input(&text, cx);
 2939                }
 2940            } else {
 2941                this.trigger_completion_on_input(&text, cx);
 2942                this.refresh_copilot_suggestions(true, cx);
 2943            }
 2944        });
 2945    }
 2946
 2947    pub fn newline(&mut self, _: &Newline, cx: &mut ViewContext<Self>) {
 2948        self.transact(cx, |this, cx| {
 2949            let (edits, selection_fixup_info): (Vec<_>, Vec<_>) = {
 2950                let selections = this.selections.all::<usize>(cx);
 2951                let multi_buffer = this.buffer.read(cx);
 2952                let buffer = multi_buffer.snapshot(cx);
 2953                selections
 2954                    .iter()
 2955                    .map(|selection| {
 2956                        let start_point = selection.start.to_point(&buffer);
 2957                        let mut indent = buffer.indent_size_for_line(start_point.row);
 2958                        indent.len = cmp::min(indent.len, start_point.column);
 2959                        let start = selection.start;
 2960                        let end = selection.end;
 2961                        let is_cursor = start == end;
 2962                        let language_scope = buffer.language_scope_at(start);
 2963                        let (comment_delimiter, insert_extra_newline) = if let Some(language) =
 2964                            &language_scope
 2965                        {
 2966                            let leading_whitespace_len = buffer
 2967                                .reversed_chars_at(start)
 2968                                .take_while(|c| c.is_whitespace() && *c != '\n')
 2969                                .map(|c| c.len_utf8())
 2970                                .sum::<usize>();
 2971
 2972                            let trailing_whitespace_len = buffer
 2973                                .chars_at(end)
 2974                                .take_while(|c| c.is_whitespace() && *c != '\n')
 2975                                .map(|c| c.len_utf8())
 2976                                .sum::<usize>();
 2977
 2978                            let insert_extra_newline =
 2979                                language.brackets().any(|(pair, enabled)| {
 2980                                    let pair_start = pair.start.trim_end();
 2981                                    let pair_end = pair.end.trim_start();
 2982
 2983                                    enabled
 2984                                        && pair.newline
 2985                                        && buffer.contains_str_at(
 2986                                            end + trailing_whitespace_len,
 2987                                            pair_end,
 2988                                        )
 2989                                        && buffer.contains_str_at(
 2990                                            (start - leading_whitespace_len)
 2991                                                .saturating_sub(pair_start.len()),
 2992                                            pair_start,
 2993                                        )
 2994                                });
 2995                            // Comment extension on newline is allowed only for cursor selections
 2996                            let comment_delimiter = language.line_comment_prefix().filter(|_| {
 2997                                let is_comment_extension_enabled =
 2998                                    multi_buffer.settings_at(0, cx).extend_comment_on_newline;
 2999                                is_cursor && is_comment_extension_enabled
 3000                            });
 3001                            let comment_delimiter = if let Some(delimiter) = comment_delimiter {
 3002                                buffer
 3003                                    .buffer_line_for_row(start_point.row)
 3004                                    .is_some_and(|(snapshot, range)| {
 3005                                        let mut index_of_first_non_whitespace = 0;
 3006                                        let line_starts_with_comment = snapshot
 3007                                            .chars_for_range(range)
 3008                                            .skip_while(|c| {
 3009                                                let should_skip = c.is_whitespace();
 3010                                                if should_skip {
 3011                                                    index_of_first_non_whitespace += 1;
 3012                                                }
 3013                                                should_skip
 3014                                            })
 3015                                            .take(delimiter.len())
 3016                                            .eq(delimiter.chars());
 3017                                        let cursor_is_placed_after_comment_marker =
 3018                                            index_of_first_non_whitespace + delimiter.len()
 3019                                                <= start_point.column as usize;
 3020                                        line_starts_with_comment
 3021                                            && cursor_is_placed_after_comment_marker
 3022                                    })
 3023                                    .then(|| delimiter.clone())
 3024                            } else {
 3025                                None
 3026                            };
 3027                            (comment_delimiter, insert_extra_newline)
 3028                        } else {
 3029                            (None, false)
 3030                        };
 3031
 3032                        let capacity_for_delimiter = comment_delimiter
 3033                            .as_deref()
 3034                            .map(str::len)
 3035                            .unwrap_or_default();
 3036                        let mut new_text =
 3037                            String::with_capacity(1 + capacity_for_delimiter + indent.len as usize);
 3038                        new_text.push_str("\n");
 3039                        new_text.extend(indent.chars());
 3040                        if let Some(delimiter) = &comment_delimiter {
 3041                            new_text.push_str(&delimiter);
 3042                        }
 3043                        if insert_extra_newline {
 3044                            new_text = new_text.repeat(2);
 3045                        }
 3046
 3047                        let anchor = buffer.anchor_after(end);
 3048                        let new_selection = selection.map(|_| anchor);
 3049                        (
 3050                            (start..end, new_text),
 3051                            (insert_extra_newline, new_selection),
 3052                        )
 3053                    })
 3054                    .unzip()
 3055            };
 3056
 3057            this.edit_with_autoindent(edits, cx);
 3058            let buffer = this.buffer.read(cx).snapshot(cx);
 3059            let new_selections = selection_fixup_info
 3060                .into_iter()
 3061                .map(|(extra_newline_inserted, new_selection)| {
 3062                    let mut cursor = new_selection.end.to_point(&buffer);
 3063                    if extra_newline_inserted {
 3064                        cursor.row -= 1;
 3065                        cursor.column = buffer.line_len(cursor.row);
 3066                    }
 3067                    new_selection.map(|_| cursor)
 3068                })
 3069                .collect();
 3070
 3071            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(new_selections));
 3072            this.refresh_copilot_suggestions(true, cx);
 3073        });
 3074    }
 3075
 3076    pub fn newline_above(&mut self, _: &NewlineAbove, cx: &mut ViewContext<Self>) {
 3077        let buffer = self.buffer.read(cx);
 3078        let snapshot = buffer.snapshot(cx);
 3079
 3080        let mut edits = Vec::new();
 3081        let mut rows = Vec::new();
 3082        let mut rows_inserted = 0;
 3083
 3084        for selection in self.selections.all_adjusted(cx) {
 3085            let cursor = selection.head();
 3086            let row = cursor.row;
 3087
 3088            let start_of_line = snapshot.clip_point(Point::new(row, 0), Bias::Left);
 3089
 3090            let newline = "\n".to_string();
 3091            edits.push((start_of_line..start_of_line, newline));
 3092
 3093            rows.push(row + rows_inserted);
 3094            rows_inserted += 1;
 3095        }
 3096
 3097        self.transact(cx, |editor, cx| {
 3098            editor.edit(edits, cx);
 3099
 3100            editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
 3101                let mut index = 0;
 3102                s.move_cursors_with(|map, _, _| {
 3103                    let row = rows[index];
 3104                    index += 1;
 3105
 3106                    let point = Point::new(row, 0);
 3107                    let boundary = map.next_line_boundary(point).1;
 3108                    let clipped = map.clip_point(boundary, Bias::Left);
 3109
 3110                    (clipped, SelectionGoal::None)
 3111                });
 3112            });
 3113
 3114            let mut indent_edits = Vec::new();
 3115            let multibuffer_snapshot = editor.buffer.read(cx).snapshot(cx);
 3116            for row in rows {
 3117                let indents = multibuffer_snapshot.suggested_indents(row..row + 1, cx);
 3118                for (row, indent) in indents {
 3119                    if indent.len == 0 {
 3120                        continue;
 3121                    }
 3122
 3123                    let text = match indent.kind {
 3124                        IndentKind::Space => " ".repeat(indent.len as usize),
 3125                        IndentKind::Tab => "\t".repeat(indent.len as usize),
 3126                    };
 3127                    let point = Point::new(row, 0);
 3128                    indent_edits.push((point..point, text));
 3129                }
 3130            }
 3131            editor.edit(indent_edits, cx);
 3132        });
 3133    }
 3134
 3135    pub fn newline_below(&mut self, _: &NewlineBelow, cx: &mut ViewContext<Self>) {
 3136        let buffer = self.buffer.read(cx);
 3137        let snapshot = buffer.snapshot(cx);
 3138
 3139        let mut edits = Vec::new();
 3140        let mut rows = Vec::new();
 3141        let mut rows_inserted = 0;
 3142
 3143        for selection in self.selections.all_adjusted(cx) {
 3144            let cursor = selection.head();
 3145            let row = cursor.row;
 3146
 3147            let point = Point::new(row + 1, 0);
 3148            let start_of_line = snapshot.clip_point(point, Bias::Left);
 3149
 3150            let newline = "\n".to_string();
 3151            edits.push((start_of_line..start_of_line, newline));
 3152
 3153            rows_inserted += 1;
 3154            rows.push(row + rows_inserted);
 3155        }
 3156
 3157        self.transact(cx, |editor, cx| {
 3158            editor.edit(edits, cx);
 3159
 3160            editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
 3161                let mut index = 0;
 3162                s.move_cursors_with(|map, _, _| {
 3163                    let row = rows[index];
 3164                    index += 1;
 3165
 3166                    let point = Point::new(row, 0);
 3167                    let boundary = map.next_line_boundary(point).1;
 3168                    let clipped = map.clip_point(boundary, Bias::Left);
 3169
 3170                    (clipped, SelectionGoal::None)
 3171                });
 3172            });
 3173
 3174            let mut indent_edits = Vec::new();
 3175            let multibuffer_snapshot = editor.buffer.read(cx).snapshot(cx);
 3176            for row in rows {
 3177                let indents = multibuffer_snapshot.suggested_indents(row..row + 1, cx);
 3178                for (row, indent) in indents {
 3179                    if indent.len == 0 {
 3180                        continue;
 3181                    }
 3182
 3183                    let text = match indent.kind {
 3184                        IndentKind::Space => " ".repeat(indent.len as usize),
 3185                        IndentKind::Tab => "\t".repeat(indent.len as usize),
 3186                    };
 3187                    let point = Point::new(row, 0);
 3188                    indent_edits.push((point..point, text));
 3189                }
 3190            }
 3191            editor.edit(indent_edits, cx);
 3192        });
 3193    }
 3194
 3195    pub fn insert(&mut self, text: &str, cx: &mut ViewContext<Self>) {
 3196        self.insert_with_autoindent_mode(
 3197            text,
 3198            Some(AutoindentMode::Block {
 3199                original_indent_columns: Vec::new(),
 3200            }),
 3201            cx,
 3202        );
 3203    }
 3204
 3205    fn insert_with_autoindent_mode(
 3206        &mut self,
 3207        text: &str,
 3208        autoindent_mode: Option<AutoindentMode>,
 3209        cx: &mut ViewContext<Self>,
 3210    ) {
 3211        if self.read_only {
 3212            return;
 3213        }
 3214
 3215        let text: Arc<str> = text.into();
 3216        self.transact(cx, |this, cx| {
 3217            let old_selections = this.selections.all_adjusted(cx);
 3218            let selection_anchors = this.buffer.update(cx, |buffer, cx| {
 3219                let anchors = {
 3220                    let snapshot = buffer.read(cx);
 3221                    old_selections
 3222                        .iter()
 3223                        .map(|s| {
 3224                            let anchor = snapshot.anchor_after(s.head());
 3225                            s.map(|_| anchor)
 3226                        })
 3227                        .collect::<Vec<_>>()
 3228                };
 3229                buffer.edit(
 3230                    old_selections
 3231                        .iter()
 3232                        .map(|s| (s.start..s.end, text.clone())),
 3233                    autoindent_mode,
 3234                    cx,
 3235                );
 3236                anchors
 3237            });
 3238
 3239            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 3240                s.select_anchors(selection_anchors);
 3241            })
 3242        });
 3243    }
 3244
 3245    fn trigger_completion_on_input(&mut self, text: &str, cx: &mut ViewContext<Self>) {
 3246        if !EditorSettings::get_global(cx).show_completions_on_input {
 3247            return;
 3248        }
 3249
 3250        let selection = self.selections.newest_anchor();
 3251        if self
 3252            .buffer
 3253            .read(cx)
 3254            .is_completion_trigger(selection.head(), text, cx)
 3255        {
 3256            self.show_completions(&ShowCompletions, cx);
 3257        } else {
 3258            self.hide_context_menu(cx);
 3259        }
 3260    }
 3261
 3262    /// If any empty selections is touching the start of its innermost containing autoclose
 3263    /// region, expand it to select the brackets.
 3264    fn select_autoclose_pair(&mut self, cx: &mut ViewContext<Self>) {
 3265        let selections = self.selections.all::<usize>(cx);
 3266        let buffer = self.buffer.read(cx).read(cx);
 3267        let mut new_selections = Vec::new();
 3268        for (mut selection, region) in self.selections_with_autoclose_regions(selections, &buffer) {
 3269            if let (Some(region), true) = (region, selection.is_empty()) {
 3270                let mut range = region.range.to_offset(&buffer);
 3271                if selection.start == range.start {
 3272                    if range.start >= region.pair.start.len() {
 3273                        range.start -= region.pair.start.len();
 3274                        if buffer.contains_str_at(range.start, &region.pair.start) {
 3275                            if buffer.contains_str_at(range.end, &region.pair.end) {
 3276                                range.end += region.pair.end.len();
 3277                                selection.start = range.start;
 3278                                selection.end = range.end;
 3279                            }
 3280                        }
 3281                    }
 3282                }
 3283            }
 3284            new_selections.push(selection);
 3285        }
 3286
 3287        drop(buffer);
 3288        self.change_selections(None, cx, |selections| selections.select(new_selections));
 3289    }
 3290
 3291    /// Iterate the given selections, and for each one, find the smallest surrounding
 3292    /// autoclose region. This uses the ordering of the selections and the autoclose
 3293    /// regions to avoid repeated comparisons.
 3294    fn selections_with_autoclose_regions<'a, D: ToOffset + Clone>(
 3295        &'a self,
 3296        selections: impl IntoIterator<Item = Selection<D>>,
 3297        buffer: &'a MultiBufferSnapshot,
 3298    ) -> impl Iterator<Item = (Selection<D>, Option<&'a AutocloseRegion>)> {
 3299        let mut i = 0;
 3300        let mut regions = self.autoclose_regions.as_slice();
 3301        selections.into_iter().map(move |selection| {
 3302            let range = selection.start.to_offset(buffer)..selection.end.to_offset(buffer);
 3303
 3304            let mut enclosing = None;
 3305            while let Some(pair_state) = regions.get(i) {
 3306                if pair_state.range.end.to_offset(buffer) < range.start {
 3307                    regions = &regions[i + 1..];
 3308                    i = 0;
 3309                } else if pair_state.range.start.to_offset(buffer) > range.end {
 3310                    break;
 3311                } else {
 3312                    if pair_state.selection_id == selection.id {
 3313                        enclosing = Some(pair_state);
 3314                    }
 3315                    i += 1;
 3316                }
 3317            }
 3318
 3319            (selection.clone(), enclosing)
 3320        })
 3321    }
 3322
 3323    /// Remove any autoclose regions that no longer contain their selection.
 3324    fn invalidate_autoclose_regions(
 3325        &mut self,
 3326        mut selections: &[Selection<Anchor>],
 3327        buffer: &MultiBufferSnapshot,
 3328    ) {
 3329        self.autoclose_regions.retain(|state| {
 3330            let mut i = 0;
 3331            while let Some(selection) = selections.get(i) {
 3332                if selection.end.cmp(&state.range.start, buffer).is_lt() {
 3333                    selections = &selections[1..];
 3334                    continue;
 3335                }
 3336                if selection.start.cmp(&state.range.end, buffer).is_gt() {
 3337                    break;
 3338                }
 3339                if selection.id == state.selection_id {
 3340                    return true;
 3341                } else {
 3342                    i += 1;
 3343                }
 3344            }
 3345            false
 3346        });
 3347    }
 3348
 3349    fn completion_query(buffer: &MultiBufferSnapshot, position: impl ToOffset) -> Option<String> {
 3350        let offset = position.to_offset(buffer);
 3351        let (word_range, kind) = buffer.surrounding_word(offset);
 3352        if offset > word_range.start && kind == Some(CharKind::Word) {
 3353            Some(
 3354                buffer
 3355                    .text_for_range(word_range.start..offset)
 3356                    .collect::<String>(),
 3357            )
 3358        } else {
 3359            None
 3360        }
 3361    }
 3362
 3363    pub fn toggle_inlay_hints(&mut self, _: &ToggleInlayHints, cx: &mut ViewContext<Self>) {
 3364        self.refresh_inlay_hints(
 3365            InlayHintRefreshReason::Toggle(!self.inlay_hint_cache.enabled),
 3366            cx,
 3367        );
 3368    }
 3369
 3370    pub fn inlay_hints_enabled(&self) -> bool {
 3371        self.inlay_hint_cache.enabled
 3372    }
 3373
 3374    fn refresh_inlay_hints(&mut self, reason: InlayHintRefreshReason, cx: &mut ViewContext<Self>) {
 3375        if self.project.is_none() || self.mode != EditorMode::Full {
 3376            return;
 3377        }
 3378
 3379        let reason_description = reason.description();
 3380        let (invalidate_cache, required_languages) = match reason {
 3381            InlayHintRefreshReason::Toggle(enabled) => {
 3382                self.inlay_hint_cache.enabled = enabled;
 3383                if enabled {
 3384                    (InvalidationStrategy::RefreshRequested, None)
 3385                } else {
 3386                    self.inlay_hint_cache.clear();
 3387                    self.splice_inlay_hints(
 3388                        self.visible_inlay_hints(cx)
 3389                            .iter()
 3390                            .map(|inlay| inlay.id)
 3391                            .collect(),
 3392                        Vec::new(),
 3393                        cx,
 3394                    );
 3395                    return;
 3396                }
 3397            }
 3398            InlayHintRefreshReason::SettingsChange(new_settings) => {
 3399                match self.inlay_hint_cache.update_settings(
 3400                    &self.buffer,
 3401                    new_settings,
 3402                    self.visible_inlay_hints(cx),
 3403                    cx,
 3404                ) {
 3405                    ControlFlow::Break(Some(InlaySplice {
 3406                        to_remove,
 3407                        to_insert,
 3408                    })) => {
 3409                        self.splice_inlay_hints(to_remove, to_insert, cx);
 3410                        return;
 3411                    }
 3412                    ControlFlow::Break(None) => return,
 3413                    ControlFlow::Continue(()) => (InvalidationStrategy::RefreshRequested, None),
 3414                }
 3415            }
 3416            InlayHintRefreshReason::ExcerptsRemoved(excerpts_removed) => {
 3417                if let Some(InlaySplice {
 3418                    to_remove,
 3419                    to_insert,
 3420                }) = self.inlay_hint_cache.remove_excerpts(excerpts_removed)
 3421                {
 3422                    self.splice_inlay_hints(to_remove, to_insert, cx);
 3423                }
 3424                return;
 3425            }
 3426            InlayHintRefreshReason::NewLinesShown => (InvalidationStrategy::None, None),
 3427            InlayHintRefreshReason::BufferEdited(buffer_languages) => {
 3428                (InvalidationStrategy::BufferEdited, Some(buffer_languages))
 3429            }
 3430            InlayHintRefreshReason::RefreshRequested => {
 3431                (InvalidationStrategy::RefreshRequested, None)
 3432            }
 3433        };
 3434
 3435        if let Some(InlaySplice {
 3436            to_remove,
 3437            to_insert,
 3438        }) = self.inlay_hint_cache.spawn_hint_refresh(
 3439            reason_description,
 3440            self.excerpt_visible_offsets(required_languages.as_ref(), cx),
 3441            invalidate_cache,
 3442            cx,
 3443        ) {
 3444            self.splice_inlay_hints(to_remove, to_insert, cx);
 3445        }
 3446    }
 3447
 3448    fn visible_inlay_hints(&self, cx: &ViewContext<'_, Editor>) -> Vec<Inlay> {
 3449        self.display_map
 3450            .read(cx)
 3451            .current_inlays()
 3452            .filter(move |inlay| {
 3453                Some(inlay.id) != self.copilot_state.suggestion.as_ref().map(|h| h.id)
 3454            })
 3455            .cloned()
 3456            .collect()
 3457    }
 3458
 3459    pub fn excerpt_visible_offsets(
 3460        &self,
 3461        restrict_to_languages: Option<&HashSet<Arc<Language>>>,
 3462        cx: &mut ViewContext<Editor>,
 3463    ) -> HashMap<ExcerptId, (Model<Buffer>, clock::Global, Range<usize>)> {
 3464        let multi_buffer = self.buffer().read(cx);
 3465        let multi_buffer_snapshot = multi_buffer.snapshot(cx);
 3466        let multi_buffer_visible_start = self
 3467            .scroll_manager
 3468            .anchor()
 3469            .anchor
 3470            .to_point(&multi_buffer_snapshot);
 3471        let multi_buffer_visible_end = multi_buffer_snapshot.clip_point(
 3472            multi_buffer_visible_start
 3473                + Point::new(self.visible_line_count().unwrap_or(0.).ceil() as u32, 0),
 3474            Bias::Left,
 3475        );
 3476        let multi_buffer_visible_range = multi_buffer_visible_start..multi_buffer_visible_end;
 3477        multi_buffer
 3478            .range_to_buffer_ranges(multi_buffer_visible_range, cx)
 3479            .into_iter()
 3480            .filter(|(_, excerpt_visible_range, _)| !excerpt_visible_range.is_empty())
 3481            .filter_map(|(buffer_handle, excerpt_visible_range, excerpt_id)| {
 3482                let buffer = buffer_handle.read(cx);
 3483                let language = buffer.language()?;
 3484                if let Some(restrict_to_languages) = restrict_to_languages {
 3485                    if !restrict_to_languages.contains(language) {
 3486                        return None;
 3487                    }
 3488                }
 3489                Some((
 3490                    excerpt_id,
 3491                    (
 3492                        buffer_handle,
 3493                        buffer.version().clone(),
 3494                        excerpt_visible_range,
 3495                    ),
 3496                ))
 3497            })
 3498            .collect()
 3499    }
 3500
 3501    pub fn text_layout_details(&self, cx: &WindowContext) -> TextLayoutDetails {
 3502        TextLayoutDetails {
 3503            text_system: cx.text_system().clone(),
 3504            editor_style: self.style.clone().unwrap(),
 3505            rem_size: cx.rem_size(),
 3506        }
 3507    }
 3508
 3509    fn splice_inlay_hints(
 3510        &self,
 3511        to_remove: Vec<InlayId>,
 3512        to_insert: Vec<Inlay>,
 3513        cx: &mut ViewContext<Self>,
 3514    ) {
 3515        self.display_map.update(cx, |display_map, cx| {
 3516            display_map.splice_inlays(to_remove, to_insert, cx);
 3517        });
 3518        cx.notify();
 3519    }
 3520
 3521    fn trigger_on_type_formatting(
 3522        &self,
 3523        input: String,
 3524        cx: &mut ViewContext<Self>,
 3525    ) -> Option<Task<Result<()>>> {
 3526        if input.len() != 1 {
 3527            return None;
 3528        }
 3529
 3530        let project = self.project.as_ref()?;
 3531        let position = self.selections.newest_anchor().head();
 3532        let (buffer, buffer_position) = self
 3533            .buffer
 3534            .read(cx)
 3535            .text_anchor_for_position(position.clone(), cx)?;
 3536
 3537        // OnTypeFormatting returns a list of edits, no need to pass them between Zed instances,
 3538        // hence we do LSP request & edit on host side only — add formats to host's history.
 3539        let push_to_lsp_host_history = true;
 3540        // If this is not the host, append its history with new edits.
 3541        let push_to_client_history = project.read(cx).is_remote();
 3542
 3543        let on_type_formatting = project.update(cx, |project, cx| {
 3544            project.on_type_format(
 3545                buffer.clone(),
 3546                buffer_position,
 3547                input,
 3548                push_to_lsp_host_history,
 3549                cx,
 3550            )
 3551        });
 3552        Some(cx.spawn(|editor, mut cx| async move {
 3553            if let Some(transaction) = on_type_formatting.await? {
 3554                if push_to_client_history {
 3555                    buffer.update(&mut cx, |buffer, _| {
 3556                        buffer.push_transaction(transaction, Instant::now());
 3557                    });
 3558                }
 3559                editor.update(&mut cx, |editor, cx| {
 3560                    editor.refresh_document_highlights(cx);
 3561                })?;
 3562            }
 3563            Ok(())
 3564        }))
 3565    }
 3566
 3567    fn show_completions(&mut self, _: &ShowCompletions, cx: &mut ViewContext<Self>) {
 3568        if self.pending_rename.is_some() {
 3569            return;
 3570        }
 3571
 3572        let project = if let Some(project) = self.project.clone() {
 3573            project
 3574        } else {
 3575            return;
 3576        };
 3577
 3578        let position = self.selections.newest_anchor().head();
 3579        let (buffer, buffer_position) = if let Some(output) = self
 3580            .buffer
 3581            .read(cx)
 3582            .text_anchor_for_position(position.clone(), cx)
 3583        {
 3584            output
 3585        } else {
 3586            return;
 3587        };
 3588
 3589        let query = Self::completion_query(&self.buffer.read(cx).read(cx), position.clone());
 3590        let completions = project.update(cx, |project, cx| {
 3591            project.completions(&buffer, buffer_position, cx)
 3592        });
 3593
 3594        let id = post_inc(&mut self.next_completion_id);
 3595        let task = cx.spawn(|this, mut cx| {
 3596            async move {
 3597                let menu = if let Some(completions) = completions.await.log_err() {
 3598                    let mut menu = CompletionsMenu {
 3599                        id,
 3600                        initial_position: position,
 3601                        match_candidates: completions
 3602                            .iter()
 3603                            .enumerate()
 3604                            .map(|(id, completion)| {
 3605                                StringMatchCandidate::new(
 3606                                    id,
 3607                                    completion.label.text[completion.label.filter_range.clone()]
 3608                                        .into(),
 3609                                )
 3610                            })
 3611                            .collect(),
 3612                        buffer,
 3613                        completions: Arc::new(RwLock::new(completions.into())),
 3614                        matches: Vec::new().into(),
 3615                        selected_item: 0,
 3616                        scroll_handle: UniformListScrollHandle::new(),
 3617                    };
 3618                    menu.filter(query.as_deref(), cx.background_executor().clone())
 3619                        .await;
 3620                    if menu.matches.is_empty() {
 3621                        None
 3622                    } else {
 3623                        _ = this.update(&mut cx, |editor, cx| {
 3624                            menu.pre_resolve_completion_documentation(editor.project.clone(), cx);
 3625                        });
 3626                        Some(menu)
 3627                    }
 3628                } else {
 3629                    None
 3630                };
 3631
 3632                this.update(&mut cx, |this, cx| {
 3633                    this.completion_tasks.retain(|(task_id, _)| *task_id > id);
 3634
 3635                    let mut context_menu = this.context_menu.write();
 3636                    match context_menu.as_ref() {
 3637                        None => {}
 3638
 3639                        Some(ContextMenu::Completions(prev_menu)) => {
 3640                            if prev_menu.id > id {
 3641                                return;
 3642                            }
 3643                        }
 3644
 3645                        _ => return,
 3646                    }
 3647
 3648                    if this.focus_handle.is_focused(cx) && menu.is_some() {
 3649                        let menu = menu.unwrap();
 3650                        *context_menu = Some(ContextMenu::Completions(menu));
 3651                        drop(context_menu);
 3652                        this.discard_copilot_suggestion(cx);
 3653                        cx.notify();
 3654                    } else if this.completion_tasks.is_empty() {
 3655                        // If there are no more completion tasks and the last menu was
 3656                        // empty, we should hide it. If it was already hidden, we should
 3657                        // also show the copilot suggestion when available.
 3658                        drop(context_menu);
 3659                        if this.hide_context_menu(cx).is_none() {
 3660                            this.update_visible_copilot_suggestion(cx);
 3661                        }
 3662                    }
 3663                })?;
 3664
 3665                Ok::<_, anyhow::Error>(())
 3666            }
 3667            .log_err()
 3668        });
 3669        self.completion_tasks.push((id, task));
 3670    }
 3671
 3672    //     pub fn confirm_completion(
 3673    //         &mut self,
 3674    //         action: &ConfirmCompletion,
 3675    //         cx: &mut ViewContext<Self>,
 3676    //     ) -> Option<Task<Result<()>>> {
 3677    //         use language::ToOffset as _;
 3678
 3679    //         let completions_menu = if let ContextMenu::Completions(menu) = self.hide_context_menu(cx)? {
 3680    //             menu
 3681    //         } else {
 3682    //             return None;
 3683    //         };
 3684
 3685    //         let mat = completions_menu
 3686    //             .matches
 3687    //             .get(action.item_ix.unwrap_or(completions_menu.selected_item))?;
 3688    //         let buffer_handle = completions_menu.buffer;
 3689    //         let completions = completions_menu.completions.read();
 3690    //         let completion = completions.get(mat.candidate_id)?;
 3691
 3692    //         let snippet;
 3693    //         let text;
 3694    //         if completion.is_snippet() {
 3695    //             snippet = Some(Snippet::parse(&completion.new_text).log_err()?);
 3696    //             text = snippet.as_ref().unwrap().text.clone();
 3697    //         } else {
 3698    //             snippet = None;
 3699    //             text = completion.new_text.clone();
 3700    //         };
 3701    //         let selections = self.selections.all::<usize>(cx);
 3702    //         let buffer = buffer_handle.read(cx);
 3703    //         let old_range = completion.old_range.to_offset(buffer);
 3704    //         let old_text = buffer.text_for_range(old_range.clone()).collect::<String>();
 3705
 3706    //         let newest_selection = self.selections.newest_anchor();
 3707    //         if newest_selection.start.buffer_id != Some(buffer_handle.read(cx).remote_id()) {
 3708    //             return None;
 3709    //         }
 3710
 3711    //         let lookbehind = newest_selection
 3712    //             .start
 3713    //             .text_anchor
 3714    //             .to_offset(buffer)
 3715    //             .saturating_sub(old_range.start);
 3716    //         let lookahead = old_range
 3717    //             .end
 3718    //             .saturating_sub(newest_selection.end.text_anchor.to_offset(buffer));
 3719    //         let mut common_prefix_len = old_text
 3720    //             .bytes()
 3721    //             .zip(text.bytes())
 3722    //             .take_while(|(a, b)| a == b)
 3723    //             .count();
 3724
 3725    //         let snapshot = self.buffer.read(cx).snapshot(cx);
 3726    //         let mut range_to_replace: Option<Range<isize>> = None;
 3727    //         let mut ranges = Vec::new();
 3728    //         for selection in &selections {
 3729    //             if snapshot.contains_str_at(selection.start.saturating_sub(lookbehind), &old_text) {
 3730    //                 let start = selection.start.saturating_sub(lookbehind);
 3731    //                 let end = selection.end + lookahead;
 3732    //                 if selection.id == newest_selection.id {
 3733    //                     range_to_replace = Some(
 3734    //                         ((start + common_prefix_len) as isize - selection.start as isize)
 3735    //                             ..(end as isize - selection.start as isize),
 3736    //                     );
 3737    //                 }
 3738    //                 ranges.push(start + common_prefix_len..end);
 3739    //             } else {
 3740    //                 common_prefix_len = 0;
 3741    //                 ranges.clear();
 3742    //                 ranges.extend(selections.iter().map(|s| {
 3743    //                     if s.id == newest_selection.id {
 3744    //                         range_to_replace = Some(
 3745    //                             old_range.start.to_offset_utf16(&snapshot).0 as isize
 3746    //                                 - selection.start as isize
 3747    //                                 ..old_range.end.to_offset_utf16(&snapshot).0 as isize
 3748    //                                     - selection.start as isize,
 3749    //                         );
 3750    //                         old_range.clone()
 3751    //                     } else {
 3752    //                         s.start..s.end
 3753    //                     }
 3754    //                 }));
 3755    //                 break;
 3756    //             }
 3757    //         }
 3758    //         let text = &text[common_prefix_len..];
 3759
 3760    //         cx.emit(Event::InputHandled {
 3761    //             utf16_range_to_replace: range_to_replace,
 3762    //             text: text.into(),
 3763    //         });
 3764
 3765    //         self.transact(cx, |this, cx| {
 3766    //             if let Some(mut snippet) = snippet {
 3767    //                 snippet.text = text.to_string();
 3768    //                 for tabstop in snippet.tabstops.iter_mut().flatten() {
 3769    //                     tabstop.start -= common_prefix_len as isize;
 3770    //                     tabstop.end -= common_prefix_len as isize;
 3771    //                 }
 3772
 3773    //                 this.insert_snippet(&ranges, snippet, cx).log_err();
 3774    //             } else {
 3775    //                 this.buffer.update(cx, |buffer, cx| {
 3776    //                     buffer.edit(
 3777    //                         ranges.iter().map(|range| (range.clone(), text)),
 3778    //                         this.autoindent_mode.clone(),
 3779    //                         cx,
 3780    //                     );
 3781    //                 });
 3782    //             }
 3783
 3784    //             this.refresh_copilot_suggestions(true, cx);
 3785    //         });
 3786
 3787    //         let project = self.project.clone()?;
 3788    //         let apply_edits = project.update(cx, |project, cx| {
 3789    //             project.apply_additional_edits_for_completion(
 3790    //                 buffer_handle,
 3791    //                 completion.clone(),
 3792    //                 true,
 3793    //                 cx,
 3794    //             )
 3795    //         });
 3796    //         Some(cx.foreground().spawn(async move {
 3797    //             apply_edits.await?;
 3798    //             Ok(())
 3799    //         }))
 3800    //     }
 3801
 3802    pub fn toggle_code_actions(&mut self, action: &ToggleCodeActions, cx: &mut ViewContext<Self>) {
 3803        let mut context_menu = self.context_menu.write();
 3804        if matches!(context_menu.as_ref(), Some(ContextMenu::CodeActions(_))) {
 3805            *context_menu = None;
 3806            cx.notify();
 3807            return;
 3808        }
 3809        drop(context_menu);
 3810
 3811        let deployed_from_indicator = action.deployed_from_indicator;
 3812        let mut task = self.code_actions_task.take();
 3813        cx.spawn(|this, mut cx| async move {
 3814            while let Some(prev_task) = task {
 3815                prev_task.await;
 3816                task = this.update(&mut cx, |this, _| this.code_actions_task.take())?;
 3817            }
 3818
 3819            this.update(&mut cx, |this, cx| {
 3820                if this.focus_handle.is_focused(cx) {
 3821                    if let Some((buffer, actions)) = this.available_code_actions.clone() {
 3822                        this.completion_tasks.clear();
 3823                        this.discard_copilot_suggestion(cx);
 3824                        *this.context_menu.write() =
 3825                            Some(ContextMenu::CodeActions(CodeActionsMenu {
 3826                                buffer,
 3827                                actions,
 3828                                selected_item: Default::default(),
 3829                                scroll_handle: UniformListScrollHandle::default(),
 3830                                deployed_from_indicator,
 3831                            }));
 3832                        cx.notify();
 3833                    }
 3834                }
 3835            })?;
 3836
 3837            Ok::<_, anyhow::Error>(())
 3838        })
 3839        .detach_and_log_err(cx);
 3840    }
 3841
 3842    pub fn confirm_code_action(
 3843        &mut self,
 3844        action: &ConfirmCodeAction,
 3845        cx: &mut ViewContext<Self>,
 3846    ) -> Option<Task<Result<()>>> {
 3847        let actions_menu = if let ContextMenu::CodeActions(menu) = self.hide_context_menu(cx)? {
 3848            menu
 3849        } else {
 3850            return None;
 3851        };
 3852        let action_ix = action.item_ix.unwrap_or(actions_menu.selected_item);
 3853        let action = actions_menu.actions.get(action_ix)?.clone();
 3854        let title = action.lsp_action.title.clone();
 3855        let buffer = actions_menu.buffer;
 3856        let workspace = self.workspace()?;
 3857
 3858        let apply_code_actions = workspace
 3859            .read(cx)
 3860            .project()
 3861            .clone()
 3862            .update(cx, |project, cx| {
 3863                project.apply_code_action(buffer, action, true, cx)
 3864            });
 3865        let workspace = workspace.downgrade();
 3866        Some(cx.spawn(|editor, cx| async move {
 3867            let project_transaction = apply_code_actions.await?;
 3868            Self::open_project_transaction(&editor, workspace, project_transaction, title, cx).await
 3869        }))
 3870    }
 3871
 3872    async fn open_project_transaction(
 3873        this: &WeakView<Editor>,
 3874        workspace: WeakView<Workspace>,
 3875        transaction: ProjectTransaction,
 3876        title: String,
 3877        mut cx: AsyncWindowContext,
 3878    ) -> Result<()> {
 3879        let replica_id = this.update(&mut cx, |this, cx| this.replica_id(cx))?;
 3880
 3881        let mut entries = transaction.0.into_iter().collect::<Vec<_>>();
 3882        cx.update(|_, cx| {
 3883            entries.sort_unstable_by_key(|(buffer, _)| {
 3884                buffer.read(cx).file().map(|f| f.path().clone())
 3885            });
 3886        })?;
 3887
 3888        // If the project transaction's edits are all contained within this editor, then
 3889        // avoid opening a new editor to display them.
 3890
 3891        if let Some((buffer, transaction)) = entries.first() {
 3892            if entries.len() == 1 {
 3893                let excerpt = this.update(&mut cx, |editor, cx| {
 3894                    editor
 3895                        .buffer()
 3896                        .read(cx)
 3897                        .excerpt_containing(editor.selections.newest_anchor().head(), cx)
 3898                })?;
 3899                if let Some((_, excerpted_buffer, excerpt_range)) = excerpt {
 3900                    if excerpted_buffer == *buffer {
 3901                        let all_edits_within_excerpt = buffer.read_with(&cx, |buffer, _| {
 3902                            let excerpt_range = excerpt_range.to_offset(buffer);
 3903                            buffer
 3904                                .edited_ranges_for_transaction::<usize>(transaction)
 3905                                .all(|range| {
 3906                                    excerpt_range.start <= range.start
 3907                                        && excerpt_range.end >= range.end
 3908                                })
 3909                        })?;
 3910
 3911                        if all_edits_within_excerpt {
 3912                            return Ok(());
 3913                        }
 3914                    }
 3915                }
 3916            }
 3917        } else {
 3918            return Ok(());
 3919        }
 3920
 3921        let mut ranges_to_highlight = Vec::new();
 3922        let excerpt_buffer = cx.build_model(|cx| {
 3923            let mut multibuffer = MultiBuffer::new(replica_id).with_title(title);
 3924            for (buffer_handle, transaction) in &entries {
 3925                let buffer = buffer_handle.read(cx);
 3926                ranges_to_highlight.extend(
 3927                    multibuffer.push_excerpts_with_context_lines(
 3928                        buffer_handle.clone(),
 3929                        buffer
 3930                            .edited_ranges_for_transaction::<usize>(transaction)
 3931                            .collect(),
 3932                        1,
 3933                        cx,
 3934                    ),
 3935                );
 3936            }
 3937            multibuffer.push_transaction(entries.iter().map(|(b, t)| (b, t)), cx);
 3938            multibuffer
 3939        })?;
 3940
 3941        workspace.update(&mut cx, |workspace, cx| {
 3942            let project = workspace.project().clone();
 3943            let editor =
 3944                cx.build_view(|cx| Editor::for_multibuffer(excerpt_buffer, Some(project), cx));
 3945            workspace.add_item(Box::new(editor.clone()), cx);
 3946            editor.update(cx, |editor, cx| {
 3947                editor.highlight_background::<Self>(
 3948                    ranges_to_highlight,
 3949                    |theme| theme.editor_highlighted_line_background,
 3950                    cx,
 3951                );
 3952            });
 3953        })?;
 3954
 3955        Ok(())
 3956    }
 3957
 3958    fn refresh_code_actions(&mut self, cx: &mut ViewContext<Self>) -> Option<()> {
 3959        let project = self.project.clone()?;
 3960        let buffer = self.buffer.read(cx);
 3961        let newest_selection = self.selections.newest_anchor().clone();
 3962        let (start_buffer, start) = buffer.text_anchor_for_position(newest_selection.start, cx)?;
 3963        let (end_buffer, end) = buffer.text_anchor_for_position(newest_selection.end, cx)?;
 3964        if start_buffer != end_buffer {
 3965            return None;
 3966        }
 3967
 3968        self.code_actions_task = Some(cx.spawn(|this, mut cx| async move {
 3969            cx.background_executor()
 3970                .timer(CODE_ACTIONS_DEBOUNCE_TIMEOUT)
 3971                .await;
 3972
 3973            let actions = if let Ok(code_actions) = project.update(&mut cx, |project, cx| {
 3974                project.code_actions(&start_buffer, start..end, cx)
 3975            }) {
 3976                code_actions.await.log_err()
 3977            } else {
 3978                None
 3979            };
 3980
 3981            this.update(&mut cx, |this, cx| {
 3982                this.available_code_actions = actions.and_then(|actions| {
 3983                    if actions.is_empty() {
 3984                        None
 3985                    } else {
 3986                        Some((start_buffer, actions.into()))
 3987                    }
 3988                });
 3989                cx.notify();
 3990            })
 3991            .log_err();
 3992        }));
 3993        None
 3994    }
 3995
 3996    fn refresh_document_highlights(&mut self, cx: &mut ViewContext<Self>) -> Option<()> {
 3997        if self.pending_rename.is_some() {
 3998            return None;
 3999        }
 4000
 4001        let project = self.project.clone()?;
 4002        let buffer = self.buffer.read(cx);
 4003        let newest_selection = self.selections.newest_anchor().clone();
 4004        let cursor_position = newest_selection.head();
 4005        let (cursor_buffer, cursor_buffer_position) =
 4006            buffer.text_anchor_for_position(cursor_position.clone(), cx)?;
 4007        let (tail_buffer, _) = buffer.text_anchor_for_position(newest_selection.tail(), cx)?;
 4008        if cursor_buffer != tail_buffer {
 4009            return None;
 4010        }
 4011
 4012        self.document_highlights_task = Some(cx.spawn(|this, mut cx| async move {
 4013            cx.background_executor()
 4014                .timer(DOCUMENT_HIGHLIGHTS_DEBOUNCE_TIMEOUT)
 4015                .await;
 4016
 4017            let highlights = if let Some(highlights) = project
 4018                .update(&mut cx, |project, cx| {
 4019                    project.document_highlights(&cursor_buffer, cursor_buffer_position, cx)
 4020                })
 4021                .log_err()
 4022            {
 4023                highlights.await.log_err()
 4024            } else {
 4025                None
 4026            };
 4027
 4028            if let Some(highlights) = highlights {
 4029                this.update(&mut cx, |this, cx| {
 4030                    if this.pending_rename.is_some() {
 4031                        return;
 4032                    }
 4033
 4034                    let buffer_id = cursor_position.buffer_id;
 4035                    let buffer = this.buffer.read(cx);
 4036                    if !buffer
 4037                        .text_anchor_for_position(cursor_position, cx)
 4038                        .map_or(false, |(buffer, _)| buffer == cursor_buffer)
 4039                    {
 4040                        return;
 4041                    }
 4042
 4043                    let cursor_buffer_snapshot = cursor_buffer.read(cx);
 4044                    let mut write_ranges = Vec::new();
 4045                    let mut read_ranges = Vec::new();
 4046                    for highlight in highlights {
 4047                        for (excerpt_id, excerpt_range) in
 4048                            buffer.excerpts_for_buffer(&cursor_buffer, cx)
 4049                        {
 4050                            let start = highlight
 4051                                .range
 4052                                .start
 4053                                .max(&excerpt_range.context.start, cursor_buffer_snapshot);
 4054                            let end = highlight
 4055                                .range
 4056                                .end
 4057                                .min(&excerpt_range.context.end, cursor_buffer_snapshot);
 4058                            if start.cmp(&end, cursor_buffer_snapshot).is_ge() {
 4059                                continue;
 4060                            }
 4061
 4062                            let range = Anchor {
 4063                                buffer_id,
 4064                                excerpt_id: excerpt_id.clone(),
 4065                                text_anchor: start,
 4066                            }..Anchor {
 4067                                buffer_id,
 4068                                excerpt_id,
 4069                                text_anchor: end,
 4070                            };
 4071                            if highlight.kind == lsp::DocumentHighlightKind::WRITE {
 4072                                write_ranges.push(range);
 4073                            } else {
 4074                                read_ranges.push(range);
 4075                            }
 4076                        }
 4077                    }
 4078
 4079                    this.highlight_background::<DocumentHighlightRead>(
 4080                        read_ranges,
 4081                        |theme| theme.editor_document_highlight_read_background,
 4082                        cx,
 4083                    );
 4084                    this.highlight_background::<DocumentHighlightWrite>(
 4085                        write_ranges,
 4086                        |theme| theme.editor_document_highlight_write_background,
 4087                        cx,
 4088                    );
 4089                    cx.notify();
 4090                })
 4091                .log_err();
 4092            }
 4093        }));
 4094        None
 4095    }
 4096
 4097    fn refresh_copilot_suggestions(
 4098        &mut self,
 4099        debounce: bool,
 4100        cx: &mut ViewContext<Self>,
 4101    ) -> Option<()> {
 4102        let copilot = Copilot::global(cx)?;
 4103        if self.mode != EditorMode::Full || !copilot.read(cx).status().is_authorized() {
 4104            self.clear_copilot_suggestions(cx);
 4105            return None;
 4106        }
 4107        self.update_visible_copilot_suggestion(cx);
 4108
 4109        let snapshot = self.buffer.read(cx).snapshot(cx);
 4110        let cursor = self.selections.newest_anchor().head();
 4111        if !self.is_copilot_enabled_at(cursor, &snapshot, cx) {
 4112            self.clear_copilot_suggestions(cx);
 4113            return None;
 4114        }
 4115
 4116        let (buffer, buffer_position) =
 4117            self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
 4118        self.copilot_state.pending_refresh = cx.spawn(|this, mut cx| async move {
 4119            if debounce {
 4120                cx.background_executor()
 4121                    .timer(COPILOT_DEBOUNCE_TIMEOUT)
 4122                    .await;
 4123            }
 4124
 4125            let completions = copilot
 4126                .update(&mut cx, |copilot, cx| {
 4127                    copilot.completions(&buffer, buffer_position, cx)
 4128                })
 4129                .log_err()
 4130                .unwrap_or(Task::ready(Ok(Vec::new())))
 4131                .await
 4132                .log_err()
 4133                .into_iter()
 4134                .flatten()
 4135                .collect_vec();
 4136
 4137            this.update(&mut cx, |this, cx| {
 4138                if !completions.is_empty() {
 4139                    this.copilot_state.cycled = false;
 4140                    this.copilot_state.pending_cycling_refresh = Task::ready(None);
 4141                    this.copilot_state.completions.clear();
 4142                    this.copilot_state.active_completion_index = 0;
 4143                    this.copilot_state.excerpt_id = Some(cursor.excerpt_id);
 4144                    for completion in completions {
 4145                        this.copilot_state.push_completion(completion);
 4146                    }
 4147                    this.update_visible_copilot_suggestion(cx);
 4148                }
 4149            })
 4150            .log_err()?;
 4151            Some(())
 4152        });
 4153
 4154        Some(())
 4155    }
 4156
 4157    fn cycle_copilot_suggestions(
 4158        &mut self,
 4159        direction: Direction,
 4160        cx: &mut ViewContext<Self>,
 4161    ) -> Option<()> {
 4162        let copilot = Copilot::global(cx)?;
 4163        if self.mode != EditorMode::Full || !copilot.read(cx).status().is_authorized() {
 4164            return None;
 4165        }
 4166
 4167        if self.copilot_state.cycled {
 4168            self.copilot_state.cycle_completions(direction);
 4169            self.update_visible_copilot_suggestion(cx);
 4170        } else {
 4171            let cursor = self.selections.newest_anchor().head();
 4172            let (buffer, buffer_position) =
 4173                self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
 4174            self.copilot_state.pending_cycling_refresh = cx.spawn(|this, mut cx| async move {
 4175                let completions = copilot
 4176                    .update(&mut cx, |copilot, cx| {
 4177                        copilot.completions_cycling(&buffer, buffer_position, cx)
 4178                    })
 4179                    .log_err()?
 4180                    .await;
 4181
 4182                this.update(&mut cx, |this, cx| {
 4183                    this.copilot_state.cycled = true;
 4184                    for completion in completions.log_err().into_iter().flatten() {
 4185                        this.copilot_state.push_completion(completion);
 4186                    }
 4187                    this.copilot_state.cycle_completions(direction);
 4188                    this.update_visible_copilot_suggestion(cx);
 4189                })
 4190                .log_err()?;
 4191
 4192                Some(())
 4193            });
 4194        }
 4195
 4196        Some(())
 4197    }
 4198
 4199    fn copilot_suggest(&mut self, _: &copilot::Suggest, cx: &mut ViewContext<Self>) {
 4200        if !self.has_active_copilot_suggestion(cx) {
 4201            self.refresh_copilot_suggestions(false, cx);
 4202            return;
 4203        }
 4204
 4205        self.update_visible_copilot_suggestion(cx);
 4206    }
 4207
 4208    fn next_copilot_suggestion(&mut self, _: &copilot::NextSuggestion, cx: &mut ViewContext<Self>) {
 4209        if self.has_active_copilot_suggestion(cx) {
 4210            self.cycle_copilot_suggestions(Direction::Next, cx);
 4211        } else {
 4212            let is_copilot_disabled = self.refresh_copilot_suggestions(false, cx).is_none();
 4213            if is_copilot_disabled {
 4214                cx.propagate();
 4215            }
 4216        }
 4217    }
 4218
 4219    fn previous_copilot_suggestion(
 4220        &mut self,
 4221        _: &copilot::PreviousSuggestion,
 4222        cx: &mut ViewContext<Self>,
 4223    ) {
 4224        if self.has_active_copilot_suggestion(cx) {
 4225            self.cycle_copilot_suggestions(Direction::Prev, cx);
 4226        } else {
 4227            let is_copilot_disabled = self.refresh_copilot_suggestions(false, cx).is_none();
 4228            if is_copilot_disabled {
 4229                cx.propagate();
 4230            }
 4231        }
 4232    }
 4233
 4234    fn accept_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) -> bool {
 4235        if let Some(suggestion) = self.take_active_copilot_suggestion(cx) {
 4236            if let Some((copilot, completion)) =
 4237                Copilot::global(cx).zip(self.copilot_state.active_completion())
 4238            {
 4239                copilot
 4240                    .update(cx, |copilot, cx| copilot.accept_completion(completion, cx))
 4241                    .detach_and_log_err(cx);
 4242
 4243                self.report_copilot_event(Some(completion.uuid.clone()), true, cx)
 4244            }
 4245            cx.emit(Event::InputHandled {
 4246                utf16_range_to_replace: None,
 4247                text: suggestion.text.to_string().into(),
 4248            });
 4249            self.insert_with_autoindent_mode(&suggestion.text.to_string(), None, cx);
 4250            cx.notify();
 4251            true
 4252        } else {
 4253            false
 4254        }
 4255    }
 4256
 4257    fn discard_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) -> bool {
 4258        if let Some(suggestion) = self.take_active_copilot_suggestion(cx) {
 4259            if let Some(copilot) = Copilot::global(cx) {
 4260                copilot
 4261                    .update(cx, |copilot, cx| {
 4262                        copilot.discard_completions(&self.copilot_state.completions, cx)
 4263                    })
 4264                    .detach_and_log_err(cx);
 4265
 4266                self.report_copilot_event(None, false, cx)
 4267            }
 4268
 4269            self.display_map.update(cx, |map, cx| {
 4270                map.splice_inlays(vec![suggestion.id], Vec::new(), cx)
 4271            });
 4272            cx.notify();
 4273            true
 4274        } else {
 4275            false
 4276        }
 4277    }
 4278
 4279    fn is_copilot_enabled_at(
 4280        &self,
 4281        location: Anchor,
 4282        snapshot: &MultiBufferSnapshot,
 4283        cx: &mut ViewContext<Self>,
 4284    ) -> bool {
 4285        let file = snapshot.file_at(location);
 4286        let language = snapshot.language_at(location);
 4287        let settings = all_language_settings(file, cx);
 4288        settings.copilot_enabled(language, file.map(|f| f.path().as_ref()))
 4289    }
 4290
 4291    fn has_active_copilot_suggestion(&self, cx: &AppContext) -> bool {
 4292        if let Some(suggestion) = self.copilot_state.suggestion.as_ref() {
 4293            let buffer = self.buffer.read(cx).read(cx);
 4294            suggestion.position.is_valid(&buffer)
 4295        } else {
 4296            false
 4297        }
 4298    }
 4299
 4300    fn take_active_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) -> Option<Inlay> {
 4301        let suggestion = self.copilot_state.suggestion.take()?;
 4302        self.display_map.update(cx, |map, cx| {
 4303            map.splice_inlays(vec![suggestion.id], Default::default(), cx);
 4304        });
 4305        let buffer = self.buffer.read(cx).read(cx);
 4306
 4307        if suggestion.position.is_valid(&buffer) {
 4308            Some(suggestion)
 4309        } else {
 4310            None
 4311        }
 4312    }
 4313
 4314    fn update_visible_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) {
 4315        let snapshot = self.buffer.read(cx).snapshot(cx);
 4316        let selection = self.selections.newest_anchor();
 4317        let cursor = selection.head();
 4318
 4319        if self.context_menu.read().is_some()
 4320            || !self.completion_tasks.is_empty()
 4321            || selection.start != selection.end
 4322        {
 4323            self.discard_copilot_suggestion(cx);
 4324        } else if let Some(text) = self
 4325            .copilot_state
 4326            .text_for_active_completion(cursor, &snapshot)
 4327        {
 4328            let text = Rope::from(text);
 4329            let mut to_remove = Vec::new();
 4330            if let Some(suggestion) = self.copilot_state.suggestion.take() {
 4331                to_remove.push(suggestion.id);
 4332            }
 4333
 4334            let suggestion_inlay =
 4335                Inlay::suggestion(post_inc(&mut self.next_inlay_id), cursor, text);
 4336            self.copilot_state.suggestion = Some(suggestion_inlay.clone());
 4337            self.display_map.update(cx, move |map, cx| {
 4338                map.splice_inlays(to_remove, vec![suggestion_inlay], cx)
 4339            });
 4340            cx.notify();
 4341        } else {
 4342            self.discard_copilot_suggestion(cx);
 4343        }
 4344    }
 4345
 4346    fn clear_copilot_suggestions(&mut self, cx: &mut ViewContext<Self>) {
 4347        self.copilot_state = Default::default();
 4348        self.discard_copilot_suggestion(cx);
 4349    }
 4350
 4351    pub fn render_code_actions_indicator(
 4352        &self,
 4353        style: &EditorStyle,
 4354        is_active: bool,
 4355        cx: &mut ViewContext<Self>,
 4356    ) -> Option<AnyElement<Self>> {
 4357        if self.available_code_actions.is_some() {
 4358            Some(
 4359                IconButton::new("code_actions_indicator", ui::Icon::Bolt)
 4360                    .on_click(|editor: &mut Editor, cx| {
 4361                        editor.toggle_code_actions(
 4362                            &ToggleCodeActions {
 4363                                deployed_from_indicator: true,
 4364                            },
 4365                            cx,
 4366                        );
 4367                    })
 4368                    .render(),
 4369            )
 4370        } else {
 4371            None
 4372        }
 4373    }
 4374
 4375    pub fn render_fold_indicators(
 4376        &self,
 4377        fold_data: Vec<Option<(FoldStatus, u32, bool)>>,
 4378        style: &EditorStyle,
 4379        gutter_hovered: bool,
 4380        line_height: Pixels,
 4381        gutter_margin: Pixels,
 4382        cx: &mut ViewContext<Self>,
 4383    ) -> Vec<Option<AnyElement<Self>>> {
 4384        fold_data
 4385            .iter()
 4386            .enumerate()
 4387            .map(|(ix, fold_data)| {
 4388                fold_data
 4389                    .map(|(fold_status, buffer_row, active)| {
 4390                        (active || gutter_hovered || fold_status == FoldStatus::Folded).then(|| {
 4391                            let icon = match fold_status {
 4392                                FoldStatus::Folded => ui::Icon::ChevronRight,
 4393                                FoldStatus::Foldable => ui::Icon::ChevronDown,
 4394                            };
 4395                            IconButton::new(ix as usize, icon)
 4396                                .on_click(move |editor: &mut Editor, cx| match fold_status {
 4397                                    FoldStatus::Folded => {
 4398                                        editor.unfold_at(&UnfoldAt { buffer_row }, cx);
 4399                                    }
 4400                                    FoldStatus::Foldable => {
 4401                                        editor.fold_at(&FoldAt { buffer_row }, cx);
 4402                                    }
 4403                                })
 4404                                .render()
 4405                        })
 4406                    })
 4407                    .flatten()
 4408            })
 4409            .collect()
 4410    }
 4411
 4412    pub fn context_menu_visible(&self) -> bool {
 4413        self.context_menu
 4414            .read()
 4415            .as_ref()
 4416            .map_or(false, |menu| menu.visible())
 4417    }
 4418
 4419    pub fn render_context_menu(
 4420        &self,
 4421        cursor_position: DisplayPoint,
 4422        style: &EditorStyle,
 4423        cx: &mut ViewContext<Editor>,
 4424    ) -> Option<(DisplayPoint, AnyElement<Editor>)> {
 4425        self.context_menu.read().as_ref().map(|menu| {
 4426            menu.render(
 4427                cursor_position,
 4428                style,
 4429                self.workspace.as_ref().map(|(w, _)| w.clone()),
 4430                cx,
 4431            )
 4432        })
 4433    }
 4434
 4435    fn hide_context_menu(&mut self, cx: &mut ViewContext<Self>) -> Option<ContextMenu> {
 4436        cx.notify();
 4437        self.completion_tasks.clear();
 4438        let context_menu = self.context_menu.write().take();
 4439        if context_menu.is_some() {
 4440            self.update_visible_copilot_suggestion(cx);
 4441        }
 4442        context_menu
 4443    }
 4444
 4445    pub fn insert_snippet(
 4446        &mut self,
 4447        insertion_ranges: &[Range<usize>],
 4448        snippet: Snippet,
 4449        cx: &mut ViewContext<Self>,
 4450    ) -> Result<()> {
 4451        let tabstops = self.buffer.update(cx, |buffer, cx| {
 4452            let snippet_text: Arc<str> = snippet.text.clone().into();
 4453            buffer.edit(
 4454                insertion_ranges
 4455                    .iter()
 4456                    .cloned()
 4457                    .map(|range| (range, snippet_text.clone())),
 4458                Some(AutoindentMode::EachLine),
 4459                cx,
 4460            );
 4461
 4462            let snapshot = &*buffer.read(cx);
 4463            let snippet = &snippet;
 4464            snippet
 4465                .tabstops
 4466                .iter()
 4467                .map(|tabstop| {
 4468                    let mut tabstop_ranges = tabstop
 4469                        .iter()
 4470                        .flat_map(|tabstop_range| {
 4471                            let mut delta = 0_isize;
 4472                            insertion_ranges.iter().map(move |insertion_range| {
 4473                                let insertion_start = insertion_range.start as isize + delta;
 4474                                delta +=
 4475                                    snippet.text.len() as isize - insertion_range.len() as isize;
 4476
 4477                                let start = snapshot.anchor_before(
 4478                                    (insertion_start + tabstop_range.start) as usize,
 4479                                );
 4480                                let end = snapshot
 4481                                    .anchor_after((insertion_start + tabstop_range.end) as usize);
 4482                                start..end
 4483                            })
 4484                        })
 4485                        .collect::<Vec<_>>();
 4486                    tabstop_ranges.sort_unstable_by(|a, b| a.start.cmp(&b.start, snapshot));
 4487                    tabstop_ranges
 4488                })
 4489                .collect::<Vec<_>>()
 4490        });
 4491
 4492        if let Some(tabstop) = tabstops.first() {
 4493            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 4494                s.select_ranges(tabstop.iter().cloned());
 4495            });
 4496            self.snippet_stack.push(SnippetState {
 4497                active_index: 0,
 4498                ranges: tabstops,
 4499            });
 4500        }
 4501
 4502        Ok(())
 4503    }
 4504
 4505    pub fn move_to_next_snippet_tabstop(&mut self, cx: &mut ViewContext<Self>) -> bool {
 4506        self.move_to_snippet_tabstop(Bias::Right, cx)
 4507    }
 4508
 4509    pub fn move_to_prev_snippet_tabstop(&mut self, cx: &mut ViewContext<Self>) -> bool {
 4510        self.move_to_snippet_tabstop(Bias::Left, cx)
 4511    }
 4512
 4513    pub fn move_to_snippet_tabstop(&mut self, bias: Bias, cx: &mut ViewContext<Self>) -> bool {
 4514        if let Some(mut snippet) = self.snippet_stack.pop() {
 4515            match bias {
 4516                Bias::Left => {
 4517                    if snippet.active_index > 0 {
 4518                        snippet.active_index -= 1;
 4519                    } else {
 4520                        self.snippet_stack.push(snippet);
 4521                        return false;
 4522                    }
 4523                }
 4524                Bias::Right => {
 4525                    if snippet.active_index + 1 < snippet.ranges.len() {
 4526                        snippet.active_index += 1;
 4527                    } else {
 4528                        self.snippet_stack.push(snippet);
 4529                        return false;
 4530                    }
 4531                }
 4532            }
 4533            if let Some(current_ranges) = snippet.ranges.get(snippet.active_index) {
 4534                self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 4535                    s.select_anchor_ranges(current_ranges.iter().cloned())
 4536                });
 4537                // If snippet state is not at the last tabstop, push it back on the stack
 4538                if snippet.active_index + 1 < snippet.ranges.len() {
 4539                    self.snippet_stack.push(snippet);
 4540                }
 4541                return true;
 4542            }
 4543        }
 4544
 4545        false
 4546    }
 4547
 4548    pub fn clear(&mut self, cx: &mut ViewContext<Self>) {
 4549        self.transact(cx, |this, cx| {
 4550            this.select_all(&SelectAll, cx);
 4551            this.insert("", cx);
 4552        });
 4553    }
 4554
 4555    pub fn backspace(&mut self, _: &Backspace, cx: &mut ViewContext<Self>) {
 4556        self.transact(cx, |this, cx| {
 4557            this.select_autoclose_pair(cx);
 4558            let mut selections = this.selections.all::<Point>(cx);
 4559            if !this.selections.line_mode {
 4560                let display_map = this.display_map.update(cx, |map, cx| map.snapshot(cx));
 4561                for selection in &mut selections {
 4562                    if selection.is_empty() {
 4563                        let old_head = selection.head();
 4564                        let mut new_head =
 4565                            movement::left(&display_map, old_head.to_display_point(&display_map))
 4566                                .to_point(&display_map);
 4567                        if let Some((buffer, line_buffer_range)) = display_map
 4568                            .buffer_snapshot
 4569                            .buffer_line_for_row(old_head.row)
 4570                        {
 4571                            let indent_size =
 4572                                buffer.indent_size_for_line(line_buffer_range.start.row);
 4573                            let indent_len = match indent_size.kind {
 4574                                IndentKind::Space => {
 4575                                    buffer.settings_at(line_buffer_range.start, cx).tab_size
 4576                                }
 4577                                IndentKind::Tab => NonZeroU32::new(1).unwrap(),
 4578                            };
 4579                            if old_head.column <= indent_size.len && old_head.column > 0 {
 4580                                let indent_len = indent_len.get();
 4581                                new_head = cmp::min(
 4582                                    new_head,
 4583                                    Point::new(
 4584                                        old_head.row,
 4585                                        ((old_head.column - 1) / indent_len) * indent_len,
 4586                                    ),
 4587                                );
 4588                            }
 4589                        }
 4590
 4591                        selection.set_head(new_head, SelectionGoal::None);
 4592                    }
 4593                }
 4594            }
 4595
 4596            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
 4597            this.insert("", cx);
 4598            this.refresh_copilot_suggestions(true, cx);
 4599        });
 4600    }
 4601
 4602    pub fn delete(&mut self, _: &Delete, cx: &mut ViewContext<Self>) {
 4603        self.transact(cx, |this, cx| {
 4604            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 4605                let line_mode = s.line_mode;
 4606                s.move_with(|map, selection| {
 4607                    if selection.is_empty() && !line_mode {
 4608                        let cursor = movement::right(map, selection.head());
 4609                        selection.end = cursor;
 4610                        selection.reversed = true;
 4611                        selection.goal = SelectionGoal::None;
 4612                    }
 4613                })
 4614            });
 4615            this.insert("", cx);
 4616            this.refresh_copilot_suggestions(true, cx);
 4617        });
 4618    }
 4619
 4620    pub fn tab_prev(&mut self, _: &TabPrev, cx: &mut ViewContext<Self>) {
 4621        if self.move_to_prev_snippet_tabstop(cx) {
 4622            return;
 4623        }
 4624
 4625        self.outdent(&Outdent, cx);
 4626    }
 4627
 4628    pub fn tab(&mut self, _: &Tab, cx: &mut ViewContext<Self>) {
 4629        if self.move_to_next_snippet_tabstop(cx) {
 4630            return;
 4631        }
 4632
 4633        let mut selections = self.selections.all_adjusted(cx);
 4634        let buffer = self.buffer.read(cx);
 4635        let snapshot = buffer.snapshot(cx);
 4636        let rows_iter = selections.iter().map(|s| s.head().row);
 4637        let suggested_indents = snapshot.suggested_indents(rows_iter, cx);
 4638
 4639        let mut edits = Vec::new();
 4640        let mut prev_edited_row = 0;
 4641        let mut row_delta = 0;
 4642        for selection in &mut selections {
 4643            if selection.start.row != prev_edited_row {
 4644                row_delta = 0;
 4645            }
 4646            prev_edited_row = selection.end.row;
 4647
 4648            // If the selection is non-empty, then increase the indentation of the selected lines.
 4649            if !selection.is_empty() {
 4650                row_delta =
 4651                    Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
 4652                continue;
 4653            }
 4654
 4655            // If the selection is empty and the cursor is in the leading whitespace before the
 4656            // suggested indentation, then auto-indent the line.
 4657            let cursor = selection.head();
 4658            let current_indent = snapshot.indent_size_for_line(cursor.row);
 4659            if let Some(suggested_indent) = suggested_indents.get(&cursor.row).copied() {
 4660                if cursor.column < suggested_indent.len
 4661                    && cursor.column <= current_indent.len
 4662                    && current_indent.len <= suggested_indent.len
 4663                {
 4664                    selection.start = Point::new(cursor.row, suggested_indent.len);
 4665                    selection.end = selection.start;
 4666                    if row_delta == 0 {
 4667                        edits.extend(Buffer::edit_for_indent_size_adjustment(
 4668                            cursor.row,
 4669                            current_indent,
 4670                            suggested_indent,
 4671                        ));
 4672                        row_delta = suggested_indent.len - current_indent.len;
 4673                    }
 4674                    continue;
 4675                }
 4676            }
 4677
 4678            // Accept copilot suggestion if there is only one selection and the cursor is not
 4679            // in the leading whitespace.
 4680            if self.selections.count() == 1
 4681                && cursor.column >= current_indent.len
 4682                && self.has_active_copilot_suggestion(cx)
 4683            {
 4684                self.accept_copilot_suggestion(cx);
 4685                return;
 4686            }
 4687
 4688            // Otherwise, insert a hard or soft tab.
 4689            let settings = buffer.settings_at(cursor, cx);
 4690            let tab_size = if settings.hard_tabs {
 4691                IndentSize::tab()
 4692            } else {
 4693                let tab_size = settings.tab_size.get();
 4694                let char_column = snapshot
 4695                    .text_for_range(Point::new(cursor.row, 0)..cursor)
 4696                    .flat_map(str::chars)
 4697                    .count()
 4698                    + row_delta as usize;
 4699                let chars_to_next_tab_stop = tab_size - (char_column as u32 % tab_size);
 4700                IndentSize::spaces(chars_to_next_tab_stop)
 4701            };
 4702            selection.start = Point::new(cursor.row, cursor.column + row_delta + tab_size.len);
 4703            selection.end = selection.start;
 4704            edits.push((cursor..cursor, tab_size.chars().collect::<String>()));
 4705            row_delta += tab_size.len;
 4706        }
 4707
 4708        self.transact(cx, |this, cx| {
 4709            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
 4710            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
 4711            this.refresh_copilot_suggestions(true, cx);
 4712        });
 4713    }
 4714
 4715    pub fn indent(&mut self, _: &Indent, cx: &mut ViewContext<Self>) {
 4716        let mut selections = self.selections.all::<Point>(cx);
 4717        let mut prev_edited_row = 0;
 4718        let mut row_delta = 0;
 4719        let mut edits = Vec::new();
 4720        let buffer = self.buffer.read(cx);
 4721        let snapshot = buffer.snapshot(cx);
 4722        for selection in &mut selections {
 4723            if selection.start.row != prev_edited_row {
 4724                row_delta = 0;
 4725            }
 4726            prev_edited_row = selection.end.row;
 4727
 4728            row_delta =
 4729                Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
 4730        }
 4731
 4732        self.transact(cx, |this, cx| {
 4733            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
 4734            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
 4735        });
 4736    }
 4737
 4738    fn indent_selection(
 4739        buffer: &MultiBuffer,
 4740        snapshot: &MultiBufferSnapshot,
 4741        selection: &mut Selection<Point>,
 4742        edits: &mut Vec<(Range<Point>, String)>,
 4743        delta_for_start_row: u32,
 4744        cx: &AppContext,
 4745    ) -> u32 {
 4746        let settings = buffer.settings_at(selection.start, cx);
 4747        let tab_size = settings.tab_size.get();
 4748        let indent_kind = if settings.hard_tabs {
 4749            IndentKind::Tab
 4750        } else {
 4751            IndentKind::Space
 4752        };
 4753        let mut start_row = selection.start.row;
 4754        let mut end_row = selection.end.row + 1;
 4755
 4756        // If a selection ends at the beginning of a line, don't indent
 4757        // that last line.
 4758        if selection.end.column == 0 {
 4759            end_row -= 1;
 4760        }
 4761
 4762        // Avoid re-indenting a row that has already been indented by a
 4763        // previous selection, but still update this selection's column
 4764        // to reflect that indentation.
 4765        if delta_for_start_row > 0 {
 4766            start_row += 1;
 4767            selection.start.column += delta_for_start_row;
 4768            if selection.end.row == selection.start.row {
 4769                selection.end.column += delta_for_start_row;
 4770            }
 4771        }
 4772
 4773        let mut delta_for_end_row = 0;
 4774        for row in start_row..end_row {
 4775            let current_indent = snapshot.indent_size_for_line(row);
 4776            let indent_delta = match (current_indent.kind, indent_kind) {
 4777                (IndentKind::Space, IndentKind::Space) => {
 4778                    let columns_to_next_tab_stop = tab_size - (current_indent.len % tab_size);
 4779                    IndentSize::spaces(columns_to_next_tab_stop)
 4780                }
 4781                (IndentKind::Tab, IndentKind::Space) => IndentSize::spaces(tab_size),
 4782                (_, IndentKind::Tab) => IndentSize::tab(),
 4783            };
 4784
 4785            let row_start = Point::new(row, 0);
 4786            edits.push((
 4787                row_start..row_start,
 4788                indent_delta.chars().collect::<String>(),
 4789            ));
 4790
 4791            // Update this selection's endpoints to reflect the indentation.
 4792            if row == selection.start.row {
 4793                selection.start.column += indent_delta.len;
 4794            }
 4795            if row == selection.end.row {
 4796                selection.end.column += indent_delta.len;
 4797                delta_for_end_row = indent_delta.len;
 4798            }
 4799        }
 4800
 4801        if selection.start.row == selection.end.row {
 4802            delta_for_start_row + delta_for_end_row
 4803        } else {
 4804            delta_for_end_row
 4805        }
 4806    }
 4807
 4808    pub fn outdent(&mut self, _: &Outdent, cx: &mut ViewContext<Self>) {
 4809        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 4810        let selections = self.selections.all::<Point>(cx);
 4811        let mut deletion_ranges = Vec::new();
 4812        let mut last_outdent = None;
 4813        {
 4814            let buffer = self.buffer.read(cx);
 4815            let snapshot = buffer.snapshot(cx);
 4816            for selection in &selections {
 4817                let settings = buffer.settings_at(selection.start, cx);
 4818                let tab_size = settings.tab_size.get();
 4819                let mut rows = selection.spanned_rows(false, &display_map);
 4820
 4821                // Avoid re-outdenting a row that has already been outdented by a
 4822                // previous selection.
 4823                if let Some(last_row) = last_outdent {
 4824                    if last_row == rows.start {
 4825                        rows.start += 1;
 4826                    }
 4827                }
 4828
 4829                for row in rows {
 4830                    let indent_size = snapshot.indent_size_for_line(row);
 4831                    if indent_size.len > 0 {
 4832                        let deletion_len = match indent_size.kind {
 4833                            IndentKind::Space => {
 4834                                let columns_to_prev_tab_stop = indent_size.len % tab_size;
 4835                                if columns_to_prev_tab_stop == 0 {
 4836                                    tab_size
 4837                                } else {
 4838                                    columns_to_prev_tab_stop
 4839                                }
 4840                            }
 4841                            IndentKind::Tab => 1,
 4842                        };
 4843                        deletion_ranges.push(Point::new(row, 0)..Point::new(row, deletion_len));
 4844                        last_outdent = Some(row);
 4845                    }
 4846                }
 4847            }
 4848        }
 4849
 4850        self.transact(cx, |this, cx| {
 4851            this.buffer.update(cx, |buffer, cx| {
 4852                let empty_str: Arc<str> = "".into();
 4853                buffer.edit(
 4854                    deletion_ranges
 4855                        .into_iter()
 4856                        .map(|range| (range, empty_str.clone())),
 4857                    None,
 4858                    cx,
 4859                );
 4860            });
 4861            let selections = this.selections.all::<usize>(cx);
 4862            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
 4863        });
 4864    }
 4865
 4866    pub fn delete_line(&mut self, _: &DeleteLine, cx: &mut ViewContext<Self>) {
 4867        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 4868        let selections = self.selections.all::<Point>(cx);
 4869
 4870        let mut new_cursors = Vec::new();
 4871        let mut edit_ranges = Vec::new();
 4872        let mut selections = selections.iter().peekable();
 4873        while let Some(selection) = selections.next() {
 4874            let mut rows = selection.spanned_rows(false, &display_map);
 4875            let goal_display_column = selection.head().to_display_point(&display_map).column();
 4876
 4877            // Accumulate contiguous regions of rows that we want to delete.
 4878            while let Some(next_selection) = selections.peek() {
 4879                let next_rows = next_selection.spanned_rows(false, &display_map);
 4880                if next_rows.start <= rows.end {
 4881                    rows.end = next_rows.end;
 4882                    selections.next().unwrap();
 4883                } else {
 4884                    break;
 4885                }
 4886            }
 4887
 4888            let buffer = &display_map.buffer_snapshot;
 4889            let mut edit_start = Point::new(rows.start, 0).to_offset(buffer);
 4890            let edit_end;
 4891            let cursor_buffer_row;
 4892            if buffer.max_point().row >= rows.end {
 4893                // If there's a line after the range, delete the \n from the end of the row range
 4894                // and position the cursor on the next line.
 4895                edit_end = Point::new(rows.end, 0).to_offset(buffer);
 4896                cursor_buffer_row = rows.end;
 4897            } else {
 4898                // If there isn't a line after the range, delete the \n from the line before the
 4899                // start of the row range and position the cursor there.
 4900                edit_start = edit_start.saturating_sub(1);
 4901                edit_end = buffer.len();
 4902                cursor_buffer_row = rows.start.saturating_sub(1);
 4903            }
 4904
 4905            let mut cursor = Point::new(cursor_buffer_row, 0).to_display_point(&display_map);
 4906            *cursor.column_mut() =
 4907                cmp::min(goal_display_column, display_map.line_len(cursor.row()));
 4908
 4909            new_cursors.push((
 4910                selection.id,
 4911                buffer.anchor_after(cursor.to_point(&display_map)),
 4912            ));
 4913            edit_ranges.push(edit_start..edit_end);
 4914        }
 4915
 4916        self.transact(cx, |this, cx| {
 4917            let buffer = this.buffer.update(cx, |buffer, cx| {
 4918                let empty_str: Arc<str> = "".into();
 4919                buffer.edit(
 4920                    edit_ranges
 4921                        .into_iter()
 4922                        .map(|range| (range, empty_str.clone())),
 4923                    None,
 4924                    cx,
 4925                );
 4926                buffer.snapshot(cx)
 4927            });
 4928            let new_selections = new_cursors
 4929                .into_iter()
 4930                .map(|(id, cursor)| {
 4931                    let cursor = cursor.to_point(&buffer);
 4932                    Selection {
 4933                        id,
 4934                        start: cursor,
 4935                        end: cursor,
 4936                        reversed: false,
 4937                        goal: SelectionGoal::None,
 4938                    }
 4939                })
 4940                .collect();
 4941
 4942            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 4943                s.select(new_selections);
 4944            });
 4945        });
 4946    }
 4947
 4948    pub fn join_lines(&mut self, _: &JoinLines, cx: &mut ViewContext<Self>) {
 4949        let mut row_ranges = Vec::<Range<u32>>::new();
 4950        for selection in self.selections.all::<Point>(cx) {
 4951            let start = selection.start.row;
 4952            let end = if selection.start.row == selection.end.row {
 4953                selection.start.row + 1
 4954            } else {
 4955                selection.end.row
 4956            };
 4957
 4958            if let Some(last_row_range) = row_ranges.last_mut() {
 4959                if start <= last_row_range.end {
 4960                    last_row_range.end = end;
 4961                    continue;
 4962                }
 4963            }
 4964            row_ranges.push(start..end);
 4965        }
 4966
 4967        let snapshot = self.buffer.read(cx).snapshot(cx);
 4968        let mut cursor_positions = Vec::new();
 4969        for row_range in &row_ranges {
 4970            let anchor = snapshot.anchor_before(Point::new(
 4971                row_range.end - 1,
 4972                snapshot.line_len(row_range.end - 1),
 4973            ));
 4974            cursor_positions.push(anchor.clone()..anchor);
 4975        }
 4976
 4977        self.transact(cx, |this, cx| {
 4978            for row_range in row_ranges.into_iter().rev() {
 4979                for row in row_range.rev() {
 4980                    let end_of_line = Point::new(row, snapshot.line_len(row));
 4981                    let indent = snapshot.indent_size_for_line(row + 1);
 4982                    let start_of_next_line = Point::new(row + 1, indent.len);
 4983
 4984                    let replace = if snapshot.line_len(row + 1) > indent.len {
 4985                        " "
 4986                    } else {
 4987                        ""
 4988                    };
 4989
 4990                    this.buffer.update(cx, |buffer, cx| {
 4991                        buffer.edit([(end_of_line..start_of_next_line, replace)], None, cx)
 4992                    });
 4993                }
 4994            }
 4995
 4996            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 4997                s.select_anchor_ranges(cursor_positions)
 4998            });
 4999        });
 5000    }
 5001
 5002    pub fn sort_lines_case_sensitive(
 5003        &mut self,
 5004        _: &SortLinesCaseSensitive,
 5005        cx: &mut ViewContext<Self>,
 5006    ) {
 5007        self.manipulate_lines(cx, |lines| lines.sort())
 5008    }
 5009
 5010    pub fn sort_lines_case_insensitive(
 5011        &mut self,
 5012        _: &SortLinesCaseInsensitive,
 5013        cx: &mut ViewContext<Self>,
 5014    ) {
 5015        self.manipulate_lines(cx, |lines| lines.sort_by_key(|line| line.to_lowercase()))
 5016    }
 5017
 5018    pub fn reverse_lines(&mut self, _: &ReverseLines, cx: &mut ViewContext<Self>) {
 5019        self.manipulate_lines(cx, |lines| lines.reverse())
 5020    }
 5021
 5022    pub fn shuffle_lines(&mut self, _: &ShuffleLines, cx: &mut ViewContext<Self>) {
 5023        self.manipulate_lines(cx, |lines| lines.shuffle(&mut thread_rng()))
 5024    }
 5025
 5026    fn manipulate_lines<Fn>(&mut self, cx: &mut ViewContext<Self>, mut callback: Fn)
 5027    where
 5028        Fn: FnMut(&mut [&str]),
 5029    {
 5030        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 5031        let buffer = self.buffer.read(cx).snapshot(cx);
 5032
 5033        let mut edits = Vec::new();
 5034
 5035        let selections = self.selections.all::<Point>(cx);
 5036        let mut selections = selections.iter().peekable();
 5037        let mut contiguous_row_selections = Vec::new();
 5038        let mut new_selections = Vec::new();
 5039
 5040        while let Some(selection) = selections.next() {
 5041            let (start_row, end_row) = consume_contiguous_rows(
 5042                &mut contiguous_row_selections,
 5043                selection,
 5044                &display_map,
 5045                &mut selections,
 5046            );
 5047
 5048            let start_point = Point::new(start_row, 0);
 5049            let end_point = Point::new(end_row - 1, buffer.line_len(end_row - 1));
 5050            let text = buffer
 5051                .text_for_range(start_point..end_point)
 5052                .collect::<String>();
 5053            let mut lines = text.split("\n").collect_vec();
 5054
 5055            let lines_len = lines.len();
 5056            callback(&mut lines);
 5057
 5058            // This is a current limitation with selections.
 5059            // If we wanted to support removing or adding lines, we'd need to fix the logic associated with selections.
 5060            debug_assert!(
 5061                lines.len() == lines_len,
 5062                "callback should not change the number of lines"
 5063            );
 5064
 5065            edits.push((start_point..end_point, lines.join("\n")));
 5066            let start_anchor = buffer.anchor_after(start_point);
 5067            let end_anchor = buffer.anchor_before(end_point);
 5068
 5069            // Make selection and push
 5070            new_selections.push(Selection {
 5071                id: selection.id,
 5072                start: start_anchor.to_offset(&buffer),
 5073                end: end_anchor.to_offset(&buffer),
 5074                goal: SelectionGoal::None,
 5075                reversed: selection.reversed,
 5076            });
 5077        }
 5078
 5079        self.transact(cx, |this, cx| {
 5080            this.buffer.update(cx, |buffer, cx| {
 5081                buffer.edit(edits, None, cx);
 5082            });
 5083
 5084            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5085                s.select(new_selections);
 5086            });
 5087
 5088            this.request_autoscroll(Autoscroll::fit(), cx);
 5089        });
 5090    }
 5091
 5092    pub fn convert_to_upper_case(&mut self, _: &ConvertToUpperCase, cx: &mut ViewContext<Self>) {
 5093        self.manipulate_text(cx, |text| text.to_uppercase())
 5094    }
 5095
 5096    pub fn convert_to_lower_case(&mut self, _: &ConvertToLowerCase, cx: &mut ViewContext<Self>) {
 5097        self.manipulate_text(cx, |text| text.to_lowercase())
 5098    }
 5099
 5100    pub fn convert_to_title_case(&mut self, _: &ConvertToTitleCase, cx: &mut ViewContext<Self>) {
 5101        self.manipulate_text(cx, |text| {
 5102            // Hack to get around the fact that to_case crate doesn't support '\n' as a word boundary
 5103            // https://github.com/rutrum/convert-case/issues/16
 5104            text.split("\n")
 5105                .map(|line| line.to_case(Case::Title))
 5106                .join("\n")
 5107        })
 5108    }
 5109
 5110    pub fn convert_to_snake_case(&mut self, _: &ConvertToSnakeCase, cx: &mut ViewContext<Self>) {
 5111        self.manipulate_text(cx, |text| text.to_case(Case::Snake))
 5112    }
 5113
 5114    pub fn convert_to_kebab_case(&mut self, _: &ConvertToKebabCase, cx: &mut ViewContext<Self>) {
 5115        self.manipulate_text(cx, |text| text.to_case(Case::Kebab))
 5116    }
 5117
 5118    pub fn convert_to_upper_camel_case(
 5119        &mut self,
 5120        _: &ConvertToUpperCamelCase,
 5121        cx: &mut ViewContext<Self>,
 5122    ) {
 5123        self.manipulate_text(cx, |text| {
 5124            // Hack to get around the fact that to_case crate doesn't support '\n' as a word boundary
 5125            // https://github.com/rutrum/convert-case/issues/16
 5126            text.split("\n")
 5127                .map(|line| line.to_case(Case::UpperCamel))
 5128                .join("\n")
 5129        })
 5130    }
 5131
 5132    pub fn convert_to_lower_camel_case(
 5133        &mut self,
 5134        _: &ConvertToLowerCamelCase,
 5135        cx: &mut ViewContext<Self>,
 5136    ) {
 5137        self.manipulate_text(cx, |text| text.to_case(Case::Camel))
 5138    }
 5139
 5140    fn manipulate_text<Fn>(&mut self, cx: &mut ViewContext<Self>, mut callback: Fn)
 5141    where
 5142        Fn: FnMut(&str) -> String,
 5143    {
 5144        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 5145        let buffer = self.buffer.read(cx).snapshot(cx);
 5146
 5147        let mut new_selections = Vec::new();
 5148        let mut edits = Vec::new();
 5149        let mut selection_adjustment = 0i32;
 5150
 5151        for selection in self.selections.all::<usize>(cx) {
 5152            let selection_is_empty = selection.is_empty();
 5153
 5154            let (start, end) = if selection_is_empty {
 5155                let word_range = movement::surrounding_word(
 5156                    &display_map,
 5157                    selection.start.to_display_point(&display_map),
 5158                );
 5159                let start = word_range.start.to_offset(&display_map, Bias::Left);
 5160                let end = word_range.end.to_offset(&display_map, Bias::Left);
 5161                (start, end)
 5162            } else {
 5163                (selection.start, selection.end)
 5164            };
 5165
 5166            let text = buffer.text_for_range(start..end).collect::<String>();
 5167            let old_length = text.len() as i32;
 5168            let text = callback(&text);
 5169
 5170            new_selections.push(Selection {
 5171                start: (start as i32 - selection_adjustment) as usize,
 5172                end: ((start + text.len()) as i32 - selection_adjustment) as usize,
 5173                goal: SelectionGoal::None,
 5174                ..selection
 5175            });
 5176
 5177            selection_adjustment += old_length - text.len() as i32;
 5178
 5179            edits.push((start..end, text));
 5180        }
 5181
 5182        self.transact(cx, |this, cx| {
 5183            this.buffer.update(cx, |buffer, cx| {
 5184                buffer.edit(edits, None, cx);
 5185            });
 5186
 5187            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5188                s.select(new_selections);
 5189            });
 5190
 5191            this.request_autoscroll(Autoscroll::fit(), cx);
 5192        });
 5193    }
 5194
 5195    pub fn duplicate_line(&mut self, _: &DuplicateLine, cx: &mut ViewContext<Self>) {
 5196        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 5197        let buffer = &display_map.buffer_snapshot;
 5198        let selections = self.selections.all::<Point>(cx);
 5199
 5200        let mut edits = Vec::new();
 5201        let mut selections_iter = selections.iter().peekable();
 5202        while let Some(selection) = selections_iter.next() {
 5203            // Avoid duplicating the same lines twice.
 5204            let mut rows = selection.spanned_rows(false, &display_map);
 5205
 5206            while let Some(next_selection) = selections_iter.peek() {
 5207                let next_rows = next_selection.spanned_rows(false, &display_map);
 5208                if next_rows.start < rows.end {
 5209                    rows.end = next_rows.end;
 5210                    selections_iter.next().unwrap();
 5211                } else {
 5212                    break;
 5213                }
 5214            }
 5215
 5216            // Copy the text from the selected row region and splice it at the start of the region.
 5217            let start = Point::new(rows.start, 0);
 5218            let end = Point::new(rows.end - 1, buffer.line_len(rows.end - 1));
 5219            let text = buffer
 5220                .text_for_range(start..end)
 5221                .chain(Some("\n"))
 5222                .collect::<String>();
 5223            edits.push((start..start, text));
 5224        }
 5225
 5226        self.transact(cx, |this, cx| {
 5227            this.buffer.update(cx, |buffer, cx| {
 5228                buffer.edit(edits, None, cx);
 5229            });
 5230
 5231            this.request_autoscroll(Autoscroll::fit(), cx);
 5232        });
 5233    }
 5234
 5235    pub fn move_line_up(&mut self, _: &MoveLineUp, cx: &mut ViewContext<Self>) {
 5236        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 5237        let buffer = self.buffer.read(cx).snapshot(cx);
 5238
 5239        let mut edits = Vec::new();
 5240        let mut unfold_ranges = Vec::new();
 5241        let mut refold_ranges = Vec::new();
 5242
 5243        let selections = self.selections.all::<Point>(cx);
 5244        let mut selections = selections.iter().peekable();
 5245        let mut contiguous_row_selections = Vec::new();
 5246        let mut new_selections = Vec::new();
 5247
 5248        while let Some(selection) = selections.next() {
 5249            // Find all the selections that span a contiguous row range
 5250            let (start_row, end_row) = consume_contiguous_rows(
 5251                &mut contiguous_row_selections,
 5252                selection,
 5253                &display_map,
 5254                &mut selections,
 5255            );
 5256
 5257            // Move the text spanned by the row range to be before the line preceding the row range
 5258            if start_row > 0 {
 5259                let range_to_move = Point::new(start_row - 1, buffer.line_len(start_row - 1))
 5260                    ..Point::new(end_row - 1, buffer.line_len(end_row - 1));
 5261                let insertion_point = display_map
 5262                    .prev_line_boundary(Point::new(start_row - 1, 0))
 5263                    .0;
 5264
 5265                // Don't move lines across excerpts
 5266                if buffer
 5267                    .excerpt_boundaries_in_range((
 5268                        Bound::Excluded(insertion_point),
 5269                        Bound::Included(range_to_move.end),
 5270                    ))
 5271                    .next()
 5272                    .is_none()
 5273                {
 5274                    let text = buffer
 5275                        .text_for_range(range_to_move.clone())
 5276                        .flat_map(|s| s.chars())
 5277                        .skip(1)
 5278                        .chain(['\n'])
 5279                        .collect::<String>();
 5280
 5281                    edits.push((
 5282                        buffer.anchor_after(range_to_move.start)
 5283                            ..buffer.anchor_before(range_to_move.end),
 5284                        String::new(),
 5285                    ));
 5286                    let insertion_anchor = buffer.anchor_after(insertion_point);
 5287                    edits.push((insertion_anchor..insertion_anchor, text));
 5288
 5289                    let row_delta = range_to_move.start.row - insertion_point.row + 1;
 5290
 5291                    // Move selections up
 5292                    new_selections.extend(contiguous_row_selections.drain(..).map(
 5293                        |mut selection| {
 5294                            selection.start.row -= row_delta;
 5295                            selection.end.row -= row_delta;
 5296                            selection
 5297                        },
 5298                    ));
 5299
 5300                    // Move folds up
 5301                    unfold_ranges.push(range_to_move.clone());
 5302                    for fold in display_map.folds_in_range(
 5303                        buffer.anchor_before(range_to_move.start)
 5304                            ..buffer.anchor_after(range_to_move.end),
 5305                    ) {
 5306                        let mut start = fold.range.start.to_point(&buffer);
 5307                        let mut end = fold.range.end.to_point(&buffer);
 5308                        start.row -= row_delta;
 5309                        end.row -= row_delta;
 5310                        refold_ranges.push(start..end);
 5311                    }
 5312                }
 5313            }
 5314
 5315            // If we didn't move line(s), preserve the existing selections
 5316            new_selections.append(&mut contiguous_row_selections);
 5317        }
 5318
 5319        self.transact(cx, |this, cx| {
 5320            this.unfold_ranges(unfold_ranges, true, true, cx);
 5321            this.buffer.update(cx, |buffer, cx| {
 5322                for (range, text) in edits {
 5323                    buffer.edit([(range, text)], None, cx);
 5324                }
 5325            });
 5326            this.fold_ranges(refold_ranges, true, cx);
 5327            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5328                s.select(new_selections);
 5329            })
 5330        });
 5331    }
 5332
 5333    pub fn move_line_down(&mut self, _: &MoveLineDown, cx: &mut ViewContext<Self>) {
 5334        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 5335        let buffer = self.buffer.read(cx).snapshot(cx);
 5336
 5337        let mut edits = Vec::new();
 5338        let mut unfold_ranges = Vec::new();
 5339        let mut refold_ranges = Vec::new();
 5340
 5341        let selections = self.selections.all::<Point>(cx);
 5342        let mut selections = selections.iter().peekable();
 5343        let mut contiguous_row_selections = Vec::new();
 5344        let mut new_selections = Vec::new();
 5345
 5346        while let Some(selection) = selections.next() {
 5347            // Find all the selections that span a contiguous row range
 5348            let (start_row, end_row) = consume_contiguous_rows(
 5349                &mut contiguous_row_selections,
 5350                selection,
 5351                &display_map,
 5352                &mut selections,
 5353            );
 5354
 5355            // Move the text spanned by the row range to be after the last line of the row range
 5356            if end_row <= buffer.max_point().row {
 5357                let range_to_move = Point::new(start_row, 0)..Point::new(end_row, 0);
 5358                let insertion_point = display_map.next_line_boundary(Point::new(end_row, 0)).0;
 5359
 5360                // Don't move lines across excerpt boundaries
 5361                if buffer
 5362                    .excerpt_boundaries_in_range((
 5363                        Bound::Excluded(range_to_move.start),
 5364                        Bound::Included(insertion_point),
 5365                    ))
 5366                    .next()
 5367                    .is_none()
 5368                {
 5369                    let mut text = String::from("\n");
 5370                    text.extend(buffer.text_for_range(range_to_move.clone()));
 5371                    text.pop(); // Drop trailing newline
 5372                    edits.push((
 5373                        buffer.anchor_after(range_to_move.start)
 5374                            ..buffer.anchor_before(range_to_move.end),
 5375                        String::new(),
 5376                    ));
 5377                    let insertion_anchor = buffer.anchor_after(insertion_point);
 5378                    edits.push((insertion_anchor..insertion_anchor, text));
 5379
 5380                    let row_delta = insertion_point.row - range_to_move.end.row + 1;
 5381
 5382                    // Move selections down
 5383                    new_selections.extend(contiguous_row_selections.drain(..).map(
 5384                        |mut selection| {
 5385                            selection.start.row += row_delta;
 5386                            selection.end.row += row_delta;
 5387                            selection
 5388                        },
 5389                    ));
 5390
 5391                    // Move folds down
 5392                    unfold_ranges.push(range_to_move.clone());
 5393                    for fold in display_map.folds_in_range(
 5394                        buffer.anchor_before(range_to_move.start)
 5395                            ..buffer.anchor_after(range_to_move.end),
 5396                    ) {
 5397                        let mut start = fold.range.start.to_point(&buffer);
 5398                        let mut end = fold.range.end.to_point(&buffer);
 5399                        start.row += row_delta;
 5400                        end.row += row_delta;
 5401                        refold_ranges.push(start..end);
 5402                    }
 5403                }
 5404            }
 5405
 5406            // If we didn't move line(s), preserve the existing selections
 5407            new_selections.append(&mut contiguous_row_selections);
 5408        }
 5409
 5410        self.transact(cx, |this, cx| {
 5411            this.unfold_ranges(unfold_ranges, true, true, cx);
 5412            this.buffer.update(cx, |buffer, cx| {
 5413                for (range, text) in edits {
 5414                    buffer.edit([(range, text)], None, cx);
 5415                }
 5416            });
 5417            this.fold_ranges(refold_ranges, true, cx);
 5418            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(new_selections));
 5419        });
 5420    }
 5421
 5422    pub fn transpose(&mut self, _: &Transpose, cx: &mut ViewContext<Self>) {
 5423        let text_layout_details = &self.text_layout_details(cx);
 5424        self.transact(cx, |this, cx| {
 5425            let edits = this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5426                let mut edits: Vec<(Range<usize>, String)> = Default::default();
 5427                let line_mode = s.line_mode;
 5428                s.move_with(|display_map, selection| {
 5429                    if !selection.is_empty() || line_mode {
 5430                        return;
 5431                    }
 5432
 5433                    let mut head = selection.head();
 5434                    let mut transpose_offset = head.to_offset(display_map, Bias::Right);
 5435                    if head.column() == display_map.line_len(head.row()) {
 5436                        transpose_offset = display_map
 5437                            .buffer_snapshot
 5438                            .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
 5439                    }
 5440
 5441                    if transpose_offset == 0 {
 5442                        return;
 5443                    }
 5444
 5445                    *head.column_mut() += 1;
 5446                    head = display_map.clip_point(head, Bias::Right);
 5447                    let goal = SelectionGoal::HorizontalPosition(
 5448                        display_map.x_for_point(head, &text_layout_details).into(),
 5449                    );
 5450                    selection.collapse_to(head, goal);
 5451
 5452                    let transpose_start = display_map
 5453                        .buffer_snapshot
 5454                        .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
 5455                    if edits.last().map_or(true, |e| e.0.end <= transpose_start) {
 5456                        let transpose_end = display_map
 5457                            .buffer_snapshot
 5458                            .clip_offset(transpose_offset + 1, Bias::Right);
 5459                        if let Some(ch) =
 5460                            display_map.buffer_snapshot.chars_at(transpose_start).next()
 5461                        {
 5462                            edits.push((transpose_start..transpose_offset, String::new()));
 5463                            edits.push((transpose_end..transpose_end, ch.to_string()));
 5464                        }
 5465                    }
 5466                });
 5467                edits
 5468            });
 5469            this.buffer
 5470                .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
 5471            let selections = this.selections.all::<usize>(cx);
 5472            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5473                s.select(selections);
 5474            });
 5475        });
 5476    }
 5477
 5478    pub fn cut(&mut self, _: &Cut, cx: &mut ViewContext<Self>) {
 5479        let mut text = String::new();
 5480        let buffer = self.buffer.read(cx).snapshot(cx);
 5481        let mut selections = self.selections.all::<Point>(cx);
 5482        let mut clipboard_selections = Vec::with_capacity(selections.len());
 5483        {
 5484            let max_point = buffer.max_point();
 5485            let mut is_first = true;
 5486            for selection in &mut selections {
 5487                let is_entire_line = selection.is_empty() || self.selections.line_mode;
 5488                if is_entire_line {
 5489                    selection.start = Point::new(selection.start.row, 0);
 5490                    selection.end = cmp::min(max_point, Point::new(selection.end.row + 1, 0));
 5491                    selection.goal = SelectionGoal::None;
 5492                }
 5493                if is_first {
 5494                    is_first = false;
 5495                } else {
 5496                    text += "\n";
 5497                }
 5498                let mut len = 0;
 5499                for chunk in buffer.text_for_range(selection.start..selection.end) {
 5500                    text.push_str(chunk);
 5501                    len += chunk.len();
 5502                }
 5503                clipboard_selections.push(ClipboardSelection {
 5504                    len,
 5505                    is_entire_line,
 5506                    first_line_indent: buffer.indent_size_for_line(selection.start.row).len,
 5507                });
 5508            }
 5509        }
 5510
 5511        self.transact(cx, |this, cx| {
 5512            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5513                s.select(selections);
 5514            });
 5515            this.insert("", cx);
 5516            cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
 5517        });
 5518    }
 5519
 5520    pub fn copy(&mut self, _: &Copy, cx: &mut ViewContext<Self>) {
 5521        let selections = self.selections.all::<Point>(cx);
 5522        let buffer = self.buffer.read(cx).read(cx);
 5523        let mut text = String::new();
 5524
 5525        let mut clipboard_selections = Vec::with_capacity(selections.len());
 5526        {
 5527            let max_point = buffer.max_point();
 5528            let mut is_first = true;
 5529            for selection in selections.iter() {
 5530                let mut start = selection.start;
 5531                let mut end = selection.end;
 5532                let is_entire_line = selection.is_empty() || self.selections.line_mode;
 5533                if is_entire_line {
 5534                    start = Point::new(start.row, 0);
 5535                    end = cmp::min(max_point, Point::new(end.row + 1, 0));
 5536                }
 5537                if is_first {
 5538                    is_first = false;
 5539                } else {
 5540                    text += "\n";
 5541                }
 5542                let mut len = 0;
 5543                for chunk in buffer.text_for_range(start..end) {
 5544                    text.push_str(chunk);
 5545                    len += chunk.len();
 5546                }
 5547                clipboard_selections.push(ClipboardSelection {
 5548                    len,
 5549                    is_entire_line,
 5550                    first_line_indent: buffer.indent_size_for_line(start.row).len,
 5551                });
 5552            }
 5553        }
 5554
 5555        cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
 5556    }
 5557
 5558    pub fn paste(&mut self, _: &Paste, cx: &mut ViewContext<Self>) {
 5559        self.transact(cx, |this, cx| {
 5560            if let Some(item) = cx.read_from_clipboard() {
 5561                let clipboard_text = Cow::Borrowed(item.text());
 5562                if let Some(mut clipboard_selections) = item.metadata::<Vec<ClipboardSelection>>() {
 5563                    let old_selections = this.selections.all::<usize>(cx);
 5564                    let all_selections_were_entire_line =
 5565                        clipboard_selections.iter().all(|s| s.is_entire_line);
 5566                    let first_selection_indent_column =
 5567                        clipboard_selections.first().map(|s| s.first_line_indent);
 5568                    if clipboard_selections.len() != old_selections.len() {
 5569                        clipboard_selections.drain(..);
 5570                    }
 5571
 5572                    this.buffer.update(cx, |buffer, cx| {
 5573                        let snapshot = buffer.read(cx);
 5574                        let mut start_offset = 0;
 5575                        let mut edits = Vec::new();
 5576                        let mut original_indent_columns = Vec::new();
 5577                        let line_mode = this.selections.line_mode;
 5578                        for (ix, selection) in old_selections.iter().enumerate() {
 5579                            let to_insert;
 5580                            let entire_line;
 5581                            let original_indent_column;
 5582                            if let Some(clipboard_selection) = clipboard_selections.get(ix) {
 5583                                let end_offset = start_offset + clipboard_selection.len;
 5584                                to_insert = &clipboard_text[start_offset..end_offset];
 5585                                entire_line = clipboard_selection.is_entire_line;
 5586                                start_offset = end_offset + 1;
 5587                                original_indent_column =
 5588                                    Some(clipboard_selection.first_line_indent);
 5589                            } else {
 5590                                to_insert = clipboard_text.as_str();
 5591                                entire_line = all_selections_were_entire_line;
 5592                                original_indent_column = first_selection_indent_column
 5593                            }
 5594
 5595                            // If the corresponding selection was empty when this slice of the
 5596                            // clipboard text was written, then the entire line containing the
 5597                            // selection was copied. If this selection is also currently empty,
 5598                            // then paste the line before the current line of the buffer.
 5599                            let range = if selection.is_empty() && !line_mode && entire_line {
 5600                                let column = selection.start.to_point(&snapshot).column as usize;
 5601                                let line_start = selection.start - column;
 5602                                line_start..line_start
 5603                            } else {
 5604                                selection.range()
 5605                            };
 5606
 5607                            edits.push((range, to_insert));
 5608                            original_indent_columns.extend(original_indent_column);
 5609                        }
 5610                        drop(snapshot);
 5611
 5612                        buffer.edit(
 5613                            edits,
 5614                            Some(AutoindentMode::Block {
 5615                                original_indent_columns,
 5616                            }),
 5617                            cx,
 5618                        );
 5619                    });
 5620
 5621                    let selections = this.selections.all::<usize>(cx);
 5622                    this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
 5623                } else {
 5624                    this.insert(&clipboard_text, cx);
 5625                }
 5626            }
 5627        });
 5628    }
 5629
 5630    pub fn undo(&mut self, _: &Undo, cx: &mut ViewContext<Self>) {
 5631        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.undo(cx)) {
 5632            if let Some((selections, _)) = self.selection_history.transaction(tx_id).cloned() {
 5633                self.change_selections(None, cx, |s| {
 5634                    s.select_anchors(selections.to_vec());
 5635                });
 5636            }
 5637            self.request_autoscroll(Autoscroll::fit(), cx);
 5638            self.unmark_text(cx);
 5639            self.refresh_copilot_suggestions(true, cx);
 5640            cx.emit(Event::Edited);
 5641        }
 5642    }
 5643
 5644    pub fn redo(&mut self, _: &Redo, cx: &mut ViewContext<Self>) {
 5645        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.redo(cx)) {
 5646            if let Some((_, Some(selections))) = self.selection_history.transaction(tx_id).cloned()
 5647            {
 5648                self.change_selections(None, cx, |s| {
 5649                    s.select_anchors(selections.to_vec());
 5650                });
 5651            }
 5652            self.request_autoscroll(Autoscroll::fit(), cx);
 5653            self.unmark_text(cx);
 5654            self.refresh_copilot_suggestions(true, cx);
 5655            cx.emit(Event::Edited);
 5656        }
 5657    }
 5658
 5659    pub fn finalize_last_transaction(&mut self, cx: &mut ViewContext<Self>) {
 5660        self.buffer
 5661            .update(cx, |buffer, cx| buffer.finalize_last_transaction(cx));
 5662    }
 5663
 5664    pub fn move_left(&mut self, _: &MoveLeft, cx: &mut ViewContext<Self>) {
 5665        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5666            let line_mode = s.line_mode;
 5667            s.move_with(|map, selection| {
 5668                let cursor = if selection.is_empty() && !line_mode {
 5669                    movement::left(map, selection.start)
 5670                } else {
 5671                    selection.start
 5672                };
 5673                selection.collapse_to(cursor, SelectionGoal::None);
 5674            });
 5675        })
 5676    }
 5677
 5678    pub fn select_left(&mut self, _: &SelectLeft, cx: &mut ViewContext<Self>) {
 5679        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5680            s.move_heads_with(|map, head, _| (movement::left(map, head), SelectionGoal::None));
 5681        })
 5682    }
 5683
 5684    pub fn move_right(&mut self, _: &MoveRight, cx: &mut ViewContext<Self>) {
 5685        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5686            let line_mode = s.line_mode;
 5687            s.move_with(|map, selection| {
 5688                let cursor = if selection.is_empty() && !line_mode {
 5689                    movement::right(map, selection.end)
 5690                } else {
 5691                    selection.end
 5692                };
 5693                selection.collapse_to(cursor, SelectionGoal::None)
 5694            });
 5695        })
 5696    }
 5697
 5698    pub fn select_right(&mut self, _: &SelectRight, cx: &mut ViewContext<Self>) {
 5699        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5700            s.move_heads_with(|map, head, _| (movement::right(map, head), SelectionGoal::None));
 5701        })
 5702    }
 5703
 5704    pub fn move_up(&mut self, _: &MoveUp, cx: &mut ViewContext<Self>) {
 5705        if self.take_rename(true, cx).is_some() {
 5706            return;
 5707        }
 5708
 5709        if matches!(self.mode, EditorMode::SingleLine) {
 5710            cx.propagate();
 5711            return;
 5712        }
 5713
 5714        let text_layout_details = &self.text_layout_details(cx);
 5715
 5716        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5717            let line_mode = s.line_mode;
 5718            s.move_with(|map, selection| {
 5719                if !selection.is_empty() && !line_mode {
 5720                    selection.goal = SelectionGoal::None;
 5721                }
 5722                let (cursor, goal) = movement::up(
 5723                    map,
 5724                    selection.start,
 5725                    selection.goal,
 5726                    false,
 5727                    &text_layout_details,
 5728                );
 5729                selection.collapse_to(cursor, goal);
 5730            });
 5731        })
 5732    }
 5733
 5734    pub fn move_page_up(&mut self, action: &MovePageUp, cx: &mut ViewContext<Self>) {
 5735        if self.take_rename(true, cx).is_some() {
 5736            return;
 5737        }
 5738
 5739        if matches!(self.mode, EditorMode::SingleLine) {
 5740            cx.propagate();
 5741            return;
 5742        }
 5743
 5744        let row_count = if let Some(row_count) = self.visible_line_count() {
 5745            row_count as u32 - 1
 5746        } else {
 5747            return;
 5748        };
 5749
 5750        let autoscroll = if action.center_cursor {
 5751            Autoscroll::center()
 5752        } else {
 5753            Autoscroll::fit()
 5754        };
 5755
 5756        let text_layout_details = &self.text_layout_details(cx);
 5757
 5758        self.change_selections(Some(autoscroll), cx, |s| {
 5759            let line_mode = s.line_mode;
 5760            s.move_with(|map, selection| {
 5761                if !selection.is_empty() && !line_mode {
 5762                    selection.goal = SelectionGoal::None;
 5763                }
 5764                let (cursor, goal) = movement::up_by_rows(
 5765                    map,
 5766                    selection.end,
 5767                    row_count,
 5768                    selection.goal,
 5769                    false,
 5770                    &text_layout_details,
 5771                );
 5772                selection.collapse_to(cursor, goal);
 5773            });
 5774        });
 5775    }
 5776
 5777    pub fn select_up(&mut self, _: &SelectUp, cx: &mut ViewContext<Self>) {
 5778        let text_layout_details = &self.text_layout_details(cx);
 5779        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5780            s.move_heads_with(|map, head, goal| {
 5781                movement::up(map, head, goal, false, &text_layout_details)
 5782            })
 5783        })
 5784    }
 5785
 5786    pub fn move_down(&mut self, _: &MoveDown, cx: &mut ViewContext<Self>) {
 5787        self.take_rename(true, cx);
 5788
 5789        if self.mode == EditorMode::SingleLine {
 5790            cx.propagate();
 5791            return;
 5792        }
 5793
 5794        let text_layout_details = &self.text_layout_details(cx);
 5795        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5796            let line_mode = s.line_mode;
 5797            s.move_with(|map, selection| {
 5798                if !selection.is_empty() && !line_mode {
 5799                    selection.goal = SelectionGoal::None;
 5800                }
 5801                let (cursor, goal) = movement::down(
 5802                    map,
 5803                    selection.end,
 5804                    selection.goal,
 5805                    false,
 5806                    &text_layout_details,
 5807                );
 5808                selection.collapse_to(cursor, goal);
 5809            });
 5810        });
 5811    }
 5812
 5813    pub fn move_page_down(&mut self, action: &MovePageDown, cx: &mut ViewContext<Self>) {
 5814        if self.take_rename(true, cx).is_some() {
 5815            return;
 5816        }
 5817
 5818        if self
 5819            .context_menu
 5820            .write()
 5821            .as_mut()
 5822            .map(|menu| menu.select_last(self.project.as_ref(), cx))
 5823            .unwrap_or(false)
 5824        {
 5825            return;
 5826        }
 5827
 5828        if matches!(self.mode, EditorMode::SingleLine) {
 5829            cx.propagate();
 5830            return;
 5831        }
 5832
 5833        let row_count = if let Some(row_count) = self.visible_line_count() {
 5834            row_count as u32 - 1
 5835        } else {
 5836            return;
 5837        };
 5838
 5839        let autoscroll = if action.center_cursor {
 5840            Autoscroll::center()
 5841        } else {
 5842            Autoscroll::fit()
 5843        };
 5844
 5845        let text_layout_details = &self.text_layout_details(cx);
 5846        self.change_selections(Some(autoscroll), cx, |s| {
 5847            let line_mode = s.line_mode;
 5848            s.move_with(|map, selection| {
 5849                if !selection.is_empty() && !line_mode {
 5850                    selection.goal = SelectionGoal::None;
 5851                }
 5852                let (cursor, goal) = movement::down_by_rows(
 5853                    map,
 5854                    selection.end,
 5855                    row_count,
 5856                    selection.goal,
 5857                    false,
 5858                    &text_layout_details,
 5859                );
 5860                selection.collapse_to(cursor, goal);
 5861            });
 5862        });
 5863    }
 5864
 5865    pub fn select_down(&mut self, _: &SelectDown, cx: &mut ViewContext<Self>) {
 5866        let text_layout_details = &self.text_layout_details(cx);
 5867        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5868            s.move_heads_with(|map, head, goal| {
 5869                movement::down(map, head, goal, false, &text_layout_details)
 5870            })
 5871        });
 5872    }
 5873
 5874    pub fn context_menu_first(&mut self, _: &ContextMenuFirst, cx: &mut ViewContext<Self>) {
 5875        if let Some(context_menu) = self.context_menu.write().as_mut() {
 5876            context_menu.select_first(self.project.as_ref(), cx);
 5877        }
 5878    }
 5879
 5880    pub fn context_menu_prev(&mut self, _: &ContextMenuPrev, cx: &mut ViewContext<Self>) {
 5881        if let Some(context_menu) = self.context_menu.write().as_mut() {
 5882            context_menu.select_prev(self.project.as_ref(), cx);
 5883        }
 5884    }
 5885
 5886    pub fn context_menu_next(&mut self, _: &ContextMenuNext, cx: &mut ViewContext<Self>) {
 5887        if let Some(context_menu) = self.context_menu.write().as_mut() {
 5888            context_menu.select_next(self.project.as_ref(), cx);
 5889        }
 5890    }
 5891
 5892    pub fn context_menu_last(&mut self, _: &ContextMenuLast, cx: &mut ViewContext<Self>) {
 5893        if let Some(context_menu) = self.context_menu.write().as_mut() {
 5894            context_menu.select_last(self.project.as_ref(), cx);
 5895        }
 5896    }
 5897
 5898    pub fn move_to_previous_word_start(
 5899        &mut self,
 5900        _: &MoveToPreviousWordStart,
 5901        cx: &mut ViewContext<Self>,
 5902    ) {
 5903        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5904            s.move_cursors_with(|map, head, _| {
 5905                (
 5906                    movement::previous_word_start(map, head),
 5907                    SelectionGoal::None,
 5908                )
 5909            });
 5910        })
 5911    }
 5912
 5913    pub fn move_to_previous_subword_start(
 5914        &mut self,
 5915        _: &MoveToPreviousSubwordStart,
 5916        cx: &mut ViewContext<Self>,
 5917    ) {
 5918        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5919            s.move_cursors_with(|map, head, _| {
 5920                (
 5921                    movement::previous_subword_start(map, head),
 5922                    SelectionGoal::None,
 5923                )
 5924            });
 5925        })
 5926    }
 5927
 5928    pub fn select_to_previous_word_start(
 5929        &mut self,
 5930        _: &SelectToPreviousWordStart,
 5931        cx: &mut ViewContext<Self>,
 5932    ) {
 5933        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5934            s.move_heads_with(|map, head, _| {
 5935                (
 5936                    movement::previous_word_start(map, head),
 5937                    SelectionGoal::None,
 5938                )
 5939            });
 5940        })
 5941    }
 5942
 5943    pub fn select_to_previous_subword_start(
 5944        &mut self,
 5945        _: &SelectToPreviousSubwordStart,
 5946        cx: &mut ViewContext<Self>,
 5947    ) {
 5948        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5949            s.move_heads_with(|map, head, _| {
 5950                (
 5951                    movement::previous_subword_start(map, head),
 5952                    SelectionGoal::None,
 5953                )
 5954            });
 5955        })
 5956    }
 5957
 5958    pub fn delete_to_previous_word_start(
 5959        &mut self,
 5960        _: &DeleteToPreviousWordStart,
 5961        cx: &mut ViewContext<Self>,
 5962    ) {
 5963        self.transact(cx, |this, cx| {
 5964            this.select_autoclose_pair(cx);
 5965            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5966                let line_mode = s.line_mode;
 5967                s.move_with(|map, selection| {
 5968                    if selection.is_empty() && !line_mode {
 5969                        let cursor = movement::previous_word_start(map, selection.head());
 5970                        selection.set_head(cursor, SelectionGoal::None);
 5971                    }
 5972                });
 5973            });
 5974            this.insert("", cx);
 5975        });
 5976    }
 5977
 5978    pub fn delete_to_previous_subword_start(
 5979        &mut self,
 5980        _: &DeleteToPreviousSubwordStart,
 5981        cx: &mut ViewContext<Self>,
 5982    ) {
 5983        self.transact(cx, |this, cx| {
 5984            this.select_autoclose_pair(cx);
 5985            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5986                let line_mode = s.line_mode;
 5987                s.move_with(|map, selection| {
 5988                    if selection.is_empty() && !line_mode {
 5989                        let cursor = movement::previous_subword_start(map, selection.head());
 5990                        selection.set_head(cursor, SelectionGoal::None);
 5991                    }
 5992                });
 5993            });
 5994            this.insert("", cx);
 5995        });
 5996    }
 5997
 5998    pub fn move_to_next_word_end(&mut self, _: &MoveToNextWordEnd, cx: &mut ViewContext<Self>) {
 5999        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6000            s.move_cursors_with(|map, head, _| {
 6001                (movement::next_word_end(map, head), SelectionGoal::None)
 6002            });
 6003        })
 6004    }
 6005
 6006    pub fn move_to_next_subword_end(
 6007        &mut self,
 6008        _: &MoveToNextSubwordEnd,
 6009        cx: &mut ViewContext<Self>,
 6010    ) {
 6011        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6012            s.move_cursors_with(|map, head, _| {
 6013                (movement::next_subword_end(map, head), SelectionGoal::None)
 6014            });
 6015        })
 6016    }
 6017
 6018    pub fn select_to_next_word_end(&mut self, _: &SelectToNextWordEnd, cx: &mut ViewContext<Self>) {
 6019        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6020            s.move_heads_with(|map, head, _| {
 6021                (movement::next_word_end(map, head), SelectionGoal::None)
 6022            });
 6023        })
 6024    }
 6025
 6026    pub fn select_to_next_subword_end(
 6027        &mut self,
 6028        _: &SelectToNextSubwordEnd,
 6029        cx: &mut ViewContext<Self>,
 6030    ) {
 6031        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6032            s.move_heads_with(|map, head, _| {
 6033                (movement::next_subword_end(map, head), SelectionGoal::None)
 6034            });
 6035        })
 6036    }
 6037
 6038    pub fn delete_to_next_word_end(&mut self, _: &DeleteToNextWordEnd, cx: &mut ViewContext<Self>) {
 6039        self.transact(cx, |this, cx| {
 6040            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6041                let line_mode = s.line_mode;
 6042                s.move_with(|map, selection| {
 6043                    if selection.is_empty() && !line_mode {
 6044                        let cursor = movement::next_word_end(map, selection.head());
 6045                        selection.set_head(cursor, SelectionGoal::None);
 6046                    }
 6047                });
 6048            });
 6049            this.insert("", cx);
 6050        });
 6051    }
 6052
 6053    pub fn delete_to_next_subword_end(
 6054        &mut self,
 6055        _: &DeleteToNextSubwordEnd,
 6056        cx: &mut ViewContext<Self>,
 6057    ) {
 6058        self.transact(cx, |this, cx| {
 6059            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6060                s.move_with(|map, selection| {
 6061                    if selection.is_empty() {
 6062                        let cursor = movement::next_subword_end(map, selection.head());
 6063                        selection.set_head(cursor, SelectionGoal::None);
 6064                    }
 6065                });
 6066            });
 6067            this.insert("", cx);
 6068        });
 6069    }
 6070
 6071    pub fn move_to_beginning_of_line(
 6072        &mut self,
 6073        _: &MoveToBeginningOfLine,
 6074        cx: &mut ViewContext<Self>,
 6075    ) {
 6076        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6077            s.move_cursors_with(|map, head, _| {
 6078                (
 6079                    movement::indented_line_beginning(map, head, true),
 6080                    SelectionGoal::None,
 6081                )
 6082            });
 6083        })
 6084    }
 6085
 6086    pub fn select_to_beginning_of_line(
 6087        &mut self,
 6088        action: &SelectToBeginningOfLine,
 6089        cx: &mut ViewContext<Self>,
 6090    ) {
 6091        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6092            s.move_heads_with(|map, head, _| {
 6093                (
 6094                    movement::indented_line_beginning(map, head, action.stop_at_soft_wraps),
 6095                    SelectionGoal::None,
 6096                )
 6097            });
 6098        });
 6099    }
 6100
 6101    pub fn delete_to_beginning_of_line(
 6102        &mut self,
 6103        _: &DeleteToBeginningOfLine,
 6104        cx: &mut ViewContext<Self>,
 6105    ) {
 6106        self.transact(cx, |this, cx| {
 6107            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6108                s.move_with(|_, selection| {
 6109                    selection.reversed = true;
 6110                });
 6111            });
 6112
 6113            this.select_to_beginning_of_line(
 6114                &SelectToBeginningOfLine {
 6115                    stop_at_soft_wraps: false,
 6116                },
 6117                cx,
 6118            );
 6119            this.backspace(&Backspace, cx);
 6120        });
 6121    }
 6122
 6123    pub fn move_to_end_of_line(&mut self, _: &MoveToEndOfLine, cx: &mut ViewContext<Self>) {
 6124        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6125            s.move_cursors_with(|map, head, _| {
 6126                (movement::line_end(map, head, true), SelectionGoal::None)
 6127            });
 6128        })
 6129    }
 6130
 6131    pub fn select_to_end_of_line(
 6132        &mut self,
 6133        action: &SelectToEndOfLine,
 6134        cx: &mut ViewContext<Self>,
 6135    ) {
 6136        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6137            s.move_heads_with(|map, head, _| {
 6138                (
 6139                    movement::line_end(map, head, action.stop_at_soft_wraps),
 6140                    SelectionGoal::None,
 6141                )
 6142            });
 6143        })
 6144    }
 6145
 6146    pub fn delete_to_end_of_line(&mut self, _: &DeleteToEndOfLine, cx: &mut ViewContext<Self>) {
 6147        self.transact(cx, |this, cx| {
 6148            this.select_to_end_of_line(
 6149                &SelectToEndOfLine {
 6150                    stop_at_soft_wraps: false,
 6151                },
 6152                cx,
 6153            );
 6154            this.delete(&Delete, cx);
 6155        });
 6156    }
 6157
 6158    pub fn cut_to_end_of_line(&mut self, _: &CutToEndOfLine, cx: &mut ViewContext<Self>) {
 6159        self.transact(cx, |this, cx| {
 6160            this.select_to_end_of_line(
 6161                &SelectToEndOfLine {
 6162                    stop_at_soft_wraps: false,
 6163                },
 6164                cx,
 6165            );
 6166            this.cut(&Cut, cx);
 6167        });
 6168    }
 6169
 6170    pub fn move_to_start_of_paragraph(
 6171        &mut self,
 6172        _: &MoveToStartOfParagraph,
 6173        cx: &mut ViewContext<Self>,
 6174    ) {
 6175        if matches!(self.mode, EditorMode::SingleLine) {
 6176            cx.propagate();
 6177            return;
 6178        }
 6179
 6180        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6181            s.move_with(|map, selection| {
 6182                selection.collapse_to(
 6183                    movement::start_of_paragraph(map, selection.head(), 1),
 6184                    SelectionGoal::None,
 6185                )
 6186            });
 6187        })
 6188    }
 6189
 6190    pub fn move_to_end_of_paragraph(
 6191        &mut self,
 6192        _: &MoveToEndOfParagraph,
 6193        cx: &mut ViewContext<Self>,
 6194    ) {
 6195        if matches!(self.mode, EditorMode::SingleLine) {
 6196            cx.propagate();
 6197            return;
 6198        }
 6199
 6200        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6201            s.move_with(|map, selection| {
 6202                selection.collapse_to(
 6203                    movement::end_of_paragraph(map, selection.head(), 1),
 6204                    SelectionGoal::None,
 6205                )
 6206            });
 6207        })
 6208    }
 6209
 6210    pub fn select_to_start_of_paragraph(
 6211        &mut self,
 6212        _: &SelectToStartOfParagraph,
 6213        cx: &mut ViewContext<Self>,
 6214    ) {
 6215        if matches!(self.mode, EditorMode::SingleLine) {
 6216            cx.propagate();
 6217            return;
 6218        }
 6219
 6220        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6221            s.move_heads_with(|map, head, _| {
 6222                (
 6223                    movement::start_of_paragraph(map, head, 1),
 6224                    SelectionGoal::None,
 6225                )
 6226            });
 6227        })
 6228    }
 6229
 6230    pub fn select_to_end_of_paragraph(
 6231        &mut self,
 6232        _: &SelectToEndOfParagraph,
 6233        cx: &mut ViewContext<Self>,
 6234    ) {
 6235        if matches!(self.mode, EditorMode::SingleLine) {
 6236            cx.propagate();
 6237            return;
 6238        }
 6239
 6240        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6241            s.move_heads_with(|map, head, _| {
 6242                (
 6243                    movement::end_of_paragraph(map, head, 1),
 6244                    SelectionGoal::None,
 6245                )
 6246            });
 6247        })
 6248    }
 6249
 6250    pub fn move_to_beginning(&mut self, _: &MoveToBeginning, cx: &mut ViewContext<Self>) {
 6251        if matches!(self.mode, EditorMode::SingleLine) {
 6252            cx.propagate();
 6253            return;
 6254        }
 6255
 6256        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6257            s.select_ranges(vec![0..0]);
 6258        });
 6259    }
 6260
 6261    pub fn select_to_beginning(&mut self, _: &SelectToBeginning, cx: &mut ViewContext<Self>) {
 6262        let mut selection = self.selections.last::<Point>(cx);
 6263        selection.set_head(Point::zero(), SelectionGoal::None);
 6264
 6265        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6266            s.select(vec![selection]);
 6267        });
 6268    }
 6269
 6270    pub fn move_to_end(&mut self, _: &MoveToEnd, cx: &mut ViewContext<Self>) {
 6271        if matches!(self.mode, EditorMode::SingleLine) {
 6272            cx.propagate();
 6273            return;
 6274        }
 6275
 6276        let cursor = self.buffer.read(cx).read(cx).len();
 6277        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6278            s.select_ranges(vec![cursor..cursor])
 6279        });
 6280    }
 6281
 6282    pub fn set_nav_history(&mut self, nav_history: Option<ItemNavHistory>) {
 6283        self.nav_history = nav_history;
 6284    }
 6285
 6286    pub fn nav_history(&self) -> Option<&ItemNavHistory> {
 6287        self.nav_history.as_ref()
 6288    }
 6289
 6290    fn push_to_nav_history(
 6291        &mut self,
 6292        cursor_anchor: Anchor,
 6293        new_position: Option<Point>,
 6294        cx: &mut ViewContext<Self>,
 6295    ) {
 6296        if let Some(nav_history) = self.nav_history.as_mut() {
 6297            let buffer = self.buffer.read(cx).read(cx);
 6298            let cursor_position = cursor_anchor.to_point(&buffer);
 6299            let scroll_state = self.scroll_manager.anchor();
 6300            let scroll_top_row = scroll_state.top_row(&buffer);
 6301            drop(buffer);
 6302
 6303            if let Some(new_position) = new_position {
 6304                let row_delta = (new_position.row as i64 - cursor_position.row as i64).abs();
 6305                if row_delta < MIN_NAVIGATION_HISTORY_ROW_DELTA {
 6306                    return;
 6307                }
 6308            }
 6309
 6310            nav_history.push(
 6311                Some(NavigationData {
 6312                    cursor_anchor,
 6313                    cursor_position,
 6314                    scroll_anchor: scroll_state,
 6315                    scroll_top_row,
 6316                }),
 6317                cx,
 6318            );
 6319        }
 6320    }
 6321
 6322    pub fn select_to_end(&mut self, _: &SelectToEnd, cx: &mut ViewContext<Self>) {
 6323        let buffer = self.buffer.read(cx).snapshot(cx);
 6324        let mut selection = self.selections.first::<usize>(cx);
 6325        selection.set_head(buffer.len(), SelectionGoal::None);
 6326        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6327            s.select(vec![selection]);
 6328        });
 6329    }
 6330
 6331    pub fn select_all(&mut self, _: &SelectAll, cx: &mut ViewContext<Self>) {
 6332        let end = self.buffer.read(cx).read(cx).len();
 6333        self.change_selections(None, cx, |s| {
 6334            s.select_ranges(vec![0..end]);
 6335        });
 6336    }
 6337
 6338    pub fn select_line(&mut self, _: &SelectLine, cx: &mut ViewContext<Self>) {
 6339        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 6340        let mut selections = self.selections.all::<Point>(cx);
 6341        let max_point = display_map.buffer_snapshot.max_point();
 6342        for selection in &mut selections {
 6343            let rows = selection.spanned_rows(true, &display_map);
 6344            selection.start = Point::new(rows.start, 0);
 6345            selection.end = cmp::min(max_point, Point::new(rows.end, 0));
 6346            selection.reversed = false;
 6347        }
 6348        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6349            s.select(selections);
 6350        });
 6351    }
 6352
 6353    pub fn split_selection_into_lines(
 6354        &mut self,
 6355        _: &SplitSelectionIntoLines,
 6356        cx: &mut ViewContext<Self>,
 6357    ) {
 6358        let mut to_unfold = Vec::new();
 6359        let mut new_selection_ranges = Vec::new();
 6360        {
 6361            let selections = self.selections.all::<Point>(cx);
 6362            let buffer = self.buffer.read(cx).read(cx);
 6363            for selection in selections {
 6364                for row in selection.start.row..selection.end.row {
 6365                    let cursor = Point::new(row, buffer.line_len(row));
 6366                    new_selection_ranges.push(cursor..cursor);
 6367                }
 6368                new_selection_ranges.push(selection.end..selection.end);
 6369                to_unfold.push(selection.start..selection.end);
 6370            }
 6371        }
 6372        self.unfold_ranges(to_unfold, true, true, cx);
 6373        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6374            s.select_ranges(new_selection_ranges);
 6375        });
 6376    }
 6377
 6378    pub fn add_selection_above(&mut self, _: &AddSelectionAbove, cx: &mut ViewContext<Self>) {
 6379        self.add_selection(true, cx);
 6380    }
 6381
 6382    pub fn add_selection_below(&mut self, _: &AddSelectionBelow, cx: &mut ViewContext<Self>) {
 6383        self.add_selection(false, cx);
 6384    }
 6385
 6386    fn add_selection(&mut self, above: bool, cx: &mut ViewContext<Self>) {
 6387        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 6388        let mut selections = self.selections.all::<Point>(cx);
 6389        let text_layout_details = self.text_layout_details(cx);
 6390        let mut state = self.add_selections_state.take().unwrap_or_else(|| {
 6391            let oldest_selection = selections.iter().min_by_key(|s| s.id).unwrap().clone();
 6392            let range = oldest_selection.display_range(&display_map).sorted();
 6393
 6394            let start_x = display_map.x_for_point(range.start, &text_layout_details);
 6395            let end_x = display_map.x_for_point(range.end, &text_layout_details);
 6396            let positions = start_x.min(end_x)..start_x.max(end_x);
 6397
 6398            selections.clear();
 6399            let mut stack = Vec::new();
 6400            for row in range.start.row()..=range.end.row() {
 6401                if let Some(selection) = self.selections.build_columnar_selection(
 6402                    &display_map,
 6403                    row,
 6404                    &positions,
 6405                    oldest_selection.reversed,
 6406                    &text_layout_details,
 6407                ) {
 6408                    stack.push(selection.id);
 6409                    selections.push(selection);
 6410                }
 6411            }
 6412
 6413            if above {
 6414                stack.reverse();
 6415            }
 6416
 6417            AddSelectionsState { above, stack }
 6418        });
 6419
 6420        let last_added_selection = *state.stack.last().unwrap();
 6421        let mut new_selections = Vec::new();
 6422        if above == state.above {
 6423            let end_row = if above {
 6424                0
 6425            } else {
 6426                display_map.max_point().row()
 6427            };
 6428
 6429            'outer: for selection in selections {
 6430                if selection.id == last_added_selection {
 6431                    let range = selection.display_range(&display_map).sorted();
 6432                    debug_assert_eq!(range.start.row(), range.end.row());
 6433                    let mut row = range.start.row();
 6434                    let positions = if let SelectionGoal::HorizontalRange { start, end } =
 6435                        selection.goal
 6436                    {
 6437                        px(start)..px(end)
 6438                    } else {
 6439                        let start_x = display_map.x_for_point(range.start, &text_layout_details);
 6440                        let end_x = display_map.x_for_point(range.end, &text_layout_details);
 6441                        start_x.min(end_x)..start_x.max(end_x)
 6442                    };
 6443
 6444                    while row != end_row {
 6445                        if above {
 6446                            row -= 1;
 6447                        } else {
 6448                            row += 1;
 6449                        }
 6450
 6451                        if let Some(new_selection) = self.selections.build_columnar_selection(
 6452                            &display_map,
 6453                            row,
 6454                            &positions,
 6455                            selection.reversed,
 6456                            &text_layout_details,
 6457                        ) {
 6458                            state.stack.push(new_selection.id);
 6459                            if above {
 6460                                new_selections.push(new_selection);
 6461                                new_selections.push(selection);
 6462                            } else {
 6463                                new_selections.push(selection);
 6464                                new_selections.push(new_selection);
 6465                            }
 6466
 6467                            continue 'outer;
 6468                        }
 6469                    }
 6470                }
 6471
 6472                new_selections.push(selection);
 6473            }
 6474        } else {
 6475            new_selections = selections;
 6476            new_selections.retain(|s| s.id != last_added_selection);
 6477            state.stack.pop();
 6478        }
 6479
 6480        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6481            s.select(new_selections);
 6482        });
 6483        if state.stack.len() > 1 {
 6484            self.add_selections_state = Some(state);
 6485        }
 6486    }
 6487
 6488    pub fn select_next_match_internal(
 6489        &mut self,
 6490        display_map: &DisplaySnapshot,
 6491        replace_newest: bool,
 6492        autoscroll: Option<Autoscroll>,
 6493        cx: &mut ViewContext<Self>,
 6494    ) -> Result<()> {
 6495        fn select_next_match_ranges(
 6496            this: &mut Editor,
 6497            range: Range<usize>,
 6498            replace_newest: bool,
 6499            auto_scroll: Option<Autoscroll>,
 6500            cx: &mut ViewContext<Editor>,
 6501        ) {
 6502            this.unfold_ranges([range.clone()], false, true, cx);
 6503            this.change_selections(auto_scroll, cx, |s| {
 6504                if replace_newest {
 6505                    s.delete(s.newest_anchor().id);
 6506                }
 6507                s.insert_range(range.clone());
 6508            });
 6509        }
 6510
 6511        let buffer = &display_map.buffer_snapshot;
 6512        let mut selections = self.selections.all::<usize>(cx);
 6513        if let Some(mut select_next_state) = self.select_next_state.take() {
 6514            let query = &select_next_state.query;
 6515            if !select_next_state.done {
 6516                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
 6517                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
 6518                let mut next_selected_range = None;
 6519
 6520                let bytes_after_last_selection =
 6521                    buffer.bytes_in_range(last_selection.end..buffer.len());
 6522                let bytes_before_first_selection = buffer.bytes_in_range(0..first_selection.start);
 6523                let query_matches = query
 6524                    .stream_find_iter(bytes_after_last_selection)
 6525                    .map(|result| (last_selection.end, result))
 6526                    .chain(
 6527                        query
 6528                            .stream_find_iter(bytes_before_first_selection)
 6529                            .map(|result| (0, result)),
 6530                    );
 6531
 6532                for (start_offset, query_match) in query_matches {
 6533                    let query_match = query_match.unwrap(); // can only fail due to I/O
 6534                    let offset_range =
 6535                        start_offset + query_match.start()..start_offset + query_match.end();
 6536                    let display_range = offset_range.start.to_display_point(&display_map)
 6537                        ..offset_range.end.to_display_point(&display_map);
 6538
 6539                    if !select_next_state.wordwise
 6540                        || (!movement::is_inside_word(&display_map, display_range.start)
 6541                            && !movement::is_inside_word(&display_map, display_range.end))
 6542                    {
 6543                        if selections
 6544                            .iter()
 6545                            .find(|selection| selection.range().overlaps(&offset_range))
 6546                            .is_none()
 6547                        {
 6548                            next_selected_range = Some(offset_range);
 6549                            break;
 6550                        }
 6551                    }
 6552                }
 6553
 6554                if let Some(next_selected_range) = next_selected_range {
 6555                    select_next_match_ranges(
 6556                        self,
 6557                        next_selected_range,
 6558                        replace_newest,
 6559                        autoscroll,
 6560                        cx,
 6561                    );
 6562                } else {
 6563                    select_next_state.done = true;
 6564                }
 6565            }
 6566
 6567            self.select_next_state = Some(select_next_state);
 6568        } else if selections.len() == 1 {
 6569            let selection = selections.last_mut().unwrap();
 6570            if selection.start == selection.end {
 6571                let word_range = movement::surrounding_word(
 6572                    &display_map,
 6573                    selection.start.to_display_point(&display_map),
 6574                );
 6575                selection.start = word_range.start.to_offset(&display_map, Bias::Left);
 6576                selection.end = word_range.end.to_offset(&display_map, Bias::Left);
 6577                selection.goal = SelectionGoal::None;
 6578                selection.reversed = false;
 6579
 6580                let query = buffer
 6581                    .text_for_range(selection.start..selection.end)
 6582                    .collect::<String>();
 6583
 6584                let is_empty = query.is_empty();
 6585                let select_state = SelectNextState {
 6586                    query: AhoCorasick::new(&[query])?,
 6587                    wordwise: true,
 6588                    done: is_empty,
 6589                };
 6590                select_next_match_ranges(
 6591                    self,
 6592                    selection.start..selection.end,
 6593                    replace_newest,
 6594                    autoscroll,
 6595                    cx,
 6596                );
 6597                self.select_next_state = Some(select_state);
 6598            } else {
 6599                let query = buffer
 6600                    .text_for_range(selection.start..selection.end)
 6601                    .collect::<String>();
 6602                self.select_next_state = Some(SelectNextState {
 6603                    query: AhoCorasick::new(&[query])?,
 6604                    wordwise: false,
 6605                    done: false,
 6606                });
 6607                self.select_next_match_internal(display_map, replace_newest, autoscroll, cx)?;
 6608            }
 6609        }
 6610        Ok(())
 6611    }
 6612
 6613    pub fn select_all_matches(
 6614        &mut self,
 6615        action: &SelectAllMatches,
 6616        cx: &mut ViewContext<Self>,
 6617    ) -> Result<()> {
 6618        self.push_to_selection_history();
 6619        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 6620
 6621        loop {
 6622            self.select_next_match_internal(&display_map, action.replace_newest, None, cx)?;
 6623
 6624            if self
 6625                .select_next_state
 6626                .as_ref()
 6627                .map(|selection_state| selection_state.done)
 6628                .unwrap_or(true)
 6629            {
 6630                break;
 6631            }
 6632        }
 6633
 6634        Ok(())
 6635    }
 6636
 6637    pub fn select_next(&mut self, action: &SelectNext, cx: &mut ViewContext<Self>) -> Result<()> {
 6638        self.push_to_selection_history();
 6639        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 6640        self.select_next_match_internal(
 6641            &display_map,
 6642            action.replace_newest,
 6643            Some(Autoscroll::newest()),
 6644            cx,
 6645        )?;
 6646        Ok(())
 6647    }
 6648
 6649    pub fn select_previous(
 6650        &mut self,
 6651        action: &SelectPrevious,
 6652        cx: &mut ViewContext<Self>,
 6653    ) -> Result<()> {
 6654        self.push_to_selection_history();
 6655        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 6656        let buffer = &display_map.buffer_snapshot;
 6657        let mut selections = self.selections.all::<usize>(cx);
 6658        if let Some(mut select_prev_state) = self.select_prev_state.take() {
 6659            let query = &select_prev_state.query;
 6660            if !select_prev_state.done {
 6661                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
 6662                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
 6663                let mut next_selected_range = None;
 6664                // When we're iterating matches backwards, the oldest match will actually be the furthest one in the buffer.
 6665                let bytes_before_last_selection =
 6666                    buffer.reversed_bytes_in_range(0..last_selection.start);
 6667                let bytes_after_first_selection =
 6668                    buffer.reversed_bytes_in_range(first_selection.end..buffer.len());
 6669                let query_matches = query
 6670                    .stream_find_iter(bytes_before_last_selection)
 6671                    .map(|result| (last_selection.start, result))
 6672                    .chain(
 6673                        query
 6674                            .stream_find_iter(bytes_after_first_selection)
 6675                            .map(|result| (buffer.len(), result)),
 6676                    );
 6677                for (end_offset, query_match) in query_matches {
 6678                    let query_match = query_match.unwrap(); // can only fail due to I/O
 6679                    let offset_range =
 6680                        end_offset - query_match.end()..end_offset - query_match.start();
 6681                    let display_range = offset_range.start.to_display_point(&display_map)
 6682                        ..offset_range.end.to_display_point(&display_map);
 6683
 6684                    if !select_prev_state.wordwise
 6685                        || (!movement::is_inside_word(&display_map, display_range.start)
 6686                            && !movement::is_inside_word(&display_map, display_range.end))
 6687                    {
 6688                        next_selected_range = Some(offset_range);
 6689                        break;
 6690                    }
 6691                }
 6692
 6693                if let Some(next_selected_range) = next_selected_range {
 6694                    self.unfold_ranges([next_selected_range.clone()], false, true, cx);
 6695                    self.change_selections(Some(Autoscroll::newest()), cx, |s| {
 6696                        if action.replace_newest {
 6697                            s.delete(s.newest_anchor().id);
 6698                        }
 6699                        s.insert_range(next_selected_range);
 6700                    });
 6701                } else {
 6702                    select_prev_state.done = true;
 6703                }
 6704            }
 6705
 6706            self.select_prev_state = Some(select_prev_state);
 6707        } else if selections.len() == 1 {
 6708            let selection = selections.last_mut().unwrap();
 6709            if selection.start == selection.end {
 6710                let word_range = movement::surrounding_word(
 6711                    &display_map,
 6712                    selection.start.to_display_point(&display_map),
 6713                );
 6714                selection.start = word_range.start.to_offset(&display_map, Bias::Left);
 6715                selection.end = word_range.end.to_offset(&display_map, Bias::Left);
 6716                selection.goal = SelectionGoal::None;
 6717                selection.reversed = false;
 6718
 6719                let query = buffer
 6720                    .text_for_range(selection.start..selection.end)
 6721                    .collect::<String>();
 6722                let query = query.chars().rev().collect::<String>();
 6723                let select_state = SelectNextState {
 6724                    query: AhoCorasick::new(&[query])?,
 6725                    wordwise: true,
 6726                    done: false,
 6727                };
 6728                self.unfold_ranges([selection.start..selection.end], false, true, cx);
 6729                self.change_selections(Some(Autoscroll::newest()), cx, |s| {
 6730                    s.select(selections);
 6731                });
 6732                self.select_prev_state = Some(select_state);
 6733            } else {
 6734                let query = buffer
 6735                    .text_for_range(selection.start..selection.end)
 6736                    .collect::<String>();
 6737                let query = query.chars().rev().collect::<String>();
 6738                self.select_prev_state = Some(SelectNextState {
 6739                    query: AhoCorasick::new(&[query])?,
 6740                    wordwise: false,
 6741                    done: false,
 6742                });
 6743                self.select_previous(action, cx)?;
 6744            }
 6745        }
 6746        Ok(())
 6747    }
 6748
 6749    pub fn toggle_comments(&mut self, action: &ToggleComments, cx: &mut ViewContext<Self>) {
 6750        let text_layout_details = &self.text_layout_details(cx);
 6751        self.transact(cx, |this, cx| {
 6752            let mut selections = this.selections.all::<Point>(cx);
 6753            let mut edits = Vec::new();
 6754            let mut selection_edit_ranges = Vec::new();
 6755            let mut last_toggled_row = None;
 6756            let snapshot = this.buffer.read(cx).read(cx);
 6757            let empty_str: Arc<str> = "".into();
 6758            let mut suffixes_inserted = Vec::new();
 6759
 6760            fn comment_prefix_range(
 6761                snapshot: &MultiBufferSnapshot,
 6762                row: u32,
 6763                comment_prefix: &str,
 6764                comment_prefix_whitespace: &str,
 6765            ) -> Range<Point> {
 6766                let start = Point::new(row, snapshot.indent_size_for_line(row).len);
 6767
 6768                let mut line_bytes = snapshot
 6769                    .bytes_in_range(start..snapshot.max_point())
 6770                    .flatten()
 6771                    .copied();
 6772
 6773                // If this line currently begins with the line comment prefix, then record
 6774                // the range containing the prefix.
 6775                if line_bytes
 6776                    .by_ref()
 6777                    .take(comment_prefix.len())
 6778                    .eq(comment_prefix.bytes())
 6779                {
 6780                    // Include any whitespace that matches the comment prefix.
 6781                    let matching_whitespace_len = line_bytes
 6782                        .zip(comment_prefix_whitespace.bytes())
 6783                        .take_while(|(a, b)| a == b)
 6784                        .count() as u32;
 6785                    let end = Point::new(
 6786                        start.row,
 6787                        start.column + comment_prefix.len() as u32 + matching_whitespace_len,
 6788                    );
 6789                    start..end
 6790                } else {
 6791                    start..start
 6792                }
 6793            }
 6794
 6795            fn comment_suffix_range(
 6796                snapshot: &MultiBufferSnapshot,
 6797                row: u32,
 6798                comment_suffix: &str,
 6799                comment_suffix_has_leading_space: bool,
 6800            ) -> Range<Point> {
 6801                let end = Point::new(row, snapshot.line_len(row));
 6802                let suffix_start_column = end.column.saturating_sub(comment_suffix.len() as u32);
 6803
 6804                let mut line_end_bytes = snapshot
 6805                    .bytes_in_range(Point::new(end.row, suffix_start_column.saturating_sub(1))..end)
 6806                    .flatten()
 6807                    .copied();
 6808
 6809                let leading_space_len = if suffix_start_column > 0
 6810                    && line_end_bytes.next() == Some(b' ')
 6811                    && comment_suffix_has_leading_space
 6812                {
 6813                    1
 6814                } else {
 6815                    0
 6816                };
 6817
 6818                // If this line currently begins with the line comment prefix, then record
 6819                // the range containing the prefix.
 6820                if line_end_bytes.by_ref().eq(comment_suffix.bytes()) {
 6821                    let start = Point::new(end.row, suffix_start_column - leading_space_len);
 6822                    start..end
 6823                } else {
 6824                    end..end
 6825                }
 6826            }
 6827
 6828            // TODO: Handle selections that cross excerpts
 6829            for selection in &mut selections {
 6830                let start_column = snapshot.indent_size_for_line(selection.start.row).len;
 6831                let language = if let Some(language) =
 6832                    snapshot.language_scope_at(Point::new(selection.start.row, start_column))
 6833                {
 6834                    language
 6835                } else {
 6836                    continue;
 6837                };
 6838
 6839                selection_edit_ranges.clear();
 6840
 6841                // If multiple selections contain a given row, avoid processing that
 6842                // row more than once.
 6843                let mut start_row = selection.start.row;
 6844                if last_toggled_row == Some(start_row) {
 6845                    start_row += 1;
 6846                }
 6847                let end_row =
 6848                    if selection.end.row > selection.start.row && selection.end.column == 0 {
 6849                        selection.end.row - 1
 6850                    } else {
 6851                        selection.end.row
 6852                    };
 6853                last_toggled_row = Some(end_row);
 6854
 6855                if start_row > end_row {
 6856                    continue;
 6857                }
 6858
 6859                // If the language has line comments, toggle those.
 6860                if let Some(full_comment_prefix) = language.line_comment_prefix() {
 6861                    // Split the comment prefix's trailing whitespace into a separate string,
 6862                    // as that portion won't be used for detecting if a line is a comment.
 6863                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
 6864                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
 6865                    let mut all_selection_lines_are_comments = true;
 6866
 6867                    for row in start_row..=end_row {
 6868                        if snapshot.is_line_blank(row) && start_row < end_row {
 6869                            continue;
 6870                        }
 6871
 6872                        let prefix_range = comment_prefix_range(
 6873                            snapshot.deref(),
 6874                            row,
 6875                            comment_prefix,
 6876                            comment_prefix_whitespace,
 6877                        );
 6878                        if prefix_range.is_empty() {
 6879                            all_selection_lines_are_comments = false;
 6880                        }
 6881                        selection_edit_ranges.push(prefix_range);
 6882                    }
 6883
 6884                    if all_selection_lines_are_comments {
 6885                        edits.extend(
 6886                            selection_edit_ranges
 6887                                .iter()
 6888                                .cloned()
 6889                                .map(|range| (range, empty_str.clone())),
 6890                        );
 6891                    } else {
 6892                        let min_column = selection_edit_ranges
 6893                            .iter()
 6894                            .map(|r| r.start.column)
 6895                            .min()
 6896                            .unwrap_or(0);
 6897                        edits.extend(selection_edit_ranges.iter().map(|range| {
 6898                            let position = Point::new(range.start.row, min_column);
 6899                            (position..position, full_comment_prefix.clone())
 6900                        }));
 6901                    }
 6902                } else if let Some((full_comment_prefix, comment_suffix)) =
 6903                    language.block_comment_delimiters()
 6904                {
 6905                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
 6906                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
 6907                    let prefix_range = comment_prefix_range(
 6908                        snapshot.deref(),
 6909                        start_row,
 6910                        comment_prefix,
 6911                        comment_prefix_whitespace,
 6912                    );
 6913                    let suffix_range = comment_suffix_range(
 6914                        snapshot.deref(),
 6915                        end_row,
 6916                        comment_suffix.trim_start_matches(' '),
 6917                        comment_suffix.starts_with(' '),
 6918                    );
 6919
 6920                    if prefix_range.is_empty() || suffix_range.is_empty() {
 6921                        edits.push((
 6922                            prefix_range.start..prefix_range.start,
 6923                            full_comment_prefix.clone(),
 6924                        ));
 6925                        edits.push((suffix_range.end..suffix_range.end, comment_suffix.clone()));
 6926                        suffixes_inserted.push((end_row, comment_suffix.len()));
 6927                    } else {
 6928                        edits.push((prefix_range, empty_str.clone()));
 6929                        edits.push((suffix_range, empty_str.clone()));
 6930                    }
 6931                } else {
 6932                    continue;
 6933                }
 6934            }
 6935
 6936            drop(snapshot);
 6937            this.buffer.update(cx, |buffer, cx| {
 6938                buffer.edit(edits, None, cx);
 6939            });
 6940
 6941            // Adjust selections so that they end before any comment suffixes that
 6942            // were inserted.
 6943            let mut suffixes_inserted = suffixes_inserted.into_iter().peekable();
 6944            let mut selections = this.selections.all::<Point>(cx);
 6945            let snapshot = this.buffer.read(cx).read(cx);
 6946            for selection in &mut selections {
 6947                while let Some((row, suffix_len)) = suffixes_inserted.peek().copied() {
 6948                    match row.cmp(&selection.end.row) {
 6949                        Ordering::Less => {
 6950                            suffixes_inserted.next();
 6951                            continue;
 6952                        }
 6953                        Ordering::Greater => break,
 6954                        Ordering::Equal => {
 6955                            if selection.end.column == snapshot.line_len(row) {
 6956                                if selection.is_empty() {
 6957                                    selection.start.column -= suffix_len as u32;
 6958                                }
 6959                                selection.end.column -= suffix_len as u32;
 6960                            }
 6961                            break;
 6962                        }
 6963                    }
 6964                }
 6965            }
 6966
 6967            drop(snapshot);
 6968            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
 6969
 6970            let selections = this.selections.all::<Point>(cx);
 6971            let selections_on_single_row = selections.windows(2).all(|selections| {
 6972                selections[0].start.row == selections[1].start.row
 6973                    && selections[0].end.row == selections[1].end.row
 6974                    && selections[0].start.row == selections[0].end.row
 6975            });
 6976            let selections_selecting = selections
 6977                .iter()
 6978                .any(|selection| selection.start != selection.end);
 6979            let advance_downwards = action.advance_downwards
 6980                && selections_on_single_row
 6981                && !selections_selecting
 6982                && this.mode != EditorMode::SingleLine;
 6983
 6984            if advance_downwards {
 6985                let snapshot = this.buffer.read(cx).snapshot(cx);
 6986
 6987                this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6988                    s.move_cursors_with(|display_snapshot, display_point, _| {
 6989                        let mut point = display_point.to_point(display_snapshot);
 6990                        point.row += 1;
 6991                        point = snapshot.clip_point(point, Bias::Left);
 6992                        let display_point = point.to_display_point(display_snapshot);
 6993                        let goal = SelectionGoal::HorizontalPosition(
 6994                            display_snapshot
 6995                                .x_for_point(display_point, &text_layout_details)
 6996                                .into(),
 6997                        );
 6998                        (display_point, goal)
 6999                    })
 7000                });
 7001            }
 7002        });
 7003    }
 7004
 7005    pub fn select_larger_syntax_node(
 7006        &mut self,
 7007        _: &SelectLargerSyntaxNode,
 7008        cx: &mut ViewContext<Self>,
 7009    ) {
 7010        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 7011        let buffer = self.buffer.read(cx).snapshot(cx);
 7012        let old_selections = self.selections.all::<usize>(cx).into_boxed_slice();
 7013
 7014        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
 7015        let mut selected_larger_node = false;
 7016        let new_selections = old_selections
 7017            .iter()
 7018            .map(|selection| {
 7019                let old_range = selection.start..selection.end;
 7020                let mut new_range = old_range.clone();
 7021                while let Some(containing_range) =
 7022                    buffer.range_for_syntax_ancestor(new_range.clone())
 7023                {
 7024                    new_range = containing_range;
 7025                    if !display_map.intersects_fold(new_range.start)
 7026                        && !display_map.intersects_fold(new_range.end)
 7027                    {
 7028                        break;
 7029                    }
 7030                }
 7031
 7032                selected_larger_node |= new_range != old_range;
 7033                Selection {
 7034                    id: selection.id,
 7035                    start: new_range.start,
 7036                    end: new_range.end,
 7037                    goal: SelectionGoal::None,
 7038                    reversed: selection.reversed,
 7039                }
 7040            })
 7041            .collect::<Vec<_>>();
 7042
 7043        if selected_larger_node {
 7044            stack.push(old_selections);
 7045            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7046                s.select(new_selections);
 7047            });
 7048        }
 7049        self.select_larger_syntax_node_stack = stack;
 7050    }
 7051
 7052    pub fn select_smaller_syntax_node(
 7053        &mut self,
 7054        _: &SelectSmallerSyntaxNode,
 7055        cx: &mut ViewContext<Self>,
 7056    ) {
 7057        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
 7058        if let Some(selections) = stack.pop() {
 7059            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7060                s.select(selections.to_vec());
 7061            });
 7062        }
 7063        self.select_larger_syntax_node_stack = stack;
 7064    }
 7065
 7066    pub fn move_to_enclosing_bracket(
 7067        &mut self,
 7068        _: &MoveToEnclosingBracket,
 7069        cx: &mut ViewContext<Self>,
 7070    ) {
 7071        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7072            s.move_offsets_with(|snapshot, selection| {
 7073                let Some(enclosing_bracket_ranges) =
 7074                    snapshot.enclosing_bracket_ranges(selection.start..selection.end)
 7075                else {
 7076                    return;
 7077                };
 7078
 7079                let mut best_length = usize::MAX;
 7080                let mut best_inside = false;
 7081                let mut best_in_bracket_range = false;
 7082                let mut best_destination = None;
 7083                for (open, close) in enclosing_bracket_ranges {
 7084                    let close = close.to_inclusive();
 7085                    let length = close.end() - open.start;
 7086                    let inside = selection.start >= open.end && selection.end <= *close.start();
 7087                    let in_bracket_range = open.to_inclusive().contains(&selection.head())
 7088                        || close.contains(&selection.head());
 7089
 7090                    // If best is next to a bracket and current isn't, skip
 7091                    if !in_bracket_range && best_in_bracket_range {
 7092                        continue;
 7093                    }
 7094
 7095                    // Prefer smaller lengths unless best is inside and current isn't
 7096                    if length > best_length && (best_inside || !inside) {
 7097                        continue;
 7098                    }
 7099
 7100                    best_length = length;
 7101                    best_inside = inside;
 7102                    best_in_bracket_range = in_bracket_range;
 7103                    best_destination = Some(
 7104                        if close.contains(&selection.start) && close.contains(&selection.end) {
 7105                            if inside {
 7106                                open.end
 7107                            } else {
 7108                                open.start
 7109                            }
 7110                        } else {
 7111                            if inside {
 7112                                *close.start()
 7113                            } else {
 7114                                *close.end()
 7115                            }
 7116                        },
 7117                    );
 7118                }
 7119
 7120                if let Some(destination) = best_destination {
 7121                    selection.collapse_to(destination, SelectionGoal::None);
 7122                }
 7123            })
 7124        });
 7125    }
 7126
 7127    pub fn undo_selection(&mut self, _: &UndoSelection, cx: &mut ViewContext<Self>) {
 7128        self.end_selection(cx);
 7129        self.selection_history.mode = SelectionHistoryMode::Undoing;
 7130        if let Some(entry) = self.selection_history.undo_stack.pop_back() {
 7131            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
 7132            self.select_next_state = entry.select_next_state;
 7133            self.select_prev_state = entry.select_prev_state;
 7134            self.add_selections_state = entry.add_selections_state;
 7135            self.request_autoscroll(Autoscroll::newest(), cx);
 7136        }
 7137        self.selection_history.mode = SelectionHistoryMode::Normal;
 7138    }
 7139
 7140    pub fn redo_selection(&mut self, _: &RedoSelection, cx: &mut ViewContext<Self>) {
 7141        self.end_selection(cx);
 7142        self.selection_history.mode = SelectionHistoryMode::Redoing;
 7143        if let Some(entry) = self.selection_history.redo_stack.pop_back() {
 7144            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
 7145            self.select_next_state = entry.select_next_state;
 7146            self.select_prev_state = entry.select_prev_state;
 7147            self.add_selections_state = entry.add_selections_state;
 7148            self.request_autoscroll(Autoscroll::newest(), cx);
 7149        }
 7150        self.selection_history.mode = SelectionHistoryMode::Normal;
 7151    }
 7152
 7153    fn go_to_diagnostic(&mut self, _: &GoToDiagnostic, cx: &mut ViewContext<Self>) {
 7154        self.go_to_diagnostic_impl(Direction::Next, cx)
 7155    }
 7156
 7157    fn go_to_prev_diagnostic(&mut self, _: &GoToPrevDiagnostic, cx: &mut ViewContext<Self>) {
 7158        self.go_to_diagnostic_impl(Direction::Prev, cx)
 7159    }
 7160
 7161    pub fn go_to_diagnostic_impl(&mut self, direction: Direction, cx: &mut ViewContext<Self>) {
 7162        let buffer = self.buffer.read(cx).snapshot(cx);
 7163        let selection = self.selections.newest::<usize>(cx);
 7164
 7165        // If there is an active Diagnostic Popover. Jump to it's diagnostic instead.
 7166        if direction == Direction::Next {
 7167            if let Some(popover) = self.hover_state.diagnostic_popover.as_ref() {
 7168                let (group_id, jump_to) = popover.activation_info();
 7169                if self.activate_diagnostics(group_id, cx) {
 7170                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7171                        let mut new_selection = s.newest_anchor().clone();
 7172                        new_selection.collapse_to(jump_to, SelectionGoal::None);
 7173                        s.select_anchors(vec![new_selection.clone()]);
 7174                    });
 7175                }
 7176                return;
 7177            }
 7178        }
 7179
 7180        let mut active_primary_range = self.active_diagnostics.as_ref().map(|active_diagnostics| {
 7181            active_diagnostics
 7182                .primary_range
 7183                .to_offset(&buffer)
 7184                .to_inclusive()
 7185        });
 7186        let mut search_start = if let Some(active_primary_range) = active_primary_range.as_ref() {
 7187            if active_primary_range.contains(&selection.head()) {
 7188                *active_primary_range.end()
 7189            } else {
 7190                selection.head()
 7191            }
 7192        } else {
 7193            selection.head()
 7194        };
 7195
 7196        loop {
 7197            let mut diagnostics = if direction == Direction::Prev {
 7198                buffer.diagnostics_in_range::<_, usize>(0..search_start, true)
 7199            } else {
 7200                buffer.diagnostics_in_range::<_, usize>(search_start..buffer.len(), false)
 7201            };
 7202            let group = diagnostics.find_map(|entry| {
 7203                if entry.diagnostic.is_primary
 7204                    && entry.diagnostic.severity <= DiagnosticSeverity::WARNING
 7205                    && !entry.range.is_empty()
 7206                    && Some(entry.range.end) != active_primary_range.as_ref().map(|r| *r.end())
 7207                    && !entry.range.contains(&search_start)
 7208                {
 7209                    Some((entry.range, entry.diagnostic.group_id))
 7210                } else {
 7211                    None
 7212                }
 7213            });
 7214
 7215            if let Some((primary_range, group_id)) = group {
 7216                if self.activate_diagnostics(group_id, cx) {
 7217                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7218                        s.select(vec![Selection {
 7219                            id: selection.id,
 7220                            start: primary_range.start,
 7221                            end: primary_range.start,
 7222                            reversed: false,
 7223                            goal: SelectionGoal::None,
 7224                        }]);
 7225                    });
 7226                }
 7227                break;
 7228            } else {
 7229                // Cycle around to the start of the buffer, potentially moving back to the start of
 7230                // the currently active diagnostic.
 7231                active_primary_range.take();
 7232                if direction == Direction::Prev {
 7233                    if search_start == buffer.len() {
 7234                        break;
 7235                    } else {
 7236                        search_start = buffer.len();
 7237                    }
 7238                } else if search_start == 0 {
 7239                    break;
 7240                } else {
 7241                    search_start = 0;
 7242                }
 7243            }
 7244        }
 7245    }
 7246
 7247    fn go_to_hunk(&mut self, _: &GoToHunk, cx: &mut ViewContext<Self>) {
 7248        let snapshot = self
 7249            .display_map
 7250            .update(cx, |display_map, cx| display_map.snapshot(cx));
 7251        let selection = self.selections.newest::<Point>(cx);
 7252
 7253        if !self.seek_in_direction(
 7254            &snapshot,
 7255            selection.head(),
 7256            false,
 7257            snapshot
 7258                .buffer_snapshot
 7259                .git_diff_hunks_in_range((selection.head().row + 1)..u32::MAX),
 7260            cx,
 7261        ) {
 7262            let wrapped_point = Point::zero();
 7263            self.seek_in_direction(
 7264                &snapshot,
 7265                wrapped_point,
 7266                true,
 7267                snapshot
 7268                    .buffer_snapshot
 7269                    .git_diff_hunks_in_range((wrapped_point.row + 1)..u32::MAX),
 7270                cx,
 7271            );
 7272        }
 7273    }
 7274
 7275    fn go_to_prev_hunk(&mut self, _: &GoToPrevHunk, cx: &mut ViewContext<Self>) {
 7276        let snapshot = self
 7277            .display_map
 7278            .update(cx, |display_map, cx| display_map.snapshot(cx));
 7279        let selection = self.selections.newest::<Point>(cx);
 7280
 7281        if !self.seek_in_direction(
 7282            &snapshot,
 7283            selection.head(),
 7284            false,
 7285            snapshot
 7286                .buffer_snapshot
 7287                .git_diff_hunks_in_range_rev(0..selection.head().row),
 7288            cx,
 7289        ) {
 7290            let wrapped_point = snapshot.buffer_snapshot.max_point();
 7291            self.seek_in_direction(
 7292                &snapshot,
 7293                wrapped_point,
 7294                true,
 7295                snapshot
 7296                    .buffer_snapshot
 7297                    .git_diff_hunks_in_range_rev(0..wrapped_point.row),
 7298                cx,
 7299            );
 7300        }
 7301    }
 7302
 7303    fn seek_in_direction(
 7304        &mut self,
 7305        snapshot: &DisplaySnapshot,
 7306        initial_point: Point,
 7307        is_wrapped: bool,
 7308        hunks: impl Iterator<Item = DiffHunk<u32>>,
 7309        cx: &mut ViewContext<Editor>,
 7310    ) -> bool {
 7311        let display_point = initial_point.to_display_point(snapshot);
 7312        let mut hunks = hunks
 7313            .map(|hunk| diff_hunk_to_display(hunk, &snapshot))
 7314            .filter(|hunk| {
 7315                if is_wrapped {
 7316                    true
 7317                } else {
 7318                    !hunk.contains_display_row(display_point.row())
 7319                }
 7320            })
 7321            .dedup();
 7322
 7323        if let Some(hunk) = hunks.next() {
 7324            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7325                let row = hunk.start_display_row();
 7326                let point = DisplayPoint::new(row, 0);
 7327                s.select_display_ranges([point..point]);
 7328            });
 7329
 7330            true
 7331        } else {
 7332            false
 7333        }
 7334    }
 7335
 7336    pub fn go_to_definition(&mut self, _: &GoToDefinition, cx: &mut ViewContext<Self>) {
 7337        self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, false, cx);
 7338    }
 7339
 7340    pub fn go_to_type_definition(&mut self, _: &GoToTypeDefinition, cx: &mut ViewContext<Self>) {
 7341        self.go_to_definition_of_kind(GotoDefinitionKind::Type, false, cx);
 7342    }
 7343
 7344    pub fn go_to_definition_split(&mut self, _: &GoToDefinitionSplit, cx: &mut ViewContext<Self>) {
 7345        self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, true, cx);
 7346    }
 7347
 7348    pub fn go_to_type_definition_split(
 7349        &mut self,
 7350        _: &GoToTypeDefinitionSplit,
 7351        cx: &mut ViewContext<Self>,
 7352    ) {
 7353        self.go_to_definition_of_kind(GotoDefinitionKind::Type, true, cx);
 7354    }
 7355
 7356    fn go_to_definition_of_kind(
 7357        &mut self,
 7358        kind: GotoDefinitionKind,
 7359        split: bool,
 7360        cx: &mut ViewContext<Self>,
 7361    ) {
 7362        let Some(workspace) = self.workspace() else {
 7363            return;
 7364        };
 7365        let buffer = self.buffer.read(cx);
 7366        let head = self.selections.newest::<usize>(cx).head();
 7367        let (buffer, head) = if let Some(text_anchor) = buffer.text_anchor_for_position(head, cx) {
 7368            text_anchor
 7369        } else {
 7370            return;
 7371        };
 7372
 7373        let project = workspace.read(cx).project().clone();
 7374        let definitions = project.update(cx, |project, cx| match kind {
 7375            GotoDefinitionKind::Symbol => project.definition(&buffer, head, cx),
 7376            GotoDefinitionKind::Type => project.type_definition(&buffer, head, cx),
 7377        });
 7378
 7379        cx.spawn(|editor, mut cx| async move {
 7380            let definitions = definitions.await?;
 7381            editor.update(&mut cx, |editor, cx| {
 7382                editor.navigate_to_definitions(
 7383                    definitions
 7384                        .into_iter()
 7385                        .map(GoToDefinitionLink::Text)
 7386                        .collect(),
 7387                    split,
 7388                    cx,
 7389                );
 7390            })?;
 7391            Ok::<(), anyhow::Error>(())
 7392        })
 7393        .detach_and_log_err(cx);
 7394    }
 7395
 7396    pub fn navigate_to_definitions(
 7397        &mut self,
 7398        mut definitions: Vec<GoToDefinitionLink>,
 7399        split: bool,
 7400        cx: &mut ViewContext<Editor>,
 7401    ) {
 7402        let Some(workspace) = self.workspace() else {
 7403            return;
 7404        };
 7405        let pane = workspace.read(cx).active_pane().clone();
 7406        // If there is one definition, just open it directly
 7407        if definitions.len() == 1 {
 7408            let definition = definitions.pop().unwrap();
 7409            let target_task = match definition {
 7410                GoToDefinitionLink::Text(link) => Task::Ready(Some(Ok(Some(link.target)))),
 7411                GoToDefinitionLink::InlayHint(lsp_location, server_id) => {
 7412                    self.compute_target_location(lsp_location, server_id, cx)
 7413                }
 7414            };
 7415            cx.spawn(|editor, mut cx| async move {
 7416                let target = target_task.await.context("target resolution task")?;
 7417                if let Some(target) = target {
 7418                    editor.update(&mut cx, |editor, cx| {
 7419                        let range = target.range.to_offset(target.buffer.read(cx));
 7420                        let range = editor.range_for_match(&range);
 7421                        if Some(&target.buffer) == editor.buffer.read(cx).as_singleton().as_ref() {
 7422                            editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7423                                s.select_ranges([range]);
 7424                            });
 7425                        } else {
 7426                            cx.window_context().defer(move |cx| {
 7427                                let target_editor: View<Self> =
 7428                                    workspace.update(cx, |workspace, cx| {
 7429                                        if split {
 7430                                            workspace.split_project_item(target.buffer.clone(), cx)
 7431                                        } else {
 7432                                            workspace.open_project_item(target.buffer.clone(), cx)
 7433                                        }
 7434                                    });
 7435                                target_editor.update(cx, |target_editor, cx| {
 7436                                    // When selecting a definition in a different buffer, disable the nav history
 7437                                    // to avoid creating a history entry at the previous cursor location.
 7438                                    pane.update(cx, |pane, _| pane.disable_history());
 7439                                    target_editor.change_selections(
 7440                                        Some(Autoscroll::fit()),
 7441                                        cx,
 7442                                        |s| {
 7443                                            s.select_ranges([range]);
 7444                                        },
 7445                                    );
 7446                                    pane.update(cx, |pane, _| pane.enable_history());
 7447                                });
 7448                            });
 7449                        }
 7450                    })
 7451                } else {
 7452                    Ok(())
 7453                }
 7454            })
 7455            .detach_and_log_err(cx);
 7456        } else if !definitions.is_empty() {
 7457            let replica_id = self.replica_id(cx);
 7458            cx.spawn(|editor, mut cx| async move {
 7459                let (title, location_tasks) = editor
 7460                    .update(&mut cx, |editor, cx| {
 7461                        let title = definitions
 7462                            .iter()
 7463                            .find_map(|definition| match definition {
 7464                                GoToDefinitionLink::Text(link) => {
 7465                                    link.origin.as_ref().map(|origin| {
 7466                                        let buffer = origin.buffer.read(cx);
 7467                                        format!(
 7468                                            "Definitions for {}",
 7469                                            buffer
 7470                                                .text_for_range(origin.range.clone())
 7471                                                .collect::<String>()
 7472                                        )
 7473                                    })
 7474                                }
 7475                                GoToDefinitionLink::InlayHint(_, _) => None,
 7476                            })
 7477                            .unwrap_or("Definitions".to_string());
 7478                        let location_tasks = definitions
 7479                            .into_iter()
 7480                            .map(|definition| match definition {
 7481                                GoToDefinitionLink::Text(link) => {
 7482                                    Task::Ready(Some(Ok(Some(link.target))))
 7483                                }
 7484                                GoToDefinitionLink::InlayHint(lsp_location, server_id) => {
 7485                                    editor.compute_target_location(lsp_location, server_id, cx)
 7486                                }
 7487                            })
 7488                            .collect::<Vec<_>>();
 7489                        (title, location_tasks)
 7490                    })
 7491                    .context("location tasks preparation")?;
 7492
 7493                let locations = futures::future::join_all(location_tasks)
 7494                    .await
 7495                    .into_iter()
 7496                    .filter_map(|location| location.transpose())
 7497                    .collect::<Result<_>>()
 7498                    .context("location tasks")?;
 7499                workspace.update(&mut cx, |workspace, cx| {
 7500                    Self::open_locations_in_multibuffer(
 7501                        workspace, locations, replica_id, title, split, cx,
 7502                    )
 7503                });
 7504
 7505                anyhow::Ok(())
 7506            })
 7507            .detach_and_log_err(cx);
 7508        }
 7509    }
 7510
 7511    fn compute_target_location(
 7512        &self,
 7513        lsp_location: lsp::Location,
 7514        server_id: LanguageServerId,
 7515        cx: &mut ViewContext<Editor>,
 7516    ) -> Task<anyhow::Result<Option<Location>>> {
 7517        let Some(project) = self.project.clone() else {
 7518            return Task::Ready(Some(Ok(None)));
 7519        };
 7520
 7521        cx.spawn(move |editor, mut cx| async move {
 7522            let location_task = editor.update(&mut cx, |editor, cx| {
 7523                project.update(cx, |project, cx| {
 7524                    let language_server_name =
 7525                        editor.buffer.read(cx).as_singleton().and_then(|buffer| {
 7526                            project
 7527                                .language_server_for_buffer(buffer.read(cx), server_id, cx)
 7528                                .map(|(_, lsp_adapter)| {
 7529                                    LanguageServerName(Arc::from(lsp_adapter.name()))
 7530                                })
 7531                        });
 7532                    language_server_name.map(|language_server_name| {
 7533                        project.open_local_buffer_via_lsp(
 7534                            lsp_location.uri.clone(),
 7535                            server_id,
 7536                            language_server_name,
 7537                            cx,
 7538                        )
 7539                    })
 7540                })
 7541            })?;
 7542            let location = match location_task {
 7543                Some(task) => Some({
 7544                    let target_buffer_handle = task.await.context("open local buffer")?;
 7545                    let range = target_buffer_handle.update(&mut cx, |target_buffer, _| {
 7546                        let target_start = target_buffer
 7547                            .clip_point_utf16(point_from_lsp(lsp_location.range.start), Bias::Left);
 7548                        let target_end = target_buffer
 7549                            .clip_point_utf16(point_from_lsp(lsp_location.range.end), Bias::Left);
 7550                        target_buffer.anchor_after(target_start)
 7551                            ..target_buffer.anchor_before(target_end)
 7552                    })?;
 7553                    Location {
 7554                        buffer: target_buffer_handle,
 7555                        range,
 7556                    }
 7557                }),
 7558                None => None,
 7559            };
 7560            Ok(location)
 7561        })
 7562    }
 7563
 7564    pub fn find_all_references(
 7565        &mut self,
 7566        _: &FindAllReferences,
 7567        cx: &mut ViewContext<Self>,
 7568    ) -> Option<Task<Result<()>>> {
 7569        let buffer = self.buffer.read(cx);
 7570        let head = self.selections.newest::<usize>(cx).head();
 7571        let (buffer, head) = buffer.text_anchor_for_position(head, cx)?;
 7572        let replica_id = self.replica_id(cx);
 7573
 7574        let workspace = self.workspace()?;
 7575        let project = workspace.read(cx).project().clone();
 7576        let references = project.update(cx, |project, cx| project.references(&buffer, head, cx));
 7577        Some(cx.spawn(|_, mut cx| async move {
 7578            let locations = references.await?;
 7579            if locations.is_empty() {
 7580                return Ok(());
 7581            }
 7582
 7583            workspace.update(&mut cx, |workspace, cx| {
 7584                let title = locations
 7585                    .first()
 7586                    .as_ref()
 7587                    .map(|location| {
 7588                        let buffer = location.buffer.read(cx);
 7589                        format!(
 7590                            "References to `{}`",
 7591                            buffer
 7592                                .text_for_range(location.range.clone())
 7593                                .collect::<String>()
 7594                        )
 7595                    })
 7596                    .unwrap();
 7597                Self::open_locations_in_multibuffer(
 7598                    workspace, locations, replica_id, title, false, cx,
 7599                );
 7600            })?;
 7601
 7602            Ok(())
 7603        }))
 7604    }
 7605
 7606    /// Opens a multibuffer with the given project locations in it
 7607    pub fn open_locations_in_multibuffer(
 7608        workspace: &mut Workspace,
 7609        mut locations: Vec<Location>,
 7610        replica_id: ReplicaId,
 7611        title: String,
 7612        split: bool,
 7613        cx: &mut ViewContext<Workspace>,
 7614    ) {
 7615        // If there are multiple definitions, open them in a multibuffer
 7616        locations.sort_by_key(|location| location.buffer.read(cx).remote_id());
 7617        let mut locations = locations.into_iter().peekable();
 7618        let mut ranges_to_highlight = Vec::new();
 7619
 7620        let excerpt_buffer = cx.build_model(|cx| {
 7621            let mut multibuffer = MultiBuffer::new(replica_id);
 7622            while let Some(location) = locations.next() {
 7623                let buffer = location.buffer.read(cx);
 7624                let mut ranges_for_buffer = Vec::new();
 7625                let range = location.range.to_offset(buffer);
 7626                ranges_for_buffer.push(range.clone());
 7627
 7628                while let Some(next_location) = locations.peek() {
 7629                    if next_location.buffer == location.buffer {
 7630                        ranges_for_buffer.push(next_location.range.to_offset(buffer));
 7631                        locations.next();
 7632                    } else {
 7633                        break;
 7634                    }
 7635                }
 7636
 7637                ranges_for_buffer.sort_by_key(|range| (range.start, Reverse(range.end)));
 7638                ranges_to_highlight.extend(multibuffer.push_excerpts_with_context_lines(
 7639                    location.buffer.clone(),
 7640                    ranges_for_buffer,
 7641                    1,
 7642                    cx,
 7643                ))
 7644            }
 7645
 7646            multibuffer.with_title(title)
 7647        });
 7648
 7649        let editor = cx.build_view(|cx| {
 7650            Editor::for_multibuffer(excerpt_buffer, Some(workspace.project().clone()), cx)
 7651        });
 7652        editor.update(cx, |editor, cx| {
 7653            editor.highlight_background::<Self>(
 7654                ranges_to_highlight,
 7655                |theme| theme.editor_highlighted_line_background,
 7656                cx,
 7657            );
 7658        });
 7659        if split {
 7660            workspace.split_item(SplitDirection::Right, Box::new(editor), cx);
 7661        } else {
 7662            workspace.add_item(Box::new(editor), cx);
 7663        }
 7664    }
 7665
 7666    pub fn rename(&mut self, _: &Rename, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
 7667        use language::ToOffset as _;
 7668
 7669        let project = self.project.clone()?;
 7670        let selection = self.selections.newest_anchor().clone();
 7671        let (cursor_buffer, cursor_buffer_position) = self
 7672            .buffer
 7673            .read(cx)
 7674            .text_anchor_for_position(selection.head(), cx)?;
 7675        let (tail_buffer, _) = self
 7676            .buffer
 7677            .read(cx)
 7678            .text_anchor_for_position(selection.tail(), cx)?;
 7679        if tail_buffer != cursor_buffer {
 7680            return None;
 7681        }
 7682
 7683        let snapshot = cursor_buffer.read(cx).snapshot();
 7684        let cursor_buffer_offset = cursor_buffer_position.to_offset(&snapshot);
 7685        let prepare_rename = project.update(cx, |project, cx| {
 7686            project.prepare_rename(cursor_buffer, cursor_buffer_offset, cx)
 7687        });
 7688
 7689        Some(cx.spawn(|this, mut cx| async move {
 7690            let rename_range = if let Some(range) = prepare_rename.await? {
 7691                Some(range)
 7692            } else {
 7693                this.update(&mut cx, |this, cx| {
 7694                    let buffer = this.buffer.read(cx).snapshot(cx);
 7695                    let mut buffer_highlights = this
 7696                        .document_highlights_for_position(selection.head(), &buffer)
 7697                        .filter(|highlight| {
 7698                            highlight.start.excerpt_id == selection.head().excerpt_id
 7699                                && highlight.end.excerpt_id == selection.head().excerpt_id
 7700                        });
 7701                    buffer_highlights
 7702                        .next()
 7703                        .map(|highlight| highlight.start.text_anchor..highlight.end.text_anchor)
 7704                })?
 7705            };
 7706            if let Some(rename_range) = rename_range {
 7707                let rename_buffer_range = rename_range.to_offset(&snapshot);
 7708                let cursor_offset_in_rename_range =
 7709                    cursor_buffer_offset.saturating_sub(rename_buffer_range.start);
 7710
 7711                this.update(&mut cx, |this, cx| {
 7712                    this.take_rename(false, cx);
 7713                    let buffer = this.buffer.read(cx).read(cx);
 7714                    let cursor_offset = selection.head().to_offset(&buffer);
 7715                    let rename_start = cursor_offset.saturating_sub(cursor_offset_in_rename_range);
 7716                    let rename_end = rename_start + rename_buffer_range.len();
 7717                    let range = buffer.anchor_before(rename_start)..buffer.anchor_after(rename_end);
 7718                    let mut old_highlight_id = None;
 7719                    let old_name: Arc<str> = buffer
 7720                        .chunks(rename_start..rename_end, true)
 7721                        .map(|chunk| {
 7722                            if old_highlight_id.is_none() {
 7723                                old_highlight_id = chunk.syntax_highlight_id;
 7724                            }
 7725                            chunk.text
 7726                        })
 7727                        .collect::<String>()
 7728                        .into();
 7729
 7730                    drop(buffer);
 7731
 7732                    // Position the selection in the rename editor so that it matches the current selection.
 7733                    this.show_local_selections = false;
 7734                    let rename_editor = cx.build_view(|cx| {
 7735                        let mut editor = Editor::single_line(cx);
 7736                        editor.buffer.update(cx, |buffer, cx| {
 7737                            buffer.edit([(0..0, old_name.clone())], None, cx)
 7738                        });
 7739                        editor.select_all(&SelectAll, cx);
 7740                        editor
 7741                    });
 7742
 7743                    let ranges = this
 7744                        .clear_background_highlights::<DocumentHighlightWrite>(cx)
 7745                        .into_iter()
 7746                        .flat_map(|(_, ranges)| ranges.into_iter())
 7747                        .chain(
 7748                            this.clear_background_highlights::<DocumentHighlightRead>(cx)
 7749                                .into_iter()
 7750                                .flat_map(|(_, ranges)| ranges.into_iter()),
 7751                        )
 7752                        .collect();
 7753
 7754                    this.highlight_text::<Rename>(
 7755                        ranges,
 7756                        HighlightStyle {
 7757                            fade_out: Some(0.6),
 7758                            ..Default::default()
 7759                        },
 7760                        cx,
 7761                    );
 7762                    let rename_focus_handle = rename_editor.focus_handle(cx);
 7763                    cx.focus(&rename_focus_handle);
 7764                    let block_id = this.insert_blocks(
 7765                        [BlockProperties {
 7766                            style: BlockStyle::Flex,
 7767                            position: range.start.clone(),
 7768                            height: 1,
 7769                            render: Arc::new({
 7770                                let rename_editor = rename_editor.clone();
 7771                                move |cx: &mut BlockContext| {
 7772                                    let mut text_style = cx.editor_style.text.clone();
 7773                                    if let Some(highlight_style) = old_highlight_id
 7774                                        .and_then(|h| h.style(&cx.editor_style.syntax))
 7775                                    {
 7776                                        text_style = text_style.highlight(highlight_style);
 7777                                    }
 7778                                    div()
 7779                                        .pl(cx.anchor_x)
 7780                                        .child(rename_editor.render_with(EditorElement::new(
 7781                                            &rename_editor,
 7782                                            EditorStyle {
 7783                                                background: cx.theme().system().transparent,
 7784                                                local_player: cx.editor_style.local_player,
 7785                                                text: text_style,
 7786                                                scrollbar_width: cx.editor_style.scrollbar_width,
 7787                                                syntax: cx.editor_style.syntax.clone(),
 7788                                                diagnostic_style:
 7789                                                    cx.editor_style.diagnostic_style.clone(),
 7790                                            },
 7791                                        )))
 7792                                        .render()
 7793                                }
 7794                            }),
 7795                            disposition: BlockDisposition::Below,
 7796                        }],
 7797                        Some(Autoscroll::fit()),
 7798                        cx,
 7799                    )[0];
 7800                    this.pending_rename = Some(RenameState {
 7801                        range,
 7802                        old_name,
 7803                        editor: rename_editor,
 7804                        block_id,
 7805                    });
 7806                })?;
 7807            }
 7808
 7809            Ok(())
 7810        }))
 7811    }
 7812
 7813    pub fn confirm_rename(
 7814        &mut self,
 7815        _: &ConfirmRename,
 7816        cx: &mut ViewContext<Self>,
 7817    ) -> Option<Task<Result<()>>> {
 7818        let rename = self.take_rename(false, cx)?;
 7819        let workspace = self.workspace()?;
 7820        let (start_buffer, start) = self
 7821            .buffer
 7822            .read(cx)
 7823            .text_anchor_for_position(rename.range.start.clone(), cx)?;
 7824        let (end_buffer, end) = self
 7825            .buffer
 7826            .read(cx)
 7827            .text_anchor_for_position(rename.range.end.clone(), cx)?;
 7828        if start_buffer != end_buffer {
 7829            return None;
 7830        }
 7831
 7832        let buffer = start_buffer;
 7833        let range = start..end;
 7834        let old_name = rename.old_name;
 7835        let new_name = rename.editor.read(cx).text(cx);
 7836
 7837        let rename = workspace
 7838            .read(cx)
 7839            .project()
 7840            .clone()
 7841            .update(cx, |project, cx| {
 7842                project.perform_rename(buffer.clone(), range.start, new_name.clone(), true, cx)
 7843            });
 7844        let workspace = workspace.downgrade();
 7845
 7846        Some(cx.spawn(|editor, mut cx| async move {
 7847            let project_transaction = rename.await?;
 7848            Self::open_project_transaction(
 7849                &editor,
 7850                workspace,
 7851                project_transaction,
 7852                format!("Rename: {}{}", old_name, new_name),
 7853                cx.clone(),
 7854            )
 7855            .await?;
 7856
 7857            editor.update(&mut cx, |editor, cx| {
 7858                editor.refresh_document_highlights(cx);
 7859            })?;
 7860            Ok(())
 7861        }))
 7862    }
 7863
 7864    fn take_rename(
 7865        &mut self,
 7866        moving_cursor: bool,
 7867        cx: &mut ViewContext<Self>,
 7868    ) -> Option<RenameState> {
 7869        let rename = self.pending_rename.take()?;
 7870        if rename.editor.focus_handle(cx).is_focused(cx) {
 7871            cx.focus(&self.focus_handle);
 7872        }
 7873
 7874        self.remove_blocks(
 7875            [rename.block_id].into_iter().collect(),
 7876            Some(Autoscroll::fit()),
 7877            cx,
 7878        );
 7879        self.clear_highlights::<Rename>(cx);
 7880        self.show_local_selections = true;
 7881
 7882        if moving_cursor {
 7883            let rename_editor = rename.editor.read(cx);
 7884            let cursor_in_rename_editor = rename_editor.selections.newest::<usize>(cx).head();
 7885
 7886            // Update the selection to match the position of the selection inside
 7887            // the rename editor.
 7888            let snapshot = self.buffer.read(cx).read(cx);
 7889            let rename_range = rename.range.to_offset(&snapshot);
 7890            let cursor_in_editor = snapshot
 7891                .clip_offset(rename_range.start + cursor_in_rename_editor, Bias::Left)
 7892                .min(rename_range.end);
 7893            drop(snapshot);
 7894
 7895            self.change_selections(None, cx, |s| {
 7896                s.select_ranges(vec![cursor_in_editor..cursor_in_editor])
 7897            });
 7898        } else {
 7899            self.refresh_document_highlights(cx);
 7900        }
 7901
 7902        Some(rename)
 7903    }
 7904
 7905    #[cfg(any(test, feature = "test-support"))]
 7906    pub fn pending_rename(&self) -> Option<&RenameState> {
 7907        self.pending_rename.as_ref()
 7908    }
 7909
 7910    fn format(&mut self, _: &Format, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
 7911        let project = match &self.project {
 7912            Some(project) => project.clone(),
 7913            None => return None,
 7914        };
 7915
 7916        Some(self.perform_format(project, FormatTrigger::Manual, cx))
 7917    }
 7918
 7919    fn perform_format(
 7920        &mut self,
 7921        project: Model<Project>,
 7922        trigger: FormatTrigger,
 7923        cx: &mut ViewContext<Self>,
 7924    ) -> Task<Result<()>> {
 7925        let buffer = self.buffer().clone();
 7926        let buffers = buffer.read(cx).all_buffers();
 7927
 7928        let mut timeout = cx.background_executor().timer(FORMAT_TIMEOUT).fuse();
 7929        let format = project.update(cx, |project, cx| project.format(buffers, true, trigger, cx));
 7930
 7931        cx.spawn(|_, mut cx| async move {
 7932            let transaction = futures::select_biased! {
 7933                _ = timeout => {
 7934                    log::warn!("timed out waiting for formatting");
 7935                    None
 7936                }
 7937                transaction = format.log_err().fuse() => transaction,
 7938            };
 7939
 7940            buffer.update(&mut cx, |buffer, cx| {
 7941                if let Some(transaction) = transaction {
 7942                    if !buffer.is_singleton() {
 7943                        buffer.push_transaction(&transaction.0, cx);
 7944                    }
 7945                }
 7946
 7947                cx.notify();
 7948            });
 7949
 7950            Ok(())
 7951        })
 7952    }
 7953
 7954    fn restart_language_server(&mut self, _: &RestartLanguageServer, cx: &mut ViewContext<Self>) {
 7955        if let Some(project) = self.project.clone() {
 7956            self.buffer.update(cx, |multi_buffer, cx| {
 7957                project.update(cx, |project, cx| {
 7958                    project.restart_language_servers_for_buffers(multi_buffer.all_buffers(), cx);
 7959                });
 7960            })
 7961        }
 7962    }
 7963
 7964    fn show_character_palette(&mut self, _: &ShowCharacterPalette, cx: &mut ViewContext<Self>) {
 7965        cx.show_character_palette();
 7966    }
 7967
 7968    fn refresh_active_diagnostics(&mut self, cx: &mut ViewContext<Editor>) {
 7969        if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
 7970            let buffer = self.buffer.read(cx).snapshot(cx);
 7971            let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
 7972            let is_valid = buffer
 7973                .diagnostics_in_range::<_, usize>(active_diagnostics.primary_range.clone(), false)
 7974                .any(|entry| {
 7975                    entry.diagnostic.is_primary
 7976                        && !entry.range.is_empty()
 7977                        && entry.range.start == primary_range_start
 7978                        && entry.diagnostic.message == active_diagnostics.primary_message
 7979                });
 7980
 7981            if is_valid != active_diagnostics.is_valid {
 7982                active_diagnostics.is_valid = is_valid;
 7983                let mut new_styles = HashMap::default();
 7984                for (block_id, diagnostic) in &active_diagnostics.blocks {
 7985                    new_styles.insert(
 7986                        *block_id,
 7987                        diagnostic_block_renderer(diagnostic.clone(), is_valid),
 7988                    );
 7989                }
 7990                self.display_map
 7991                    .update(cx, |display_map, _| display_map.replace_blocks(new_styles));
 7992            }
 7993        }
 7994    }
 7995
 7996    fn activate_diagnostics(&mut self, group_id: usize, cx: &mut ViewContext<Self>) -> bool {
 7997        self.dismiss_diagnostics(cx);
 7998        self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
 7999            let buffer = self.buffer.read(cx).snapshot(cx);
 8000
 8001            let mut primary_range = None;
 8002            let mut primary_message = None;
 8003            let mut group_end = Point::zero();
 8004            let diagnostic_group = buffer
 8005                .diagnostic_group::<Point>(group_id)
 8006                .map(|entry| {
 8007                    if entry.range.end > group_end {
 8008                        group_end = entry.range.end;
 8009                    }
 8010                    if entry.diagnostic.is_primary {
 8011                        primary_range = Some(entry.range.clone());
 8012                        primary_message = Some(entry.diagnostic.message.clone());
 8013                    }
 8014                    entry
 8015                })
 8016                .collect::<Vec<_>>();
 8017            let primary_range = primary_range?;
 8018            let primary_message = primary_message?;
 8019            let primary_range =
 8020                buffer.anchor_after(primary_range.start)..buffer.anchor_before(primary_range.end);
 8021
 8022            let blocks = display_map
 8023                .insert_blocks(
 8024                    diagnostic_group.iter().map(|entry| {
 8025                        let diagnostic = entry.diagnostic.clone();
 8026                        let message_height = diagnostic.message.lines().count() as u8;
 8027                        BlockProperties {
 8028                            style: BlockStyle::Fixed,
 8029                            position: buffer.anchor_after(entry.range.start),
 8030                            height: message_height,
 8031                            render: diagnostic_block_renderer(diagnostic, true),
 8032                            disposition: BlockDisposition::Below,
 8033                        }
 8034                    }),
 8035                    cx,
 8036                )
 8037                .into_iter()
 8038                .zip(diagnostic_group.into_iter().map(|entry| entry.diagnostic))
 8039                .collect();
 8040
 8041            Some(ActiveDiagnosticGroup {
 8042                primary_range,
 8043                primary_message,
 8044                blocks,
 8045                is_valid: true,
 8046            })
 8047        });
 8048        self.active_diagnostics.is_some()
 8049    }
 8050
 8051    fn dismiss_diagnostics(&mut self, cx: &mut ViewContext<Self>) {
 8052        if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
 8053            self.display_map.update(cx, |display_map, cx| {
 8054                display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx);
 8055            });
 8056            cx.notify();
 8057        }
 8058    }
 8059
 8060    pub fn set_selections_from_remote(
 8061        &mut self,
 8062        selections: Vec<Selection<Anchor>>,
 8063        pending_selection: Option<Selection<Anchor>>,
 8064        cx: &mut ViewContext<Self>,
 8065    ) {
 8066        let old_cursor_position = self.selections.newest_anchor().head();
 8067        self.selections.change_with(cx, |s| {
 8068            s.select_anchors(selections);
 8069            if let Some(pending_selection) = pending_selection {
 8070                s.set_pending(pending_selection, SelectMode::Character);
 8071            } else {
 8072                s.clear_pending();
 8073            }
 8074        });
 8075        self.selections_did_change(false, &old_cursor_position, cx);
 8076    }
 8077
 8078    fn push_to_selection_history(&mut self) {
 8079        self.selection_history.push(SelectionHistoryEntry {
 8080            selections: self.selections.disjoint_anchors(),
 8081            select_next_state: self.select_next_state.clone(),
 8082            select_prev_state: self.select_prev_state.clone(),
 8083            add_selections_state: self.add_selections_state.clone(),
 8084        });
 8085    }
 8086
 8087    pub fn transact(
 8088        &mut self,
 8089        cx: &mut ViewContext<Self>,
 8090        update: impl FnOnce(&mut Self, &mut ViewContext<Self>),
 8091    ) -> Option<TransactionId> {
 8092        self.start_transaction_at(Instant::now(), cx);
 8093        update(self, cx);
 8094        self.end_transaction_at(Instant::now(), cx)
 8095    }
 8096
 8097    fn start_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
 8098        self.end_selection(cx);
 8099        if let Some(tx_id) = self
 8100            .buffer
 8101            .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx))
 8102        {
 8103            self.selection_history
 8104                .insert_transaction(tx_id, self.selections.disjoint_anchors());
 8105        }
 8106    }
 8107
 8108    fn end_transaction_at(
 8109        &mut self,
 8110        now: Instant,
 8111        cx: &mut ViewContext<Self>,
 8112    ) -> Option<TransactionId> {
 8113        if let Some(tx_id) = self
 8114            .buffer
 8115            .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
 8116        {
 8117            if let Some((_, end_selections)) = self.selection_history.transaction_mut(tx_id) {
 8118                *end_selections = Some(self.selections.disjoint_anchors());
 8119            } else {
 8120                log::error!("unexpectedly ended a transaction that wasn't started by this editor");
 8121            }
 8122
 8123            cx.emit(Event::Edited);
 8124            Some(tx_id)
 8125        } else {
 8126            None
 8127        }
 8128    }
 8129
 8130    pub fn fold(&mut self, _: &Fold, cx: &mut ViewContext<Self>) {
 8131        let mut fold_ranges = Vec::new();
 8132
 8133        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8134
 8135        let selections = self.selections.all_adjusted(cx);
 8136        for selection in selections {
 8137            let range = selection.range().sorted();
 8138            let buffer_start_row = range.start.row;
 8139
 8140            for row in (0..=range.end.row).rev() {
 8141                let fold_range = display_map.foldable_range(row);
 8142
 8143                if let Some(fold_range) = fold_range {
 8144                    if fold_range.end.row >= buffer_start_row {
 8145                        fold_ranges.push(fold_range);
 8146                        if row <= range.start.row {
 8147                            break;
 8148                        }
 8149                    }
 8150                }
 8151            }
 8152        }
 8153
 8154        self.fold_ranges(fold_ranges, true, cx);
 8155    }
 8156
 8157    pub fn fold_at(&mut self, fold_at: &FoldAt, cx: &mut ViewContext<Self>) {
 8158        let buffer_row = fold_at.buffer_row;
 8159        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8160
 8161        if let Some(fold_range) = display_map.foldable_range(buffer_row) {
 8162            let autoscroll = self
 8163                .selections
 8164                .all::<Point>(cx)
 8165                .iter()
 8166                .any(|selection| fold_range.overlaps(&selection.range()));
 8167
 8168            self.fold_ranges(std::iter::once(fold_range), autoscroll, cx);
 8169        }
 8170    }
 8171
 8172    pub fn unfold_lines(&mut self, _: &UnfoldLines, cx: &mut ViewContext<Self>) {
 8173        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8174        let buffer = &display_map.buffer_snapshot;
 8175        let selections = self.selections.all::<Point>(cx);
 8176        let ranges = selections
 8177            .iter()
 8178            .map(|s| {
 8179                let range = s.display_range(&display_map).sorted();
 8180                let mut start = range.start.to_point(&display_map);
 8181                let mut end = range.end.to_point(&display_map);
 8182                start.column = 0;
 8183                end.column = buffer.line_len(end.row);
 8184                start..end
 8185            })
 8186            .collect::<Vec<_>>();
 8187
 8188        self.unfold_ranges(ranges, true, true, cx);
 8189    }
 8190
 8191    pub fn unfold_at(&mut self, unfold_at: &UnfoldAt, cx: &mut ViewContext<Self>) {
 8192        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8193
 8194        let intersection_range = Point::new(unfold_at.buffer_row, 0)
 8195            ..Point::new(
 8196                unfold_at.buffer_row,
 8197                display_map.buffer_snapshot.line_len(unfold_at.buffer_row),
 8198            );
 8199
 8200        let autoscroll = self
 8201            .selections
 8202            .all::<Point>(cx)
 8203            .iter()
 8204            .any(|selection| selection.range().overlaps(&intersection_range));
 8205
 8206        self.unfold_ranges(std::iter::once(intersection_range), true, autoscroll, cx)
 8207    }
 8208
 8209    pub fn fold_selected_ranges(&mut self, _: &FoldSelectedRanges, cx: &mut ViewContext<Self>) {
 8210        let selections = self.selections.all::<Point>(cx);
 8211        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8212        let line_mode = self.selections.line_mode;
 8213        let ranges = selections.into_iter().map(|s| {
 8214            if line_mode {
 8215                let start = Point::new(s.start.row, 0);
 8216                let end = Point::new(s.end.row, display_map.buffer_snapshot.line_len(s.end.row));
 8217                start..end
 8218            } else {
 8219                s.start..s.end
 8220            }
 8221        });
 8222        self.fold_ranges(ranges, true, cx);
 8223    }
 8224
 8225    pub fn fold_ranges<T: ToOffset + Clone>(
 8226        &mut self,
 8227        ranges: impl IntoIterator<Item = Range<T>>,
 8228        auto_scroll: bool,
 8229        cx: &mut ViewContext<Self>,
 8230    ) {
 8231        let mut ranges = ranges.into_iter().peekable();
 8232        if ranges.peek().is_some() {
 8233            self.display_map.update(cx, |map, cx| map.fold(ranges, cx));
 8234
 8235            if auto_scroll {
 8236                self.request_autoscroll(Autoscroll::fit(), cx);
 8237            }
 8238
 8239            cx.notify();
 8240        }
 8241    }
 8242
 8243    pub fn unfold_ranges<T: ToOffset + Clone>(
 8244        &mut self,
 8245        ranges: impl IntoIterator<Item = Range<T>>,
 8246        inclusive: bool,
 8247        auto_scroll: bool,
 8248        cx: &mut ViewContext<Self>,
 8249    ) {
 8250        let mut ranges = ranges.into_iter().peekable();
 8251        if ranges.peek().is_some() {
 8252            self.display_map
 8253                .update(cx, |map, cx| map.unfold(ranges, inclusive, cx));
 8254            if auto_scroll {
 8255                self.request_autoscroll(Autoscroll::fit(), cx);
 8256            }
 8257
 8258            cx.notify();
 8259        }
 8260    }
 8261
 8262    pub fn set_gutter_hovered(&mut self, hovered: bool, cx: &mut ViewContext<Self>) {
 8263        if hovered != self.gutter_hovered {
 8264            self.gutter_hovered = hovered;
 8265            cx.notify();
 8266        }
 8267    }
 8268
 8269    pub fn insert_blocks(
 8270        &mut self,
 8271        blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
 8272        autoscroll: Option<Autoscroll>,
 8273        cx: &mut ViewContext<Self>,
 8274    ) -> Vec<BlockId> {
 8275        let blocks = self
 8276            .display_map
 8277            .update(cx, |display_map, cx| display_map.insert_blocks(blocks, cx));
 8278        if let Some(autoscroll) = autoscroll {
 8279            self.request_autoscroll(autoscroll, cx);
 8280        }
 8281        blocks
 8282    }
 8283
 8284    pub fn replace_blocks(
 8285        &mut self,
 8286        blocks: HashMap<BlockId, RenderBlock>,
 8287        autoscroll: Option<Autoscroll>,
 8288        cx: &mut ViewContext<Self>,
 8289    ) {
 8290        self.display_map
 8291            .update(cx, |display_map, _| display_map.replace_blocks(blocks));
 8292        if let Some(autoscroll) = autoscroll {
 8293            self.request_autoscroll(autoscroll, cx);
 8294        }
 8295    }
 8296
 8297    pub fn remove_blocks(
 8298        &mut self,
 8299        block_ids: HashSet<BlockId>,
 8300        autoscroll: Option<Autoscroll>,
 8301        cx: &mut ViewContext<Self>,
 8302    ) {
 8303        self.display_map.update(cx, |display_map, cx| {
 8304            display_map.remove_blocks(block_ids, cx)
 8305        });
 8306        if let Some(autoscroll) = autoscroll {
 8307            self.request_autoscroll(autoscroll, cx);
 8308        }
 8309    }
 8310
 8311    pub fn longest_row(&self, cx: &mut AppContext) -> u32 {
 8312        self.display_map
 8313            .update(cx, |map, cx| map.snapshot(cx))
 8314            .longest_row()
 8315    }
 8316
 8317    pub fn max_point(&self, cx: &mut AppContext) -> DisplayPoint {
 8318        self.display_map
 8319            .update(cx, |map, cx| map.snapshot(cx))
 8320            .max_point()
 8321    }
 8322
 8323    pub fn text(&self, cx: &AppContext) -> String {
 8324        self.buffer.read(cx).read(cx).text()
 8325    }
 8326
 8327    pub fn set_text(&mut self, text: impl Into<Arc<str>>, cx: &mut ViewContext<Self>) {
 8328        self.transact(cx, |this, cx| {
 8329            this.buffer
 8330                .read(cx)
 8331                .as_singleton()
 8332                .expect("you can only call set_text on editors for singleton buffers")
 8333                .update(cx, |buffer, cx| buffer.set_text(text, cx));
 8334        });
 8335    }
 8336
 8337    pub fn display_text(&self, cx: &mut AppContext) -> String {
 8338        self.display_map
 8339            .update(cx, |map, cx| map.snapshot(cx))
 8340            .text()
 8341    }
 8342
 8343    pub fn wrap_guides(&self, cx: &AppContext) -> SmallVec<[(usize, bool); 2]> {
 8344        let mut wrap_guides = smallvec::smallvec![];
 8345
 8346        if self.show_wrap_guides == Some(false) {
 8347            return wrap_guides;
 8348        }
 8349
 8350        let settings = self.buffer.read(cx).settings_at(0, cx);
 8351        if settings.show_wrap_guides {
 8352            if let SoftWrap::Column(soft_wrap) = self.soft_wrap_mode(cx) {
 8353                wrap_guides.push((soft_wrap as usize, true));
 8354            }
 8355            wrap_guides.extend(settings.wrap_guides.iter().map(|guide| (*guide, false)))
 8356        }
 8357
 8358        wrap_guides
 8359    }
 8360
 8361    pub fn soft_wrap_mode(&self, cx: &AppContext) -> SoftWrap {
 8362        let settings = self.buffer.read(cx).settings_at(0, cx);
 8363        let mode = self
 8364            .soft_wrap_mode_override
 8365            .unwrap_or_else(|| settings.soft_wrap);
 8366        match mode {
 8367            language_settings::SoftWrap::None => SoftWrap::None,
 8368            language_settings::SoftWrap::EditorWidth => SoftWrap::EditorWidth,
 8369            language_settings::SoftWrap::PreferredLineLength => {
 8370                SoftWrap::Column(settings.preferred_line_length)
 8371            }
 8372        }
 8373    }
 8374
 8375    pub fn set_soft_wrap_mode(
 8376        &mut self,
 8377        mode: language_settings::SoftWrap,
 8378        cx: &mut ViewContext<Self>,
 8379    ) {
 8380        self.soft_wrap_mode_override = Some(mode);
 8381        cx.notify();
 8382    }
 8383
 8384    pub fn set_wrap_width(&self, width: Option<Pixels>, cx: &mut AppContext) -> bool {
 8385        self.display_map
 8386            .update(cx, |map, cx| map.set_wrap_width(width, cx))
 8387    }
 8388
 8389    pub fn toggle_soft_wrap(&mut self, _: &ToggleSoftWrap, cx: &mut ViewContext<Self>) {
 8390        if self.soft_wrap_mode_override.is_some() {
 8391            self.soft_wrap_mode_override.take();
 8392        } else {
 8393            let soft_wrap = match self.soft_wrap_mode(cx) {
 8394                SoftWrap::None => language_settings::SoftWrap::EditorWidth,
 8395                SoftWrap::EditorWidth | SoftWrap::Column(_) => language_settings::SoftWrap::None,
 8396            };
 8397            self.soft_wrap_mode_override = Some(soft_wrap);
 8398        }
 8399        cx.notify();
 8400    }
 8401
 8402    pub fn set_show_gutter(&mut self, show_gutter: bool, cx: &mut ViewContext<Self>) {
 8403        self.show_gutter = show_gutter;
 8404        cx.notify();
 8405    }
 8406
 8407    pub fn set_show_wrap_guides(&mut self, show_gutter: bool, cx: &mut ViewContext<Self>) {
 8408        self.show_wrap_guides = Some(show_gutter);
 8409        cx.notify();
 8410    }
 8411
 8412    pub fn reveal_in_finder(&mut self, _: &RevealInFinder, cx: &mut ViewContext<Self>) {
 8413        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
 8414            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
 8415                cx.reveal_path(&file.abs_path(cx));
 8416            }
 8417        }
 8418    }
 8419
 8420    pub fn copy_path(&mut self, _: &CopyPath, cx: &mut ViewContext<Self>) {
 8421        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
 8422            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
 8423                if let Some(path) = file.abs_path(cx).to_str() {
 8424                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
 8425                }
 8426            }
 8427        }
 8428    }
 8429
 8430    pub fn copy_relative_path(&mut self, _: &CopyRelativePath, cx: &mut ViewContext<Self>) {
 8431        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
 8432            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
 8433                if let Some(path) = file.path().to_str() {
 8434                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
 8435                }
 8436            }
 8437        }
 8438    }
 8439
 8440    pub fn highlight_rows(&mut self, rows: Option<Range<u32>>) {
 8441        self.highlighted_rows = rows;
 8442    }
 8443
 8444    pub fn highlighted_rows(&self) -> Option<Range<u32>> {
 8445        self.highlighted_rows.clone()
 8446    }
 8447
 8448    pub fn highlight_background<T: 'static>(
 8449        &mut self,
 8450        ranges: Vec<Range<Anchor>>,
 8451        color_fetcher: fn(&ThemeColors) -> Hsla,
 8452        cx: &mut ViewContext<Self>,
 8453    ) {
 8454        self.background_highlights
 8455            .insert(TypeId::of::<T>(), (color_fetcher, ranges));
 8456        cx.notify();
 8457    }
 8458
 8459    pub fn highlight_inlay_background<T: 'static>(
 8460        &mut self,
 8461        ranges: Vec<InlayHighlight>,
 8462        color_fetcher: fn(&ThemeColors) -> Hsla,
 8463        cx: &mut ViewContext<Self>,
 8464    ) {
 8465        // TODO: no actual highlights happen for inlays currently, find a way to do that
 8466        self.inlay_background_highlights
 8467            .insert(Some(TypeId::of::<T>()), (color_fetcher, ranges));
 8468        cx.notify();
 8469    }
 8470
 8471    pub fn clear_background_highlights<T: 'static>(
 8472        &mut self,
 8473        cx: &mut ViewContext<Self>,
 8474    ) -> Option<BackgroundHighlight> {
 8475        let text_highlights = self.background_highlights.remove(&TypeId::of::<T>());
 8476        let inlay_highlights = self
 8477            .inlay_background_highlights
 8478            .remove(&Some(TypeId::of::<T>()));
 8479        if text_highlights.is_some() || inlay_highlights.is_some() {
 8480            cx.notify();
 8481        }
 8482        text_highlights
 8483    }
 8484
 8485    #[cfg(feature = "test-support")]
 8486    pub fn all_text_background_highlights(
 8487        &mut self,
 8488        cx: &mut ViewContext<Self>,
 8489    ) -> Vec<(Range<DisplayPoint>, Hsla)> {
 8490        let snapshot = self.snapshot(cx);
 8491        let buffer = &snapshot.buffer_snapshot;
 8492        let start = buffer.anchor_before(0);
 8493        let end = buffer.anchor_after(buffer.len());
 8494        let theme = cx.theme().colors();
 8495        self.background_highlights_in_range(start..end, &snapshot, theme)
 8496    }
 8497
 8498    fn document_highlights_for_position<'a>(
 8499        &'a self,
 8500        position: Anchor,
 8501        buffer: &'a MultiBufferSnapshot,
 8502    ) -> impl 'a + Iterator<Item = &Range<Anchor>> {
 8503        let read_highlights = self
 8504            .background_highlights
 8505            .get(&TypeId::of::<DocumentHighlightRead>())
 8506            .map(|h| &h.1);
 8507        let write_highlights = self
 8508            .background_highlights
 8509            .get(&TypeId::of::<DocumentHighlightWrite>())
 8510            .map(|h| &h.1);
 8511        let left_position = position.bias_left(buffer);
 8512        let right_position = position.bias_right(buffer);
 8513        read_highlights
 8514            .into_iter()
 8515            .chain(write_highlights)
 8516            .flat_map(move |ranges| {
 8517                let start_ix = match ranges.binary_search_by(|probe| {
 8518                    let cmp = probe.end.cmp(&left_position, buffer);
 8519                    if cmp.is_ge() {
 8520                        Ordering::Greater
 8521                    } else {
 8522                        Ordering::Less
 8523                    }
 8524                }) {
 8525                    Ok(i) | Err(i) => i,
 8526                };
 8527
 8528                let right_position = right_position.clone();
 8529                ranges[start_ix..]
 8530                    .iter()
 8531                    .take_while(move |range| range.start.cmp(&right_position, buffer).is_le())
 8532            })
 8533    }
 8534
 8535    pub fn background_highlights_in_range(
 8536        &self,
 8537        search_range: Range<Anchor>,
 8538        display_snapshot: &DisplaySnapshot,
 8539        theme: &ThemeColors,
 8540    ) -> Vec<(Range<DisplayPoint>, Hsla)> {
 8541        let mut results = Vec::new();
 8542        for (color_fetcher, ranges) in self.background_highlights.values() {
 8543            let color = color_fetcher(theme);
 8544            let start_ix = match ranges.binary_search_by(|probe| {
 8545                let cmp = probe
 8546                    .end
 8547                    .cmp(&search_range.start, &display_snapshot.buffer_snapshot);
 8548                if cmp.is_gt() {
 8549                    Ordering::Greater
 8550                } else {
 8551                    Ordering::Less
 8552                }
 8553            }) {
 8554                Ok(i) | Err(i) => i,
 8555            };
 8556            for range in &ranges[start_ix..] {
 8557                if range
 8558                    .start
 8559                    .cmp(&search_range.end, &display_snapshot.buffer_snapshot)
 8560                    .is_ge()
 8561                {
 8562                    break;
 8563                }
 8564
 8565                let start = range.start.to_display_point(&display_snapshot);
 8566                let end = range.end.to_display_point(&display_snapshot);
 8567                results.push((start..end, color))
 8568            }
 8569        }
 8570        results
 8571    }
 8572
 8573    pub fn background_highlight_row_ranges<T: 'static>(
 8574        &self,
 8575        search_range: Range<Anchor>,
 8576        display_snapshot: &DisplaySnapshot,
 8577        count: usize,
 8578    ) -> Vec<RangeInclusive<DisplayPoint>> {
 8579        let mut results = Vec::new();
 8580        let Some((_, ranges)) = self.background_highlights.get(&TypeId::of::<T>()) else {
 8581            return vec![];
 8582        };
 8583
 8584        let start_ix = match ranges.binary_search_by(|probe| {
 8585            let cmp = probe
 8586                .end
 8587                .cmp(&search_range.start, &display_snapshot.buffer_snapshot);
 8588            if cmp.is_gt() {
 8589                Ordering::Greater
 8590            } else {
 8591                Ordering::Less
 8592            }
 8593        }) {
 8594            Ok(i) | Err(i) => i,
 8595        };
 8596        let mut push_region = |start: Option<Point>, end: Option<Point>| {
 8597            if let (Some(start_display), Some(end_display)) = (start, end) {
 8598                results.push(
 8599                    start_display.to_display_point(display_snapshot)
 8600                        ..=end_display.to_display_point(display_snapshot),
 8601                );
 8602            }
 8603        };
 8604        let mut start_row: Option<Point> = None;
 8605        let mut end_row: Option<Point> = None;
 8606        if ranges.len() > count {
 8607            return Vec::new();
 8608        }
 8609        for range in &ranges[start_ix..] {
 8610            if range
 8611                .start
 8612                .cmp(&search_range.end, &display_snapshot.buffer_snapshot)
 8613                .is_ge()
 8614            {
 8615                break;
 8616            }
 8617            let end = range.end.to_point(&display_snapshot.buffer_snapshot);
 8618            if let Some(current_row) = &end_row {
 8619                if end.row == current_row.row {
 8620                    continue;
 8621                }
 8622            }
 8623            let start = range.start.to_point(&display_snapshot.buffer_snapshot);
 8624            if start_row.is_none() {
 8625                assert_eq!(end_row, None);
 8626                start_row = Some(start);
 8627                end_row = Some(end);
 8628                continue;
 8629            }
 8630            if let Some(current_end) = end_row.as_mut() {
 8631                if start.row > current_end.row + 1 {
 8632                    push_region(start_row, end_row);
 8633                    start_row = Some(start);
 8634                    end_row = Some(end);
 8635                } else {
 8636                    // Merge two hunks.
 8637                    *current_end = end;
 8638                }
 8639            } else {
 8640                unreachable!();
 8641            }
 8642        }
 8643        // We might still have a hunk that was not rendered (if there was a search hit on the last line)
 8644        push_region(start_row, end_row);
 8645        results
 8646    }
 8647
 8648    pub fn highlight_text<T: 'static>(
 8649        &mut self,
 8650        ranges: Vec<Range<Anchor>>,
 8651        style: HighlightStyle,
 8652        cx: &mut ViewContext<Self>,
 8653    ) {
 8654        self.display_map.update(cx, |map, _| {
 8655            map.highlight_text(TypeId::of::<T>(), ranges, style)
 8656        });
 8657        cx.notify();
 8658    }
 8659
 8660    pub fn highlight_inlays<T: 'static>(
 8661        &mut self,
 8662        highlights: Vec<InlayHighlight>,
 8663        style: HighlightStyle,
 8664        cx: &mut ViewContext<Self>,
 8665    ) {
 8666        self.display_map.update(cx, |map, _| {
 8667            map.highlight_inlays(TypeId::of::<T>(), highlights, style)
 8668        });
 8669        cx.notify();
 8670    }
 8671
 8672    pub fn text_highlights<'a, T: 'static>(
 8673        &'a self,
 8674        cx: &'a AppContext,
 8675    ) -> Option<(HighlightStyle, &'a [Range<Anchor>])> {
 8676        self.display_map.read(cx).text_highlights(TypeId::of::<T>())
 8677    }
 8678
 8679    pub fn clear_highlights<T: 'static>(&mut self, cx: &mut ViewContext<Self>) {
 8680        let cleared = self
 8681            .display_map
 8682            .update(cx, |map, _| map.clear_highlights(TypeId::of::<T>()));
 8683        if cleared {
 8684            cx.notify();
 8685        }
 8686    }
 8687
 8688    pub fn show_local_cursors(&self, cx: &WindowContext) -> bool {
 8689        self.blink_manager.read(cx).visible() && self.focus_handle.is_focused(cx)
 8690    }
 8691
 8692    fn on_buffer_changed(&mut self, _: Model<MultiBuffer>, cx: &mut ViewContext<Self>) {
 8693        cx.notify();
 8694    }
 8695
 8696    fn on_buffer_event(
 8697        &mut self,
 8698        multibuffer: Model<MultiBuffer>,
 8699        event: &multi_buffer::Event,
 8700        cx: &mut ViewContext<Self>,
 8701    ) {
 8702        match event {
 8703            multi_buffer::Event::Edited {
 8704                sigleton_buffer_edited,
 8705            } => {
 8706                self.refresh_active_diagnostics(cx);
 8707                self.refresh_code_actions(cx);
 8708                if self.has_active_copilot_suggestion(cx) {
 8709                    self.update_visible_copilot_suggestion(cx);
 8710                }
 8711                cx.emit(Event::BufferEdited);
 8712                cx.emit(ItemEvent::Edit);
 8713                cx.emit(ItemEvent::UpdateBreadcrumbs);
 8714                cx.emit(SearchEvent::MatchesInvalidated);
 8715
 8716                if *sigleton_buffer_edited {
 8717                    if let Some(project) = &self.project {
 8718                        let project = project.read(cx);
 8719                        let languages_affected = multibuffer
 8720                            .read(cx)
 8721                            .all_buffers()
 8722                            .into_iter()
 8723                            .filter_map(|buffer| {
 8724                                let buffer = buffer.read(cx);
 8725                                let language = buffer.language()?;
 8726                                if project.is_local()
 8727                                    && project.language_servers_for_buffer(buffer, cx).count() == 0
 8728                                {
 8729                                    None
 8730                                } else {
 8731                                    Some(language)
 8732                                }
 8733                            })
 8734                            .cloned()
 8735                            .collect::<HashSet<_>>();
 8736                        if !languages_affected.is_empty() {
 8737                            self.refresh_inlay_hints(
 8738                                InlayHintRefreshReason::BufferEdited(languages_affected),
 8739                                cx,
 8740                            );
 8741                        }
 8742                    }
 8743                }
 8744            }
 8745            multi_buffer::Event::ExcerptsAdded {
 8746                buffer,
 8747                predecessor,
 8748                excerpts,
 8749            } => {
 8750                cx.emit(Event::ExcerptsAdded {
 8751                    buffer: buffer.clone(),
 8752                    predecessor: *predecessor,
 8753                    excerpts: excerpts.clone(),
 8754                });
 8755                self.refresh_inlay_hints(InlayHintRefreshReason::NewLinesShown, cx);
 8756            }
 8757            multi_buffer::Event::ExcerptsRemoved { ids } => {
 8758                self.refresh_inlay_hints(InlayHintRefreshReason::ExcerptsRemoved(ids.clone()), cx);
 8759                cx.emit(Event::ExcerptsRemoved { ids: ids.clone() })
 8760            }
 8761            multi_buffer::Event::Reparsed => {
 8762                cx.emit(ItemEvent::UpdateBreadcrumbs);
 8763            }
 8764            multi_buffer::Event::DirtyChanged => {
 8765                cx.emit(ItemEvent::UpdateTab);
 8766            }
 8767            multi_buffer::Event::Saved
 8768            | multi_buffer::Event::FileHandleChanged
 8769            | multi_buffer::Event::Reloaded => {
 8770                cx.emit(ItemEvent::UpdateTab);
 8771                cx.emit(ItemEvent::UpdateBreadcrumbs);
 8772            }
 8773            multi_buffer::Event::DiffBaseChanged => cx.emit(Event::DiffBaseChanged),
 8774            multi_buffer::Event::Closed => cx.emit(ItemEvent::CloseItem),
 8775            multi_buffer::Event::DiagnosticsUpdated => {
 8776                self.refresh_active_diagnostics(cx);
 8777            }
 8778            _ => {}
 8779        };
 8780    }
 8781
 8782    fn on_display_map_changed(&mut self, _: Model<DisplayMap>, cx: &mut ViewContext<Self>) {
 8783        cx.notify();
 8784    }
 8785
 8786    fn settings_changed(&mut self, cx: &mut ViewContext<Self>) {
 8787        self.refresh_copilot_suggestions(true, cx);
 8788        self.refresh_inlay_hints(
 8789            InlayHintRefreshReason::SettingsChange(inlay_hint_settings(
 8790                self.selections.newest_anchor().head(),
 8791                &self.buffer.read(cx).snapshot(cx),
 8792                cx,
 8793            )),
 8794            cx,
 8795        );
 8796    }
 8797
 8798    //     pub fn set_searchable(&mut self, searchable: bool) {
 8799    //         self.searchable = searchable;
 8800    //     }
 8801
 8802    //     pub fn searchable(&self) -> bool {
 8803    //         self.searchable
 8804    //     }
 8805
 8806    //     fn open_excerpts(workspace: &mut Workspace, _: &OpenExcerpts, cx: &mut ViewContext<Workspace>) {
 8807    //         let active_item = workspace.active_item(cx);
 8808    //         let editor_handle = if let Some(editor) = active_item
 8809    //             .as_ref()
 8810    //             .and_then(|item| item.act_as::<Self>(cx))
 8811    //         {
 8812    //             editor
 8813    //         } else {
 8814    //             cx.propagate();
 8815    //             return;
 8816    //         };
 8817
 8818    //         let editor = editor_handle.read(cx);
 8819    //         let buffer = editor.buffer.read(cx);
 8820    //         if buffer.is_singleton() {
 8821    //             cx.propagate();
 8822    //             return;
 8823    //         }
 8824
 8825    //         let mut new_selections_by_buffer = HashMap::default();
 8826    //         for selection in editor.selections.all::<usize>(cx) {
 8827    //             for (buffer, mut range, _) in
 8828    //                 buffer.range_to_buffer_ranges(selection.start..selection.end, cx)
 8829    //             {
 8830    //                 if selection.reversed {
 8831    //                     mem::swap(&mut range.start, &mut range.end);
 8832    //                 }
 8833    //                 new_selections_by_buffer
 8834    //                     .entry(buffer)
 8835    //                     .or_insert(Vec::new())
 8836    //                     .push(range)
 8837    //             }
 8838    //         }
 8839
 8840    //         editor_handle.update(cx, |editor, cx| {
 8841    //             editor.push_to_nav_history(editor.selections.newest_anchor().head(), None, cx);
 8842    //         });
 8843    //         let pane = workspace.active_pane().clone();
 8844    //         pane.update(cx, |pane, _| pane.disable_history());
 8845
 8846    //         // We defer the pane interaction because we ourselves are a workspace item
 8847    //         // and activating a new item causes the pane to call a method on us reentrantly,
 8848    //         // which panics if we're on the stack.
 8849    //         cx.defer(move |workspace, cx| {
 8850    //             for (buffer, ranges) in new_selections_by_buffer.into_iter() {
 8851    //                 let editor = workspace.open_project_item::<Self>(buffer, cx);
 8852    //                 editor.update(cx, |editor, cx| {
 8853    //                     editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
 8854    //                         s.select_ranges(ranges);
 8855    //                     });
 8856    //                 });
 8857    //             }
 8858
 8859    //             pane.update(cx, |pane, _| pane.enable_history());
 8860    //         });
 8861    //     }
 8862
 8863    fn jump(
 8864        &mut self,
 8865        path: ProjectPath,
 8866        position: Point,
 8867        anchor: language::Anchor,
 8868        cx: &mut ViewContext<Self>,
 8869    ) {
 8870        let workspace = self.workspace();
 8871        cx.spawn(|_, mut cx| async move {
 8872            let workspace = workspace.ok_or_else(|| anyhow!("cannot jump without workspace"))?;
 8873            let editor = workspace.update(&mut cx, |workspace, cx| {
 8874                workspace.open_path(path, None, true, cx)
 8875            })?;
 8876            let editor = editor
 8877                .await?
 8878                .downcast::<Editor>()
 8879                .ok_or_else(|| anyhow!("opened item was not an editor"))?
 8880                .downgrade();
 8881            editor.update(&mut cx, |editor, cx| {
 8882                let buffer = editor
 8883                    .buffer()
 8884                    .read(cx)
 8885                    .as_singleton()
 8886                    .ok_or_else(|| anyhow!("cannot jump in a multi-buffer"))?;
 8887                let buffer = buffer.read(cx);
 8888                let cursor = if buffer.can_resolve(&anchor) {
 8889                    language::ToPoint::to_point(&anchor, buffer)
 8890                } else {
 8891                    buffer.clip_point(position, Bias::Left)
 8892                };
 8893
 8894                let nav_history = editor.nav_history.take();
 8895                editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
 8896                    s.select_ranges([cursor..cursor]);
 8897                });
 8898                editor.nav_history = nav_history;
 8899
 8900                anyhow::Ok(())
 8901            })??;
 8902
 8903            anyhow::Ok(())
 8904        })
 8905        .detach_and_log_err(cx);
 8906    }
 8907
 8908    fn marked_text_ranges(&self, cx: &AppContext) -> Option<Vec<Range<OffsetUtf16>>> {
 8909        let snapshot = self.buffer.read(cx).read(cx);
 8910        let (_, ranges) = self.text_highlights::<InputComposition>(cx)?;
 8911        Some(
 8912            ranges
 8913                .iter()
 8914                .map(move |range| {
 8915                    range.start.to_offset_utf16(&snapshot)..range.end.to_offset_utf16(&snapshot)
 8916                })
 8917                .collect(),
 8918        )
 8919    }
 8920
 8921    fn selection_replacement_ranges(
 8922        &self,
 8923        range: Range<OffsetUtf16>,
 8924        cx: &AppContext,
 8925    ) -> Vec<Range<OffsetUtf16>> {
 8926        let selections = self.selections.all::<OffsetUtf16>(cx);
 8927        let newest_selection = selections
 8928            .iter()
 8929            .max_by_key(|selection| selection.id)
 8930            .unwrap();
 8931        let start_delta = range.start.0 as isize - newest_selection.start.0 as isize;
 8932        let end_delta = range.end.0 as isize - newest_selection.end.0 as isize;
 8933        let snapshot = self.buffer.read(cx).read(cx);
 8934        selections
 8935            .into_iter()
 8936            .map(|mut selection| {
 8937                selection.start.0 =
 8938                    (selection.start.0 as isize).saturating_add(start_delta) as usize;
 8939                selection.end.0 = (selection.end.0 as isize).saturating_add(end_delta) as usize;
 8940                snapshot.clip_offset_utf16(selection.start, Bias::Left)
 8941                    ..snapshot.clip_offset_utf16(selection.end, Bias::Right)
 8942            })
 8943            .collect()
 8944    }
 8945
 8946    fn report_copilot_event(
 8947        &self,
 8948        suggestion_id: Option<String>,
 8949        suggestion_accepted: bool,
 8950        cx: &AppContext,
 8951    ) {
 8952        let Some(project) = &self.project else { return };
 8953
 8954        // If None, we are either getting suggestions in a new, unsaved file, or in a file without an extension
 8955        let file_extension = self
 8956            .buffer
 8957            .read(cx)
 8958            .as_singleton()
 8959            .and_then(|b| b.read(cx).file())
 8960            .and_then(|file| Path::new(file.file_name(cx)).extension())
 8961            .and_then(|e| e.to_str())
 8962            .map(|a| a.to_string());
 8963
 8964        let telemetry = project.read(cx).client().telemetry().clone();
 8965        let telemetry_settings = *TelemetrySettings::get_global(cx);
 8966
 8967        let event = ClickhouseEvent::Copilot {
 8968            suggestion_id,
 8969            suggestion_accepted,
 8970            file_extension,
 8971        };
 8972        telemetry.report_clickhouse_event(event, telemetry_settings);
 8973    }
 8974
 8975    #[cfg(any(test, feature = "test-support"))]
 8976    fn report_editor_event(
 8977        &self,
 8978        _operation: &'static str,
 8979        _file_extension: Option<String>,
 8980        _cx: &AppContext,
 8981    ) {
 8982    }
 8983
 8984    #[cfg(not(any(test, feature = "test-support")))]
 8985    fn report_editor_event(
 8986        &self,
 8987        operation: &'static str,
 8988        file_extension: Option<String>,
 8989        cx: &AppContext,
 8990    ) {
 8991        let Some(project) = &self.project else { return };
 8992
 8993        // If None, we are in a file without an extension
 8994        let file = self
 8995            .buffer
 8996            .read(cx)
 8997            .as_singleton()
 8998            .and_then(|b| b.read(cx).file());
 8999        let file_extension = file_extension.or(file
 9000            .as_ref()
 9001            .and_then(|file| Path::new(file.file_name(cx)).extension())
 9002            .and_then(|e| e.to_str())
 9003            .map(|a| a.to_string()));
 9004
 9005        let vim_mode = cx
 9006            .global::<SettingsStore>()
 9007            .raw_user_settings()
 9008            .get("vim_mode")
 9009            == Some(&serde_json::Value::Bool(true));
 9010        let telemetry_settings = *TelemetrySettings::get_global(cx);
 9011        let copilot_enabled = all_language_settings(file, cx).copilot_enabled(None, None);
 9012        let copilot_enabled_for_language = self
 9013            .buffer
 9014            .read(cx)
 9015            .settings_at(0, cx)
 9016            .show_copilot_suggestions;
 9017
 9018        let telemetry = project.read(cx).client().telemetry().clone();
 9019        let event = ClickhouseEvent::Editor {
 9020            file_extension,
 9021            vim_mode,
 9022            operation,
 9023            copilot_enabled,
 9024            copilot_enabled_for_language,
 9025        };
 9026        telemetry.report_clickhouse_event(event, telemetry_settings)
 9027    }
 9028
 9029    /// Copy the highlighted chunks to the clipboard as JSON. The format is an array of lines,
 9030    /// with each line being an array of {text, highlight} objects.
 9031    fn copy_highlight_json(&mut self, _: &CopyHighlightJson, cx: &mut ViewContext<Self>) {
 9032        let Some(buffer) = self.buffer.read(cx).as_singleton() else {
 9033            return;
 9034        };
 9035
 9036        #[derive(Serialize)]
 9037        struct Chunk<'a> {
 9038            text: String,
 9039            highlight: Option<&'a str>,
 9040        }
 9041
 9042        let snapshot = buffer.read(cx).snapshot();
 9043        let range = self
 9044            .selected_text_range(cx)
 9045            .and_then(|selected_range| {
 9046                if selected_range.is_empty() {
 9047                    None
 9048                } else {
 9049                    Some(selected_range)
 9050                }
 9051            })
 9052            .unwrap_or_else(|| 0..snapshot.len());
 9053
 9054        let chunks = snapshot.chunks(range, true);
 9055        let mut lines = Vec::new();
 9056        let mut line: VecDeque<Chunk> = VecDeque::new();
 9057
 9058        let Some(style) = self.style.as_ref() else {
 9059            return;
 9060        };
 9061
 9062        for chunk in chunks {
 9063            let highlight = chunk
 9064                .syntax_highlight_id
 9065                .and_then(|id| id.name(&style.syntax));
 9066            let mut chunk_lines = chunk.text.split("\n").peekable();
 9067            while let Some(text) = chunk_lines.next() {
 9068                let mut merged_with_last_token = false;
 9069                if let Some(last_token) = line.back_mut() {
 9070                    if last_token.highlight == highlight {
 9071                        last_token.text.push_str(text);
 9072                        merged_with_last_token = true;
 9073                    }
 9074                }
 9075
 9076                if !merged_with_last_token {
 9077                    line.push_back(Chunk {
 9078                        text: text.into(),
 9079                        highlight,
 9080                    });
 9081                }
 9082
 9083                if chunk_lines.peek().is_some() {
 9084                    if line.len() > 1 && line.front().unwrap().text.is_empty() {
 9085                        line.pop_front();
 9086                    }
 9087                    if line.len() > 1 && line.back().unwrap().text.is_empty() {
 9088                        line.pop_back();
 9089                    }
 9090
 9091                    lines.push(mem::take(&mut line));
 9092                }
 9093            }
 9094        }
 9095
 9096        let Some(lines) = serde_json::to_string_pretty(&lines).log_err() else {
 9097            return;
 9098        };
 9099        cx.write_to_clipboard(ClipboardItem::new(lines));
 9100    }
 9101
 9102    pub fn inlay_hint_cache(&self) -> &InlayHintCache {
 9103        &self.inlay_hint_cache
 9104    }
 9105
 9106    pub fn replay_insert_event(
 9107        &mut self,
 9108        text: &str,
 9109        relative_utf16_range: Option<Range<isize>>,
 9110        cx: &mut ViewContext<Self>,
 9111    ) {
 9112        if !self.input_enabled {
 9113            cx.emit(Event::InputIgnored { text: text.into() });
 9114            return;
 9115        }
 9116        if let Some(relative_utf16_range) = relative_utf16_range {
 9117            let selections = self.selections.all::<OffsetUtf16>(cx);
 9118            self.change_selections(None, cx, |s| {
 9119                let new_ranges = selections.into_iter().map(|range| {
 9120                    let start = OffsetUtf16(
 9121                        range
 9122                            .head()
 9123                            .0
 9124                            .saturating_add_signed(relative_utf16_range.start),
 9125                    );
 9126                    let end = OffsetUtf16(
 9127                        range
 9128                            .head()
 9129                            .0
 9130                            .saturating_add_signed(relative_utf16_range.end),
 9131                    );
 9132                    start..end
 9133                });
 9134                s.select_ranges(new_ranges);
 9135            });
 9136        }
 9137
 9138        self.handle_input(text, cx);
 9139    }
 9140
 9141    pub fn supports_inlay_hints(&self, cx: &AppContext) -> bool {
 9142        let Some(project) = self.project.as_ref() else {
 9143            return false;
 9144        };
 9145        let project = project.read(cx);
 9146
 9147        let mut supports = false;
 9148        self.buffer().read(cx).for_each_buffer(|buffer| {
 9149            if !supports {
 9150                supports = project
 9151                    .language_servers_for_buffer(buffer.read(cx), cx)
 9152                    .any(
 9153                        |(_, server)| match server.capabilities().inlay_hint_provider {
 9154                            Some(lsp::OneOf::Left(enabled)) => enabled,
 9155                            Some(lsp::OneOf::Right(_)) => true,
 9156                            None => false,
 9157                        },
 9158                    )
 9159            }
 9160        });
 9161        supports
 9162    }
 9163
 9164    pub fn focus(&self, cx: &mut WindowContext) {
 9165        cx.focus(&self.focus_handle)
 9166    }
 9167
 9168    pub fn is_focused(&self, cx: &WindowContext) -> bool {
 9169        self.focus_handle.is_focused(cx)
 9170    }
 9171
 9172    fn handle_focus(&mut self, cx: &mut ViewContext<Self>) {
 9173        cx.emit(Event::Focused);
 9174
 9175        if let Some(rename) = self.pending_rename.as_ref() {
 9176            let rename_editor_focus_handle = rename.editor.read(cx).focus_handle.clone();
 9177            cx.focus(&rename_editor_focus_handle);
 9178        } else {
 9179            self.blink_manager.update(cx, BlinkManager::enable);
 9180            self.buffer.update(cx, |buffer, cx| {
 9181                buffer.finalize_last_transaction(cx);
 9182                if self.leader_peer_id.is_none() {
 9183                    buffer.set_active_selections(
 9184                        &self.selections.disjoint_anchors(),
 9185                        self.selections.line_mode,
 9186                        self.cursor_shape,
 9187                        cx,
 9188                    );
 9189                }
 9190            });
 9191        }
 9192    }
 9193
 9194    fn handle_blur(&mut self, cx: &mut ViewContext<Self>) {
 9195        // todo!()
 9196        // let blurred_event = EditorBlurred(cx.handle());
 9197        // cx.emit_global(blurred_event);
 9198        self.blink_manager.update(cx, BlinkManager::disable);
 9199        self.buffer
 9200            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
 9201        self.hide_context_menu(cx);
 9202        hide_hover(self, cx);
 9203        cx.emit(Event::Blurred);
 9204        cx.notify();
 9205    }
 9206}
 9207
 9208pub trait CollaborationHub {
 9209    fn collaborators<'a>(&self, cx: &'a AppContext) -> &'a HashMap<PeerId, Collaborator>;
 9210    fn user_participant_indices<'a>(
 9211        &self,
 9212        cx: &'a AppContext,
 9213    ) -> &'a HashMap<u64, ParticipantIndex>;
 9214}
 9215
 9216impl CollaborationHub for Model<Project> {
 9217    fn collaborators<'a>(&self, cx: &'a AppContext) -> &'a HashMap<PeerId, Collaborator> {
 9218        self.read(cx).collaborators()
 9219    }
 9220
 9221    fn user_participant_indices<'a>(
 9222        &self,
 9223        cx: &'a AppContext,
 9224    ) -> &'a HashMap<u64, ParticipantIndex> {
 9225        self.read(cx).user_store().read(cx).participant_indices()
 9226    }
 9227}
 9228
 9229fn inlay_hint_settings(
 9230    location: Anchor,
 9231    snapshot: &MultiBufferSnapshot,
 9232    cx: &mut ViewContext<'_, Editor>,
 9233) -> InlayHintSettings {
 9234    let file = snapshot.file_at(location);
 9235    let language = snapshot.language_at(location);
 9236    let settings = all_language_settings(file, cx);
 9237    settings
 9238        .language(language.map(|l| l.name()).as_deref())
 9239        .inlay_hints
 9240}
 9241
 9242fn consume_contiguous_rows(
 9243    contiguous_row_selections: &mut Vec<Selection<Point>>,
 9244    selection: &Selection<Point>,
 9245    display_map: &DisplaySnapshot,
 9246    selections: &mut std::iter::Peekable<std::slice::Iter<Selection<Point>>>,
 9247) -> (u32, u32) {
 9248    contiguous_row_selections.push(selection.clone());
 9249    let start_row = selection.start.row;
 9250    let mut end_row = ending_row(selection, display_map);
 9251
 9252    while let Some(next_selection) = selections.peek() {
 9253        if next_selection.start.row <= end_row {
 9254            end_row = ending_row(next_selection, display_map);
 9255            contiguous_row_selections.push(selections.next().unwrap().clone());
 9256        } else {
 9257            break;
 9258        }
 9259    }
 9260    (start_row, end_row)
 9261}
 9262
 9263fn ending_row(next_selection: &Selection<Point>, display_map: &DisplaySnapshot) -> u32 {
 9264    if next_selection.end.column > 0 || next_selection.is_empty() {
 9265        display_map.next_line_boundary(next_selection.end).0.row + 1
 9266    } else {
 9267        next_selection.end.row
 9268    }
 9269}
 9270
 9271impl EditorSnapshot {
 9272    pub fn remote_selections_in_range<'a>(
 9273        &'a self,
 9274        range: &'a Range<Anchor>,
 9275        collaboration_hub: &dyn CollaborationHub,
 9276        cx: &'a AppContext,
 9277    ) -> impl 'a + Iterator<Item = RemoteSelection> {
 9278        let participant_indices = collaboration_hub.user_participant_indices(cx);
 9279        let collaborators_by_peer_id = collaboration_hub.collaborators(cx);
 9280        let collaborators_by_replica_id = collaborators_by_peer_id
 9281            .iter()
 9282            .map(|(_, collaborator)| (collaborator.replica_id, collaborator))
 9283            .collect::<HashMap<_, _>>();
 9284        self.buffer_snapshot
 9285            .remote_selections_in_range(range)
 9286            .filter_map(move |(replica_id, line_mode, cursor_shape, selection)| {
 9287                let collaborator = collaborators_by_replica_id.get(&replica_id)?;
 9288                let participant_index = participant_indices.get(&collaborator.user_id).copied();
 9289                Some(RemoteSelection {
 9290                    replica_id,
 9291                    selection,
 9292                    cursor_shape,
 9293                    line_mode,
 9294                    participant_index,
 9295                    peer_id: collaborator.peer_id,
 9296                })
 9297            })
 9298    }
 9299
 9300    pub fn language_at<T: ToOffset>(&self, position: T) -> Option<&Arc<Language>> {
 9301        self.display_snapshot.buffer_snapshot.language_at(position)
 9302    }
 9303
 9304    pub fn is_focused(&self) -> bool {
 9305        self.is_focused
 9306    }
 9307
 9308    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
 9309        self.placeholder_text.as_ref()
 9310    }
 9311
 9312    pub fn scroll_position(&self) -> gpui::Point<f32> {
 9313        self.scroll_anchor.scroll_position(&self.display_snapshot)
 9314    }
 9315}
 9316
 9317impl Deref for EditorSnapshot {
 9318    type Target = DisplaySnapshot;
 9319
 9320    fn deref(&self) -> &Self::Target {
 9321        &self.display_snapshot
 9322    }
 9323}
 9324
 9325#[derive(Clone, Debug, PartialEq, Eq)]
 9326pub enum Event {
 9327    InputIgnored {
 9328        text: Arc<str>,
 9329    },
 9330    InputHandled {
 9331        utf16_range_to_replace: Option<Range<isize>>,
 9332        text: Arc<str>,
 9333    },
 9334    ExcerptsAdded {
 9335        buffer: Model<Buffer>,
 9336        predecessor: ExcerptId,
 9337        excerpts: Vec<(ExcerptId, ExcerptRange<language::Anchor>)>,
 9338    },
 9339    ExcerptsRemoved {
 9340        ids: Vec<ExcerptId>,
 9341    },
 9342    BufferEdited,
 9343    Edited,
 9344    Focused,
 9345    Blurred,
 9346    DiffBaseChanged,
 9347    SelectionsChanged {
 9348        local: bool,
 9349    },
 9350    ScrollPositionChanged {
 9351        local: bool,
 9352        autoscroll: bool,
 9353    },
 9354}
 9355
 9356pub struct EditorFocused(pub View<Editor>);
 9357pub struct EditorBlurred(pub View<Editor>);
 9358pub struct EditorReleased(pub WeakView<Editor>);
 9359
 9360// impl Entity for Editor {
 9361//     type Event = Event;
 9362
 9363//     fn release(&mut self, cx: &mut AppContext) {
 9364//         cx.emit_global(EditorReleased(self.handle.clone()));
 9365//     }
 9366// }
 9367//
 9368impl EventEmitter<Event> for Editor {}
 9369
 9370impl Render for Editor {
 9371    type Element = EditorElement;
 9372
 9373    fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
 9374        let settings = ThemeSettings::get_global(cx);
 9375        let text_style = match self.mode {
 9376            EditorMode::SingleLine => {
 9377                TextStyle {
 9378                    color: cx.theme().colors().text,
 9379                    font_family: settings.ui_font.family.clone(), // todo!()
 9380                    font_features: settings.ui_font.features,
 9381                    font_size: rems(0.875).into(),
 9382                    font_weight: FontWeight::NORMAL,
 9383                    font_style: FontStyle::Normal,
 9384                    line_height: relative(1.3).into(), // TODO relative(settings.buffer_line_height.value()),
 9385                    underline: None,
 9386                }
 9387            }
 9388
 9389            EditorMode::AutoHeight { max_lines } => todo!(),
 9390
 9391            EditorMode::Full => TextStyle {
 9392                color: cx.theme().colors().text,
 9393                font_family: settings.buffer_font.family.clone(),
 9394                font_features: settings.buffer_font.features,
 9395                font_size: settings.buffer_font_size.into(),
 9396                font_weight: FontWeight::NORMAL,
 9397                font_style: FontStyle::Normal,
 9398                line_height: relative(settings.buffer_line_height.value()),
 9399                underline: None,
 9400            },
 9401        };
 9402
 9403        let background = match self.mode {
 9404            EditorMode::SingleLine => cx.theme().system().transparent,
 9405            EditorMode::AutoHeight { max_lines } => cx.theme().system().transparent,
 9406            EditorMode::Full => cx.theme().colors().editor_background,
 9407        };
 9408
 9409        EditorElement::new(
 9410            cx.view(),
 9411            EditorStyle {
 9412                background,
 9413                local_player: cx.theme().players().local(),
 9414                text: text_style,
 9415                scrollbar_width: px(12.),
 9416                syntax: cx.theme().syntax().clone(),
 9417                diagnostic_style: cx.theme().diagnostic_style(),
 9418            },
 9419        )
 9420    }
 9421}
 9422
 9423// impl View for Editor {
 9424//     fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
 9425//         let style = self.style(cx);
 9426//         let font_changed = self.display_map.update(cx, |map, cx| {
 9427//             map.set_fold_ellipses_color(style.folds.ellipses.text_color);
 9428//             map.set_font_with_size(style.text.font_id, style.text.font_size, cx)
 9429//         });
 9430
 9431//         if font_changed {
 9432//             cx.defer(move |editor, cx: &mut ViewContext<Editor>| {
 9433//                 hide_hover(editor, cx);
 9434//                 hide_link_definition(editor, cx);
 9435//             });
 9436//         }
 9437
 9438//         Stack::new()
 9439//             .with_child(EditorElement::new(style.clone()))
 9440//             .with_child(ChildView::new(&self.mouse_context_menu, cx))
 9441//             .into_any()
 9442//     }
 9443
 9444//     fn ui_name() -> &'static str {
 9445//         "Editor"
 9446//     }
 9447
 9448//     fn focus_in(&mut self, focused: AnyView, cx: &mut ViewContext<Self>) {
 9449//         if cx.is_self_focused() {
 9450//             let focused_event = EditorFocused(cx.handle());
 9451//             cx.emit(Event::Focused);
 9452//             cx.emit_global(focused_event);
 9453//         }
 9454//         if let Some(rename) = self.pending_rename.as_ref() {
 9455//             cx.focus(&rename.editor);
 9456//         } else if cx.is_self_focused() || !focused.is::<Editor>() {
 9457//             if !self.focused {
 9458//                 self.blink_manager.update(cx, BlinkManager::enable);
 9459//             }
 9460//             self.focused = true;
 9461//             self.buffer.update(cx, |buffer, cx| {
 9462//                 buffer.finalize_last_transaction(cx);
 9463//                 if self.leader_peer_id.is_none() {
 9464//                     buffer.set_active_selections(
 9465//                         &self.selections.disjoint_anchors(),
 9466//                         self.selections.line_mode,
 9467//                         self.cursor_shape,
 9468//                         cx,
 9469//                     );
 9470//                 }
 9471//             });
 9472//         }
 9473//     }
 9474
 9475//     fn focus_out(&mut self, _: AnyView, cx: &mut ViewContext<Self>) {
 9476//         let blurred_event = EditorBlurred(cx.handle());
 9477//         cx.emit_global(blurred_event);
 9478//         self.focused = false;
 9479//         self.blink_manager.update(cx, BlinkManager::disable);
 9480//         self.buffer
 9481//             .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
 9482//         self.hide_context_menu(cx);
 9483//         hide_hover(self, cx);
 9484//         cx.emit(Event::Blurred);
 9485//         cx.notify();
 9486//     }
 9487
 9488//     fn modifiers_changed(
 9489//         &mut self,
 9490//         event: &gpui::platform::ModifiersChangedEvent,
 9491//         cx: &mut ViewContext<Self>,
 9492//     ) -> bool {
 9493//         let pending_selection = self.has_pending_selection();
 9494
 9495//         if let Some(point) = &self.link_go_to_definition_state.last_trigger_point {
 9496//             if event.cmd && !pending_selection {
 9497//                 let point = point.clone();
 9498//                 let snapshot = self.snapshot(cx);
 9499//                 let kind = point.definition_kind(event.shift);
 9500
 9501//                 show_link_definition(kind, self, point, snapshot, cx);
 9502//                 return false;
 9503//             }
 9504//         }
 9505
 9506//         {
 9507//             if self.link_go_to_definition_state.symbol_range.is_some()
 9508//                 || !self.link_go_to_definition_state.definitions.is_empty()
 9509//             {
 9510//                 self.link_go_to_definition_state.symbol_range.take();
 9511//                 self.link_go_to_definition_state.definitions.clear();
 9512//                 cx.notify();
 9513//             }
 9514
 9515//             self.link_go_to_definition_state.task = None;
 9516
 9517//             self.clear_highlights::<LinkGoToDefinitionState>(cx);
 9518//         }
 9519
 9520//         false
 9521//     }
 9522
 9523impl InputHandler for Editor {
 9524    fn text_for_range(
 9525        &mut self,
 9526        range_utf16: Range<usize>,
 9527        cx: &mut ViewContext<Self>,
 9528    ) -> Option<String> {
 9529        Some(
 9530            self.buffer
 9531                .read(cx)
 9532                .read(cx)
 9533                .text_for_range(OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end))
 9534                .collect(),
 9535        )
 9536    }
 9537
 9538    fn selected_text_range(&mut self, cx: &mut ViewContext<Self>) -> Option<Range<usize>> {
 9539        // Prevent the IME menu from appearing when holding down an alphabetic key
 9540        // while input is disabled.
 9541        if !self.input_enabled {
 9542            return None;
 9543        }
 9544
 9545        let range = self.selections.newest::<OffsetUtf16>(cx).range();
 9546        Some(range.start.0..range.end.0)
 9547    }
 9548
 9549    fn marked_text_range(&self, cx: &mut ViewContext<Self>) -> Option<Range<usize>> {
 9550        let snapshot = self.buffer.read(cx).read(cx);
 9551        let range = self.text_highlights::<InputComposition>(cx)?.1.get(0)?;
 9552        Some(range.start.to_offset_utf16(&snapshot).0..range.end.to_offset_utf16(&snapshot).0)
 9553    }
 9554
 9555    fn unmark_text(&mut self, cx: &mut ViewContext<Self>) {
 9556        self.clear_highlights::<InputComposition>(cx);
 9557        self.ime_transaction.take();
 9558    }
 9559
 9560    fn replace_text_in_range(
 9561        &mut self,
 9562        range_utf16: Option<Range<usize>>,
 9563        text: &str,
 9564        cx: &mut ViewContext<Self>,
 9565    ) {
 9566        if !self.input_enabled {
 9567            cx.emit(Event::InputIgnored { text: text.into() });
 9568            return;
 9569        }
 9570
 9571        self.transact(cx, |this, cx| {
 9572            let new_selected_ranges = if let Some(range_utf16) = range_utf16 {
 9573                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
 9574                Some(this.selection_replacement_ranges(range_utf16, cx))
 9575            } else {
 9576                this.marked_text_ranges(cx)
 9577            };
 9578
 9579            let range_to_replace = new_selected_ranges.as_ref().and_then(|ranges_to_replace| {
 9580                let newest_selection_id = this.selections.newest_anchor().id;
 9581                this.selections
 9582                    .all::<OffsetUtf16>(cx)
 9583                    .iter()
 9584                    .zip(ranges_to_replace.iter())
 9585                    .find_map(|(selection, range)| {
 9586                        if selection.id == newest_selection_id {
 9587                            Some(
 9588                                (range.start.0 as isize - selection.head().0 as isize)
 9589                                    ..(range.end.0 as isize - selection.head().0 as isize),
 9590                            )
 9591                        } else {
 9592                            None
 9593                        }
 9594                    })
 9595            });
 9596
 9597            cx.emit(Event::InputHandled {
 9598                utf16_range_to_replace: range_to_replace,
 9599                text: text.into(),
 9600            });
 9601
 9602            if let Some(new_selected_ranges) = new_selected_ranges {
 9603                this.change_selections(None, cx, |selections| {
 9604                    selections.select_ranges(new_selected_ranges)
 9605                });
 9606            }
 9607
 9608            this.handle_input(text, cx);
 9609        });
 9610
 9611        if let Some(transaction) = self.ime_transaction {
 9612            self.buffer.update(cx, |buffer, cx| {
 9613                buffer.group_until_transaction(transaction, cx);
 9614            });
 9615        }
 9616
 9617        self.unmark_text(cx);
 9618    }
 9619
 9620    fn replace_and_mark_text_in_range(
 9621        &mut self,
 9622        range_utf16: Option<Range<usize>>,
 9623        text: &str,
 9624        new_selected_range_utf16: Option<Range<usize>>,
 9625        cx: &mut ViewContext<Self>,
 9626    ) {
 9627        if !self.input_enabled {
 9628            cx.emit(Event::InputIgnored { text: text.into() });
 9629            return;
 9630        }
 9631
 9632        let transaction = self.transact(cx, |this, cx| {
 9633            let ranges_to_replace = if let Some(mut marked_ranges) = this.marked_text_ranges(cx) {
 9634                let snapshot = this.buffer.read(cx).read(cx);
 9635                if let Some(relative_range_utf16) = range_utf16.as_ref() {
 9636                    for marked_range in &mut marked_ranges {
 9637                        marked_range.end.0 = marked_range.start.0 + relative_range_utf16.end;
 9638                        marked_range.start.0 += relative_range_utf16.start;
 9639                        marked_range.start =
 9640                            snapshot.clip_offset_utf16(marked_range.start, Bias::Left);
 9641                        marked_range.end =
 9642                            snapshot.clip_offset_utf16(marked_range.end, Bias::Right);
 9643                    }
 9644                }
 9645                Some(marked_ranges)
 9646            } else if let Some(range_utf16) = range_utf16 {
 9647                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
 9648                Some(this.selection_replacement_ranges(range_utf16, cx))
 9649            } else {
 9650                None
 9651            };
 9652
 9653            let range_to_replace = ranges_to_replace.as_ref().and_then(|ranges_to_replace| {
 9654                let newest_selection_id = this.selections.newest_anchor().id;
 9655                this.selections
 9656                    .all::<OffsetUtf16>(cx)
 9657                    .iter()
 9658                    .zip(ranges_to_replace.iter())
 9659                    .find_map(|(selection, range)| {
 9660                        if selection.id == newest_selection_id {
 9661                            Some(
 9662                                (range.start.0 as isize - selection.head().0 as isize)
 9663                                    ..(range.end.0 as isize - selection.head().0 as isize),
 9664                            )
 9665                        } else {
 9666                            None
 9667                        }
 9668                    })
 9669            });
 9670
 9671            cx.emit(Event::InputHandled {
 9672                utf16_range_to_replace: range_to_replace,
 9673                text: text.into(),
 9674            });
 9675
 9676            if let Some(ranges) = ranges_to_replace {
 9677                this.change_selections(None, cx, |s| s.select_ranges(ranges));
 9678            }
 9679
 9680            let marked_ranges = {
 9681                let snapshot = this.buffer.read(cx).read(cx);
 9682                this.selections
 9683                    .disjoint_anchors()
 9684                    .iter()
 9685                    .map(|selection| {
 9686                        selection.start.bias_left(&*snapshot)..selection.end.bias_right(&*snapshot)
 9687                    })
 9688                    .collect::<Vec<_>>()
 9689            };
 9690
 9691            if text.is_empty() {
 9692                this.unmark_text(cx);
 9693            } else {
 9694                this.highlight_text::<InputComposition>(
 9695                    marked_ranges.clone(),
 9696                    HighlightStyle::default(), // todo!() this.style(cx).composition_mark,
 9697                    cx,
 9698                );
 9699            }
 9700
 9701            this.handle_input(text, cx);
 9702
 9703            if let Some(new_selected_range) = new_selected_range_utf16 {
 9704                let snapshot = this.buffer.read(cx).read(cx);
 9705                let new_selected_ranges = marked_ranges
 9706                    .into_iter()
 9707                    .map(|marked_range| {
 9708                        let insertion_start = marked_range.start.to_offset_utf16(&snapshot).0;
 9709                        let new_start = OffsetUtf16(new_selected_range.start + insertion_start);
 9710                        let new_end = OffsetUtf16(new_selected_range.end + insertion_start);
 9711                        snapshot.clip_offset_utf16(new_start, Bias::Left)
 9712                            ..snapshot.clip_offset_utf16(new_end, Bias::Right)
 9713                    })
 9714                    .collect::<Vec<_>>();
 9715
 9716                drop(snapshot);
 9717                this.change_selections(None, cx, |selections| {
 9718                    selections.select_ranges(new_selected_ranges)
 9719                });
 9720            }
 9721        });
 9722
 9723        self.ime_transaction = self.ime_transaction.or(transaction);
 9724        if let Some(transaction) = self.ime_transaction {
 9725            self.buffer.update(cx, |buffer, cx| {
 9726                buffer.group_until_transaction(transaction, cx);
 9727            });
 9728        }
 9729
 9730        if self.text_highlights::<InputComposition>(cx).is_none() {
 9731            self.ime_transaction.take();
 9732        }
 9733    }
 9734
 9735    fn bounds_for_range(
 9736        &mut self,
 9737        range_utf16: Range<usize>,
 9738        element_bounds: gpui::Bounds<Pixels>,
 9739        cx: &mut ViewContext<Self>,
 9740    ) -> Option<gpui::Bounds<Pixels>> {
 9741        let text_layout_details = self.text_layout_details(cx);
 9742        let style = &text_layout_details.editor_style;
 9743        let font_id = cx.text_system().font_id(&style.text.font()).unwrap();
 9744        let font_size = style.text.font_size.to_pixels(cx.rem_size());
 9745        let line_height = style.text.line_height_in_pixels(cx.rem_size());
 9746        let em_width = cx
 9747            .text_system()
 9748            .typographic_bounds(font_id, font_size, 'm')
 9749            .unwrap()
 9750            .size
 9751            .width;
 9752
 9753        let snapshot = self.snapshot(cx);
 9754        let scroll_position = snapshot.scroll_position();
 9755        let scroll_left = scroll_position.x * em_width;
 9756
 9757        let start = OffsetUtf16(range_utf16.start).to_display_point(&snapshot);
 9758        let x = snapshot.x_for_point(start, &text_layout_details) - scroll_left + self.gutter_width;
 9759        let y = line_height * (start.row() as f32 - scroll_position.y);
 9760
 9761        Some(Bounds {
 9762            origin: element_bounds.origin + point(x, y),
 9763            size: size(em_width, line_height),
 9764        })
 9765    }
 9766}
 9767
 9768// fn build_style(
 9769//     settings: &ThemeSettings,
 9770//     get_field_editor_theme: Option<&GetFieldEditorTheme>,
 9771//     override_text_style: Option<&OverrideTextStyle>,
 9772//     cx: &mut AppContext,
 9773// ) -> EditorStyle {
 9774//     let font_cache = cx.font_cache();
 9775//     let line_height_scalar = settings.line_height();
 9776//     let theme_id = settings.theme.meta.id;
 9777//     let mut theme = settings.theme.editor.clone();
 9778//     let mut style = if let Some(get_field_editor_theme) = get_field_editor_theme {
 9779//         let field_editor_theme = get_field_editor_theme(&settings.theme);
 9780//         theme.text_color = field_editor_theme.text.color;
 9781//         theme.selection = field_editor_theme.selection;
 9782//         theme.background = field_editor_theme
 9783//             .container
 9784//             .background_color
 9785//             .unwrap_or_default();
 9786//         EditorStyle {
 9787//             text: field_editor_theme.text,
 9788//             placeholder_text: field_editor_theme.placeholder_text,
 9789//             line_height_scalar,
 9790//             theme,
 9791//             theme_id,
 9792//         }
 9793//     } else {
 9794//         todo!();
 9795//         // let font_family_id = settings.buffer_font_family;
 9796//         // let font_family_name = cx.font_cache().family_name(font_family_id).unwrap();
 9797//         // let font_properties = Default::default();
 9798//         // let font_id = font_cache
 9799//         //     .select_font(font_family_id, &font_properties)
 9800//         //     .unwrap();
 9801//         // let font_size = settings.buffer_font_size(cx);
 9802//         // EditorStyle {
 9803//         //     text: TextStyle {
 9804//         //         color: settings.theme.editor.text_color,
 9805//         //         font_family_name,
 9806//         //         font_family_id,
 9807//         //         font_id,
 9808//         //         font_size,
 9809//         //         font_properties,
 9810//         //         underline: Default::default(),
 9811//         //         soft_wrap: false,
 9812//         //     },
 9813//         //     placeholder_text: None,
 9814//         //     line_height_scalar,
 9815//         //     theme,
 9816//         //     theme_id,
 9817//         // }
 9818//     };
 9819
 9820//     if let Some(highlight_style) = override_text_style.and_then(|build_style| build_style(&style)) {
 9821//         if let Some(highlighted) = style
 9822//             .text
 9823//             .clone()
 9824//             .highlight(highlight_style, font_cache)
 9825//             .log_err()
 9826//         {
 9827//             style.text = highlighted;
 9828//         }
 9829//     }
 9830
 9831//     style
 9832// }
 9833
 9834trait SelectionExt {
 9835    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize>;
 9836    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point>;
 9837    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
 9838    fn spanned_rows(&self, include_end_if_at_line_start: bool, map: &DisplaySnapshot)
 9839        -> Range<u32>;
 9840}
 9841
 9842impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
 9843    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
 9844        let start = self.start.to_point(buffer);
 9845        let end = self.end.to_point(buffer);
 9846        if self.reversed {
 9847            end..start
 9848        } else {
 9849            start..end
 9850        }
 9851    }
 9852
 9853    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
 9854        let start = self.start.to_offset(buffer);
 9855        let end = self.end.to_offset(buffer);
 9856        if self.reversed {
 9857            end..start
 9858        } else {
 9859            start..end
 9860        }
 9861    }
 9862
 9863    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
 9864        let start = self
 9865            .start
 9866            .to_point(&map.buffer_snapshot)
 9867            .to_display_point(map);
 9868        let end = self
 9869            .end
 9870            .to_point(&map.buffer_snapshot)
 9871            .to_display_point(map);
 9872        if self.reversed {
 9873            end..start
 9874        } else {
 9875            start..end
 9876        }
 9877    }
 9878
 9879    fn spanned_rows(
 9880        &self,
 9881        include_end_if_at_line_start: bool,
 9882        map: &DisplaySnapshot,
 9883    ) -> Range<u32> {
 9884        let start = self.start.to_point(&map.buffer_snapshot);
 9885        let mut end = self.end.to_point(&map.buffer_snapshot);
 9886        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
 9887            end.row -= 1;
 9888        }
 9889
 9890        let buffer_start = map.prev_line_boundary(start).0;
 9891        let buffer_end = map.next_line_boundary(end).0;
 9892        buffer_start.row..buffer_end.row + 1
 9893    }
 9894}
 9895
 9896impl<T: InvalidationRegion> InvalidationStack<T> {
 9897    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
 9898    where
 9899        S: Clone + ToOffset,
 9900    {
 9901        while let Some(region) = self.last() {
 9902            let all_selections_inside_invalidation_ranges =
 9903                if selections.len() == region.ranges().len() {
 9904                    selections
 9905                        .iter()
 9906                        .zip(region.ranges().iter().map(|r| r.to_offset(buffer)))
 9907                        .all(|(selection, invalidation_range)| {
 9908                            let head = selection.head().to_offset(buffer);
 9909                            invalidation_range.start <= head && invalidation_range.end >= head
 9910                        })
 9911                } else {
 9912                    false
 9913                };
 9914
 9915            if all_selections_inside_invalidation_ranges {
 9916                break;
 9917            } else {
 9918                self.pop();
 9919            }
 9920        }
 9921    }
 9922}
 9923
 9924impl<T> Default for InvalidationStack<T> {
 9925    fn default() -> Self {
 9926        Self(Default::default())
 9927    }
 9928}
 9929
 9930impl<T> Deref for InvalidationStack<T> {
 9931    type Target = Vec<T>;
 9932
 9933    fn deref(&self) -> &Self::Target {
 9934        &self.0
 9935    }
 9936}
 9937
 9938impl<T> DerefMut for InvalidationStack<T> {
 9939    fn deref_mut(&mut self) -> &mut Self::Target {
 9940        &mut self.0
 9941    }
 9942}
 9943
 9944impl InvalidationRegion for SnippetState {
 9945    fn ranges(&self) -> &[Range<Anchor>] {
 9946        &self.ranges[self.active_index]
 9947    }
 9948}
 9949
 9950// impl Deref for EditorStyle {
 9951//     type Target = theme::Editor;
 9952
 9953//     fn deref(&self) -> &Self::Target {
 9954//         &self.theme
 9955//     }
 9956// }
 9957
 9958pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> RenderBlock {
 9959    let mut highlighted_lines = Vec::new();
 9960
 9961    for (index, line) in diagnostic.message.lines().enumerate() {
 9962        let line = match &diagnostic.source {
 9963            Some(source) if index == 0 => {
 9964                let source_highlight = Vec::from_iter(0..source.len());
 9965                highlight_diagnostic_message(source_highlight, &format!("{source}: {line}"))
 9966            }
 9967
 9968            _ => highlight_diagnostic_message(Vec::new(), line),
 9969        };
 9970        highlighted_lines.push(line);
 9971    }
 9972    let message = diagnostic.message;
 9973    Arc::new(move |cx: &mut BlockContext| {
 9974        let message = message.clone();
 9975        v_stack()
 9976            .id(cx.block_id)
 9977            .size_full()
 9978            .bg(gpui::red())
 9979            .children(highlighted_lines.iter().map(|(line, highlights)| {
 9980                div()
 9981                    .child(HighlightedLabel::new(line.clone(), highlights.clone()))
 9982                    .ml(cx.anchor_x)
 9983            }))
 9984            .cursor_pointer()
 9985            .on_click(move |_, _, cx| {
 9986                cx.write_to_clipboard(ClipboardItem::new(message.clone()));
 9987            })
 9988            .tooltip(|_, cx| Tooltip::text("Copy diagnostic message", cx))
 9989            .render()
 9990    })
 9991}
 9992
 9993pub fn highlight_diagnostic_message(
 9994    initial_highlights: Vec<usize>,
 9995    message: &str,
 9996) -> (String, Vec<usize>) {
 9997    let mut message_without_backticks = String::new();
 9998    let mut prev_offset = 0;
 9999    let mut inside_block = false;
10000    let mut highlights = initial_highlights;
10001    for (match_ix, (offset, _)) in message
10002        .match_indices('`')
10003        .chain([(message.len(), "")])
10004        .enumerate()
10005    {
10006        message_without_backticks.push_str(&message[prev_offset..offset]);
10007        if inside_block {
10008            highlights.extend(prev_offset - match_ix..offset - match_ix);
10009        }
10010
10011        inside_block = !inside_block;
10012        prev_offset = offset + 1;
10013    }
10014
10015    (message_without_backticks, highlights)
10016}
10017
10018pub fn diagnostic_style(
10019    severity: DiagnosticSeverity,
10020    valid: bool,
10021    style: &DiagnosticStyle,
10022) -> Hsla {
10023    match (severity, valid) {
10024        (DiagnosticSeverity::ERROR, true) => style.error,
10025        (DiagnosticSeverity::ERROR, false) => style.error,
10026        (DiagnosticSeverity::WARNING, true) => style.warning,
10027        (DiagnosticSeverity::WARNING, false) => style.warning,
10028        (DiagnosticSeverity::INFORMATION, true) => style.info,
10029        (DiagnosticSeverity::INFORMATION, false) => style.info,
10030        (DiagnosticSeverity::HINT, true) => style.info,
10031        (DiagnosticSeverity::HINT, false) => style.info,
10032        _ => style.ignored,
10033    }
10034}
10035
10036pub fn combine_syntax_and_fuzzy_match_highlights(
10037    text: &str,
10038    default_style: HighlightStyle,
10039    syntax_ranges: impl Iterator<Item = (Range<usize>, HighlightStyle)>,
10040    match_indices: &[usize],
10041) -> Vec<(Range<usize>, HighlightStyle)> {
10042    let mut result = Vec::new();
10043    let mut match_indices = match_indices.iter().copied().peekable();
10044
10045    for (range, mut syntax_highlight) in syntax_ranges.chain([(usize::MAX..0, Default::default())])
10046    {
10047        syntax_highlight.font_weight = None;
10048
10049        // Add highlights for any fuzzy match characters before the next
10050        // syntax highlight range.
10051        while let Some(&match_index) = match_indices.peek() {
10052            if match_index >= range.start {
10053                break;
10054            }
10055            match_indices.next();
10056            let end_index = char_ix_after(match_index, text);
10057            let mut match_style = default_style;
10058            match_style.font_weight = Some(FontWeight::BOLD);
10059            result.push((match_index..end_index, match_style));
10060        }
10061
10062        if range.start == usize::MAX {
10063            break;
10064        }
10065
10066        // Add highlights for any fuzzy match characters within the
10067        // syntax highlight range.
10068        let mut offset = range.start;
10069        while let Some(&match_index) = match_indices.peek() {
10070            if match_index >= range.end {
10071                break;
10072            }
10073
10074            match_indices.next();
10075            if match_index > offset {
10076                result.push((offset..match_index, syntax_highlight));
10077            }
10078
10079            let mut end_index = char_ix_after(match_index, text);
10080            while let Some(&next_match_index) = match_indices.peek() {
10081                if next_match_index == end_index && next_match_index < range.end {
10082                    end_index = char_ix_after(next_match_index, text);
10083                    match_indices.next();
10084                } else {
10085                    break;
10086                }
10087            }
10088
10089            let mut match_style = syntax_highlight;
10090            match_style.font_weight = Some(FontWeight::BOLD);
10091            result.push((match_index..end_index, match_style));
10092            offset = end_index;
10093        }
10094
10095        if offset < range.end {
10096            result.push((offset..range.end, syntax_highlight));
10097        }
10098    }
10099
10100    fn char_ix_after(ix: usize, text: &str) -> usize {
10101        ix + text[ix..].chars().next().unwrap().len_utf8()
10102    }
10103
10104    result
10105}
10106
10107// pub fn styled_runs_for_code_label<'a>(
10108//     label: &'a CodeLabel,
10109//     syntax_theme: &'a theme::SyntaxTheme,
10110// ) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
10111//     let fade_out = HighlightStyle {
10112//         fade_out: Some(0.35),
10113//         ..Default::default()
10114//     };
10115
10116//     let mut prev_end = label.filter_range.end;
10117//     label
10118//         .runs
10119//         .iter()
10120//         .enumerate()
10121//         .flat_map(move |(ix, (range, highlight_id))| {
10122//             let style = if let Some(style) = highlight_id.style(syntax_theme) {
10123//                 style
10124//             } else {
10125//                 return Default::default();
10126//             };
10127//             let mut muted_style = style;
10128//             muted_style.highlight(fade_out);
10129
10130//             let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
10131//             if range.start >= label.filter_range.end {
10132//                 if range.start > prev_end {
10133//                     runs.push((prev_end..range.start, fade_out));
10134//                 }
10135//                 runs.push((range.clone(), muted_style));
10136//             } else if range.end <= label.filter_range.end {
10137//                 runs.push((range.clone(), style));
10138//             } else {
10139//                 runs.push((range.start..label.filter_range.end, style));
10140//                 runs.push((label.filter_range.end..range.end, muted_style));
10141//             }
10142//             prev_end = cmp::max(prev_end, range.end);
10143
10144//             if ix + 1 == label.runs.len() && label.text.len() > prev_end {
10145//                 runs.push((prev_end..label.text.len(), fade_out));
10146//             }
10147
10148//             runs
10149//         })
10150
10151pub fn split_words<'a>(text: &'a str) -> impl std::iter::Iterator<Item = &'a str> + 'a {
10152    let mut index = 0;
10153    let mut codepoints = text.char_indices().peekable();
10154
10155    std::iter::from_fn(move || {
10156        let start_index = index;
10157        while let Some((new_index, codepoint)) = codepoints.next() {
10158            index = new_index + codepoint.len_utf8();
10159            let current_upper = codepoint.is_uppercase();
10160            let next_upper = codepoints
10161                .peek()
10162                .map(|(_, c)| c.is_uppercase())
10163                .unwrap_or(false);
10164
10165            if !current_upper && next_upper {
10166                return Some(&text[start_index..index]);
10167            }
10168        }
10169
10170        index = text.len();
10171        if start_index < text.len() {
10172            return Some(&text[start_index..]);
10173        }
10174        None
10175    })
10176    .flat_map(|word| word.split_inclusive('_'))
10177    .flat_map(|word| word.split_inclusive('-'))
10178}
10179
10180trait RangeToAnchorExt {
10181    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor>;
10182}
10183
10184impl<T: ToOffset> RangeToAnchorExt for Range<T> {
10185    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor> {
10186        snapshot.anchor_after(self.start)..snapshot.anchor_before(self.end)
10187    }
10188}