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