editor.rs

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