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