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                    // Split the comment prefix's trailing whitespace into a separate string,
 7100                    // as that portion won't be used for detecting if a line is a comment.
 7101                    struct Comment {
 7102                        full_prefix: Arc<str>,
 7103                        trimmed_prefix_len: usize,
 7104                    }
 7105                    let prefixes: SmallVec<[Comment; 4]> = full_comment_prefixes
 7106                        .iter()
 7107                        .map(|full_prefix| {
 7108                            let trimmed_prefix_len = full_prefix.trim_end_matches(' ').len();
 7109                            Comment {
 7110                                trimmed_prefix_len,
 7111                                full_prefix: full_prefix.clone(),
 7112                            }
 7113                        })
 7114                        .collect();
 7115
 7116                    let mut all_selection_lines_are_comments = true;
 7117
 7118                    for row in start_row..=end_row {
 7119                        if start_row < end_row && snapshot.is_line_blank(row) {
 7120                            continue;
 7121                        }
 7122
 7123                        let Some((prefix, prefix_range)) = prefixes
 7124                            .iter()
 7125                            .map(|prefix| {
 7126                                (
 7127                                    prefix,
 7128                                    comment_prefix_range(
 7129                                        snapshot.deref(),
 7130                                        row,
 7131                                        &prefix.full_prefix[..prefix.trimmed_prefix_len],
 7132                                        &prefix.full_prefix[prefix.trimmed_prefix_len..],
 7133                                    ),
 7134                                )
 7135                            })
 7136                            .max_by_key(|(_, range)| range.end.column - range.start.column)
 7137                        else {
 7138                            // There has to be at least one prefix.
 7139                            break;
 7140                        };
 7141                        if prefix_range.is_empty() {
 7142                            all_selection_lines_are_comments = false;
 7143                        }
 7144                        selection_edit_ranges.push((prefix_range, prefix.full_prefix.clone()));
 7145                    }
 7146
 7147                    if all_selection_lines_are_comments {
 7148                        edits.extend(
 7149                            selection_edit_ranges
 7150                                .iter()
 7151                                .cloned()
 7152                                .map(|(range, _)| (range, empty_str.clone())),
 7153                        );
 7154                    } else {
 7155                        let min_column = selection_edit_ranges
 7156                            .iter()
 7157                            .map(|(range, _)| range.start.column)
 7158                            .min()
 7159                            .unwrap_or(0);
 7160                        edits.extend(selection_edit_ranges.iter().map(|(range, prefix)| {
 7161                            let position = Point::new(range.start.row, min_column);
 7162                            (position..position, prefix.clone())
 7163                        }));
 7164                    }
 7165                } else if let Some((full_comment_prefix, comment_suffix)) =
 7166                    language.block_comment_delimiters()
 7167                {
 7168                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
 7169                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
 7170                    let prefix_range = comment_prefix_range(
 7171                        snapshot.deref(),
 7172                        start_row,
 7173                        comment_prefix,
 7174                        comment_prefix_whitespace,
 7175                    );
 7176                    let suffix_range = comment_suffix_range(
 7177                        snapshot.deref(),
 7178                        end_row,
 7179                        comment_suffix.trim_start_matches(' '),
 7180                        comment_suffix.starts_with(' '),
 7181                    );
 7182
 7183                    if prefix_range.is_empty() || suffix_range.is_empty() {
 7184                        edits.push((
 7185                            prefix_range.start..prefix_range.start,
 7186                            full_comment_prefix.clone(),
 7187                        ));
 7188                        edits.push((suffix_range.end..suffix_range.end, comment_suffix.clone()));
 7189                        suffixes_inserted.push((end_row, comment_suffix.len()));
 7190                    } else {
 7191                        edits.push((prefix_range, empty_str.clone()));
 7192                        edits.push((suffix_range, empty_str.clone()));
 7193                    }
 7194                } else {
 7195                    continue;
 7196                }
 7197            }
 7198
 7199            drop(snapshot);
 7200            this.buffer.update(cx, |buffer, cx| {
 7201                buffer.edit(edits, None, cx);
 7202            });
 7203
 7204            // Adjust selections so that they end before any comment suffixes that
 7205            // were inserted.
 7206            let mut suffixes_inserted = suffixes_inserted.into_iter().peekable();
 7207            let mut selections = this.selections.all::<Point>(cx);
 7208            let snapshot = this.buffer.read(cx).read(cx);
 7209            for selection in &mut selections {
 7210                while let Some((row, suffix_len)) = suffixes_inserted.peek().copied() {
 7211                    match row.cmp(&selection.end.row) {
 7212                        Ordering::Less => {
 7213                            suffixes_inserted.next();
 7214                            continue;
 7215                        }
 7216                        Ordering::Greater => break,
 7217                        Ordering::Equal => {
 7218                            if selection.end.column == snapshot.line_len(row) {
 7219                                if selection.is_empty() {
 7220                                    selection.start.column -= suffix_len as u32;
 7221                                }
 7222                                selection.end.column -= suffix_len as u32;
 7223                            }
 7224                            break;
 7225                        }
 7226                    }
 7227                }
 7228            }
 7229
 7230            drop(snapshot);
 7231            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
 7232
 7233            let selections = this.selections.all::<Point>(cx);
 7234            let selections_on_single_row = selections.windows(2).all(|selections| {
 7235                selections[0].start.row == selections[1].start.row
 7236                    && selections[0].end.row == selections[1].end.row
 7237                    && selections[0].start.row == selections[0].end.row
 7238            });
 7239            let selections_selecting = selections
 7240                .iter()
 7241                .any(|selection| selection.start != selection.end);
 7242            let advance_downwards = action.advance_downwards
 7243                && selections_on_single_row
 7244                && !selections_selecting
 7245                && this.mode != EditorMode::SingleLine;
 7246
 7247            if advance_downwards {
 7248                let snapshot = this.buffer.read(cx).snapshot(cx);
 7249
 7250                this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7251                    s.move_cursors_with(|display_snapshot, display_point, _| {
 7252                        let mut point = display_point.to_point(display_snapshot);
 7253                        point.row += 1;
 7254                        point = snapshot.clip_point(point, Bias::Left);
 7255                        let display_point = point.to_display_point(display_snapshot);
 7256                        let goal = SelectionGoal::HorizontalPosition(
 7257                            display_snapshot
 7258                                .x_for_display_point(display_point, &text_layout_details)
 7259                                .into(),
 7260                        );
 7261                        (display_point, goal)
 7262                    })
 7263                });
 7264            }
 7265        });
 7266    }
 7267
 7268    pub fn select_larger_syntax_node(
 7269        &mut self,
 7270        _: &SelectLargerSyntaxNode,
 7271        cx: &mut ViewContext<Self>,
 7272    ) {
 7273        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 7274        let buffer = self.buffer.read(cx).snapshot(cx);
 7275        let old_selections = self.selections.all::<usize>(cx).into_boxed_slice();
 7276
 7277        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
 7278        let mut selected_larger_node = false;
 7279        let new_selections = old_selections
 7280            .iter()
 7281            .map(|selection| {
 7282                let old_range = selection.start..selection.end;
 7283                let mut new_range = old_range.clone();
 7284                while let Some(containing_range) =
 7285                    buffer.range_for_syntax_ancestor(new_range.clone())
 7286                {
 7287                    new_range = containing_range;
 7288                    if !display_map.intersects_fold(new_range.start)
 7289                        && !display_map.intersects_fold(new_range.end)
 7290                    {
 7291                        break;
 7292                    }
 7293                }
 7294
 7295                selected_larger_node |= new_range != old_range;
 7296                Selection {
 7297                    id: selection.id,
 7298                    start: new_range.start,
 7299                    end: new_range.end,
 7300                    goal: SelectionGoal::None,
 7301                    reversed: selection.reversed,
 7302                }
 7303            })
 7304            .collect::<Vec<_>>();
 7305
 7306        if selected_larger_node {
 7307            stack.push(old_selections);
 7308            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7309                s.select(new_selections);
 7310            });
 7311        }
 7312        self.select_larger_syntax_node_stack = stack;
 7313    }
 7314
 7315    pub fn select_smaller_syntax_node(
 7316        &mut self,
 7317        _: &SelectSmallerSyntaxNode,
 7318        cx: &mut ViewContext<Self>,
 7319    ) {
 7320        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
 7321        if let Some(selections) = stack.pop() {
 7322            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7323                s.select(selections.to_vec());
 7324            });
 7325        }
 7326        self.select_larger_syntax_node_stack = stack;
 7327    }
 7328
 7329    pub fn move_to_enclosing_bracket(
 7330        &mut self,
 7331        _: &MoveToEnclosingBracket,
 7332        cx: &mut ViewContext<Self>,
 7333    ) {
 7334        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7335            s.move_offsets_with(|snapshot, selection| {
 7336                let Some(enclosing_bracket_ranges) =
 7337                    snapshot.enclosing_bracket_ranges(selection.start..selection.end)
 7338                else {
 7339                    return;
 7340                };
 7341
 7342                let mut best_length = usize::MAX;
 7343                let mut best_inside = false;
 7344                let mut best_in_bracket_range = false;
 7345                let mut best_destination = None;
 7346                for (open, close) in enclosing_bracket_ranges {
 7347                    let close = close.to_inclusive();
 7348                    let length = close.end() - open.start;
 7349                    let inside = selection.start >= open.end && selection.end <= *close.start();
 7350                    let in_bracket_range = open.to_inclusive().contains(&selection.head())
 7351                        || close.contains(&selection.head());
 7352
 7353                    // If best is next to a bracket and current isn't, skip
 7354                    if !in_bracket_range && best_in_bracket_range {
 7355                        continue;
 7356                    }
 7357
 7358                    // Prefer smaller lengths unless best is inside and current isn't
 7359                    if length > best_length && (best_inside || !inside) {
 7360                        continue;
 7361                    }
 7362
 7363                    best_length = length;
 7364                    best_inside = inside;
 7365                    best_in_bracket_range = in_bracket_range;
 7366                    best_destination = Some(
 7367                        if close.contains(&selection.start) && close.contains(&selection.end) {
 7368                            if inside {
 7369                                open.end
 7370                            } else {
 7371                                open.start
 7372                            }
 7373                        } else {
 7374                            if inside {
 7375                                *close.start()
 7376                            } else {
 7377                                *close.end()
 7378                            }
 7379                        },
 7380                    );
 7381                }
 7382
 7383                if let Some(destination) = best_destination {
 7384                    selection.collapse_to(destination, SelectionGoal::None);
 7385                }
 7386            })
 7387        });
 7388    }
 7389
 7390    pub fn undo_selection(&mut self, _: &UndoSelection, cx: &mut ViewContext<Self>) {
 7391        self.end_selection(cx);
 7392        self.selection_history.mode = SelectionHistoryMode::Undoing;
 7393        if let Some(entry) = self.selection_history.undo_stack.pop_back() {
 7394            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
 7395            self.select_next_state = entry.select_next_state;
 7396            self.select_prev_state = entry.select_prev_state;
 7397            self.add_selections_state = entry.add_selections_state;
 7398            self.request_autoscroll(Autoscroll::newest(), cx);
 7399        }
 7400        self.selection_history.mode = SelectionHistoryMode::Normal;
 7401    }
 7402
 7403    pub fn redo_selection(&mut self, _: &RedoSelection, cx: &mut ViewContext<Self>) {
 7404        self.end_selection(cx);
 7405        self.selection_history.mode = SelectionHistoryMode::Redoing;
 7406        if let Some(entry) = self.selection_history.redo_stack.pop_back() {
 7407            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
 7408            self.select_next_state = entry.select_next_state;
 7409            self.select_prev_state = entry.select_prev_state;
 7410            self.add_selections_state = entry.add_selections_state;
 7411            self.request_autoscroll(Autoscroll::newest(), cx);
 7412        }
 7413        self.selection_history.mode = SelectionHistoryMode::Normal;
 7414    }
 7415
 7416    fn go_to_diagnostic(&mut self, _: &GoToDiagnostic, cx: &mut ViewContext<Self>) {
 7417        self.go_to_diagnostic_impl(Direction::Next, cx)
 7418    }
 7419
 7420    fn go_to_prev_diagnostic(&mut self, _: &GoToPrevDiagnostic, cx: &mut ViewContext<Self>) {
 7421        self.go_to_diagnostic_impl(Direction::Prev, cx)
 7422    }
 7423
 7424    pub fn go_to_diagnostic_impl(&mut self, direction: Direction, cx: &mut ViewContext<Self>) {
 7425        let buffer = self.buffer.read(cx).snapshot(cx);
 7426        let selection = self.selections.newest::<usize>(cx);
 7427
 7428        // If there is an active Diagnostic Popover jump to its diagnostic instead.
 7429        if direction == Direction::Next {
 7430            if let Some(popover) = self.hover_state.diagnostic_popover.as_ref() {
 7431                let (group_id, jump_to) = popover.activation_info();
 7432                if self.activate_diagnostics(group_id, cx) {
 7433                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7434                        let mut new_selection = s.newest_anchor().clone();
 7435                        new_selection.collapse_to(jump_to, SelectionGoal::None);
 7436                        s.select_anchors(vec![new_selection.clone()]);
 7437                    });
 7438                }
 7439                return;
 7440            }
 7441        }
 7442
 7443        let mut active_primary_range = self.active_diagnostics.as_ref().map(|active_diagnostics| {
 7444            active_diagnostics
 7445                .primary_range
 7446                .to_offset(&buffer)
 7447                .to_inclusive()
 7448        });
 7449        let mut search_start = if let Some(active_primary_range) = active_primary_range.as_ref() {
 7450            if active_primary_range.contains(&selection.head()) {
 7451                *active_primary_range.end()
 7452            } else {
 7453                selection.head()
 7454            }
 7455        } else {
 7456            selection.head()
 7457        };
 7458
 7459        loop {
 7460            let mut diagnostics = if direction == Direction::Prev {
 7461                buffer.diagnostics_in_range::<_, usize>(0..search_start, true)
 7462            } else {
 7463                buffer.diagnostics_in_range::<_, usize>(search_start..buffer.len(), false)
 7464            };
 7465            let group = diagnostics.find_map(|entry| {
 7466                if entry.diagnostic.is_primary
 7467                    && entry.diagnostic.severity <= DiagnosticSeverity::WARNING
 7468                    && !entry.range.is_empty()
 7469                    && Some(entry.range.end) != active_primary_range.as_ref().map(|r| *r.end())
 7470                    && !entry.range.contains(&search_start)
 7471                {
 7472                    Some((entry.range, entry.diagnostic.group_id))
 7473                } else {
 7474                    None
 7475                }
 7476            });
 7477
 7478            if let Some((primary_range, group_id)) = group {
 7479                if self.activate_diagnostics(group_id, cx) {
 7480                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7481                        s.select(vec![Selection {
 7482                            id: selection.id,
 7483                            start: primary_range.start,
 7484                            end: primary_range.start,
 7485                            reversed: false,
 7486                            goal: SelectionGoal::None,
 7487                        }]);
 7488                    });
 7489                }
 7490                break;
 7491            } else {
 7492                // Cycle around to the start of the buffer, potentially moving back to the start of
 7493                // the currently active diagnostic.
 7494                active_primary_range.take();
 7495                if direction == Direction::Prev {
 7496                    if search_start == buffer.len() {
 7497                        break;
 7498                    } else {
 7499                        search_start = buffer.len();
 7500                    }
 7501                } else if search_start == 0 {
 7502                    break;
 7503                } else {
 7504                    search_start = 0;
 7505                }
 7506            }
 7507        }
 7508    }
 7509
 7510    fn go_to_hunk(&mut self, _: &GoToHunk, cx: &mut ViewContext<Self>) {
 7511        let snapshot = self
 7512            .display_map
 7513            .update(cx, |display_map, cx| display_map.snapshot(cx));
 7514        let selection = self.selections.newest::<Point>(cx);
 7515
 7516        if !self.seek_in_direction(
 7517            &snapshot,
 7518            selection.head(),
 7519            false,
 7520            snapshot
 7521                .buffer_snapshot
 7522                .git_diff_hunks_in_range((selection.head().row + 1)..u32::MAX),
 7523            cx,
 7524        ) {
 7525            let wrapped_point = Point::zero();
 7526            self.seek_in_direction(
 7527                &snapshot,
 7528                wrapped_point,
 7529                true,
 7530                snapshot
 7531                    .buffer_snapshot
 7532                    .git_diff_hunks_in_range((wrapped_point.row + 1)..u32::MAX),
 7533                cx,
 7534            );
 7535        }
 7536    }
 7537
 7538    fn go_to_prev_hunk(&mut self, _: &GoToPrevHunk, cx: &mut ViewContext<Self>) {
 7539        let snapshot = self
 7540            .display_map
 7541            .update(cx, |display_map, cx| display_map.snapshot(cx));
 7542        let selection = self.selections.newest::<Point>(cx);
 7543
 7544        if !self.seek_in_direction(
 7545            &snapshot,
 7546            selection.head(),
 7547            false,
 7548            snapshot
 7549                .buffer_snapshot
 7550                .git_diff_hunks_in_range_rev(0..selection.head().row),
 7551            cx,
 7552        ) {
 7553            let wrapped_point = snapshot.buffer_snapshot.max_point();
 7554            self.seek_in_direction(
 7555                &snapshot,
 7556                wrapped_point,
 7557                true,
 7558                snapshot
 7559                    .buffer_snapshot
 7560                    .git_diff_hunks_in_range_rev(0..wrapped_point.row),
 7561                cx,
 7562            );
 7563        }
 7564    }
 7565
 7566    fn seek_in_direction(
 7567        &mut self,
 7568        snapshot: &DisplaySnapshot,
 7569        initial_point: Point,
 7570        is_wrapped: bool,
 7571        hunks: impl Iterator<Item = DiffHunk<u32>>,
 7572        cx: &mut ViewContext<Editor>,
 7573    ) -> bool {
 7574        let display_point = initial_point.to_display_point(snapshot);
 7575        let mut hunks = hunks
 7576            .map(|hunk| diff_hunk_to_display(hunk, &snapshot))
 7577            .filter(|hunk| {
 7578                if is_wrapped {
 7579                    true
 7580                } else {
 7581                    !hunk.contains_display_row(display_point.row())
 7582                }
 7583            })
 7584            .dedup();
 7585
 7586        if let Some(hunk) = hunks.next() {
 7587            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7588                let row = hunk.start_display_row();
 7589                let point = DisplayPoint::new(row, 0);
 7590                s.select_display_ranges([point..point]);
 7591            });
 7592
 7593            true
 7594        } else {
 7595            false
 7596        }
 7597    }
 7598
 7599    pub fn go_to_definition(
 7600        &mut self,
 7601        _: &GoToDefinition,
 7602        cx: &mut ViewContext<Self>,
 7603    ) -> Task<Result<bool>> {
 7604        self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, false, cx)
 7605    }
 7606
 7607    pub fn go_to_implementation(
 7608        &mut self,
 7609        _: &GoToImplementation,
 7610        cx: &mut ViewContext<Self>,
 7611    ) -> Task<Result<bool>> {
 7612        self.go_to_definition_of_kind(GotoDefinitionKind::Implementation, false, cx)
 7613    }
 7614
 7615    pub fn go_to_implementation_split(
 7616        &mut self,
 7617        _: &GoToImplementationSplit,
 7618        cx: &mut ViewContext<Self>,
 7619    ) -> Task<Result<bool>> {
 7620        self.go_to_definition_of_kind(GotoDefinitionKind::Implementation, true, cx)
 7621    }
 7622
 7623    pub fn go_to_type_definition(
 7624        &mut self,
 7625        _: &GoToTypeDefinition,
 7626        cx: &mut ViewContext<Self>,
 7627    ) -> Task<Result<bool>> {
 7628        self.go_to_definition_of_kind(GotoDefinitionKind::Type, false, cx)
 7629    }
 7630
 7631    pub fn go_to_definition_split(
 7632        &mut self,
 7633        _: &GoToDefinitionSplit,
 7634        cx: &mut ViewContext<Self>,
 7635    ) -> Task<Result<bool>> {
 7636        self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, true, cx)
 7637    }
 7638
 7639    pub fn go_to_type_definition_split(
 7640        &mut self,
 7641        _: &GoToTypeDefinitionSplit,
 7642        cx: &mut ViewContext<Self>,
 7643    ) -> Task<Result<bool>> {
 7644        self.go_to_definition_of_kind(GotoDefinitionKind::Type, true, cx)
 7645    }
 7646
 7647    fn go_to_definition_of_kind(
 7648        &mut self,
 7649        kind: GotoDefinitionKind,
 7650        split: bool,
 7651        cx: &mut ViewContext<Self>,
 7652    ) -> Task<Result<bool>> {
 7653        let Some(workspace) = self.workspace() else {
 7654            return Task::ready(Ok(false));
 7655        };
 7656        let buffer = self.buffer.read(cx);
 7657        let head = self.selections.newest::<usize>(cx).head();
 7658        let (buffer, head) = if let Some(text_anchor) = buffer.text_anchor_for_position(head, cx) {
 7659            text_anchor
 7660        } else {
 7661            return Task::ready(Ok(false));
 7662        };
 7663
 7664        let project = workspace.read(cx).project().clone();
 7665        let definitions = project.update(cx, |project, cx| match kind {
 7666            GotoDefinitionKind::Symbol => project.definition(&buffer, head, cx),
 7667            GotoDefinitionKind::Type => project.type_definition(&buffer, head, cx),
 7668            GotoDefinitionKind::Implementation => project.implementation(&buffer, head, cx),
 7669        });
 7670
 7671        cx.spawn(|editor, mut cx| async move {
 7672            let definitions = definitions.await?;
 7673            let navigated = editor
 7674                .update(&mut cx, |editor, cx| {
 7675                    editor.navigate_to_hover_links(
 7676                        Some(kind),
 7677                        definitions.into_iter().map(HoverLink::Text).collect(),
 7678                        split,
 7679                        cx,
 7680                    )
 7681                })?
 7682                .await?;
 7683            anyhow::Ok(navigated)
 7684        })
 7685    }
 7686
 7687    pub fn open_url(&mut self, _: &OpenUrl, cx: &mut ViewContext<Self>) {
 7688        let position = self.selections.newest_anchor().head();
 7689        let Some((buffer, buffer_position)) =
 7690            self.buffer.read(cx).text_anchor_for_position(position, cx)
 7691        else {
 7692            return;
 7693        };
 7694
 7695        cx.spawn(|editor, mut cx| async move {
 7696            if let Some((_, url)) = find_url(&buffer, buffer_position, cx.clone()) {
 7697                editor.update(&mut cx, |_, cx| {
 7698                    cx.open_url(&url);
 7699                })
 7700            } else {
 7701                Ok(())
 7702            }
 7703        })
 7704        .detach();
 7705    }
 7706
 7707    pub(crate) fn navigate_to_hover_links(
 7708        &mut self,
 7709        kind: Option<GotoDefinitionKind>,
 7710        mut definitions: Vec<HoverLink>,
 7711        split: bool,
 7712        cx: &mut ViewContext<Editor>,
 7713    ) -> Task<Result<bool>> {
 7714        // If there is one definition, just open it directly
 7715        if definitions.len() == 1 {
 7716            let definition = definitions.pop().unwrap();
 7717            let target_task = match definition {
 7718                HoverLink::Text(link) => Task::Ready(Some(Ok(Some(link.target)))),
 7719                HoverLink::InlayHint(lsp_location, server_id) => {
 7720                    self.compute_target_location(lsp_location, server_id, cx)
 7721                }
 7722                HoverLink::Url(url) => {
 7723                    cx.open_url(&url);
 7724                    Task::ready(Ok(None))
 7725                }
 7726            };
 7727            cx.spawn(|editor, mut cx| async move {
 7728                let target = target_task.await.context("target resolution task")?;
 7729                if let Some(target) = target {
 7730                    editor.update(&mut cx, |editor, cx| {
 7731                        let Some(workspace) = editor.workspace() else {
 7732                            return false;
 7733                        };
 7734                        let pane = workspace.read(cx).active_pane().clone();
 7735
 7736                        let range = target.range.to_offset(target.buffer.read(cx));
 7737                        let range = editor.range_for_match(&range);
 7738                        if Some(&target.buffer) == editor.buffer.read(cx).as_singleton().as_ref() {
 7739                            editor.change_selections(Some(Autoscroll::focused()), cx, |s| {
 7740                                s.select_ranges([range]);
 7741                            });
 7742                        } else {
 7743                            cx.window_context().defer(move |cx| {
 7744                                let target_editor: View<Self> =
 7745                                    workspace.update(cx, |workspace, cx| {
 7746                                        let pane = if split {
 7747                                            workspace.adjacent_pane(cx)
 7748                                        } else {
 7749                                            workspace.active_pane().clone()
 7750                                        };
 7751
 7752                                        workspace.open_project_item(pane, target.buffer.clone(), cx)
 7753                                    });
 7754                                target_editor.update(cx, |target_editor, cx| {
 7755                                    // When selecting a definition in a different buffer, disable the nav history
 7756                                    // to avoid creating a history entry at the previous cursor location.
 7757                                    pane.update(cx, |pane, _| pane.disable_history());
 7758                                    target_editor.change_selections(
 7759                                        Some(Autoscroll::focused()),
 7760                                        cx,
 7761                                        |s| {
 7762                                            s.select_ranges([range]);
 7763                                        },
 7764                                    );
 7765                                    pane.update(cx, |pane, _| pane.enable_history());
 7766                                });
 7767                            });
 7768                        }
 7769                        true
 7770                    })
 7771                } else {
 7772                    Ok(false)
 7773                }
 7774            })
 7775        } else if !definitions.is_empty() {
 7776            let replica_id = self.replica_id(cx);
 7777            cx.spawn(|editor, mut cx| async move {
 7778                let (title, location_tasks, workspace) = editor
 7779                    .update(&mut cx, |editor, cx| {
 7780                        let tab_kind = match kind {
 7781                            Some(GotoDefinitionKind::Implementation) => "Implementations",
 7782                            _ => "Definitions",
 7783                        };
 7784                        let title = definitions
 7785                            .iter()
 7786                            .find_map(|definition| match definition {
 7787                                HoverLink::Text(link) => link.origin.as_ref().map(|origin| {
 7788                                    let buffer = origin.buffer.read(cx);
 7789                                    format!(
 7790                                        "{} for {}",
 7791                                        tab_kind,
 7792                                        buffer
 7793                                            .text_for_range(origin.range.clone())
 7794                                            .collect::<String>()
 7795                                    )
 7796                                }),
 7797                                HoverLink::InlayHint(_, _) => None,
 7798                                HoverLink::Url(_) => None,
 7799                            })
 7800                            .unwrap_or(tab_kind.to_string());
 7801                        let location_tasks = definitions
 7802                            .into_iter()
 7803                            .map(|definition| match definition {
 7804                                HoverLink::Text(link) => Task::Ready(Some(Ok(Some(link.target)))),
 7805                                HoverLink::InlayHint(lsp_location, server_id) => {
 7806                                    editor.compute_target_location(lsp_location, server_id, cx)
 7807                                }
 7808                                HoverLink::Url(_) => Task::ready(Ok(None)),
 7809                            })
 7810                            .collect::<Vec<_>>();
 7811                        (title, location_tasks, editor.workspace().clone())
 7812                    })
 7813                    .context("location tasks preparation")?;
 7814
 7815                let locations = futures::future::join_all(location_tasks)
 7816                    .await
 7817                    .into_iter()
 7818                    .filter_map(|location| location.transpose())
 7819                    .collect::<Result<_>>()
 7820                    .context("location tasks")?;
 7821
 7822                let Some(workspace) = workspace else {
 7823                    return Ok(false);
 7824                };
 7825                let opened = workspace
 7826                    .update(&mut cx, |workspace, cx| {
 7827                        Self::open_locations_in_multibuffer(
 7828                            workspace, locations, replica_id, title, split, cx,
 7829                        )
 7830                    })
 7831                    .ok();
 7832
 7833                anyhow::Ok(opened.is_some())
 7834            })
 7835        } else {
 7836            Task::ready(Ok(false))
 7837        }
 7838    }
 7839
 7840    fn compute_target_location(
 7841        &self,
 7842        lsp_location: lsp::Location,
 7843        server_id: LanguageServerId,
 7844        cx: &mut ViewContext<Editor>,
 7845    ) -> Task<anyhow::Result<Option<Location>>> {
 7846        let Some(project) = self.project.clone() else {
 7847            return Task::Ready(Some(Ok(None)));
 7848        };
 7849
 7850        cx.spawn(move |editor, mut cx| async move {
 7851            let location_task = editor.update(&mut cx, |editor, cx| {
 7852                project.update(cx, |project, cx| {
 7853                    let language_server_name =
 7854                        editor.buffer.read(cx).as_singleton().and_then(|buffer| {
 7855                            project
 7856                                .language_server_for_buffer(buffer.read(cx), server_id, cx)
 7857                                .map(|(lsp_adapter, _)| lsp_adapter.name.clone())
 7858                        });
 7859                    language_server_name.map(|language_server_name| {
 7860                        project.open_local_buffer_via_lsp(
 7861                            lsp_location.uri.clone(),
 7862                            server_id,
 7863                            language_server_name,
 7864                            cx,
 7865                        )
 7866                    })
 7867                })
 7868            })?;
 7869            let location = match location_task {
 7870                Some(task) => Some({
 7871                    let target_buffer_handle = task.await.context("open local buffer")?;
 7872                    let range = target_buffer_handle.update(&mut cx, |target_buffer, _| {
 7873                        let target_start = target_buffer
 7874                            .clip_point_utf16(point_from_lsp(lsp_location.range.start), Bias::Left);
 7875                        let target_end = target_buffer
 7876                            .clip_point_utf16(point_from_lsp(lsp_location.range.end), Bias::Left);
 7877                        target_buffer.anchor_after(target_start)
 7878                            ..target_buffer.anchor_before(target_end)
 7879                    })?;
 7880                    Location {
 7881                        buffer: target_buffer_handle,
 7882                        range,
 7883                    }
 7884                }),
 7885                None => None,
 7886            };
 7887            Ok(location)
 7888        })
 7889    }
 7890
 7891    pub fn find_all_references(
 7892        &mut self,
 7893        _: &FindAllReferences,
 7894        cx: &mut ViewContext<Self>,
 7895    ) -> Option<Task<Result<()>>> {
 7896        let multi_buffer = self.buffer.read(cx);
 7897        let selection = self.selections.newest::<usize>(cx);
 7898        let head = selection.head();
 7899
 7900        let multi_buffer_snapshot = multi_buffer.snapshot(cx);
 7901        let head_anchor = multi_buffer_snapshot.anchor_at(
 7902            head,
 7903            if head < selection.tail() {
 7904                Bias::Right
 7905            } else {
 7906                Bias::Left
 7907            },
 7908        );
 7909
 7910        match self
 7911            .find_all_references_task_sources
 7912            .binary_search_by(|anchor| anchor.cmp(&head_anchor, &multi_buffer_snapshot))
 7913        {
 7914            Ok(_) => {
 7915                log::info!(
 7916                    "Ignoring repeated FindAllReferences invocation with the position of already running task"
 7917                );
 7918                return None;
 7919            }
 7920            Err(i) => {
 7921                self.find_all_references_task_sources.insert(i, head_anchor);
 7922            }
 7923        }
 7924
 7925        let (buffer, head) = multi_buffer.text_anchor_for_position(head, cx)?;
 7926        let replica_id = self.replica_id(cx);
 7927        let workspace = self.workspace()?;
 7928        let project = workspace.read(cx).project().clone();
 7929        let references = project.update(cx, |project, cx| project.references(&buffer, head, cx));
 7930        Some(cx.spawn(|editor, mut cx| async move {
 7931            let _cleanup = defer({
 7932                let mut cx = cx.clone();
 7933                move || {
 7934                    let _ = editor.update(&mut cx, |editor, _| {
 7935                        if let Ok(i) =
 7936                            editor
 7937                                .find_all_references_task_sources
 7938                                .binary_search_by(|anchor| {
 7939                                    anchor.cmp(&head_anchor, &multi_buffer_snapshot)
 7940                                })
 7941                        {
 7942                            editor.find_all_references_task_sources.remove(i);
 7943                        }
 7944                    });
 7945                }
 7946            });
 7947
 7948            let locations = references.await?;
 7949            if locations.is_empty() {
 7950                return anyhow::Ok(());
 7951            }
 7952
 7953            workspace.update(&mut cx, |workspace, cx| {
 7954                let title = locations
 7955                    .first()
 7956                    .as_ref()
 7957                    .map(|location| {
 7958                        let buffer = location.buffer.read(cx);
 7959                        format!(
 7960                            "References to `{}`",
 7961                            buffer
 7962                                .text_for_range(location.range.clone())
 7963                                .collect::<String>()
 7964                        )
 7965                    })
 7966                    .unwrap();
 7967                Self::open_locations_in_multibuffer(
 7968                    workspace, locations, replica_id, title, false, cx,
 7969                );
 7970            })
 7971        }))
 7972    }
 7973
 7974    /// Opens a multibuffer with the given project locations in it
 7975    pub fn open_locations_in_multibuffer(
 7976        workspace: &mut Workspace,
 7977        mut locations: Vec<Location>,
 7978        replica_id: ReplicaId,
 7979        title: String,
 7980        split: bool,
 7981        cx: &mut ViewContext<Workspace>,
 7982    ) {
 7983        // If there are multiple definitions, open them in a multibuffer
 7984        locations.sort_by_key(|location| location.buffer.read(cx).remote_id());
 7985        let mut locations = locations.into_iter().peekable();
 7986        let mut ranges_to_highlight = Vec::new();
 7987        let capability = workspace.project().read(cx).capability();
 7988
 7989        let excerpt_buffer = cx.new_model(|cx| {
 7990            let mut multibuffer = MultiBuffer::new(replica_id, capability);
 7991            while let Some(location) = locations.next() {
 7992                let buffer = location.buffer.read(cx);
 7993                let mut ranges_for_buffer = Vec::new();
 7994                let range = location.range.to_offset(buffer);
 7995                ranges_for_buffer.push(range.clone());
 7996
 7997                while let Some(next_location) = locations.peek() {
 7998                    if next_location.buffer == location.buffer {
 7999                        ranges_for_buffer.push(next_location.range.to_offset(buffer));
 8000                        locations.next();
 8001                    } else {
 8002                        break;
 8003                    }
 8004                }
 8005
 8006                ranges_for_buffer.sort_by_key(|range| (range.start, Reverse(range.end)));
 8007                ranges_to_highlight.extend(multibuffer.push_excerpts_with_context_lines(
 8008                    location.buffer.clone(),
 8009                    ranges_for_buffer,
 8010                    1,
 8011                    cx,
 8012                ))
 8013            }
 8014
 8015            multibuffer.with_title(title)
 8016        });
 8017
 8018        let editor = cx.new_view(|cx| {
 8019            Editor::for_multibuffer(excerpt_buffer, Some(workspace.project().clone()), cx)
 8020        });
 8021        editor.update(cx, |editor, cx| {
 8022            editor.highlight_background::<Self>(
 8023                &ranges_to_highlight,
 8024                |theme| theme.editor_highlighted_line_background,
 8025                cx,
 8026            );
 8027        });
 8028        if split {
 8029            workspace.split_item(SplitDirection::Right, Box::new(editor), cx);
 8030        } else {
 8031            workspace.add_item_to_active_pane(Box::new(editor), cx);
 8032        }
 8033    }
 8034
 8035    pub fn rename(&mut self, _: &Rename, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
 8036        use language::ToOffset as _;
 8037
 8038        let project = self.project.clone()?;
 8039        let selection = self.selections.newest_anchor().clone();
 8040        let (cursor_buffer, cursor_buffer_position) = self
 8041            .buffer
 8042            .read(cx)
 8043            .text_anchor_for_position(selection.head(), cx)?;
 8044        let (tail_buffer, _) = self
 8045            .buffer
 8046            .read(cx)
 8047            .text_anchor_for_position(selection.tail(), cx)?;
 8048        if tail_buffer != cursor_buffer {
 8049            return None;
 8050        }
 8051
 8052        let snapshot = cursor_buffer.read(cx).snapshot();
 8053        let cursor_buffer_offset = cursor_buffer_position.to_offset(&snapshot);
 8054        let prepare_rename = project.update(cx, |project, cx| {
 8055            project.prepare_rename(cursor_buffer.clone(), cursor_buffer_offset, cx)
 8056        });
 8057        drop(snapshot);
 8058
 8059        Some(cx.spawn(|this, mut cx| async move {
 8060            let rename_range = if let Some(range) = prepare_rename.await? {
 8061                Some(range)
 8062            } else {
 8063                this.update(&mut cx, |this, cx| {
 8064                    let buffer = this.buffer.read(cx).snapshot(cx);
 8065                    let mut buffer_highlights = this
 8066                        .document_highlights_for_position(selection.head(), &buffer)
 8067                        .filter(|highlight| {
 8068                            highlight.start.excerpt_id == selection.head().excerpt_id
 8069                                && highlight.end.excerpt_id == selection.head().excerpt_id
 8070                        });
 8071                    buffer_highlights
 8072                        .next()
 8073                        .map(|highlight| highlight.start.text_anchor..highlight.end.text_anchor)
 8074                })?
 8075            };
 8076            if let Some(rename_range) = rename_range {
 8077                this.update(&mut cx, |this, cx| {
 8078                    let snapshot = cursor_buffer.read(cx).snapshot();
 8079                    let rename_buffer_range = rename_range.to_offset(&snapshot);
 8080                    let cursor_offset_in_rename_range =
 8081                        cursor_buffer_offset.saturating_sub(rename_buffer_range.start);
 8082
 8083                    this.take_rename(false, cx);
 8084                    let buffer = this.buffer.read(cx).read(cx);
 8085                    let cursor_offset = selection.head().to_offset(&buffer);
 8086                    let rename_start = cursor_offset.saturating_sub(cursor_offset_in_rename_range);
 8087                    let rename_end = rename_start + rename_buffer_range.len();
 8088                    let range = buffer.anchor_before(rename_start)..buffer.anchor_after(rename_end);
 8089                    let mut old_highlight_id = None;
 8090                    let old_name: Arc<str> = buffer
 8091                        .chunks(rename_start..rename_end, true)
 8092                        .map(|chunk| {
 8093                            if old_highlight_id.is_none() {
 8094                                old_highlight_id = chunk.syntax_highlight_id;
 8095                            }
 8096                            chunk.text
 8097                        })
 8098                        .collect::<String>()
 8099                        .into();
 8100
 8101                    drop(buffer);
 8102
 8103                    // Position the selection in the rename editor so that it matches the current selection.
 8104                    this.show_local_selections = false;
 8105                    let rename_editor = cx.new_view(|cx| {
 8106                        let mut editor = Editor::single_line(cx);
 8107                        editor.buffer.update(cx, |buffer, cx| {
 8108                            buffer.edit([(0..0, old_name.clone())], None, cx)
 8109                        });
 8110                        editor.select_all(&SelectAll, cx);
 8111                        editor
 8112                    });
 8113
 8114                    let write_highlights =
 8115                        this.clear_background_highlights::<DocumentHighlightWrite>(cx);
 8116                    let read_highlights =
 8117                        this.clear_background_highlights::<DocumentHighlightRead>(cx);
 8118                    let ranges = write_highlights
 8119                        .iter()
 8120                        .flat_map(|(_, ranges)| ranges.iter())
 8121                        .chain(read_highlights.iter().flat_map(|(_, ranges)| ranges.iter()))
 8122                        .cloned()
 8123                        .collect();
 8124
 8125                    this.highlight_text::<Rename>(
 8126                        ranges,
 8127                        HighlightStyle {
 8128                            fade_out: Some(0.6),
 8129                            ..Default::default()
 8130                        },
 8131                        cx,
 8132                    );
 8133                    let rename_focus_handle = rename_editor.focus_handle(cx);
 8134                    cx.focus(&rename_focus_handle);
 8135                    let block_id = this.insert_blocks(
 8136                        [BlockProperties {
 8137                            style: BlockStyle::Flex,
 8138                            position: range.start,
 8139                            height: 1,
 8140                            render: Box::new({
 8141                                let rename_editor = rename_editor.clone();
 8142                                move |cx: &mut BlockContext| {
 8143                                    let mut text_style = cx.editor_style.text.clone();
 8144                                    if let Some(highlight_style) = old_highlight_id
 8145                                        .and_then(|h| h.style(&cx.editor_style.syntax))
 8146                                    {
 8147                                        text_style = text_style.highlight(highlight_style);
 8148                                    }
 8149                                    div()
 8150                                        .pl(cx.anchor_x)
 8151                                        .child(EditorElement::new(
 8152                                            &rename_editor,
 8153                                            EditorStyle {
 8154                                                background: cx.theme().system().transparent,
 8155                                                local_player: cx.editor_style.local_player,
 8156                                                text: text_style,
 8157                                                scrollbar_width: cx.editor_style.scrollbar_width,
 8158                                                syntax: cx.editor_style.syntax.clone(),
 8159                                                status: cx.editor_style.status.clone(),
 8160                                                inlay_hints_style: HighlightStyle {
 8161                                                    color: Some(cx.theme().status().hint),
 8162                                                    font_weight: Some(FontWeight::BOLD),
 8163                                                    ..HighlightStyle::default()
 8164                                                },
 8165                                                suggestions_style: HighlightStyle {
 8166                                                    color: Some(cx.theme().status().predictive),
 8167                                                    ..HighlightStyle::default()
 8168                                                },
 8169                                            },
 8170                                        ))
 8171                                        .into_any_element()
 8172                                }
 8173                            }),
 8174                            disposition: BlockDisposition::Below,
 8175                        }],
 8176                        Some(Autoscroll::fit()),
 8177                        cx,
 8178                    )[0];
 8179                    this.pending_rename = Some(RenameState {
 8180                        range,
 8181                        old_name,
 8182                        editor: rename_editor,
 8183                        block_id,
 8184                    });
 8185                })?;
 8186            }
 8187
 8188            Ok(())
 8189        }))
 8190    }
 8191
 8192    pub fn confirm_rename(
 8193        &mut self,
 8194        _: &ConfirmRename,
 8195        cx: &mut ViewContext<Self>,
 8196    ) -> Option<Task<Result<()>>> {
 8197        let rename = self.take_rename(false, cx)?;
 8198        let workspace = self.workspace()?;
 8199        let (start_buffer, start) = self
 8200            .buffer
 8201            .read(cx)
 8202            .text_anchor_for_position(rename.range.start, cx)?;
 8203        let (end_buffer, end) = self
 8204            .buffer
 8205            .read(cx)
 8206            .text_anchor_for_position(rename.range.end, cx)?;
 8207        if start_buffer != end_buffer {
 8208            return None;
 8209        }
 8210
 8211        let buffer = start_buffer;
 8212        let range = start..end;
 8213        let old_name = rename.old_name;
 8214        let new_name = rename.editor.read(cx).text(cx);
 8215
 8216        let rename = workspace
 8217            .read(cx)
 8218            .project()
 8219            .clone()
 8220            .update(cx, |project, cx| {
 8221                project.perform_rename(buffer.clone(), range.start, new_name.clone(), true, cx)
 8222            });
 8223        let workspace = workspace.downgrade();
 8224
 8225        Some(cx.spawn(|editor, mut cx| async move {
 8226            let project_transaction = rename.await?;
 8227            Self::open_project_transaction(
 8228                &editor,
 8229                workspace,
 8230                project_transaction,
 8231                format!("Rename: {}{}", old_name, new_name),
 8232                cx.clone(),
 8233            )
 8234            .await?;
 8235
 8236            editor.update(&mut cx, |editor, cx| {
 8237                editor.refresh_document_highlights(cx);
 8238            })?;
 8239            Ok(())
 8240        }))
 8241    }
 8242
 8243    fn take_rename(
 8244        &mut self,
 8245        moving_cursor: bool,
 8246        cx: &mut ViewContext<Self>,
 8247    ) -> Option<RenameState> {
 8248        let rename = self.pending_rename.take()?;
 8249        if rename.editor.focus_handle(cx).is_focused(cx) {
 8250            cx.focus(&self.focus_handle);
 8251        }
 8252
 8253        self.remove_blocks(
 8254            [rename.block_id].into_iter().collect(),
 8255            Some(Autoscroll::fit()),
 8256            cx,
 8257        );
 8258        self.clear_highlights::<Rename>(cx);
 8259        self.show_local_selections = true;
 8260
 8261        if moving_cursor {
 8262            let rename_editor = rename.editor.read(cx);
 8263            let cursor_in_rename_editor = rename_editor.selections.newest::<usize>(cx).head();
 8264
 8265            // Update the selection to match the position of the selection inside
 8266            // the rename editor.
 8267            let snapshot = self.buffer.read(cx).read(cx);
 8268            let rename_range = rename.range.to_offset(&snapshot);
 8269            let cursor_in_editor = snapshot
 8270                .clip_offset(rename_range.start + cursor_in_rename_editor, Bias::Left)
 8271                .min(rename_range.end);
 8272            drop(snapshot);
 8273
 8274            self.change_selections(None, cx, |s| {
 8275                s.select_ranges(vec![cursor_in_editor..cursor_in_editor])
 8276            });
 8277        } else {
 8278            self.refresh_document_highlights(cx);
 8279        }
 8280
 8281        Some(rename)
 8282    }
 8283
 8284    pub fn pending_rename(&self) -> Option<&RenameState> {
 8285        self.pending_rename.as_ref()
 8286    }
 8287
 8288    fn format(&mut self, _: &Format, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
 8289        let project = match &self.project {
 8290            Some(project) => project.clone(),
 8291            None => return None,
 8292        };
 8293
 8294        Some(self.perform_format(project, FormatTrigger::Manual, cx))
 8295    }
 8296
 8297    fn perform_format(
 8298        &mut self,
 8299        project: Model<Project>,
 8300        trigger: FormatTrigger,
 8301        cx: &mut ViewContext<Self>,
 8302    ) -> Task<Result<()>> {
 8303        let buffer = self.buffer().clone();
 8304        let mut buffers = buffer.read(cx).all_buffers();
 8305        if trigger == FormatTrigger::Save {
 8306            buffers.retain(|buffer| buffer.read(cx).is_dirty());
 8307        }
 8308
 8309        let mut timeout = cx.background_executor().timer(FORMAT_TIMEOUT).fuse();
 8310        let format = project.update(cx, |project, cx| project.format(buffers, true, trigger, cx));
 8311
 8312        cx.spawn(|_, mut cx| async move {
 8313            let transaction = futures::select_biased! {
 8314                () = timeout => {
 8315                    log::warn!("timed out waiting for formatting");
 8316                    None
 8317                }
 8318                transaction = format.log_err().fuse() => transaction,
 8319            };
 8320
 8321            buffer
 8322                .update(&mut cx, |buffer, cx| {
 8323                    if let Some(transaction) = transaction {
 8324                        if !buffer.is_singleton() {
 8325                            buffer.push_transaction(&transaction.0, cx);
 8326                        }
 8327                    }
 8328
 8329                    cx.notify();
 8330                })
 8331                .ok();
 8332
 8333            Ok(())
 8334        })
 8335    }
 8336
 8337    fn restart_language_server(&mut self, _: &RestartLanguageServer, cx: &mut ViewContext<Self>) {
 8338        if let Some(project) = self.project.clone() {
 8339            self.buffer.update(cx, |multi_buffer, cx| {
 8340                project.update(cx, |project, cx| {
 8341                    project.restart_language_servers_for_buffers(multi_buffer.all_buffers(), cx);
 8342                });
 8343            })
 8344        }
 8345    }
 8346
 8347    fn show_character_palette(&mut self, _: &ShowCharacterPalette, cx: &mut ViewContext<Self>) {
 8348        cx.show_character_palette();
 8349    }
 8350
 8351    fn refresh_active_diagnostics(&mut self, cx: &mut ViewContext<Editor>) {
 8352        if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
 8353            let buffer = self.buffer.read(cx).snapshot(cx);
 8354            let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
 8355            let is_valid = buffer
 8356                .diagnostics_in_range::<_, usize>(active_diagnostics.primary_range.clone(), false)
 8357                .any(|entry| {
 8358                    entry.diagnostic.is_primary
 8359                        && !entry.range.is_empty()
 8360                        && entry.range.start == primary_range_start
 8361                        && entry.diagnostic.message == active_diagnostics.primary_message
 8362                });
 8363
 8364            if is_valid != active_diagnostics.is_valid {
 8365                active_diagnostics.is_valid = is_valid;
 8366                let mut new_styles = HashMap::default();
 8367                for (block_id, diagnostic) in &active_diagnostics.blocks {
 8368                    new_styles.insert(
 8369                        *block_id,
 8370                        diagnostic_block_renderer(diagnostic.clone(), is_valid),
 8371                    );
 8372                }
 8373                self.display_map
 8374                    .update(cx, |display_map, _| display_map.replace_blocks(new_styles));
 8375            }
 8376        }
 8377    }
 8378
 8379    fn activate_diagnostics(&mut self, group_id: usize, cx: &mut ViewContext<Self>) -> bool {
 8380        self.dismiss_diagnostics(cx);
 8381        self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
 8382            let buffer = self.buffer.read(cx).snapshot(cx);
 8383
 8384            let mut primary_range = None;
 8385            let mut primary_message = None;
 8386            let mut group_end = Point::zero();
 8387            let diagnostic_group = buffer
 8388                .diagnostic_group::<Point>(group_id)
 8389                .map(|entry| {
 8390                    if entry.range.end > group_end {
 8391                        group_end = entry.range.end;
 8392                    }
 8393                    if entry.diagnostic.is_primary {
 8394                        primary_range = Some(entry.range.clone());
 8395                        primary_message = Some(entry.diagnostic.message.clone());
 8396                    }
 8397                    entry
 8398                })
 8399                .collect::<Vec<_>>();
 8400            let primary_range = primary_range?;
 8401            let primary_message = primary_message?;
 8402            let primary_range =
 8403                buffer.anchor_after(primary_range.start)..buffer.anchor_before(primary_range.end);
 8404
 8405            let blocks = display_map
 8406                .insert_blocks(
 8407                    diagnostic_group.iter().map(|entry| {
 8408                        let diagnostic = entry.diagnostic.clone();
 8409                        let message_height = diagnostic.message.matches('\n').count() as u8 + 1;
 8410                        BlockProperties {
 8411                            style: BlockStyle::Fixed,
 8412                            position: buffer.anchor_after(entry.range.start),
 8413                            height: message_height,
 8414                            render: diagnostic_block_renderer(diagnostic, true),
 8415                            disposition: BlockDisposition::Below,
 8416                        }
 8417                    }),
 8418                    cx,
 8419                )
 8420                .into_iter()
 8421                .zip(diagnostic_group.into_iter().map(|entry| entry.diagnostic))
 8422                .collect();
 8423
 8424            Some(ActiveDiagnosticGroup {
 8425                primary_range,
 8426                primary_message,
 8427                blocks,
 8428                is_valid: true,
 8429            })
 8430        });
 8431        self.active_diagnostics.is_some()
 8432    }
 8433
 8434    fn dismiss_diagnostics(&mut self, cx: &mut ViewContext<Self>) {
 8435        if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
 8436            self.display_map.update(cx, |display_map, cx| {
 8437                display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx);
 8438            });
 8439            cx.notify();
 8440        }
 8441    }
 8442
 8443    pub fn set_selections_from_remote(
 8444        &mut self,
 8445        selections: Vec<Selection<Anchor>>,
 8446        pending_selection: Option<Selection<Anchor>>,
 8447        cx: &mut ViewContext<Self>,
 8448    ) {
 8449        let old_cursor_position = self.selections.newest_anchor().head();
 8450        self.selections.change_with(cx, |s| {
 8451            s.select_anchors(selections);
 8452            if let Some(pending_selection) = pending_selection {
 8453                s.set_pending(pending_selection, SelectMode::Character);
 8454            } else {
 8455                s.clear_pending();
 8456            }
 8457        });
 8458        self.selections_did_change(false, &old_cursor_position, cx);
 8459    }
 8460
 8461    fn push_to_selection_history(&mut self) {
 8462        self.selection_history.push(SelectionHistoryEntry {
 8463            selections: self.selections.disjoint_anchors(),
 8464            select_next_state: self.select_next_state.clone(),
 8465            select_prev_state: self.select_prev_state.clone(),
 8466            add_selections_state: self.add_selections_state.clone(),
 8467        });
 8468    }
 8469
 8470    pub fn transact(
 8471        &mut self,
 8472        cx: &mut ViewContext<Self>,
 8473        update: impl FnOnce(&mut Self, &mut ViewContext<Self>),
 8474    ) -> Option<TransactionId> {
 8475        self.start_transaction_at(Instant::now(), cx);
 8476        update(self, cx);
 8477        self.end_transaction_at(Instant::now(), cx)
 8478    }
 8479
 8480    fn start_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
 8481        self.end_selection(cx);
 8482        if let Some(tx_id) = self
 8483            .buffer
 8484            .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx))
 8485        {
 8486            self.selection_history
 8487                .insert_transaction(tx_id, self.selections.disjoint_anchors());
 8488            cx.emit(EditorEvent::TransactionBegun {
 8489                transaction_id: tx_id,
 8490            })
 8491        }
 8492    }
 8493
 8494    fn end_transaction_at(
 8495        &mut self,
 8496        now: Instant,
 8497        cx: &mut ViewContext<Self>,
 8498    ) -> Option<TransactionId> {
 8499        if let Some(tx_id) = self
 8500            .buffer
 8501            .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
 8502        {
 8503            if let Some((_, end_selections)) = self.selection_history.transaction_mut(tx_id) {
 8504                *end_selections = Some(self.selections.disjoint_anchors());
 8505            } else {
 8506                log::error!("unexpectedly ended a transaction that wasn't started by this editor");
 8507            }
 8508
 8509            cx.emit(EditorEvent::Edited);
 8510            Some(tx_id)
 8511        } else {
 8512            None
 8513        }
 8514    }
 8515
 8516    pub fn fold(&mut self, _: &actions::Fold, cx: &mut ViewContext<Self>) {
 8517        let mut fold_ranges = Vec::new();
 8518
 8519        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8520
 8521        let selections = self.selections.all_adjusted(cx);
 8522        for selection in selections {
 8523            let range = selection.range().sorted();
 8524            let buffer_start_row = range.start.row;
 8525
 8526            for row in (0..=range.end.row).rev() {
 8527                let fold_range = display_map.foldable_range(row);
 8528
 8529                if let Some(fold_range) = fold_range {
 8530                    if fold_range.end.row >= buffer_start_row {
 8531                        fold_ranges.push(fold_range);
 8532                        if row <= range.start.row {
 8533                            break;
 8534                        }
 8535                    }
 8536                }
 8537            }
 8538        }
 8539
 8540        self.fold_ranges(fold_ranges, true, cx);
 8541    }
 8542
 8543    pub fn fold_at(&mut self, fold_at: &FoldAt, cx: &mut ViewContext<Self>) {
 8544        let buffer_row = fold_at.buffer_row;
 8545        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8546
 8547        if let Some(fold_range) = display_map.foldable_range(buffer_row) {
 8548            let autoscroll = self
 8549                .selections
 8550                .all::<Point>(cx)
 8551                .iter()
 8552                .any(|selection| fold_range.overlaps(&selection.range()));
 8553
 8554            self.fold_ranges(std::iter::once(fold_range), autoscroll, cx);
 8555        }
 8556    }
 8557
 8558    pub fn unfold_lines(&mut self, _: &UnfoldLines, cx: &mut ViewContext<Self>) {
 8559        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8560        let buffer = &display_map.buffer_snapshot;
 8561        let selections = self.selections.all::<Point>(cx);
 8562        let ranges = selections
 8563            .iter()
 8564            .map(|s| {
 8565                let range = s.display_range(&display_map).sorted();
 8566                let mut start = range.start.to_point(&display_map);
 8567                let mut end = range.end.to_point(&display_map);
 8568                start.column = 0;
 8569                end.column = buffer.line_len(end.row);
 8570                start..end
 8571            })
 8572            .collect::<Vec<_>>();
 8573
 8574        self.unfold_ranges(ranges, true, true, cx);
 8575    }
 8576
 8577    pub fn unfold_at(&mut self, unfold_at: &UnfoldAt, cx: &mut ViewContext<Self>) {
 8578        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8579
 8580        let intersection_range = Point::new(unfold_at.buffer_row, 0)
 8581            ..Point::new(
 8582                unfold_at.buffer_row,
 8583                display_map.buffer_snapshot.line_len(unfold_at.buffer_row),
 8584            );
 8585
 8586        let autoscroll = self
 8587            .selections
 8588            .all::<Point>(cx)
 8589            .iter()
 8590            .any(|selection| selection.range().overlaps(&intersection_range));
 8591
 8592        self.unfold_ranges(std::iter::once(intersection_range), true, autoscroll, cx)
 8593    }
 8594
 8595    pub fn fold_selected_ranges(&mut self, _: &FoldSelectedRanges, cx: &mut ViewContext<Self>) {
 8596        let selections = self.selections.all::<Point>(cx);
 8597        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8598        let line_mode = self.selections.line_mode;
 8599        let ranges = selections.into_iter().map(|s| {
 8600            if line_mode {
 8601                let start = Point::new(s.start.row, 0);
 8602                let end = Point::new(s.end.row, display_map.buffer_snapshot.line_len(s.end.row));
 8603                start..end
 8604            } else {
 8605                s.start..s.end
 8606            }
 8607        });
 8608        self.fold_ranges(ranges, true, cx);
 8609    }
 8610
 8611    pub fn fold_ranges<T: ToOffset + Clone>(
 8612        &mut self,
 8613        ranges: impl IntoIterator<Item = Range<T>>,
 8614        auto_scroll: bool,
 8615        cx: &mut ViewContext<Self>,
 8616    ) {
 8617        let mut ranges = ranges.into_iter().peekable();
 8618        if ranges.peek().is_some() {
 8619            self.display_map.update(cx, |map, cx| map.fold(ranges, cx));
 8620
 8621            if auto_scroll {
 8622                self.request_autoscroll(Autoscroll::fit(), cx);
 8623            }
 8624
 8625            cx.notify();
 8626        }
 8627    }
 8628
 8629    pub fn unfold_ranges<T: ToOffset + Clone>(
 8630        &mut self,
 8631        ranges: impl IntoIterator<Item = Range<T>>,
 8632        inclusive: bool,
 8633        auto_scroll: bool,
 8634        cx: &mut ViewContext<Self>,
 8635    ) {
 8636        let mut ranges = ranges.into_iter().peekable();
 8637        if ranges.peek().is_some() {
 8638            self.display_map
 8639                .update(cx, |map, cx| map.unfold(ranges, inclusive, cx));
 8640            if auto_scroll {
 8641                self.request_autoscroll(Autoscroll::fit(), cx);
 8642            }
 8643
 8644            cx.notify();
 8645        }
 8646    }
 8647
 8648    pub fn set_gutter_hovered(&mut self, hovered: bool, cx: &mut ViewContext<Self>) {
 8649        if hovered != self.gutter_hovered {
 8650            self.gutter_hovered = hovered;
 8651            cx.notify();
 8652        }
 8653    }
 8654
 8655    pub fn insert_blocks(
 8656        &mut self,
 8657        blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
 8658        autoscroll: Option<Autoscroll>,
 8659        cx: &mut ViewContext<Self>,
 8660    ) -> Vec<BlockId> {
 8661        let blocks = self
 8662            .display_map
 8663            .update(cx, |display_map, cx| display_map.insert_blocks(blocks, cx));
 8664        if let Some(autoscroll) = autoscroll {
 8665            self.request_autoscroll(autoscroll, cx);
 8666        }
 8667        blocks
 8668    }
 8669
 8670    pub fn replace_blocks(
 8671        &mut self,
 8672        blocks: HashMap<BlockId, RenderBlock>,
 8673        autoscroll: Option<Autoscroll>,
 8674        cx: &mut ViewContext<Self>,
 8675    ) {
 8676        self.display_map
 8677            .update(cx, |display_map, _| display_map.replace_blocks(blocks));
 8678        if let Some(autoscroll) = autoscroll {
 8679            self.request_autoscroll(autoscroll, cx);
 8680        }
 8681    }
 8682
 8683    pub fn remove_blocks(
 8684        &mut self,
 8685        block_ids: HashSet<BlockId>,
 8686        autoscroll: Option<Autoscroll>,
 8687        cx: &mut ViewContext<Self>,
 8688    ) {
 8689        self.display_map.update(cx, |display_map, cx| {
 8690            display_map.remove_blocks(block_ids, cx)
 8691        });
 8692        if let Some(autoscroll) = autoscroll {
 8693            self.request_autoscroll(autoscroll, cx);
 8694        }
 8695    }
 8696
 8697    pub fn longest_row(&self, cx: &mut AppContext) -> u32 {
 8698        self.display_map
 8699            .update(cx, |map, cx| map.snapshot(cx))
 8700            .longest_row()
 8701    }
 8702
 8703    pub fn max_point(&self, cx: &mut AppContext) -> DisplayPoint {
 8704        self.display_map
 8705            .update(cx, |map, cx| map.snapshot(cx))
 8706            .max_point()
 8707    }
 8708
 8709    pub fn text(&self, cx: &AppContext) -> String {
 8710        self.buffer.read(cx).read(cx).text()
 8711    }
 8712
 8713    pub fn text_option(&self, cx: &AppContext) -> Option<String> {
 8714        let text = self.text(cx);
 8715        let text = text.trim();
 8716
 8717        if text.is_empty() {
 8718            return None;
 8719        }
 8720
 8721        Some(text.to_string())
 8722    }
 8723
 8724    pub fn set_text(&mut self, text: impl Into<Arc<str>>, cx: &mut ViewContext<Self>) {
 8725        self.transact(cx, |this, cx| {
 8726            this.buffer
 8727                .read(cx)
 8728                .as_singleton()
 8729                .expect("you can only call set_text on editors for singleton buffers")
 8730                .update(cx, |buffer, cx| buffer.set_text(text, cx));
 8731        });
 8732    }
 8733
 8734    pub fn display_text(&self, cx: &mut AppContext) -> String {
 8735        self.display_map
 8736            .update(cx, |map, cx| map.snapshot(cx))
 8737            .text()
 8738    }
 8739
 8740    pub fn wrap_guides(&self, cx: &AppContext) -> SmallVec<[(usize, bool); 2]> {
 8741        let mut wrap_guides = smallvec::smallvec![];
 8742
 8743        if self.show_wrap_guides == Some(false) {
 8744            return wrap_guides;
 8745        }
 8746
 8747        let settings = self.buffer.read(cx).settings_at(0, cx);
 8748        if settings.show_wrap_guides {
 8749            if let SoftWrap::Column(soft_wrap) = self.soft_wrap_mode(cx) {
 8750                wrap_guides.push((soft_wrap as usize, true));
 8751            }
 8752            wrap_guides.extend(settings.wrap_guides.iter().map(|guide| (*guide, false)))
 8753        }
 8754
 8755        wrap_guides
 8756    }
 8757
 8758    pub fn soft_wrap_mode(&self, cx: &AppContext) -> SoftWrap {
 8759        let settings = self.buffer.read(cx).settings_at(0, cx);
 8760        let mode = self
 8761            .soft_wrap_mode_override
 8762            .unwrap_or_else(|| settings.soft_wrap);
 8763        match mode {
 8764            language_settings::SoftWrap::None => SoftWrap::None,
 8765            language_settings::SoftWrap::EditorWidth => SoftWrap::EditorWidth,
 8766            language_settings::SoftWrap::PreferredLineLength => {
 8767                SoftWrap::Column(settings.preferred_line_length)
 8768            }
 8769        }
 8770    }
 8771
 8772    pub fn set_soft_wrap_mode(
 8773        &mut self,
 8774        mode: language_settings::SoftWrap,
 8775        cx: &mut ViewContext<Self>,
 8776    ) {
 8777        self.soft_wrap_mode_override = Some(mode);
 8778        cx.notify();
 8779    }
 8780
 8781    pub fn set_style(&mut self, style: EditorStyle, cx: &mut ViewContext<Self>) {
 8782        let rem_size = cx.rem_size();
 8783        self.display_map.update(cx, |map, cx| {
 8784            map.set_font(
 8785                style.text.font(),
 8786                style.text.font_size.to_pixels(rem_size),
 8787                cx,
 8788            )
 8789        });
 8790        self.style = Some(style);
 8791    }
 8792
 8793    #[cfg(any(test, feature = "test-support"))]
 8794    pub fn style(&self) -> Option<&EditorStyle> {
 8795        self.style.as_ref()
 8796    }
 8797
 8798    // Called by the element. This method is not designed to be called outside of the editor
 8799    // element's layout code because it does not notify when rewrapping is computed synchronously.
 8800    pub(crate) fn set_wrap_width(&self, width: Option<Pixels>, cx: &mut AppContext) -> bool {
 8801        self.display_map
 8802            .update(cx, |map, cx| map.set_wrap_width(width, cx))
 8803    }
 8804
 8805    pub fn toggle_soft_wrap(&mut self, _: &ToggleSoftWrap, cx: &mut ViewContext<Self>) {
 8806        if self.soft_wrap_mode_override.is_some() {
 8807            self.soft_wrap_mode_override.take();
 8808        } else {
 8809            let soft_wrap = match self.soft_wrap_mode(cx) {
 8810                SoftWrap::None => language_settings::SoftWrap::EditorWidth,
 8811                SoftWrap::EditorWidth | SoftWrap::Column(_) => language_settings::SoftWrap::None,
 8812            };
 8813            self.soft_wrap_mode_override = Some(soft_wrap);
 8814        }
 8815        cx.notify();
 8816    }
 8817
 8818    pub fn toggle_line_numbers(&mut self, _: &ToggleLineNumbers, cx: &mut ViewContext<Self>) {
 8819        let mut editor_settings = EditorSettings::get_global(cx).clone();
 8820        editor_settings.gutter.line_numbers = !editor_settings.gutter.line_numbers;
 8821        EditorSettings::override_global(editor_settings, cx);
 8822    }
 8823
 8824    pub fn set_show_gutter(&mut self, show_gutter: bool, cx: &mut ViewContext<Self>) {
 8825        self.show_gutter = show_gutter;
 8826        cx.notify();
 8827    }
 8828
 8829    pub fn set_show_wrap_guides(&mut self, show_gutter: bool, cx: &mut ViewContext<Self>) {
 8830        self.show_wrap_guides = Some(show_gutter);
 8831        cx.notify();
 8832    }
 8833
 8834    pub fn reveal_in_finder(&mut self, _: &RevealInFinder, cx: &mut ViewContext<Self>) {
 8835        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
 8836            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
 8837                cx.reveal_path(&file.abs_path(cx));
 8838            }
 8839        }
 8840    }
 8841
 8842    pub fn copy_path(&mut self, _: &CopyPath, cx: &mut ViewContext<Self>) {
 8843        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
 8844            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
 8845                if let Some(path) = file.abs_path(cx).to_str() {
 8846                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
 8847                }
 8848            }
 8849        }
 8850    }
 8851
 8852    pub fn copy_relative_path(&mut self, _: &CopyRelativePath, cx: &mut ViewContext<Self>) {
 8853        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
 8854            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
 8855                if let Some(path) = file.path().to_str() {
 8856                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
 8857                }
 8858            }
 8859        }
 8860    }
 8861
 8862    pub fn toggle_git_blame(&mut self, _: &ToggleGitBlame, cx: &mut ViewContext<Self>) {
 8863        if !self.show_git_blame {
 8864            if let Err(error) = self.show_git_blame_internal(cx) {
 8865                log::error!("failed to toggle on 'git blame': {}", error);
 8866                return;
 8867            }
 8868            self.show_git_blame = true
 8869        } else {
 8870            self.blame_subscription.take();
 8871            self.blame.take();
 8872            self.show_git_blame = false
 8873        }
 8874
 8875        cx.notify();
 8876    }
 8877
 8878    fn show_git_blame_internal(&mut self, cx: &mut ViewContext<Self>) -> Result<()> {
 8879        if let Some(project) = self.project.as_ref() {
 8880            let Some(buffer) = self.buffer().read(cx).as_singleton() else {
 8881                anyhow::bail!("git blame not available in multi buffers")
 8882            };
 8883
 8884            let project = project.clone();
 8885            let blame = cx.new_model(|cx| GitBlame::new(buffer, project, cx));
 8886            self.blame_subscription = Some(cx.observe(&blame, |_, _, cx| cx.notify()));
 8887            self.blame = Some(blame);
 8888        }
 8889
 8890        Ok(())
 8891    }
 8892
 8893    pub fn blame(&self) -> Option<&Model<GitBlame>> {
 8894        self.blame.as_ref()
 8895    }
 8896
 8897    fn get_permalink_to_line(&mut self, cx: &mut ViewContext<Self>) -> Result<url::Url> {
 8898        let (path, repo) = maybe!({
 8899            let project_handle = self.project.as_ref()?.clone();
 8900            let project = project_handle.read(cx);
 8901            let buffer = self.buffer().read(cx).as_singleton()?;
 8902            let path = buffer
 8903                .read(cx)
 8904                .file()?
 8905                .as_local()?
 8906                .path()
 8907                .to_str()?
 8908                .to_string();
 8909            let repo = project.get_repo(&buffer.read(cx).project_path(cx)?, cx)?;
 8910            Some((path, repo))
 8911        })
 8912        .ok_or_else(|| anyhow!("unable to open git repository"))?;
 8913
 8914        const REMOTE_NAME: &str = "origin";
 8915        let origin_url = repo
 8916            .lock()
 8917            .remote_url(REMOTE_NAME)
 8918            .ok_or_else(|| anyhow!("remote \"{REMOTE_NAME}\" not found"))?;
 8919        let sha = repo
 8920            .lock()
 8921            .head_sha()
 8922            .ok_or_else(|| anyhow!("failed to read HEAD SHA"))?;
 8923        let selections = self.selections.all::<Point>(cx);
 8924        let selection = selections.iter().peekable().next();
 8925
 8926        build_permalink(BuildPermalinkParams {
 8927            remote_url: &origin_url,
 8928            sha: &sha,
 8929            path: &path,
 8930            selection: selection.map(|selection| {
 8931                let range = selection.range();
 8932                let start = range.start.row;
 8933                let end = range.end.row;
 8934                start..end
 8935            }),
 8936        })
 8937    }
 8938
 8939    pub fn copy_permalink_to_line(&mut self, _: &CopyPermalinkToLine, cx: &mut ViewContext<Self>) {
 8940        let permalink = self.get_permalink_to_line(cx);
 8941
 8942        match permalink {
 8943            Ok(permalink) => {
 8944                cx.write_to_clipboard(ClipboardItem::new(permalink.to_string()));
 8945            }
 8946            Err(err) => {
 8947                let message = format!("Failed to copy permalink: {err}");
 8948
 8949                Err::<(), anyhow::Error>(err).log_err();
 8950
 8951                if let Some(workspace) = self.workspace() {
 8952                    workspace.update(cx, |workspace, cx| {
 8953                        workspace.show_toast(Toast::new(0x156a5f9ee, message), cx)
 8954                    })
 8955                }
 8956            }
 8957        }
 8958    }
 8959
 8960    pub fn open_permalink_to_line(&mut self, _: &OpenPermalinkToLine, cx: &mut ViewContext<Self>) {
 8961        let permalink = self.get_permalink_to_line(cx);
 8962
 8963        match permalink {
 8964            Ok(permalink) => {
 8965                cx.open_url(permalink.as_ref());
 8966            }
 8967            Err(err) => {
 8968                let message = format!("Failed to open permalink: {err}");
 8969
 8970                Err::<(), anyhow::Error>(err).log_err();
 8971
 8972                if let Some(workspace) = self.workspace() {
 8973                    workspace.update(cx, |workspace, cx| {
 8974                        workspace.show_toast(Toast::new(0x45a8978, message), cx)
 8975                    })
 8976                }
 8977            }
 8978        }
 8979    }
 8980
 8981    /// Adds or removes (on `None` color) a highlight for the rows corresponding to the anchor range given.
 8982    /// On matching anchor range, replaces the old highlight; does not clear the other existing highlights.
 8983    /// If multiple anchor ranges will produce highlights for the same row, the last range added will be used.
 8984    pub fn highlight_rows<T: 'static>(
 8985        &mut self,
 8986        rows: Range<Anchor>,
 8987        color: Option<Hsla>,
 8988        cx: &mut ViewContext<Self>,
 8989    ) {
 8990        let multi_buffer_snapshot = self.buffer().read(cx).snapshot(cx);
 8991        match self.highlighted_rows.entry(TypeId::of::<T>()) {
 8992            hash_map::Entry::Occupied(o) => {
 8993                let row_highlights = o.into_mut();
 8994                let existing_highlight_index =
 8995                    row_highlights.binary_search_by(|(_, highlight_range, _)| {
 8996                        highlight_range
 8997                            .start
 8998                            .cmp(&rows.start, &multi_buffer_snapshot)
 8999                            .then(highlight_range.end.cmp(&rows.end, &multi_buffer_snapshot))
 9000                    });
 9001                match color {
 9002                    Some(color) => {
 9003                        let insert_index = match existing_highlight_index {
 9004                            Ok(i) => i,
 9005                            Err(i) => i,
 9006                        };
 9007                        row_highlights.insert(
 9008                            insert_index,
 9009                            (post_inc(&mut self.highlight_order), rows, color),
 9010                        );
 9011                    }
 9012                    None => {
 9013                        if let Ok(i) = existing_highlight_index {
 9014                            row_highlights.remove(i);
 9015                        }
 9016                    }
 9017                }
 9018            }
 9019            hash_map::Entry::Vacant(v) => {
 9020                if let Some(color) = color {
 9021                    v.insert(vec![(post_inc(&mut self.highlight_order), rows, color)]);
 9022                }
 9023            }
 9024        }
 9025    }
 9026
 9027    /// Clear all anchor ranges for a certain highlight context type, so no corresponding rows will be highlighted.
 9028    pub fn clear_row_highlights<T: 'static>(&mut self) {
 9029        self.highlighted_rows.remove(&TypeId::of::<T>());
 9030    }
 9031
 9032    /// For a highlight given context type, gets all anchor ranges that will be used for row highlighting.
 9033    pub fn highlighted_rows<T: 'static>(
 9034        &self,
 9035    ) -> Option<impl Iterator<Item = (&Range<Anchor>, &Hsla)>> {
 9036        Some(
 9037            self.highlighted_rows
 9038                .get(&TypeId::of::<T>())?
 9039                .iter()
 9040                .map(|(_, range, color)| (range, color)),
 9041        )
 9042    }
 9043
 9044    // Merges all anchor ranges for all context types ever set, picking the last highlight added in case of a row conflict.
 9045    // Rerturns a map of display rows that are highlighted and their corresponding highlight color.
 9046    pub fn highlighted_display_rows(&mut self, cx: &mut WindowContext) -> BTreeMap<u32, Hsla> {
 9047        let snapshot = self.snapshot(cx);
 9048        let mut used_highlight_orders = HashMap::default();
 9049        self.highlighted_rows
 9050            .iter()
 9051            .flat_map(|(_, highlighted_rows)| highlighted_rows.iter())
 9052            .fold(
 9053                BTreeMap::<u32, Hsla>::new(),
 9054                |mut unique_rows, (highlight_order, anchor_range, hsla)| {
 9055                    let start_row = anchor_range.start.to_display_point(&snapshot).row();
 9056                    let end_row = anchor_range.end.to_display_point(&snapshot).row();
 9057                    for row in start_row..=end_row {
 9058                        let used_index =
 9059                            used_highlight_orders.entry(row).or_insert(*highlight_order);
 9060                        if highlight_order >= used_index {
 9061                            *used_index = *highlight_order;
 9062                            unique_rows.insert(row, *hsla);
 9063                        }
 9064                    }
 9065                    unique_rows
 9066                },
 9067            )
 9068    }
 9069
 9070    pub fn highlight_background<T: 'static>(
 9071        &mut self,
 9072        ranges: &[Range<Anchor>],
 9073        color_fetcher: fn(&ThemeColors) -> Hsla,
 9074        cx: &mut ViewContext<Self>,
 9075    ) {
 9076        let snapshot = self.snapshot(cx);
 9077        // this is to try and catch a panic sooner
 9078        for range in ranges {
 9079            snapshot
 9080                .buffer_snapshot
 9081                .summary_for_anchor::<usize>(&range.start);
 9082            snapshot
 9083                .buffer_snapshot
 9084                .summary_for_anchor::<usize>(&range.end);
 9085        }
 9086
 9087        self.background_highlights
 9088            .insert(TypeId::of::<T>(), (color_fetcher, Arc::from(ranges)));
 9089        self.scrollbar_marker_state.dirty = true;
 9090        cx.notify();
 9091    }
 9092
 9093    pub fn clear_background_highlights<T: 'static>(
 9094        &mut self,
 9095        cx: &mut ViewContext<Self>,
 9096    ) -> Option<BackgroundHighlight> {
 9097        let text_highlights = self.background_highlights.remove(&TypeId::of::<T>())?;
 9098        if !text_highlights.1.is_empty() {
 9099            self.scrollbar_marker_state.dirty = true;
 9100            cx.notify();
 9101        }
 9102        Some(text_highlights)
 9103    }
 9104
 9105    #[cfg(feature = "test-support")]
 9106    pub fn all_text_background_highlights(
 9107        &mut self,
 9108        cx: &mut ViewContext<Self>,
 9109    ) -> Vec<(Range<DisplayPoint>, Hsla)> {
 9110        let snapshot = self.snapshot(cx);
 9111        let buffer = &snapshot.buffer_snapshot;
 9112        let start = buffer.anchor_before(0);
 9113        let end = buffer.anchor_after(buffer.len());
 9114        let theme = cx.theme().colors();
 9115        self.background_highlights_in_range(start..end, &snapshot, theme)
 9116    }
 9117
 9118    fn document_highlights_for_position<'a>(
 9119        &'a self,
 9120        position: Anchor,
 9121        buffer: &'a MultiBufferSnapshot,
 9122    ) -> impl 'a + Iterator<Item = &Range<Anchor>> {
 9123        let read_highlights = self
 9124            .background_highlights
 9125            .get(&TypeId::of::<DocumentHighlightRead>())
 9126            .map(|h| &h.1);
 9127        let write_highlights = self
 9128            .background_highlights
 9129            .get(&TypeId::of::<DocumentHighlightWrite>())
 9130            .map(|h| &h.1);
 9131        let left_position = position.bias_left(buffer);
 9132        let right_position = position.bias_right(buffer);
 9133        read_highlights
 9134            .into_iter()
 9135            .chain(write_highlights)
 9136            .flat_map(move |ranges| {
 9137                let start_ix = match ranges.binary_search_by(|probe| {
 9138                    let cmp = probe.end.cmp(&left_position, buffer);
 9139                    if cmp.is_ge() {
 9140                        Ordering::Greater
 9141                    } else {
 9142                        Ordering::Less
 9143                    }
 9144                }) {
 9145                    Ok(i) | Err(i) => i,
 9146                };
 9147
 9148                ranges[start_ix..]
 9149                    .iter()
 9150                    .take_while(move |range| range.start.cmp(&right_position, buffer).is_le())
 9151            })
 9152    }
 9153
 9154    pub fn has_background_highlights<T: 'static>(&self) -> bool {
 9155        self.background_highlights
 9156            .get(&TypeId::of::<T>())
 9157            .map_or(false, |(_, highlights)| !highlights.is_empty())
 9158    }
 9159
 9160    pub fn background_highlights_in_range(
 9161        &self,
 9162        search_range: Range<Anchor>,
 9163        display_snapshot: &DisplaySnapshot,
 9164        theme: &ThemeColors,
 9165    ) -> Vec<(Range<DisplayPoint>, Hsla)> {
 9166        let mut results = Vec::new();
 9167        for (color_fetcher, ranges) in self.background_highlights.values() {
 9168            let color = color_fetcher(theme);
 9169            let start_ix = match ranges.binary_search_by(|probe| {
 9170                let cmp = probe
 9171                    .end
 9172                    .cmp(&search_range.start, &display_snapshot.buffer_snapshot);
 9173                if cmp.is_gt() {
 9174                    Ordering::Greater
 9175                } else {
 9176                    Ordering::Less
 9177                }
 9178            }) {
 9179                Ok(i) | Err(i) => i,
 9180            };
 9181            for range in &ranges[start_ix..] {
 9182                if range
 9183                    .start
 9184                    .cmp(&search_range.end, &display_snapshot.buffer_snapshot)
 9185                    .is_ge()
 9186                {
 9187                    break;
 9188                }
 9189
 9190                let start = range.start.to_display_point(&display_snapshot);
 9191                let end = range.end.to_display_point(&display_snapshot);
 9192                results.push((start..end, color))
 9193            }
 9194        }
 9195        results
 9196    }
 9197
 9198    pub fn background_highlight_row_ranges<T: 'static>(
 9199        &self,
 9200        search_range: Range<Anchor>,
 9201        display_snapshot: &DisplaySnapshot,
 9202        count: usize,
 9203    ) -> Vec<RangeInclusive<DisplayPoint>> {
 9204        let mut results = Vec::new();
 9205        let Some((_, ranges)) = self.background_highlights.get(&TypeId::of::<T>()) else {
 9206            return vec![];
 9207        };
 9208
 9209        let start_ix = match ranges.binary_search_by(|probe| {
 9210            let cmp = probe
 9211                .end
 9212                .cmp(&search_range.start, &display_snapshot.buffer_snapshot);
 9213            if cmp.is_gt() {
 9214                Ordering::Greater
 9215            } else {
 9216                Ordering::Less
 9217            }
 9218        }) {
 9219            Ok(i) | Err(i) => i,
 9220        };
 9221        let mut push_region = |start: Option<Point>, end: Option<Point>| {
 9222            if let (Some(start_display), Some(end_display)) = (start, end) {
 9223                results.push(
 9224                    start_display.to_display_point(display_snapshot)
 9225                        ..=end_display.to_display_point(display_snapshot),
 9226                );
 9227            }
 9228        };
 9229        let mut start_row: Option<Point> = None;
 9230        let mut end_row: Option<Point> = None;
 9231        if ranges.len() > count {
 9232            return Vec::new();
 9233        }
 9234        for range in &ranges[start_ix..] {
 9235            if range
 9236                .start
 9237                .cmp(&search_range.end, &display_snapshot.buffer_snapshot)
 9238                .is_ge()
 9239            {
 9240                break;
 9241            }
 9242            let end = range.end.to_point(&display_snapshot.buffer_snapshot);
 9243            if let Some(current_row) = &end_row {
 9244                if end.row == current_row.row {
 9245                    continue;
 9246                }
 9247            }
 9248            let start = range.start.to_point(&display_snapshot.buffer_snapshot);
 9249            if start_row.is_none() {
 9250                assert_eq!(end_row, None);
 9251                start_row = Some(start);
 9252                end_row = Some(end);
 9253                continue;
 9254            }
 9255            if let Some(current_end) = end_row.as_mut() {
 9256                if start.row > current_end.row + 1 {
 9257                    push_region(start_row, end_row);
 9258                    start_row = Some(start);
 9259                    end_row = Some(end);
 9260                } else {
 9261                    // Merge two hunks.
 9262                    *current_end = end;
 9263                }
 9264            } else {
 9265                unreachable!();
 9266            }
 9267        }
 9268        // We might still have a hunk that was not rendered (if there was a search hit on the last line)
 9269        push_region(start_row, end_row);
 9270        results
 9271    }
 9272
 9273    /// Get the text ranges corresponding to the redaction query
 9274    pub fn redacted_ranges(
 9275        &self,
 9276        search_range: Range<Anchor>,
 9277        display_snapshot: &DisplaySnapshot,
 9278        cx: &WindowContext,
 9279    ) -> Vec<Range<DisplayPoint>> {
 9280        display_snapshot
 9281            .buffer_snapshot
 9282            .redacted_ranges(search_range, |file| {
 9283                if let Some(file) = file {
 9284                    file.is_private()
 9285                        && EditorSettings::get(Some(file.as_ref().into()), cx).redact_private_values
 9286                } else {
 9287                    false
 9288                }
 9289            })
 9290            .map(|range| {
 9291                range.start.to_display_point(display_snapshot)
 9292                    ..range.end.to_display_point(display_snapshot)
 9293            })
 9294            .collect()
 9295    }
 9296
 9297    pub fn highlight_text<T: 'static>(
 9298        &mut self,
 9299        ranges: Vec<Range<Anchor>>,
 9300        style: HighlightStyle,
 9301        cx: &mut ViewContext<Self>,
 9302    ) {
 9303        self.display_map.update(cx, |map, _| {
 9304            map.highlight_text(TypeId::of::<T>(), ranges, style)
 9305        });
 9306        cx.notify();
 9307    }
 9308
 9309    pub(crate) fn highlight_inlays<T: 'static>(
 9310        &mut self,
 9311        highlights: Vec<InlayHighlight>,
 9312        style: HighlightStyle,
 9313        cx: &mut ViewContext<Self>,
 9314    ) {
 9315        self.display_map.update(cx, |map, _| {
 9316            map.highlight_inlays(TypeId::of::<T>(), highlights, style)
 9317        });
 9318        cx.notify();
 9319    }
 9320
 9321    pub fn text_highlights<'a, T: 'static>(
 9322        &'a self,
 9323        cx: &'a AppContext,
 9324    ) -> Option<(HighlightStyle, &'a [Range<Anchor>])> {
 9325        self.display_map.read(cx).text_highlights(TypeId::of::<T>())
 9326    }
 9327
 9328    pub fn clear_highlights<T: 'static>(&mut self, cx: &mut ViewContext<Self>) {
 9329        let cleared = self
 9330            .display_map
 9331            .update(cx, |map, _| map.clear_highlights(TypeId::of::<T>()));
 9332        if cleared {
 9333            cx.notify();
 9334        }
 9335    }
 9336
 9337    pub fn show_local_cursors(&self, cx: &WindowContext) -> bool {
 9338        (self.read_only(cx) || self.blink_manager.read(cx).visible())
 9339            && self.focus_handle.is_focused(cx)
 9340    }
 9341
 9342    fn on_buffer_changed(&mut self, _: Model<MultiBuffer>, cx: &mut ViewContext<Self>) {
 9343        cx.notify();
 9344    }
 9345
 9346    fn on_buffer_event(
 9347        &mut self,
 9348        multibuffer: Model<MultiBuffer>,
 9349        event: &multi_buffer::Event,
 9350        cx: &mut ViewContext<Self>,
 9351    ) {
 9352        match event {
 9353            multi_buffer::Event::Edited {
 9354                singleton_buffer_edited,
 9355            } => {
 9356                self.scrollbar_marker_state.dirty = true;
 9357                self.refresh_active_diagnostics(cx);
 9358                self.refresh_code_actions(cx);
 9359                if self.has_active_inline_completion(cx) {
 9360                    self.update_visible_inline_completion(cx);
 9361                }
 9362                cx.emit(EditorEvent::BufferEdited);
 9363                cx.emit(SearchEvent::MatchesInvalidated);
 9364
 9365                if *singleton_buffer_edited {
 9366                    if let Some(project) = &self.project {
 9367                        let project = project.read(cx);
 9368                        let languages_affected = multibuffer
 9369                            .read(cx)
 9370                            .all_buffers()
 9371                            .into_iter()
 9372                            .filter_map(|buffer| {
 9373                                let buffer = buffer.read(cx);
 9374                                let language = buffer.language()?;
 9375                                if project.is_local()
 9376                                    && project.language_servers_for_buffer(buffer, cx).count() == 0
 9377                                {
 9378                                    None
 9379                                } else {
 9380                                    Some(language)
 9381                                }
 9382                            })
 9383                            .cloned()
 9384                            .collect::<HashSet<_>>();
 9385                        if !languages_affected.is_empty() {
 9386                            self.refresh_inlay_hints(
 9387                                InlayHintRefreshReason::BufferEdited(languages_affected),
 9388                                cx,
 9389                            );
 9390                        }
 9391                    }
 9392                }
 9393
 9394                let Some(project) = &self.project else { return };
 9395                let telemetry = project.read(cx).client().telemetry().clone();
 9396                telemetry.log_edit_event("editor");
 9397            }
 9398            multi_buffer::Event::ExcerptsAdded {
 9399                buffer,
 9400                predecessor,
 9401                excerpts,
 9402            } => {
 9403                cx.emit(EditorEvent::ExcerptsAdded {
 9404                    buffer: buffer.clone(),
 9405                    predecessor: *predecessor,
 9406                    excerpts: excerpts.clone(),
 9407                });
 9408                self.refresh_inlay_hints(InlayHintRefreshReason::NewLinesShown, cx);
 9409            }
 9410            multi_buffer::Event::ExcerptsRemoved { ids } => {
 9411                self.refresh_inlay_hints(InlayHintRefreshReason::ExcerptsRemoved(ids.clone()), cx);
 9412                cx.emit(EditorEvent::ExcerptsRemoved { ids: ids.clone() })
 9413            }
 9414            multi_buffer::Event::Reparsed => cx.emit(EditorEvent::Reparsed),
 9415            multi_buffer::Event::LanguageChanged => {
 9416                cx.emit(EditorEvent::Reparsed);
 9417                cx.notify();
 9418            }
 9419            multi_buffer::Event::DirtyChanged => cx.emit(EditorEvent::DirtyChanged),
 9420            multi_buffer::Event::Saved => cx.emit(EditorEvent::Saved),
 9421            multi_buffer::Event::FileHandleChanged | multi_buffer::Event::Reloaded => {
 9422                cx.emit(EditorEvent::TitleChanged)
 9423            }
 9424            multi_buffer::Event::DiffBaseChanged => {
 9425                self.scrollbar_marker_state.dirty = true;
 9426                cx.emit(EditorEvent::DiffBaseChanged);
 9427                cx.notify();
 9428            }
 9429            multi_buffer::Event::Closed => cx.emit(EditorEvent::Closed),
 9430            multi_buffer::Event::DiagnosticsUpdated => {
 9431                self.refresh_active_diagnostics(cx);
 9432                self.scrollbar_marker_state.dirty = true;
 9433                cx.notify();
 9434            }
 9435            _ => {}
 9436        };
 9437    }
 9438
 9439    fn on_display_map_changed(&mut self, _: Model<DisplayMap>, cx: &mut ViewContext<Self>) {
 9440        cx.notify();
 9441    }
 9442
 9443    fn settings_changed(&mut self, cx: &mut ViewContext<Self>) {
 9444        self.refresh_inline_completion(true, cx);
 9445        self.refresh_inlay_hints(
 9446            InlayHintRefreshReason::SettingsChange(inlay_hint_settings(
 9447                self.selections.newest_anchor().head(),
 9448                &self.buffer.read(cx).snapshot(cx),
 9449                cx,
 9450            )),
 9451            cx,
 9452        );
 9453        let editor_settings = EditorSettings::get_global(cx);
 9454        self.scroll_manager.vertical_scroll_margin = editor_settings.vertical_scroll_margin;
 9455        self.show_breadcrumbs = editor_settings.toolbar.breadcrumbs;
 9456        cx.notify();
 9457    }
 9458
 9459    pub fn set_searchable(&mut self, searchable: bool) {
 9460        self.searchable = searchable;
 9461    }
 9462
 9463    pub fn searchable(&self) -> bool {
 9464        self.searchable
 9465    }
 9466
 9467    fn open_excerpts_in_split(&mut self, _: &OpenExcerptsSplit, cx: &mut ViewContext<Self>) {
 9468        self.open_excerpts_common(true, cx)
 9469    }
 9470
 9471    fn open_excerpts(&mut self, _: &OpenExcerpts, cx: &mut ViewContext<Self>) {
 9472        self.open_excerpts_common(false, cx)
 9473    }
 9474
 9475    fn open_excerpts_common(&mut self, split: bool, cx: &mut ViewContext<Self>) {
 9476        let buffer = self.buffer.read(cx);
 9477        if buffer.is_singleton() {
 9478            cx.propagate();
 9479            return;
 9480        }
 9481
 9482        let Some(workspace) = self.workspace() else {
 9483            cx.propagate();
 9484            return;
 9485        };
 9486
 9487        let mut new_selections_by_buffer = HashMap::default();
 9488        for selection in self.selections.all::<usize>(cx) {
 9489            for (buffer, mut range, _) in
 9490                buffer.range_to_buffer_ranges(selection.start..selection.end, cx)
 9491            {
 9492                if selection.reversed {
 9493                    mem::swap(&mut range.start, &mut range.end);
 9494                }
 9495                new_selections_by_buffer
 9496                    .entry(buffer)
 9497                    .or_insert(Vec::new())
 9498                    .push(range)
 9499            }
 9500        }
 9501
 9502        // We defer the pane interaction because we ourselves are a workspace item
 9503        // and activating a new item causes the pane to call a method on us reentrantly,
 9504        // which panics if we're on the stack.
 9505        cx.window_context().defer(move |cx| {
 9506            workspace.update(cx, |workspace, cx| {
 9507                let pane = if split {
 9508                    workspace.adjacent_pane(cx)
 9509                } else {
 9510                    workspace.active_pane().clone()
 9511                };
 9512
 9513                for (buffer, ranges) in new_selections_by_buffer {
 9514                    let editor = workspace.open_project_item::<Self>(pane.clone(), buffer, cx);
 9515                    editor.update(cx, |editor, cx| {
 9516                        editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
 9517                            s.select_ranges(ranges);
 9518                        });
 9519                    });
 9520                }
 9521            })
 9522        });
 9523    }
 9524
 9525    fn jump(
 9526        &mut self,
 9527        path: ProjectPath,
 9528        position: Point,
 9529        anchor: language::Anchor,
 9530        offset_from_top: u32,
 9531        cx: &mut ViewContext<Self>,
 9532    ) {
 9533        let workspace = self.workspace();
 9534        cx.spawn(|_, mut cx| async move {
 9535            let workspace = workspace.ok_or_else(|| anyhow!("cannot jump without workspace"))?;
 9536            let editor = workspace.update(&mut cx, |workspace, cx| {
 9537                workspace.open_path(path, None, true, cx)
 9538            })?;
 9539            let editor = editor
 9540                .await?
 9541                .downcast::<Editor>()
 9542                .ok_or_else(|| anyhow!("opened item was not an editor"))?
 9543                .downgrade();
 9544            editor.update(&mut cx, |editor, cx| {
 9545                let buffer = editor
 9546                    .buffer()
 9547                    .read(cx)
 9548                    .as_singleton()
 9549                    .ok_or_else(|| anyhow!("cannot jump in a multi-buffer"))?;
 9550                let buffer = buffer.read(cx);
 9551                let cursor = if buffer.can_resolve(&anchor) {
 9552                    language::ToPoint::to_point(&anchor, buffer)
 9553                } else {
 9554                    buffer.clip_point(position, Bias::Left)
 9555                };
 9556
 9557                let nav_history = editor.nav_history.take();
 9558                editor.change_selections(
 9559                    Some(Autoscroll::top_relative(offset_from_top as usize)),
 9560                    cx,
 9561                    |s| {
 9562                        s.select_ranges([cursor..cursor]);
 9563                    },
 9564                );
 9565                editor.nav_history = nav_history;
 9566
 9567                anyhow::Ok(())
 9568            })??;
 9569
 9570            anyhow::Ok(())
 9571        })
 9572        .detach_and_log_err(cx);
 9573    }
 9574
 9575    fn marked_text_ranges(&self, cx: &AppContext) -> Option<Vec<Range<OffsetUtf16>>> {
 9576        let snapshot = self.buffer.read(cx).read(cx);
 9577        let (_, ranges) = self.text_highlights::<InputComposition>(cx)?;
 9578        Some(
 9579            ranges
 9580                .iter()
 9581                .map(move |range| {
 9582                    range.start.to_offset_utf16(&snapshot)..range.end.to_offset_utf16(&snapshot)
 9583                })
 9584                .collect(),
 9585        )
 9586    }
 9587
 9588    fn selection_replacement_ranges(
 9589        &self,
 9590        range: Range<OffsetUtf16>,
 9591        cx: &AppContext,
 9592    ) -> Vec<Range<OffsetUtf16>> {
 9593        let selections = self.selections.all::<OffsetUtf16>(cx);
 9594        let newest_selection = selections
 9595            .iter()
 9596            .max_by_key(|selection| selection.id)
 9597            .unwrap();
 9598        let start_delta = range.start.0 as isize - newest_selection.start.0 as isize;
 9599        let end_delta = range.end.0 as isize - newest_selection.end.0 as isize;
 9600        let snapshot = self.buffer.read(cx).read(cx);
 9601        selections
 9602            .into_iter()
 9603            .map(|mut selection| {
 9604                selection.start.0 =
 9605                    (selection.start.0 as isize).saturating_add(start_delta) as usize;
 9606                selection.end.0 = (selection.end.0 as isize).saturating_add(end_delta) as usize;
 9607                snapshot.clip_offset_utf16(selection.start, Bias::Left)
 9608                    ..snapshot.clip_offset_utf16(selection.end, Bias::Right)
 9609            })
 9610            .collect()
 9611    }
 9612
 9613    fn report_editor_event(
 9614        &self,
 9615        operation: &'static str,
 9616        file_extension: Option<String>,
 9617        cx: &AppContext,
 9618    ) {
 9619        if cfg!(any(test, feature = "test-support")) {
 9620            return;
 9621        }
 9622
 9623        let Some(project) = &self.project else { return };
 9624
 9625        // If None, we are in a file without an extension
 9626        let file = self
 9627            .buffer
 9628            .read(cx)
 9629            .as_singleton()
 9630            .and_then(|b| b.read(cx).file());
 9631        let file_extension = file_extension.or(file
 9632            .as_ref()
 9633            .and_then(|file| Path::new(file.file_name(cx)).extension())
 9634            .and_then(|e| e.to_str())
 9635            .map(|a| a.to_string()));
 9636
 9637        let vim_mode = cx
 9638            .global::<SettingsStore>()
 9639            .raw_user_settings()
 9640            .get("vim_mode")
 9641            == Some(&serde_json::Value::Bool(true));
 9642        let copilot_enabled = all_language_settings(file, cx).copilot_enabled(None, None);
 9643        let copilot_enabled_for_language = self
 9644            .buffer
 9645            .read(cx)
 9646            .settings_at(0, cx)
 9647            .show_copilot_suggestions;
 9648
 9649        let telemetry = project.read(cx).client().telemetry().clone();
 9650        telemetry.report_editor_event(
 9651            file_extension,
 9652            vim_mode,
 9653            operation,
 9654            copilot_enabled,
 9655            copilot_enabled_for_language,
 9656        )
 9657    }
 9658
 9659    /// Copy the highlighted chunks to the clipboard as JSON. The format is an array of lines,
 9660    /// with each line being an array of {text, highlight} objects.
 9661    fn copy_highlight_json(&mut self, _: &CopyHighlightJson, cx: &mut ViewContext<Self>) {
 9662        let Some(buffer) = self.buffer.read(cx).as_singleton() else {
 9663            return;
 9664        };
 9665
 9666        #[derive(Serialize)]
 9667        struct Chunk<'a> {
 9668            text: String,
 9669            highlight: Option<&'a str>,
 9670        }
 9671
 9672        let snapshot = buffer.read(cx).snapshot();
 9673        let range = self
 9674            .selected_text_range(cx)
 9675            .and_then(|selected_range| {
 9676                if selected_range.is_empty() {
 9677                    None
 9678                } else {
 9679                    Some(selected_range)
 9680                }
 9681            })
 9682            .unwrap_or_else(|| 0..snapshot.len());
 9683
 9684        let chunks = snapshot.chunks(range, true);
 9685        let mut lines = Vec::new();
 9686        let mut line: VecDeque<Chunk> = VecDeque::new();
 9687
 9688        let Some(style) = self.style.as_ref() else {
 9689            return;
 9690        };
 9691
 9692        for chunk in chunks {
 9693            let highlight = chunk
 9694                .syntax_highlight_id
 9695                .and_then(|id| id.name(&style.syntax));
 9696            let mut chunk_lines = chunk.text.split('\n').peekable();
 9697            while let Some(text) = chunk_lines.next() {
 9698                let mut merged_with_last_token = false;
 9699                if let Some(last_token) = line.back_mut() {
 9700                    if last_token.highlight == highlight {
 9701                        last_token.text.push_str(text);
 9702                        merged_with_last_token = true;
 9703                    }
 9704                }
 9705
 9706                if !merged_with_last_token {
 9707                    line.push_back(Chunk {
 9708                        text: text.into(),
 9709                        highlight,
 9710                    });
 9711                }
 9712
 9713                if chunk_lines.peek().is_some() {
 9714                    if line.len() > 1 && line.front().unwrap().text.is_empty() {
 9715                        line.pop_front();
 9716                    }
 9717                    if line.len() > 1 && line.back().unwrap().text.is_empty() {
 9718                        line.pop_back();
 9719                    }
 9720
 9721                    lines.push(mem::take(&mut line));
 9722                }
 9723            }
 9724        }
 9725
 9726        let Some(lines) = serde_json::to_string_pretty(&lines).log_err() else {
 9727            return;
 9728        };
 9729        cx.write_to_clipboard(ClipboardItem::new(lines));
 9730    }
 9731
 9732    pub fn inlay_hint_cache(&self) -> &InlayHintCache {
 9733        &self.inlay_hint_cache
 9734    }
 9735
 9736    pub fn replay_insert_event(
 9737        &mut self,
 9738        text: &str,
 9739        relative_utf16_range: Option<Range<isize>>,
 9740        cx: &mut ViewContext<Self>,
 9741    ) {
 9742        if !self.input_enabled {
 9743            cx.emit(EditorEvent::InputIgnored { text: text.into() });
 9744            return;
 9745        }
 9746        if let Some(relative_utf16_range) = relative_utf16_range {
 9747            let selections = self.selections.all::<OffsetUtf16>(cx);
 9748            self.change_selections(None, cx, |s| {
 9749                let new_ranges = selections.into_iter().map(|range| {
 9750                    let start = OffsetUtf16(
 9751                        range
 9752                            .head()
 9753                            .0
 9754                            .saturating_add_signed(relative_utf16_range.start),
 9755                    );
 9756                    let end = OffsetUtf16(
 9757                        range
 9758                            .head()
 9759                            .0
 9760                            .saturating_add_signed(relative_utf16_range.end),
 9761                    );
 9762                    start..end
 9763                });
 9764                s.select_ranges(new_ranges);
 9765            });
 9766        }
 9767
 9768        self.handle_input(text, cx);
 9769    }
 9770
 9771    pub fn supports_inlay_hints(&self, cx: &AppContext) -> bool {
 9772        let Some(project) = self.project.as_ref() else {
 9773            return false;
 9774        };
 9775        let project = project.read(cx);
 9776
 9777        let mut supports = false;
 9778        self.buffer().read(cx).for_each_buffer(|buffer| {
 9779            if !supports {
 9780                supports = project
 9781                    .language_servers_for_buffer(buffer.read(cx), cx)
 9782                    .any(
 9783                        |(_, server)| match server.capabilities().inlay_hint_provider {
 9784                            Some(lsp::OneOf::Left(enabled)) => enabled,
 9785                            Some(lsp::OneOf::Right(_)) => true,
 9786                            None => false,
 9787                        },
 9788                    )
 9789            }
 9790        });
 9791        supports
 9792    }
 9793
 9794    pub fn focus(&self, cx: &mut WindowContext) {
 9795        cx.focus(&self.focus_handle)
 9796    }
 9797
 9798    pub fn is_focused(&self, cx: &WindowContext) -> bool {
 9799        self.focus_handle.is_focused(cx)
 9800    }
 9801
 9802    fn handle_focus(&mut self, cx: &mut ViewContext<Self>) {
 9803        cx.emit(EditorEvent::Focused);
 9804
 9805        if let Some(rename) = self.pending_rename.as_ref() {
 9806            let rename_editor_focus_handle = rename.editor.read(cx).focus_handle.clone();
 9807            cx.focus(&rename_editor_focus_handle);
 9808        } else {
 9809            self.blink_manager.update(cx, BlinkManager::enable);
 9810            self.show_cursor_names(cx);
 9811            self.buffer.update(cx, |buffer, cx| {
 9812                buffer.finalize_last_transaction(cx);
 9813                if self.leader_peer_id.is_none() {
 9814                    buffer.set_active_selections(
 9815                        &self.selections.disjoint_anchors(),
 9816                        self.selections.line_mode,
 9817                        self.cursor_shape,
 9818                        cx,
 9819                    );
 9820                }
 9821            });
 9822        }
 9823    }
 9824
 9825    pub fn handle_blur(&mut self, cx: &mut ViewContext<Self>) {
 9826        self.blink_manager.update(cx, BlinkManager::disable);
 9827        self.buffer
 9828            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
 9829        self.hide_context_menu(cx);
 9830        hide_hover(self, cx);
 9831        cx.emit(EditorEvent::Blurred);
 9832        cx.notify();
 9833    }
 9834
 9835    pub fn register_action<A: Action>(
 9836        &mut self,
 9837        listener: impl Fn(&A, &mut WindowContext) + 'static,
 9838    ) -> &mut Self {
 9839        let listener = Arc::new(listener);
 9840
 9841        self.editor_actions.push(Box::new(move |cx| {
 9842            let _view = cx.view().clone();
 9843            let cx = cx.window_context();
 9844            let listener = listener.clone();
 9845            cx.on_action(TypeId::of::<A>(), move |action, phase, cx| {
 9846                let action = action.downcast_ref().unwrap();
 9847                if phase == DispatchPhase::Bubble {
 9848                    listener(action, cx)
 9849                }
 9850            })
 9851        }));
 9852        self
 9853    }
 9854}
 9855
 9856pub trait CollaborationHub {
 9857    fn collaborators<'a>(&self, cx: &'a AppContext) -> &'a HashMap<PeerId, Collaborator>;
 9858    fn user_participant_indices<'a>(
 9859        &self,
 9860        cx: &'a AppContext,
 9861    ) -> &'a HashMap<u64, ParticipantIndex>;
 9862    fn user_names(&self, cx: &AppContext) -> HashMap<u64, SharedString>;
 9863}
 9864
 9865impl CollaborationHub for Model<Project> {
 9866    fn collaborators<'a>(&self, cx: &'a AppContext) -> &'a HashMap<PeerId, Collaborator> {
 9867        self.read(cx).collaborators()
 9868    }
 9869
 9870    fn user_participant_indices<'a>(
 9871        &self,
 9872        cx: &'a AppContext,
 9873    ) -> &'a HashMap<u64, ParticipantIndex> {
 9874        self.read(cx).user_store().read(cx).participant_indices()
 9875    }
 9876
 9877    fn user_names(&self, cx: &AppContext) -> HashMap<u64, SharedString> {
 9878        let this = self.read(cx);
 9879        let user_ids = this.collaborators().values().map(|c| c.user_id);
 9880        this.user_store().read_with(cx, |user_store, cx| {
 9881            user_store.participant_names(user_ids, cx)
 9882        })
 9883    }
 9884}
 9885
 9886pub trait CompletionProvider {
 9887    fn completions(
 9888        &self,
 9889        buffer: &Model<Buffer>,
 9890        buffer_position: text::Anchor,
 9891        cx: &mut ViewContext<Editor>,
 9892    ) -> Task<Result<Vec<Completion>>>;
 9893
 9894    fn resolve_completions(
 9895        &self,
 9896        completion_indices: Vec<usize>,
 9897        completions: Arc<RwLock<Box<[Completion]>>>,
 9898        cx: &mut ViewContext<Editor>,
 9899    ) -> Task<Result<bool>>;
 9900
 9901    fn apply_additional_edits_for_completion(
 9902        &self,
 9903        buffer: Model<Buffer>,
 9904        completion: Completion,
 9905        push_to_history: bool,
 9906        cx: &mut ViewContext<Editor>,
 9907    ) -> Task<Result<Option<language::Transaction>>>;
 9908}
 9909
 9910impl CompletionProvider for Model<Project> {
 9911    fn completions(
 9912        &self,
 9913        buffer: &Model<Buffer>,
 9914        buffer_position: text::Anchor,
 9915        cx: &mut ViewContext<Editor>,
 9916    ) -> Task<Result<Vec<Completion>>> {
 9917        self.update(cx, |project, cx| {
 9918            project.completions(&buffer, buffer_position, cx)
 9919        })
 9920    }
 9921
 9922    fn resolve_completions(
 9923        &self,
 9924        completion_indices: Vec<usize>,
 9925        completions: Arc<RwLock<Box<[Completion]>>>,
 9926        cx: &mut ViewContext<Editor>,
 9927    ) -> Task<Result<bool>> {
 9928        self.update(cx, |project, cx| {
 9929            project.resolve_completions(completion_indices, completions, cx)
 9930        })
 9931    }
 9932
 9933    fn apply_additional_edits_for_completion(
 9934        &self,
 9935        buffer: Model<Buffer>,
 9936        completion: Completion,
 9937        push_to_history: bool,
 9938        cx: &mut ViewContext<Editor>,
 9939    ) -> Task<Result<Option<language::Transaction>>> {
 9940        self.update(cx, |project, cx| {
 9941            project.apply_additional_edits_for_completion(buffer, completion, push_to_history, cx)
 9942        })
 9943    }
 9944}
 9945
 9946fn inlay_hint_settings(
 9947    location: Anchor,
 9948    snapshot: &MultiBufferSnapshot,
 9949    cx: &mut ViewContext<'_, Editor>,
 9950) -> InlayHintSettings {
 9951    let file = snapshot.file_at(location);
 9952    let language = snapshot.language_at(location);
 9953    let settings = all_language_settings(file, cx);
 9954    settings
 9955        .language(language.map(|l| l.name()).as_deref())
 9956        .inlay_hints
 9957}
 9958
 9959fn consume_contiguous_rows(
 9960    contiguous_row_selections: &mut Vec<Selection<Point>>,
 9961    selection: &Selection<Point>,
 9962    display_map: &DisplaySnapshot,
 9963    selections: &mut std::iter::Peekable<std::slice::Iter<Selection<Point>>>,
 9964) -> (u32, u32) {
 9965    contiguous_row_selections.push(selection.clone());
 9966    let start_row = selection.start.row;
 9967    let mut end_row = ending_row(selection, display_map);
 9968
 9969    while let Some(next_selection) = selections.peek() {
 9970        if next_selection.start.row <= end_row {
 9971            end_row = ending_row(next_selection, display_map);
 9972            contiguous_row_selections.push(selections.next().unwrap().clone());
 9973        } else {
 9974            break;
 9975        }
 9976    }
 9977    (start_row, end_row)
 9978}
 9979
 9980fn ending_row(next_selection: &Selection<Point>, display_map: &DisplaySnapshot) -> u32 {
 9981    if next_selection.end.column > 0 || next_selection.is_empty() {
 9982        display_map.next_line_boundary(next_selection.end).0.row + 1
 9983    } else {
 9984        next_selection.end.row
 9985    }
 9986}
 9987
 9988impl EditorSnapshot {
 9989    pub fn remote_selections_in_range<'a>(
 9990        &'a self,
 9991        range: &'a Range<Anchor>,
 9992        collaboration_hub: &dyn CollaborationHub,
 9993        cx: &'a AppContext,
 9994    ) -> impl 'a + Iterator<Item = RemoteSelection> {
 9995        let participant_names = collaboration_hub.user_names(cx);
 9996        let participant_indices = collaboration_hub.user_participant_indices(cx);
 9997        let collaborators_by_peer_id = collaboration_hub.collaborators(cx);
 9998        let collaborators_by_replica_id = collaborators_by_peer_id
 9999            .iter()
10000            .map(|(_, collaborator)| (collaborator.replica_id, collaborator))
10001            .collect::<HashMap<_, _>>();
10002        self.buffer_snapshot
10003            .remote_selections_in_range(range)
10004            .filter_map(move |(replica_id, line_mode, cursor_shape, selection)| {
10005                let collaborator = collaborators_by_replica_id.get(&replica_id)?;
10006                let participant_index = participant_indices.get(&collaborator.user_id).copied();
10007                let user_name = participant_names.get(&collaborator.user_id).cloned();
10008                Some(RemoteSelection {
10009                    replica_id,
10010                    selection,
10011                    cursor_shape,
10012                    line_mode,
10013                    participant_index,
10014                    peer_id: collaborator.peer_id,
10015                    user_name,
10016                })
10017            })
10018    }
10019
10020    pub fn language_at<T: ToOffset>(&self, position: T) -> Option<&Arc<Language>> {
10021        self.display_snapshot.buffer_snapshot.language_at(position)
10022    }
10023
10024    pub fn is_focused(&self) -> bool {
10025        self.is_focused
10026    }
10027
10028    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
10029        self.placeholder_text.as_ref()
10030    }
10031
10032    pub fn scroll_position(&self) -> gpui::Point<f32> {
10033        self.scroll_anchor.scroll_position(&self.display_snapshot)
10034    }
10035
10036    pub fn gutter_dimensions(
10037        &self,
10038        font_id: FontId,
10039        font_size: Pixels,
10040        em_width: Pixels,
10041        max_line_number_width: Pixels,
10042        cx: &AppContext,
10043    ) -> GutterDimensions {
10044        if !self.show_gutter {
10045            return GutterDimensions::default();
10046        }
10047        let descent = cx.text_system().descent(font_id, font_size);
10048
10049        let show_git_gutter = matches!(
10050            ProjectSettings::get_global(cx).git.git_gutter,
10051            Some(GitGutterSetting::TrackedFiles)
10052        );
10053        let gutter_settings = EditorSettings::get_global(cx).gutter;
10054
10055        let line_gutter_width = if gutter_settings.line_numbers {
10056            // Avoid flicker-like gutter resizes when the line number gains another digit and only resize the gutter on files with N*10^5 lines.
10057            let min_width_for_number_on_gutter = em_width * 4.0;
10058            max_line_number_width.max(min_width_for_number_on_gutter)
10059        } else {
10060            0.0.into()
10061        };
10062
10063        let git_blame_entries_width = self
10064            .show_git_blame
10065            .then_some(em_width * GIT_BLAME_GUTTER_WIDTH_CHARS);
10066
10067        let mut left_padding = git_blame_entries_width.unwrap_or(Pixels::ZERO);
10068        left_padding += if gutter_settings.code_actions {
10069            em_width * 3.0
10070        } else if show_git_gutter && gutter_settings.line_numbers {
10071            em_width * 2.0
10072        } else if show_git_gutter || gutter_settings.line_numbers {
10073            em_width
10074        } else {
10075            px(0.)
10076        };
10077
10078        let right_padding = if gutter_settings.folds && gutter_settings.line_numbers {
10079            em_width * 4.0
10080        } else if gutter_settings.folds {
10081            em_width * 3.0
10082        } else if gutter_settings.line_numbers {
10083            em_width
10084        } else {
10085            px(0.)
10086        };
10087
10088        GutterDimensions {
10089            left_padding,
10090            right_padding,
10091            width: line_gutter_width + left_padding + right_padding,
10092            margin: -descent,
10093            git_blame_entries_width,
10094        }
10095    }
10096}
10097
10098impl Deref for EditorSnapshot {
10099    type Target = DisplaySnapshot;
10100
10101    fn deref(&self) -> &Self::Target {
10102        &self.display_snapshot
10103    }
10104}
10105
10106#[derive(Clone, Debug, PartialEq, Eq)]
10107pub enum EditorEvent {
10108    InputIgnored {
10109        text: Arc<str>,
10110    },
10111    InputHandled {
10112        utf16_range_to_replace: Option<Range<isize>>,
10113        text: Arc<str>,
10114    },
10115    ExcerptsAdded {
10116        buffer: Model<Buffer>,
10117        predecessor: ExcerptId,
10118        excerpts: Vec<(ExcerptId, ExcerptRange<language::Anchor>)>,
10119    },
10120    ExcerptsRemoved {
10121        ids: Vec<ExcerptId>,
10122    },
10123    BufferEdited,
10124    Edited,
10125    Reparsed,
10126    Focused,
10127    Blurred,
10128    DirtyChanged,
10129    Saved,
10130    TitleChanged,
10131    DiffBaseChanged,
10132    SelectionsChanged {
10133        local: bool,
10134    },
10135    ScrollPositionChanged {
10136        local: bool,
10137        autoscroll: bool,
10138    },
10139    Closed,
10140    TransactionUndone {
10141        transaction_id: clock::Lamport,
10142    },
10143    TransactionBegun {
10144        transaction_id: clock::Lamport,
10145    },
10146}
10147
10148impl EventEmitter<EditorEvent> for Editor {}
10149
10150impl FocusableView for Editor {
10151    fn focus_handle(&self, _cx: &AppContext) -> FocusHandle {
10152        self.focus_handle.clone()
10153    }
10154}
10155
10156impl Render for Editor {
10157    fn render<'a>(&mut self, cx: &mut ViewContext<'a, Self>) -> impl IntoElement {
10158        let settings = ThemeSettings::get_global(cx);
10159        let text_style = match self.mode {
10160            EditorMode::SingleLine | EditorMode::AutoHeight { .. } => TextStyle {
10161                color: cx.theme().colors().editor_foreground,
10162                font_family: settings.ui_font.family.clone(),
10163                font_features: settings.ui_font.features,
10164                font_size: rems(0.875).into(),
10165                font_weight: FontWeight::NORMAL,
10166                font_style: FontStyle::Normal,
10167                line_height: relative(settings.buffer_line_height.value()),
10168                background_color: None,
10169                underline: None,
10170                strikethrough: None,
10171                white_space: WhiteSpace::Normal,
10172            },
10173
10174            EditorMode::Full => TextStyle {
10175                color: cx.theme().colors().editor_foreground,
10176                font_family: settings.buffer_font.family.clone(),
10177                font_features: settings.buffer_font.features,
10178                font_size: settings.buffer_font_size(cx).into(),
10179                font_weight: FontWeight::NORMAL,
10180                font_style: FontStyle::Normal,
10181                line_height: relative(settings.buffer_line_height.value()),
10182                background_color: None,
10183                underline: None,
10184                strikethrough: None,
10185                white_space: WhiteSpace::Normal,
10186            },
10187        };
10188
10189        let background = match self.mode {
10190            EditorMode::SingleLine => cx.theme().system().transparent,
10191            EditorMode::AutoHeight { max_lines: _ } => cx.theme().system().transparent,
10192            EditorMode::Full => cx.theme().colors().editor_background,
10193        };
10194
10195        EditorElement::new(
10196            cx.view(),
10197            EditorStyle {
10198                background,
10199                local_player: cx.theme().players().local(),
10200                text: text_style,
10201                scrollbar_width: px(12.),
10202                syntax: cx.theme().syntax().clone(),
10203                status: cx.theme().status().clone(),
10204                inlay_hints_style: HighlightStyle {
10205                    color: Some(cx.theme().status().hint),
10206                    ..HighlightStyle::default()
10207                },
10208                suggestions_style: HighlightStyle {
10209                    color: Some(cx.theme().status().predictive),
10210                    ..HighlightStyle::default()
10211                },
10212            },
10213        )
10214    }
10215}
10216
10217impl ViewInputHandler for Editor {
10218    fn text_for_range(
10219        &mut self,
10220        range_utf16: Range<usize>,
10221        cx: &mut ViewContext<Self>,
10222    ) -> Option<String> {
10223        Some(
10224            self.buffer
10225                .read(cx)
10226                .read(cx)
10227                .text_for_range(OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end))
10228                .collect(),
10229        )
10230    }
10231
10232    fn selected_text_range(&mut self, cx: &mut ViewContext<Self>) -> Option<Range<usize>> {
10233        // Prevent the IME menu from appearing when holding down an alphabetic key
10234        // while input is disabled.
10235        if !self.input_enabled {
10236            return None;
10237        }
10238
10239        let range = self.selections.newest::<OffsetUtf16>(cx).range();
10240        Some(range.start.0..range.end.0)
10241    }
10242
10243    fn marked_text_range(&self, cx: &mut ViewContext<Self>) -> Option<Range<usize>> {
10244        let snapshot = self.buffer.read(cx).read(cx);
10245        let range = self.text_highlights::<InputComposition>(cx)?.1.get(0)?;
10246        Some(range.start.to_offset_utf16(&snapshot).0..range.end.to_offset_utf16(&snapshot).0)
10247    }
10248
10249    fn unmark_text(&mut self, cx: &mut ViewContext<Self>) {
10250        self.clear_highlights::<InputComposition>(cx);
10251        self.ime_transaction.take();
10252    }
10253
10254    fn replace_text_in_range(
10255        &mut self,
10256        range_utf16: Option<Range<usize>>,
10257        text: &str,
10258        cx: &mut ViewContext<Self>,
10259    ) {
10260        if !self.input_enabled {
10261            cx.emit(EditorEvent::InputIgnored { text: text.into() });
10262            return;
10263        }
10264
10265        self.transact(cx, |this, cx| {
10266            let new_selected_ranges = if let Some(range_utf16) = range_utf16 {
10267                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
10268                Some(this.selection_replacement_ranges(range_utf16, cx))
10269            } else {
10270                this.marked_text_ranges(cx)
10271            };
10272
10273            let range_to_replace = new_selected_ranges.as_ref().and_then(|ranges_to_replace| {
10274                let newest_selection_id = this.selections.newest_anchor().id;
10275                this.selections
10276                    .all::<OffsetUtf16>(cx)
10277                    .iter()
10278                    .zip(ranges_to_replace.iter())
10279                    .find_map(|(selection, range)| {
10280                        if selection.id == newest_selection_id {
10281                            Some(
10282                                (range.start.0 as isize - selection.head().0 as isize)
10283                                    ..(range.end.0 as isize - selection.head().0 as isize),
10284                            )
10285                        } else {
10286                            None
10287                        }
10288                    })
10289            });
10290
10291            cx.emit(EditorEvent::InputHandled {
10292                utf16_range_to_replace: range_to_replace,
10293                text: text.into(),
10294            });
10295
10296            if let Some(new_selected_ranges) = new_selected_ranges {
10297                this.change_selections(None, cx, |selections| {
10298                    selections.select_ranges(new_selected_ranges)
10299                });
10300                this.backspace(&Default::default(), cx);
10301            }
10302
10303            this.handle_input(text, cx);
10304        });
10305
10306        if let Some(transaction) = self.ime_transaction {
10307            self.buffer.update(cx, |buffer, cx| {
10308                buffer.group_until_transaction(transaction, cx);
10309            });
10310        }
10311
10312        self.unmark_text(cx);
10313    }
10314
10315    fn replace_and_mark_text_in_range(
10316        &mut self,
10317        range_utf16: Option<Range<usize>>,
10318        text: &str,
10319        new_selected_range_utf16: Option<Range<usize>>,
10320        cx: &mut ViewContext<Self>,
10321    ) {
10322        if !self.input_enabled {
10323            cx.emit(EditorEvent::InputIgnored { text: text.into() });
10324            return;
10325        }
10326
10327        let transaction = self.transact(cx, |this, cx| {
10328            let ranges_to_replace = if let Some(mut marked_ranges) = this.marked_text_ranges(cx) {
10329                let snapshot = this.buffer.read(cx).read(cx);
10330                if let Some(relative_range_utf16) = range_utf16.as_ref() {
10331                    for marked_range in &mut marked_ranges {
10332                        marked_range.end.0 = marked_range.start.0 + relative_range_utf16.end;
10333                        marked_range.start.0 += relative_range_utf16.start;
10334                        marked_range.start =
10335                            snapshot.clip_offset_utf16(marked_range.start, Bias::Left);
10336                        marked_range.end =
10337                            snapshot.clip_offset_utf16(marked_range.end, Bias::Right);
10338                    }
10339                }
10340                Some(marked_ranges)
10341            } else if let Some(range_utf16) = range_utf16 {
10342                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
10343                Some(this.selection_replacement_ranges(range_utf16, cx))
10344            } else {
10345                None
10346            };
10347
10348            let range_to_replace = ranges_to_replace.as_ref().and_then(|ranges_to_replace| {
10349                let newest_selection_id = this.selections.newest_anchor().id;
10350                this.selections
10351                    .all::<OffsetUtf16>(cx)
10352                    .iter()
10353                    .zip(ranges_to_replace.iter())
10354                    .find_map(|(selection, range)| {
10355                        if selection.id == newest_selection_id {
10356                            Some(
10357                                (range.start.0 as isize - selection.head().0 as isize)
10358                                    ..(range.end.0 as isize - selection.head().0 as isize),
10359                            )
10360                        } else {
10361                            None
10362                        }
10363                    })
10364            });
10365
10366            cx.emit(EditorEvent::InputHandled {
10367                utf16_range_to_replace: range_to_replace,
10368                text: text.into(),
10369            });
10370
10371            if let Some(ranges) = ranges_to_replace {
10372                this.change_selections(None, cx, |s| s.select_ranges(ranges));
10373            }
10374
10375            let marked_ranges = {
10376                let snapshot = this.buffer.read(cx).read(cx);
10377                this.selections
10378                    .disjoint_anchors()
10379                    .iter()
10380                    .map(|selection| {
10381                        selection.start.bias_left(&snapshot)..selection.end.bias_right(&snapshot)
10382                    })
10383                    .collect::<Vec<_>>()
10384            };
10385
10386            if text.is_empty() {
10387                this.unmark_text(cx);
10388            } else {
10389                this.highlight_text::<InputComposition>(
10390                    marked_ranges.clone(),
10391                    HighlightStyle {
10392                        underline: Some(UnderlineStyle {
10393                            thickness: px(1.),
10394                            color: None,
10395                            wavy: false,
10396                        }),
10397                        ..Default::default()
10398                    },
10399                    cx,
10400                );
10401            }
10402
10403            // Disable auto-closing when composing text (i.e. typing a `"` on a Brazilian keyboard)
10404            let use_autoclose = this.use_autoclose;
10405            this.set_use_autoclose(false);
10406            this.handle_input(text, cx);
10407            this.set_use_autoclose(use_autoclose);
10408
10409            if let Some(new_selected_range) = new_selected_range_utf16 {
10410                let snapshot = this.buffer.read(cx).read(cx);
10411                let new_selected_ranges = marked_ranges
10412                    .into_iter()
10413                    .map(|marked_range| {
10414                        let insertion_start = marked_range.start.to_offset_utf16(&snapshot).0;
10415                        let new_start = OffsetUtf16(new_selected_range.start + insertion_start);
10416                        let new_end = OffsetUtf16(new_selected_range.end + insertion_start);
10417                        snapshot.clip_offset_utf16(new_start, Bias::Left)
10418                            ..snapshot.clip_offset_utf16(new_end, Bias::Right)
10419                    })
10420                    .collect::<Vec<_>>();
10421
10422                drop(snapshot);
10423                this.change_selections(None, cx, |selections| {
10424                    selections.select_ranges(new_selected_ranges)
10425                });
10426            }
10427        });
10428
10429        self.ime_transaction = self.ime_transaction.or(transaction);
10430        if let Some(transaction) = self.ime_transaction {
10431            self.buffer.update(cx, |buffer, cx| {
10432                buffer.group_until_transaction(transaction, cx);
10433            });
10434        }
10435
10436        if self.text_highlights::<InputComposition>(cx).is_none() {
10437            self.ime_transaction.take();
10438        }
10439    }
10440
10441    fn bounds_for_range(
10442        &mut self,
10443        range_utf16: Range<usize>,
10444        element_bounds: gpui::Bounds<Pixels>,
10445        cx: &mut ViewContext<Self>,
10446    ) -> Option<gpui::Bounds<Pixels>> {
10447        let text_layout_details = self.text_layout_details(cx);
10448        let style = &text_layout_details.editor_style;
10449        let font_id = cx.text_system().resolve_font(&style.text.font());
10450        let font_size = style.text.font_size.to_pixels(cx.rem_size());
10451        let line_height = style.text.line_height_in_pixels(cx.rem_size());
10452        let em_width = cx
10453            .text_system()
10454            .typographic_bounds(font_id, font_size, 'm')
10455            .unwrap()
10456            .size
10457            .width;
10458
10459        let snapshot = self.snapshot(cx);
10460        let scroll_position = snapshot.scroll_position();
10461        let scroll_left = scroll_position.x * em_width;
10462
10463        let start = OffsetUtf16(range_utf16.start).to_display_point(&snapshot);
10464        let x = snapshot.x_for_display_point(start, &text_layout_details) - scroll_left
10465            + self.gutter_width;
10466        let y = line_height * (start.row() as f32 - scroll_position.y);
10467
10468        Some(Bounds {
10469            origin: element_bounds.origin + point(x, y),
10470            size: size(em_width, line_height),
10471        })
10472    }
10473}
10474
10475trait SelectionExt {
10476    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize>;
10477    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point>;
10478    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
10479    fn spanned_rows(&self, include_end_if_at_line_start: bool, map: &DisplaySnapshot)
10480        -> Range<u32>;
10481}
10482
10483impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
10484    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
10485        let start = self.start.to_point(buffer);
10486        let end = self.end.to_point(buffer);
10487        if self.reversed {
10488            end..start
10489        } else {
10490            start..end
10491        }
10492    }
10493
10494    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
10495        let start = self.start.to_offset(buffer);
10496        let end = self.end.to_offset(buffer);
10497        if self.reversed {
10498            end..start
10499        } else {
10500            start..end
10501        }
10502    }
10503
10504    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
10505        let start = self
10506            .start
10507            .to_point(&map.buffer_snapshot)
10508            .to_display_point(map);
10509        let end = self
10510            .end
10511            .to_point(&map.buffer_snapshot)
10512            .to_display_point(map);
10513        if self.reversed {
10514            end..start
10515        } else {
10516            start..end
10517        }
10518    }
10519
10520    fn spanned_rows(
10521        &self,
10522        include_end_if_at_line_start: bool,
10523        map: &DisplaySnapshot,
10524    ) -> Range<u32> {
10525        let start = self.start.to_point(&map.buffer_snapshot);
10526        let mut end = self.end.to_point(&map.buffer_snapshot);
10527        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
10528            end.row -= 1;
10529        }
10530
10531        let buffer_start = map.prev_line_boundary(start).0;
10532        let buffer_end = map.next_line_boundary(end).0;
10533        buffer_start.row..buffer_end.row + 1
10534    }
10535}
10536
10537impl<T: InvalidationRegion> InvalidationStack<T> {
10538    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
10539    where
10540        S: Clone + ToOffset,
10541    {
10542        while let Some(region) = self.last() {
10543            let all_selections_inside_invalidation_ranges =
10544                if selections.len() == region.ranges().len() {
10545                    selections
10546                        .iter()
10547                        .zip(region.ranges().iter().map(|r| r.to_offset(buffer)))
10548                        .all(|(selection, invalidation_range)| {
10549                            let head = selection.head().to_offset(buffer);
10550                            invalidation_range.start <= head && invalidation_range.end >= head
10551                        })
10552                } else {
10553                    false
10554                };
10555
10556            if all_selections_inside_invalidation_ranges {
10557                break;
10558            } else {
10559                self.pop();
10560            }
10561        }
10562    }
10563}
10564
10565impl<T> Default for InvalidationStack<T> {
10566    fn default() -> Self {
10567        Self(Default::default())
10568    }
10569}
10570
10571impl<T> Deref for InvalidationStack<T> {
10572    type Target = Vec<T>;
10573
10574    fn deref(&self) -> &Self::Target {
10575        &self.0
10576    }
10577}
10578
10579impl<T> DerefMut for InvalidationStack<T> {
10580    fn deref_mut(&mut self) -> &mut Self::Target {
10581        &mut self.0
10582    }
10583}
10584
10585impl InvalidationRegion for SnippetState {
10586    fn ranges(&self) -> &[Range<Anchor>] {
10587        &self.ranges[self.active_index]
10588    }
10589}
10590
10591pub fn diagnostic_block_renderer(diagnostic: Diagnostic, _is_valid: bool) -> RenderBlock {
10592    let (text_without_backticks, code_ranges) = highlight_diagnostic_message(&diagnostic);
10593
10594    Box::new(move |cx: &mut BlockContext| {
10595        let group_id: SharedString = cx.block_id.to_string().into();
10596
10597        let mut text_style = cx.text_style().clone();
10598        text_style.color = diagnostic_style(diagnostic.severity, true, cx.theme().status());
10599
10600        let multi_line_diagnostic = diagnostic.message.contains('\n');
10601
10602        let buttons = |diagnostic: &Diagnostic, block_id: usize| {
10603            if multi_line_diagnostic {
10604                v_flex()
10605            } else {
10606                h_flex()
10607            }
10608            .children(diagnostic.is_primary.then(|| {
10609                IconButton::new(("close-block", block_id), IconName::XCircle)
10610                    .icon_color(Color::Muted)
10611                    .size(ButtonSize::Compact)
10612                    .style(ButtonStyle::Transparent)
10613                    .visible_on_hover(group_id.clone())
10614                    .on_click(move |_click, cx| cx.dispatch_action(Box::new(Cancel)))
10615                    .tooltip(|cx| Tooltip::for_action("Close Diagnostics", &Cancel, cx))
10616            }))
10617            .child(
10618                IconButton::new(("copy-block", block_id), IconName::Copy)
10619                    .icon_color(Color::Muted)
10620                    .size(ButtonSize::Compact)
10621                    .style(ButtonStyle::Transparent)
10622                    .visible_on_hover(group_id.clone())
10623                    .on_click({
10624                        let message = diagnostic.message.clone();
10625                        move |_click, cx| cx.write_to_clipboard(ClipboardItem::new(message.clone()))
10626                    })
10627                    .tooltip(|cx| Tooltip::text("Copy diagnostic message", cx)),
10628            )
10629        };
10630
10631        let icon_size = buttons(&diagnostic, cx.block_id)
10632            .into_any_element()
10633            .measure(AvailableSpace::min_size(), cx);
10634
10635        h_flex()
10636            .id(cx.block_id)
10637            .group(group_id.clone())
10638            .relative()
10639            .size_full()
10640            .pl(cx.gutter_dimensions.width)
10641            .w(cx.max_width + cx.gutter_dimensions.width)
10642            .child(
10643                div()
10644                    .flex()
10645                    .w(cx.anchor_x - cx.gutter_dimensions.width - icon_size.width)
10646                    .flex_shrink(),
10647            )
10648            .child(buttons(&diagnostic, cx.block_id))
10649            .child(div().flex().flex_shrink_0().child(
10650                StyledText::new(text_without_backticks.clone()).with_highlights(
10651                    &text_style,
10652                    code_ranges.iter().map(|range| {
10653                        (
10654                            range.clone(),
10655                            HighlightStyle {
10656                                font_weight: Some(FontWeight::BOLD),
10657                                ..Default::default()
10658                            },
10659                        )
10660                    }),
10661                ),
10662            ))
10663            .into_any_element()
10664    })
10665}
10666
10667pub fn highlight_diagnostic_message(diagnostic: &Diagnostic) -> (SharedString, Vec<Range<usize>>) {
10668    let mut text_without_backticks = String::new();
10669    let mut code_ranges = Vec::new();
10670
10671    if let Some(source) = &diagnostic.source {
10672        text_without_backticks.push_str(&source);
10673        code_ranges.push(0..source.len());
10674        text_without_backticks.push_str(": ");
10675    }
10676
10677    let mut prev_offset = 0;
10678    let mut in_code_block = false;
10679    for (ix, _) in diagnostic
10680        .message
10681        .match_indices('`')
10682        .chain([(diagnostic.message.len(), "")])
10683    {
10684        let prev_len = text_without_backticks.len();
10685        text_without_backticks.push_str(&diagnostic.message[prev_offset..ix]);
10686        prev_offset = ix + 1;
10687        if in_code_block {
10688            code_ranges.push(prev_len..text_without_backticks.len());
10689            in_code_block = false;
10690        } else {
10691            in_code_block = true;
10692        }
10693    }
10694
10695    (text_without_backticks.into(), code_ranges)
10696}
10697
10698fn diagnostic_style(severity: DiagnosticSeverity, valid: bool, colors: &StatusColors) -> Hsla {
10699    match (severity, valid) {
10700        (DiagnosticSeverity::ERROR, true) => colors.error,
10701        (DiagnosticSeverity::ERROR, false) => colors.error,
10702        (DiagnosticSeverity::WARNING, true) => colors.warning,
10703        (DiagnosticSeverity::WARNING, false) => colors.warning,
10704        (DiagnosticSeverity::INFORMATION, true) => colors.info,
10705        (DiagnosticSeverity::INFORMATION, false) => colors.info,
10706        (DiagnosticSeverity::HINT, true) => colors.info,
10707        (DiagnosticSeverity::HINT, false) => colors.info,
10708        _ => colors.ignored,
10709    }
10710}
10711
10712pub fn styled_runs_for_code_label<'a>(
10713    label: &'a CodeLabel,
10714    syntax_theme: &'a theme::SyntaxTheme,
10715) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
10716    let fade_out = HighlightStyle {
10717        fade_out: Some(0.35),
10718        ..Default::default()
10719    };
10720
10721    let mut prev_end = label.filter_range.end;
10722    label
10723        .runs
10724        .iter()
10725        .enumerate()
10726        .flat_map(move |(ix, (range, highlight_id))| {
10727            let style = if let Some(style) = highlight_id.style(syntax_theme) {
10728                style
10729            } else {
10730                return Default::default();
10731            };
10732            let mut muted_style = style;
10733            muted_style.highlight(fade_out);
10734
10735            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
10736            if range.start >= label.filter_range.end {
10737                if range.start > prev_end {
10738                    runs.push((prev_end..range.start, fade_out));
10739                }
10740                runs.push((range.clone(), muted_style));
10741            } else if range.end <= label.filter_range.end {
10742                runs.push((range.clone(), style));
10743            } else {
10744                runs.push((range.start..label.filter_range.end, style));
10745                runs.push((label.filter_range.end..range.end, muted_style));
10746            }
10747            prev_end = cmp::max(prev_end, range.end);
10748
10749            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
10750                runs.push((prev_end..label.text.len(), fade_out));
10751            }
10752
10753            runs
10754        })
10755}
10756
10757pub(crate) fn split_words(text: &str) -> impl std::iter::Iterator<Item = &str> + '_ {
10758    let mut prev_index = 0;
10759    let mut prev_codepoint: Option<char> = None;
10760    text.char_indices()
10761        .chain([(text.len(), '\0')])
10762        .filter_map(move |(index, codepoint)| {
10763            let prev_codepoint = prev_codepoint.replace(codepoint)?;
10764            let is_boundary = index == text.len()
10765                || !prev_codepoint.is_uppercase() && codepoint.is_uppercase()
10766                || !prev_codepoint.is_alphanumeric() && codepoint.is_alphanumeric();
10767            if is_boundary {
10768                let chunk = &text[prev_index..index];
10769                prev_index = index;
10770                Some(chunk)
10771            } else {
10772                None
10773            }
10774        })
10775}
10776
10777trait RangeToAnchorExt {
10778    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor>;
10779}
10780
10781impl<T: ToOffset> RangeToAnchorExt for Range<T> {
10782    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor> {
10783        snapshot.anchor_after(self.start)..snapshot.anchor_before(self.end)
10784    }
10785}