editor.rs

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