editor.rs

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