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