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