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 behavior.
   15pub mod actions;
   16mod blame_entry_tooltip;
   17mod blink_manager;
   18mod clangd_ext;
   19mod code_context_menus;
   20pub mod display_map;
   21mod editor_settings;
   22mod editor_settings_controls;
   23mod element;
   24mod git;
   25mod highlight_matching_bracket;
   26mod hover_links;
   27mod hover_popover;
   28mod indent_guides;
   29mod inlay_hint_cache;
   30pub mod items;
   31mod linked_editing_ranges;
   32mod lsp_ext;
   33mod mouse_context_menu;
   34pub mod movement;
   35mod persistence;
   36mod proposed_changes_editor;
   37mod rust_analyzer_ext;
   38pub mod scroll;
   39mod selections_collection;
   40pub mod tasks;
   41
   42#[cfg(test)]
   43mod editor_tests;
   44#[cfg(test)]
   45mod inline_completion_tests;
   46mod signature_help;
   47#[cfg(any(test, feature = "test-support"))]
   48pub mod test;
   49
   50pub(crate) use actions::*;
   51pub use actions::{OpenExcerpts, OpenExcerptsSplit};
   52use aho_corasick::AhoCorasick;
   53use anyhow::{anyhow, Context as _, Result};
   54use blink_manager::BlinkManager;
   55use client::{Collaborator, ParticipantIndex};
   56use clock::ReplicaId;
   57use collections::{BTreeMap, HashMap, HashSet, VecDeque};
   58use convert_case::{Case, Casing};
   59use display_map::*;
   60pub use display_map::{DisplayPoint, FoldPlaceholder};
   61pub use editor_settings::{
   62    CurrentLineHighlight, EditorSettings, ScrollBeyondLastLine, SearchSettings, ShowScrollbar,
   63};
   64pub use editor_settings_controls::*;
   65pub use element::{
   66    CursorLayout, EditorElement, HighlightedRange, HighlightedRangeLine, PointForPosition,
   67};
   68use element::{LineWithInvisibles, PositionMap};
   69use futures::{future, FutureExt};
   70use fuzzy::StringMatchCandidate;
   71
   72use code_context_menus::{
   73    AvailableCodeAction, CodeActionContents, CodeActionsItem, CodeActionsMenu, CodeContextMenu,
   74    CompletionsMenu, ContextMenuOrigin,
   75};
   76use diff::DiffHunkStatus;
   77use git::blame::GitBlame;
   78use gpui::{
   79    div, impl_actions, linear_color_stop, linear_gradient, point, prelude::*, pulsating_between,
   80    px, relative, size, Action, Animation, AnimationExt, AnyElement, App, AsyncWindowContext,
   81    AvailableSpace, Bounds, ClipboardEntry, ClipboardItem, Context, DispatchPhase, ElementId,
   82    Entity, EntityInputHandler, EventEmitter, FocusHandle, FocusOutEvent, Focusable, FontId,
   83    FontWeight, Global, HighlightStyle, Hsla, InteractiveText, KeyContext, Modifiers, MouseButton,
   84    MouseDownEvent, PaintQuad, ParentElement, Pixels, Render, SharedString, Size, Styled,
   85    StyledText, Subscription, Task, TextRun, TextStyle, TextStyleRefinement, UTF16Selection,
   86    UnderlineStyle, UniformListScrollHandle, WeakEntity, WeakFocusHandle, Window,
   87};
   88use highlight_matching_bracket::refresh_matching_bracket_highlights;
   89use hover_popover::{hide_hover, HoverState};
   90use indent_guides::ActiveIndentGuidesState;
   91use inlay_hint_cache::{InlayHintCache, InlaySplice, InvalidationStrategy};
   92pub use inline_completion::Direction;
   93use inline_completion::{EditPredictionProvider, InlineCompletionProviderHandle};
   94pub use items::MAX_TAB_TITLE_LEN;
   95use itertools::Itertools;
   96use language::{
   97    language_settings::{self, all_language_settings, language_settings, InlayHintSettings},
   98    markdown, point_from_lsp, AutoindentMode, BracketPair, Buffer, Capability, CharKind, CodeLabel,
   99    CompletionDocumentation, CursorShape, Diagnostic, EditPreview, HighlightedText, IndentKind,
  100    IndentSize, InlineCompletionPreviewMode, Language, OffsetRangeExt, Point, Selection,
  101    SelectionGoal, TextObject, TransactionId, TreeSitterOptions,
  102};
  103use language::{point_to_lsp, BufferRow, CharClassifier, Runnable, RunnableRange};
  104use linked_editing_ranges::refresh_linked_ranges;
  105use mouse_context_menu::MouseContextMenu;
  106pub use proposed_changes_editor::{
  107    ProposedChangeLocation, ProposedChangesEditor, ProposedChangesEditorToolbar,
  108};
  109use similar::{ChangeTag, TextDiff};
  110use std::iter::Peekable;
  111use task::{ResolvedTask, TaskTemplate, TaskVariables};
  112
  113use hover_links::{find_file, HoverLink, HoveredLinkState, InlayHighlight};
  114pub use lsp::CompletionContext;
  115use lsp::{
  116    CompletionItemKind, CompletionTriggerKind, DiagnosticSeverity, InsertTextFormat,
  117    LanguageServerId, LanguageServerName,
  118};
  119
  120use language::BufferSnapshot;
  121use movement::TextLayoutDetails;
  122pub use multi_buffer::{
  123    Anchor, AnchorRangeExt, ExcerptId, ExcerptRange, MultiBuffer, MultiBufferSnapshot, RowInfo,
  124    ToOffset, ToPoint,
  125};
  126use multi_buffer::{
  127    ExcerptInfo, ExpandExcerptDirection, MultiBufferDiffHunk, MultiBufferPoint, MultiBufferRow,
  128    ToOffsetUtf16,
  129};
  130use project::{
  131    lsp_store::{FormatTrigger, LspFormatTarget, OpenLspBufferHandle},
  132    project_settings::{GitGutterSetting, ProjectSettings},
  133    CodeAction, Completion, CompletionIntent, DocumentHighlight, InlayHint, Location, LocationLink,
  134    LspStore, PrepareRenameResponse, Project, ProjectItem, ProjectTransaction, TaskSourceKind,
  135};
  136use rand::prelude::*;
  137use rpc::{proto::*, ErrorExt};
  138use scroll::{Autoscroll, OngoingScroll, ScrollAnchor, ScrollManager, ScrollbarAutoHide};
  139use selections_collection::{
  140    resolve_selections, MutableSelectionsCollection, SelectionsCollection,
  141};
  142use serde::{Deserialize, Serialize};
  143use settings::{update_settings_file, Settings, SettingsLocation, SettingsStore};
  144use smallvec::SmallVec;
  145use snippet::Snippet;
  146use std::{
  147    any::TypeId,
  148    borrow::Cow,
  149    cell::RefCell,
  150    cmp::{self, Ordering, Reverse},
  151    mem,
  152    num::NonZeroU32,
  153    ops::{ControlFlow, Deref, DerefMut, Not as _, Range, RangeInclusive},
  154    path::{Path, PathBuf},
  155    rc::Rc,
  156    sync::Arc,
  157    time::{Duration, Instant},
  158};
  159pub use sum_tree::Bias;
  160use sum_tree::TreeMap;
  161use text::{BufferId, OffsetUtf16, Rope};
  162use theme::{ActiveTheme, PlayerColor, StatusColors, SyntaxTheme, ThemeColors, ThemeSettings};
  163use ui::{
  164    h_flex, prelude::*, ButtonSize, ButtonStyle, Disclosure, IconButton, IconName, IconSize,
  165    Tooltip,
  166};
  167use util::{defer, maybe, post_inc, RangeExt, ResultExt, TakeUntilExt, TryFutureExt};
  168use workspace::item::{ItemHandle, PreviewTabsSettings};
  169use workspace::notifications::{DetachAndPromptErr, NotificationId, NotifyTaskExt};
  170use workspace::{
  171    searchable::SearchEvent, ItemNavHistory, SplitDirection, ViewId, Workspace, WorkspaceId,
  172};
  173use workspace::{Item as WorkspaceItem, OpenInTerminal, OpenTerminal, TabBarSettings, Toast};
  174
  175use crate::hover_links::{find_url, find_url_from_range};
  176use crate::signature_help::{SignatureHelpHiddenBy, SignatureHelpState};
  177
  178pub const FILE_HEADER_HEIGHT: u32 = 2;
  179pub const MULTI_BUFFER_EXCERPT_HEADER_HEIGHT: u32 = 1;
  180pub const MULTI_BUFFER_EXCERPT_FOOTER_HEIGHT: u32 = 1;
  181pub const DEFAULT_MULTIBUFFER_CONTEXT: u32 = 2;
  182const CURSOR_BLINK_INTERVAL: Duration = Duration::from_millis(500);
  183const MAX_LINE_LEN: usize = 1024;
  184const MIN_NAVIGATION_HISTORY_ROW_DELTA: i64 = 10;
  185const MAX_SELECTION_HISTORY_LEN: usize = 1024;
  186pub(crate) const CURSORS_VISIBLE_FOR: Duration = Duration::from_millis(2000);
  187#[doc(hidden)]
  188pub const CODE_ACTIONS_DEBOUNCE_TIMEOUT: Duration = Duration::from_millis(250);
  189
  190pub(crate) const FORMAT_TIMEOUT: Duration = Duration::from_secs(2);
  191pub(crate) const SCROLL_CENTER_TOP_BOTTOM_DEBOUNCE_TIMEOUT: Duration = Duration::from_secs(1);
  192
  193pub fn render_parsed_markdown(
  194    element_id: impl Into<ElementId>,
  195    parsed: &language::ParsedMarkdown,
  196    editor_style: &EditorStyle,
  197    workspace: Option<WeakEntity<Workspace>>,
  198    cx: &mut App,
  199) -> InteractiveText {
  200    let code_span_background_color = cx
  201        .theme()
  202        .colors()
  203        .editor_document_highlight_read_background;
  204
  205    let highlights = gpui::combine_highlights(
  206        parsed.highlights.iter().filter_map(|(range, highlight)| {
  207            let highlight = highlight.to_highlight_style(&editor_style.syntax)?;
  208            Some((range.clone(), highlight))
  209        }),
  210        parsed
  211            .regions
  212            .iter()
  213            .zip(&parsed.region_ranges)
  214            .filter_map(|(region, range)| {
  215                if region.code {
  216                    Some((
  217                        range.clone(),
  218                        HighlightStyle {
  219                            background_color: Some(code_span_background_color),
  220                            ..Default::default()
  221                        },
  222                    ))
  223                } else {
  224                    None
  225                }
  226            }),
  227    );
  228
  229    let mut links = Vec::new();
  230    let mut link_ranges = Vec::new();
  231    for (range, region) in parsed.region_ranges.iter().zip(&parsed.regions) {
  232        if let Some(link) = region.link.clone() {
  233            links.push(link);
  234            link_ranges.push(range.clone());
  235        }
  236    }
  237
  238    InteractiveText::new(
  239        element_id,
  240        StyledText::new(parsed.text.clone()).with_highlights(&editor_style.text, highlights),
  241    )
  242    .on_click(
  243        link_ranges,
  244        move |clicked_range_ix, window, cx| match &links[clicked_range_ix] {
  245            markdown::Link::Web { url } => cx.open_url(url),
  246            markdown::Link::Path { path } => {
  247                if let Some(workspace) = &workspace {
  248                    _ = workspace.update(cx, |workspace, cx| {
  249                        workspace
  250                            .open_abs_path(path.clone(), false, window, cx)
  251                            .detach();
  252                    });
  253                }
  254            }
  255        },
  256    )
  257}
  258
  259#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
  260pub enum InlayId {
  261    InlineCompletion(usize),
  262    Hint(usize),
  263}
  264
  265impl InlayId {
  266    fn id(&self) -> usize {
  267        match self {
  268            Self::InlineCompletion(id) => *id,
  269            Self::Hint(id) => *id,
  270        }
  271    }
  272}
  273
  274enum DocumentHighlightRead {}
  275enum DocumentHighlightWrite {}
  276enum InputComposition {}
  277
  278#[derive(Debug, Copy, Clone, PartialEq, Eq)]
  279pub enum Navigated {
  280    Yes,
  281    No,
  282}
  283
  284impl Navigated {
  285    pub fn from_bool(yes: bool) -> Navigated {
  286        if yes {
  287            Navigated::Yes
  288        } else {
  289            Navigated::No
  290        }
  291    }
  292}
  293
  294pub fn init_settings(cx: &mut App) {
  295    EditorSettings::register(cx);
  296}
  297
  298pub fn init(cx: &mut App) {
  299    init_settings(cx);
  300
  301    workspace::register_project_item::<Editor>(cx);
  302    workspace::FollowableViewRegistry::register::<Editor>(cx);
  303    workspace::register_serializable_item::<Editor>(cx);
  304
  305    cx.observe_new(
  306        |workspace: &mut Workspace, _: Option<&mut Window>, _cx: &mut Context<Workspace>| {
  307            workspace.register_action(Editor::new_file);
  308            workspace.register_action(Editor::new_file_vertical);
  309            workspace.register_action(Editor::new_file_horizontal);
  310            workspace.register_action(Editor::cancel_language_server_work);
  311        },
  312    )
  313    .detach();
  314
  315    cx.on_action(move |_: &workspace::NewFile, cx| {
  316        let app_state = workspace::AppState::global(cx);
  317        if let Some(app_state) = app_state.upgrade() {
  318            workspace::open_new(
  319                Default::default(),
  320                app_state,
  321                cx,
  322                |workspace, window, cx| {
  323                    Editor::new_file(workspace, &Default::default(), window, cx)
  324                },
  325            )
  326            .detach();
  327        }
  328    });
  329    cx.on_action(move |_: &workspace::NewWindow, cx| {
  330        let app_state = workspace::AppState::global(cx);
  331        if let Some(app_state) = app_state.upgrade() {
  332            workspace::open_new(
  333                Default::default(),
  334                app_state,
  335                cx,
  336                |workspace, window, cx| {
  337                    cx.activate(true);
  338                    Editor::new_file(workspace, &Default::default(), window, cx)
  339                },
  340            )
  341            .detach();
  342        }
  343    });
  344}
  345
  346pub struct SearchWithinRange;
  347
  348trait InvalidationRegion {
  349    fn ranges(&self) -> &[Range<Anchor>];
  350}
  351
  352#[derive(Clone, Debug, PartialEq)]
  353pub enum SelectPhase {
  354    Begin {
  355        position: DisplayPoint,
  356        add: bool,
  357        click_count: usize,
  358    },
  359    BeginColumnar {
  360        position: DisplayPoint,
  361        reset: bool,
  362        goal_column: u32,
  363    },
  364    Extend {
  365        position: DisplayPoint,
  366        click_count: usize,
  367    },
  368    Update {
  369        position: DisplayPoint,
  370        goal_column: u32,
  371        scroll_delta: gpui::Point<f32>,
  372    },
  373    End,
  374}
  375
  376#[derive(Clone, Debug)]
  377pub enum SelectMode {
  378    Character,
  379    Word(Range<Anchor>),
  380    Line(Range<Anchor>),
  381    All,
  382}
  383
  384#[derive(Copy, Clone, PartialEq, Eq, Debug)]
  385pub enum EditorMode {
  386    SingleLine { auto_width: bool },
  387    AutoHeight { max_lines: usize },
  388    Full,
  389}
  390
  391#[derive(Copy, Clone, Debug)]
  392pub enum SoftWrap {
  393    /// Prefer not to wrap at all.
  394    ///
  395    /// Note: this is currently internal, as actually limited by [`crate::MAX_LINE_LEN`] until it wraps.
  396    /// The mode is used inside git diff hunks, where it's seems currently more useful to not wrap as much as possible.
  397    GitDiff,
  398    /// Prefer a single line generally, unless an overly long line is encountered.
  399    None,
  400    /// Soft wrap lines that exceed the editor width.
  401    EditorWidth,
  402    /// Soft wrap lines at the preferred line length.
  403    Column(u32),
  404    /// Soft wrap line at the preferred line length or the editor width (whichever is smaller).
  405    Bounded(u32),
  406}
  407
  408#[derive(Clone)]
  409pub struct EditorStyle {
  410    pub background: Hsla,
  411    pub local_player: PlayerColor,
  412    pub text: TextStyle,
  413    pub scrollbar_width: Pixels,
  414    pub syntax: Arc<SyntaxTheme>,
  415    pub status: StatusColors,
  416    pub inlay_hints_style: HighlightStyle,
  417    pub inline_completion_styles: InlineCompletionStyles,
  418    pub unnecessary_code_fade: f32,
  419}
  420
  421impl Default for EditorStyle {
  422    fn default() -> Self {
  423        Self {
  424            background: Hsla::default(),
  425            local_player: PlayerColor::default(),
  426            text: TextStyle::default(),
  427            scrollbar_width: Pixels::default(),
  428            syntax: Default::default(),
  429            // HACK: Status colors don't have a real default.
  430            // We should look into removing the status colors from the editor
  431            // style and retrieve them directly from the theme.
  432            status: StatusColors::dark(),
  433            inlay_hints_style: HighlightStyle::default(),
  434            inline_completion_styles: InlineCompletionStyles {
  435                insertion: HighlightStyle::default(),
  436                whitespace: HighlightStyle::default(),
  437            },
  438            unnecessary_code_fade: Default::default(),
  439        }
  440    }
  441}
  442
  443pub fn make_inlay_hints_style(cx: &mut App) -> HighlightStyle {
  444    let show_background = language_settings::language_settings(None, None, cx)
  445        .inlay_hints
  446        .show_background;
  447
  448    HighlightStyle {
  449        color: Some(cx.theme().status().hint),
  450        background_color: show_background.then(|| cx.theme().status().hint_background),
  451        ..HighlightStyle::default()
  452    }
  453}
  454
  455pub fn make_suggestion_styles(cx: &mut App) -> InlineCompletionStyles {
  456    InlineCompletionStyles {
  457        insertion: HighlightStyle {
  458            color: Some(cx.theme().status().predictive),
  459            ..HighlightStyle::default()
  460        },
  461        whitespace: HighlightStyle {
  462            background_color: Some(cx.theme().status().created_background),
  463            ..HighlightStyle::default()
  464        },
  465    }
  466}
  467
  468type CompletionId = usize;
  469
  470pub(crate) enum EditDisplayMode {
  471    TabAccept,
  472    DiffPopover,
  473    Inline,
  474}
  475
  476enum InlineCompletion {
  477    Edit {
  478        edits: Vec<(Range<Anchor>, String)>,
  479        edit_preview: Option<EditPreview>,
  480        display_mode: EditDisplayMode,
  481        snapshot: BufferSnapshot,
  482    },
  483    Move {
  484        target: Anchor,
  485        range_around_target: Range<text::Anchor>,
  486        snapshot: BufferSnapshot,
  487    },
  488}
  489
  490struct InlineCompletionState {
  491    inlay_ids: Vec<InlayId>,
  492    completion: InlineCompletion,
  493    invalidation_range: Range<Anchor>,
  494}
  495
  496enum InlineCompletionHighlight {}
  497
  498pub enum MenuInlineCompletionsPolicy {
  499    Never,
  500    ByProvider,
  501}
  502
  503#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Debug, Default)]
  504struct EditorActionId(usize);
  505
  506impl EditorActionId {
  507    pub fn post_inc(&mut self) -> Self {
  508        let answer = self.0;
  509
  510        *self = Self(answer + 1);
  511
  512        Self(answer)
  513    }
  514}
  515
  516// type GetFieldEditorTheme = dyn Fn(&theme::Theme) -> theme::FieldEditor;
  517// type OverrideTextStyle = dyn Fn(&EditorStyle) -> Option<HighlightStyle>;
  518
  519type BackgroundHighlight = (fn(&ThemeColors) -> Hsla, Arc<[Range<Anchor>]>);
  520type GutterHighlight = (fn(&App) -> Hsla, Arc<[Range<Anchor>]>);
  521
  522#[derive(Default)]
  523struct ScrollbarMarkerState {
  524    scrollbar_size: Size<Pixels>,
  525    dirty: bool,
  526    markers: Arc<[PaintQuad]>,
  527    pending_refresh: Option<Task<Result<()>>>,
  528}
  529
  530impl ScrollbarMarkerState {
  531    fn should_refresh(&self, scrollbar_size: Size<Pixels>) -> bool {
  532        self.pending_refresh.is_none() && (self.scrollbar_size != scrollbar_size || self.dirty)
  533    }
  534}
  535
  536#[derive(Clone, Debug)]
  537struct RunnableTasks {
  538    templates: Vec<(TaskSourceKind, TaskTemplate)>,
  539    offset: MultiBufferOffset,
  540    // We need the column at which the task context evaluation should take place (when we're spawning it via gutter).
  541    column: u32,
  542    // Values of all named captures, including those starting with '_'
  543    extra_variables: HashMap<String, String>,
  544    // Full range of the tagged region. We use it to determine which `extra_variables` to grab for context resolution in e.g. a modal.
  545    context_range: Range<BufferOffset>,
  546}
  547
  548impl RunnableTasks {
  549    fn resolve<'a>(
  550        &'a self,
  551        cx: &'a task::TaskContext,
  552    ) -> impl Iterator<Item = (TaskSourceKind, ResolvedTask)> + 'a {
  553        self.templates.iter().filter_map(|(kind, template)| {
  554            template
  555                .resolve_task(&kind.to_id_base(), cx)
  556                .map(|task| (kind.clone(), task))
  557        })
  558    }
  559}
  560
  561#[derive(Clone)]
  562struct ResolvedTasks {
  563    templates: SmallVec<[(TaskSourceKind, ResolvedTask); 1]>,
  564    position: Anchor,
  565}
  566#[derive(Copy, Clone, Debug)]
  567struct MultiBufferOffset(usize);
  568#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
  569struct BufferOffset(usize);
  570
  571// Addons allow storing per-editor state in other crates (e.g. Vim)
  572pub trait Addon: 'static {
  573    fn extend_key_context(&self, _: &mut KeyContext, _: &App) {}
  574
  575    fn render_buffer_header_controls(
  576        &self,
  577        _: &ExcerptInfo,
  578        _: &Window,
  579        _: &App,
  580    ) -> Option<AnyElement> {
  581        None
  582    }
  583
  584    fn to_any(&self) -> &dyn std::any::Any;
  585}
  586
  587#[derive(Debug, Copy, Clone, PartialEq, Eq)]
  588pub enum IsVimMode {
  589    Yes,
  590    No,
  591}
  592
  593/// Zed's primary implementation of text input, allowing users to edit a [`MultiBuffer`].
  594///
  595/// See the [module level documentation](self) for more information.
  596pub struct Editor {
  597    focus_handle: FocusHandle,
  598    last_focused_descendant: Option<WeakFocusHandle>,
  599    /// The text buffer being edited
  600    buffer: Entity<MultiBuffer>,
  601    /// Map of how text in the buffer should be displayed.
  602    /// Handles soft wraps, folds, fake inlay text insertions, etc.
  603    pub display_map: Entity<DisplayMap>,
  604    pub selections: SelectionsCollection,
  605    pub scroll_manager: ScrollManager,
  606    /// When inline assist editors are linked, they all render cursors because
  607    /// typing enters text into each of them, even the ones that aren't focused.
  608    pub(crate) show_cursor_when_unfocused: bool,
  609    columnar_selection_tail: Option<Anchor>,
  610    add_selections_state: Option<AddSelectionsState>,
  611    select_next_state: Option<SelectNextState>,
  612    select_prev_state: Option<SelectNextState>,
  613    selection_history: SelectionHistory,
  614    autoclose_regions: Vec<AutocloseRegion>,
  615    snippet_stack: InvalidationStack<SnippetState>,
  616    select_larger_syntax_node_stack: Vec<Box<[Selection<usize>]>>,
  617    ime_transaction: Option<TransactionId>,
  618    active_diagnostics: Option<ActiveDiagnosticGroup>,
  619    soft_wrap_mode_override: Option<language_settings::SoftWrap>,
  620
  621    // TODO: make this a access method
  622    pub project: Option<Entity<Project>>,
  623    semantics_provider: Option<Rc<dyn SemanticsProvider>>,
  624    completion_provider: Option<Box<dyn CompletionProvider>>,
  625    collaboration_hub: Option<Box<dyn CollaborationHub>>,
  626    blink_manager: Entity<BlinkManager>,
  627    show_cursor_names: bool,
  628    hovered_cursors: HashMap<HoveredCursor, Task<()>>,
  629    pub show_local_selections: bool,
  630    mode: EditorMode,
  631    show_breadcrumbs: bool,
  632    show_gutter: bool,
  633    show_scrollbars: bool,
  634    show_line_numbers: Option<bool>,
  635    use_relative_line_numbers: Option<bool>,
  636    show_git_diff_gutter: Option<bool>,
  637    show_code_actions: Option<bool>,
  638    show_runnables: Option<bool>,
  639    show_wrap_guides: Option<bool>,
  640    show_indent_guides: Option<bool>,
  641    placeholder_text: Option<Arc<str>>,
  642    highlight_order: usize,
  643    highlighted_rows: HashMap<TypeId, Vec<RowHighlight>>,
  644    background_highlights: TreeMap<TypeId, BackgroundHighlight>,
  645    gutter_highlights: TreeMap<TypeId, GutterHighlight>,
  646    scrollbar_marker_state: ScrollbarMarkerState,
  647    active_indent_guides_state: ActiveIndentGuidesState,
  648    nav_history: Option<ItemNavHistory>,
  649    context_menu: RefCell<Option<CodeContextMenu>>,
  650    mouse_context_menu: Option<MouseContextMenu>,
  651    completion_tasks: Vec<(CompletionId, Task<Option<()>>)>,
  652    signature_help_state: SignatureHelpState,
  653    auto_signature_help: Option<bool>,
  654    find_all_references_task_sources: Vec<Anchor>,
  655    next_completion_id: CompletionId,
  656    available_code_actions: Option<(Location, Rc<[AvailableCodeAction]>)>,
  657    code_actions_task: Option<Task<Result<()>>>,
  658    document_highlights_task: Option<Task<()>>,
  659    linked_editing_range_task: Option<Task<Option<()>>>,
  660    linked_edit_ranges: linked_editing_ranges::LinkedEditingRanges,
  661    pending_rename: Option<RenameState>,
  662    searchable: bool,
  663    cursor_shape: CursorShape,
  664    current_line_highlight: Option<CurrentLineHighlight>,
  665    collapse_matches: bool,
  666    autoindent_mode: Option<AutoindentMode>,
  667    workspace: Option<(WeakEntity<Workspace>, Option<WorkspaceId>)>,
  668    input_enabled: bool,
  669    use_modal_editing: bool,
  670    read_only: bool,
  671    leader_peer_id: Option<PeerId>,
  672    remote_id: Option<ViewId>,
  673    hover_state: HoverState,
  674    pending_mouse_down: Option<Rc<RefCell<Option<MouseDownEvent>>>>,
  675    gutter_hovered: bool,
  676    hovered_link_state: Option<HoveredLinkState>,
  677    edit_prediction_provider: Option<RegisteredInlineCompletionProvider>,
  678    code_action_providers: Vec<Rc<dyn CodeActionProvider>>,
  679    active_inline_completion: Option<InlineCompletionState>,
  680    /// Used to prevent flickering as the user types while the menu is open
  681    stale_inline_completion_in_menu: Option<InlineCompletionState>,
  682    inline_completions_hidden_for_vim_mode: bool,
  683    show_inline_completions_override: Option<bool>,
  684    menu_inline_completions_policy: MenuInlineCompletionsPolicy,
  685    previewing_inline_completion: bool,
  686    inlay_hint_cache: InlayHintCache,
  687    next_inlay_id: usize,
  688    _subscriptions: Vec<Subscription>,
  689    pixel_position_of_newest_cursor: Option<gpui::Point<Pixels>>,
  690    gutter_dimensions: GutterDimensions,
  691    style: Option<EditorStyle>,
  692    text_style_refinement: Option<TextStyleRefinement>,
  693    next_editor_action_id: EditorActionId,
  694    editor_actions:
  695        Rc<RefCell<BTreeMap<EditorActionId, Box<dyn Fn(&mut Window, &mut Context<Self>)>>>>,
  696    use_autoclose: bool,
  697    use_auto_surround: bool,
  698    auto_replace_emoji_shortcode: bool,
  699    show_git_blame_gutter: bool,
  700    show_git_blame_inline: bool,
  701    show_git_blame_inline_delay_task: Option<Task<()>>,
  702    git_blame_inline_enabled: bool,
  703    serialize_dirty_buffers: bool,
  704    show_selection_menu: Option<bool>,
  705    blame: Option<Entity<GitBlame>>,
  706    blame_subscription: Option<Subscription>,
  707    custom_context_menu: Option<
  708        Box<
  709            dyn 'static
  710                + Fn(
  711                    &mut Self,
  712                    DisplayPoint,
  713                    &mut Window,
  714                    &mut Context<Self>,
  715                ) -> Option<Entity<ui::ContextMenu>>,
  716        >,
  717    >,
  718    last_bounds: Option<Bounds<Pixels>>,
  719    last_position_map: Option<Rc<PositionMap>>,
  720    expect_bounds_change: Option<Bounds<Pixels>>,
  721    tasks: BTreeMap<(BufferId, BufferRow), RunnableTasks>,
  722    tasks_update_task: Option<Task<()>>,
  723    in_project_search: bool,
  724    previous_search_ranges: Option<Arc<[Range<Anchor>]>>,
  725    breadcrumb_header: Option<String>,
  726    focused_block: Option<FocusedBlock>,
  727    next_scroll_position: NextScrollCursorCenterTopBottom,
  728    addons: HashMap<TypeId, Box<dyn Addon>>,
  729    registered_buffers: HashMap<BufferId, OpenLspBufferHandle>,
  730    selection_mark_mode: bool,
  731    toggle_fold_multiple_buffers: Task<()>,
  732    _scroll_cursor_center_top_bottom_task: Task<()>,
  733}
  734
  735#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)]
  736enum NextScrollCursorCenterTopBottom {
  737    #[default]
  738    Center,
  739    Top,
  740    Bottom,
  741}
  742
  743impl NextScrollCursorCenterTopBottom {
  744    fn next(&self) -> Self {
  745        match self {
  746            Self::Center => Self::Top,
  747            Self::Top => Self::Bottom,
  748            Self::Bottom => Self::Center,
  749        }
  750    }
  751}
  752
  753#[derive(Clone)]
  754pub struct EditorSnapshot {
  755    pub mode: EditorMode,
  756    show_gutter: bool,
  757    show_line_numbers: Option<bool>,
  758    show_git_diff_gutter: Option<bool>,
  759    show_code_actions: Option<bool>,
  760    show_runnables: Option<bool>,
  761    git_blame_gutter_max_author_length: Option<usize>,
  762    pub display_snapshot: DisplaySnapshot,
  763    pub placeholder_text: Option<Arc<str>>,
  764    is_focused: bool,
  765    scroll_anchor: ScrollAnchor,
  766    ongoing_scroll: OngoingScroll,
  767    current_line_highlight: CurrentLineHighlight,
  768    gutter_hovered: bool,
  769}
  770
  771const GIT_BLAME_MAX_AUTHOR_CHARS_DISPLAYED: usize = 20;
  772
  773#[derive(Default, Debug, Clone, Copy)]
  774pub struct GutterDimensions {
  775    pub left_padding: Pixels,
  776    pub right_padding: Pixels,
  777    pub width: Pixels,
  778    pub margin: Pixels,
  779    pub git_blame_entries_width: Option<Pixels>,
  780}
  781
  782impl GutterDimensions {
  783    /// The full width of the space taken up by the gutter.
  784    pub fn full_width(&self) -> Pixels {
  785        self.margin + self.width
  786    }
  787
  788    /// The width of the space reserved for the fold indicators,
  789    /// use alongside 'justify_end' and `gutter_width` to
  790    /// right align content with the line numbers
  791    pub fn fold_area_width(&self) -> Pixels {
  792        self.margin + self.right_padding
  793    }
  794}
  795
  796#[derive(Debug)]
  797pub struct RemoteSelection {
  798    pub replica_id: ReplicaId,
  799    pub selection: Selection<Anchor>,
  800    pub cursor_shape: CursorShape,
  801    pub peer_id: PeerId,
  802    pub line_mode: bool,
  803    pub participant_index: Option<ParticipantIndex>,
  804    pub user_name: Option<SharedString>,
  805}
  806
  807#[derive(Clone, Debug)]
  808struct SelectionHistoryEntry {
  809    selections: Arc<[Selection<Anchor>]>,
  810    select_next_state: Option<SelectNextState>,
  811    select_prev_state: Option<SelectNextState>,
  812    add_selections_state: Option<AddSelectionsState>,
  813}
  814
  815enum SelectionHistoryMode {
  816    Normal,
  817    Undoing,
  818    Redoing,
  819}
  820
  821#[derive(Clone, PartialEq, Eq, Hash)]
  822struct HoveredCursor {
  823    replica_id: u16,
  824    selection_id: usize,
  825}
  826
  827impl Default for SelectionHistoryMode {
  828    fn default() -> Self {
  829        Self::Normal
  830    }
  831}
  832
  833#[derive(Default)]
  834struct SelectionHistory {
  835    #[allow(clippy::type_complexity)]
  836    selections_by_transaction:
  837        HashMap<TransactionId, (Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)>,
  838    mode: SelectionHistoryMode,
  839    undo_stack: VecDeque<SelectionHistoryEntry>,
  840    redo_stack: VecDeque<SelectionHistoryEntry>,
  841}
  842
  843impl SelectionHistory {
  844    fn insert_transaction(
  845        &mut self,
  846        transaction_id: TransactionId,
  847        selections: Arc<[Selection<Anchor>]>,
  848    ) {
  849        self.selections_by_transaction
  850            .insert(transaction_id, (selections, None));
  851    }
  852
  853    #[allow(clippy::type_complexity)]
  854    fn transaction(
  855        &self,
  856        transaction_id: TransactionId,
  857    ) -> Option<&(Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)> {
  858        self.selections_by_transaction.get(&transaction_id)
  859    }
  860
  861    #[allow(clippy::type_complexity)]
  862    fn transaction_mut(
  863        &mut self,
  864        transaction_id: TransactionId,
  865    ) -> Option<&mut (Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)> {
  866        self.selections_by_transaction.get_mut(&transaction_id)
  867    }
  868
  869    fn push(&mut self, entry: SelectionHistoryEntry) {
  870        if !entry.selections.is_empty() {
  871            match self.mode {
  872                SelectionHistoryMode::Normal => {
  873                    self.push_undo(entry);
  874                    self.redo_stack.clear();
  875                }
  876                SelectionHistoryMode::Undoing => self.push_redo(entry),
  877                SelectionHistoryMode::Redoing => self.push_undo(entry),
  878            }
  879        }
  880    }
  881
  882    fn push_undo(&mut self, entry: SelectionHistoryEntry) {
  883        if self
  884            .undo_stack
  885            .back()
  886            .map_or(true, |e| e.selections != entry.selections)
  887        {
  888            self.undo_stack.push_back(entry);
  889            if self.undo_stack.len() > MAX_SELECTION_HISTORY_LEN {
  890                self.undo_stack.pop_front();
  891            }
  892        }
  893    }
  894
  895    fn push_redo(&mut self, entry: SelectionHistoryEntry) {
  896        if self
  897            .redo_stack
  898            .back()
  899            .map_or(true, |e| e.selections != entry.selections)
  900        {
  901            self.redo_stack.push_back(entry);
  902            if self.redo_stack.len() > MAX_SELECTION_HISTORY_LEN {
  903                self.redo_stack.pop_front();
  904            }
  905        }
  906    }
  907}
  908
  909struct RowHighlight {
  910    index: usize,
  911    range: Range<Anchor>,
  912    color: Hsla,
  913    should_autoscroll: bool,
  914}
  915
  916#[derive(Clone, Debug)]
  917struct AddSelectionsState {
  918    above: bool,
  919    stack: Vec<usize>,
  920}
  921
  922#[derive(Clone)]
  923struct SelectNextState {
  924    query: AhoCorasick,
  925    wordwise: bool,
  926    done: bool,
  927}
  928
  929impl std::fmt::Debug for SelectNextState {
  930    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  931        f.debug_struct(std::any::type_name::<Self>())
  932            .field("wordwise", &self.wordwise)
  933            .field("done", &self.done)
  934            .finish()
  935    }
  936}
  937
  938#[derive(Debug)]
  939struct AutocloseRegion {
  940    selection_id: usize,
  941    range: Range<Anchor>,
  942    pair: BracketPair,
  943}
  944
  945#[derive(Debug)]
  946struct SnippetState {
  947    ranges: Vec<Vec<Range<Anchor>>>,
  948    active_index: usize,
  949    choices: Vec<Option<Vec<String>>>,
  950}
  951
  952#[doc(hidden)]
  953pub struct RenameState {
  954    pub range: Range<Anchor>,
  955    pub old_name: Arc<str>,
  956    pub editor: Entity<Editor>,
  957    block_id: CustomBlockId,
  958}
  959
  960struct InvalidationStack<T>(Vec<T>);
  961
  962struct RegisteredInlineCompletionProvider {
  963    provider: Arc<dyn InlineCompletionProviderHandle>,
  964    _subscription: Subscription,
  965}
  966
  967#[derive(Debug)]
  968struct ActiveDiagnosticGroup {
  969    primary_range: Range<Anchor>,
  970    primary_message: String,
  971    group_id: usize,
  972    blocks: HashMap<CustomBlockId, Diagnostic>,
  973    is_valid: bool,
  974}
  975
  976#[derive(Serialize, Deserialize, Clone, Debug)]
  977pub struct ClipboardSelection {
  978    pub len: usize,
  979    pub is_entire_line: bool,
  980    pub first_line_indent: u32,
  981}
  982
  983#[derive(Debug)]
  984pub(crate) struct NavigationData {
  985    cursor_anchor: Anchor,
  986    cursor_position: Point,
  987    scroll_anchor: ScrollAnchor,
  988    scroll_top_row: u32,
  989}
  990
  991#[derive(Debug, Clone, Copy, PartialEq, Eq)]
  992pub enum GotoDefinitionKind {
  993    Symbol,
  994    Declaration,
  995    Type,
  996    Implementation,
  997}
  998
  999#[derive(Debug, Clone)]
 1000enum InlayHintRefreshReason {
 1001    Toggle(bool),
 1002    SettingsChange(InlayHintSettings),
 1003    NewLinesShown,
 1004    BufferEdited(HashSet<Arc<Language>>),
 1005    RefreshRequested,
 1006    ExcerptsRemoved(Vec<ExcerptId>),
 1007}
 1008
 1009impl InlayHintRefreshReason {
 1010    fn description(&self) -> &'static str {
 1011        match self {
 1012            Self::Toggle(_) => "toggle",
 1013            Self::SettingsChange(_) => "settings change",
 1014            Self::NewLinesShown => "new lines shown",
 1015            Self::BufferEdited(_) => "buffer edited",
 1016            Self::RefreshRequested => "refresh requested",
 1017            Self::ExcerptsRemoved(_) => "excerpts removed",
 1018        }
 1019    }
 1020}
 1021
 1022pub enum FormatTarget {
 1023    Buffers,
 1024    Ranges(Vec<Range<MultiBufferPoint>>),
 1025}
 1026
 1027pub(crate) struct FocusedBlock {
 1028    id: BlockId,
 1029    focus_handle: WeakFocusHandle,
 1030}
 1031
 1032#[derive(Clone)]
 1033enum JumpData {
 1034    MultiBufferRow {
 1035        row: MultiBufferRow,
 1036        line_offset_from_top: u32,
 1037    },
 1038    MultiBufferPoint {
 1039        excerpt_id: ExcerptId,
 1040        position: Point,
 1041        anchor: text::Anchor,
 1042        line_offset_from_top: u32,
 1043    },
 1044}
 1045
 1046pub enum MultibufferSelectionMode {
 1047    First,
 1048    All,
 1049}
 1050
 1051impl Editor {
 1052    pub fn single_line(window: &mut Window, cx: &mut Context<Self>) -> Self {
 1053        let buffer = cx.new(|cx| Buffer::local("", cx));
 1054        let buffer = cx.new(|cx| MultiBuffer::singleton(buffer, cx));
 1055        Self::new(
 1056            EditorMode::SingleLine { auto_width: false },
 1057            buffer,
 1058            None,
 1059            false,
 1060            window,
 1061            cx,
 1062        )
 1063    }
 1064
 1065    pub fn multi_line(window: &mut Window, cx: &mut Context<Self>) -> Self {
 1066        let buffer = cx.new(|cx| Buffer::local("", cx));
 1067        let buffer = cx.new(|cx| MultiBuffer::singleton(buffer, cx));
 1068        Self::new(EditorMode::Full, buffer, None, false, window, cx)
 1069    }
 1070
 1071    pub fn auto_width(window: &mut Window, cx: &mut Context<Self>) -> Self {
 1072        let buffer = cx.new(|cx| Buffer::local("", cx));
 1073        let buffer = cx.new(|cx| MultiBuffer::singleton(buffer, cx));
 1074        Self::new(
 1075            EditorMode::SingleLine { auto_width: true },
 1076            buffer,
 1077            None,
 1078            false,
 1079            window,
 1080            cx,
 1081        )
 1082    }
 1083
 1084    pub fn auto_height(max_lines: usize, window: &mut Window, cx: &mut Context<Self>) -> Self {
 1085        let buffer = cx.new(|cx| Buffer::local("", cx));
 1086        let buffer = cx.new(|cx| MultiBuffer::singleton(buffer, cx));
 1087        Self::new(
 1088            EditorMode::AutoHeight { max_lines },
 1089            buffer,
 1090            None,
 1091            false,
 1092            window,
 1093            cx,
 1094        )
 1095    }
 1096
 1097    pub fn for_buffer(
 1098        buffer: Entity<Buffer>,
 1099        project: Option<Entity<Project>>,
 1100        window: &mut Window,
 1101        cx: &mut Context<Self>,
 1102    ) -> Self {
 1103        let buffer = cx.new(|cx| MultiBuffer::singleton(buffer, cx));
 1104        Self::new(EditorMode::Full, buffer, project, false, window, cx)
 1105    }
 1106
 1107    pub fn for_multibuffer(
 1108        buffer: Entity<MultiBuffer>,
 1109        project: Option<Entity<Project>>,
 1110        show_excerpt_controls: bool,
 1111        window: &mut Window,
 1112        cx: &mut Context<Self>,
 1113    ) -> Self {
 1114        Self::new(
 1115            EditorMode::Full,
 1116            buffer,
 1117            project,
 1118            show_excerpt_controls,
 1119            window,
 1120            cx,
 1121        )
 1122    }
 1123
 1124    pub fn clone(&self, window: &mut Window, cx: &mut Context<Self>) -> Self {
 1125        let show_excerpt_controls = self.display_map.read(cx).show_excerpt_controls();
 1126        let mut clone = Self::new(
 1127            self.mode,
 1128            self.buffer.clone(),
 1129            self.project.clone(),
 1130            show_excerpt_controls,
 1131            window,
 1132            cx,
 1133        );
 1134        self.display_map.update(cx, |display_map, cx| {
 1135            let snapshot = display_map.snapshot(cx);
 1136            clone.display_map.update(cx, |display_map, cx| {
 1137                display_map.set_state(&snapshot, cx);
 1138            });
 1139        });
 1140        clone.selections.clone_state(&self.selections);
 1141        clone.scroll_manager.clone_state(&self.scroll_manager);
 1142        clone.searchable = self.searchable;
 1143        clone
 1144    }
 1145
 1146    pub fn new(
 1147        mode: EditorMode,
 1148        buffer: Entity<MultiBuffer>,
 1149        project: Option<Entity<Project>>,
 1150        show_excerpt_controls: bool,
 1151        window: &mut Window,
 1152        cx: &mut Context<Self>,
 1153    ) -> Self {
 1154        let style = window.text_style();
 1155        let font_size = style.font_size.to_pixels(window.rem_size());
 1156        let editor = cx.entity().downgrade();
 1157        let fold_placeholder = FoldPlaceholder {
 1158            constrain_width: true,
 1159            render: Arc::new(move |fold_id, fold_range, _, cx| {
 1160                let editor = editor.clone();
 1161                div()
 1162                    .id(fold_id)
 1163                    .bg(cx.theme().colors().ghost_element_background)
 1164                    .hover(|style| style.bg(cx.theme().colors().ghost_element_hover))
 1165                    .active(|style| style.bg(cx.theme().colors().ghost_element_active))
 1166                    .rounded_sm()
 1167                    .size_full()
 1168                    .cursor_pointer()
 1169                    .child("")
 1170                    .on_mouse_down(MouseButton::Left, |_, _, cx| cx.stop_propagation())
 1171                    .on_click(move |_, _window, cx| {
 1172                        editor
 1173                            .update(cx, |editor, cx| {
 1174                                editor.unfold_ranges(
 1175                                    &[fold_range.start..fold_range.end],
 1176                                    true,
 1177                                    false,
 1178                                    cx,
 1179                                );
 1180                                cx.stop_propagation();
 1181                            })
 1182                            .ok();
 1183                    })
 1184                    .into_any()
 1185            }),
 1186            merge_adjacent: true,
 1187            ..Default::default()
 1188        };
 1189        let display_map = cx.new(|cx| {
 1190            DisplayMap::new(
 1191                buffer.clone(),
 1192                style.font(),
 1193                font_size,
 1194                None,
 1195                show_excerpt_controls,
 1196                FILE_HEADER_HEIGHT,
 1197                MULTI_BUFFER_EXCERPT_HEADER_HEIGHT,
 1198                MULTI_BUFFER_EXCERPT_FOOTER_HEIGHT,
 1199                fold_placeholder,
 1200                cx,
 1201            )
 1202        });
 1203
 1204        let selections = SelectionsCollection::new(display_map.clone(), buffer.clone());
 1205
 1206        let blink_manager = cx.new(|cx| BlinkManager::new(CURSOR_BLINK_INTERVAL, cx));
 1207
 1208        let soft_wrap_mode_override = matches!(mode, EditorMode::SingleLine { .. })
 1209            .then(|| language_settings::SoftWrap::None);
 1210
 1211        let mut project_subscriptions = Vec::new();
 1212        if mode == EditorMode::Full {
 1213            if let Some(project) = project.as_ref() {
 1214                if buffer.read(cx).is_singleton() {
 1215                    project_subscriptions.push(cx.observe_in(project, window, |_, _, _, cx| {
 1216                        cx.emit(EditorEvent::TitleChanged);
 1217                    }));
 1218                }
 1219                project_subscriptions.push(cx.subscribe_in(
 1220                    project,
 1221                    window,
 1222                    |editor, _, event, window, cx| {
 1223                        if let project::Event::RefreshInlayHints = event {
 1224                            editor
 1225                                .refresh_inlay_hints(InlayHintRefreshReason::RefreshRequested, cx);
 1226                        } else if let project::Event::SnippetEdit(id, snippet_edits) = event {
 1227                            if let Some(buffer) = editor.buffer.read(cx).buffer(*id) {
 1228                                let focus_handle = editor.focus_handle(cx);
 1229                                if focus_handle.is_focused(window) {
 1230                                    let snapshot = buffer.read(cx).snapshot();
 1231                                    for (range, snippet) in snippet_edits {
 1232                                        let editor_range =
 1233                                            language::range_from_lsp(*range).to_offset(&snapshot);
 1234                                        editor
 1235                                            .insert_snippet(
 1236                                                &[editor_range],
 1237                                                snippet.clone(),
 1238                                                window,
 1239                                                cx,
 1240                                            )
 1241                                            .ok();
 1242                                    }
 1243                                }
 1244                            }
 1245                        }
 1246                    },
 1247                ));
 1248                if let Some(task_inventory) = project
 1249                    .read(cx)
 1250                    .task_store()
 1251                    .read(cx)
 1252                    .task_inventory()
 1253                    .cloned()
 1254                {
 1255                    project_subscriptions.push(cx.observe_in(
 1256                        &task_inventory,
 1257                        window,
 1258                        |editor, _, window, cx| {
 1259                            editor.tasks_update_task = Some(editor.refresh_runnables(window, cx));
 1260                        },
 1261                    ));
 1262                }
 1263            }
 1264        }
 1265
 1266        let buffer_snapshot = buffer.read(cx).snapshot(cx);
 1267
 1268        let inlay_hint_settings =
 1269            inlay_hint_settings(selections.newest_anchor().head(), &buffer_snapshot, cx);
 1270        let focus_handle = cx.focus_handle();
 1271        cx.on_focus(&focus_handle, window, Self::handle_focus)
 1272            .detach();
 1273        cx.on_focus_in(&focus_handle, window, Self::handle_focus_in)
 1274            .detach();
 1275        cx.on_focus_out(&focus_handle, window, Self::handle_focus_out)
 1276            .detach();
 1277        cx.on_blur(&focus_handle, window, Self::handle_blur)
 1278            .detach();
 1279
 1280        let show_indent_guides = if matches!(mode, EditorMode::SingleLine { .. }) {
 1281            Some(false)
 1282        } else {
 1283            None
 1284        };
 1285
 1286        let mut code_action_providers = Vec::new();
 1287        if let Some(project) = project.clone() {
 1288            get_uncommitted_diff_for_buffer(
 1289                &project,
 1290                buffer.read(cx).all_buffers(),
 1291                buffer.clone(),
 1292                cx,
 1293            );
 1294            code_action_providers.push(Rc::new(project) as Rc<_>);
 1295        }
 1296
 1297        let mut this = Self {
 1298            focus_handle,
 1299            show_cursor_when_unfocused: false,
 1300            last_focused_descendant: None,
 1301            buffer: buffer.clone(),
 1302            display_map: display_map.clone(),
 1303            selections,
 1304            scroll_manager: ScrollManager::new(cx),
 1305            columnar_selection_tail: None,
 1306            add_selections_state: None,
 1307            select_next_state: None,
 1308            select_prev_state: None,
 1309            selection_history: Default::default(),
 1310            autoclose_regions: Default::default(),
 1311            snippet_stack: Default::default(),
 1312            select_larger_syntax_node_stack: Vec::new(),
 1313            ime_transaction: Default::default(),
 1314            active_diagnostics: None,
 1315            soft_wrap_mode_override,
 1316            completion_provider: project.clone().map(|project| Box::new(project) as _),
 1317            semantics_provider: project.clone().map(|project| Rc::new(project) as _),
 1318            collaboration_hub: project.clone().map(|project| Box::new(project) as _),
 1319            project,
 1320            blink_manager: blink_manager.clone(),
 1321            show_local_selections: true,
 1322            show_scrollbars: true,
 1323            mode,
 1324            show_breadcrumbs: EditorSettings::get_global(cx).toolbar.breadcrumbs,
 1325            show_gutter: mode == EditorMode::Full,
 1326            show_line_numbers: None,
 1327            use_relative_line_numbers: None,
 1328            show_git_diff_gutter: None,
 1329            show_code_actions: None,
 1330            show_runnables: None,
 1331            show_wrap_guides: None,
 1332            show_indent_guides,
 1333            placeholder_text: None,
 1334            highlight_order: 0,
 1335            highlighted_rows: HashMap::default(),
 1336            background_highlights: Default::default(),
 1337            gutter_highlights: TreeMap::default(),
 1338            scrollbar_marker_state: ScrollbarMarkerState::default(),
 1339            active_indent_guides_state: ActiveIndentGuidesState::default(),
 1340            nav_history: None,
 1341            context_menu: RefCell::new(None),
 1342            mouse_context_menu: None,
 1343            completion_tasks: Default::default(),
 1344            signature_help_state: SignatureHelpState::default(),
 1345            auto_signature_help: None,
 1346            find_all_references_task_sources: Vec::new(),
 1347            next_completion_id: 0,
 1348            next_inlay_id: 0,
 1349            code_action_providers,
 1350            available_code_actions: Default::default(),
 1351            code_actions_task: Default::default(),
 1352            document_highlights_task: Default::default(),
 1353            linked_editing_range_task: Default::default(),
 1354            pending_rename: Default::default(),
 1355            searchable: true,
 1356            cursor_shape: EditorSettings::get_global(cx)
 1357                .cursor_shape
 1358                .unwrap_or_default(),
 1359            current_line_highlight: None,
 1360            autoindent_mode: Some(AutoindentMode::EachLine),
 1361            collapse_matches: false,
 1362            workspace: None,
 1363            input_enabled: true,
 1364            use_modal_editing: mode == EditorMode::Full,
 1365            read_only: false,
 1366            use_autoclose: true,
 1367            use_auto_surround: true,
 1368            auto_replace_emoji_shortcode: false,
 1369            leader_peer_id: None,
 1370            remote_id: None,
 1371            hover_state: Default::default(),
 1372            pending_mouse_down: None,
 1373            hovered_link_state: Default::default(),
 1374            edit_prediction_provider: None,
 1375            active_inline_completion: None,
 1376            stale_inline_completion_in_menu: None,
 1377            previewing_inline_completion: false,
 1378            inlay_hint_cache: InlayHintCache::new(inlay_hint_settings),
 1379
 1380            gutter_hovered: false,
 1381            pixel_position_of_newest_cursor: None,
 1382            last_bounds: None,
 1383            last_position_map: None,
 1384            expect_bounds_change: None,
 1385            gutter_dimensions: GutterDimensions::default(),
 1386            style: None,
 1387            show_cursor_names: false,
 1388            hovered_cursors: Default::default(),
 1389            next_editor_action_id: EditorActionId::default(),
 1390            editor_actions: Rc::default(),
 1391            inline_completions_hidden_for_vim_mode: false,
 1392            show_inline_completions_override: None,
 1393            menu_inline_completions_policy: MenuInlineCompletionsPolicy::ByProvider,
 1394            custom_context_menu: None,
 1395            show_git_blame_gutter: false,
 1396            show_git_blame_inline: false,
 1397            show_selection_menu: None,
 1398            show_git_blame_inline_delay_task: None,
 1399            git_blame_inline_enabled: ProjectSettings::get_global(cx).git.inline_blame_enabled(),
 1400            serialize_dirty_buffers: ProjectSettings::get_global(cx)
 1401                .session
 1402                .restore_unsaved_buffers,
 1403            blame: None,
 1404            blame_subscription: None,
 1405            tasks: Default::default(),
 1406            _subscriptions: vec![
 1407                cx.observe(&buffer, Self::on_buffer_changed),
 1408                cx.subscribe_in(&buffer, window, Self::on_buffer_event),
 1409                cx.observe_in(&display_map, window, Self::on_display_map_changed),
 1410                cx.observe(&blink_manager, |_, _, cx| cx.notify()),
 1411                cx.observe_global_in::<SettingsStore>(window, Self::settings_changed),
 1412                cx.observe_window_activation(window, |editor, window, cx| {
 1413                    let active = window.is_window_active();
 1414                    editor.blink_manager.update(cx, |blink_manager, cx| {
 1415                        if active {
 1416                            blink_manager.enable(cx);
 1417                        } else {
 1418                            blink_manager.disable(cx);
 1419                        }
 1420                    });
 1421                }),
 1422            ],
 1423            tasks_update_task: None,
 1424            linked_edit_ranges: Default::default(),
 1425            in_project_search: false,
 1426            previous_search_ranges: None,
 1427            breadcrumb_header: None,
 1428            focused_block: None,
 1429            next_scroll_position: NextScrollCursorCenterTopBottom::default(),
 1430            addons: HashMap::default(),
 1431            registered_buffers: HashMap::default(),
 1432            _scroll_cursor_center_top_bottom_task: Task::ready(()),
 1433            selection_mark_mode: false,
 1434            toggle_fold_multiple_buffers: Task::ready(()),
 1435            text_style_refinement: None,
 1436        };
 1437        this.tasks_update_task = Some(this.refresh_runnables(window, cx));
 1438        this._subscriptions.extend(project_subscriptions);
 1439
 1440        this.end_selection(window, cx);
 1441        this.scroll_manager.show_scrollbar(window, cx);
 1442
 1443        if mode == EditorMode::Full {
 1444            let should_auto_hide_scrollbars = cx.should_auto_hide_scrollbars();
 1445            cx.set_global(ScrollbarAutoHide(should_auto_hide_scrollbars));
 1446
 1447            if this.git_blame_inline_enabled {
 1448                this.git_blame_inline_enabled = true;
 1449                this.start_git_blame_inline(false, window, cx);
 1450            }
 1451
 1452            if let Some(buffer) = buffer.read(cx).as_singleton() {
 1453                if let Some(project) = this.project.as_ref() {
 1454                    let lsp_store = project.read(cx).lsp_store();
 1455                    let handle = lsp_store.update(cx, |lsp_store, cx| {
 1456                        lsp_store.register_buffer_with_language_servers(&buffer, cx)
 1457                    });
 1458                    this.registered_buffers
 1459                        .insert(buffer.read(cx).remote_id(), handle);
 1460                }
 1461            }
 1462        }
 1463
 1464        this.report_editor_event("Editor Opened", None, cx);
 1465        this
 1466    }
 1467
 1468    pub fn mouse_menu_is_focused(&self, window: &mut Window, cx: &mut App) -> bool {
 1469        self.mouse_context_menu
 1470            .as_ref()
 1471            .is_some_and(|menu| menu.context_menu.focus_handle(cx).is_focused(window))
 1472    }
 1473
 1474    fn key_context(&self, window: &mut Window, cx: &mut Context<Self>) -> KeyContext {
 1475        let mut key_context = KeyContext::new_with_defaults();
 1476        key_context.add("Editor");
 1477        let mode = match self.mode {
 1478            EditorMode::SingleLine { .. } => "single_line",
 1479            EditorMode::AutoHeight { .. } => "auto_height",
 1480            EditorMode::Full => "full",
 1481        };
 1482
 1483        if EditorSettings::jupyter_enabled(cx) {
 1484            key_context.add("jupyter");
 1485        }
 1486
 1487        key_context.set("mode", mode);
 1488        if self.pending_rename.is_some() {
 1489            key_context.add("renaming");
 1490        }
 1491
 1492        let mut showing_completions = false;
 1493
 1494        match self.context_menu.borrow().as_ref() {
 1495            Some(CodeContextMenu::Completions(_)) => {
 1496                key_context.add("menu");
 1497                key_context.add("showing_completions");
 1498                showing_completions = true;
 1499            }
 1500            Some(CodeContextMenu::CodeActions(_)) => {
 1501                key_context.add("menu");
 1502                key_context.add("showing_code_actions")
 1503            }
 1504            None => {}
 1505        }
 1506
 1507        // Disable vim contexts when a sub-editor (e.g. rename/inline assistant) is focused.
 1508        if !self.focus_handle(cx).contains_focused(window, cx)
 1509            || (self.is_focused(window) || self.mouse_menu_is_focused(window, cx))
 1510        {
 1511            for addon in self.addons.values() {
 1512                addon.extend_key_context(&mut key_context, cx)
 1513            }
 1514        }
 1515
 1516        if let Some(extension) = self
 1517            .buffer
 1518            .read(cx)
 1519            .as_singleton()
 1520            .and_then(|buffer| buffer.read(cx).file()?.path().extension()?.to_str())
 1521        {
 1522            key_context.set("extension", extension.to_string());
 1523        }
 1524
 1525        if self.has_active_inline_completion() {
 1526            key_context.add("copilot_suggestion");
 1527            key_context.add("edit_prediction");
 1528
 1529            if showing_completions || self.edit_prediction_requires_modifier(cx) {
 1530                key_context.add("edit_prediction_requires_modifier");
 1531            }
 1532        }
 1533
 1534        if self.selection_mark_mode {
 1535            key_context.add("selection_mode");
 1536        }
 1537
 1538        key_context
 1539    }
 1540
 1541    pub fn new_file(
 1542        workspace: &mut Workspace,
 1543        _: &workspace::NewFile,
 1544        window: &mut Window,
 1545        cx: &mut Context<Workspace>,
 1546    ) {
 1547        Self::new_in_workspace(workspace, window, cx).detach_and_prompt_err(
 1548            "Failed to create buffer",
 1549            window,
 1550            cx,
 1551            |e, _, _| match e.error_code() {
 1552                ErrorCode::RemoteUpgradeRequired => Some(format!(
 1553                "The remote instance of Zed does not support this yet. It must be upgraded to {}",
 1554                e.error_tag("required").unwrap_or("the latest version")
 1555            )),
 1556                _ => None,
 1557            },
 1558        );
 1559    }
 1560
 1561    pub fn new_in_workspace(
 1562        workspace: &mut Workspace,
 1563        window: &mut Window,
 1564        cx: &mut Context<Workspace>,
 1565    ) -> Task<Result<Entity<Editor>>> {
 1566        let project = workspace.project().clone();
 1567        let create = project.update(cx, |project, cx| project.create_buffer(cx));
 1568
 1569        cx.spawn_in(window, |workspace, mut cx| async move {
 1570            let buffer = create.await?;
 1571            workspace.update_in(&mut cx, |workspace, window, cx| {
 1572                let editor =
 1573                    cx.new(|cx| Editor::for_buffer(buffer, Some(project.clone()), window, cx));
 1574                workspace.add_item_to_active_pane(Box::new(editor.clone()), None, true, window, cx);
 1575                editor
 1576            })
 1577        })
 1578    }
 1579
 1580    fn new_file_vertical(
 1581        workspace: &mut Workspace,
 1582        _: &workspace::NewFileSplitVertical,
 1583        window: &mut Window,
 1584        cx: &mut Context<Workspace>,
 1585    ) {
 1586        Self::new_file_in_direction(workspace, SplitDirection::vertical(cx), window, cx)
 1587    }
 1588
 1589    fn new_file_horizontal(
 1590        workspace: &mut Workspace,
 1591        _: &workspace::NewFileSplitHorizontal,
 1592        window: &mut Window,
 1593        cx: &mut Context<Workspace>,
 1594    ) {
 1595        Self::new_file_in_direction(workspace, SplitDirection::horizontal(cx), window, cx)
 1596    }
 1597
 1598    fn new_file_in_direction(
 1599        workspace: &mut Workspace,
 1600        direction: SplitDirection,
 1601        window: &mut Window,
 1602        cx: &mut Context<Workspace>,
 1603    ) {
 1604        let project = workspace.project().clone();
 1605        let create = project.update(cx, |project, cx| project.create_buffer(cx));
 1606
 1607        cx.spawn_in(window, |workspace, mut cx| async move {
 1608            let buffer = create.await?;
 1609            workspace.update_in(&mut cx, move |workspace, window, cx| {
 1610                workspace.split_item(
 1611                    direction,
 1612                    Box::new(
 1613                        cx.new(|cx| Editor::for_buffer(buffer, Some(project.clone()), window, cx)),
 1614                    ),
 1615                    window,
 1616                    cx,
 1617                )
 1618            })?;
 1619            anyhow::Ok(())
 1620        })
 1621        .detach_and_prompt_err("Failed to create buffer", window, cx, |e, _, _| {
 1622            match e.error_code() {
 1623                ErrorCode::RemoteUpgradeRequired => Some(format!(
 1624                "The remote instance of Zed does not support this yet. It must be upgraded to {}",
 1625                e.error_tag("required").unwrap_or("the latest version")
 1626            )),
 1627                _ => None,
 1628            }
 1629        });
 1630    }
 1631
 1632    pub fn leader_peer_id(&self) -> Option<PeerId> {
 1633        self.leader_peer_id
 1634    }
 1635
 1636    pub fn buffer(&self) -> &Entity<MultiBuffer> {
 1637        &self.buffer
 1638    }
 1639
 1640    pub fn workspace(&self) -> Option<Entity<Workspace>> {
 1641        self.workspace.as_ref()?.0.upgrade()
 1642    }
 1643
 1644    pub fn title<'a>(&self, cx: &'a App) -> Cow<'a, str> {
 1645        self.buffer().read(cx).title(cx)
 1646    }
 1647
 1648    pub fn snapshot(&self, window: &mut Window, cx: &mut App) -> EditorSnapshot {
 1649        let git_blame_gutter_max_author_length = self
 1650            .render_git_blame_gutter(cx)
 1651            .then(|| {
 1652                if let Some(blame) = self.blame.as_ref() {
 1653                    let max_author_length =
 1654                        blame.update(cx, |blame, cx| blame.max_author_length(cx));
 1655                    Some(max_author_length)
 1656                } else {
 1657                    None
 1658                }
 1659            })
 1660            .flatten();
 1661
 1662        EditorSnapshot {
 1663            mode: self.mode,
 1664            show_gutter: self.show_gutter,
 1665            show_line_numbers: self.show_line_numbers,
 1666            show_git_diff_gutter: self.show_git_diff_gutter,
 1667            show_code_actions: self.show_code_actions,
 1668            show_runnables: self.show_runnables,
 1669            git_blame_gutter_max_author_length,
 1670            display_snapshot: self.display_map.update(cx, |map, cx| map.snapshot(cx)),
 1671            scroll_anchor: self.scroll_manager.anchor(),
 1672            ongoing_scroll: self.scroll_manager.ongoing_scroll(),
 1673            placeholder_text: self.placeholder_text.clone(),
 1674            is_focused: self.focus_handle.is_focused(window),
 1675            current_line_highlight: self
 1676                .current_line_highlight
 1677                .unwrap_or_else(|| EditorSettings::get_global(cx).current_line_highlight),
 1678            gutter_hovered: self.gutter_hovered,
 1679        }
 1680    }
 1681
 1682    pub fn language_at<T: ToOffset>(&self, point: T, cx: &App) -> Option<Arc<Language>> {
 1683        self.buffer.read(cx).language_at(point, cx)
 1684    }
 1685
 1686    pub fn file_at<T: ToOffset>(&self, point: T, cx: &App) -> Option<Arc<dyn language::File>> {
 1687        self.buffer.read(cx).read(cx).file_at(point).cloned()
 1688    }
 1689
 1690    pub fn active_excerpt(
 1691        &self,
 1692        cx: &App,
 1693    ) -> Option<(ExcerptId, Entity<Buffer>, Range<text::Anchor>)> {
 1694        self.buffer
 1695            .read(cx)
 1696            .excerpt_containing(self.selections.newest_anchor().head(), cx)
 1697    }
 1698
 1699    pub fn mode(&self) -> EditorMode {
 1700        self.mode
 1701    }
 1702
 1703    pub fn collaboration_hub(&self) -> Option<&dyn CollaborationHub> {
 1704        self.collaboration_hub.as_deref()
 1705    }
 1706
 1707    pub fn set_collaboration_hub(&mut self, hub: Box<dyn CollaborationHub>) {
 1708        self.collaboration_hub = Some(hub);
 1709    }
 1710
 1711    pub fn set_in_project_search(&mut self, in_project_search: bool) {
 1712        self.in_project_search = in_project_search;
 1713    }
 1714
 1715    pub fn set_custom_context_menu(
 1716        &mut self,
 1717        f: impl 'static
 1718            + Fn(
 1719                &mut Self,
 1720                DisplayPoint,
 1721                &mut Window,
 1722                &mut Context<Self>,
 1723            ) -> Option<Entity<ui::ContextMenu>>,
 1724    ) {
 1725        self.custom_context_menu = Some(Box::new(f))
 1726    }
 1727
 1728    pub fn set_completion_provider(&mut self, provider: Option<Box<dyn CompletionProvider>>) {
 1729        self.completion_provider = provider;
 1730    }
 1731
 1732    pub fn semantics_provider(&self) -> Option<Rc<dyn SemanticsProvider>> {
 1733        self.semantics_provider.clone()
 1734    }
 1735
 1736    pub fn set_semantics_provider(&mut self, provider: Option<Rc<dyn SemanticsProvider>>) {
 1737        self.semantics_provider = provider;
 1738    }
 1739
 1740    pub fn set_edit_prediction_provider<T>(
 1741        &mut self,
 1742        provider: Option<Entity<T>>,
 1743        window: &mut Window,
 1744        cx: &mut Context<Self>,
 1745    ) where
 1746        T: EditPredictionProvider,
 1747    {
 1748        self.edit_prediction_provider =
 1749            provider.map(|provider| RegisteredInlineCompletionProvider {
 1750                _subscription: cx.observe_in(&provider, window, |this, _, window, cx| {
 1751                    if this.focus_handle.is_focused(window) {
 1752                        this.update_visible_inline_completion(window, cx);
 1753                    }
 1754                }),
 1755                provider: Arc::new(provider),
 1756            });
 1757        self.refresh_inline_completion(false, false, window, cx);
 1758    }
 1759
 1760    pub fn placeholder_text(&self) -> Option<&str> {
 1761        self.placeholder_text.as_deref()
 1762    }
 1763
 1764    pub fn set_placeholder_text(
 1765        &mut self,
 1766        placeholder_text: impl Into<Arc<str>>,
 1767        cx: &mut Context<Self>,
 1768    ) {
 1769        let placeholder_text = Some(placeholder_text.into());
 1770        if self.placeholder_text != placeholder_text {
 1771            self.placeholder_text = placeholder_text;
 1772            cx.notify();
 1773        }
 1774    }
 1775
 1776    pub fn set_cursor_shape(&mut self, cursor_shape: CursorShape, cx: &mut Context<Self>) {
 1777        self.cursor_shape = cursor_shape;
 1778
 1779        // Disrupt blink for immediate user feedback that the cursor shape has changed
 1780        self.blink_manager.update(cx, BlinkManager::show_cursor);
 1781
 1782        cx.notify();
 1783    }
 1784
 1785    pub fn set_current_line_highlight(
 1786        &mut self,
 1787        current_line_highlight: Option<CurrentLineHighlight>,
 1788    ) {
 1789        self.current_line_highlight = current_line_highlight;
 1790    }
 1791
 1792    pub fn set_collapse_matches(&mut self, collapse_matches: bool) {
 1793        self.collapse_matches = collapse_matches;
 1794    }
 1795
 1796    fn register_buffers_with_language_servers(&mut self, cx: &mut Context<Self>) {
 1797        let buffers = self.buffer.read(cx).all_buffers();
 1798        let Some(lsp_store) = self.lsp_store(cx) else {
 1799            return;
 1800        };
 1801        lsp_store.update(cx, |lsp_store, cx| {
 1802            for buffer in buffers {
 1803                self.registered_buffers
 1804                    .entry(buffer.read(cx).remote_id())
 1805                    .or_insert_with(|| {
 1806                        lsp_store.register_buffer_with_language_servers(&buffer, cx)
 1807                    });
 1808            }
 1809        })
 1810    }
 1811
 1812    pub fn range_for_match<T: std::marker::Copy>(&self, range: &Range<T>) -> Range<T> {
 1813        if self.collapse_matches {
 1814            return range.start..range.start;
 1815        }
 1816        range.clone()
 1817    }
 1818
 1819    pub fn set_clip_at_line_ends(&mut self, clip: bool, cx: &mut Context<Self>) {
 1820        if self.display_map.read(cx).clip_at_line_ends != clip {
 1821            self.display_map
 1822                .update(cx, |map, _| map.clip_at_line_ends = clip);
 1823        }
 1824    }
 1825
 1826    pub fn set_input_enabled(&mut self, input_enabled: bool) {
 1827        self.input_enabled = input_enabled;
 1828    }
 1829
 1830    pub fn set_inline_completions_hidden_for_vim_mode(
 1831        &mut self,
 1832        hidden: bool,
 1833        window: &mut Window,
 1834        cx: &mut Context<Self>,
 1835    ) {
 1836        if hidden != self.inline_completions_hidden_for_vim_mode {
 1837            self.inline_completions_hidden_for_vim_mode = hidden;
 1838            if hidden {
 1839                self.update_visible_inline_completion(window, cx);
 1840            } else {
 1841                self.refresh_inline_completion(true, false, window, cx);
 1842            }
 1843        }
 1844    }
 1845
 1846    pub fn set_menu_inline_completions_policy(&mut self, value: MenuInlineCompletionsPolicy) {
 1847        self.menu_inline_completions_policy = value;
 1848    }
 1849
 1850    pub fn set_autoindent(&mut self, autoindent: bool) {
 1851        if autoindent {
 1852            self.autoindent_mode = Some(AutoindentMode::EachLine);
 1853        } else {
 1854            self.autoindent_mode = None;
 1855        }
 1856    }
 1857
 1858    pub fn read_only(&self, cx: &App) -> bool {
 1859        self.read_only || self.buffer.read(cx).read_only()
 1860    }
 1861
 1862    pub fn set_read_only(&mut self, read_only: bool) {
 1863        self.read_only = read_only;
 1864    }
 1865
 1866    pub fn set_use_autoclose(&mut self, autoclose: bool) {
 1867        self.use_autoclose = autoclose;
 1868    }
 1869
 1870    pub fn set_use_auto_surround(&mut self, auto_surround: bool) {
 1871        self.use_auto_surround = auto_surround;
 1872    }
 1873
 1874    pub fn set_auto_replace_emoji_shortcode(&mut self, auto_replace: bool) {
 1875        self.auto_replace_emoji_shortcode = auto_replace;
 1876    }
 1877
 1878    pub fn toggle_inline_completions(
 1879        &mut self,
 1880        _: &ToggleEditPrediction,
 1881        window: &mut Window,
 1882        cx: &mut Context<Self>,
 1883    ) {
 1884        if self.show_inline_completions_override.is_some() {
 1885            self.set_show_inline_completions(None, window, cx);
 1886        } else {
 1887            let cursor = self.selections.newest_anchor().head();
 1888            if let Some((buffer, cursor_buffer_position)) =
 1889                self.buffer.read(cx).text_anchor_for_position(cursor, cx)
 1890            {
 1891                let show_inline_completions = !self.should_show_inline_completions_in_buffer(
 1892                    &buffer,
 1893                    cursor_buffer_position,
 1894                    cx,
 1895                );
 1896                self.set_show_inline_completions(Some(show_inline_completions), window, cx);
 1897            }
 1898        }
 1899    }
 1900
 1901    pub fn set_show_inline_completions(
 1902        &mut self,
 1903        show_edit_predictions: Option<bool>,
 1904        window: &mut Window,
 1905        cx: &mut Context<Self>,
 1906    ) {
 1907        self.show_inline_completions_override = show_edit_predictions;
 1908        self.refresh_inline_completion(false, true, window, cx);
 1909    }
 1910
 1911    pub fn inline_completion_start_anchor(&self) -> Option<Anchor> {
 1912        let active_completion = self.active_inline_completion.as_ref()?;
 1913        let result = match &active_completion.completion {
 1914            InlineCompletion::Edit { edits, .. } => edits.first()?.0.start,
 1915            InlineCompletion::Move { target, .. } => *target,
 1916        };
 1917        Some(result)
 1918    }
 1919
 1920    fn inline_completions_disabled_in_scope(
 1921        &self,
 1922        buffer: &Entity<Buffer>,
 1923        buffer_position: language::Anchor,
 1924        cx: &App,
 1925    ) -> bool {
 1926        let snapshot = buffer.read(cx).snapshot();
 1927        let settings = snapshot.settings_at(buffer_position, cx);
 1928
 1929        let Some(scope) = snapshot.language_scope_at(buffer_position) else {
 1930            return false;
 1931        };
 1932
 1933        scope.override_name().map_or(false, |scope_name| {
 1934            settings
 1935                .edit_predictions_disabled_in
 1936                .iter()
 1937                .any(|s| s == scope_name)
 1938        })
 1939    }
 1940
 1941    pub fn set_use_modal_editing(&mut self, to: bool) {
 1942        self.use_modal_editing = to;
 1943    }
 1944
 1945    pub fn use_modal_editing(&self) -> bool {
 1946        self.use_modal_editing
 1947    }
 1948
 1949    fn selections_did_change(
 1950        &mut self,
 1951        local: bool,
 1952        old_cursor_position: &Anchor,
 1953        show_completions: bool,
 1954        window: &mut Window,
 1955        cx: &mut Context<Self>,
 1956    ) {
 1957        window.invalidate_character_coordinates();
 1958
 1959        // Copy selections to primary selection buffer
 1960        #[cfg(any(target_os = "linux", target_os = "freebsd"))]
 1961        if local {
 1962            let selections = self.selections.all::<usize>(cx);
 1963            let buffer_handle = self.buffer.read(cx).read(cx);
 1964
 1965            let mut text = String::new();
 1966            for (index, selection) in selections.iter().enumerate() {
 1967                let text_for_selection = buffer_handle
 1968                    .text_for_range(selection.start..selection.end)
 1969                    .collect::<String>();
 1970
 1971                text.push_str(&text_for_selection);
 1972                if index != selections.len() - 1 {
 1973                    text.push('\n');
 1974                }
 1975            }
 1976
 1977            if !text.is_empty() {
 1978                cx.write_to_primary(ClipboardItem::new_string(text));
 1979            }
 1980        }
 1981
 1982        if self.focus_handle.is_focused(window) && self.leader_peer_id.is_none() {
 1983            self.buffer.update(cx, |buffer, cx| {
 1984                buffer.set_active_selections(
 1985                    &self.selections.disjoint_anchors(),
 1986                    self.selections.line_mode,
 1987                    self.cursor_shape,
 1988                    cx,
 1989                )
 1990            });
 1991        }
 1992        let display_map = self
 1993            .display_map
 1994            .update(cx, |display_map, cx| display_map.snapshot(cx));
 1995        let buffer = &display_map.buffer_snapshot;
 1996        self.add_selections_state = None;
 1997        self.select_next_state = None;
 1998        self.select_prev_state = None;
 1999        self.select_larger_syntax_node_stack.clear();
 2000        self.invalidate_autoclose_regions(&self.selections.disjoint_anchors(), buffer);
 2001        self.snippet_stack
 2002            .invalidate(&self.selections.disjoint_anchors(), buffer);
 2003        self.take_rename(false, window, cx);
 2004
 2005        let new_cursor_position = self.selections.newest_anchor().head();
 2006
 2007        self.push_to_nav_history(
 2008            *old_cursor_position,
 2009            Some(new_cursor_position.to_point(buffer)),
 2010            cx,
 2011        );
 2012
 2013        if local {
 2014            let new_cursor_position = self.selections.newest_anchor().head();
 2015            let mut context_menu = self.context_menu.borrow_mut();
 2016            let completion_menu = match context_menu.as_ref() {
 2017                Some(CodeContextMenu::Completions(menu)) => Some(menu),
 2018                _ => {
 2019                    *context_menu = None;
 2020                    None
 2021                }
 2022            };
 2023            if let Some(buffer_id) = new_cursor_position.buffer_id {
 2024                if !self.registered_buffers.contains_key(&buffer_id) {
 2025                    if let Some(lsp_store) = self.lsp_store(cx) {
 2026                        lsp_store.update(cx, |lsp_store, cx| {
 2027                            let Some(buffer) = self.buffer.read(cx).buffer(buffer_id) else {
 2028                                return;
 2029                            };
 2030                            self.registered_buffers.insert(
 2031                                buffer_id,
 2032                                lsp_store.register_buffer_with_language_servers(&buffer, cx),
 2033                            );
 2034                        })
 2035                    }
 2036                }
 2037            }
 2038
 2039            if let Some(completion_menu) = completion_menu {
 2040                let cursor_position = new_cursor_position.to_offset(buffer);
 2041                let (word_range, kind) =
 2042                    buffer.surrounding_word(completion_menu.initial_position, true);
 2043                if kind == Some(CharKind::Word)
 2044                    && word_range.to_inclusive().contains(&cursor_position)
 2045                {
 2046                    let mut completion_menu = completion_menu.clone();
 2047                    drop(context_menu);
 2048
 2049                    let query = Self::completion_query(buffer, cursor_position);
 2050                    cx.spawn(move |this, mut cx| async move {
 2051                        completion_menu
 2052                            .filter(query.as_deref(), cx.background_executor().clone())
 2053                            .await;
 2054
 2055                        this.update(&mut cx, |this, cx| {
 2056                            let mut context_menu = this.context_menu.borrow_mut();
 2057                            let Some(CodeContextMenu::Completions(menu)) = context_menu.as_ref()
 2058                            else {
 2059                                return;
 2060                            };
 2061
 2062                            if menu.id > completion_menu.id {
 2063                                return;
 2064                            }
 2065
 2066                            *context_menu = Some(CodeContextMenu::Completions(completion_menu));
 2067                            drop(context_menu);
 2068                            cx.notify();
 2069                        })
 2070                    })
 2071                    .detach();
 2072
 2073                    if show_completions {
 2074                        self.show_completions(&ShowCompletions { trigger: None }, window, cx);
 2075                    }
 2076                } else {
 2077                    drop(context_menu);
 2078                    self.hide_context_menu(window, cx);
 2079                }
 2080            } else {
 2081                drop(context_menu);
 2082            }
 2083
 2084            hide_hover(self, cx);
 2085
 2086            if old_cursor_position.to_display_point(&display_map).row()
 2087                != new_cursor_position.to_display_point(&display_map).row()
 2088            {
 2089                self.available_code_actions.take();
 2090            }
 2091            self.refresh_code_actions(window, cx);
 2092            self.refresh_document_highlights(cx);
 2093            refresh_matching_bracket_highlights(self, window, cx);
 2094            self.update_visible_inline_completion(window, cx);
 2095            linked_editing_ranges::refresh_linked_ranges(self, window, cx);
 2096            if self.git_blame_inline_enabled {
 2097                self.start_inline_blame_timer(window, cx);
 2098            }
 2099        }
 2100
 2101        self.blink_manager.update(cx, BlinkManager::pause_blinking);
 2102        cx.emit(EditorEvent::SelectionsChanged { local });
 2103
 2104        if self.selections.disjoint_anchors().len() == 1 {
 2105            cx.emit(SearchEvent::ActiveMatchChanged)
 2106        }
 2107        cx.notify();
 2108    }
 2109
 2110    pub fn change_selections<R>(
 2111        &mut self,
 2112        autoscroll: Option<Autoscroll>,
 2113        window: &mut Window,
 2114        cx: &mut Context<Self>,
 2115        change: impl FnOnce(&mut MutableSelectionsCollection<'_>) -> R,
 2116    ) -> R {
 2117        self.change_selections_inner(autoscroll, true, window, cx, change)
 2118    }
 2119
 2120    pub fn change_selections_inner<R>(
 2121        &mut self,
 2122        autoscroll: Option<Autoscroll>,
 2123        request_completions: bool,
 2124        window: &mut Window,
 2125        cx: &mut Context<Self>,
 2126        change: impl FnOnce(&mut MutableSelectionsCollection<'_>) -> R,
 2127    ) -> R {
 2128        let old_cursor_position = self.selections.newest_anchor().head();
 2129        self.push_to_selection_history();
 2130
 2131        let (changed, result) = self.selections.change_with(cx, change);
 2132
 2133        if changed {
 2134            if let Some(autoscroll) = autoscroll {
 2135                self.request_autoscroll(autoscroll, cx);
 2136            }
 2137            self.selections_did_change(true, &old_cursor_position, request_completions, window, cx);
 2138
 2139            if self.should_open_signature_help_automatically(
 2140                &old_cursor_position,
 2141                self.signature_help_state.backspace_pressed(),
 2142                cx,
 2143            ) {
 2144                self.show_signature_help(&ShowSignatureHelp, window, cx);
 2145            }
 2146            self.signature_help_state.set_backspace_pressed(false);
 2147        }
 2148
 2149        result
 2150    }
 2151
 2152    pub fn edit<I, S, T>(&mut self, edits: I, cx: &mut Context<Self>)
 2153    where
 2154        I: IntoIterator<Item = (Range<S>, T)>,
 2155        S: ToOffset,
 2156        T: Into<Arc<str>>,
 2157    {
 2158        if self.read_only(cx) {
 2159            return;
 2160        }
 2161
 2162        self.buffer
 2163            .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
 2164    }
 2165
 2166    pub fn edit_with_autoindent<I, S, T>(&mut self, edits: I, cx: &mut Context<Self>)
 2167    where
 2168        I: IntoIterator<Item = (Range<S>, T)>,
 2169        S: ToOffset,
 2170        T: Into<Arc<str>>,
 2171    {
 2172        if self.read_only(cx) {
 2173            return;
 2174        }
 2175
 2176        self.buffer.update(cx, |buffer, cx| {
 2177            buffer.edit(edits, self.autoindent_mode.clone(), cx)
 2178        });
 2179    }
 2180
 2181    pub fn edit_with_block_indent<I, S, T>(
 2182        &mut self,
 2183        edits: I,
 2184        original_indent_columns: Vec<u32>,
 2185        cx: &mut Context<Self>,
 2186    ) where
 2187        I: IntoIterator<Item = (Range<S>, T)>,
 2188        S: ToOffset,
 2189        T: Into<Arc<str>>,
 2190    {
 2191        if self.read_only(cx) {
 2192            return;
 2193        }
 2194
 2195        self.buffer.update(cx, |buffer, cx| {
 2196            buffer.edit(
 2197                edits,
 2198                Some(AutoindentMode::Block {
 2199                    original_indent_columns,
 2200                }),
 2201                cx,
 2202            )
 2203        });
 2204    }
 2205
 2206    fn select(&mut self, phase: SelectPhase, window: &mut Window, cx: &mut Context<Self>) {
 2207        self.hide_context_menu(window, cx);
 2208
 2209        match phase {
 2210            SelectPhase::Begin {
 2211                position,
 2212                add,
 2213                click_count,
 2214            } => self.begin_selection(position, add, click_count, window, cx),
 2215            SelectPhase::BeginColumnar {
 2216                position,
 2217                goal_column,
 2218                reset,
 2219            } => self.begin_columnar_selection(position, goal_column, reset, window, cx),
 2220            SelectPhase::Extend {
 2221                position,
 2222                click_count,
 2223            } => self.extend_selection(position, click_count, window, cx),
 2224            SelectPhase::Update {
 2225                position,
 2226                goal_column,
 2227                scroll_delta,
 2228            } => self.update_selection(position, goal_column, scroll_delta, window, cx),
 2229            SelectPhase::End => self.end_selection(window, cx),
 2230        }
 2231    }
 2232
 2233    fn extend_selection(
 2234        &mut self,
 2235        position: DisplayPoint,
 2236        click_count: usize,
 2237        window: &mut Window,
 2238        cx: &mut Context<Self>,
 2239    ) {
 2240        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 2241        let tail = self.selections.newest::<usize>(cx).tail();
 2242        self.begin_selection(position, false, click_count, window, cx);
 2243
 2244        let position = position.to_offset(&display_map, Bias::Left);
 2245        let tail_anchor = display_map.buffer_snapshot.anchor_before(tail);
 2246
 2247        let mut pending_selection = self
 2248            .selections
 2249            .pending_anchor()
 2250            .expect("extend_selection not called with pending selection");
 2251        if position >= tail {
 2252            pending_selection.start = tail_anchor;
 2253        } else {
 2254            pending_selection.end = tail_anchor;
 2255            pending_selection.reversed = true;
 2256        }
 2257
 2258        let mut pending_mode = self.selections.pending_mode().unwrap();
 2259        match &mut pending_mode {
 2260            SelectMode::Word(range) | SelectMode::Line(range) => *range = tail_anchor..tail_anchor,
 2261            _ => {}
 2262        }
 2263
 2264        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 2265            s.set_pending(pending_selection, pending_mode)
 2266        });
 2267    }
 2268
 2269    fn begin_selection(
 2270        &mut self,
 2271        position: DisplayPoint,
 2272        add: bool,
 2273        click_count: usize,
 2274        window: &mut Window,
 2275        cx: &mut Context<Self>,
 2276    ) {
 2277        if !self.focus_handle.is_focused(window) {
 2278            self.last_focused_descendant = None;
 2279            window.focus(&self.focus_handle);
 2280        }
 2281
 2282        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 2283        let buffer = &display_map.buffer_snapshot;
 2284        let newest_selection = self.selections.newest_anchor().clone();
 2285        let position = display_map.clip_point(position, Bias::Left);
 2286
 2287        let start;
 2288        let end;
 2289        let mode;
 2290        let mut auto_scroll;
 2291        match click_count {
 2292            1 => {
 2293                start = buffer.anchor_before(position.to_point(&display_map));
 2294                end = start;
 2295                mode = SelectMode::Character;
 2296                auto_scroll = true;
 2297            }
 2298            2 => {
 2299                let range = movement::surrounding_word(&display_map, position);
 2300                start = buffer.anchor_before(range.start.to_point(&display_map));
 2301                end = buffer.anchor_before(range.end.to_point(&display_map));
 2302                mode = SelectMode::Word(start..end);
 2303                auto_scroll = true;
 2304            }
 2305            3 => {
 2306                let position = display_map
 2307                    .clip_point(position, Bias::Left)
 2308                    .to_point(&display_map);
 2309                let line_start = display_map.prev_line_boundary(position).0;
 2310                let next_line_start = buffer.clip_point(
 2311                    display_map.next_line_boundary(position).0 + Point::new(1, 0),
 2312                    Bias::Left,
 2313                );
 2314                start = buffer.anchor_before(line_start);
 2315                end = buffer.anchor_before(next_line_start);
 2316                mode = SelectMode::Line(start..end);
 2317                auto_scroll = true;
 2318            }
 2319            _ => {
 2320                start = buffer.anchor_before(0);
 2321                end = buffer.anchor_before(buffer.len());
 2322                mode = SelectMode::All;
 2323                auto_scroll = false;
 2324            }
 2325        }
 2326        auto_scroll &= EditorSettings::get_global(cx).autoscroll_on_clicks;
 2327
 2328        let point_to_delete: Option<usize> = {
 2329            let selected_points: Vec<Selection<Point>> =
 2330                self.selections.disjoint_in_range(start..end, cx);
 2331
 2332            if !add || click_count > 1 {
 2333                None
 2334            } else if !selected_points.is_empty() {
 2335                Some(selected_points[0].id)
 2336            } else {
 2337                let clicked_point_already_selected =
 2338                    self.selections.disjoint.iter().find(|selection| {
 2339                        selection.start.to_point(buffer) == start.to_point(buffer)
 2340                            || selection.end.to_point(buffer) == end.to_point(buffer)
 2341                    });
 2342
 2343                clicked_point_already_selected.map(|selection| selection.id)
 2344            }
 2345        };
 2346
 2347        let selections_count = self.selections.count();
 2348
 2349        self.change_selections(auto_scroll.then(Autoscroll::newest), window, cx, |s| {
 2350            if let Some(point_to_delete) = point_to_delete {
 2351                s.delete(point_to_delete);
 2352
 2353                if selections_count == 1 {
 2354                    s.set_pending_anchor_range(start..end, mode);
 2355                }
 2356            } else {
 2357                if !add {
 2358                    s.clear_disjoint();
 2359                } else if click_count > 1 {
 2360                    s.delete(newest_selection.id)
 2361                }
 2362
 2363                s.set_pending_anchor_range(start..end, mode);
 2364            }
 2365        });
 2366    }
 2367
 2368    fn begin_columnar_selection(
 2369        &mut self,
 2370        position: DisplayPoint,
 2371        goal_column: u32,
 2372        reset: bool,
 2373        window: &mut Window,
 2374        cx: &mut Context<Self>,
 2375    ) {
 2376        if !self.focus_handle.is_focused(window) {
 2377            self.last_focused_descendant = None;
 2378            window.focus(&self.focus_handle);
 2379        }
 2380
 2381        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 2382
 2383        if reset {
 2384            let pointer_position = display_map
 2385                .buffer_snapshot
 2386                .anchor_before(position.to_point(&display_map));
 2387
 2388            self.change_selections(Some(Autoscroll::newest()), window, cx, |s| {
 2389                s.clear_disjoint();
 2390                s.set_pending_anchor_range(
 2391                    pointer_position..pointer_position,
 2392                    SelectMode::Character,
 2393                );
 2394            });
 2395        }
 2396
 2397        let tail = self.selections.newest::<Point>(cx).tail();
 2398        self.columnar_selection_tail = Some(display_map.buffer_snapshot.anchor_before(tail));
 2399
 2400        if !reset {
 2401            self.select_columns(
 2402                tail.to_display_point(&display_map),
 2403                position,
 2404                goal_column,
 2405                &display_map,
 2406                window,
 2407                cx,
 2408            );
 2409        }
 2410    }
 2411
 2412    fn update_selection(
 2413        &mut self,
 2414        position: DisplayPoint,
 2415        goal_column: u32,
 2416        scroll_delta: gpui::Point<f32>,
 2417        window: &mut Window,
 2418        cx: &mut Context<Self>,
 2419    ) {
 2420        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 2421
 2422        if let Some(tail) = self.columnar_selection_tail.as_ref() {
 2423            let tail = tail.to_display_point(&display_map);
 2424            self.select_columns(tail, position, goal_column, &display_map, window, cx);
 2425        } else if let Some(mut pending) = self.selections.pending_anchor() {
 2426            let buffer = self.buffer.read(cx).snapshot(cx);
 2427            let head;
 2428            let tail;
 2429            let mode = self.selections.pending_mode().unwrap();
 2430            match &mode {
 2431                SelectMode::Character => {
 2432                    head = position.to_point(&display_map);
 2433                    tail = pending.tail().to_point(&buffer);
 2434                }
 2435                SelectMode::Word(original_range) => {
 2436                    let original_display_range = original_range.start.to_display_point(&display_map)
 2437                        ..original_range.end.to_display_point(&display_map);
 2438                    let original_buffer_range = original_display_range.start.to_point(&display_map)
 2439                        ..original_display_range.end.to_point(&display_map);
 2440                    if movement::is_inside_word(&display_map, position)
 2441                        || original_display_range.contains(&position)
 2442                    {
 2443                        let word_range = movement::surrounding_word(&display_map, position);
 2444                        if word_range.start < original_display_range.start {
 2445                            head = word_range.start.to_point(&display_map);
 2446                        } else {
 2447                            head = word_range.end.to_point(&display_map);
 2448                        }
 2449                    } else {
 2450                        head = position.to_point(&display_map);
 2451                    }
 2452
 2453                    if head <= original_buffer_range.start {
 2454                        tail = original_buffer_range.end;
 2455                    } else {
 2456                        tail = original_buffer_range.start;
 2457                    }
 2458                }
 2459                SelectMode::Line(original_range) => {
 2460                    let original_range = original_range.to_point(&display_map.buffer_snapshot);
 2461
 2462                    let position = display_map
 2463                        .clip_point(position, Bias::Left)
 2464                        .to_point(&display_map);
 2465                    let line_start = display_map.prev_line_boundary(position).0;
 2466                    let next_line_start = buffer.clip_point(
 2467                        display_map.next_line_boundary(position).0 + Point::new(1, 0),
 2468                        Bias::Left,
 2469                    );
 2470
 2471                    if line_start < original_range.start {
 2472                        head = line_start
 2473                    } else {
 2474                        head = next_line_start
 2475                    }
 2476
 2477                    if head <= original_range.start {
 2478                        tail = original_range.end;
 2479                    } else {
 2480                        tail = original_range.start;
 2481                    }
 2482                }
 2483                SelectMode::All => {
 2484                    return;
 2485                }
 2486            };
 2487
 2488            if head < tail {
 2489                pending.start = buffer.anchor_before(head);
 2490                pending.end = buffer.anchor_before(tail);
 2491                pending.reversed = true;
 2492            } else {
 2493                pending.start = buffer.anchor_before(tail);
 2494                pending.end = buffer.anchor_before(head);
 2495                pending.reversed = false;
 2496            }
 2497
 2498            self.change_selections(None, window, cx, |s| {
 2499                s.set_pending(pending, mode);
 2500            });
 2501        } else {
 2502            log::error!("update_selection dispatched with no pending selection");
 2503            return;
 2504        }
 2505
 2506        self.apply_scroll_delta(scroll_delta, window, cx);
 2507        cx.notify();
 2508    }
 2509
 2510    fn end_selection(&mut self, window: &mut Window, cx: &mut Context<Self>) {
 2511        self.columnar_selection_tail.take();
 2512        if self.selections.pending_anchor().is_some() {
 2513            let selections = self.selections.all::<usize>(cx);
 2514            self.change_selections(None, window, cx, |s| {
 2515                s.select(selections);
 2516                s.clear_pending();
 2517            });
 2518        }
 2519    }
 2520
 2521    fn select_columns(
 2522        &mut self,
 2523        tail: DisplayPoint,
 2524        head: DisplayPoint,
 2525        goal_column: u32,
 2526        display_map: &DisplaySnapshot,
 2527        window: &mut Window,
 2528        cx: &mut Context<Self>,
 2529    ) {
 2530        let start_row = cmp::min(tail.row(), head.row());
 2531        let end_row = cmp::max(tail.row(), head.row());
 2532        let start_column = cmp::min(tail.column(), goal_column);
 2533        let end_column = cmp::max(tail.column(), goal_column);
 2534        let reversed = start_column < tail.column();
 2535
 2536        let selection_ranges = (start_row.0..=end_row.0)
 2537            .map(DisplayRow)
 2538            .filter_map(|row| {
 2539                if start_column <= display_map.line_len(row) && !display_map.is_block_line(row) {
 2540                    let start = display_map
 2541                        .clip_point(DisplayPoint::new(row, start_column), Bias::Left)
 2542                        .to_point(display_map);
 2543                    let end = display_map
 2544                        .clip_point(DisplayPoint::new(row, end_column), Bias::Right)
 2545                        .to_point(display_map);
 2546                    if reversed {
 2547                        Some(end..start)
 2548                    } else {
 2549                        Some(start..end)
 2550                    }
 2551                } else {
 2552                    None
 2553                }
 2554            })
 2555            .collect::<Vec<_>>();
 2556
 2557        self.change_selections(None, window, cx, |s| {
 2558            s.select_ranges(selection_ranges);
 2559        });
 2560        cx.notify();
 2561    }
 2562
 2563    pub fn has_pending_nonempty_selection(&self) -> bool {
 2564        let pending_nonempty_selection = match self.selections.pending_anchor() {
 2565            Some(Selection { start, end, .. }) => start != end,
 2566            None => false,
 2567        };
 2568
 2569        pending_nonempty_selection
 2570            || (self.columnar_selection_tail.is_some() && self.selections.disjoint.len() > 1)
 2571    }
 2572
 2573    pub fn has_pending_selection(&self) -> bool {
 2574        self.selections.pending_anchor().is_some() || self.columnar_selection_tail.is_some()
 2575    }
 2576
 2577    pub fn cancel(&mut self, _: &Cancel, window: &mut Window, cx: &mut Context<Self>) {
 2578        self.selection_mark_mode = false;
 2579
 2580        if self.clear_expanded_diff_hunks(cx) {
 2581            cx.notify();
 2582            return;
 2583        }
 2584        if self.dismiss_menus_and_popups(true, window, cx) {
 2585            return;
 2586        }
 2587
 2588        if self.mode == EditorMode::Full
 2589            && self.change_selections(Some(Autoscroll::fit()), window, cx, |s| s.try_cancel())
 2590        {
 2591            return;
 2592        }
 2593
 2594        cx.propagate();
 2595    }
 2596
 2597    pub fn dismiss_menus_and_popups(
 2598        &mut self,
 2599        is_user_requested: bool,
 2600        window: &mut Window,
 2601        cx: &mut Context<Self>,
 2602    ) -> bool {
 2603        if self.take_rename(false, window, cx).is_some() {
 2604            return true;
 2605        }
 2606
 2607        if hide_hover(self, cx) {
 2608            return true;
 2609        }
 2610
 2611        if self.hide_signature_help(cx, SignatureHelpHiddenBy::Escape) {
 2612            return true;
 2613        }
 2614
 2615        if self.hide_context_menu(window, cx).is_some() {
 2616            return true;
 2617        }
 2618
 2619        if self.mouse_context_menu.take().is_some() {
 2620            return true;
 2621        }
 2622
 2623        if is_user_requested && self.discard_inline_completion(true, cx) {
 2624            return true;
 2625        }
 2626
 2627        if self.snippet_stack.pop().is_some() {
 2628            return true;
 2629        }
 2630
 2631        if self.mode == EditorMode::Full && self.active_diagnostics.is_some() {
 2632            self.dismiss_diagnostics(cx);
 2633            return true;
 2634        }
 2635
 2636        false
 2637    }
 2638
 2639    fn linked_editing_ranges_for(
 2640        &self,
 2641        selection: Range<text::Anchor>,
 2642        cx: &App,
 2643    ) -> Option<HashMap<Entity<Buffer>, Vec<Range<text::Anchor>>>> {
 2644        if self.linked_edit_ranges.is_empty() {
 2645            return None;
 2646        }
 2647        let ((base_range, linked_ranges), buffer_snapshot, buffer) =
 2648            selection.end.buffer_id.and_then(|end_buffer_id| {
 2649                if selection.start.buffer_id != Some(end_buffer_id) {
 2650                    return None;
 2651                }
 2652                let buffer = self.buffer.read(cx).buffer(end_buffer_id)?;
 2653                let snapshot = buffer.read(cx).snapshot();
 2654                self.linked_edit_ranges
 2655                    .get(end_buffer_id, selection.start..selection.end, &snapshot)
 2656                    .map(|ranges| (ranges, snapshot, buffer))
 2657            })?;
 2658        use text::ToOffset as TO;
 2659        // find offset from the start of current range to current cursor position
 2660        let start_byte_offset = TO::to_offset(&base_range.start, &buffer_snapshot);
 2661
 2662        let start_offset = TO::to_offset(&selection.start, &buffer_snapshot);
 2663        let start_difference = start_offset - start_byte_offset;
 2664        let end_offset = TO::to_offset(&selection.end, &buffer_snapshot);
 2665        let end_difference = end_offset - start_byte_offset;
 2666        // Current range has associated linked ranges.
 2667        let mut linked_edits = HashMap::<_, Vec<_>>::default();
 2668        for range in linked_ranges.iter() {
 2669            let start_offset = TO::to_offset(&range.start, &buffer_snapshot);
 2670            let end_offset = start_offset + end_difference;
 2671            let start_offset = start_offset + start_difference;
 2672            if start_offset > buffer_snapshot.len() || end_offset > buffer_snapshot.len() {
 2673                continue;
 2674            }
 2675            if self.selections.disjoint_anchor_ranges().any(|s| {
 2676                if s.start.buffer_id != selection.start.buffer_id
 2677                    || s.end.buffer_id != selection.end.buffer_id
 2678                {
 2679                    return false;
 2680                }
 2681                TO::to_offset(&s.start.text_anchor, &buffer_snapshot) <= end_offset
 2682                    && TO::to_offset(&s.end.text_anchor, &buffer_snapshot) >= start_offset
 2683            }) {
 2684                continue;
 2685            }
 2686            let start = buffer_snapshot.anchor_after(start_offset);
 2687            let end = buffer_snapshot.anchor_after(end_offset);
 2688            linked_edits
 2689                .entry(buffer.clone())
 2690                .or_default()
 2691                .push(start..end);
 2692        }
 2693        Some(linked_edits)
 2694    }
 2695
 2696    pub fn handle_input(&mut self, text: &str, window: &mut Window, cx: &mut Context<Self>) {
 2697        let text: Arc<str> = text.into();
 2698
 2699        if self.read_only(cx) {
 2700            return;
 2701        }
 2702
 2703        let selections = self.selections.all_adjusted(cx);
 2704        let mut bracket_inserted = false;
 2705        let mut edits = Vec::new();
 2706        let mut linked_edits = HashMap::<_, Vec<_>>::default();
 2707        let mut new_selections = Vec::with_capacity(selections.len());
 2708        let mut new_autoclose_regions = Vec::new();
 2709        let snapshot = self.buffer.read(cx).read(cx);
 2710
 2711        for (selection, autoclose_region) in
 2712            self.selections_with_autoclose_regions(selections, &snapshot)
 2713        {
 2714            if let Some(scope) = snapshot.language_scope_at(selection.head()) {
 2715                // Determine if the inserted text matches the opening or closing
 2716                // bracket of any of this language's bracket pairs.
 2717                let mut bracket_pair = None;
 2718                let mut is_bracket_pair_start = false;
 2719                let mut is_bracket_pair_end = false;
 2720                if !text.is_empty() {
 2721                    // `text` can be empty when a user is using IME (e.g. Chinese Wubi Simplified)
 2722                    //  and they are removing the character that triggered IME popup.
 2723                    for (pair, enabled) in scope.brackets() {
 2724                        if !pair.close && !pair.surround {
 2725                            continue;
 2726                        }
 2727
 2728                        if enabled && pair.start.ends_with(text.as_ref()) {
 2729                            let prefix_len = pair.start.len() - text.len();
 2730                            let preceding_text_matches_prefix = prefix_len == 0
 2731                                || (selection.start.column >= (prefix_len as u32)
 2732                                    && snapshot.contains_str_at(
 2733                                        Point::new(
 2734                                            selection.start.row,
 2735                                            selection.start.column - (prefix_len as u32),
 2736                                        ),
 2737                                        &pair.start[..prefix_len],
 2738                                    ));
 2739                            if preceding_text_matches_prefix {
 2740                                bracket_pair = Some(pair.clone());
 2741                                is_bracket_pair_start = true;
 2742                                break;
 2743                            }
 2744                        }
 2745                        if pair.end.as_str() == text.as_ref() {
 2746                            bracket_pair = Some(pair.clone());
 2747                            is_bracket_pair_end = true;
 2748                            break;
 2749                        }
 2750                    }
 2751                }
 2752
 2753                if let Some(bracket_pair) = bracket_pair {
 2754                    let snapshot_settings = snapshot.settings_at(selection.start, cx);
 2755                    let autoclose = self.use_autoclose && snapshot_settings.use_autoclose;
 2756                    let auto_surround =
 2757                        self.use_auto_surround && snapshot_settings.use_auto_surround;
 2758                    if selection.is_empty() {
 2759                        if is_bracket_pair_start {
 2760                            // If the inserted text is a suffix of an opening bracket and the
 2761                            // selection is preceded by the rest of the opening bracket, then
 2762                            // insert the closing bracket.
 2763                            let following_text_allows_autoclose = snapshot
 2764                                .chars_at(selection.start)
 2765                                .next()
 2766                                .map_or(true, |c| scope.should_autoclose_before(c));
 2767
 2768                            let is_closing_quote = if bracket_pair.end == bracket_pair.start
 2769                                && bracket_pair.start.len() == 1
 2770                            {
 2771                                let target = bracket_pair.start.chars().next().unwrap();
 2772                                let current_line_count = snapshot
 2773                                    .reversed_chars_at(selection.start)
 2774                                    .take_while(|&c| c != '\n')
 2775                                    .filter(|&c| c == target)
 2776                                    .count();
 2777                                current_line_count % 2 == 1
 2778                            } else {
 2779                                false
 2780                            };
 2781
 2782                            if autoclose
 2783                                && bracket_pair.close
 2784                                && following_text_allows_autoclose
 2785                                && !is_closing_quote
 2786                            {
 2787                                let anchor = snapshot.anchor_before(selection.end);
 2788                                new_selections.push((selection.map(|_| anchor), text.len()));
 2789                                new_autoclose_regions.push((
 2790                                    anchor,
 2791                                    text.len(),
 2792                                    selection.id,
 2793                                    bracket_pair.clone(),
 2794                                ));
 2795                                edits.push((
 2796                                    selection.range(),
 2797                                    format!("{}{}", text, bracket_pair.end).into(),
 2798                                ));
 2799                                bracket_inserted = true;
 2800                                continue;
 2801                            }
 2802                        }
 2803
 2804                        if let Some(region) = autoclose_region {
 2805                            // If the selection is followed by an auto-inserted closing bracket,
 2806                            // then don't insert that closing bracket again; just move the selection
 2807                            // past the closing bracket.
 2808                            let should_skip = selection.end == region.range.end.to_point(&snapshot)
 2809                                && text.as_ref() == region.pair.end.as_str();
 2810                            if should_skip {
 2811                                let anchor = snapshot.anchor_after(selection.end);
 2812                                new_selections
 2813                                    .push((selection.map(|_| anchor), region.pair.end.len()));
 2814                                continue;
 2815                            }
 2816                        }
 2817
 2818                        let always_treat_brackets_as_autoclosed = snapshot
 2819                            .settings_at(selection.start, cx)
 2820                            .always_treat_brackets_as_autoclosed;
 2821                        if always_treat_brackets_as_autoclosed
 2822                            && is_bracket_pair_end
 2823                            && snapshot.contains_str_at(selection.end, text.as_ref())
 2824                        {
 2825                            // Otherwise, when `always_treat_brackets_as_autoclosed` is set to `true
 2826                            // and the inserted text is a closing bracket and the selection is followed
 2827                            // by the closing bracket then move the selection past the closing bracket.
 2828                            let anchor = snapshot.anchor_after(selection.end);
 2829                            new_selections.push((selection.map(|_| anchor), text.len()));
 2830                            continue;
 2831                        }
 2832                    }
 2833                    // If an opening bracket is 1 character long and is typed while
 2834                    // text is selected, then surround that text with the bracket pair.
 2835                    else if auto_surround
 2836                        && bracket_pair.surround
 2837                        && is_bracket_pair_start
 2838                        && bracket_pair.start.chars().count() == 1
 2839                    {
 2840                        edits.push((selection.start..selection.start, text.clone()));
 2841                        edits.push((
 2842                            selection.end..selection.end,
 2843                            bracket_pair.end.as_str().into(),
 2844                        ));
 2845                        bracket_inserted = true;
 2846                        new_selections.push((
 2847                            Selection {
 2848                                id: selection.id,
 2849                                start: snapshot.anchor_after(selection.start),
 2850                                end: snapshot.anchor_before(selection.end),
 2851                                reversed: selection.reversed,
 2852                                goal: selection.goal,
 2853                            },
 2854                            0,
 2855                        ));
 2856                        continue;
 2857                    }
 2858                }
 2859            }
 2860
 2861            if self.auto_replace_emoji_shortcode
 2862                && selection.is_empty()
 2863                && text.as_ref().ends_with(':')
 2864            {
 2865                if let Some(possible_emoji_short_code) =
 2866                    Self::find_possible_emoji_shortcode_at_position(&snapshot, selection.start)
 2867                {
 2868                    if !possible_emoji_short_code.is_empty() {
 2869                        if let Some(emoji) = emojis::get_by_shortcode(&possible_emoji_short_code) {
 2870                            let emoji_shortcode_start = Point::new(
 2871                                selection.start.row,
 2872                                selection.start.column - possible_emoji_short_code.len() as u32 - 1,
 2873                            );
 2874
 2875                            // Remove shortcode from buffer
 2876                            edits.push((
 2877                                emoji_shortcode_start..selection.start,
 2878                                "".to_string().into(),
 2879                            ));
 2880                            new_selections.push((
 2881                                Selection {
 2882                                    id: selection.id,
 2883                                    start: snapshot.anchor_after(emoji_shortcode_start),
 2884                                    end: snapshot.anchor_before(selection.start),
 2885                                    reversed: selection.reversed,
 2886                                    goal: selection.goal,
 2887                                },
 2888                                0,
 2889                            ));
 2890
 2891                            // Insert emoji
 2892                            let selection_start_anchor = snapshot.anchor_after(selection.start);
 2893                            new_selections.push((selection.map(|_| selection_start_anchor), 0));
 2894                            edits.push((selection.start..selection.end, emoji.to_string().into()));
 2895
 2896                            continue;
 2897                        }
 2898                    }
 2899                }
 2900            }
 2901
 2902            // If not handling any auto-close operation, then just replace the selected
 2903            // text with the given input and move the selection to the end of the
 2904            // newly inserted text.
 2905            let anchor = snapshot.anchor_after(selection.end);
 2906            if !self.linked_edit_ranges.is_empty() {
 2907                let start_anchor = snapshot.anchor_before(selection.start);
 2908
 2909                let is_word_char = text.chars().next().map_or(true, |char| {
 2910                    let classifier = snapshot.char_classifier_at(start_anchor.to_offset(&snapshot));
 2911                    classifier.is_word(char)
 2912                });
 2913
 2914                if is_word_char {
 2915                    if let Some(ranges) = self
 2916                        .linked_editing_ranges_for(start_anchor.text_anchor..anchor.text_anchor, cx)
 2917                    {
 2918                        for (buffer, edits) in ranges {
 2919                            linked_edits
 2920                                .entry(buffer.clone())
 2921                                .or_default()
 2922                                .extend(edits.into_iter().map(|range| (range, text.clone())));
 2923                        }
 2924                    }
 2925                }
 2926            }
 2927
 2928            new_selections.push((selection.map(|_| anchor), 0));
 2929            edits.push((selection.start..selection.end, text.clone()));
 2930        }
 2931
 2932        drop(snapshot);
 2933
 2934        self.transact(window, cx, |this, window, cx| {
 2935            this.buffer.update(cx, |buffer, cx| {
 2936                buffer.edit(edits, this.autoindent_mode.clone(), cx);
 2937            });
 2938            for (buffer, edits) in linked_edits {
 2939                buffer.update(cx, |buffer, cx| {
 2940                    let snapshot = buffer.snapshot();
 2941                    let edits = edits
 2942                        .into_iter()
 2943                        .map(|(range, text)| {
 2944                            use text::ToPoint as TP;
 2945                            let end_point = TP::to_point(&range.end, &snapshot);
 2946                            let start_point = TP::to_point(&range.start, &snapshot);
 2947                            (start_point..end_point, text)
 2948                        })
 2949                        .sorted_by_key(|(range, _)| range.start)
 2950                        .collect::<Vec<_>>();
 2951                    buffer.edit(edits, None, cx);
 2952                })
 2953            }
 2954            let new_anchor_selections = new_selections.iter().map(|e| &e.0);
 2955            let new_selection_deltas = new_selections.iter().map(|e| e.1);
 2956            let map = this.display_map.update(cx, |map, cx| map.snapshot(cx));
 2957            let new_selections = resolve_selections::<usize, _>(new_anchor_selections, &map)
 2958                .zip(new_selection_deltas)
 2959                .map(|(selection, delta)| Selection {
 2960                    id: selection.id,
 2961                    start: selection.start + delta,
 2962                    end: selection.end + delta,
 2963                    reversed: selection.reversed,
 2964                    goal: SelectionGoal::None,
 2965                })
 2966                .collect::<Vec<_>>();
 2967
 2968            let mut i = 0;
 2969            for (position, delta, selection_id, pair) in new_autoclose_regions {
 2970                let position = position.to_offset(&map.buffer_snapshot) + delta;
 2971                let start = map.buffer_snapshot.anchor_before(position);
 2972                let end = map.buffer_snapshot.anchor_after(position);
 2973                while let Some(existing_state) = this.autoclose_regions.get(i) {
 2974                    match existing_state.range.start.cmp(&start, &map.buffer_snapshot) {
 2975                        Ordering::Less => i += 1,
 2976                        Ordering::Greater => break,
 2977                        Ordering::Equal => {
 2978                            match end.cmp(&existing_state.range.end, &map.buffer_snapshot) {
 2979                                Ordering::Less => i += 1,
 2980                                Ordering::Equal => break,
 2981                                Ordering::Greater => break,
 2982                            }
 2983                        }
 2984                    }
 2985                }
 2986                this.autoclose_regions.insert(
 2987                    i,
 2988                    AutocloseRegion {
 2989                        selection_id,
 2990                        range: start..end,
 2991                        pair,
 2992                    },
 2993                );
 2994            }
 2995
 2996            let had_active_inline_completion = this.has_active_inline_completion();
 2997            this.change_selections_inner(Some(Autoscroll::fit()), false, window, cx, |s| {
 2998                s.select(new_selections)
 2999            });
 3000
 3001            if !bracket_inserted {
 3002                if let Some(on_type_format_task) =
 3003                    this.trigger_on_type_formatting(text.to_string(), window, cx)
 3004                {
 3005                    on_type_format_task.detach_and_log_err(cx);
 3006                }
 3007            }
 3008
 3009            let editor_settings = EditorSettings::get_global(cx);
 3010            if bracket_inserted
 3011                && (editor_settings.auto_signature_help
 3012                    || editor_settings.show_signature_help_after_edits)
 3013            {
 3014                this.show_signature_help(&ShowSignatureHelp, window, cx);
 3015            }
 3016
 3017            let trigger_in_words =
 3018                this.show_edit_predictions_in_menu(cx) || !had_active_inline_completion;
 3019            this.trigger_completion_on_input(&text, trigger_in_words, window, cx);
 3020            linked_editing_ranges::refresh_linked_ranges(this, window, cx);
 3021            this.refresh_inline_completion(true, false, window, cx);
 3022        });
 3023    }
 3024
 3025    fn find_possible_emoji_shortcode_at_position(
 3026        snapshot: &MultiBufferSnapshot,
 3027        position: Point,
 3028    ) -> Option<String> {
 3029        let mut chars = Vec::new();
 3030        let mut found_colon = false;
 3031        for char in snapshot.reversed_chars_at(position).take(100) {
 3032            // Found a possible emoji shortcode in the middle of the buffer
 3033            if found_colon {
 3034                if char.is_whitespace() {
 3035                    chars.reverse();
 3036                    return Some(chars.iter().collect());
 3037                }
 3038                // If the previous character is not a whitespace, we are in the middle of a word
 3039                // and we only want to complete the shortcode if the word is made up of other emojis
 3040                let mut containing_word = String::new();
 3041                for ch in snapshot
 3042                    .reversed_chars_at(position)
 3043                    .skip(chars.len() + 1)
 3044                    .take(100)
 3045                {
 3046                    if ch.is_whitespace() {
 3047                        break;
 3048                    }
 3049                    containing_word.push(ch);
 3050                }
 3051                let containing_word = containing_word.chars().rev().collect::<String>();
 3052                if util::word_consists_of_emojis(containing_word.as_str()) {
 3053                    chars.reverse();
 3054                    return Some(chars.iter().collect());
 3055                }
 3056            }
 3057
 3058            if char.is_whitespace() || !char.is_ascii() {
 3059                return None;
 3060            }
 3061            if char == ':' {
 3062                found_colon = true;
 3063            } else {
 3064                chars.push(char);
 3065            }
 3066        }
 3067        // Found a possible emoji shortcode at the beginning of the buffer
 3068        chars.reverse();
 3069        Some(chars.iter().collect())
 3070    }
 3071
 3072    pub fn newline(&mut self, _: &Newline, window: &mut Window, cx: &mut Context<Self>) {
 3073        self.transact(window, cx, |this, window, cx| {
 3074            let (edits, selection_fixup_info): (Vec<_>, Vec<_>) = {
 3075                let selections = this.selections.all::<usize>(cx);
 3076                let multi_buffer = this.buffer.read(cx);
 3077                let buffer = multi_buffer.snapshot(cx);
 3078                selections
 3079                    .iter()
 3080                    .map(|selection| {
 3081                        let start_point = selection.start.to_point(&buffer);
 3082                        let mut indent =
 3083                            buffer.indent_size_for_line(MultiBufferRow(start_point.row));
 3084                        indent.len = cmp::min(indent.len, start_point.column);
 3085                        let start = selection.start;
 3086                        let end = selection.end;
 3087                        let selection_is_empty = start == end;
 3088                        let language_scope = buffer.language_scope_at(start);
 3089                        let (comment_delimiter, insert_extra_newline) = if let Some(language) =
 3090                            &language_scope
 3091                        {
 3092                            let leading_whitespace_len = buffer
 3093                                .reversed_chars_at(start)
 3094                                .take_while(|c| c.is_whitespace() && *c != '\n')
 3095                                .map(|c| c.len_utf8())
 3096                                .sum::<usize>();
 3097
 3098                            let trailing_whitespace_len = buffer
 3099                                .chars_at(end)
 3100                                .take_while(|c| c.is_whitespace() && *c != '\n')
 3101                                .map(|c| c.len_utf8())
 3102                                .sum::<usize>();
 3103
 3104                            let insert_extra_newline =
 3105                                language.brackets().any(|(pair, enabled)| {
 3106                                    let pair_start = pair.start.trim_end();
 3107                                    let pair_end = pair.end.trim_start();
 3108
 3109                                    enabled
 3110                                        && pair.newline
 3111                                        && buffer.contains_str_at(
 3112                                            end + trailing_whitespace_len,
 3113                                            pair_end,
 3114                                        )
 3115                                        && buffer.contains_str_at(
 3116                                            (start - leading_whitespace_len)
 3117                                                .saturating_sub(pair_start.len()),
 3118                                            pair_start,
 3119                                        )
 3120                                });
 3121
 3122                            // Comment extension on newline is allowed only for cursor selections
 3123                            let comment_delimiter = maybe!({
 3124                                if !selection_is_empty {
 3125                                    return None;
 3126                                }
 3127
 3128                                if !multi_buffer.settings_at(0, cx).extend_comment_on_newline {
 3129                                    return None;
 3130                                }
 3131
 3132                                let delimiters = language.line_comment_prefixes();
 3133                                let max_len_of_delimiter =
 3134                                    delimiters.iter().map(|delimiter| delimiter.len()).max()?;
 3135                                let (snapshot, range) =
 3136                                    buffer.buffer_line_for_row(MultiBufferRow(start_point.row))?;
 3137
 3138                                let mut index_of_first_non_whitespace = 0;
 3139                                let comment_candidate = snapshot
 3140                                    .chars_for_range(range)
 3141                                    .skip_while(|c| {
 3142                                        let should_skip = c.is_whitespace();
 3143                                        if should_skip {
 3144                                            index_of_first_non_whitespace += 1;
 3145                                        }
 3146                                        should_skip
 3147                                    })
 3148                                    .take(max_len_of_delimiter)
 3149                                    .collect::<String>();
 3150                                let comment_prefix = delimiters.iter().find(|comment_prefix| {
 3151                                    comment_candidate.starts_with(comment_prefix.as_ref())
 3152                                })?;
 3153                                let cursor_is_placed_after_comment_marker =
 3154                                    index_of_first_non_whitespace + comment_prefix.len()
 3155                                        <= start_point.column as usize;
 3156                                if cursor_is_placed_after_comment_marker {
 3157                                    Some(comment_prefix.clone())
 3158                                } else {
 3159                                    None
 3160                                }
 3161                            });
 3162                            (comment_delimiter, insert_extra_newline)
 3163                        } else {
 3164                            (None, false)
 3165                        };
 3166
 3167                        let capacity_for_delimiter = comment_delimiter
 3168                            .as_deref()
 3169                            .map(str::len)
 3170                            .unwrap_or_default();
 3171                        let mut new_text =
 3172                            String::with_capacity(1 + capacity_for_delimiter + indent.len as usize);
 3173                        new_text.push('\n');
 3174                        new_text.extend(indent.chars());
 3175                        if let Some(delimiter) = &comment_delimiter {
 3176                            new_text.push_str(delimiter);
 3177                        }
 3178                        if insert_extra_newline {
 3179                            new_text = new_text.repeat(2);
 3180                        }
 3181
 3182                        let anchor = buffer.anchor_after(end);
 3183                        let new_selection = selection.map(|_| anchor);
 3184                        (
 3185                            (start..end, new_text),
 3186                            (insert_extra_newline, new_selection),
 3187                        )
 3188                    })
 3189                    .unzip()
 3190            };
 3191
 3192            this.edit_with_autoindent(edits, cx);
 3193            let buffer = this.buffer.read(cx).snapshot(cx);
 3194            let new_selections = selection_fixup_info
 3195                .into_iter()
 3196                .map(|(extra_newline_inserted, new_selection)| {
 3197                    let mut cursor = new_selection.end.to_point(&buffer);
 3198                    if extra_newline_inserted {
 3199                        cursor.row -= 1;
 3200                        cursor.column = buffer.line_len(MultiBufferRow(cursor.row));
 3201                    }
 3202                    new_selection.map(|_| cursor)
 3203                })
 3204                .collect();
 3205
 3206            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 3207                s.select(new_selections)
 3208            });
 3209            this.refresh_inline_completion(true, false, window, cx);
 3210        });
 3211    }
 3212
 3213    pub fn newline_above(&mut self, _: &NewlineAbove, window: &mut Window, cx: &mut Context<Self>) {
 3214        let buffer = self.buffer.read(cx);
 3215        let snapshot = buffer.snapshot(cx);
 3216
 3217        let mut edits = Vec::new();
 3218        let mut rows = Vec::new();
 3219
 3220        for (rows_inserted, selection) in self.selections.all_adjusted(cx).into_iter().enumerate() {
 3221            let cursor = selection.head();
 3222            let row = cursor.row;
 3223
 3224            let start_of_line = snapshot.clip_point(Point::new(row, 0), Bias::Left);
 3225
 3226            let newline = "\n".to_string();
 3227            edits.push((start_of_line..start_of_line, newline));
 3228
 3229            rows.push(row + rows_inserted as u32);
 3230        }
 3231
 3232        self.transact(window, cx, |editor, window, cx| {
 3233            editor.edit(edits, cx);
 3234
 3235            editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 3236                let mut index = 0;
 3237                s.move_cursors_with(|map, _, _| {
 3238                    let row = rows[index];
 3239                    index += 1;
 3240
 3241                    let point = Point::new(row, 0);
 3242                    let boundary = map.next_line_boundary(point).1;
 3243                    let clipped = map.clip_point(boundary, Bias::Left);
 3244
 3245                    (clipped, SelectionGoal::None)
 3246                });
 3247            });
 3248
 3249            let mut indent_edits = Vec::new();
 3250            let multibuffer_snapshot = editor.buffer.read(cx).snapshot(cx);
 3251            for row in rows {
 3252                let indents = multibuffer_snapshot.suggested_indents(row..row + 1, cx);
 3253                for (row, indent) in indents {
 3254                    if indent.len == 0 {
 3255                        continue;
 3256                    }
 3257
 3258                    let text = match indent.kind {
 3259                        IndentKind::Space => " ".repeat(indent.len as usize),
 3260                        IndentKind::Tab => "\t".repeat(indent.len as usize),
 3261                    };
 3262                    let point = Point::new(row.0, 0);
 3263                    indent_edits.push((point..point, text));
 3264                }
 3265            }
 3266            editor.edit(indent_edits, cx);
 3267        });
 3268    }
 3269
 3270    pub fn newline_below(&mut self, _: &NewlineBelow, window: &mut Window, cx: &mut Context<Self>) {
 3271        let buffer = self.buffer.read(cx);
 3272        let snapshot = buffer.snapshot(cx);
 3273
 3274        let mut edits = Vec::new();
 3275        let mut rows = Vec::new();
 3276        let mut rows_inserted = 0;
 3277
 3278        for selection in self.selections.all_adjusted(cx) {
 3279            let cursor = selection.head();
 3280            let row = cursor.row;
 3281
 3282            let point = Point::new(row + 1, 0);
 3283            let start_of_line = snapshot.clip_point(point, Bias::Left);
 3284
 3285            let newline = "\n".to_string();
 3286            edits.push((start_of_line..start_of_line, newline));
 3287
 3288            rows_inserted += 1;
 3289            rows.push(row + rows_inserted);
 3290        }
 3291
 3292        self.transact(window, cx, |editor, window, cx| {
 3293            editor.edit(edits, cx);
 3294
 3295            editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 3296                let mut index = 0;
 3297                s.move_cursors_with(|map, _, _| {
 3298                    let row = rows[index];
 3299                    index += 1;
 3300
 3301                    let point = Point::new(row, 0);
 3302                    let boundary = map.next_line_boundary(point).1;
 3303                    let clipped = map.clip_point(boundary, Bias::Left);
 3304
 3305                    (clipped, SelectionGoal::None)
 3306                });
 3307            });
 3308
 3309            let mut indent_edits = Vec::new();
 3310            let multibuffer_snapshot = editor.buffer.read(cx).snapshot(cx);
 3311            for row in rows {
 3312                let indents = multibuffer_snapshot.suggested_indents(row..row + 1, cx);
 3313                for (row, indent) in indents {
 3314                    if indent.len == 0 {
 3315                        continue;
 3316                    }
 3317
 3318                    let text = match indent.kind {
 3319                        IndentKind::Space => " ".repeat(indent.len as usize),
 3320                        IndentKind::Tab => "\t".repeat(indent.len as usize),
 3321                    };
 3322                    let point = Point::new(row.0, 0);
 3323                    indent_edits.push((point..point, text));
 3324                }
 3325            }
 3326            editor.edit(indent_edits, cx);
 3327        });
 3328    }
 3329
 3330    pub fn insert(&mut self, text: &str, window: &mut Window, cx: &mut Context<Self>) {
 3331        let autoindent = text.is_empty().not().then(|| AutoindentMode::Block {
 3332            original_indent_columns: Vec::new(),
 3333        });
 3334        self.insert_with_autoindent_mode(text, autoindent, window, cx);
 3335    }
 3336
 3337    fn insert_with_autoindent_mode(
 3338        &mut self,
 3339        text: &str,
 3340        autoindent_mode: Option<AutoindentMode>,
 3341        window: &mut Window,
 3342        cx: &mut Context<Self>,
 3343    ) {
 3344        if self.read_only(cx) {
 3345            return;
 3346        }
 3347
 3348        let text: Arc<str> = text.into();
 3349        self.transact(window, cx, |this, window, cx| {
 3350            let old_selections = this.selections.all_adjusted(cx);
 3351            let selection_anchors = this.buffer.update(cx, |buffer, cx| {
 3352                let anchors = {
 3353                    let snapshot = buffer.read(cx);
 3354                    old_selections
 3355                        .iter()
 3356                        .map(|s| {
 3357                            let anchor = snapshot.anchor_after(s.head());
 3358                            s.map(|_| anchor)
 3359                        })
 3360                        .collect::<Vec<_>>()
 3361                };
 3362                buffer.edit(
 3363                    old_selections
 3364                        .iter()
 3365                        .map(|s| (s.start..s.end, text.clone())),
 3366                    autoindent_mode,
 3367                    cx,
 3368                );
 3369                anchors
 3370            });
 3371
 3372            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 3373                s.select_anchors(selection_anchors);
 3374            });
 3375
 3376            cx.notify();
 3377        });
 3378    }
 3379
 3380    fn trigger_completion_on_input(
 3381        &mut self,
 3382        text: &str,
 3383        trigger_in_words: bool,
 3384        window: &mut Window,
 3385        cx: &mut Context<Self>,
 3386    ) {
 3387        if self.is_completion_trigger(text, trigger_in_words, cx) {
 3388            self.show_completions(
 3389                &ShowCompletions {
 3390                    trigger: Some(text.to_owned()).filter(|x| !x.is_empty()),
 3391                },
 3392                window,
 3393                cx,
 3394            );
 3395        } else {
 3396            self.hide_context_menu(window, cx);
 3397        }
 3398    }
 3399
 3400    fn is_completion_trigger(
 3401        &self,
 3402        text: &str,
 3403        trigger_in_words: bool,
 3404        cx: &mut Context<Self>,
 3405    ) -> bool {
 3406        let position = self.selections.newest_anchor().head();
 3407        let multibuffer = self.buffer.read(cx);
 3408        let Some(buffer) = position
 3409            .buffer_id
 3410            .and_then(|buffer_id| multibuffer.buffer(buffer_id).clone())
 3411        else {
 3412            return false;
 3413        };
 3414
 3415        if let Some(completion_provider) = &self.completion_provider {
 3416            completion_provider.is_completion_trigger(
 3417                &buffer,
 3418                position.text_anchor,
 3419                text,
 3420                trigger_in_words,
 3421                cx,
 3422            )
 3423        } else {
 3424            false
 3425        }
 3426    }
 3427
 3428    /// If any empty selections is touching the start of its innermost containing autoclose
 3429    /// region, expand it to select the brackets.
 3430    fn select_autoclose_pair(&mut self, window: &mut Window, cx: &mut Context<Self>) {
 3431        let selections = self.selections.all::<usize>(cx);
 3432        let buffer = self.buffer.read(cx).read(cx);
 3433        let new_selections = self
 3434            .selections_with_autoclose_regions(selections, &buffer)
 3435            .map(|(mut selection, region)| {
 3436                if !selection.is_empty() {
 3437                    return selection;
 3438                }
 3439
 3440                if let Some(region) = region {
 3441                    let mut range = region.range.to_offset(&buffer);
 3442                    if selection.start == range.start && range.start >= region.pair.start.len() {
 3443                        range.start -= region.pair.start.len();
 3444                        if buffer.contains_str_at(range.start, &region.pair.start)
 3445                            && buffer.contains_str_at(range.end, &region.pair.end)
 3446                        {
 3447                            range.end += region.pair.end.len();
 3448                            selection.start = range.start;
 3449                            selection.end = range.end;
 3450
 3451                            return selection;
 3452                        }
 3453                    }
 3454                }
 3455
 3456                let always_treat_brackets_as_autoclosed = buffer
 3457                    .settings_at(selection.start, cx)
 3458                    .always_treat_brackets_as_autoclosed;
 3459
 3460                if !always_treat_brackets_as_autoclosed {
 3461                    return selection;
 3462                }
 3463
 3464                if let Some(scope) = buffer.language_scope_at(selection.start) {
 3465                    for (pair, enabled) in scope.brackets() {
 3466                        if !enabled || !pair.close {
 3467                            continue;
 3468                        }
 3469
 3470                        if buffer.contains_str_at(selection.start, &pair.end) {
 3471                            let pair_start_len = pair.start.len();
 3472                            if buffer.contains_str_at(
 3473                                selection.start.saturating_sub(pair_start_len),
 3474                                &pair.start,
 3475                            ) {
 3476                                selection.start -= pair_start_len;
 3477                                selection.end += pair.end.len();
 3478
 3479                                return selection;
 3480                            }
 3481                        }
 3482                    }
 3483                }
 3484
 3485                selection
 3486            })
 3487            .collect();
 3488
 3489        drop(buffer);
 3490        self.change_selections(None, window, cx, |selections| {
 3491            selections.select(new_selections)
 3492        });
 3493    }
 3494
 3495    /// Iterate the given selections, and for each one, find the smallest surrounding
 3496    /// autoclose region. This uses the ordering of the selections and the autoclose
 3497    /// regions to avoid repeated comparisons.
 3498    fn selections_with_autoclose_regions<'a, D: ToOffset + Clone>(
 3499        &'a self,
 3500        selections: impl IntoIterator<Item = Selection<D>>,
 3501        buffer: &'a MultiBufferSnapshot,
 3502    ) -> impl Iterator<Item = (Selection<D>, Option<&'a AutocloseRegion>)> {
 3503        let mut i = 0;
 3504        let mut regions = self.autoclose_regions.as_slice();
 3505        selections.into_iter().map(move |selection| {
 3506            let range = selection.start.to_offset(buffer)..selection.end.to_offset(buffer);
 3507
 3508            let mut enclosing = None;
 3509            while let Some(pair_state) = regions.get(i) {
 3510                if pair_state.range.end.to_offset(buffer) < range.start {
 3511                    regions = &regions[i + 1..];
 3512                    i = 0;
 3513                } else if pair_state.range.start.to_offset(buffer) > range.end {
 3514                    break;
 3515                } else {
 3516                    if pair_state.selection_id == selection.id {
 3517                        enclosing = Some(pair_state);
 3518                    }
 3519                    i += 1;
 3520                }
 3521            }
 3522
 3523            (selection, enclosing)
 3524        })
 3525    }
 3526
 3527    /// Remove any autoclose regions that no longer contain their selection.
 3528    fn invalidate_autoclose_regions(
 3529        &mut self,
 3530        mut selections: &[Selection<Anchor>],
 3531        buffer: &MultiBufferSnapshot,
 3532    ) {
 3533        self.autoclose_regions.retain(|state| {
 3534            let mut i = 0;
 3535            while let Some(selection) = selections.get(i) {
 3536                if selection.end.cmp(&state.range.start, buffer).is_lt() {
 3537                    selections = &selections[1..];
 3538                    continue;
 3539                }
 3540                if selection.start.cmp(&state.range.end, buffer).is_gt() {
 3541                    break;
 3542                }
 3543                if selection.id == state.selection_id {
 3544                    return true;
 3545                } else {
 3546                    i += 1;
 3547                }
 3548            }
 3549            false
 3550        });
 3551    }
 3552
 3553    fn completion_query(buffer: &MultiBufferSnapshot, position: impl ToOffset) -> Option<String> {
 3554        let offset = position.to_offset(buffer);
 3555        let (word_range, kind) = buffer.surrounding_word(offset, true);
 3556        if offset > word_range.start && kind == Some(CharKind::Word) {
 3557            Some(
 3558                buffer
 3559                    .text_for_range(word_range.start..offset)
 3560                    .collect::<String>(),
 3561            )
 3562        } else {
 3563            None
 3564        }
 3565    }
 3566
 3567    pub fn toggle_inlay_hints(
 3568        &mut self,
 3569        _: &ToggleInlayHints,
 3570        _: &mut Window,
 3571        cx: &mut Context<Self>,
 3572    ) {
 3573        self.refresh_inlay_hints(
 3574            InlayHintRefreshReason::Toggle(!self.inlay_hint_cache.enabled),
 3575            cx,
 3576        );
 3577    }
 3578
 3579    pub fn inlay_hints_enabled(&self) -> bool {
 3580        self.inlay_hint_cache.enabled
 3581    }
 3582
 3583    fn refresh_inlay_hints(&mut self, reason: InlayHintRefreshReason, cx: &mut Context<Self>) {
 3584        if self.semantics_provider.is_none() || self.mode != EditorMode::Full {
 3585            return;
 3586        }
 3587
 3588        let reason_description = reason.description();
 3589        let ignore_debounce = matches!(
 3590            reason,
 3591            InlayHintRefreshReason::SettingsChange(_)
 3592                | InlayHintRefreshReason::Toggle(_)
 3593                | InlayHintRefreshReason::ExcerptsRemoved(_)
 3594        );
 3595        let (invalidate_cache, required_languages) = match reason {
 3596            InlayHintRefreshReason::Toggle(enabled) => {
 3597                self.inlay_hint_cache.enabled = enabled;
 3598                if enabled {
 3599                    (InvalidationStrategy::RefreshRequested, None)
 3600                } else {
 3601                    self.inlay_hint_cache.clear();
 3602                    self.splice_inlays(
 3603                        &self
 3604                            .visible_inlay_hints(cx)
 3605                            .iter()
 3606                            .map(|inlay| inlay.id)
 3607                            .collect::<Vec<InlayId>>(),
 3608                        Vec::new(),
 3609                        cx,
 3610                    );
 3611                    return;
 3612                }
 3613            }
 3614            InlayHintRefreshReason::SettingsChange(new_settings) => {
 3615                match self.inlay_hint_cache.update_settings(
 3616                    &self.buffer,
 3617                    new_settings,
 3618                    self.visible_inlay_hints(cx),
 3619                    cx,
 3620                ) {
 3621                    ControlFlow::Break(Some(InlaySplice {
 3622                        to_remove,
 3623                        to_insert,
 3624                    })) => {
 3625                        self.splice_inlays(&to_remove, to_insert, cx);
 3626                        return;
 3627                    }
 3628                    ControlFlow::Break(None) => return,
 3629                    ControlFlow::Continue(()) => (InvalidationStrategy::RefreshRequested, None),
 3630                }
 3631            }
 3632            InlayHintRefreshReason::ExcerptsRemoved(excerpts_removed) => {
 3633                if let Some(InlaySplice {
 3634                    to_remove,
 3635                    to_insert,
 3636                }) = self.inlay_hint_cache.remove_excerpts(excerpts_removed)
 3637                {
 3638                    self.splice_inlays(&to_remove, to_insert, cx);
 3639                }
 3640                return;
 3641            }
 3642            InlayHintRefreshReason::NewLinesShown => (InvalidationStrategy::None, None),
 3643            InlayHintRefreshReason::BufferEdited(buffer_languages) => {
 3644                (InvalidationStrategy::BufferEdited, Some(buffer_languages))
 3645            }
 3646            InlayHintRefreshReason::RefreshRequested => {
 3647                (InvalidationStrategy::RefreshRequested, None)
 3648            }
 3649        };
 3650
 3651        if let Some(InlaySplice {
 3652            to_remove,
 3653            to_insert,
 3654        }) = self.inlay_hint_cache.spawn_hint_refresh(
 3655            reason_description,
 3656            self.excerpts_for_inlay_hints_query(required_languages.as_ref(), cx),
 3657            invalidate_cache,
 3658            ignore_debounce,
 3659            cx,
 3660        ) {
 3661            self.splice_inlays(&to_remove, to_insert, cx);
 3662        }
 3663    }
 3664
 3665    fn visible_inlay_hints(&self, cx: &Context<Editor>) -> Vec<Inlay> {
 3666        self.display_map
 3667            .read(cx)
 3668            .current_inlays()
 3669            .filter(move |inlay| matches!(inlay.id, InlayId::Hint(_)))
 3670            .cloned()
 3671            .collect()
 3672    }
 3673
 3674    pub fn excerpts_for_inlay_hints_query(
 3675        &self,
 3676        restrict_to_languages: Option<&HashSet<Arc<Language>>>,
 3677        cx: &mut Context<Editor>,
 3678    ) -> HashMap<ExcerptId, (Entity<Buffer>, clock::Global, Range<usize>)> {
 3679        let Some(project) = self.project.as_ref() else {
 3680            return HashMap::default();
 3681        };
 3682        let project = project.read(cx);
 3683        let multi_buffer = self.buffer().read(cx);
 3684        let multi_buffer_snapshot = multi_buffer.snapshot(cx);
 3685        let multi_buffer_visible_start = self
 3686            .scroll_manager
 3687            .anchor()
 3688            .anchor
 3689            .to_point(&multi_buffer_snapshot);
 3690        let multi_buffer_visible_end = multi_buffer_snapshot.clip_point(
 3691            multi_buffer_visible_start
 3692                + Point::new(self.visible_line_count().unwrap_or(0.).ceil() as u32, 0),
 3693            Bias::Left,
 3694        );
 3695        let multi_buffer_visible_range = multi_buffer_visible_start..multi_buffer_visible_end;
 3696        multi_buffer_snapshot
 3697            .range_to_buffer_ranges(multi_buffer_visible_range)
 3698            .into_iter()
 3699            .filter(|(_, excerpt_visible_range, _)| !excerpt_visible_range.is_empty())
 3700            .filter_map(|(buffer, excerpt_visible_range, excerpt_id)| {
 3701                let buffer_file = project::File::from_dyn(buffer.file())?;
 3702                let buffer_worktree = project.worktree_for_id(buffer_file.worktree_id(cx), cx)?;
 3703                let worktree_entry = buffer_worktree
 3704                    .read(cx)
 3705                    .entry_for_id(buffer_file.project_entry_id(cx)?)?;
 3706                if worktree_entry.is_ignored {
 3707                    return None;
 3708                }
 3709
 3710                let language = buffer.language()?;
 3711                if let Some(restrict_to_languages) = restrict_to_languages {
 3712                    if !restrict_to_languages.contains(language) {
 3713                        return None;
 3714                    }
 3715                }
 3716                Some((
 3717                    excerpt_id,
 3718                    (
 3719                        multi_buffer.buffer(buffer.remote_id()).unwrap(),
 3720                        buffer.version().clone(),
 3721                        excerpt_visible_range,
 3722                    ),
 3723                ))
 3724            })
 3725            .collect()
 3726    }
 3727
 3728    pub fn text_layout_details(&self, window: &mut Window) -> TextLayoutDetails {
 3729        TextLayoutDetails {
 3730            text_system: window.text_system().clone(),
 3731            editor_style: self.style.clone().unwrap(),
 3732            rem_size: window.rem_size(),
 3733            scroll_anchor: self.scroll_manager.anchor(),
 3734            visible_rows: self.visible_line_count(),
 3735            vertical_scroll_margin: self.scroll_manager.vertical_scroll_margin,
 3736        }
 3737    }
 3738
 3739    pub fn splice_inlays(
 3740        &self,
 3741        to_remove: &[InlayId],
 3742        to_insert: Vec<Inlay>,
 3743        cx: &mut Context<Self>,
 3744    ) {
 3745        self.display_map.update(cx, |display_map, cx| {
 3746            display_map.splice_inlays(to_remove, to_insert, cx)
 3747        });
 3748        cx.notify();
 3749    }
 3750
 3751    fn trigger_on_type_formatting(
 3752        &self,
 3753        input: String,
 3754        window: &mut Window,
 3755        cx: &mut Context<Self>,
 3756    ) -> Option<Task<Result<()>>> {
 3757        if input.len() != 1 {
 3758            return None;
 3759        }
 3760
 3761        let project = self.project.as_ref()?;
 3762        let position = self.selections.newest_anchor().head();
 3763        let (buffer, buffer_position) = self
 3764            .buffer
 3765            .read(cx)
 3766            .text_anchor_for_position(position, cx)?;
 3767
 3768        let settings = language_settings::language_settings(
 3769            buffer
 3770                .read(cx)
 3771                .language_at(buffer_position)
 3772                .map(|l| l.name()),
 3773            buffer.read(cx).file(),
 3774            cx,
 3775        );
 3776        if !settings.use_on_type_format {
 3777            return None;
 3778        }
 3779
 3780        // OnTypeFormatting returns a list of edits, no need to pass them between Zed instances,
 3781        // hence we do LSP request & edit on host side only — add formats to host's history.
 3782        let push_to_lsp_host_history = true;
 3783        // If this is not the host, append its history with new edits.
 3784        let push_to_client_history = project.read(cx).is_via_collab();
 3785
 3786        let on_type_formatting = project.update(cx, |project, cx| {
 3787            project.on_type_format(
 3788                buffer.clone(),
 3789                buffer_position,
 3790                input,
 3791                push_to_lsp_host_history,
 3792                cx,
 3793            )
 3794        });
 3795        Some(cx.spawn_in(window, |editor, mut cx| async move {
 3796            if let Some(transaction) = on_type_formatting.await? {
 3797                if push_to_client_history {
 3798                    buffer
 3799                        .update(&mut cx, |buffer, _| {
 3800                            buffer.push_transaction(transaction, Instant::now());
 3801                        })
 3802                        .ok();
 3803                }
 3804                editor.update(&mut cx, |editor, cx| {
 3805                    editor.refresh_document_highlights(cx);
 3806                })?;
 3807            }
 3808            Ok(())
 3809        }))
 3810    }
 3811
 3812    pub fn show_completions(
 3813        &mut self,
 3814        options: &ShowCompletions,
 3815        window: &mut Window,
 3816        cx: &mut Context<Self>,
 3817    ) {
 3818        if self.pending_rename.is_some() {
 3819            return;
 3820        }
 3821
 3822        let Some(provider) = self.completion_provider.as_ref() else {
 3823            return;
 3824        };
 3825
 3826        if !self.snippet_stack.is_empty() && self.context_menu.borrow().as_ref().is_some() {
 3827            return;
 3828        }
 3829
 3830        let position = self.selections.newest_anchor().head();
 3831        if position.diff_base_anchor.is_some() {
 3832            return;
 3833        }
 3834        let (buffer, buffer_position) =
 3835            if let Some(output) = self.buffer.read(cx).text_anchor_for_position(position, cx) {
 3836                output
 3837            } else {
 3838                return;
 3839            };
 3840        let show_completion_documentation = buffer
 3841            .read(cx)
 3842            .snapshot()
 3843            .settings_at(buffer_position, cx)
 3844            .show_completion_documentation;
 3845
 3846        let query = Self::completion_query(&self.buffer.read(cx).read(cx), position);
 3847
 3848        let trigger_kind = match &options.trigger {
 3849            Some(trigger) if buffer.read(cx).completion_triggers().contains(trigger) => {
 3850                CompletionTriggerKind::TRIGGER_CHARACTER
 3851            }
 3852            _ => CompletionTriggerKind::INVOKED,
 3853        };
 3854        let completion_context = CompletionContext {
 3855            trigger_character: options.trigger.as_ref().and_then(|trigger| {
 3856                if trigger_kind == CompletionTriggerKind::TRIGGER_CHARACTER {
 3857                    Some(String::from(trigger))
 3858                } else {
 3859                    None
 3860                }
 3861            }),
 3862            trigger_kind,
 3863        };
 3864        let completions =
 3865            provider.completions(&buffer, buffer_position, completion_context, window, cx);
 3866        let sort_completions = provider.sort_completions();
 3867
 3868        let id = post_inc(&mut self.next_completion_id);
 3869        let task = cx.spawn_in(window, |editor, mut cx| {
 3870            async move {
 3871                editor.update(&mut cx, |this, _| {
 3872                    this.completion_tasks.retain(|(task_id, _)| *task_id >= id);
 3873                })?;
 3874                let completions = completions.await.log_err();
 3875                let menu = if let Some(completions) = completions {
 3876                    let mut menu = CompletionsMenu::new(
 3877                        id,
 3878                        sort_completions,
 3879                        show_completion_documentation,
 3880                        position,
 3881                        buffer.clone(),
 3882                        completions.into(),
 3883                    );
 3884
 3885                    menu.filter(query.as_deref(), cx.background_executor().clone())
 3886                        .await;
 3887
 3888                    menu.visible().then_some(menu)
 3889                } else {
 3890                    None
 3891                };
 3892
 3893                editor.update_in(&mut cx, |editor, window, cx| {
 3894                    match editor.context_menu.borrow().as_ref() {
 3895                        None => {}
 3896                        Some(CodeContextMenu::Completions(prev_menu)) => {
 3897                            if prev_menu.id > id {
 3898                                return;
 3899                            }
 3900                        }
 3901                        _ => return,
 3902                    }
 3903
 3904                    if editor.focus_handle.is_focused(window) && menu.is_some() {
 3905                        let mut menu = menu.unwrap();
 3906                        menu.resolve_visible_completions(editor.completion_provider.as_deref(), cx);
 3907
 3908                        *editor.context_menu.borrow_mut() =
 3909                            Some(CodeContextMenu::Completions(menu));
 3910
 3911                        if editor.show_edit_predictions_in_menu(cx) {
 3912                            editor.update_visible_inline_completion(window, cx);
 3913                        } else {
 3914                            editor.discard_inline_completion(false, cx);
 3915                        }
 3916
 3917                        cx.notify();
 3918                    } else if editor.completion_tasks.len() <= 1 {
 3919                        // If there are no more completion tasks and the last menu was
 3920                        // empty, we should hide it.
 3921                        let was_hidden = editor.hide_context_menu(window, cx).is_none();
 3922                        // If it was already hidden and we don't show inline
 3923                        // completions in the menu, we should also show the
 3924                        // inline-completion when available.
 3925                        if was_hidden && editor.show_edit_predictions_in_menu(cx) {
 3926                            editor.update_visible_inline_completion(window, cx);
 3927                        }
 3928                    }
 3929                })?;
 3930
 3931                Ok::<_, anyhow::Error>(())
 3932            }
 3933            .log_err()
 3934        });
 3935
 3936        self.completion_tasks.push((id, task));
 3937    }
 3938
 3939    pub fn confirm_completion(
 3940        &mut self,
 3941        action: &ConfirmCompletion,
 3942        window: &mut Window,
 3943        cx: &mut Context<Self>,
 3944    ) -> Option<Task<Result<()>>> {
 3945        self.do_completion(action.item_ix, CompletionIntent::Complete, window, cx)
 3946    }
 3947
 3948    pub fn compose_completion(
 3949        &mut self,
 3950        action: &ComposeCompletion,
 3951        window: &mut Window,
 3952        cx: &mut Context<Self>,
 3953    ) -> Option<Task<Result<()>>> {
 3954        self.do_completion(action.item_ix, CompletionIntent::Compose, window, cx)
 3955    }
 3956
 3957    fn do_completion(
 3958        &mut self,
 3959        item_ix: Option<usize>,
 3960        intent: CompletionIntent,
 3961        window: &mut Window,
 3962        cx: &mut Context<Editor>,
 3963    ) -> Option<Task<std::result::Result<(), anyhow::Error>>> {
 3964        use language::ToOffset as _;
 3965
 3966        let completions_menu =
 3967            if let CodeContextMenu::Completions(menu) = self.hide_context_menu(window, cx)? {
 3968                menu
 3969            } else {
 3970                return None;
 3971            };
 3972
 3973        let entries = completions_menu.entries.borrow();
 3974        let mat = entries.get(item_ix.unwrap_or(completions_menu.selected_item))?;
 3975        if self.show_edit_predictions_in_menu(cx) {
 3976            self.discard_inline_completion(true, cx);
 3977        }
 3978        let candidate_id = mat.candidate_id;
 3979        drop(entries);
 3980
 3981        let buffer_handle = completions_menu.buffer;
 3982        let completion = completions_menu
 3983            .completions
 3984            .borrow()
 3985            .get(candidate_id)?
 3986            .clone();
 3987        cx.stop_propagation();
 3988
 3989        let snippet;
 3990        let text;
 3991
 3992        if completion.is_snippet() {
 3993            snippet = Some(Snippet::parse(&completion.new_text).log_err()?);
 3994            text = snippet.as_ref().unwrap().text.clone();
 3995        } else {
 3996            snippet = None;
 3997            text = completion.new_text.clone();
 3998        };
 3999        let selections = self.selections.all::<usize>(cx);
 4000        let buffer = buffer_handle.read(cx);
 4001        let old_range = completion.old_range.to_offset(buffer);
 4002        let old_text = buffer.text_for_range(old_range.clone()).collect::<String>();
 4003
 4004        let newest_selection = self.selections.newest_anchor();
 4005        if newest_selection.start.buffer_id != Some(buffer_handle.read(cx).remote_id()) {
 4006            return None;
 4007        }
 4008
 4009        let lookbehind = newest_selection
 4010            .start
 4011            .text_anchor
 4012            .to_offset(buffer)
 4013            .saturating_sub(old_range.start);
 4014        let lookahead = old_range
 4015            .end
 4016            .saturating_sub(newest_selection.end.text_anchor.to_offset(buffer));
 4017        let mut common_prefix_len = old_text
 4018            .bytes()
 4019            .zip(text.bytes())
 4020            .take_while(|(a, b)| a == b)
 4021            .count();
 4022
 4023        let snapshot = self.buffer.read(cx).snapshot(cx);
 4024        let mut range_to_replace: Option<Range<isize>> = None;
 4025        let mut ranges = Vec::new();
 4026        let mut linked_edits = HashMap::<_, Vec<_>>::default();
 4027        for selection in &selections {
 4028            if snapshot.contains_str_at(selection.start.saturating_sub(lookbehind), &old_text) {
 4029                let start = selection.start.saturating_sub(lookbehind);
 4030                let end = selection.end + lookahead;
 4031                if selection.id == newest_selection.id {
 4032                    range_to_replace = Some(
 4033                        ((start + common_prefix_len) as isize - selection.start as isize)
 4034                            ..(end as isize - selection.start as isize),
 4035                    );
 4036                }
 4037                ranges.push(start + common_prefix_len..end);
 4038            } else {
 4039                common_prefix_len = 0;
 4040                ranges.clear();
 4041                ranges.extend(selections.iter().map(|s| {
 4042                    if s.id == newest_selection.id {
 4043                        range_to_replace = Some(
 4044                            old_range.start.to_offset_utf16(&snapshot).0 as isize
 4045                                - selection.start as isize
 4046                                ..old_range.end.to_offset_utf16(&snapshot).0 as isize
 4047                                    - selection.start as isize,
 4048                        );
 4049                        old_range.clone()
 4050                    } else {
 4051                        s.start..s.end
 4052                    }
 4053                }));
 4054                break;
 4055            }
 4056            if !self.linked_edit_ranges.is_empty() {
 4057                let start_anchor = snapshot.anchor_before(selection.head());
 4058                let end_anchor = snapshot.anchor_after(selection.tail());
 4059                if let Some(ranges) = self
 4060                    .linked_editing_ranges_for(start_anchor.text_anchor..end_anchor.text_anchor, cx)
 4061                {
 4062                    for (buffer, edits) in ranges {
 4063                        linked_edits.entry(buffer.clone()).or_default().extend(
 4064                            edits
 4065                                .into_iter()
 4066                                .map(|range| (range, text[common_prefix_len..].to_owned())),
 4067                        );
 4068                    }
 4069                }
 4070            }
 4071        }
 4072        let text = &text[common_prefix_len..];
 4073
 4074        cx.emit(EditorEvent::InputHandled {
 4075            utf16_range_to_replace: range_to_replace,
 4076            text: text.into(),
 4077        });
 4078
 4079        self.transact(window, cx, |this, window, cx| {
 4080            if let Some(mut snippet) = snippet {
 4081                snippet.text = text.to_string();
 4082                for tabstop in snippet
 4083                    .tabstops
 4084                    .iter_mut()
 4085                    .flat_map(|tabstop| tabstop.ranges.iter_mut())
 4086                {
 4087                    tabstop.start -= common_prefix_len as isize;
 4088                    tabstop.end -= common_prefix_len as isize;
 4089                }
 4090
 4091                this.insert_snippet(&ranges, snippet, window, cx).log_err();
 4092            } else {
 4093                this.buffer.update(cx, |buffer, cx| {
 4094                    buffer.edit(
 4095                        ranges.iter().map(|range| (range.clone(), text)),
 4096                        this.autoindent_mode.clone(),
 4097                        cx,
 4098                    );
 4099                });
 4100            }
 4101            for (buffer, edits) in linked_edits {
 4102                buffer.update(cx, |buffer, cx| {
 4103                    let snapshot = buffer.snapshot();
 4104                    let edits = edits
 4105                        .into_iter()
 4106                        .map(|(range, text)| {
 4107                            use text::ToPoint as TP;
 4108                            let end_point = TP::to_point(&range.end, &snapshot);
 4109                            let start_point = TP::to_point(&range.start, &snapshot);
 4110                            (start_point..end_point, text)
 4111                        })
 4112                        .sorted_by_key(|(range, _)| range.start)
 4113                        .collect::<Vec<_>>();
 4114                    buffer.edit(edits, None, cx);
 4115                })
 4116            }
 4117
 4118            this.refresh_inline_completion(true, false, window, cx);
 4119        });
 4120
 4121        let show_new_completions_on_confirm = completion
 4122            .confirm
 4123            .as_ref()
 4124            .map_or(false, |confirm| confirm(intent, window, cx));
 4125        if show_new_completions_on_confirm {
 4126            self.show_completions(&ShowCompletions { trigger: None }, window, cx);
 4127        }
 4128
 4129        let provider = self.completion_provider.as_ref()?;
 4130        drop(completion);
 4131        let apply_edits = provider.apply_additional_edits_for_completion(
 4132            buffer_handle,
 4133            completions_menu.completions.clone(),
 4134            candidate_id,
 4135            true,
 4136            cx,
 4137        );
 4138
 4139        let editor_settings = EditorSettings::get_global(cx);
 4140        if editor_settings.show_signature_help_after_edits || editor_settings.auto_signature_help {
 4141            // After the code completion is finished, users often want to know what signatures are needed.
 4142            // so we should automatically call signature_help
 4143            self.show_signature_help(&ShowSignatureHelp, window, cx);
 4144        }
 4145
 4146        Some(cx.foreground_executor().spawn(async move {
 4147            apply_edits.await?;
 4148            Ok(())
 4149        }))
 4150    }
 4151
 4152    pub fn toggle_code_actions(
 4153        &mut self,
 4154        action: &ToggleCodeActions,
 4155        window: &mut Window,
 4156        cx: &mut Context<Self>,
 4157    ) {
 4158        let mut context_menu = self.context_menu.borrow_mut();
 4159        if let Some(CodeContextMenu::CodeActions(code_actions)) = context_menu.as_ref() {
 4160            if code_actions.deployed_from_indicator == action.deployed_from_indicator {
 4161                // Toggle if we're selecting the same one
 4162                *context_menu = None;
 4163                cx.notify();
 4164                return;
 4165            } else {
 4166                // Otherwise, clear it and start a new one
 4167                *context_menu = None;
 4168                cx.notify();
 4169            }
 4170        }
 4171        drop(context_menu);
 4172        let snapshot = self.snapshot(window, cx);
 4173        let deployed_from_indicator = action.deployed_from_indicator;
 4174        let mut task = self.code_actions_task.take();
 4175        let action = action.clone();
 4176        cx.spawn_in(window, |editor, mut cx| async move {
 4177            while let Some(prev_task) = task {
 4178                prev_task.await.log_err();
 4179                task = editor.update(&mut cx, |this, _| this.code_actions_task.take())?;
 4180            }
 4181
 4182            let spawned_test_task = editor.update_in(&mut cx, |editor, window, cx| {
 4183                if editor.focus_handle.is_focused(window) {
 4184                    let multibuffer_point = action
 4185                        .deployed_from_indicator
 4186                        .map(|row| DisplayPoint::new(row, 0).to_point(&snapshot))
 4187                        .unwrap_or_else(|| editor.selections.newest::<Point>(cx).head());
 4188                    let (buffer, buffer_row) = snapshot
 4189                        .buffer_snapshot
 4190                        .buffer_line_for_row(MultiBufferRow(multibuffer_point.row))
 4191                        .and_then(|(buffer_snapshot, range)| {
 4192                            editor
 4193                                .buffer
 4194                                .read(cx)
 4195                                .buffer(buffer_snapshot.remote_id())
 4196                                .map(|buffer| (buffer, range.start.row))
 4197                        })?;
 4198                    let (_, code_actions) = editor
 4199                        .available_code_actions
 4200                        .clone()
 4201                        .and_then(|(location, code_actions)| {
 4202                            let snapshot = location.buffer.read(cx).snapshot();
 4203                            let point_range = location.range.to_point(&snapshot);
 4204                            let point_range = point_range.start.row..=point_range.end.row;
 4205                            if point_range.contains(&buffer_row) {
 4206                                Some((location, code_actions))
 4207                            } else {
 4208                                None
 4209                            }
 4210                        })
 4211                        .unzip();
 4212                    let buffer_id = buffer.read(cx).remote_id();
 4213                    let tasks = editor
 4214                        .tasks
 4215                        .get(&(buffer_id, buffer_row))
 4216                        .map(|t| Arc::new(t.to_owned()));
 4217                    if tasks.is_none() && code_actions.is_none() {
 4218                        return None;
 4219                    }
 4220
 4221                    editor.completion_tasks.clear();
 4222                    editor.discard_inline_completion(false, cx);
 4223                    let task_context =
 4224                        tasks
 4225                            .as_ref()
 4226                            .zip(editor.project.clone())
 4227                            .map(|(tasks, project)| {
 4228                                Self::build_tasks_context(&project, &buffer, buffer_row, tasks, cx)
 4229                            });
 4230
 4231                    Some(cx.spawn_in(window, |editor, mut cx| async move {
 4232                        let task_context = match task_context {
 4233                            Some(task_context) => task_context.await,
 4234                            None => None,
 4235                        };
 4236                        let resolved_tasks =
 4237                            tasks.zip(task_context).map(|(tasks, task_context)| {
 4238                                Rc::new(ResolvedTasks {
 4239                                    templates: tasks.resolve(&task_context).collect(),
 4240                                    position: snapshot.buffer_snapshot.anchor_before(Point::new(
 4241                                        multibuffer_point.row,
 4242                                        tasks.column,
 4243                                    )),
 4244                                })
 4245                            });
 4246                        let spawn_straight_away = resolved_tasks
 4247                            .as_ref()
 4248                            .map_or(false, |tasks| tasks.templates.len() == 1)
 4249                            && code_actions
 4250                                .as_ref()
 4251                                .map_or(true, |actions| actions.is_empty());
 4252                        if let Ok(task) = editor.update_in(&mut cx, |editor, window, cx| {
 4253                            *editor.context_menu.borrow_mut() =
 4254                                Some(CodeContextMenu::CodeActions(CodeActionsMenu {
 4255                                    buffer,
 4256                                    actions: CodeActionContents {
 4257                                        tasks: resolved_tasks,
 4258                                        actions: code_actions,
 4259                                    },
 4260                                    selected_item: Default::default(),
 4261                                    scroll_handle: UniformListScrollHandle::default(),
 4262                                    deployed_from_indicator,
 4263                                }));
 4264                            if spawn_straight_away {
 4265                                if let Some(task) = editor.confirm_code_action(
 4266                                    &ConfirmCodeAction { item_ix: Some(0) },
 4267                                    window,
 4268                                    cx,
 4269                                ) {
 4270                                    cx.notify();
 4271                                    return task;
 4272                                }
 4273                            }
 4274                            cx.notify();
 4275                            Task::ready(Ok(()))
 4276                        }) {
 4277                            task.await
 4278                        } else {
 4279                            Ok(())
 4280                        }
 4281                    }))
 4282                } else {
 4283                    Some(Task::ready(Ok(())))
 4284                }
 4285            })?;
 4286            if let Some(task) = spawned_test_task {
 4287                task.await?;
 4288            }
 4289
 4290            Ok::<_, anyhow::Error>(())
 4291        })
 4292        .detach_and_log_err(cx);
 4293    }
 4294
 4295    pub fn confirm_code_action(
 4296        &mut self,
 4297        action: &ConfirmCodeAction,
 4298        window: &mut Window,
 4299        cx: &mut Context<Self>,
 4300    ) -> Option<Task<Result<()>>> {
 4301        let actions_menu =
 4302            if let CodeContextMenu::CodeActions(menu) = self.hide_context_menu(window, cx)? {
 4303                menu
 4304            } else {
 4305                return None;
 4306            };
 4307        let action_ix = action.item_ix.unwrap_or(actions_menu.selected_item);
 4308        let action = actions_menu.actions.get(action_ix)?;
 4309        let title = action.label();
 4310        let buffer = actions_menu.buffer;
 4311        let workspace = self.workspace()?;
 4312
 4313        match action {
 4314            CodeActionsItem::Task(task_source_kind, resolved_task) => {
 4315                workspace.update(cx, |workspace, cx| {
 4316                    workspace::tasks::schedule_resolved_task(
 4317                        workspace,
 4318                        task_source_kind,
 4319                        resolved_task,
 4320                        false,
 4321                        cx,
 4322                    );
 4323
 4324                    Some(Task::ready(Ok(())))
 4325                })
 4326            }
 4327            CodeActionsItem::CodeAction {
 4328                excerpt_id,
 4329                action,
 4330                provider,
 4331            } => {
 4332                let apply_code_action =
 4333                    provider.apply_code_action(buffer, action, excerpt_id, true, window, cx);
 4334                let workspace = workspace.downgrade();
 4335                Some(cx.spawn_in(window, |editor, cx| async move {
 4336                    let project_transaction = apply_code_action.await?;
 4337                    Self::open_project_transaction(
 4338                        &editor,
 4339                        workspace,
 4340                        project_transaction,
 4341                        title,
 4342                        cx,
 4343                    )
 4344                    .await
 4345                }))
 4346            }
 4347        }
 4348    }
 4349
 4350    pub async fn open_project_transaction(
 4351        this: &WeakEntity<Editor>,
 4352        workspace: WeakEntity<Workspace>,
 4353        transaction: ProjectTransaction,
 4354        title: String,
 4355        mut cx: AsyncWindowContext,
 4356    ) -> Result<()> {
 4357        let mut entries = transaction.0.into_iter().collect::<Vec<_>>();
 4358        cx.update(|_, cx| {
 4359            entries.sort_unstable_by_key(|(buffer, _)| {
 4360                buffer.read(cx).file().map(|f| f.path().clone())
 4361            });
 4362        })?;
 4363
 4364        // If the project transaction's edits are all contained within this editor, then
 4365        // avoid opening a new editor to display them.
 4366
 4367        if let Some((buffer, transaction)) = entries.first() {
 4368            if entries.len() == 1 {
 4369                let excerpt = this.update(&mut cx, |editor, cx| {
 4370                    editor
 4371                        .buffer()
 4372                        .read(cx)
 4373                        .excerpt_containing(editor.selections.newest_anchor().head(), cx)
 4374                })?;
 4375                if let Some((_, excerpted_buffer, excerpt_range)) = excerpt {
 4376                    if excerpted_buffer == *buffer {
 4377                        let all_edits_within_excerpt = buffer.read_with(&cx, |buffer, _| {
 4378                            let excerpt_range = excerpt_range.to_offset(buffer);
 4379                            buffer
 4380                                .edited_ranges_for_transaction::<usize>(transaction)
 4381                                .all(|range| {
 4382                                    excerpt_range.start <= range.start
 4383                                        && excerpt_range.end >= range.end
 4384                                })
 4385                        })?;
 4386
 4387                        if all_edits_within_excerpt {
 4388                            return Ok(());
 4389                        }
 4390                    }
 4391                }
 4392            }
 4393        } else {
 4394            return Ok(());
 4395        }
 4396
 4397        let mut ranges_to_highlight = Vec::new();
 4398        let excerpt_buffer = cx.new(|cx| {
 4399            let mut multibuffer = MultiBuffer::new(Capability::ReadWrite).with_title(title);
 4400            for (buffer_handle, transaction) in &entries {
 4401                let buffer = buffer_handle.read(cx);
 4402                ranges_to_highlight.extend(
 4403                    multibuffer.push_excerpts_with_context_lines(
 4404                        buffer_handle.clone(),
 4405                        buffer
 4406                            .edited_ranges_for_transaction::<usize>(transaction)
 4407                            .collect(),
 4408                        DEFAULT_MULTIBUFFER_CONTEXT,
 4409                        cx,
 4410                    ),
 4411                );
 4412            }
 4413            multibuffer.push_transaction(entries.iter().map(|(b, t)| (b, t)), cx);
 4414            multibuffer
 4415        })?;
 4416
 4417        workspace.update_in(&mut cx, |workspace, window, cx| {
 4418            let project = workspace.project().clone();
 4419            let editor = cx
 4420                .new(|cx| Editor::for_multibuffer(excerpt_buffer, Some(project), true, window, cx));
 4421            workspace.add_item_to_active_pane(Box::new(editor.clone()), None, true, window, cx);
 4422            editor.update(cx, |editor, cx| {
 4423                editor.highlight_background::<Self>(
 4424                    &ranges_to_highlight,
 4425                    |theme| theme.editor_highlighted_line_background,
 4426                    cx,
 4427                );
 4428            });
 4429        })?;
 4430
 4431        Ok(())
 4432    }
 4433
 4434    pub fn clear_code_action_providers(&mut self) {
 4435        self.code_action_providers.clear();
 4436        self.available_code_actions.take();
 4437    }
 4438
 4439    pub fn add_code_action_provider(
 4440        &mut self,
 4441        provider: Rc<dyn CodeActionProvider>,
 4442        window: &mut Window,
 4443        cx: &mut Context<Self>,
 4444    ) {
 4445        if self
 4446            .code_action_providers
 4447            .iter()
 4448            .any(|existing_provider| existing_provider.id() == provider.id())
 4449        {
 4450            return;
 4451        }
 4452
 4453        self.code_action_providers.push(provider);
 4454        self.refresh_code_actions(window, cx);
 4455    }
 4456
 4457    pub fn remove_code_action_provider(
 4458        &mut self,
 4459        id: Arc<str>,
 4460        window: &mut Window,
 4461        cx: &mut Context<Self>,
 4462    ) {
 4463        self.code_action_providers
 4464            .retain(|provider| provider.id() != id);
 4465        self.refresh_code_actions(window, cx);
 4466    }
 4467
 4468    fn refresh_code_actions(&mut self, window: &mut Window, cx: &mut Context<Self>) -> Option<()> {
 4469        let buffer = self.buffer.read(cx);
 4470        let newest_selection = self.selections.newest_anchor().clone();
 4471        if newest_selection.head().diff_base_anchor.is_some() {
 4472            return None;
 4473        }
 4474        let (start_buffer, start) = buffer.text_anchor_for_position(newest_selection.start, cx)?;
 4475        let (end_buffer, end) = buffer.text_anchor_for_position(newest_selection.end, cx)?;
 4476        if start_buffer != end_buffer {
 4477            return None;
 4478        }
 4479
 4480        self.code_actions_task = Some(cx.spawn_in(window, |this, mut cx| async move {
 4481            cx.background_executor()
 4482                .timer(CODE_ACTIONS_DEBOUNCE_TIMEOUT)
 4483                .await;
 4484
 4485            let (providers, tasks) = this.update_in(&mut cx, |this, window, cx| {
 4486                let providers = this.code_action_providers.clone();
 4487                let tasks = this
 4488                    .code_action_providers
 4489                    .iter()
 4490                    .map(|provider| provider.code_actions(&start_buffer, start..end, window, cx))
 4491                    .collect::<Vec<_>>();
 4492                (providers, tasks)
 4493            })?;
 4494
 4495            let mut actions = Vec::new();
 4496            for (provider, provider_actions) in
 4497                providers.into_iter().zip(future::join_all(tasks).await)
 4498            {
 4499                if let Some(provider_actions) = provider_actions.log_err() {
 4500                    actions.extend(provider_actions.into_iter().map(|action| {
 4501                        AvailableCodeAction {
 4502                            excerpt_id: newest_selection.start.excerpt_id,
 4503                            action,
 4504                            provider: provider.clone(),
 4505                        }
 4506                    }));
 4507                }
 4508            }
 4509
 4510            this.update(&mut cx, |this, cx| {
 4511                this.available_code_actions = if actions.is_empty() {
 4512                    None
 4513                } else {
 4514                    Some((
 4515                        Location {
 4516                            buffer: start_buffer,
 4517                            range: start..end,
 4518                        },
 4519                        actions.into(),
 4520                    ))
 4521                };
 4522                cx.notify();
 4523            })
 4524        }));
 4525        None
 4526    }
 4527
 4528    fn start_inline_blame_timer(&mut self, window: &mut Window, cx: &mut Context<Self>) {
 4529        if let Some(delay) = ProjectSettings::get_global(cx).git.inline_blame_delay() {
 4530            self.show_git_blame_inline = false;
 4531
 4532            self.show_git_blame_inline_delay_task =
 4533                Some(cx.spawn_in(window, |this, mut cx| async move {
 4534                    cx.background_executor().timer(delay).await;
 4535
 4536                    this.update(&mut cx, |this, cx| {
 4537                        this.show_git_blame_inline = true;
 4538                        cx.notify();
 4539                    })
 4540                    .log_err();
 4541                }));
 4542        }
 4543    }
 4544
 4545    fn refresh_document_highlights(&mut self, cx: &mut Context<Self>) -> Option<()> {
 4546        if self.pending_rename.is_some() {
 4547            return None;
 4548        }
 4549
 4550        let provider = self.semantics_provider.clone()?;
 4551        let buffer = self.buffer.read(cx);
 4552        let newest_selection = self.selections.newest_anchor().clone();
 4553        let cursor_position = newest_selection.head();
 4554        let (cursor_buffer, cursor_buffer_position) =
 4555            buffer.text_anchor_for_position(cursor_position, cx)?;
 4556        let (tail_buffer, _) = buffer.text_anchor_for_position(newest_selection.tail(), cx)?;
 4557        if cursor_buffer != tail_buffer {
 4558            return None;
 4559        }
 4560        let debounce = EditorSettings::get_global(cx).lsp_highlight_debounce;
 4561        self.document_highlights_task = Some(cx.spawn(|this, mut cx| async move {
 4562            cx.background_executor()
 4563                .timer(Duration::from_millis(debounce))
 4564                .await;
 4565
 4566            let highlights = if let Some(highlights) = cx
 4567                .update(|cx| {
 4568                    provider.document_highlights(&cursor_buffer, cursor_buffer_position, cx)
 4569                })
 4570                .ok()
 4571                .flatten()
 4572            {
 4573                highlights.await.log_err()
 4574            } else {
 4575                None
 4576            };
 4577
 4578            if let Some(highlights) = highlights {
 4579                this.update(&mut cx, |this, cx| {
 4580                    if this.pending_rename.is_some() {
 4581                        return;
 4582                    }
 4583
 4584                    let buffer_id = cursor_position.buffer_id;
 4585                    let buffer = this.buffer.read(cx);
 4586                    if !buffer
 4587                        .text_anchor_for_position(cursor_position, cx)
 4588                        .map_or(false, |(buffer, _)| buffer == cursor_buffer)
 4589                    {
 4590                        return;
 4591                    }
 4592
 4593                    let cursor_buffer_snapshot = cursor_buffer.read(cx);
 4594                    let mut write_ranges = Vec::new();
 4595                    let mut read_ranges = Vec::new();
 4596                    for highlight in highlights {
 4597                        for (excerpt_id, excerpt_range) in
 4598                            buffer.excerpts_for_buffer(cursor_buffer.read(cx).remote_id(), cx)
 4599                        {
 4600                            let start = highlight
 4601                                .range
 4602                                .start
 4603                                .max(&excerpt_range.context.start, cursor_buffer_snapshot);
 4604                            let end = highlight
 4605                                .range
 4606                                .end
 4607                                .min(&excerpt_range.context.end, cursor_buffer_snapshot);
 4608                            if start.cmp(&end, cursor_buffer_snapshot).is_ge() {
 4609                                continue;
 4610                            }
 4611
 4612                            let range = Anchor {
 4613                                buffer_id,
 4614                                excerpt_id,
 4615                                text_anchor: start,
 4616                                diff_base_anchor: None,
 4617                            }..Anchor {
 4618                                buffer_id,
 4619                                excerpt_id,
 4620                                text_anchor: end,
 4621                                diff_base_anchor: None,
 4622                            };
 4623                            if highlight.kind == lsp::DocumentHighlightKind::WRITE {
 4624                                write_ranges.push(range);
 4625                            } else {
 4626                                read_ranges.push(range);
 4627                            }
 4628                        }
 4629                    }
 4630
 4631                    this.highlight_background::<DocumentHighlightRead>(
 4632                        &read_ranges,
 4633                        |theme| theme.editor_document_highlight_read_background,
 4634                        cx,
 4635                    );
 4636                    this.highlight_background::<DocumentHighlightWrite>(
 4637                        &write_ranges,
 4638                        |theme| theme.editor_document_highlight_write_background,
 4639                        cx,
 4640                    );
 4641                    cx.notify();
 4642                })
 4643                .log_err();
 4644            }
 4645        }));
 4646        None
 4647    }
 4648
 4649    pub fn refresh_inline_completion(
 4650        &mut self,
 4651        debounce: bool,
 4652        user_requested: bool,
 4653        window: &mut Window,
 4654        cx: &mut Context<Self>,
 4655    ) -> Option<()> {
 4656        let provider = self.edit_prediction_provider()?;
 4657        let cursor = self.selections.newest_anchor().head();
 4658        let (buffer, cursor_buffer_position) =
 4659            self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
 4660
 4661        if !self.inline_completions_enabled_in_buffer(&buffer, cursor_buffer_position, cx) {
 4662            self.discard_inline_completion(false, cx);
 4663            return None;
 4664        }
 4665
 4666        if !user_requested
 4667            && (!self.should_show_inline_completions_in_buffer(&buffer, cursor_buffer_position, cx)
 4668                || !self.is_focused(window)
 4669                || buffer.read(cx).is_empty())
 4670        {
 4671            self.discard_inline_completion(false, cx);
 4672            return None;
 4673        }
 4674
 4675        self.update_visible_inline_completion(window, cx);
 4676        provider.refresh(
 4677            self.project.clone(),
 4678            buffer,
 4679            cursor_buffer_position,
 4680            debounce,
 4681            cx,
 4682        );
 4683        Some(())
 4684    }
 4685
 4686    pub fn should_show_inline_completions(&self, cx: &App) -> bool {
 4687        let cursor = self.selections.newest_anchor().head();
 4688        if let Some((buffer, cursor_position)) =
 4689            self.buffer.read(cx).text_anchor_for_position(cursor, cx)
 4690        {
 4691            self.should_show_inline_completions_in_buffer(&buffer, cursor_position, cx)
 4692        } else {
 4693            false
 4694        }
 4695    }
 4696
 4697    fn edit_prediction_requires_modifier(&self, cx: &App) -> bool {
 4698        let cursor = self.selections.newest_anchor().head();
 4699
 4700        self.buffer
 4701            .read(cx)
 4702            .text_anchor_for_position(cursor, cx)
 4703            .map(|(buffer, _)| {
 4704                all_language_settings(buffer.read(cx).file(), cx).inline_completions_preview_mode()
 4705                    == InlineCompletionPreviewMode::WhenHoldingModifier
 4706            })
 4707            .unwrap_or(false)
 4708    }
 4709
 4710    fn should_show_inline_completions_in_buffer(
 4711        &self,
 4712        buffer: &Entity<Buffer>,
 4713        buffer_position: language::Anchor,
 4714        cx: &App,
 4715    ) -> bool {
 4716        if !self.snippet_stack.is_empty() {
 4717            return false;
 4718        }
 4719
 4720        if self.inline_completions_disabled_in_scope(buffer, buffer_position, cx) {
 4721            return false;
 4722        }
 4723
 4724        if let Some(show_inline_completions) = self.show_inline_completions_override {
 4725            show_inline_completions
 4726        } else {
 4727            let buffer = buffer.read(cx);
 4728            self.mode == EditorMode::Full
 4729                && language_settings(
 4730                    buffer.language_at(buffer_position).map(|l| l.name()),
 4731                    buffer.file(),
 4732                    cx,
 4733                )
 4734                .show_edit_predictions
 4735        }
 4736    }
 4737
 4738    pub fn inline_completions_enabled(&self, cx: &App) -> bool {
 4739        let cursor = self.selections.newest_anchor().head();
 4740        if let Some((buffer, cursor_position)) =
 4741            self.buffer.read(cx).text_anchor_for_position(cursor, cx)
 4742        {
 4743            self.inline_completions_enabled_in_buffer(&buffer, cursor_position, cx)
 4744        } else {
 4745            false
 4746        }
 4747    }
 4748
 4749    fn inline_completions_enabled_in_buffer(
 4750        &self,
 4751        buffer: &Entity<Buffer>,
 4752        buffer_position: language::Anchor,
 4753        cx: &App,
 4754    ) -> bool {
 4755        maybe!({
 4756            let provider = self.edit_prediction_provider()?;
 4757            if !provider.is_enabled(&buffer, buffer_position, cx) {
 4758                return Some(false);
 4759            }
 4760            let buffer = buffer.read(cx);
 4761            let Some(file) = buffer.file() else {
 4762                return Some(true);
 4763            };
 4764            let settings = all_language_settings(Some(file), cx);
 4765            Some(settings.inline_completions_enabled_for_path(file.path()))
 4766        })
 4767        .unwrap_or(false)
 4768    }
 4769
 4770    fn cycle_inline_completion(
 4771        &mut self,
 4772        direction: Direction,
 4773        window: &mut Window,
 4774        cx: &mut Context<Self>,
 4775    ) -> Option<()> {
 4776        let provider = self.edit_prediction_provider()?;
 4777        let cursor = self.selections.newest_anchor().head();
 4778        let (buffer, cursor_buffer_position) =
 4779            self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
 4780        if self.inline_completions_hidden_for_vim_mode
 4781            || !self.should_show_inline_completions_in_buffer(&buffer, cursor_buffer_position, cx)
 4782        {
 4783            return None;
 4784        }
 4785
 4786        provider.cycle(buffer, cursor_buffer_position, direction, cx);
 4787        self.update_visible_inline_completion(window, cx);
 4788
 4789        Some(())
 4790    }
 4791
 4792    pub fn show_inline_completion(
 4793        &mut self,
 4794        _: &ShowEditPrediction,
 4795        window: &mut Window,
 4796        cx: &mut Context<Self>,
 4797    ) {
 4798        if !self.has_active_inline_completion() {
 4799            self.refresh_inline_completion(false, true, window, cx);
 4800            return;
 4801        }
 4802
 4803        self.update_visible_inline_completion(window, cx);
 4804    }
 4805
 4806    pub fn display_cursor_names(
 4807        &mut self,
 4808        _: &DisplayCursorNames,
 4809        window: &mut Window,
 4810        cx: &mut Context<Self>,
 4811    ) {
 4812        self.show_cursor_names(window, cx);
 4813    }
 4814
 4815    fn show_cursor_names(&mut self, window: &mut Window, cx: &mut Context<Self>) {
 4816        self.show_cursor_names = true;
 4817        cx.notify();
 4818        cx.spawn_in(window, |this, mut cx| async move {
 4819            cx.background_executor().timer(CURSORS_VISIBLE_FOR).await;
 4820            this.update(&mut cx, |this, cx| {
 4821                this.show_cursor_names = false;
 4822                cx.notify()
 4823            })
 4824            .ok()
 4825        })
 4826        .detach();
 4827    }
 4828
 4829    pub fn next_edit_prediction(
 4830        &mut self,
 4831        _: &NextEditPrediction,
 4832        window: &mut Window,
 4833        cx: &mut Context<Self>,
 4834    ) {
 4835        if self.has_active_inline_completion() {
 4836            self.cycle_inline_completion(Direction::Next, window, cx);
 4837        } else {
 4838            let is_copilot_disabled = self
 4839                .refresh_inline_completion(false, true, window, cx)
 4840                .is_none();
 4841            if is_copilot_disabled {
 4842                cx.propagate();
 4843            }
 4844        }
 4845    }
 4846
 4847    pub fn previous_edit_prediction(
 4848        &mut self,
 4849        _: &PreviousEditPrediction,
 4850        window: &mut Window,
 4851        cx: &mut Context<Self>,
 4852    ) {
 4853        if self.has_active_inline_completion() {
 4854            self.cycle_inline_completion(Direction::Prev, window, cx);
 4855        } else {
 4856            let is_copilot_disabled = self
 4857                .refresh_inline_completion(false, true, window, cx)
 4858                .is_none();
 4859            if is_copilot_disabled {
 4860                cx.propagate();
 4861            }
 4862        }
 4863    }
 4864
 4865    pub fn accept_edit_prediction(
 4866        &mut self,
 4867        _: &AcceptEditPrediction,
 4868        window: &mut Window,
 4869        cx: &mut Context<Self>,
 4870    ) {
 4871        let buffer = self.buffer.read(cx);
 4872        let snapshot = buffer.snapshot(cx);
 4873        let selection = self.selections.newest_adjusted(cx);
 4874        let cursor = selection.head();
 4875        let current_indent = snapshot.indent_size_for_line(MultiBufferRow(cursor.row));
 4876        let suggested_indents = snapshot.suggested_indents([cursor.row], cx);
 4877        if let Some(suggested_indent) = suggested_indents.get(&MultiBufferRow(cursor.row)).copied()
 4878        {
 4879            if cursor.column < suggested_indent.len
 4880                && cursor.column <= current_indent.len
 4881                && current_indent.len <= suggested_indent.len
 4882            {
 4883                self.tab(&Default::default(), window, cx);
 4884                return;
 4885            }
 4886        }
 4887
 4888        if self.show_edit_predictions_in_menu(cx) {
 4889            self.hide_context_menu(window, cx);
 4890        }
 4891
 4892        let Some(active_inline_completion) = self.active_inline_completion.as_ref() else {
 4893            return;
 4894        };
 4895
 4896        self.report_inline_completion_event(true, cx);
 4897
 4898        match &active_inline_completion.completion {
 4899            InlineCompletion::Move { target, .. } => {
 4900                let target = *target;
 4901                // Note that this is also done in vim's handler of the Tab action.
 4902                self.change_selections(Some(Autoscroll::newest()), window, cx, |selections| {
 4903                    selections.select_anchor_ranges([target..target]);
 4904                });
 4905            }
 4906            InlineCompletion::Edit { edits, .. } => {
 4907                if let Some(provider) = self.edit_prediction_provider() {
 4908                    provider.accept(cx);
 4909                }
 4910
 4911                let snapshot = self.buffer.read(cx).snapshot(cx);
 4912                let last_edit_end = edits.last().unwrap().0.end.bias_right(&snapshot);
 4913
 4914                self.buffer.update(cx, |buffer, cx| {
 4915                    buffer.edit(edits.iter().cloned(), None, cx)
 4916                });
 4917
 4918                self.change_selections(None, window, cx, |s| {
 4919                    s.select_anchor_ranges([last_edit_end..last_edit_end])
 4920                });
 4921
 4922                self.update_visible_inline_completion(window, cx);
 4923                if self.active_inline_completion.is_none() {
 4924                    self.refresh_inline_completion(true, true, window, cx);
 4925                }
 4926
 4927                cx.notify();
 4928            }
 4929        }
 4930    }
 4931
 4932    pub fn accept_partial_inline_completion(
 4933        &mut self,
 4934        _: &AcceptPartialEditPrediction,
 4935        window: &mut Window,
 4936        cx: &mut Context<Self>,
 4937    ) {
 4938        let Some(active_inline_completion) = self.active_inline_completion.as_ref() else {
 4939            return;
 4940        };
 4941        if self.selections.count() != 1 {
 4942            return;
 4943        }
 4944
 4945        self.report_inline_completion_event(true, cx);
 4946
 4947        match &active_inline_completion.completion {
 4948            InlineCompletion::Move { target, .. } => {
 4949                let target = *target;
 4950                self.change_selections(Some(Autoscroll::newest()), window, cx, |selections| {
 4951                    selections.select_anchor_ranges([target..target]);
 4952                });
 4953            }
 4954            InlineCompletion::Edit { edits, .. } => {
 4955                // Find an insertion that starts at the cursor position.
 4956                let snapshot = self.buffer.read(cx).snapshot(cx);
 4957                let cursor_offset = self.selections.newest::<usize>(cx).head();
 4958                let insertion = edits.iter().find_map(|(range, text)| {
 4959                    let range = range.to_offset(&snapshot);
 4960                    if range.is_empty() && range.start == cursor_offset {
 4961                        Some(text)
 4962                    } else {
 4963                        None
 4964                    }
 4965                });
 4966
 4967                if let Some(text) = insertion {
 4968                    let mut partial_completion = text
 4969                        .chars()
 4970                        .by_ref()
 4971                        .take_while(|c| c.is_alphabetic())
 4972                        .collect::<String>();
 4973                    if partial_completion.is_empty() {
 4974                        partial_completion = text
 4975                            .chars()
 4976                            .by_ref()
 4977                            .take_while(|c| c.is_whitespace() || !c.is_alphabetic())
 4978                            .collect::<String>();
 4979                    }
 4980
 4981                    cx.emit(EditorEvent::InputHandled {
 4982                        utf16_range_to_replace: None,
 4983                        text: partial_completion.clone().into(),
 4984                    });
 4985
 4986                    self.insert_with_autoindent_mode(&partial_completion, None, window, cx);
 4987
 4988                    self.refresh_inline_completion(true, true, window, cx);
 4989                    cx.notify();
 4990                } else {
 4991                    self.accept_edit_prediction(&Default::default(), window, cx);
 4992                }
 4993            }
 4994        }
 4995    }
 4996
 4997    fn discard_inline_completion(
 4998        &mut self,
 4999        should_report_inline_completion_event: bool,
 5000        cx: &mut Context<Self>,
 5001    ) -> bool {
 5002        if should_report_inline_completion_event {
 5003            self.report_inline_completion_event(false, cx);
 5004        }
 5005
 5006        if let Some(provider) = self.edit_prediction_provider() {
 5007            provider.discard(cx);
 5008        }
 5009
 5010        self.take_active_inline_completion(cx)
 5011    }
 5012
 5013    fn report_inline_completion_event(&self, accepted: bool, cx: &App) {
 5014        let Some(provider) = self.edit_prediction_provider() else {
 5015            return;
 5016        };
 5017
 5018        let Some((_, buffer, _)) = self
 5019            .buffer
 5020            .read(cx)
 5021            .excerpt_containing(self.selections.newest_anchor().head(), cx)
 5022        else {
 5023            return;
 5024        };
 5025
 5026        let extension = buffer
 5027            .read(cx)
 5028            .file()
 5029            .and_then(|file| Some(file.path().extension()?.to_string_lossy().to_string()));
 5030
 5031        let event_type = match accepted {
 5032            true => "Edit Prediction Accepted",
 5033            false => "Edit Prediction Discarded",
 5034        };
 5035        telemetry::event!(
 5036            event_type,
 5037            provider = provider.name(),
 5038            suggestion_accepted = accepted,
 5039            file_extension = extension,
 5040        );
 5041    }
 5042
 5043    pub fn has_active_inline_completion(&self) -> bool {
 5044        self.active_inline_completion.is_some()
 5045    }
 5046
 5047    fn take_active_inline_completion(&mut self, cx: &mut Context<Self>) -> bool {
 5048        let Some(active_inline_completion) = self.active_inline_completion.take() else {
 5049            return false;
 5050        };
 5051
 5052        self.splice_inlays(&active_inline_completion.inlay_ids, Default::default(), cx);
 5053        self.clear_highlights::<InlineCompletionHighlight>(cx);
 5054        self.stale_inline_completion_in_menu = Some(active_inline_completion);
 5055        true
 5056    }
 5057
 5058    /// Returns true when we're displaying the inline completion popover below the cursor
 5059    /// like we are not previewing and the LSP autocomplete menu is visible
 5060    /// or we are in `when_holding_modifier` mode.
 5061    pub fn inline_completion_visible_in_cursor_popover(
 5062        &self,
 5063        has_completion: bool,
 5064        cx: &App,
 5065    ) -> bool {
 5066        if self.previewing_inline_completion
 5067            || !self.show_edit_predictions_in_menu(cx)
 5068            || !self.should_show_inline_completions(cx)
 5069        {
 5070            return false;
 5071        }
 5072
 5073        if self.has_visible_completions_menu() {
 5074            return true;
 5075        }
 5076
 5077        has_completion && self.edit_prediction_requires_modifier(cx)
 5078    }
 5079
 5080    fn update_inline_completion_preview(
 5081        &mut self,
 5082        modifiers: &Modifiers,
 5083        window: &mut Window,
 5084        cx: &mut Context<Self>,
 5085    ) {
 5086        if !self.show_edit_predictions_in_menu(cx) {
 5087            return;
 5088        }
 5089
 5090        self.previewing_inline_completion = modifiers.alt;
 5091        self.update_visible_inline_completion(window, cx);
 5092        cx.notify();
 5093    }
 5094
 5095    fn update_visible_inline_completion(
 5096        &mut self,
 5097        _window: &mut Window,
 5098        cx: &mut Context<Self>,
 5099    ) -> Option<()> {
 5100        let selection = self.selections.newest_anchor();
 5101        let cursor = selection.head();
 5102        let multibuffer = self.buffer.read(cx).snapshot(cx);
 5103        let offset_selection = selection.map(|endpoint| endpoint.to_offset(&multibuffer));
 5104        let excerpt_id = cursor.excerpt_id;
 5105
 5106        let show_in_menu = self.show_edit_predictions_in_menu(cx);
 5107        let completions_menu_has_precedence = !show_in_menu
 5108            && (self.context_menu.borrow().is_some()
 5109                || (!self.completion_tasks.is_empty() && !self.has_active_inline_completion()));
 5110        if completions_menu_has_precedence
 5111            || !offset_selection.is_empty()
 5112            || self
 5113                .active_inline_completion
 5114                .as_ref()
 5115                .map_or(false, |completion| {
 5116                    let invalidation_range = completion.invalidation_range.to_offset(&multibuffer);
 5117                    let invalidation_range = invalidation_range.start..=invalidation_range.end;
 5118                    !invalidation_range.contains(&offset_selection.head())
 5119                })
 5120        {
 5121            self.discard_inline_completion(false, cx);
 5122            return None;
 5123        }
 5124
 5125        self.take_active_inline_completion(cx);
 5126        let provider = self.edit_prediction_provider()?;
 5127
 5128        let (buffer, cursor_buffer_position) =
 5129            self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
 5130
 5131        let inline_completion = provider.suggest(&buffer, cursor_buffer_position, cx)?;
 5132        let edits = inline_completion
 5133            .edits
 5134            .into_iter()
 5135            .flat_map(|(range, new_text)| {
 5136                let start = multibuffer.anchor_in_excerpt(excerpt_id, range.start)?;
 5137                let end = multibuffer.anchor_in_excerpt(excerpt_id, range.end)?;
 5138                Some((start..end, new_text))
 5139            })
 5140            .collect::<Vec<_>>();
 5141        if edits.is_empty() {
 5142            return None;
 5143        }
 5144
 5145        let first_edit_start = edits.first().unwrap().0.start;
 5146        let first_edit_start_point = first_edit_start.to_point(&multibuffer);
 5147        let edit_start_row = first_edit_start_point.row.saturating_sub(2);
 5148
 5149        let last_edit_end = edits.last().unwrap().0.end;
 5150        let last_edit_end_point = last_edit_end.to_point(&multibuffer);
 5151        let edit_end_row = cmp::min(multibuffer.max_point().row, last_edit_end_point.row + 2);
 5152
 5153        let cursor_row = cursor.to_point(&multibuffer).row;
 5154
 5155        let snapshot = multibuffer.buffer_for_excerpt(excerpt_id).cloned()?;
 5156
 5157        let mut inlay_ids = Vec::new();
 5158        let invalidation_row_range;
 5159        let move_invalidation_row_range = if cursor_row < edit_start_row {
 5160            Some(cursor_row..edit_end_row)
 5161        } else if cursor_row > edit_end_row {
 5162            Some(edit_start_row..cursor_row)
 5163        } else {
 5164            None
 5165        };
 5166        let is_move =
 5167            move_invalidation_row_range.is_some() || self.inline_completions_hidden_for_vim_mode;
 5168        let completion = if is_move {
 5169            invalidation_row_range =
 5170                move_invalidation_row_range.unwrap_or(edit_start_row..edit_end_row);
 5171            let target = first_edit_start;
 5172            let target_point = text::ToPoint::to_point(&target.text_anchor, &snapshot);
 5173            // TODO: Base this off of TreeSitter or word boundaries?
 5174            let target_excerpt_begin = snapshot.anchor_before(snapshot.clip_point(
 5175                Point::new(target_point.row, target_point.column.saturating_sub(20)),
 5176                Bias::Left,
 5177            ));
 5178            let target_excerpt_end = snapshot.anchor_after(snapshot.clip_point(
 5179                Point::new(target_point.row, target_point.column + 20),
 5180                Bias::Right,
 5181            ));
 5182            let range_around_target = target_excerpt_begin..target_excerpt_end;
 5183            InlineCompletion::Move {
 5184                target,
 5185                range_around_target,
 5186                snapshot,
 5187            }
 5188        } else {
 5189            let show_completions_in_buffer = !self
 5190                .inline_completion_visible_in_cursor_popover(true, cx)
 5191                && !self.inline_completions_hidden_for_vim_mode;
 5192            if show_completions_in_buffer {
 5193                if edits
 5194                    .iter()
 5195                    .all(|(range, _)| range.to_offset(&multibuffer).is_empty())
 5196                {
 5197                    let mut inlays = Vec::new();
 5198                    for (range, new_text) in &edits {
 5199                        let inlay = Inlay::inline_completion(
 5200                            post_inc(&mut self.next_inlay_id),
 5201                            range.start,
 5202                            new_text.as_str(),
 5203                        );
 5204                        inlay_ids.push(inlay.id);
 5205                        inlays.push(inlay);
 5206                    }
 5207
 5208                    self.splice_inlays(&[], inlays, cx);
 5209                } else {
 5210                    let background_color = cx.theme().status().deleted_background;
 5211                    self.highlight_text::<InlineCompletionHighlight>(
 5212                        edits.iter().map(|(range, _)| range.clone()).collect(),
 5213                        HighlightStyle {
 5214                            background_color: Some(background_color),
 5215                            ..Default::default()
 5216                        },
 5217                        cx,
 5218                    );
 5219                }
 5220            }
 5221
 5222            invalidation_row_range = edit_start_row..edit_end_row;
 5223
 5224            let display_mode = if all_edits_insertions_or_deletions(&edits, &multibuffer) {
 5225                if provider.show_tab_accept_marker() {
 5226                    EditDisplayMode::TabAccept
 5227                } else {
 5228                    EditDisplayMode::Inline
 5229                }
 5230            } else {
 5231                EditDisplayMode::DiffPopover
 5232            };
 5233
 5234            InlineCompletion::Edit {
 5235                edits,
 5236                edit_preview: inline_completion.edit_preview,
 5237                display_mode,
 5238                snapshot,
 5239            }
 5240        };
 5241
 5242        let invalidation_range = multibuffer
 5243            .anchor_before(Point::new(invalidation_row_range.start, 0))
 5244            ..multibuffer.anchor_after(Point::new(
 5245                invalidation_row_range.end,
 5246                multibuffer.line_len(MultiBufferRow(invalidation_row_range.end)),
 5247            ));
 5248
 5249        self.stale_inline_completion_in_menu = None;
 5250        self.active_inline_completion = Some(InlineCompletionState {
 5251            inlay_ids,
 5252            completion,
 5253            invalidation_range,
 5254        });
 5255
 5256        cx.notify();
 5257
 5258        Some(())
 5259    }
 5260
 5261    pub fn edit_prediction_provider(&self) -> Option<Arc<dyn InlineCompletionProviderHandle>> {
 5262        Some(self.edit_prediction_provider.as_ref()?.provider.clone())
 5263    }
 5264
 5265    fn show_edit_predictions_in_menu(&self, cx: &App) -> bool {
 5266        let by_provider = matches!(
 5267            self.menu_inline_completions_policy,
 5268            MenuInlineCompletionsPolicy::ByProvider
 5269        );
 5270
 5271        by_provider
 5272            && EditorSettings::get_global(cx).show_edit_predictions_in_menu
 5273            && self
 5274                .edit_prediction_provider()
 5275                .map_or(false, |provider| provider.show_completions_in_menu())
 5276    }
 5277
 5278    fn render_code_actions_indicator(
 5279        &self,
 5280        _style: &EditorStyle,
 5281        row: DisplayRow,
 5282        is_active: bool,
 5283        cx: &mut Context<Self>,
 5284    ) -> Option<IconButton> {
 5285        if self.available_code_actions.is_some() {
 5286            Some(
 5287                IconButton::new("code_actions_indicator", ui::IconName::Bolt)
 5288                    .shape(ui::IconButtonShape::Square)
 5289                    .icon_size(IconSize::XSmall)
 5290                    .icon_color(Color::Muted)
 5291                    .toggle_state(is_active)
 5292                    .tooltip({
 5293                        let focus_handle = self.focus_handle.clone();
 5294                        move |window, cx| {
 5295                            Tooltip::for_action_in(
 5296                                "Toggle Code Actions",
 5297                                &ToggleCodeActions {
 5298                                    deployed_from_indicator: None,
 5299                                },
 5300                                &focus_handle,
 5301                                window,
 5302                                cx,
 5303                            )
 5304                        }
 5305                    })
 5306                    .on_click(cx.listener(move |editor, _e, window, cx| {
 5307                        window.focus(&editor.focus_handle(cx));
 5308                        editor.toggle_code_actions(
 5309                            &ToggleCodeActions {
 5310                                deployed_from_indicator: Some(row),
 5311                            },
 5312                            window,
 5313                            cx,
 5314                        );
 5315                    })),
 5316            )
 5317        } else {
 5318            None
 5319        }
 5320    }
 5321
 5322    fn clear_tasks(&mut self) {
 5323        self.tasks.clear()
 5324    }
 5325
 5326    fn insert_tasks(&mut self, key: (BufferId, BufferRow), value: RunnableTasks) {
 5327        if self.tasks.insert(key, value).is_some() {
 5328            // This case should hopefully be rare, but just in case...
 5329            log::error!("multiple different run targets found on a single line, only the last target will be rendered")
 5330        }
 5331    }
 5332
 5333    fn build_tasks_context(
 5334        project: &Entity<Project>,
 5335        buffer: &Entity<Buffer>,
 5336        buffer_row: u32,
 5337        tasks: &Arc<RunnableTasks>,
 5338        cx: &mut Context<Self>,
 5339    ) -> Task<Option<task::TaskContext>> {
 5340        let position = Point::new(buffer_row, tasks.column);
 5341        let range_start = buffer.read(cx).anchor_at(position, Bias::Right);
 5342        let location = Location {
 5343            buffer: buffer.clone(),
 5344            range: range_start..range_start,
 5345        };
 5346        // Fill in the environmental variables from the tree-sitter captures
 5347        let mut captured_task_variables = TaskVariables::default();
 5348        for (capture_name, value) in tasks.extra_variables.clone() {
 5349            captured_task_variables.insert(
 5350                task::VariableName::Custom(capture_name.into()),
 5351                value.clone(),
 5352            );
 5353        }
 5354        project.update(cx, |project, cx| {
 5355            project.task_store().update(cx, |task_store, cx| {
 5356                task_store.task_context_for_location(captured_task_variables, location, cx)
 5357            })
 5358        })
 5359    }
 5360
 5361    pub fn spawn_nearest_task(
 5362        &mut self,
 5363        action: &SpawnNearestTask,
 5364        window: &mut Window,
 5365        cx: &mut Context<Self>,
 5366    ) {
 5367        let Some((workspace, _)) = self.workspace.clone() else {
 5368            return;
 5369        };
 5370        let Some(project) = self.project.clone() else {
 5371            return;
 5372        };
 5373
 5374        // Try to find a closest, enclosing node using tree-sitter that has a
 5375        // task
 5376        let Some((buffer, buffer_row, tasks)) = self
 5377            .find_enclosing_node_task(cx)
 5378            // Or find the task that's closest in row-distance.
 5379            .or_else(|| self.find_closest_task(cx))
 5380        else {
 5381            return;
 5382        };
 5383
 5384        let reveal_strategy = action.reveal;
 5385        let task_context = Self::build_tasks_context(&project, &buffer, buffer_row, &tasks, cx);
 5386        cx.spawn_in(window, |_, mut cx| async move {
 5387            let context = task_context.await?;
 5388            let (task_source_kind, mut resolved_task) = tasks.resolve(&context).next()?;
 5389
 5390            let resolved = resolved_task.resolved.as_mut()?;
 5391            resolved.reveal = reveal_strategy;
 5392
 5393            workspace
 5394                .update(&mut cx, |workspace, cx| {
 5395                    workspace::tasks::schedule_resolved_task(
 5396                        workspace,
 5397                        task_source_kind,
 5398                        resolved_task,
 5399                        false,
 5400                        cx,
 5401                    );
 5402                })
 5403                .ok()
 5404        })
 5405        .detach();
 5406    }
 5407
 5408    fn find_closest_task(
 5409        &mut self,
 5410        cx: &mut Context<Self>,
 5411    ) -> Option<(Entity<Buffer>, u32, Arc<RunnableTasks>)> {
 5412        let cursor_row = self.selections.newest_adjusted(cx).head().row;
 5413
 5414        let ((buffer_id, row), tasks) = self
 5415            .tasks
 5416            .iter()
 5417            .min_by_key(|((_, row), _)| cursor_row.abs_diff(*row))?;
 5418
 5419        let buffer = self.buffer.read(cx).buffer(*buffer_id)?;
 5420        let tasks = Arc::new(tasks.to_owned());
 5421        Some((buffer, *row, tasks))
 5422    }
 5423
 5424    fn find_enclosing_node_task(
 5425        &mut self,
 5426        cx: &mut Context<Self>,
 5427    ) -> Option<(Entity<Buffer>, u32, Arc<RunnableTasks>)> {
 5428        let snapshot = self.buffer.read(cx).snapshot(cx);
 5429        let offset = self.selections.newest::<usize>(cx).head();
 5430        let excerpt = snapshot.excerpt_containing(offset..offset)?;
 5431        let buffer_id = excerpt.buffer().remote_id();
 5432
 5433        let layer = excerpt.buffer().syntax_layer_at(offset)?;
 5434        let mut cursor = layer.node().walk();
 5435
 5436        while cursor.goto_first_child_for_byte(offset).is_some() {
 5437            if cursor.node().end_byte() == offset {
 5438                cursor.goto_next_sibling();
 5439            }
 5440        }
 5441
 5442        // Ascend to the smallest ancestor that contains the range and has a task.
 5443        loop {
 5444            let node = cursor.node();
 5445            let node_range = node.byte_range();
 5446            let symbol_start_row = excerpt.buffer().offset_to_point(node.start_byte()).row;
 5447
 5448            // Check if this node contains our offset
 5449            if node_range.start <= offset && node_range.end >= offset {
 5450                // If it contains offset, check for task
 5451                if let Some(tasks) = self.tasks.get(&(buffer_id, symbol_start_row)) {
 5452                    let buffer = self.buffer.read(cx).buffer(buffer_id)?;
 5453                    return Some((buffer, symbol_start_row, Arc::new(tasks.to_owned())));
 5454                }
 5455            }
 5456
 5457            if !cursor.goto_parent() {
 5458                break;
 5459            }
 5460        }
 5461        None
 5462    }
 5463
 5464    fn render_run_indicator(
 5465        &self,
 5466        _style: &EditorStyle,
 5467        is_active: bool,
 5468        row: DisplayRow,
 5469        cx: &mut Context<Self>,
 5470    ) -> IconButton {
 5471        IconButton::new(("run_indicator", row.0 as usize), ui::IconName::Play)
 5472            .shape(ui::IconButtonShape::Square)
 5473            .icon_size(IconSize::XSmall)
 5474            .icon_color(Color::Muted)
 5475            .toggle_state(is_active)
 5476            .on_click(cx.listener(move |editor, _e, window, cx| {
 5477                window.focus(&editor.focus_handle(cx));
 5478                editor.toggle_code_actions(
 5479                    &ToggleCodeActions {
 5480                        deployed_from_indicator: Some(row),
 5481                    },
 5482                    window,
 5483                    cx,
 5484                );
 5485            }))
 5486    }
 5487
 5488    pub fn context_menu_visible(&self) -> bool {
 5489        !self.previewing_inline_completion
 5490            && self
 5491                .context_menu
 5492                .borrow()
 5493                .as_ref()
 5494                .map_or(false, |menu| menu.visible())
 5495    }
 5496
 5497    fn context_menu_origin(&self) -> Option<ContextMenuOrigin> {
 5498        self.context_menu
 5499            .borrow()
 5500            .as_ref()
 5501            .map(|menu| menu.origin())
 5502    }
 5503
 5504    fn edit_prediction_cursor_popover_height(&self) -> Pixels {
 5505        px(30.)
 5506    }
 5507
 5508    fn current_user_player_color(&self, cx: &mut App) -> PlayerColor {
 5509        if self.read_only(cx) {
 5510            cx.theme().players().read_only()
 5511        } else {
 5512            self.style.as_ref().unwrap().local_player
 5513        }
 5514    }
 5515
 5516    #[allow(clippy::too_many_arguments)]
 5517    fn render_edit_prediction_cursor_popover(
 5518        &self,
 5519        min_width: Pixels,
 5520        max_width: Pixels,
 5521        cursor_point: Point,
 5522        style: &EditorStyle,
 5523        accept_keystroke: &gpui::Keystroke,
 5524        window: &Window,
 5525        cx: &mut Context<Editor>,
 5526    ) -> Option<AnyElement> {
 5527        let provider = self.edit_prediction_provider.as_ref()?;
 5528
 5529        if provider.provider.needs_terms_acceptance(cx) {
 5530            return Some(
 5531                h_flex()
 5532                    .h(self.edit_prediction_cursor_popover_height())
 5533                    .min_w(min_width)
 5534                    .flex_1()
 5535                    .px_2()
 5536                    .gap_3()
 5537                    .elevation_2(cx)
 5538                    .hover(|style| style.bg(cx.theme().colors().element_hover))
 5539                    .id("accept-terms")
 5540                    .cursor_pointer()
 5541                    .on_mouse_down(MouseButton::Left, |_, window, _| window.prevent_default())
 5542                    .on_click(cx.listener(|this, _event, window, cx| {
 5543                        cx.stop_propagation();
 5544                        this.report_editor_event("Edit Prediction Provider ToS Clicked", None, cx);
 5545                        window.dispatch_action(
 5546                            zed_actions::OpenZedPredictOnboarding.boxed_clone(),
 5547                            cx,
 5548                        );
 5549                    }))
 5550                    .child(
 5551                        h_flex()
 5552                            .w_full()
 5553                            .gap_2()
 5554                            .child(Icon::new(IconName::ZedPredict))
 5555                            .child(Label::new("Accept Terms of Service"))
 5556                            .child(div().w_full())
 5557                            .child(
 5558                                Icon::new(IconName::ArrowUpRight)
 5559                                    .color(Color::Muted)
 5560                                    .size(IconSize::Small),
 5561                            )
 5562                            .into_any_element(),
 5563                    )
 5564                    .into_any(),
 5565            );
 5566        }
 5567
 5568        let is_refreshing = provider.provider.is_refreshing(cx);
 5569
 5570        fn pending_completion_container() -> Div {
 5571            h_flex()
 5572                .h_full()
 5573                .flex_1()
 5574                .gap_2()
 5575                .child(Icon::new(IconName::ZedPredict))
 5576        }
 5577
 5578        let completion = match &self.active_inline_completion {
 5579            Some(completion) => self.render_edit_prediction_cursor_popover_preview(
 5580                completion,
 5581                cursor_point,
 5582                style,
 5583                window,
 5584                cx,
 5585            )?,
 5586
 5587            None if is_refreshing => match &self.stale_inline_completion_in_menu {
 5588                Some(stale_completion) => self.render_edit_prediction_cursor_popover_preview(
 5589                    stale_completion,
 5590                    cursor_point,
 5591                    style,
 5592                    window,
 5593                    cx,
 5594                )?,
 5595
 5596                None => {
 5597                    pending_completion_container().child(Label::new("...").size(LabelSize::Small))
 5598                }
 5599            },
 5600
 5601            None => pending_completion_container().child(Label::new("No Prediction")),
 5602        };
 5603
 5604        let buffer_font = theme::ThemeSettings::get_global(cx).buffer_font.clone();
 5605        let completion = completion.font(buffer_font.clone());
 5606
 5607        let completion = if is_refreshing {
 5608            completion
 5609                .with_animation(
 5610                    "loading-completion",
 5611                    Animation::new(Duration::from_secs(2))
 5612                        .repeat()
 5613                        .with_easing(pulsating_between(0.4, 0.8)),
 5614                    |label, delta| label.opacity(delta),
 5615                )
 5616                .into_any_element()
 5617        } else {
 5618            completion.into_any_element()
 5619        };
 5620
 5621        let has_completion = self.active_inline_completion.is_some();
 5622
 5623        Some(
 5624            h_flex()
 5625                .h(self.edit_prediction_cursor_popover_height())
 5626                .min_w(min_width)
 5627                .max_w(max_width)
 5628                .flex_1()
 5629                .px_2()
 5630                .elevation_2(cx)
 5631                .child(completion)
 5632                .child(ui::Divider::vertical())
 5633                .child(
 5634                    h_flex()
 5635                        .h_full()
 5636                        .gap_1()
 5637                        .pl_2()
 5638                        .child(h_flex().font(buffer_font.clone()).gap_1().children(
 5639                            ui::render_modifiers(
 5640                                &accept_keystroke.modifiers,
 5641                                PlatformStyle::platform(),
 5642                                Some(if !has_completion {
 5643                                    Color::Muted
 5644                                } else {
 5645                                    Color::Default
 5646                                }),
 5647                                None,
 5648                                true,
 5649                            ),
 5650                        ))
 5651                        .child(Label::new("Preview").into_any_element())
 5652                        .opacity(if has_completion { 1.0 } else { 0.4 }),
 5653                )
 5654                .into_any(),
 5655        )
 5656    }
 5657
 5658    fn render_edit_prediction_cursor_popover_preview(
 5659        &self,
 5660        completion: &InlineCompletionState,
 5661        cursor_point: Point,
 5662        style: &EditorStyle,
 5663        window: &Window,
 5664        cx: &mut Context<Editor>,
 5665    ) -> Option<Div> {
 5666        use text::ToPoint as _;
 5667
 5668        fn render_relative_row_jump(
 5669            prefix: impl Into<String>,
 5670            current_row: u32,
 5671            target_row: u32,
 5672        ) -> Div {
 5673            let (row_diff, arrow) = if target_row < current_row {
 5674                (current_row - target_row, IconName::ArrowUp)
 5675            } else {
 5676                (target_row - current_row, IconName::ArrowDown)
 5677            };
 5678
 5679            h_flex()
 5680                .child(
 5681                    Label::new(format!("{}{}", prefix.into(), row_diff))
 5682                        .color(Color::Muted)
 5683                        .size(LabelSize::Small),
 5684                )
 5685                .child(Icon::new(arrow).color(Color::Muted).size(IconSize::Small))
 5686        }
 5687
 5688        match &completion.completion {
 5689            InlineCompletion::Edit {
 5690                edits,
 5691                edit_preview,
 5692                snapshot,
 5693                display_mode: _,
 5694            } => {
 5695                let first_edit_row = edits.first()?.0.start.text_anchor.to_point(&snapshot).row;
 5696
 5697                let highlighted_edits = crate::inline_completion_edit_text(
 5698                    &snapshot,
 5699                    &edits,
 5700                    edit_preview.as_ref()?,
 5701                    true,
 5702                    cx,
 5703                );
 5704
 5705                let len_total = highlighted_edits.text.len();
 5706                let first_line = &highlighted_edits.text
 5707                    [..highlighted_edits.text.find('\n').unwrap_or(len_total)];
 5708                let first_line_len = first_line.len();
 5709
 5710                let first_highlight_start = highlighted_edits
 5711                    .highlights
 5712                    .first()
 5713                    .map_or(0, |(range, _)| range.start);
 5714                let drop_prefix_len = first_line
 5715                    .char_indices()
 5716                    .find(|(_, c)| !c.is_whitespace())
 5717                    .map_or(first_highlight_start, |(ix, _)| {
 5718                        ix.min(first_highlight_start)
 5719                    });
 5720
 5721                let preview_text = &first_line[drop_prefix_len..];
 5722                let preview_len = preview_text.len();
 5723                let highlights = highlighted_edits
 5724                    .highlights
 5725                    .into_iter()
 5726                    .take_until(|(range, _)| range.start > first_line_len)
 5727                    .map(|(range, style)| {
 5728                        (
 5729                            range.start - drop_prefix_len
 5730                                ..(range.end - drop_prefix_len).min(preview_len),
 5731                            style,
 5732                        )
 5733                    });
 5734
 5735                let styled_text = gpui::StyledText::new(SharedString::new(preview_text))
 5736                    .with_highlights(&style.text, highlights);
 5737
 5738                let preview = h_flex()
 5739                    .gap_1()
 5740                    .min_w_16()
 5741                    .child(styled_text)
 5742                    .when(len_total > first_line_len, |parent| parent.child(""));
 5743
 5744                let left = if first_edit_row != cursor_point.row {
 5745                    render_relative_row_jump("", cursor_point.row, first_edit_row)
 5746                        .into_any_element()
 5747                } else {
 5748                    Icon::new(IconName::ZedPredict).into_any_element()
 5749                };
 5750
 5751                Some(
 5752                    h_flex()
 5753                        .h_full()
 5754                        .flex_1()
 5755                        .gap_2()
 5756                        .pr_1()
 5757                        .overflow_x_hidden()
 5758                        .child(left)
 5759                        .child(preview),
 5760                )
 5761            }
 5762
 5763            InlineCompletion::Move {
 5764                target,
 5765                range_around_target,
 5766                snapshot,
 5767            } => {
 5768                let highlighted_text = snapshot.highlighted_text_for_range(
 5769                    range_around_target.clone(),
 5770                    None,
 5771                    &style.syntax,
 5772                );
 5773                let base = h_flex().gap_3().flex_1().child(render_relative_row_jump(
 5774                    "Jump ",
 5775                    cursor_point.row,
 5776                    target.text_anchor.to_point(&snapshot).row,
 5777                ));
 5778
 5779                if highlighted_text.text.is_empty() {
 5780                    return Some(base);
 5781                }
 5782
 5783                let cursor_color = self.current_user_player_color(cx).cursor;
 5784
 5785                let start_point = range_around_target.start.to_point(&snapshot);
 5786                let end_point = range_around_target.end.to_point(&snapshot);
 5787                let target_point = target.text_anchor.to_point(&snapshot);
 5788
 5789                let styled_text = highlighted_text.to_styled_text(&style.text);
 5790                let text_len = highlighted_text.text.len();
 5791
 5792                let cursor_relative_position = window
 5793                    .text_system()
 5794                    .layout_line(
 5795                        highlighted_text.text,
 5796                        style.text.font_size.to_pixels(window.rem_size()),
 5797                        // We don't need to include highlights
 5798                        // because we are only using this for the cursor position
 5799                        &[TextRun {
 5800                            len: text_len,
 5801                            font: style.text.font(),
 5802                            color: style.text.color,
 5803                            background_color: None,
 5804                            underline: None,
 5805                            strikethrough: None,
 5806                        }],
 5807                    )
 5808                    .log_err()
 5809                    .map(|line| {
 5810                        line.x_for_index(
 5811                            target_point.column.saturating_sub(start_point.column) as usize
 5812                        )
 5813                    });
 5814
 5815                let fade_before = start_point.column > 0;
 5816                let fade_after = end_point.column < snapshot.line_len(end_point.row);
 5817
 5818                let background = cx.theme().colors().elevated_surface_background;
 5819
 5820                let preview = h_flex()
 5821                    .relative()
 5822                    .child(styled_text)
 5823                    .when(fade_before, |parent| {
 5824                        parent.child(div().absolute().top_0().left_0().w_4().h_full().bg(
 5825                            linear_gradient(
 5826                                90.,
 5827                                linear_color_stop(background, 0.),
 5828                                linear_color_stop(background.opacity(0.), 1.),
 5829                            ),
 5830                        ))
 5831                    })
 5832                    .when(fade_after, |parent| {
 5833                        parent.child(div().absolute().top_0().right_0().w_4().h_full().bg(
 5834                            linear_gradient(
 5835                                -90.,
 5836                                linear_color_stop(background, 0.),
 5837                                linear_color_stop(background.opacity(0.), 1.),
 5838                            ),
 5839                        ))
 5840                    })
 5841                    .when_some(cursor_relative_position, |parent, position| {
 5842                        parent.child(
 5843                            div()
 5844                                .w(px(2.))
 5845                                .h_full()
 5846                                .bg(cursor_color)
 5847                                .absolute()
 5848                                .top_0()
 5849                                .left(position),
 5850                        )
 5851                    });
 5852
 5853                Some(base.child(preview))
 5854            }
 5855        }
 5856    }
 5857
 5858    fn render_context_menu(
 5859        &self,
 5860        style: &EditorStyle,
 5861        max_height_in_lines: u32,
 5862        y_flipped: bool,
 5863        window: &mut Window,
 5864        cx: &mut Context<Editor>,
 5865    ) -> Option<AnyElement> {
 5866        let menu = self.context_menu.borrow();
 5867        let menu = menu.as_ref()?;
 5868        if !menu.visible() {
 5869            return None;
 5870        };
 5871        Some(menu.render(style, max_height_in_lines, y_flipped, window, cx))
 5872    }
 5873
 5874    fn render_context_menu_aside(
 5875        &self,
 5876        style: &EditorStyle,
 5877        max_size: Size<Pixels>,
 5878        cx: &mut Context<Editor>,
 5879    ) -> Option<AnyElement> {
 5880        self.context_menu.borrow().as_ref().and_then(|menu| {
 5881            if menu.visible() {
 5882                menu.render_aside(
 5883                    style,
 5884                    max_size,
 5885                    self.workspace.as_ref().map(|(w, _)| w.clone()),
 5886                    cx,
 5887                )
 5888            } else {
 5889                None
 5890            }
 5891        })
 5892    }
 5893
 5894    fn hide_context_menu(
 5895        &mut self,
 5896        window: &mut Window,
 5897        cx: &mut Context<Self>,
 5898    ) -> Option<CodeContextMenu> {
 5899        cx.notify();
 5900        self.completion_tasks.clear();
 5901        let context_menu = self.context_menu.borrow_mut().take();
 5902        self.stale_inline_completion_in_menu.take();
 5903        self.update_visible_inline_completion(window, cx);
 5904        context_menu
 5905    }
 5906
 5907    fn show_snippet_choices(
 5908        &mut self,
 5909        choices: &Vec<String>,
 5910        selection: Range<Anchor>,
 5911        cx: &mut Context<Self>,
 5912    ) {
 5913        if selection.start.buffer_id.is_none() {
 5914            return;
 5915        }
 5916        let buffer_id = selection.start.buffer_id.unwrap();
 5917        let buffer = self.buffer().read(cx).buffer(buffer_id);
 5918        let id = post_inc(&mut self.next_completion_id);
 5919
 5920        if let Some(buffer) = buffer {
 5921            *self.context_menu.borrow_mut() = Some(CodeContextMenu::Completions(
 5922                CompletionsMenu::new_snippet_choices(id, true, choices, selection, buffer),
 5923            ));
 5924        }
 5925    }
 5926
 5927    pub fn insert_snippet(
 5928        &mut self,
 5929        insertion_ranges: &[Range<usize>],
 5930        snippet: Snippet,
 5931        window: &mut Window,
 5932        cx: &mut Context<Self>,
 5933    ) -> Result<()> {
 5934        struct Tabstop<T> {
 5935            is_end_tabstop: bool,
 5936            ranges: Vec<Range<T>>,
 5937            choices: Option<Vec<String>>,
 5938        }
 5939
 5940        let tabstops = self.buffer.update(cx, |buffer, cx| {
 5941            let snippet_text: Arc<str> = snippet.text.clone().into();
 5942            buffer.edit(
 5943                insertion_ranges
 5944                    .iter()
 5945                    .cloned()
 5946                    .map(|range| (range, snippet_text.clone())),
 5947                Some(AutoindentMode::EachLine),
 5948                cx,
 5949            );
 5950
 5951            let snapshot = &*buffer.read(cx);
 5952            let snippet = &snippet;
 5953            snippet
 5954                .tabstops
 5955                .iter()
 5956                .map(|tabstop| {
 5957                    let is_end_tabstop = tabstop.ranges.first().map_or(false, |tabstop| {
 5958                        tabstop.is_empty() && tabstop.start == snippet.text.len() as isize
 5959                    });
 5960                    let mut tabstop_ranges = tabstop
 5961                        .ranges
 5962                        .iter()
 5963                        .flat_map(|tabstop_range| {
 5964                            let mut delta = 0_isize;
 5965                            insertion_ranges.iter().map(move |insertion_range| {
 5966                                let insertion_start = insertion_range.start as isize + delta;
 5967                                delta +=
 5968                                    snippet.text.len() as isize - insertion_range.len() as isize;
 5969
 5970                                let start = ((insertion_start + tabstop_range.start) as usize)
 5971                                    .min(snapshot.len());
 5972                                let end = ((insertion_start + tabstop_range.end) as usize)
 5973                                    .min(snapshot.len());
 5974                                snapshot.anchor_before(start)..snapshot.anchor_after(end)
 5975                            })
 5976                        })
 5977                        .collect::<Vec<_>>();
 5978                    tabstop_ranges.sort_unstable_by(|a, b| a.start.cmp(&b.start, snapshot));
 5979
 5980                    Tabstop {
 5981                        is_end_tabstop,
 5982                        ranges: tabstop_ranges,
 5983                        choices: tabstop.choices.clone(),
 5984                    }
 5985                })
 5986                .collect::<Vec<_>>()
 5987        });
 5988        if let Some(tabstop) = tabstops.first() {
 5989            self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 5990                s.select_ranges(tabstop.ranges.iter().cloned());
 5991            });
 5992
 5993            if let Some(choices) = &tabstop.choices {
 5994                if let Some(selection) = tabstop.ranges.first() {
 5995                    self.show_snippet_choices(choices, selection.clone(), cx)
 5996                }
 5997            }
 5998
 5999            // If we're already at the last tabstop and it's at the end of the snippet,
 6000            // we're done, we don't need to keep the state around.
 6001            if !tabstop.is_end_tabstop {
 6002                let choices = tabstops
 6003                    .iter()
 6004                    .map(|tabstop| tabstop.choices.clone())
 6005                    .collect();
 6006
 6007                let ranges = tabstops
 6008                    .into_iter()
 6009                    .map(|tabstop| tabstop.ranges)
 6010                    .collect::<Vec<_>>();
 6011
 6012                self.snippet_stack.push(SnippetState {
 6013                    active_index: 0,
 6014                    ranges,
 6015                    choices,
 6016                });
 6017            }
 6018
 6019            // Check whether the just-entered snippet ends with an auto-closable bracket.
 6020            if self.autoclose_regions.is_empty() {
 6021                let snapshot = self.buffer.read(cx).snapshot(cx);
 6022                for selection in &mut self.selections.all::<Point>(cx) {
 6023                    let selection_head = selection.head();
 6024                    let Some(scope) = snapshot.language_scope_at(selection_head) else {
 6025                        continue;
 6026                    };
 6027
 6028                    let mut bracket_pair = None;
 6029                    let next_chars = snapshot.chars_at(selection_head).collect::<String>();
 6030                    let prev_chars = snapshot
 6031                        .reversed_chars_at(selection_head)
 6032                        .collect::<String>();
 6033                    for (pair, enabled) in scope.brackets() {
 6034                        if enabled
 6035                            && pair.close
 6036                            && prev_chars.starts_with(pair.start.as_str())
 6037                            && next_chars.starts_with(pair.end.as_str())
 6038                        {
 6039                            bracket_pair = Some(pair.clone());
 6040                            break;
 6041                        }
 6042                    }
 6043                    if let Some(pair) = bracket_pair {
 6044                        let start = snapshot.anchor_after(selection_head);
 6045                        let end = snapshot.anchor_after(selection_head);
 6046                        self.autoclose_regions.push(AutocloseRegion {
 6047                            selection_id: selection.id,
 6048                            range: start..end,
 6049                            pair,
 6050                        });
 6051                    }
 6052                }
 6053            }
 6054        }
 6055        Ok(())
 6056    }
 6057
 6058    pub fn move_to_next_snippet_tabstop(
 6059        &mut self,
 6060        window: &mut Window,
 6061        cx: &mut Context<Self>,
 6062    ) -> bool {
 6063        self.move_to_snippet_tabstop(Bias::Right, window, cx)
 6064    }
 6065
 6066    pub fn move_to_prev_snippet_tabstop(
 6067        &mut self,
 6068        window: &mut Window,
 6069        cx: &mut Context<Self>,
 6070    ) -> bool {
 6071        self.move_to_snippet_tabstop(Bias::Left, window, cx)
 6072    }
 6073
 6074    pub fn move_to_snippet_tabstop(
 6075        &mut self,
 6076        bias: Bias,
 6077        window: &mut Window,
 6078        cx: &mut Context<Self>,
 6079    ) -> bool {
 6080        if let Some(mut snippet) = self.snippet_stack.pop() {
 6081            match bias {
 6082                Bias::Left => {
 6083                    if snippet.active_index > 0 {
 6084                        snippet.active_index -= 1;
 6085                    } else {
 6086                        self.snippet_stack.push(snippet);
 6087                        return false;
 6088                    }
 6089                }
 6090                Bias::Right => {
 6091                    if snippet.active_index + 1 < snippet.ranges.len() {
 6092                        snippet.active_index += 1;
 6093                    } else {
 6094                        self.snippet_stack.push(snippet);
 6095                        return false;
 6096                    }
 6097                }
 6098            }
 6099            if let Some(current_ranges) = snippet.ranges.get(snippet.active_index) {
 6100                self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 6101                    s.select_anchor_ranges(current_ranges.iter().cloned())
 6102                });
 6103
 6104                if let Some(choices) = &snippet.choices[snippet.active_index] {
 6105                    if let Some(selection) = current_ranges.first() {
 6106                        self.show_snippet_choices(&choices, selection.clone(), cx);
 6107                    }
 6108                }
 6109
 6110                // If snippet state is not at the last tabstop, push it back on the stack
 6111                if snippet.active_index + 1 < snippet.ranges.len() {
 6112                    self.snippet_stack.push(snippet);
 6113                }
 6114                return true;
 6115            }
 6116        }
 6117
 6118        false
 6119    }
 6120
 6121    pub fn clear(&mut self, window: &mut Window, cx: &mut Context<Self>) {
 6122        self.transact(window, cx, |this, window, cx| {
 6123            this.select_all(&SelectAll, window, cx);
 6124            this.insert("", window, cx);
 6125        });
 6126    }
 6127
 6128    pub fn backspace(&mut self, _: &Backspace, window: &mut Window, cx: &mut Context<Self>) {
 6129        self.transact(window, cx, |this, window, cx| {
 6130            this.select_autoclose_pair(window, cx);
 6131            let mut linked_ranges = HashMap::<_, Vec<_>>::default();
 6132            if !this.linked_edit_ranges.is_empty() {
 6133                let selections = this.selections.all::<MultiBufferPoint>(cx);
 6134                let snapshot = this.buffer.read(cx).snapshot(cx);
 6135
 6136                for selection in selections.iter() {
 6137                    let selection_start = snapshot.anchor_before(selection.start).text_anchor;
 6138                    let selection_end = snapshot.anchor_after(selection.end).text_anchor;
 6139                    if selection_start.buffer_id != selection_end.buffer_id {
 6140                        continue;
 6141                    }
 6142                    if let Some(ranges) =
 6143                        this.linked_editing_ranges_for(selection_start..selection_end, cx)
 6144                    {
 6145                        for (buffer, entries) in ranges {
 6146                            linked_ranges.entry(buffer).or_default().extend(entries);
 6147                        }
 6148                    }
 6149                }
 6150            }
 6151
 6152            let mut selections = this.selections.all::<MultiBufferPoint>(cx);
 6153            if !this.selections.line_mode {
 6154                let display_map = this.display_map.update(cx, |map, cx| map.snapshot(cx));
 6155                for selection in &mut selections {
 6156                    if selection.is_empty() {
 6157                        let old_head = selection.head();
 6158                        let mut new_head =
 6159                            movement::left(&display_map, old_head.to_display_point(&display_map))
 6160                                .to_point(&display_map);
 6161                        if let Some((buffer, line_buffer_range)) = display_map
 6162                            .buffer_snapshot
 6163                            .buffer_line_for_row(MultiBufferRow(old_head.row))
 6164                        {
 6165                            let indent_size =
 6166                                buffer.indent_size_for_line(line_buffer_range.start.row);
 6167                            let indent_len = match indent_size.kind {
 6168                                IndentKind::Space => {
 6169                                    buffer.settings_at(line_buffer_range.start, cx).tab_size
 6170                                }
 6171                                IndentKind::Tab => NonZeroU32::new(1).unwrap(),
 6172                            };
 6173                            if old_head.column <= indent_size.len && old_head.column > 0 {
 6174                                let indent_len = indent_len.get();
 6175                                new_head = cmp::min(
 6176                                    new_head,
 6177                                    MultiBufferPoint::new(
 6178                                        old_head.row,
 6179                                        ((old_head.column - 1) / indent_len) * indent_len,
 6180                                    ),
 6181                                );
 6182                            }
 6183                        }
 6184
 6185                        selection.set_head(new_head, SelectionGoal::None);
 6186                    }
 6187                }
 6188            }
 6189
 6190            this.signature_help_state.set_backspace_pressed(true);
 6191            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 6192                s.select(selections)
 6193            });
 6194            this.insert("", window, cx);
 6195            let empty_str: Arc<str> = Arc::from("");
 6196            for (buffer, edits) in linked_ranges {
 6197                let snapshot = buffer.read(cx).snapshot();
 6198                use text::ToPoint as TP;
 6199
 6200                let edits = edits
 6201                    .into_iter()
 6202                    .map(|range| {
 6203                        let end_point = TP::to_point(&range.end, &snapshot);
 6204                        let mut start_point = TP::to_point(&range.start, &snapshot);
 6205
 6206                        if end_point == start_point {
 6207                            let offset = text::ToOffset::to_offset(&range.start, &snapshot)
 6208                                .saturating_sub(1);
 6209                            start_point =
 6210                                snapshot.clip_point(TP::to_point(&offset, &snapshot), Bias::Left);
 6211                        };
 6212
 6213                        (start_point..end_point, empty_str.clone())
 6214                    })
 6215                    .sorted_by_key(|(range, _)| range.start)
 6216                    .collect::<Vec<_>>();
 6217                buffer.update(cx, |this, cx| {
 6218                    this.edit(edits, None, cx);
 6219                })
 6220            }
 6221            this.refresh_inline_completion(true, false, window, cx);
 6222            linked_editing_ranges::refresh_linked_ranges(this, window, cx);
 6223        });
 6224    }
 6225
 6226    pub fn delete(&mut self, _: &Delete, window: &mut Window, cx: &mut Context<Self>) {
 6227        self.transact(window, cx, |this, window, cx| {
 6228            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 6229                let line_mode = s.line_mode;
 6230                s.move_with(|map, selection| {
 6231                    if selection.is_empty() && !line_mode {
 6232                        let cursor = movement::right(map, selection.head());
 6233                        selection.end = cursor;
 6234                        selection.reversed = true;
 6235                        selection.goal = SelectionGoal::None;
 6236                    }
 6237                })
 6238            });
 6239            this.insert("", window, cx);
 6240            this.refresh_inline_completion(true, false, window, cx);
 6241        });
 6242    }
 6243
 6244    pub fn tab_prev(&mut self, _: &TabPrev, window: &mut Window, cx: &mut Context<Self>) {
 6245        if self.move_to_prev_snippet_tabstop(window, cx) {
 6246            return;
 6247        }
 6248
 6249        self.outdent(&Outdent, window, cx);
 6250    }
 6251
 6252    pub fn tab(&mut self, _: &Tab, window: &mut Window, cx: &mut Context<Self>) {
 6253        if self.move_to_next_snippet_tabstop(window, cx) || self.read_only(cx) {
 6254            return;
 6255        }
 6256
 6257        let mut selections = self.selections.all_adjusted(cx);
 6258        let buffer = self.buffer.read(cx);
 6259        let snapshot = buffer.snapshot(cx);
 6260        let rows_iter = selections.iter().map(|s| s.head().row);
 6261        let suggested_indents = snapshot.suggested_indents(rows_iter, cx);
 6262
 6263        let mut edits = Vec::new();
 6264        let mut prev_edited_row = 0;
 6265        let mut row_delta = 0;
 6266        for selection in &mut selections {
 6267            if selection.start.row != prev_edited_row {
 6268                row_delta = 0;
 6269            }
 6270            prev_edited_row = selection.end.row;
 6271
 6272            // If the selection is non-empty, then increase the indentation of the selected lines.
 6273            if !selection.is_empty() {
 6274                row_delta =
 6275                    Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
 6276                continue;
 6277            }
 6278
 6279            // If the selection is empty and the cursor is in the leading whitespace before the
 6280            // suggested indentation, then auto-indent the line.
 6281            let cursor = selection.head();
 6282            let current_indent = snapshot.indent_size_for_line(MultiBufferRow(cursor.row));
 6283            if let Some(suggested_indent) =
 6284                suggested_indents.get(&MultiBufferRow(cursor.row)).copied()
 6285            {
 6286                if cursor.column < suggested_indent.len
 6287                    && cursor.column <= current_indent.len
 6288                    && current_indent.len <= suggested_indent.len
 6289                {
 6290                    selection.start = Point::new(cursor.row, suggested_indent.len);
 6291                    selection.end = selection.start;
 6292                    if row_delta == 0 {
 6293                        edits.extend(Buffer::edit_for_indent_size_adjustment(
 6294                            cursor.row,
 6295                            current_indent,
 6296                            suggested_indent,
 6297                        ));
 6298                        row_delta = suggested_indent.len - current_indent.len;
 6299                    }
 6300                    continue;
 6301                }
 6302            }
 6303
 6304            // Otherwise, insert a hard or soft tab.
 6305            let settings = buffer.settings_at(cursor, cx);
 6306            let tab_size = if settings.hard_tabs {
 6307                IndentSize::tab()
 6308            } else {
 6309                let tab_size = settings.tab_size.get();
 6310                let char_column = snapshot
 6311                    .text_for_range(Point::new(cursor.row, 0)..cursor)
 6312                    .flat_map(str::chars)
 6313                    .count()
 6314                    + row_delta as usize;
 6315                let chars_to_next_tab_stop = tab_size - (char_column as u32 % tab_size);
 6316                IndentSize::spaces(chars_to_next_tab_stop)
 6317            };
 6318            selection.start = Point::new(cursor.row, cursor.column + row_delta + tab_size.len);
 6319            selection.end = selection.start;
 6320            edits.push((cursor..cursor, tab_size.chars().collect::<String>()));
 6321            row_delta += tab_size.len;
 6322        }
 6323
 6324        self.transact(window, cx, |this, window, cx| {
 6325            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
 6326            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 6327                s.select(selections)
 6328            });
 6329            this.refresh_inline_completion(true, false, window, cx);
 6330        });
 6331    }
 6332
 6333    pub fn indent(&mut self, _: &Indent, window: &mut Window, cx: &mut Context<Self>) {
 6334        if self.read_only(cx) {
 6335            return;
 6336        }
 6337        let mut selections = self.selections.all::<Point>(cx);
 6338        let mut prev_edited_row = 0;
 6339        let mut row_delta = 0;
 6340        let mut edits = Vec::new();
 6341        let buffer = self.buffer.read(cx);
 6342        let snapshot = buffer.snapshot(cx);
 6343        for selection in &mut selections {
 6344            if selection.start.row != prev_edited_row {
 6345                row_delta = 0;
 6346            }
 6347            prev_edited_row = selection.end.row;
 6348
 6349            row_delta =
 6350                Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
 6351        }
 6352
 6353        self.transact(window, cx, |this, window, cx| {
 6354            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
 6355            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 6356                s.select(selections)
 6357            });
 6358        });
 6359    }
 6360
 6361    fn indent_selection(
 6362        buffer: &MultiBuffer,
 6363        snapshot: &MultiBufferSnapshot,
 6364        selection: &mut Selection<Point>,
 6365        edits: &mut Vec<(Range<Point>, String)>,
 6366        delta_for_start_row: u32,
 6367        cx: &App,
 6368    ) -> u32 {
 6369        let settings = buffer.settings_at(selection.start, cx);
 6370        let tab_size = settings.tab_size.get();
 6371        let indent_kind = if settings.hard_tabs {
 6372            IndentKind::Tab
 6373        } else {
 6374            IndentKind::Space
 6375        };
 6376        let mut start_row = selection.start.row;
 6377        let mut end_row = selection.end.row + 1;
 6378
 6379        // If a selection ends at the beginning of a line, don't indent
 6380        // that last line.
 6381        if selection.end.column == 0 && selection.end.row > selection.start.row {
 6382            end_row -= 1;
 6383        }
 6384
 6385        // Avoid re-indenting a row that has already been indented by a
 6386        // previous selection, but still update this selection's column
 6387        // to reflect that indentation.
 6388        if delta_for_start_row > 0 {
 6389            start_row += 1;
 6390            selection.start.column += delta_for_start_row;
 6391            if selection.end.row == selection.start.row {
 6392                selection.end.column += delta_for_start_row;
 6393            }
 6394        }
 6395
 6396        let mut delta_for_end_row = 0;
 6397        let has_multiple_rows = start_row + 1 != end_row;
 6398        for row in start_row..end_row {
 6399            let current_indent = snapshot.indent_size_for_line(MultiBufferRow(row));
 6400            let indent_delta = match (current_indent.kind, indent_kind) {
 6401                (IndentKind::Space, IndentKind::Space) => {
 6402                    let columns_to_next_tab_stop = tab_size - (current_indent.len % tab_size);
 6403                    IndentSize::spaces(columns_to_next_tab_stop)
 6404                }
 6405                (IndentKind::Tab, IndentKind::Space) => IndentSize::spaces(tab_size),
 6406                (_, IndentKind::Tab) => IndentSize::tab(),
 6407            };
 6408
 6409            let start = if has_multiple_rows || current_indent.len < selection.start.column {
 6410                0
 6411            } else {
 6412                selection.start.column
 6413            };
 6414            let row_start = Point::new(row, start);
 6415            edits.push((
 6416                row_start..row_start,
 6417                indent_delta.chars().collect::<String>(),
 6418            ));
 6419
 6420            // Update this selection's endpoints to reflect the indentation.
 6421            if row == selection.start.row {
 6422                selection.start.column += indent_delta.len;
 6423            }
 6424            if row == selection.end.row {
 6425                selection.end.column += indent_delta.len;
 6426                delta_for_end_row = indent_delta.len;
 6427            }
 6428        }
 6429
 6430        if selection.start.row == selection.end.row {
 6431            delta_for_start_row + delta_for_end_row
 6432        } else {
 6433            delta_for_end_row
 6434        }
 6435    }
 6436
 6437    pub fn outdent(&mut self, _: &Outdent, window: &mut Window, cx: &mut Context<Self>) {
 6438        if self.read_only(cx) {
 6439            return;
 6440        }
 6441        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 6442        let selections = self.selections.all::<Point>(cx);
 6443        let mut deletion_ranges = Vec::new();
 6444        let mut last_outdent = None;
 6445        {
 6446            let buffer = self.buffer.read(cx);
 6447            let snapshot = buffer.snapshot(cx);
 6448            for selection in &selections {
 6449                let settings = buffer.settings_at(selection.start, cx);
 6450                let tab_size = settings.tab_size.get();
 6451                let mut rows = selection.spanned_rows(false, &display_map);
 6452
 6453                // Avoid re-outdenting a row that has already been outdented by a
 6454                // previous selection.
 6455                if let Some(last_row) = last_outdent {
 6456                    if last_row == rows.start {
 6457                        rows.start = rows.start.next_row();
 6458                    }
 6459                }
 6460                let has_multiple_rows = rows.len() > 1;
 6461                for row in rows.iter_rows() {
 6462                    let indent_size = snapshot.indent_size_for_line(row);
 6463                    if indent_size.len > 0 {
 6464                        let deletion_len = match indent_size.kind {
 6465                            IndentKind::Space => {
 6466                                let columns_to_prev_tab_stop = indent_size.len % tab_size;
 6467                                if columns_to_prev_tab_stop == 0 {
 6468                                    tab_size
 6469                                } else {
 6470                                    columns_to_prev_tab_stop
 6471                                }
 6472                            }
 6473                            IndentKind::Tab => 1,
 6474                        };
 6475                        let start = if has_multiple_rows
 6476                            || deletion_len > selection.start.column
 6477                            || indent_size.len < selection.start.column
 6478                        {
 6479                            0
 6480                        } else {
 6481                            selection.start.column - deletion_len
 6482                        };
 6483                        deletion_ranges.push(
 6484                            Point::new(row.0, start)..Point::new(row.0, start + deletion_len),
 6485                        );
 6486                        last_outdent = Some(row);
 6487                    }
 6488                }
 6489            }
 6490        }
 6491
 6492        self.transact(window, cx, |this, window, cx| {
 6493            this.buffer.update(cx, |buffer, cx| {
 6494                let empty_str: Arc<str> = Arc::default();
 6495                buffer.edit(
 6496                    deletion_ranges
 6497                        .into_iter()
 6498                        .map(|range| (range, empty_str.clone())),
 6499                    None,
 6500                    cx,
 6501                );
 6502            });
 6503            let selections = this.selections.all::<usize>(cx);
 6504            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 6505                s.select(selections)
 6506            });
 6507        });
 6508    }
 6509
 6510    pub fn autoindent(&mut self, _: &AutoIndent, window: &mut Window, cx: &mut Context<Self>) {
 6511        if self.read_only(cx) {
 6512            return;
 6513        }
 6514        let selections = self
 6515            .selections
 6516            .all::<usize>(cx)
 6517            .into_iter()
 6518            .map(|s| s.range());
 6519
 6520        self.transact(window, cx, |this, window, cx| {
 6521            this.buffer.update(cx, |buffer, cx| {
 6522                buffer.autoindent_ranges(selections, cx);
 6523            });
 6524            let selections = this.selections.all::<usize>(cx);
 6525            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 6526                s.select(selections)
 6527            });
 6528        });
 6529    }
 6530
 6531    pub fn delete_line(&mut self, _: &DeleteLine, window: &mut Window, cx: &mut Context<Self>) {
 6532        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 6533        let selections = self.selections.all::<Point>(cx);
 6534
 6535        let mut new_cursors = Vec::new();
 6536        let mut edit_ranges = Vec::new();
 6537        let mut selections = selections.iter().peekable();
 6538        while let Some(selection) = selections.next() {
 6539            let mut rows = selection.spanned_rows(false, &display_map);
 6540            let goal_display_column = selection.head().to_display_point(&display_map).column();
 6541
 6542            // Accumulate contiguous regions of rows that we want to delete.
 6543            while let Some(next_selection) = selections.peek() {
 6544                let next_rows = next_selection.spanned_rows(false, &display_map);
 6545                if next_rows.start <= rows.end {
 6546                    rows.end = next_rows.end;
 6547                    selections.next().unwrap();
 6548                } else {
 6549                    break;
 6550                }
 6551            }
 6552
 6553            let buffer = &display_map.buffer_snapshot;
 6554            let mut edit_start = Point::new(rows.start.0, 0).to_offset(buffer);
 6555            let edit_end;
 6556            let cursor_buffer_row;
 6557            if buffer.max_point().row >= rows.end.0 {
 6558                // If there's a line after the range, delete the \n from the end of the row range
 6559                // and position the cursor on the next line.
 6560                edit_end = Point::new(rows.end.0, 0).to_offset(buffer);
 6561                cursor_buffer_row = rows.end;
 6562            } else {
 6563                // If there isn't a line after the range, delete the \n from the line before the
 6564                // start of the row range and position the cursor there.
 6565                edit_start = edit_start.saturating_sub(1);
 6566                edit_end = buffer.len();
 6567                cursor_buffer_row = rows.start.previous_row();
 6568            }
 6569
 6570            let mut cursor = Point::new(cursor_buffer_row.0, 0).to_display_point(&display_map);
 6571            *cursor.column_mut() =
 6572                cmp::min(goal_display_column, display_map.line_len(cursor.row()));
 6573
 6574            new_cursors.push((
 6575                selection.id,
 6576                buffer.anchor_after(cursor.to_point(&display_map)),
 6577            ));
 6578            edit_ranges.push(edit_start..edit_end);
 6579        }
 6580
 6581        self.transact(window, cx, |this, window, cx| {
 6582            let buffer = this.buffer.update(cx, |buffer, cx| {
 6583                let empty_str: Arc<str> = Arc::default();
 6584                buffer.edit(
 6585                    edit_ranges
 6586                        .into_iter()
 6587                        .map(|range| (range, empty_str.clone())),
 6588                    None,
 6589                    cx,
 6590                );
 6591                buffer.snapshot(cx)
 6592            });
 6593            let new_selections = new_cursors
 6594                .into_iter()
 6595                .map(|(id, cursor)| {
 6596                    let cursor = cursor.to_point(&buffer);
 6597                    Selection {
 6598                        id,
 6599                        start: cursor,
 6600                        end: cursor,
 6601                        reversed: false,
 6602                        goal: SelectionGoal::None,
 6603                    }
 6604                })
 6605                .collect();
 6606
 6607            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 6608                s.select(new_selections);
 6609            });
 6610        });
 6611    }
 6612
 6613    pub fn join_lines_impl(
 6614        &mut self,
 6615        insert_whitespace: bool,
 6616        window: &mut Window,
 6617        cx: &mut Context<Self>,
 6618    ) {
 6619        if self.read_only(cx) {
 6620            return;
 6621        }
 6622        let mut row_ranges = Vec::<Range<MultiBufferRow>>::new();
 6623        for selection in self.selections.all::<Point>(cx) {
 6624            let start = MultiBufferRow(selection.start.row);
 6625            // Treat single line selections as if they include the next line. Otherwise this action
 6626            // would do nothing for single line selections individual cursors.
 6627            let end = if selection.start.row == selection.end.row {
 6628                MultiBufferRow(selection.start.row + 1)
 6629            } else {
 6630                MultiBufferRow(selection.end.row)
 6631            };
 6632
 6633            if let Some(last_row_range) = row_ranges.last_mut() {
 6634                if start <= last_row_range.end {
 6635                    last_row_range.end = end;
 6636                    continue;
 6637                }
 6638            }
 6639            row_ranges.push(start..end);
 6640        }
 6641
 6642        let snapshot = self.buffer.read(cx).snapshot(cx);
 6643        let mut cursor_positions = Vec::new();
 6644        for row_range in &row_ranges {
 6645            let anchor = snapshot.anchor_before(Point::new(
 6646                row_range.end.previous_row().0,
 6647                snapshot.line_len(row_range.end.previous_row()),
 6648            ));
 6649            cursor_positions.push(anchor..anchor);
 6650        }
 6651
 6652        self.transact(window, cx, |this, window, cx| {
 6653            for row_range in row_ranges.into_iter().rev() {
 6654                for row in row_range.iter_rows().rev() {
 6655                    let end_of_line = Point::new(row.0, snapshot.line_len(row));
 6656                    let next_line_row = row.next_row();
 6657                    let indent = snapshot.indent_size_for_line(next_line_row);
 6658                    let start_of_next_line = Point::new(next_line_row.0, indent.len);
 6659
 6660                    let replace =
 6661                        if snapshot.line_len(next_line_row) > indent.len && insert_whitespace {
 6662                            " "
 6663                        } else {
 6664                            ""
 6665                        };
 6666
 6667                    this.buffer.update(cx, |buffer, cx| {
 6668                        buffer.edit([(end_of_line..start_of_next_line, replace)], None, cx)
 6669                    });
 6670                }
 6671            }
 6672
 6673            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 6674                s.select_anchor_ranges(cursor_positions)
 6675            });
 6676        });
 6677    }
 6678
 6679    pub fn join_lines(&mut self, _: &JoinLines, window: &mut Window, cx: &mut Context<Self>) {
 6680        self.join_lines_impl(true, window, cx);
 6681    }
 6682
 6683    pub fn sort_lines_case_sensitive(
 6684        &mut self,
 6685        _: &SortLinesCaseSensitive,
 6686        window: &mut Window,
 6687        cx: &mut Context<Self>,
 6688    ) {
 6689        self.manipulate_lines(window, cx, |lines| lines.sort())
 6690    }
 6691
 6692    pub fn sort_lines_case_insensitive(
 6693        &mut self,
 6694        _: &SortLinesCaseInsensitive,
 6695        window: &mut Window,
 6696        cx: &mut Context<Self>,
 6697    ) {
 6698        self.manipulate_lines(window, cx, |lines| {
 6699            lines.sort_by_key(|line| line.to_lowercase())
 6700        })
 6701    }
 6702
 6703    pub fn unique_lines_case_insensitive(
 6704        &mut self,
 6705        _: &UniqueLinesCaseInsensitive,
 6706        window: &mut Window,
 6707        cx: &mut Context<Self>,
 6708    ) {
 6709        self.manipulate_lines(window, cx, |lines| {
 6710            let mut seen = HashSet::default();
 6711            lines.retain(|line| seen.insert(line.to_lowercase()));
 6712        })
 6713    }
 6714
 6715    pub fn unique_lines_case_sensitive(
 6716        &mut self,
 6717        _: &UniqueLinesCaseSensitive,
 6718        window: &mut Window,
 6719        cx: &mut Context<Self>,
 6720    ) {
 6721        self.manipulate_lines(window, cx, |lines| {
 6722            let mut seen = HashSet::default();
 6723            lines.retain(|line| seen.insert(*line));
 6724        })
 6725    }
 6726
 6727    pub fn revert_file(&mut self, _: &RevertFile, window: &mut Window, cx: &mut Context<Self>) {
 6728        let mut revert_changes = HashMap::default();
 6729        let snapshot = self.snapshot(window, cx);
 6730        for hunk in snapshot
 6731            .hunks_for_ranges(Some(Point::zero()..snapshot.buffer_snapshot.max_point()).into_iter())
 6732        {
 6733            self.prepare_revert_change(&mut revert_changes, &hunk, cx);
 6734        }
 6735        if !revert_changes.is_empty() {
 6736            self.transact(window, cx, |editor, window, cx| {
 6737                editor.revert(revert_changes, window, cx);
 6738            });
 6739        }
 6740    }
 6741
 6742    pub fn reload_file(&mut self, _: &ReloadFile, window: &mut Window, cx: &mut Context<Self>) {
 6743        let Some(project) = self.project.clone() else {
 6744            return;
 6745        };
 6746        self.reload(project, window, cx)
 6747            .detach_and_notify_err(window, cx);
 6748    }
 6749
 6750    pub fn revert_selected_hunks(
 6751        &mut self,
 6752        _: &RevertSelectedHunks,
 6753        window: &mut Window,
 6754        cx: &mut Context<Self>,
 6755    ) {
 6756        let selections = self.selections.all(cx).into_iter().map(|s| s.range());
 6757        self.revert_hunks_in_ranges(selections, window, cx);
 6758    }
 6759
 6760    fn revert_hunks_in_ranges(
 6761        &mut self,
 6762        ranges: impl Iterator<Item = Range<Point>>,
 6763        window: &mut Window,
 6764        cx: &mut Context<Editor>,
 6765    ) {
 6766        let mut revert_changes = HashMap::default();
 6767        let snapshot = self.snapshot(window, cx);
 6768        for hunk in &snapshot.hunks_for_ranges(ranges) {
 6769            self.prepare_revert_change(&mut revert_changes, &hunk, cx);
 6770        }
 6771        if !revert_changes.is_empty() {
 6772            self.transact(window, cx, |editor, window, cx| {
 6773                editor.revert(revert_changes, window, cx);
 6774            });
 6775        }
 6776    }
 6777
 6778    pub fn open_active_item_in_terminal(
 6779        &mut self,
 6780        _: &OpenInTerminal,
 6781        window: &mut Window,
 6782        cx: &mut Context<Self>,
 6783    ) {
 6784        if let Some(working_directory) = self.active_excerpt(cx).and_then(|(_, buffer, _)| {
 6785            let project_path = buffer.read(cx).project_path(cx)?;
 6786            let project = self.project.as_ref()?.read(cx);
 6787            let entry = project.entry_for_path(&project_path, cx)?;
 6788            let parent = match &entry.canonical_path {
 6789                Some(canonical_path) => canonical_path.to_path_buf(),
 6790                None => project.absolute_path(&project_path, cx)?,
 6791            }
 6792            .parent()?
 6793            .to_path_buf();
 6794            Some(parent)
 6795        }) {
 6796            window.dispatch_action(OpenTerminal { working_directory }.boxed_clone(), cx);
 6797        }
 6798    }
 6799
 6800    pub fn prepare_revert_change(
 6801        &self,
 6802        revert_changes: &mut HashMap<BufferId, Vec<(Range<text::Anchor>, Rope)>>,
 6803        hunk: &MultiBufferDiffHunk,
 6804        cx: &mut App,
 6805    ) -> Option<()> {
 6806        let buffer = self.buffer.read(cx);
 6807        let diff = buffer.diff_for(hunk.buffer_id)?;
 6808        let buffer = buffer.buffer(hunk.buffer_id)?;
 6809        let buffer = buffer.read(cx);
 6810        let original_text = diff
 6811            .read(cx)
 6812            .snapshot
 6813            .base_text
 6814            .as_ref()?
 6815            .as_rope()
 6816            .slice(hunk.diff_base_byte_range.clone());
 6817        let buffer_snapshot = buffer.snapshot();
 6818        let buffer_revert_changes = revert_changes.entry(buffer.remote_id()).or_default();
 6819        if let Err(i) = buffer_revert_changes.binary_search_by(|probe| {
 6820            probe
 6821                .0
 6822                .start
 6823                .cmp(&hunk.buffer_range.start, &buffer_snapshot)
 6824                .then(probe.0.end.cmp(&hunk.buffer_range.end, &buffer_snapshot))
 6825        }) {
 6826            buffer_revert_changes.insert(i, (hunk.buffer_range.clone(), original_text));
 6827            Some(())
 6828        } else {
 6829            None
 6830        }
 6831    }
 6832
 6833    pub fn reverse_lines(&mut self, _: &ReverseLines, window: &mut Window, cx: &mut Context<Self>) {
 6834        self.manipulate_lines(window, cx, |lines| lines.reverse())
 6835    }
 6836
 6837    pub fn shuffle_lines(&mut self, _: &ShuffleLines, window: &mut Window, cx: &mut Context<Self>) {
 6838        self.manipulate_lines(window, cx, |lines| lines.shuffle(&mut thread_rng()))
 6839    }
 6840
 6841    fn manipulate_lines<Fn>(
 6842        &mut self,
 6843        window: &mut Window,
 6844        cx: &mut Context<Self>,
 6845        mut callback: Fn,
 6846    ) where
 6847        Fn: FnMut(&mut Vec<&str>),
 6848    {
 6849        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 6850        let buffer = self.buffer.read(cx).snapshot(cx);
 6851
 6852        let mut edits = Vec::new();
 6853
 6854        let selections = self.selections.all::<Point>(cx);
 6855        let mut selections = selections.iter().peekable();
 6856        let mut contiguous_row_selections = Vec::new();
 6857        let mut new_selections = Vec::new();
 6858        let mut added_lines = 0;
 6859        let mut removed_lines = 0;
 6860
 6861        while let Some(selection) = selections.next() {
 6862            let (start_row, end_row) = consume_contiguous_rows(
 6863                &mut contiguous_row_selections,
 6864                selection,
 6865                &display_map,
 6866                &mut selections,
 6867            );
 6868
 6869            let start_point = Point::new(start_row.0, 0);
 6870            let end_point = Point::new(
 6871                end_row.previous_row().0,
 6872                buffer.line_len(end_row.previous_row()),
 6873            );
 6874            let text = buffer
 6875                .text_for_range(start_point..end_point)
 6876                .collect::<String>();
 6877
 6878            let mut lines = text.split('\n').collect_vec();
 6879
 6880            let lines_before = lines.len();
 6881            callback(&mut lines);
 6882            let lines_after = lines.len();
 6883
 6884            edits.push((start_point..end_point, lines.join("\n")));
 6885
 6886            // Selections must change based on added and removed line count
 6887            let start_row =
 6888                MultiBufferRow(start_point.row + added_lines as u32 - removed_lines as u32);
 6889            let end_row = MultiBufferRow(start_row.0 + lines_after.saturating_sub(1) as u32);
 6890            new_selections.push(Selection {
 6891                id: selection.id,
 6892                start: start_row,
 6893                end: end_row,
 6894                goal: SelectionGoal::None,
 6895                reversed: selection.reversed,
 6896            });
 6897
 6898            if lines_after > lines_before {
 6899                added_lines += lines_after - lines_before;
 6900            } else if lines_before > lines_after {
 6901                removed_lines += lines_before - lines_after;
 6902            }
 6903        }
 6904
 6905        self.transact(window, cx, |this, window, cx| {
 6906            let buffer = this.buffer.update(cx, |buffer, cx| {
 6907                buffer.edit(edits, None, cx);
 6908                buffer.snapshot(cx)
 6909            });
 6910
 6911            // Recalculate offsets on newly edited buffer
 6912            let new_selections = new_selections
 6913                .iter()
 6914                .map(|s| {
 6915                    let start_point = Point::new(s.start.0, 0);
 6916                    let end_point = Point::new(s.end.0, buffer.line_len(s.end));
 6917                    Selection {
 6918                        id: s.id,
 6919                        start: buffer.point_to_offset(start_point),
 6920                        end: buffer.point_to_offset(end_point),
 6921                        goal: s.goal,
 6922                        reversed: s.reversed,
 6923                    }
 6924                })
 6925                .collect();
 6926
 6927            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 6928                s.select(new_selections);
 6929            });
 6930
 6931            this.request_autoscroll(Autoscroll::fit(), cx);
 6932        });
 6933    }
 6934
 6935    pub fn convert_to_upper_case(
 6936        &mut self,
 6937        _: &ConvertToUpperCase,
 6938        window: &mut Window,
 6939        cx: &mut Context<Self>,
 6940    ) {
 6941        self.manipulate_text(window, cx, |text| text.to_uppercase())
 6942    }
 6943
 6944    pub fn convert_to_lower_case(
 6945        &mut self,
 6946        _: &ConvertToLowerCase,
 6947        window: &mut Window,
 6948        cx: &mut Context<Self>,
 6949    ) {
 6950        self.manipulate_text(window, cx, |text| text.to_lowercase())
 6951    }
 6952
 6953    pub fn convert_to_title_case(
 6954        &mut self,
 6955        _: &ConvertToTitleCase,
 6956        window: &mut Window,
 6957        cx: &mut Context<Self>,
 6958    ) {
 6959        self.manipulate_text(window, cx, |text| {
 6960            text.split('\n')
 6961                .map(|line| line.to_case(Case::Title))
 6962                .join("\n")
 6963        })
 6964    }
 6965
 6966    pub fn convert_to_snake_case(
 6967        &mut self,
 6968        _: &ConvertToSnakeCase,
 6969        window: &mut Window,
 6970        cx: &mut Context<Self>,
 6971    ) {
 6972        self.manipulate_text(window, cx, |text| text.to_case(Case::Snake))
 6973    }
 6974
 6975    pub fn convert_to_kebab_case(
 6976        &mut self,
 6977        _: &ConvertToKebabCase,
 6978        window: &mut Window,
 6979        cx: &mut Context<Self>,
 6980    ) {
 6981        self.manipulate_text(window, cx, |text| text.to_case(Case::Kebab))
 6982    }
 6983
 6984    pub fn convert_to_upper_camel_case(
 6985        &mut self,
 6986        _: &ConvertToUpperCamelCase,
 6987        window: &mut Window,
 6988        cx: &mut Context<Self>,
 6989    ) {
 6990        self.manipulate_text(window, cx, |text| {
 6991            text.split('\n')
 6992                .map(|line| line.to_case(Case::UpperCamel))
 6993                .join("\n")
 6994        })
 6995    }
 6996
 6997    pub fn convert_to_lower_camel_case(
 6998        &mut self,
 6999        _: &ConvertToLowerCamelCase,
 7000        window: &mut Window,
 7001        cx: &mut Context<Self>,
 7002    ) {
 7003        self.manipulate_text(window, cx, |text| text.to_case(Case::Camel))
 7004    }
 7005
 7006    pub fn convert_to_opposite_case(
 7007        &mut self,
 7008        _: &ConvertToOppositeCase,
 7009        window: &mut Window,
 7010        cx: &mut Context<Self>,
 7011    ) {
 7012        self.manipulate_text(window, cx, |text| {
 7013            text.chars()
 7014                .fold(String::with_capacity(text.len()), |mut t, c| {
 7015                    if c.is_uppercase() {
 7016                        t.extend(c.to_lowercase());
 7017                    } else {
 7018                        t.extend(c.to_uppercase());
 7019                    }
 7020                    t
 7021                })
 7022        })
 7023    }
 7024
 7025    fn manipulate_text<Fn>(&mut self, window: &mut Window, cx: &mut Context<Self>, mut callback: Fn)
 7026    where
 7027        Fn: FnMut(&str) -> String,
 7028    {
 7029        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 7030        let buffer = self.buffer.read(cx).snapshot(cx);
 7031
 7032        let mut new_selections = Vec::new();
 7033        let mut edits = Vec::new();
 7034        let mut selection_adjustment = 0i32;
 7035
 7036        for selection in self.selections.all::<usize>(cx) {
 7037            let selection_is_empty = selection.is_empty();
 7038
 7039            let (start, end) = if selection_is_empty {
 7040                let word_range = movement::surrounding_word(
 7041                    &display_map,
 7042                    selection.start.to_display_point(&display_map),
 7043                );
 7044                let start = word_range.start.to_offset(&display_map, Bias::Left);
 7045                let end = word_range.end.to_offset(&display_map, Bias::Left);
 7046                (start, end)
 7047            } else {
 7048                (selection.start, selection.end)
 7049            };
 7050
 7051            let text = buffer.text_for_range(start..end).collect::<String>();
 7052            let old_length = text.len() as i32;
 7053            let text = callback(&text);
 7054
 7055            new_selections.push(Selection {
 7056                start: (start as i32 - selection_adjustment) as usize,
 7057                end: ((start + text.len()) as i32 - selection_adjustment) as usize,
 7058                goal: SelectionGoal::None,
 7059                ..selection
 7060            });
 7061
 7062            selection_adjustment += old_length - text.len() as i32;
 7063
 7064            edits.push((start..end, text));
 7065        }
 7066
 7067        self.transact(window, cx, |this, window, cx| {
 7068            this.buffer.update(cx, |buffer, cx| {
 7069                buffer.edit(edits, None, cx);
 7070            });
 7071
 7072            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 7073                s.select(new_selections);
 7074            });
 7075
 7076            this.request_autoscroll(Autoscroll::fit(), cx);
 7077        });
 7078    }
 7079
 7080    pub fn duplicate(
 7081        &mut self,
 7082        upwards: bool,
 7083        whole_lines: bool,
 7084        window: &mut Window,
 7085        cx: &mut Context<Self>,
 7086    ) {
 7087        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 7088        let buffer = &display_map.buffer_snapshot;
 7089        let selections = self.selections.all::<Point>(cx);
 7090
 7091        let mut edits = Vec::new();
 7092        let mut selections_iter = selections.iter().peekable();
 7093        while let Some(selection) = selections_iter.next() {
 7094            let mut rows = selection.spanned_rows(false, &display_map);
 7095            // duplicate line-wise
 7096            if whole_lines || selection.start == selection.end {
 7097                // Avoid duplicating the same lines twice.
 7098                while let Some(next_selection) = selections_iter.peek() {
 7099                    let next_rows = next_selection.spanned_rows(false, &display_map);
 7100                    if next_rows.start < rows.end {
 7101                        rows.end = next_rows.end;
 7102                        selections_iter.next().unwrap();
 7103                    } else {
 7104                        break;
 7105                    }
 7106                }
 7107
 7108                // Copy the text from the selected row region and splice it either at the start
 7109                // or end of the region.
 7110                let start = Point::new(rows.start.0, 0);
 7111                let end = Point::new(
 7112                    rows.end.previous_row().0,
 7113                    buffer.line_len(rows.end.previous_row()),
 7114                );
 7115                let text = buffer
 7116                    .text_for_range(start..end)
 7117                    .chain(Some("\n"))
 7118                    .collect::<String>();
 7119                let insert_location = if upwards {
 7120                    Point::new(rows.end.0, 0)
 7121                } else {
 7122                    start
 7123                };
 7124                edits.push((insert_location..insert_location, text));
 7125            } else {
 7126                // duplicate character-wise
 7127                let start = selection.start;
 7128                let end = selection.end;
 7129                let text = buffer.text_for_range(start..end).collect::<String>();
 7130                edits.push((selection.end..selection.end, text));
 7131            }
 7132        }
 7133
 7134        self.transact(window, cx, |this, _, cx| {
 7135            this.buffer.update(cx, |buffer, cx| {
 7136                buffer.edit(edits, None, cx);
 7137            });
 7138
 7139            this.request_autoscroll(Autoscroll::fit(), cx);
 7140        });
 7141    }
 7142
 7143    pub fn duplicate_line_up(
 7144        &mut self,
 7145        _: &DuplicateLineUp,
 7146        window: &mut Window,
 7147        cx: &mut Context<Self>,
 7148    ) {
 7149        self.duplicate(true, true, window, cx);
 7150    }
 7151
 7152    pub fn duplicate_line_down(
 7153        &mut self,
 7154        _: &DuplicateLineDown,
 7155        window: &mut Window,
 7156        cx: &mut Context<Self>,
 7157    ) {
 7158        self.duplicate(false, true, window, cx);
 7159    }
 7160
 7161    pub fn duplicate_selection(
 7162        &mut self,
 7163        _: &DuplicateSelection,
 7164        window: &mut Window,
 7165        cx: &mut Context<Self>,
 7166    ) {
 7167        self.duplicate(false, false, window, cx);
 7168    }
 7169
 7170    pub fn move_line_up(&mut self, _: &MoveLineUp, window: &mut Window, cx: &mut Context<Self>) {
 7171        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 7172        let buffer = self.buffer.read(cx).snapshot(cx);
 7173
 7174        let mut edits = Vec::new();
 7175        let mut unfold_ranges = Vec::new();
 7176        let mut refold_creases = Vec::new();
 7177
 7178        let selections = self.selections.all::<Point>(cx);
 7179        let mut selections = selections.iter().peekable();
 7180        let mut contiguous_row_selections = Vec::new();
 7181        let mut new_selections = Vec::new();
 7182
 7183        while let Some(selection) = selections.next() {
 7184            // Find all the selections that span a contiguous row range
 7185            let (start_row, end_row) = consume_contiguous_rows(
 7186                &mut contiguous_row_selections,
 7187                selection,
 7188                &display_map,
 7189                &mut selections,
 7190            );
 7191
 7192            // Move the text spanned by the row range to be before the line preceding the row range
 7193            if start_row.0 > 0 {
 7194                let range_to_move = Point::new(
 7195                    start_row.previous_row().0,
 7196                    buffer.line_len(start_row.previous_row()),
 7197                )
 7198                    ..Point::new(
 7199                        end_row.previous_row().0,
 7200                        buffer.line_len(end_row.previous_row()),
 7201                    );
 7202                let insertion_point = display_map
 7203                    .prev_line_boundary(Point::new(start_row.previous_row().0, 0))
 7204                    .0;
 7205
 7206                // Don't move lines across excerpts
 7207                if buffer
 7208                    .excerpt_containing(insertion_point..range_to_move.end)
 7209                    .is_some()
 7210                {
 7211                    let text = buffer
 7212                        .text_for_range(range_to_move.clone())
 7213                        .flat_map(|s| s.chars())
 7214                        .skip(1)
 7215                        .chain(['\n'])
 7216                        .collect::<String>();
 7217
 7218                    edits.push((
 7219                        buffer.anchor_after(range_to_move.start)
 7220                            ..buffer.anchor_before(range_to_move.end),
 7221                        String::new(),
 7222                    ));
 7223                    let insertion_anchor = buffer.anchor_after(insertion_point);
 7224                    edits.push((insertion_anchor..insertion_anchor, text));
 7225
 7226                    let row_delta = range_to_move.start.row - insertion_point.row + 1;
 7227
 7228                    // Move selections up
 7229                    new_selections.extend(contiguous_row_selections.drain(..).map(
 7230                        |mut selection| {
 7231                            selection.start.row -= row_delta;
 7232                            selection.end.row -= row_delta;
 7233                            selection
 7234                        },
 7235                    ));
 7236
 7237                    // Move folds up
 7238                    unfold_ranges.push(range_to_move.clone());
 7239                    for fold in display_map.folds_in_range(
 7240                        buffer.anchor_before(range_to_move.start)
 7241                            ..buffer.anchor_after(range_to_move.end),
 7242                    ) {
 7243                        let mut start = fold.range.start.to_point(&buffer);
 7244                        let mut end = fold.range.end.to_point(&buffer);
 7245                        start.row -= row_delta;
 7246                        end.row -= row_delta;
 7247                        refold_creases.push(Crease::simple(start..end, fold.placeholder.clone()));
 7248                    }
 7249                }
 7250            }
 7251
 7252            // If we didn't move line(s), preserve the existing selections
 7253            new_selections.append(&mut contiguous_row_selections);
 7254        }
 7255
 7256        self.transact(window, cx, |this, window, cx| {
 7257            this.unfold_ranges(&unfold_ranges, true, true, cx);
 7258            this.buffer.update(cx, |buffer, cx| {
 7259                for (range, text) in edits {
 7260                    buffer.edit([(range, text)], None, cx);
 7261                }
 7262            });
 7263            this.fold_creases(refold_creases, true, window, cx);
 7264            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 7265                s.select(new_selections);
 7266            })
 7267        });
 7268    }
 7269
 7270    pub fn move_line_down(
 7271        &mut self,
 7272        _: &MoveLineDown,
 7273        window: &mut Window,
 7274        cx: &mut Context<Self>,
 7275    ) {
 7276        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 7277        let buffer = self.buffer.read(cx).snapshot(cx);
 7278
 7279        let mut edits = Vec::new();
 7280        let mut unfold_ranges = Vec::new();
 7281        let mut refold_creases = Vec::new();
 7282
 7283        let selections = self.selections.all::<Point>(cx);
 7284        let mut selections = selections.iter().peekable();
 7285        let mut contiguous_row_selections = Vec::new();
 7286        let mut new_selections = Vec::new();
 7287
 7288        while let Some(selection) = selections.next() {
 7289            // Find all the selections that span a contiguous row range
 7290            let (start_row, end_row) = consume_contiguous_rows(
 7291                &mut contiguous_row_selections,
 7292                selection,
 7293                &display_map,
 7294                &mut selections,
 7295            );
 7296
 7297            // Move the text spanned by the row range to be after the last line of the row range
 7298            if end_row.0 <= buffer.max_point().row {
 7299                let range_to_move =
 7300                    MultiBufferPoint::new(start_row.0, 0)..MultiBufferPoint::new(end_row.0, 0);
 7301                let insertion_point = display_map
 7302                    .next_line_boundary(MultiBufferPoint::new(end_row.0, 0))
 7303                    .0;
 7304
 7305                // Don't move lines across excerpt boundaries
 7306                if buffer
 7307                    .excerpt_containing(range_to_move.start..insertion_point)
 7308                    .is_some()
 7309                {
 7310                    let mut text = String::from("\n");
 7311                    text.extend(buffer.text_for_range(range_to_move.clone()));
 7312                    text.pop(); // Drop trailing newline
 7313                    edits.push((
 7314                        buffer.anchor_after(range_to_move.start)
 7315                            ..buffer.anchor_before(range_to_move.end),
 7316                        String::new(),
 7317                    ));
 7318                    let insertion_anchor = buffer.anchor_after(insertion_point);
 7319                    edits.push((insertion_anchor..insertion_anchor, text));
 7320
 7321                    let row_delta = insertion_point.row - range_to_move.end.row + 1;
 7322
 7323                    // Move selections down
 7324                    new_selections.extend(contiguous_row_selections.drain(..).map(
 7325                        |mut selection| {
 7326                            selection.start.row += row_delta;
 7327                            selection.end.row += row_delta;
 7328                            selection
 7329                        },
 7330                    ));
 7331
 7332                    // Move folds down
 7333                    unfold_ranges.push(range_to_move.clone());
 7334                    for fold in display_map.folds_in_range(
 7335                        buffer.anchor_before(range_to_move.start)
 7336                            ..buffer.anchor_after(range_to_move.end),
 7337                    ) {
 7338                        let mut start = fold.range.start.to_point(&buffer);
 7339                        let mut end = fold.range.end.to_point(&buffer);
 7340                        start.row += row_delta;
 7341                        end.row += row_delta;
 7342                        refold_creases.push(Crease::simple(start..end, fold.placeholder.clone()));
 7343                    }
 7344                }
 7345            }
 7346
 7347            // If we didn't move line(s), preserve the existing selections
 7348            new_selections.append(&mut contiguous_row_selections);
 7349        }
 7350
 7351        self.transact(window, cx, |this, window, cx| {
 7352            this.unfold_ranges(&unfold_ranges, true, true, cx);
 7353            this.buffer.update(cx, |buffer, cx| {
 7354                for (range, text) in edits {
 7355                    buffer.edit([(range, text)], None, cx);
 7356                }
 7357            });
 7358            this.fold_creases(refold_creases, true, window, cx);
 7359            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 7360                s.select(new_selections)
 7361            });
 7362        });
 7363    }
 7364
 7365    pub fn transpose(&mut self, _: &Transpose, window: &mut Window, cx: &mut Context<Self>) {
 7366        let text_layout_details = &self.text_layout_details(window);
 7367        self.transact(window, cx, |this, window, cx| {
 7368            let edits = this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 7369                let mut edits: Vec<(Range<usize>, String)> = Default::default();
 7370                let line_mode = s.line_mode;
 7371                s.move_with(|display_map, selection| {
 7372                    if !selection.is_empty() || line_mode {
 7373                        return;
 7374                    }
 7375
 7376                    let mut head = selection.head();
 7377                    let mut transpose_offset = head.to_offset(display_map, Bias::Right);
 7378                    if head.column() == display_map.line_len(head.row()) {
 7379                        transpose_offset = display_map
 7380                            .buffer_snapshot
 7381                            .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
 7382                    }
 7383
 7384                    if transpose_offset == 0 {
 7385                        return;
 7386                    }
 7387
 7388                    *head.column_mut() += 1;
 7389                    head = display_map.clip_point(head, Bias::Right);
 7390                    let goal = SelectionGoal::HorizontalPosition(
 7391                        display_map
 7392                            .x_for_display_point(head, text_layout_details)
 7393                            .into(),
 7394                    );
 7395                    selection.collapse_to(head, goal);
 7396
 7397                    let transpose_start = display_map
 7398                        .buffer_snapshot
 7399                        .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
 7400                    if edits.last().map_or(true, |e| e.0.end <= transpose_start) {
 7401                        let transpose_end = display_map
 7402                            .buffer_snapshot
 7403                            .clip_offset(transpose_offset + 1, Bias::Right);
 7404                        if let Some(ch) =
 7405                            display_map.buffer_snapshot.chars_at(transpose_start).next()
 7406                        {
 7407                            edits.push((transpose_start..transpose_offset, String::new()));
 7408                            edits.push((transpose_end..transpose_end, ch.to_string()));
 7409                        }
 7410                    }
 7411                });
 7412                edits
 7413            });
 7414            this.buffer
 7415                .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
 7416            let selections = this.selections.all::<usize>(cx);
 7417            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 7418                s.select(selections);
 7419            });
 7420        });
 7421    }
 7422
 7423    pub fn rewrap(&mut self, _: &Rewrap, _: &mut Window, cx: &mut Context<Self>) {
 7424        self.rewrap_impl(IsVimMode::No, cx)
 7425    }
 7426
 7427    pub fn rewrap_impl(&mut self, is_vim_mode: IsVimMode, cx: &mut Context<Self>) {
 7428        let buffer = self.buffer.read(cx).snapshot(cx);
 7429        let selections = self.selections.all::<Point>(cx);
 7430        let mut selections = selections.iter().peekable();
 7431
 7432        let mut edits = Vec::new();
 7433        let mut rewrapped_row_ranges = Vec::<RangeInclusive<u32>>::new();
 7434
 7435        while let Some(selection) = selections.next() {
 7436            let mut start_row = selection.start.row;
 7437            let mut end_row = selection.end.row;
 7438
 7439            // Skip selections that overlap with a range that has already been rewrapped.
 7440            let selection_range = start_row..end_row;
 7441            if rewrapped_row_ranges
 7442                .iter()
 7443                .any(|range| range.overlaps(&selection_range))
 7444            {
 7445                continue;
 7446            }
 7447
 7448            let mut should_rewrap = is_vim_mode == IsVimMode::Yes;
 7449
 7450            if let Some(language_scope) = buffer.language_scope_at(selection.head()) {
 7451                match language_scope.language_name().as_ref() {
 7452                    "Markdown" | "Plain Text" => {
 7453                        should_rewrap = true;
 7454                    }
 7455                    _ => {}
 7456                }
 7457            }
 7458
 7459            let tab_size = buffer.settings_at(selection.head(), cx).tab_size;
 7460
 7461            // Since not all lines in the selection may be at the same indent
 7462            // level, choose the indent size that is the most common between all
 7463            // of the lines.
 7464            //
 7465            // If there is a tie, we use the deepest indent.
 7466            let (indent_size, indent_end) = {
 7467                let mut indent_size_occurrences = HashMap::default();
 7468                let mut rows_by_indent_size = HashMap::<IndentSize, Vec<u32>>::default();
 7469
 7470                for row in start_row..=end_row {
 7471                    let indent = buffer.indent_size_for_line(MultiBufferRow(row));
 7472                    rows_by_indent_size.entry(indent).or_default().push(row);
 7473                    *indent_size_occurrences.entry(indent).or_insert(0) += 1;
 7474                }
 7475
 7476                let indent_size = indent_size_occurrences
 7477                    .into_iter()
 7478                    .max_by_key(|(indent, count)| (*count, indent.len_with_expanded_tabs(tab_size)))
 7479                    .map(|(indent, _)| indent)
 7480                    .unwrap_or_default();
 7481                let row = rows_by_indent_size[&indent_size][0];
 7482                let indent_end = Point::new(row, indent_size.len);
 7483
 7484                (indent_size, indent_end)
 7485            };
 7486
 7487            let mut line_prefix = indent_size.chars().collect::<String>();
 7488
 7489            if let Some(comment_prefix) =
 7490                buffer
 7491                    .language_scope_at(selection.head())
 7492                    .and_then(|language| {
 7493                        language
 7494                            .line_comment_prefixes()
 7495                            .iter()
 7496                            .find(|prefix| buffer.contains_str_at(indent_end, prefix))
 7497                            .cloned()
 7498                    })
 7499            {
 7500                line_prefix.push_str(&comment_prefix);
 7501                should_rewrap = true;
 7502            }
 7503
 7504            if !should_rewrap {
 7505                continue;
 7506            }
 7507
 7508            if selection.is_empty() {
 7509                'expand_upwards: while start_row > 0 {
 7510                    let prev_row = start_row - 1;
 7511                    if buffer.contains_str_at(Point::new(prev_row, 0), &line_prefix)
 7512                        && buffer.line_len(MultiBufferRow(prev_row)) as usize > line_prefix.len()
 7513                    {
 7514                        start_row = prev_row;
 7515                    } else {
 7516                        break 'expand_upwards;
 7517                    }
 7518                }
 7519
 7520                'expand_downwards: while end_row < buffer.max_point().row {
 7521                    let next_row = end_row + 1;
 7522                    if buffer.contains_str_at(Point::new(next_row, 0), &line_prefix)
 7523                        && buffer.line_len(MultiBufferRow(next_row)) as usize > line_prefix.len()
 7524                    {
 7525                        end_row = next_row;
 7526                    } else {
 7527                        break 'expand_downwards;
 7528                    }
 7529                }
 7530            }
 7531
 7532            let start = Point::new(start_row, 0);
 7533            let end = Point::new(end_row, buffer.line_len(MultiBufferRow(end_row)));
 7534            let selection_text = buffer.text_for_range(start..end).collect::<String>();
 7535            let Some(lines_without_prefixes) = selection_text
 7536                .lines()
 7537                .map(|line| {
 7538                    line.strip_prefix(&line_prefix)
 7539                        .or_else(|| line.trim_start().strip_prefix(&line_prefix.trim_start()))
 7540                        .ok_or_else(|| {
 7541                            anyhow!("line did not start with prefix {line_prefix:?}: {line:?}")
 7542                        })
 7543                })
 7544                .collect::<Result<Vec<_>, _>>()
 7545                .log_err()
 7546            else {
 7547                continue;
 7548            };
 7549
 7550            let wrap_column = buffer
 7551                .settings_at(Point::new(start_row, 0), cx)
 7552                .preferred_line_length as usize;
 7553            let wrapped_text = wrap_with_prefix(
 7554                line_prefix,
 7555                lines_without_prefixes.join(" "),
 7556                wrap_column,
 7557                tab_size,
 7558            );
 7559
 7560            // TODO: should always use char-based diff while still supporting cursor behavior that
 7561            // matches vim.
 7562            let diff = match is_vim_mode {
 7563                IsVimMode::Yes => TextDiff::from_lines(&selection_text, &wrapped_text),
 7564                IsVimMode::No => TextDiff::from_chars(&selection_text, &wrapped_text),
 7565            };
 7566            let mut offset = start.to_offset(&buffer);
 7567            let mut moved_since_edit = true;
 7568
 7569            for change in diff.iter_all_changes() {
 7570                let value = change.value();
 7571                match change.tag() {
 7572                    ChangeTag::Equal => {
 7573                        offset += value.len();
 7574                        moved_since_edit = true;
 7575                    }
 7576                    ChangeTag::Delete => {
 7577                        let start = buffer.anchor_after(offset);
 7578                        let end = buffer.anchor_before(offset + value.len());
 7579
 7580                        if moved_since_edit {
 7581                            edits.push((start..end, String::new()));
 7582                        } else {
 7583                            edits.last_mut().unwrap().0.end = end;
 7584                        }
 7585
 7586                        offset += value.len();
 7587                        moved_since_edit = false;
 7588                    }
 7589                    ChangeTag::Insert => {
 7590                        if moved_since_edit {
 7591                            let anchor = buffer.anchor_after(offset);
 7592                            edits.push((anchor..anchor, value.to_string()));
 7593                        } else {
 7594                            edits.last_mut().unwrap().1.push_str(value);
 7595                        }
 7596
 7597                        moved_since_edit = false;
 7598                    }
 7599                }
 7600            }
 7601
 7602            rewrapped_row_ranges.push(start_row..=end_row);
 7603        }
 7604
 7605        self.buffer
 7606            .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
 7607    }
 7608
 7609    pub fn cut_common(&mut self, window: &mut Window, cx: &mut Context<Self>) -> ClipboardItem {
 7610        let mut text = String::new();
 7611        let buffer = self.buffer.read(cx).snapshot(cx);
 7612        let mut selections = self.selections.all::<Point>(cx);
 7613        let mut clipboard_selections = Vec::with_capacity(selections.len());
 7614        {
 7615            let max_point = buffer.max_point();
 7616            let mut is_first = true;
 7617            for selection in &mut selections {
 7618                let is_entire_line = selection.is_empty() || self.selections.line_mode;
 7619                if is_entire_line {
 7620                    selection.start = Point::new(selection.start.row, 0);
 7621                    if !selection.is_empty() && selection.end.column == 0 {
 7622                        selection.end = cmp::min(max_point, selection.end);
 7623                    } else {
 7624                        selection.end = cmp::min(max_point, Point::new(selection.end.row + 1, 0));
 7625                    }
 7626                    selection.goal = SelectionGoal::None;
 7627                }
 7628                if is_first {
 7629                    is_first = false;
 7630                } else {
 7631                    text += "\n";
 7632                }
 7633                let mut len = 0;
 7634                for chunk in buffer.text_for_range(selection.start..selection.end) {
 7635                    text.push_str(chunk);
 7636                    len += chunk.len();
 7637                }
 7638                clipboard_selections.push(ClipboardSelection {
 7639                    len,
 7640                    is_entire_line,
 7641                    first_line_indent: buffer
 7642                        .indent_size_for_line(MultiBufferRow(selection.start.row))
 7643                        .len,
 7644                });
 7645            }
 7646        }
 7647
 7648        self.transact(window, cx, |this, window, cx| {
 7649            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 7650                s.select(selections);
 7651            });
 7652            this.insert("", window, cx);
 7653        });
 7654        ClipboardItem::new_string_with_json_metadata(text, clipboard_selections)
 7655    }
 7656
 7657    pub fn cut(&mut self, _: &Cut, window: &mut Window, cx: &mut Context<Self>) {
 7658        let item = self.cut_common(window, cx);
 7659        cx.write_to_clipboard(item);
 7660    }
 7661
 7662    pub fn kill_ring_cut(&mut self, _: &KillRingCut, window: &mut Window, cx: &mut Context<Self>) {
 7663        self.change_selections(None, window, cx, |s| {
 7664            s.move_with(|snapshot, sel| {
 7665                if sel.is_empty() {
 7666                    sel.end = DisplayPoint::new(sel.end.row(), snapshot.line_len(sel.end.row()))
 7667                }
 7668            });
 7669        });
 7670        let item = self.cut_common(window, cx);
 7671        cx.set_global(KillRing(item))
 7672    }
 7673
 7674    pub fn kill_ring_yank(
 7675        &mut self,
 7676        _: &KillRingYank,
 7677        window: &mut Window,
 7678        cx: &mut Context<Self>,
 7679    ) {
 7680        let (text, metadata) = if let Some(KillRing(item)) = cx.try_global() {
 7681            if let Some(ClipboardEntry::String(kill_ring)) = item.entries().first() {
 7682                (kill_ring.text().to_string(), kill_ring.metadata_json())
 7683            } else {
 7684                return;
 7685            }
 7686        } else {
 7687            return;
 7688        };
 7689        self.do_paste(&text, metadata, false, window, cx);
 7690    }
 7691
 7692    pub fn copy(&mut self, _: &Copy, _: &mut Window, cx: &mut Context<Self>) {
 7693        let selections = self.selections.all::<Point>(cx);
 7694        let buffer = self.buffer.read(cx).read(cx);
 7695        let mut text = String::new();
 7696
 7697        let mut clipboard_selections = Vec::with_capacity(selections.len());
 7698        {
 7699            let max_point = buffer.max_point();
 7700            let mut is_first = true;
 7701            for selection in selections.iter() {
 7702                let mut start = selection.start;
 7703                let mut end = selection.end;
 7704                let is_entire_line = selection.is_empty() || self.selections.line_mode;
 7705                if is_entire_line {
 7706                    start = Point::new(start.row, 0);
 7707                    end = cmp::min(max_point, Point::new(end.row + 1, 0));
 7708                }
 7709                if is_first {
 7710                    is_first = false;
 7711                } else {
 7712                    text += "\n";
 7713                }
 7714                let mut len = 0;
 7715                for chunk in buffer.text_for_range(start..end) {
 7716                    text.push_str(chunk);
 7717                    len += chunk.len();
 7718                }
 7719                clipboard_selections.push(ClipboardSelection {
 7720                    len,
 7721                    is_entire_line,
 7722                    first_line_indent: buffer.indent_size_for_line(MultiBufferRow(start.row)).len,
 7723                });
 7724            }
 7725        }
 7726
 7727        cx.write_to_clipboard(ClipboardItem::new_string_with_json_metadata(
 7728            text,
 7729            clipboard_selections,
 7730        ));
 7731    }
 7732
 7733    pub fn do_paste(
 7734        &mut self,
 7735        text: &String,
 7736        clipboard_selections: Option<Vec<ClipboardSelection>>,
 7737        handle_entire_lines: bool,
 7738        window: &mut Window,
 7739        cx: &mut Context<Self>,
 7740    ) {
 7741        if self.read_only(cx) {
 7742            return;
 7743        }
 7744
 7745        let clipboard_text = Cow::Borrowed(text);
 7746
 7747        self.transact(window, cx, |this, window, cx| {
 7748            if let Some(mut clipboard_selections) = clipboard_selections {
 7749                let old_selections = this.selections.all::<usize>(cx);
 7750                let all_selections_were_entire_line =
 7751                    clipboard_selections.iter().all(|s| s.is_entire_line);
 7752                let first_selection_indent_column =
 7753                    clipboard_selections.first().map(|s| s.first_line_indent);
 7754                if clipboard_selections.len() != old_selections.len() {
 7755                    clipboard_selections.drain(..);
 7756                }
 7757                let cursor_offset = this.selections.last::<usize>(cx).head();
 7758                let mut auto_indent_on_paste = true;
 7759
 7760                this.buffer.update(cx, |buffer, cx| {
 7761                    let snapshot = buffer.read(cx);
 7762                    auto_indent_on_paste =
 7763                        snapshot.settings_at(cursor_offset, cx).auto_indent_on_paste;
 7764
 7765                    let mut start_offset = 0;
 7766                    let mut edits = Vec::new();
 7767                    let mut original_indent_columns = Vec::new();
 7768                    for (ix, selection) in old_selections.iter().enumerate() {
 7769                        let to_insert;
 7770                        let entire_line;
 7771                        let original_indent_column;
 7772                        if let Some(clipboard_selection) = clipboard_selections.get(ix) {
 7773                            let end_offset = start_offset + clipboard_selection.len;
 7774                            to_insert = &clipboard_text[start_offset..end_offset];
 7775                            entire_line = clipboard_selection.is_entire_line;
 7776                            start_offset = end_offset + 1;
 7777                            original_indent_column = Some(clipboard_selection.first_line_indent);
 7778                        } else {
 7779                            to_insert = clipboard_text.as_str();
 7780                            entire_line = all_selections_were_entire_line;
 7781                            original_indent_column = first_selection_indent_column
 7782                        }
 7783
 7784                        // If the corresponding selection was empty when this slice of the
 7785                        // clipboard text was written, then the entire line containing the
 7786                        // selection was copied. If this selection is also currently empty,
 7787                        // then paste the line before the current line of the buffer.
 7788                        let range = if selection.is_empty() && handle_entire_lines && entire_line {
 7789                            let column = selection.start.to_point(&snapshot).column as usize;
 7790                            let line_start = selection.start - column;
 7791                            line_start..line_start
 7792                        } else {
 7793                            selection.range()
 7794                        };
 7795
 7796                        edits.push((range, to_insert));
 7797                        original_indent_columns.extend(original_indent_column);
 7798                    }
 7799                    drop(snapshot);
 7800
 7801                    buffer.edit(
 7802                        edits,
 7803                        if auto_indent_on_paste {
 7804                            Some(AutoindentMode::Block {
 7805                                original_indent_columns,
 7806                            })
 7807                        } else {
 7808                            None
 7809                        },
 7810                        cx,
 7811                    );
 7812                });
 7813
 7814                let selections = this.selections.all::<usize>(cx);
 7815                this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 7816                    s.select(selections)
 7817                });
 7818            } else {
 7819                this.insert(&clipboard_text, window, cx);
 7820            }
 7821        });
 7822    }
 7823
 7824    pub fn paste(&mut self, _: &Paste, window: &mut Window, cx: &mut Context<Self>) {
 7825        if let Some(item) = cx.read_from_clipboard() {
 7826            let entries = item.entries();
 7827
 7828            match entries.first() {
 7829                // For now, we only support applying metadata if there's one string. In the future, we can incorporate all the selections
 7830                // of all the pasted entries.
 7831                Some(ClipboardEntry::String(clipboard_string)) if entries.len() == 1 => self
 7832                    .do_paste(
 7833                        clipboard_string.text(),
 7834                        clipboard_string.metadata_json::<Vec<ClipboardSelection>>(),
 7835                        true,
 7836                        window,
 7837                        cx,
 7838                    ),
 7839                _ => self.do_paste(&item.text().unwrap_or_default(), None, true, window, cx),
 7840            }
 7841        }
 7842    }
 7843
 7844    pub fn undo(&mut self, _: &Undo, window: &mut Window, cx: &mut Context<Self>) {
 7845        if self.read_only(cx) {
 7846            return;
 7847        }
 7848
 7849        if let Some(transaction_id) = self.buffer.update(cx, |buffer, cx| buffer.undo(cx)) {
 7850            if let Some((selections, _)) =
 7851                self.selection_history.transaction(transaction_id).cloned()
 7852            {
 7853                self.change_selections(None, window, cx, |s| {
 7854                    s.select_anchors(selections.to_vec());
 7855                });
 7856            }
 7857            self.request_autoscroll(Autoscroll::fit(), cx);
 7858            self.unmark_text(window, cx);
 7859            self.refresh_inline_completion(true, false, window, cx);
 7860            cx.emit(EditorEvent::Edited { transaction_id });
 7861            cx.emit(EditorEvent::TransactionUndone { transaction_id });
 7862        }
 7863    }
 7864
 7865    pub fn redo(&mut self, _: &Redo, window: &mut Window, cx: &mut Context<Self>) {
 7866        if self.read_only(cx) {
 7867            return;
 7868        }
 7869
 7870        if let Some(transaction_id) = self.buffer.update(cx, |buffer, cx| buffer.redo(cx)) {
 7871            if let Some((_, Some(selections))) =
 7872                self.selection_history.transaction(transaction_id).cloned()
 7873            {
 7874                self.change_selections(None, window, cx, |s| {
 7875                    s.select_anchors(selections.to_vec());
 7876                });
 7877            }
 7878            self.request_autoscroll(Autoscroll::fit(), cx);
 7879            self.unmark_text(window, cx);
 7880            self.refresh_inline_completion(true, false, window, cx);
 7881            cx.emit(EditorEvent::Edited { transaction_id });
 7882        }
 7883    }
 7884
 7885    pub fn finalize_last_transaction(&mut self, cx: &mut Context<Self>) {
 7886        self.buffer
 7887            .update(cx, |buffer, cx| buffer.finalize_last_transaction(cx));
 7888    }
 7889
 7890    pub fn group_until_transaction(&mut self, tx_id: TransactionId, cx: &mut Context<Self>) {
 7891        self.buffer
 7892            .update(cx, |buffer, cx| buffer.group_until_transaction(tx_id, cx));
 7893    }
 7894
 7895    pub fn move_left(&mut self, _: &MoveLeft, window: &mut Window, cx: &mut Context<Self>) {
 7896        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 7897            let line_mode = s.line_mode;
 7898            s.move_with(|map, selection| {
 7899                let cursor = if selection.is_empty() && !line_mode {
 7900                    movement::left(map, selection.start)
 7901                } else {
 7902                    selection.start
 7903                };
 7904                selection.collapse_to(cursor, SelectionGoal::None);
 7905            });
 7906        })
 7907    }
 7908
 7909    pub fn select_left(&mut self, _: &SelectLeft, window: &mut Window, cx: &mut Context<Self>) {
 7910        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 7911            s.move_heads_with(|map, head, _| (movement::left(map, head), SelectionGoal::None));
 7912        })
 7913    }
 7914
 7915    pub fn move_right(&mut self, _: &MoveRight, window: &mut Window, cx: &mut Context<Self>) {
 7916        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 7917            let line_mode = s.line_mode;
 7918            s.move_with(|map, selection| {
 7919                let cursor = if selection.is_empty() && !line_mode {
 7920                    movement::right(map, selection.end)
 7921                } else {
 7922                    selection.end
 7923                };
 7924                selection.collapse_to(cursor, SelectionGoal::None)
 7925            });
 7926        })
 7927    }
 7928
 7929    pub fn select_right(&mut self, _: &SelectRight, window: &mut Window, cx: &mut Context<Self>) {
 7930        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 7931            s.move_heads_with(|map, head, _| (movement::right(map, head), SelectionGoal::None));
 7932        })
 7933    }
 7934
 7935    pub fn move_up(&mut self, _: &MoveUp, window: &mut Window, cx: &mut Context<Self>) {
 7936        if self.take_rename(true, window, cx).is_some() {
 7937            return;
 7938        }
 7939
 7940        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 7941            cx.propagate();
 7942            return;
 7943        }
 7944
 7945        let text_layout_details = &self.text_layout_details(window);
 7946        let selection_count = self.selections.count();
 7947        let first_selection = self.selections.first_anchor();
 7948
 7949        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 7950            let line_mode = s.line_mode;
 7951            s.move_with(|map, selection| {
 7952                if !selection.is_empty() && !line_mode {
 7953                    selection.goal = SelectionGoal::None;
 7954                }
 7955                let (cursor, goal) = movement::up(
 7956                    map,
 7957                    selection.start,
 7958                    selection.goal,
 7959                    false,
 7960                    text_layout_details,
 7961                );
 7962                selection.collapse_to(cursor, goal);
 7963            });
 7964        });
 7965
 7966        if selection_count == 1 && first_selection.range() == self.selections.first_anchor().range()
 7967        {
 7968            cx.propagate();
 7969        }
 7970    }
 7971
 7972    pub fn move_up_by_lines(
 7973        &mut self,
 7974        action: &MoveUpByLines,
 7975        window: &mut Window,
 7976        cx: &mut Context<Self>,
 7977    ) {
 7978        if self.take_rename(true, window, cx).is_some() {
 7979            return;
 7980        }
 7981
 7982        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 7983            cx.propagate();
 7984            return;
 7985        }
 7986
 7987        let text_layout_details = &self.text_layout_details(window);
 7988
 7989        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 7990            let line_mode = s.line_mode;
 7991            s.move_with(|map, selection| {
 7992                if !selection.is_empty() && !line_mode {
 7993                    selection.goal = SelectionGoal::None;
 7994                }
 7995                let (cursor, goal) = movement::up_by_rows(
 7996                    map,
 7997                    selection.start,
 7998                    action.lines,
 7999                    selection.goal,
 8000                    false,
 8001                    text_layout_details,
 8002                );
 8003                selection.collapse_to(cursor, goal);
 8004            });
 8005        })
 8006    }
 8007
 8008    pub fn move_down_by_lines(
 8009        &mut self,
 8010        action: &MoveDownByLines,
 8011        window: &mut Window,
 8012        cx: &mut Context<Self>,
 8013    ) {
 8014        if self.take_rename(true, window, cx).is_some() {
 8015            return;
 8016        }
 8017
 8018        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 8019            cx.propagate();
 8020            return;
 8021        }
 8022
 8023        let text_layout_details = &self.text_layout_details(window);
 8024
 8025        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8026            let line_mode = s.line_mode;
 8027            s.move_with(|map, selection| {
 8028                if !selection.is_empty() && !line_mode {
 8029                    selection.goal = SelectionGoal::None;
 8030                }
 8031                let (cursor, goal) = movement::down_by_rows(
 8032                    map,
 8033                    selection.start,
 8034                    action.lines,
 8035                    selection.goal,
 8036                    false,
 8037                    text_layout_details,
 8038                );
 8039                selection.collapse_to(cursor, goal);
 8040            });
 8041        })
 8042    }
 8043
 8044    pub fn select_down_by_lines(
 8045        &mut self,
 8046        action: &SelectDownByLines,
 8047        window: &mut Window,
 8048        cx: &mut Context<Self>,
 8049    ) {
 8050        let text_layout_details = &self.text_layout_details(window);
 8051        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8052            s.move_heads_with(|map, head, goal| {
 8053                movement::down_by_rows(map, head, action.lines, goal, false, text_layout_details)
 8054            })
 8055        })
 8056    }
 8057
 8058    pub fn select_up_by_lines(
 8059        &mut self,
 8060        action: &SelectUpByLines,
 8061        window: &mut Window,
 8062        cx: &mut Context<Self>,
 8063    ) {
 8064        let text_layout_details = &self.text_layout_details(window);
 8065        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8066            s.move_heads_with(|map, head, goal| {
 8067                movement::up_by_rows(map, head, action.lines, goal, false, text_layout_details)
 8068            })
 8069        })
 8070    }
 8071
 8072    pub fn select_page_up(
 8073        &mut self,
 8074        _: &SelectPageUp,
 8075        window: &mut Window,
 8076        cx: &mut Context<Self>,
 8077    ) {
 8078        let Some(row_count) = self.visible_row_count() else {
 8079            return;
 8080        };
 8081
 8082        let text_layout_details = &self.text_layout_details(window);
 8083
 8084        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8085            s.move_heads_with(|map, head, goal| {
 8086                movement::up_by_rows(map, head, row_count, goal, false, text_layout_details)
 8087            })
 8088        })
 8089    }
 8090
 8091    pub fn move_page_up(
 8092        &mut self,
 8093        action: &MovePageUp,
 8094        window: &mut Window,
 8095        cx: &mut Context<Self>,
 8096    ) {
 8097        if self.take_rename(true, window, cx).is_some() {
 8098            return;
 8099        }
 8100
 8101        if self
 8102            .context_menu
 8103            .borrow_mut()
 8104            .as_mut()
 8105            .map(|menu| menu.select_first(self.completion_provider.as_deref(), cx))
 8106            .unwrap_or(false)
 8107        {
 8108            return;
 8109        }
 8110
 8111        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 8112            cx.propagate();
 8113            return;
 8114        }
 8115
 8116        let Some(row_count) = self.visible_row_count() else {
 8117            return;
 8118        };
 8119
 8120        let autoscroll = if action.center_cursor {
 8121            Autoscroll::center()
 8122        } else {
 8123            Autoscroll::fit()
 8124        };
 8125
 8126        let text_layout_details = &self.text_layout_details(window);
 8127
 8128        self.change_selections(Some(autoscroll), window, cx, |s| {
 8129            let line_mode = s.line_mode;
 8130            s.move_with(|map, selection| {
 8131                if !selection.is_empty() && !line_mode {
 8132                    selection.goal = SelectionGoal::None;
 8133                }
 8134                let (cursor, goal) = movement::up_by_rows(
 8135                    map,
 8136                    selection.end,
 8137                    row_count,
 8138                    selection.goal,
 8139                    false,
 8140                    text_layout_details,
 8141                );
 8142                selection.collapse_to(cursor, goal);
 8143            });
 8144        });
 8145    }
 8146
 8147    pub fn select_up(&mut self, _: &SelectUp, window: &mut Window, cx: &mut Context<Self>) {
 8148        let text_layout_details = &self.text_layout_details(window);
 8149        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8150            s.move_heads_with(|map, head, goal| {
 8151                movement::up(map, head, goal, false, text_layout_details)
 8152            })
 8153        })
 8154    }
 8155
 8156    pub fn move_down(&mut self, _: &MoveDown, window: &mut Window, cx: &mut Context<Self>) {
 8157        self.take_rename(true, window, cx);
 8158
 8159        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 8160            cx.propagate();
 8161            return;
 8162        }
 8163
 8164        let text_layout_details = &self.text_layout_details(window);
 8165        let selection_count = self.selections.count();
 8166        let first_selection = self.selections.first_anchor();
 8167
 8168        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8169            let line_mode = s.line_mode;
 8170            s.move_with(|map, selection| {
 8171                if !selection.is_empty() && !line_mode {
 8172                    selection.goal = SelectionGoal::None;
 8173                }
 8174                let (cursor, goal) = movement::down(
 8175                    map,
 8176                    selection.end,
 8177                    selection.goal,
 8178                    false,
 8179                    text_layout_details,
 8180                );
 8181                selection.collapse_to(cursor, goal);
 8182            });
 8183        });
 8184
 8185        if selection_count == 1 && first_selection.range() == self.selections.first_anchor().range()
 8186        {
 8187            cx.propagate();
 8188        }
 8189    }
 8190
 8191    pub fn select_page_down(
 8192        &mut self,
 8193        _: &SelectPageDown,
 8194        window: &mut Window,
 8195        cx: &mut Context<Self>,
 8196    ) {
 8197        let Some(row_count) = self.visible_row_count() else {
 8198            return;
 8199        };
 8200
 8201        let text_layout_details = &self.text_layout_details(window);
 8202
 8203        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8204            s.move_heads_with(|map, head, goal| {
 8205                movement::down_by_rows(map, head, row_count, goal, false, text_layout_details)
 8206            })
 8207        })
 8208    }
 8209
 8210    pub fn move_page_down(
 8211        &mut self,
 8212        action: &MovePageDown,
 8213        window: &mut Window,
 8214        cx: &mut Context<Self>,
 8215    ) {
 8216        if self.take_rename(true, window, cx).is_some() {
 8217            return;
 8218        }
 8219
 8220        if self
 8221            .context_menu
 8222            .borrow_mut()
 8223            .as_mut()
 8224            .map(|menu| menu.select_last(self.completion_provider.as_deref(), cx))
 8225            .unwrap_or(false)
 8226        {
 8227            return;
 8228        }
 8229
 8230        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 8231            cx.propagate();
 8232            return;
 8233        }
 8234
 8235        let Some(row_count) = self.visible_row_count() else {
 8236            return;
 8237        };
 8238
 8239        let autoscroll = if action.center_cursor {
 8240            Autoscroll::center()
 8241        } else {
 8242            Autoscroll::fit()
 8243        };
 8244
 8245        let text_layout_details = &self.text_layout_details(window);
 8246        self.change_selections(Some(autoscroll), window, cx, |s| {
 8247            let line_mode = s.line_mode;
 8248            s.move_with(|map, selection| {
 8249                if !selection.is_empty() && !line_mode {
 8250                    selection.goal = SelectionGoal::None;
 8251                }
 8252                let (cursor, goal) = movement::down_by_rows(
 8253                    map,
 8254                    selection.end,
 8255                    row_count,
 8256                    selection.goal,
 8257                    false,
 8258                    text_layout_details,
 8259                );
 8260                selection.collapse_to(cursor, goal);
 8261            });
 8262        });
 8263    }
 8264
 8265    pub fn select_down(&mut self, _: &SelectDown, window: &mut Window, cx: &mut Context<Self>) {
 8266        let text_layout_details = &self.text_layout_details(window);
 8267        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8268            s.move_heads_with(|map, head, goal| {
 8269                movement::down(map, head, goal, false, text_layout_details)
 8270            })
 8271        });
 8272    }
 8273
 8274    pub fn context_menu_first(
 8275        &mut self,
 8276        _: &ContextMenuFirst,
 8277        _window: &mut Window,
 8278        cx: &mut Context<Self>,
 8279    ) {
 8280        if let Some(context_menu) = self.context_menu.borrow_mut().as_mut() {
 8281            context_menu.select_first(self.completion_provider.as_deref(), cx);
 8282        }
 8283    }
 8284
 8285    pub fn context_menu_prev(
 8286        &mut self,
 8287        _: &ContextMenuPrev,
 8288        _window: &mut Window,
 8289        cx: &mut Context<Self>,
 8290    ) {
 8291        if let Some(context_menu) = self.context_menu.borrow_mut().as_mut() {
 8292            context_menu.select_prev(self.completion_provider.as_deref(), cx);
 8293        }
 8294    }
 8295
 8296    pub fn context_menu_next(
 8297        &mut self,
 8298        _: &ContextMenuNext,
 8299        _window: &mut Window,
 8300        cx: &mut Context<Self>,
 8301    ) {
 8302        if let Some(context_menu) = self.context_menu.borrow_mut().as_mut() {
 8303            context_menu.select_next(self.completion_provider.as_deref(), cx);
 8304        }
 8305    }
 8306
 8307    pub fn context_menu_last(
 8308        &mut self,
 8309        _: &ContextMenuLast,
 8310        _window: &mut Window,
 8311        cx: &mut Context<Self>,
 8312    ) {
 8313        if let Some(context_menu) = self.context_menu.borrow_mut().as_mut() {
 8314            context_menu.select_last(self.completion_provider.as_deref(), cx);
 8315        }
 8316    }
 8317
 8318    pub fn move_to_previous_word_start(
 8319        &mut self,
 8320        _: &MoveToPreviousWordStart,
 8321        window: &mut Window,
 8322        cx: &mut Context<Self>,
 8323    ) {
 8324        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8325            s.move_cursors_with(|map, head, _| {
 8326                (
 8327                    movement::previous_word_start(map, head),
 8328                    SelectionGoal::None,
 8329                )
 8330            });
 8331        })
 8332    }
 8333
 8334    pub fn move_to_previous_subword_start(
 8335        &mut self,
 8336        _: &MoveToPreviousSubwordStart,
 8337        window: &mut Window,
 8338        cx: &mut Context<Self>,
 8339    ) {
 8340        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8341            s.move_cursors_with(|map, head, _| {
 8342                (
 8343                    movement::previous_subword_start(map, head),
 8344                    SelectionGoal::None,
 8345                )
 8346            });
 8347        })
 8348    }
 8349
 8350    pub fn select_to_previous_word_start(
 8351        &mut self,
 8352        _: &SelectToPreviousWordStart,
 8353        window: &mut Window,
 8354        cx: &mut Context<Self>,
 8355    ) {
 8356        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8357            s.move_heads_with(|map, head, _| {
 8358                (
 8359                    movement::previous_word_start(map, head),
 8360                    SelectionGoal::None,
 8361                )
 8362            });
 8363        })
 8364    }
 8365
 8366    pub fn select_to_previous_subword_start(
 8367        &mut self,
 8368        _: &SelectToPreviousSubwordStart,
 8369        window: &mut Window,
 8370        cx: &mut Context<Self>,
 8371    ) {
 8372        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8373            s.move_heads_with(|map, head, _| {
 8374                (
 8375                    movement::previous_subword_start(map, head),
 8376                    SelectionGoal::None,
 8377                )
 8378            });
 8379        })
 8380    }
 8381
 8382    pub fn delete_to_previous_word_start(
 8383        &mut self,
 8384        action: &DeleteToPreviousWordStart,
 8385        window: &mut Window,
 8386        cx: &mut Context<Self>,
 8387    ) {
 8388        self.transact(window, cx, |this, window, cx| {
 8389            this.select_autoclose_pair(window, cx);
 8390            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8391                let line_mode = s.line_mode;
 8392                s.move_with(|map, selection| {
 8393                    if selection.is_empty() && !line_mode {
 8394                        let cursor = if action.ignore_newlines {
 8395                            movement::previous_word_start(map, selection.head())
 8396                        } else {
 8397                            movement::previous_word_start_or_newline(map, selection.head())
 8398                        };
 8399                        selection.set_head(cursor, SelectionGoal::None);
 8400                    }
 8401                });
 8402            });
 8403            this.insert("", window, cx);
 8404        });
 8405    }
 8406
 8407    pub fn delete_to_previous_subword_start(
 8408        &mut self,
 8409        _: &DeleteToPreviousSubwordStart,
 8410        window: &mut Window,
 8411        cx: &mut Context<Self>,
 8412    ) {
 8413        self.transact(window, cx, |this, window, cx| {
 8414            this.select_autoclose_pair(window, cx);
 8415            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8416                let line_mode = s.line_mode;
 8417                s.move_with(|map, selection| {
 8418                    if selection.is_empty() && !line_mode {
 8419                        let cursor = movement::previous_subword_start(map, selection.head());
 8420                        selection.set_head(cursor, SelectionGoal::None);
 8421                    }
 8422                });
 8423            });
 8424            this.insert("", window, cx);
 8425        });
 8426    }
 8427
 8428    pub fn move_to_next_word_end(
 8429        &mut self,
 8430        _: &MoveToNextWordEnd,
 8431        window: &mut Window,
 8432        cx: &mut Context<Self>,
 8433    ) {
 8434        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8435            s.move_cursors_with(|map, head, _| {
 8436                (movement::next_word_end(map, head), SelectionGoal::None)
 8437            });
 8438        })
 8439    }
 8440
 8441    pub fn move_to_next_subword_end(
 8442        &mut self,
 8443        _: &MoveToNextSubwordEnd,
 8444        window: &mut Window,
 8445        cx: &mut Context<Self>,
 8446    ) {
 8447        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8448            s.move_cursors_with(|map, head, _| {
 8449                (movement::next_subword_end(map, head), SelectionGoal::None)
 8450            });
 8451        })
 8452    }
 8453
 8454    pub fn select_to_next_word_end(
 8455        &mut self,
 8456        _: &SelectToNextWordEnd,
 8457        window: &mut Window,
 8458        cx: &mut Context<Self>,
 8459    ) {
 8460        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8461            s.move_heads_with(|map, head, _| {
 8462                (movement::next_word_end(map, head), SelectionGoal::None)
 8463            });
 8464        })
 8465    }
 8466
 8467    pub fn select_to_next_subword_end(
 8468        &mut self,
 8469        _: &SelectToNextSubwordEnd,
 8470        window: &mut Window,
 8471        cx: &mut Context<Self>,
 8472    ) {
 8473        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8474            s.move_heads_with(|map, head, _| {
 8475                (movement::next_subword_end(map, head), SelectionGoal::None)
 8476            });
 8477        })
 8478    }
 8479
 8480    pub fn delete_to_next_word_end(
 8481        &mut self,
 8482        action: &DeleteToNextWordEnd,
 8483        window: &mut Window,
 8484        cx: &mut Context<Self>,
 8485    ) {
 8486        self.transact(window, cx, |this, window, cx| {
 8487            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8488                let line_mode = s.line_mode;
 8489                s.move_with(|map, selection| {
 8490                    if selection.is_empty() && !line_mode {
 8491                        let cursor = if action.ignore_newlines {
 8492                            movement::next_word_end(map, selection.head())
 8493                        } else {
 8494                            movement::next_word_end_or_newline(map, selection.head())
 8495                        };
 8496                        selection.set_head(cursor, SelectionGoal::None);
 8497                    }
 8498                });
 8499            });
 8500            this.insert("", window, cx);
 8501        });
 8502    }
 8503
 8504    pub fn delete_to_next_subword_end(
 8505        &mut self,
 8506        _: &DeleteToNextSubwordEnd,
 8507        window: &mut Window,
 8508        cx: &mut Context<Self>,
 8509    ) {
 8510        self.transact(window, cx, |this, window, cx| {
 8511            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8512                s.move_with(|map, selection| {
 8513                    if selection.is_empty() {
 8514                        let cursor = movement::next_subword_end(map, selection.head());
 8515                        selection.set_head(cursor, SelectionGoal::None);
 8516                    }
 8517                });
 8518            });
 8519            this.insert("", window, cx);
 8520        });
 8521    }
 8522
 8523    pub fn move_to_beginning_of_line(
 8524        &mut self,
 8525        action: &MoveToBeginningOfLine,
 8526        window: &mut Window,
 8527        cx: &mut Context<Self>,
 8528    ) {
 8529        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8530            s.move_cursors_with(|map, head, _| {
 8531                (
 8532                    movement::indented_line_beginning(map, head, action.stop_at_soft_wraps),
 8533                    SelectionGoal::None,
 8534                )
 8535            });
 8536        })
 8537    }
 8538
 8539    pub fn select_to_beginning_of_line(
 8540        &mut self,
 8541        action: &SelectToBeginningOfLine,
 8542        window: &mut Window,
 8543        cx: &mut Context<Self>,
 8544    ) {
 8545        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8546            s.move_heads_with(|map, head, _| {
 8547                (
 8548                    movement::indented_line_beginning(map, head, action.stop_at_soft_wraps),
 8549                    SelectionGoal::None,
 8550                )
 8551            });
 8552        });
 8553    }
 8554
 8555    pub fn delete_to_beginning_of_line(
 8556        &mut self,
 8557        _: &DeleteToBeginningOfLine,
 8558        window: &mut Window,
 8559        cx: &mut Context<Self>,
 8560    ) {
 8561        self.transact(window, cx, |this, window, cx| {
 8562            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8563                s.move_with(|_, selection| {
 8564                    selection.reversed = true;
 8565                });
 8566            });
 8567
 8568            this.select_to_beginning_of_line(
 8569                &SelectToBeginningOfLine {
 8570                    stop_at_soft_wraps: false,
 8571                },
 8572                window,
 8573                cx,
 8574            );
 8575            this.backspace(&Backspace, window, cx);
 8576        });
 8577    }
 8578
 8579    pub fn move_to_end_of_line(
 8580        &mut self,
 8581        action: &MoveToEndOfLine,
 8582        window: &mut Window,
 8583        cx: &mut Context<Self>,
 8584    ) {
 8585        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8586            s.move_cursors_with(|map, head, _| {
 8587                (
 8588                    movement::line_end(map, head, action.stop_at_soft_wraps),
 8589                    SelectionGoal::None,
 8590                )
 8591            });
 8592        })
 8593    }
 8594
 8595    pub fn select_to_end_of_line(
 8596        &mut self,
 8597        action: &SelectToEndOfLine,
 8598        window: &mut Window,
 8599        cx: &mut Context<Self>,
 8600    ) {
 8601        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8602            s.move_heads_with(|map, head, _| {
 8603                (
 8604                    movement::line_end(map, head, action.stop_at_soft_wraps),
 8605                    SelectionGoal::None,
 8606                )
 8607            });
 8608        })
 8609    }
 8610
 8611    pub fn delete_to_end_of_line(
 8612        &mut self,
 8613        _: &DeleteToEndOfLine,
 8614        window: &mut Window,
 8615        cx: &mut Context<Self>,
 8616    ) {
 8617        self.transact(window, cx, |this, window, cx| {
 8618            this.select_to_end_of_line(
 8619                &SelectToEndOfLine {
 8620                    stop_at_soft_wraps: false,
 8621                },
 8622                window,
 8623                cx,
 8624            );
 8625            this.delete(&Delete, window, cx);
 8626        });
 8627    }
 8628
 8629    pub fn cut_to_end_of_line(
 8630        &mut self,
 8631        _: &CutToEndOfLine,
 8632        window: &mut Window,
 8633        cx: &mut Context<Self>,
 8634    ) {
 8635        self.transact(window, cx, |this, window, cx| {
 8636            this.select_to_end_of_line(
 8637                &SelectToEndOfLine {
 8638                    stop_at_soft_wraps: false,
 8639                },
 8640                window,
 8641                cx,
 8642            );
 8643            this.cut(&Cut, window, cx);
 8644        });
 8645    }
 8646
 8647    pub fn move_to_start_of_paragraph(
 8648        &mut self,
 8649        _: &MoveToStartOfParagraph,
 8650        window: &mut Window,
 8651        cx: &mut Context<Self>,
 8652    ) {
 8653        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 8654            cx.propagate();
 8655            return;
 8656        }
 8657
 8658        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8659            s.move_with(|map, selection| {
 8660                selection.collapse_to(
 8661                    movement::start_of_paragraph(map, selection.head(), 1),
 8662                    SelectionGoal::None,
 8663                )
 8664            });
 8665        })
 8666    }
 8667
 8668    pub fn move_to_end_of_paragraph(
 8669        &mut self,
 8670        _: &MoveToEndOfParagraph,
 8671        window: &mut Window,
 8672        cx: &mut Context<Self>,
 8673    ) {
 8674        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 8675            cx.propagate();
 8676            return;
 8677        }
 8678
 8679        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8680            s.move_with(|map, selection| {
 8681                selection.collapse_to(
 8682                    movement::end_of_paragraph(map, selection.head(), 1),
 8683                    SelectionGoal::None,
 8684                )
 8685            });
 8686        })
 8687    }
 8688
 8689    pub fn select_to_start_of_paragraph(
 8690        &mut self,
 8691        _: &SelectToStartOfParagraph,
 8692        window: &mut Window,
 8693        cx: &mut Context<Self>,
 8694    ) {
 8695        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 8696            cx.propagate();
 8697            return;
 8698        }
 8699
 8700        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8701            s.move_heads_with(|map, head, _| {
 8702                (
 8703                    movement::start_of_paragraph(map, head, 1),
 8704                    SelectionGoal::None,
 8705                )
 8706            });
 8707        })
 8708    }
 8709
 8710    pub fn select_to_end_of_paragraph(
 8711        &mut self,
 8712        _: &SelectToEndOfParagraph,
 8713        window: &mut Window,
 8714        cx: &mut Context<Self>,
 8715    ) {
 8716        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 8717            cx.propagate();
 8718            return;
 8719        }
 8720
 8721        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8722            s.move_heads_with(|map, head, _| {
 8723                (
 8724                    movement::end_of_paragraph(map, head, 1),
 8725                    SelectionGoal::None,
 8726                )
 8727            });
 8728        })
 8729    }
 8730
 8731    pub fn move_to_beginning(
 8732        &mut self,
 8733        _: &MoveToBeginning,
 8734        window: &mut Window,
 8735        cx: &mut Context<Self>,
 8736    ) {
 8737        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 8738            cx.propagate();
 8739            return;
 8740        }
 8741
 8742        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8743            s.select_ranges(vec![0..0]);
 8744        });
 8745    }
 8746
 8747    pub fn select_to_beginning(
 8748        &mut self,
 8749        _: &SelectToBeginning,
 8750        window: &mut Window,
 8751        cx: &mut Context<Self>,
 8752    ) {
 8753        let mut selection = self.selections.last::<Point>(cx);
 8754        selection.set_head(Point::zero(), SelectionGoal::None);
 8755
 8756        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8757            s.select(vec![selection]);
 8758        });
 8759    }
 8760
 8761    pub fn move_to_end(&mut self, _: &MoveToEnd, window: &mut Window, cx: &mut Context<Self>) {
 8762        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 8763            cx.propagate();
 8764            return;
 8765        }
 8766
 8767        let cursor = self.buffer.read(cx).read(cx).len();
 8768        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8769            s.select_ranges(vec![cursor..cursor])
 8770        });
 8771    }
 8772
 8773    pub fn set_nav_history(&mut self, nav_history: Option<ItemNavHistory>) {
 8774        self.nav_history = nav_history;
 8775    }
 8776
 8777    pub fn nav_history(&self) -> Option<&ItemNavHistory> {
 8778        self.nav_history.as_ref()
 8779    }
 8780
 8781    fn push_to_nav_history(
 8782        &mut self,
 8783        cursor_anchor: Anchor,
 8784        new_position: Option<Point>,
 8785        cx: &mut Context<Self>,
 8786    ) {
 8787        if let Some(nav_history) = self.nav_history.as_mut() {
 8788            let buffer = self.buffer.read(cx).read(cx);
 8789            let cursor_position = cursor_anchor.to_point(&buffer);
 8790            let scroll_state = self.scroll_manager.anchor();
 8791            let scroll_top_row = scroll_state.top_row(&buffer);
 8792            drop(buffer);
 8793
 8794            if let Some(new_position) = new_position {
 8795                let row_delta = (new_position.row as i64 - cursor_position.row as i64).abs();
 8796                if row_delta < MIN_NAVIGATION_HISTORY_ROW_DELTA {
 8797                    return;
 8798                }
 8799            }
 8800
 8801            nav_history.push(
 8802                Some(NavigationData {
 8803                    cursor_anchor,
 8804                    cursor_position,
 8805                    scroll_anchor: scroll_state,
 8806                    scroll_top_row,
 8807                }),
 8808                cx,
 8809            );
 8810        }
 8811    }
 8812
 8813    pub fn select_to_end(&mut self, _: &SelectToEnd, window: &mut Window, cx: &mut Context<Self>) {
 8814        let buffer = self.buffer.read(cx).snapshot(cx);
 8815        let mut selection = self.selections.first::<usize>(cx);
 8816        selection.set_head(buffer.len(), SelectionGoal::None);
 8817        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8818            s.select(vec![selection]);
 8819        });
 8820    }
 8821
 8822    pub fn select_all(&mut self, _: &SelectAll, window: &mut Window, cx: &mut Context<Self>) {
 8823        let end = self.buffer.read(cx).read(cx).len();
 8824        self.change_selections(None, window, cx, |s| {
 8825            s.select_ranges(vec![0..end]);
 8826        });
 8827    }
 8828
 8829    pub fn select_line(&mut self, _: &SelectLine, window: &mut Window, cx: &mut Context<Self>) {
 8830        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8831        let mut selections = self.selections.all::<Point>(cx);
 8832        let max_point = display_map.buffer_snapshot.max_point();
 8833        for selection in &mut selections {
 8834            let rows = selection.spanned_rows(true, &display_map);
 8835            selection.start = Point::new(rows.start.0, 0);
 8836            selection.end = cmp::min(max_point, Point::new(rows.end.0, 0));
 8837            selection.reversed = false;
 8838        }
 8839        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8840            s.select(selections);
 8841        });
 8842    }
 8843
 8844    pub fn split_selection_into_lines(
 8845        &mut self,
 8846        _: &SplitSelectionIntoLines,
 8847        window: &mut Window,
 8848        cx: &mut Context<Self>,
 8849    ) {
 8850        let mut to_unfold = Vec::new();
 8851        let mut new_selection_ranges = Vec::new();
 8852        {
 8853            let selections = self.selections.all::<Point>(cx);
 8854            let buffer = self.buffer.read(cx).read(cx);
 8855            for selection in selections {
 8856                for row in selection.start.row..selection.end.row {
 8857                    let cursor = Point::new(row, buffer.line_len(MultiBufferRow(row)));
 8858                    new_selection_ranges.push(cursor..cursor);
 8859                }
 8860                new_selection_ranges.push(selection.end..selection.end);
 8861                to_unfold.push(selection.start..selection.end);
 8862            }
 8863        }
 8864        self.unfold_ranges(&to_unfold, true, true, cx);
 8865        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8866            s.select_ranges(new_selection_ranges);
 8867        });
 8868    }
 8869
 8870    pub fn add_selection_above(
 8871        &mut self,
 8872        _: &AddSelectionAbove,
 8873        window: &mut Window,
 8874        cx: &mut Context<Self>,
 8875    ) {
 8876        self.add_selection(true, window, cx);
 8877    }
 8878
 8879    pub fn add_selection_below(
 8880        &mut self,
 8881        _: &AddSelectionBelow,
 8882        window: &mut Window,
 8883        cx: &mut Context<Self>,
 8884    ) {
 8885        self.add_selection(false, window, cx);
 8886    }
 8887
 8888    fn add_selection(&mut self, above: bool, window: &mut Window, cx: &mut Context<Self>) {
 8889        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8890        let mut selections = self.selections.all::<Point>(cx);
 8891        let text_layout_details = self.text_layout_details(window);
 8892        let mut state = self.add_selections_state.take().unwrap_or_else(|| {
 8893            let oldest_selection = selections.iter().min_by_key(|s| s.id).unwrap().clone();
 8894            let range = oldest_selection.display_range(&display_map).sorted();
 8895
 8896            let start_x = display_map.x_for_display_point(range.start, &text_layout_details);
 8897            let end_x = display_map.x_for_display_point(range.end, &text_layout_details);
 8898            let positions = start_x.min(end_x)..start_x.max(end_x);
 8899
 8900            selections.clear();
 8901            let mut stack = Vec::new();
 8902            for row in range.start.row().0..=range.end.row().0 {
 8903                if let Some(selection) = self.selections.build_columnar_selection(
 8904                    &display_map,
 8905                    DisplayRow(row),
 8906                    &positions,
 8907                    oldest_selection.reversed,
 8908                    &text_layout_details,
 8909                ) {
 8910                    stack.push(selection.id);
 8911                    selections.push(selection);
 8912                }
 8913            }
 8914
 8915            if above {
 8916                stack.reverse();
 8917            }
 8918
 8919            AddSelectionsState { above, stack }
 8920        });
 8921
 8922        let last_added_selection = *state.stack.last().unwrap();
 8923        let mut new_selections = Vec::new();
 8924        if above == state.above {
 8925            let end_row = if above {
 8926                DisplayRow(0)
 8927            } else {
 8928                display_map.max_point().row()
 8929            };
 8930
 8931            'outer: for selection in selections {
 8932                if selection.id == last_added_selection {
 8933                    let range = selection.display_range(&display_map).sorted();
 8934                    debug_assert_eq!(range.start.row(), range.end.row());
 8935                    let mut row = range.start.row();
 8936                    let positions =
 8937                        if let SelectionGoal::HorizontalRange { start, end } = selection.goal {
 8938                            px(start)..px(end)
 8939                        } else {
 8940                            let start_x =
 8941                                display_map.x_for_display_point(range.start, &text_layout_details);
 8942                            let end_x =
 8943                                display_map.x_for_display_point(range.end, &text_layout_details);
 8944                            start_x.min(end_x)..start_x.max(end_x)
 8945                        };
 8946
 8947                    while row != end_row {
 8948                        if above {
 8949                            row.0 -= 1;
 8950                        } else {
 8951                            row.0 += 1;
 8952                        }
 8953
 8954                        if let Some(new_selection) = self.selections.build_columnar_selection(
 8955                            &display_map,
 8956                            row,
 8957                            &positions,
 8958                            selection.reversed,
 8959                            &text_layout_details,
 8960                        ) {
 8961                            state.stack.push(new_selection.id);
 8962                            if above {
 8963                                new_selections.push(new_selection);
 8964                                new_selections.push(selection);
 8965                            } else {
 8966                                new_selections.push(selection);
 8967                                new_selections.push(new_selection);
 8968                            }
 8969
 8970                            continue 'outer;
 8971                        }
 8972                    }
 8973                }
 8974
 8975                new_selections.push(selection);
 8976            }
 8977        } else {
 8978            new_selections = selections;
 8979            new_selections.retain(|s| s.id != last_added_selection);
 8980            state.stack.pop();
 8981        }
 8982
 8983        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8984            s.select(new_selections);
 8985        });
 8986        if state.stack.len() > 1 {
 8987            self.add_selections_state = Some(state);
 8988        }
 8989    }
 8990
 8991    pub fn select_next_match_internal(
 8992        &mut self,
 8993        display_map: &DisplaySnapshot,
 8994        replace_newest: bool,
 8995        autoscroll: Option<Autoscroll>,
 8996        window: &mut Window,
 8997        cx: &mut Context<Self>,
 8998    ) -> Result<()> {
 8999        fn select_next_match_ranges(
 9000            this: &mut Editor,
 9001            range: Range<usize>,
 9002            replace_newest: bool,
 9003            auto_scroll: Option<Autoscroll>,
 9004            window: &mut Window,
 9005            cx: &mut Context<Editor>,
 9006        ) {
 9007            this.unfold_ranges(&[range.clone()], false, true, cx);
 9008            this.change_selections(auto_scroll, window, cx, |s| {
 9009                if replace_newest {
 9010                    s.delete(s.newest_anchor().id);
 9011                }
 9012                s.insert_range(range.clone());
 9013            });
 9014        }
 9015
 9016        let buffer = &display_map.buffer_snapshot;
 9017        let mut selections = self.selections.all::<usize>(cx);
 9018        if let Some(mut select_next_state) = self.select_next_state.take() {
 9019            let query = &select_next_state.query;
 9020            if !select_next_state.done {
 9021                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
 9022                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
 9023                let mut next_selected_range = None;
 9024
 9025                let bytes_after_last_selection =
 9026                    buffer.bytes_in_range(last_selection.end..buffer.len());
 9027                let bytes_before_first_selection = buffer.bytes_in_range(0..first_selection.start);
 9028                let query_matches = query
 9029                    .stream_find_iter(bytes_after_last_selection)
 9030                    .map(|result| (last_selection.end, result))
 9031                    .chain(
 9032                        query
 9033                            .stream_find_iter(bytes_before_first_selection)
 9034                            .map(|result| (0, result)),
 9035                    );
 9036
 9037                for (start_offset, query_match) in query_matches {
 9038                    let query_match = query_match.unwrap(); // can only fail due to I/O
 9039                    let offset_range =
 9040                        start_offset + query_match.start()..start_offset + query_match.end();
 9041                    let display_range = offset_range.start.to_display_point(display_map)
 9042                        ..offset_range.end.to_display_point(display_map);
 9043
 9044                    if !select_next_state.wordwise
 9045                        || (!movement::is_inside_word(display_map, display_range.start)
 9046                            && !movement::is_inside_word(display_map, display_range.end))
 9047                    {
 9048                        // TODO: This is n^2, because we might check all the selections
 9049                        if !selections
 9050                            .iter()
 9051                            .any(|selection| selection.range().overlaps(&offset_range))
 9052                        {
 9053                            next_selected_range = Some(offset_range);
 9054                            break;
 9055                        }
 9056                    }
 9057                }
 9058
 9059                if let Some(next_selected_range) = next_selected_range {
 9060                    select_next_match_ranges(
 9061                        self,
 9062                        next_selected_range,
 9063                        replace_newest,
 9064                        autoscroll,
 9065                        window,
 9066                        cx,
 9067                    );
 9068                } else {
 9069                    select_next_state.done = true;
 9070                }
 9071            }
 9072
 9073            self.select_next_state = Some(select_next_state);
 9074        } else {
 9075            let mut only_carets = true;
 9076            let mut same_text_selected = true;
 9077            let mut selected_text = None;
 9078
 9079            let mut selections_iter = selections.iter().peekable();
 9080            while let Some(selection) = selections_iter.next() {
 9081                if selection.start != selection.end {
 9082                    only_carets = false;
 9083                }
 9084
 9085                if same_text_selected {
 9086                    if selected_text.is_none() {
 9087                        selected_text =
 9088                            Some(buffer.text_for_range(selection.range()).collect::<String>());
 9089                    }
 9090
 9091                    if let Some(next_selection) = selections_iter.peek() {
 9092                        if next_selection.range().len() == selection.range().len() {
 9093                            let next_selected_text = buffer
 9094                                .text_for_range(next_selection.range())
 9095                                .collect::<String>();
 9096                            if Some(next_selected_text) != selected_text {
 9097                                same_text_selected = false;
 9098                                selected_text = None;
 9099                            }
 9100                        } else {
 9101                            same_text_selected = false;
 9102                            selected_text = None;
 9103                        }
 9104                    }
 9105                }
 9106            }
 9107
 9108            if only_carets {
 9109                for selection in &mut selections {
 9110                    let word_range = movement::surrounding_word(
 9111                        display_map,
 9112                        selection.start.to_display_point(display_map),
 9113                    );
 9114                    selection.start = word_range.start.to_offset(display_map, Bias::Left);
 9115                    selection.end = word_range.end.to_offset(display_map, Bias::Left);
 9116                    selection.goal = SelectionGoal::None;
 9117                    selection.reversed = false;
 9118                    select_next_match_ranges(
 9119                        self,
 9120                        selection.start..selection.end,
 9121                        replace_newest,
 9122                        autoscroll,
 9123                        window,
 9124                        cx,
 9125                    );
 9126                }
 9127
 9128                if selections.len() == 1 {
 9129                    let selection = selections
 9130                        .last()
 9131                        .expect("ensured that there's only one selection");
 9132                    let query = buffer
 9133                        .text_for_range(selection.start..selection.end)
 9134                        .collect::<String>();
 9135                    let is_empty = query.is_empty();
 9136                    let select_state = SelectNextState {
 9137                        query: AhoCorasick::new(&[query])?,
 9138                        wordwise: true,
 9139                        done: is_empty,
 9140                    };
 9141                    self.select_next_state = Some(select_state);
 9142                } else {
 9143                    self.select_next_state = None;
 9144                }
 9145            } else if let Some(selected_text) = selected_text {
 9146                self.select_next_state = Some(SelectNextState {
 9147                    query: AhoCorasick::new(&[selected_text])?,
 9148                    wordwise: false,
 9149                    done: false,
 9150                });
 9151                self.select_next_match_internal(
 9152                    display_map,
 9153                    replace_newest,
 9154                    autoscroll,
 9155                    window,
 9156                    cx,
 9157                )?;
 9158            }
 9159        }
 9160        Ok(())
 9161    }
 9162
 9163    pub fn select_all_matches(
 9164        &mut self,
 9165        _action: &SelectAllMatches,
 9166        window: &mut Window,
 9167        cx: &mut Context<Self>,
 9168    ) -> Result<()> {
 9169        self.push_to_selection_history();
 9170        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 9171
 9172        self.select_next_match_internal(&display_map, false, None, window, cx)?;
 9173        let Some(select_next_state) = self.select_next_state.as_mut() else {
 9174            return Ok(());
 9175        };
 9176        if select_next_state.done {
 9177            return Ok(());
 9178        }
 9179
 9180        let mut new_selections = self.selections.all::<usize>(cx);
 9181
 9182        let buffer = &display_map.buffer_snapshot;
 9183        let query_matches = select_next_state
 9184            .query
 9185            .stream_find_iter(buffer.bytes_in_range(0..buffer.len()));
 9186
 9187        for query_match in query_matches {
 9188            let query_match = query_match.unwrap(); // can only fail due to I/O
 9189            let offset_range = query_match.start()..query_match.end();
 9190            let display_range = offset_range.start.to_display_point(&display_map)
 9191                ..offset_range.end.to_display_point(&display_map);
 9192
 9193            if !select_next_state.wordwise
 9194                || (!movement::is_inside_word(&display_map, display_range.start)
 9195                    && !movement::is_inside_word(&display_map, display_range.end))
 9196            {
 9197                self.selections.change_with(cx, |selections| {
 9198                    new_selections.push(Selection {
 9199                        id: selections.new_selection_id(),
 9200                        start: offset_range.start,
 9201                        end: offset_range.end,
 9202                        reversed: false,
 9203                        goal: SelectionGoal::None,
 9204                    });
 9205                });
 9206            }
 9207        }
 9208
 9209        new_selections.sort_by_key(|selection| selection.start);
 9210        let mut ix = 0;
 9211        while ix + 1 < new_selections.len() {
 9212            let current_selection = &new_selections[ix];
 9213            let next_selection = &new_selections[ix + 1];
 9214            if current_selection.range().overlaps(&next_selection.range()) {
 9215                if current_selection.id < next_selection.id {
 9216                    new_selections.remove(ix + 1);
 9217                } else {
 9218                    new_selections.remove(ix);
 9219                }
 9220            } else {
 9221                ix += 1;
 9222            }
 9223        }
 9224
 9225        let reversed = self.selections.oldest::<usize>(cx).reversed;
 9226
 9227        for selection in new_selections.iter_mut() {
 9228            selection.reversed = reversed;
 9229        }
 9230
 9231        select_next_state.done = true;
 9232        self.unfold_ranges(
 9233            &new_selections
 9234                .iter()
 9235                .map(|selection| selection.range())
 9236                .collect::<Vec<_>>(),
 9237            false,
 9238            false,
 9239            cx,
 9240        );
 9241        self.change_selections(Some(Autoscroll::fit()), window, cx, |selections| {
 9242            selections.select(new_selections)
 9243        });
 9244
 9245        Ok(())
 9246    }
 9247
 9248    pub fn select_next(
 9249        &mut self,
 9250        action: &SelectNext,
 9251        window: &mut Window,
 9252        cx: &mut Context<Self>,
 9253    ) -> Result<()> {
 9254        self.push_to_selection_history();
 9255        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 9256        self.select_next_match_internal(
 9257            &display_map,
 9258            action.replace_newest,
 9259            Some(Autoscroll::newest()),
 9260            window,
 9261            cx,
 9262        )?;
 9263        Ok(())
 9264    }
 9265
 9266    pub fn select_previous(
 9267        &mut self,
 9268        action: &SelectPrevious,
 9269        window: &mut Window,
 9270        cx: &mut Context<Self>,
 9271    ) -> Result<()> {
 9272        self.push_to_selection_history();
 9273        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 9274        let buffer = &display_map.buffer_snapshot;
 9275        let mut selections = self.selections.all::<usize>(cx);
 9276        if let Some(mut select_prev_state) = self.select_prev_state.take() {
 9277            let query = &select_prev_state.query;
 9278            if !select_prev_state.done {
 9279                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
 9280                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
 9281                let mut next_selected_range = None;
 9282                // When we're iterating matches backwards, the oldest match will actually be the furthest one in the buffer.
 9283                let bytes_before_last_selection =
 9284                    buffer.reversed_bytes_in_range(0..last_selection.start);
 9285                let bytes_after_first_selection =
 9286                    buffer.reversed_bytes_in_range(first_selection.end..buffer.len());
 9287                let query_matches = query
 9288                    .stream_find_iter(bytes_before_last_selection)
 9289                    .map(|result| (last_selection.start, result))
 9290                    .chain(
 9291                        query
 9292                            .stream_find_iter(bytes_after_first_selection)
 9293                            .map(|result| (buffer.len(), result)),
 9294                    );
 9295                for (end_offset, query_match) in query_matches {
 9296                    let query_match = query_match.unwrap(); // can only fail due to I/O
 9297                    let offset_range =
 9298                        end_offset - query_match.end()..end_offset - query_match.start();
 9299                    let display_range = offset_range.start.to_display_point(&display_map)
 9300                        ..offset_range.end.to_display_point(&display_map);
 9301
 9302                    if !select_prev_state.wordwise
 9303                        || (!movement::is_inside_word(&display_map, display_range.start)
 9304                            && !movement::is_inside_word(&display_map, display_range.end))
 9305                    {
 9306                        next_selected_range = Some(offset_range);
 9307                        break;
 9308                    }
 9309                }
 9310
 9311                if let Some(next_selected_range) = next_selected_range {
 9312                    self.unfold_ranges(&[next_selected_range.clone()], false, true, cx);
 9313                    self.change_selections(Some(Autoscroll::newest()), window, cx, |s| {
 9314                        if action.replace_newest {
 9315                            s.delete(s.newest_anchor().id);
 9316                        }
 9317                        s.insert_range(next_selected_range);
 9318                    });
 9319                } else {
 9320                    select_prev_state.done = true;
 9321                }
 9322            }
 9323
 9324            self.select_prev_state = Some(select_prev_state);
 9325        } else {
 9326            let mut only_carets = true;
 9327            let mut same_text_selected = true;
 9328            let mut selected_text = None;
 9329
 9330            let mut selections_iter = selections.iter().peekable();
 9331            while let Some(selection) = selections_iter.next() {
 9332                if selection.start != selection.end {
 9333                    only_carets = false;
 9334                }
 9335
 9336                if same_text_selected {
 9337                    if selected_text.is_none() {
 9338                        selected_text =
 9339                            Some(buffer.text_for_range(selection.range()).collect::<String>());
 9340                    }
 9341
 9342                    if let Some(next_selection) = selections_iter.peek() {
 9343                        if next_selection.range().len() == selection.range().len() {
 9344                            let next_selected_text = buffer
 9345                                .text_for_range(next_selection.range())
 9346                                .collect::<String>();
 9347                            if Some(next_selected_text) != selected_text {
 9348                                same_text_selected = false;
 9349                                selected_text = None;
 9350                            }
 9351                        } else {
 9352                            same_text_selected = false;
 9353                            selected_text = None;
 9354                        }
 9355                    }
 9356                }
 9357            }
 9358
 9359            if only_carets {
 9360                for selection in &mut selections {
 9361                    let word_range = movement::surrounding_word(
 9362                        &display_map,
 9363                        selection.start.to_display_point(&display_map),
 9364                    );
 9365                    selection.start = word_range.start.to_offset(&display_map, Bias::Left);
 9366                    selection.end = word_range.end.to_offset(&display_map, Bias::Left);
 9367                    selection.goal = SelectionGoal::None;
 9368                    selection.reversed = false;
 9369                }
 9370                if selections.len() == 1 {
 9371                    let selection = selections
 9372                        .last()
 9373                        .expect("ensured that there's only one selection");
 9374                    let query = buffer
 9375                        .text_for_range(selection.start..selection.end)
 9376                        .collect::<String>();
 9377                    let is_empty = query.is_empty();
 9378                    let select_state = SelectNextState {
 9379                        query: AhoCorasick::new(&[query.chars().rev().collect::<String>()])?,
 9380                        wordwise: true,
 9381                        done: is_empty,
 9382                    };
 9383                    self.select_prev_state = Some(select_state);
 9384                } else {
 9385                    self.select_prev_state = None;
 9386                }
 9387
 9388                self.unfold_ranges(
 9389                    &selections.iter().map(|s| s.range()).collect::<Vec<_>>(),
 9390                    false,
 9391                    true,
 9392                    cx,
 9393                );
 9394                self.change_selections(Some(Autoscroll::newest()), window, cx, |s| {
 9395                    s.select(selections);
 9396                });
 9397            } else if let Some(selected_text) = selected_text {
 9398                self.select_prev_state = Some(SelectNextState {
 9399                    query: AhoCorasick::new(&[selected_text.chars().rev().collect::<String>()])?,
 9400                    wordwise: false,
 9401                    done: false,
 9402                });
 9403                self.select_previous(action, window, cx)?;
 9404            }
 9405        }
 9406        Ok(())
 9407    }
 9408
 9409    pub fn toggle_comments(
 9410        &mut self,
 9411        action: &ToggleComments,
 9412        window: &mut Window,
 9413        cx: &mut Context<Self>,
 9414    ) {
 9415        if self.read_only(cx) {
 9416            return;
 9417        }
 9418        let text_layout_details = &self.text_layout_details(window);
 9419        self.transact(window, cx, |this, window, cx| {
 9420            let mut selections = this.selections.all::<MultiBufferPoint>(cx);
 9421            let mut edits = Vec::new();
 9422            let mut selection_edit_ranges = Vec::new();
 9423            let mut last_toggled_row = None;
 9424            let snapshot = this.buffer.read(cx).read(cx);
 9425            let empty_str: Arc<str> = Arc::default();
 9426            let mut suffixes_inserted = Vec::new();
 9427            let ignore_indent = action.ignore_indent;
 9428
 9429            fn comment_prefix_range(
 9430                snapshot: &MultiBufferSnapshot,
 9431                row: MultiBufferRow,
 9432                comment_prefix: &str,
 9433                comment_prefix_whitespace: &str,
 9434                ignore_indent: bool,
 9435            ) -> Range<Point> {
 9436                let indent_size = if ignore_indent {
 9437                    0
 9438                } else {
 9439                    snapshot.indent_size_for_line(row).len
 9440                };
 9441
 9442                let start = Point::new(row.0, indent_size);
 9443
 9444                let mut line_bytes = snapshot
 9445                    .bytes_in_range(start..snapshot.max_point())
 9446                    .flatten()
 9447                    .copied();
 9448
 9449                // If this line currently begins with the line comment prefix, then record
 9450                // the range containing the prefix.
 9451                if line_bytes
 9452                    .by_ref()
 9453                    .take(comment_prefix.len())
 9454                    .eq(comment_prefix.bytes())
 9455                {
 9456                    // Include any whitespace that matches the comment prefix.
 9457                    let matching_whitespace_len = line_bytes
 9458                        .zip(comment_prefix_whitespace.bytes())
 9459                        .take_while(|(a, b)| a == b)
 9460                        .count() as u32;
 9461                    let end = Point::new(
 9462                        start.row,
 9463                        start.column + comment_prefix.len() as u32 + matching_whitespace_len,
 9464                    );
 9465                    start..end
 9466                } else {
 9467                    start..start
 9468                }
 9469            }
 9470
 9471            fn comment_suffix_range(
 9472                snapshot: &MultiBufferSnapshot,
 9473                row: MultiBufferRow,
 9474                comment_suffix: &str,
 9475                comment_suffix_has_leading_space: bool,
 9476            ) -> Range<Point> {
 9477                let end = Point::new(row.0, snapshot.line_len(row));
 9478                let suffix_start_column = end.column.saturating_sub(comment_suffix.len() as u32);
 9479
 9480                let mut line_end_bytes = snapshot
 9481                    .bytes_in_range(Point::new(end.row, suffix_start_column.saturating_sub(1))..end)
 9482                    .flatten()
 9483                    .copied();
 9484
 9485                let leading_space_len = if suffix_start_column > 0
 9486                    && line_end_bytes.next() == Some(b' ')
 9487                    && comment_suffix_has_leading_space
 9488                {
 9489                    1
 9490                } else {
 9491                    0
 9492                };
 9493
 9494                // If this line currently begins with the line comment prefix, then record
 9495                // the range containing the prefix.
 9496                if line_end_bytes.by_ref().eq(comment_suffix.bytes()) {
 9497                    let start = Point::new(end.row, suffix_start_column - leading_space_len);
 9498                    start..end
 9499                } else {
 9500                    end..end
 9501                }
 9502            }
 9503
 9504            // TODO: Handle selections that cross excerpts
 9505            for selection in &mut selections {
 9506                let start_column = snapshot
 9507                    .indent_size_for_line(MultiBufferRow(selection.start.row))
 9508                    .len;
 9509                let language = if let Some(language) =
 9510                    snapshot.language_scope_at(Point::new(selection.start.row, start_column))
 9511                {
 9512                    language
 9513                } else {
 9514                    continue;
 9515                };
 9516
 9517                selection_edit_ranges.clear();
 9518
 9519                // If multiple selections contain a given row, avoid processing that
 9520                // row more than once.
 9521                let mut start_row = MultiBufferRow(selection.start.row);
 9522                if last_toggled_row == Some(start_row) {
 9523                    start_row = start_row.next_row();
 9524                }
 9525                let end_row =
 9526                    if selection.end.row > selection.start.row && selection.end.column == 0 {
 9527                        MultiBufferRow(selection.end.row - 1)
 9528                    } else {
 9529                        MultiBufferRow(selection.end.row)
 9530                    };
 9531                last_toggled_row = Some(end_row);
 9532
 9533                if start_row > end_row {
 9534                    continue;
 9535                }
 9536
 9537                // If the language has line comments, toggle those.
 9538                let mut full_comment_prefixes = language.line_comment_prefixes().to_vec();
 9539
 9540                // If ignore_indent is set, trim spaces from the right side of all full_comment_prefixes
 9541                if ignore_indent {
 9542                    full_comment_prefixes = full_comment_prefixes
 9543                        .into_iter()
 9544                        .map(|s| Arc::from(s.trim_end()))
 9545                        .collect();
 9546                }
 9547
 9548                if !full_comment_prefixes.is_empty() {
 9549                    let first_prefix = full_comment_prefixes
 9550                        .first()
 9551                        .expect("prefixes is non-empty");
 9552                    let prefix_trimmed_lengths = full_comment_prefixes
 9553                        .iter()
 9554                        .map(|p| p.trim_end_matches(' ').len())
 9555                        .collect::<SmallVec<[usize; 4]>>();
 9556
 9557                    let mut all_selection_lines_are_comments = true;
 9558
 9559                    for row in start_row.0..=end_row.0 {
 9560                        let row = MultiBufferRow(row);
 9561                        if start_row < end_row && snapshot.is_line_blank(row) {
 9562                            continue;
 9563                        }
 9564
 9565                        let prefix_range = full_comment_prefixes
 9566                            .iter()
 9567                            .zip(prefix_trimmed_lengths.iter().copied())
 9568                            .map(|(prefix, trimmed_prefix_len)| {
 9569                                comment_prefix_range(
 9570                                    snapshot.deref(),
 9571                                    row,
 9572                                    &prefix[..trimmed_prefix_len],
 9573                                    &prefix[trimmed_prefix_len..],
 9574                                    ignore_indent,
 9575                                )
 9576                            })
 9577                            .max_by_key(|range| range.end.column - range.start.column)
 9578                            .expect("prefixes is non-empty");
 9579
 9580                        if prefix_range.is_empty() {
 9581                            all_selection_lines_are_comments = false;
 9582                        }
 9583
 9584                        selection_edit_ranges.push(prefix_range);
 9585                    }
 9586
 9587                    if all_selection_lines_are_comments {
 9588                        edits.extend(
 9589                            selection_edit_ranges
 9590                                .iter()
 9591                                .cloned()
 9592                                .map(|range| (range, empty_str.clone())),
 9593                        );
 9594                    } else {
 9595                        let min_column = selection_edit_ranges
 9596                            .iter()
 9597                            .map(|range| range.start.column)
 9598                            .min()
 9599                            .unwrap_or(0);
 9600                        edits.extend(selection_edit_ranges.iter().map(|range| {
 9601                            let position = Point::new(range.start.row, min_column);
 9602                            (position..position, first_prefix.clone())
 9603                        }));
 9604                    }
 9605                } else if let Some((full_comment_prefix, comment_suffix)) =
 9606                    language.block_comment_delimiters()
 9607                {
 9608                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
 9609                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
 9610                    let prefix_range = comment_prefix_range(
 9611                        snapshot.deref(),
 9612                        start_row,
 9613                        comment_prefix,
 9614                        comment_prefix_whitespace,
 9615                        ignore_indent,
 9616                    );
 9617                    let suffix_range = comment_suffix_range(
 9618                        snapshot.deref(),
 9619                        end_row,
 9620                        comment_suffix.trim_start_matches(' '),
 9621                        comment_suffix.starts_with(' '),
 9622                    );
 9623
 9624                    if prefix_range.is_empty() || suffix_range.is_empty() {
 9625                        edits.push((
 9626                            prefix_range.start..prefix_range.start,
 9627                            full_comment_prefix.clone(),
 9628                        ));
 9629                        edits.push((suffix_range.end..suffix_range.end, comment_suffix.clone()));
 9630                        suffixes_inserted.push((end_row, comment_suffix.len()));
 9631                    } else {
 9632                        edits.push((prefix_range, empty_str.clone()));
 9633                        edits.push((suffix_range, empty_str.clone()));
 9634                    }
 9635                } else {
 9636                    continue;
 9637                }
 9638            }
 9639
 9640            drop(snapshot);
 9641            this.buffer.update(cx, |buffer, cx| {
 9642                buffer.edit(edits, None, cx);
 9643            });
 9644
 9645            // Adjust selections so that they end before any comment suffixes that
 9646            // were inserted.
 9647            let mut suffixes_inserted = suffixes_inserted.into_iter().peekable();
 9648            let mut selections = this.selections.all::<Point>(cx);
 9649            let snapshot = this.buffer.read(cx).read(cx);
 9650            for selection in &mut selections {
 9651                while let Some((row, suffix_len)) = suffixes_inserted.peek().copied() {
 9652                    match row.cmp(&MultiBufferRow(selection.end.row)) {
 9653                        Ordering::Less => {
 9654                            suffixes_inserted.next();
 9655                            continue;
 9656                        }
 9657                        Ordering::Greater => break,
 9658                        Ordering::Equal => {
 9659                            if selection.end.column == snapshot.line_len(row) {
 9660                                if selection.is_empty() {
 9661                                    selection.start.column -= suffix_len as u32;
 9662                                }
 9663                                selection.end.column -= suffix_len as u32;
 9664                            }
 9665                            break;
 9666                        }
 9667                    }
 9668                }
 9669            }
 9670
 9671            drop(snapshot);
 9672            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9673                s.select(selections)
 9674            });
 9675
 9676            let selections = this.selections.all::<Point>(cx);
 9677            let selections_on_single_row = selections.windows(2).all(|selections| {
 9678                selections[0].start.row == selections[1].start.row
 9679                    && selections[0].end.row == selections[1].end.row
 9680                    && selections[0].start.row == selections[0].end.row
 9681            });
 9682            let selections_selecting = selections
 9683                .iter()
 9684                .any(|selection| selection.start != selection.end);
 9685            let advance_downwards = action.advance_downwards
 9686                && selections_on_single_row
 9687                && !selections_selecting
 9688                && !matches!(this.mode, EditorMode::SingleLine { .. });
 9689
 9690            if advance_downwards {
 9691                let snapshot = this.buffer.read(cx).snapshot(cx);
 9692
 9693                this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9694                    s.move_cursors_with(|display_snapshot, display_point, _| {
 9695                        let mut point = display_point.to_point(display_snapshot);
 9696                        point.row += 1;
 9697                        point = snapshot.clip_point(point, Bias::Left);
 9698                        let display_point = point.to_display_point(display_snapshot);
 9699                        let goal = SelectionGoal::HorizontalPosition(
 9700                            display_snapshot
 9701                                .x_for_display_point(display_point, text_layout_details)
 9702                                .into(),
 9703                        );
 9704                        (display_point, goal)
 9705                    })
 9706                });
 9707            }
 9708        });
 9709    }
 9710
 9711    pub fn select_enclosing_symbol(
 9712        &mut self,
 9713        _: &SelectEnclosingSymbol,
 9714        window: &mut Window,
 9715        cx: &mut Context<Self>,
 9716    ) {
 9717        let buffer = self.buffer.read(cx).snapshot(cx);
 9718        let old_selections = self.selections.all::<usize>(cx).into_boxed_slice();
 9719
 9720        fn update_selection(
 9721            selection: &Selection<usize>,
 9722            buffer_snap: &MultiBufferSnapshot,
 9723        ) -> Option<Selection<usize>> {
 9724            let cursor = selection.head();
 9725            let (_buffer_id, symbols) = buffer_snap.symbols_containing(cursor, None)?;
 9726            for symbol in symbols.iter().rev() {
 9727                let start = symbol.range.start.to_offset(buffer_snap);
 9728                let end = symbol.range.end.to_offset(buffer_snap);
 9729                let new_range = start..end;
 9730                if start < selection.start || end > selection.end {
 9731                    return Some(Selection {
 9732                        id: selection.id,
 9733                        start: new_range.start,
 9734                        end: new_range.end,
 9735                        goal: SelectionGoal::None,
 9736                        reversed: selection.reversed,
 9737                    });
 9738                }
 9739            }
 9740            None
 9741        }
 9742
 9743        let mut selected_larger_symbol = false;
 9744        let new_selections = old_selections
 9745            .iter()
 9746            .map(|selection| match update_selection(selection, &buffer) {
 9747                Some(new_selection) => {
 9748                    if new_selection.range() != selection.range() {
 9749                        selected_larger_symbol = true;
 9750                    }
 9751                    new_selection
 9752                }
 9753                None => selection.clone(),
 9754            })
 9755            .collect::<Vec<_>>();
 9756
 9757        if selected_larger_symbol {
 9758            self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9759                s.select(new_selections);
 9760            });
 9761        }
 9762    }
 9763
 9764    pub fn select_larger_syntax_node(
 9765        &mut self,
 9766        _: &SelectLargerSyntaxNode,
 9767        window: &mut Window,
 9768        cx: &mut Context<Self>,
 9769    ) {
 9770        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 9771        let buffer = self.buffer.read(cx).snapshot(cx);
 9772        let old_selections = self.selections.all::<usize>(cx).into_boxed_slice();
 9773
 9774        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
 9775        let mut selected_larger_node = false;
 9776        let new_selections = old_selections
 9777            .iter()
 9778            .map(|selection| {
 9779                let old_range = selection.start..selection.end;
 9780                let mut new_range = old_range.clone();
 9781                let mut new_node = None;
 9782                while let Some((node, containing_range)) = buffer.syntax_ancestor(new_range.clone())
 9783                {
 9784                    new_node = Some(node);
 9785                    new_range = containing_range;
 9786                    if !display_map.intersects_fold(new_range.start)
 9787                        && !display_map.intersects_fold(new_range.end)
 9788                    {
 9789                        break;
 9790                    }
 9791                }
 9792
 9793                if let Some(node) = new_node {
 9794                    // Log the ancestor, to support using this action as a way to explore TreeSitter
 9795                    // nodes. Parent and grandparent are also logged because this operation will not
 9796                    // visit nodes that have the same range as their parent.
 9797                    log::info!("Node: {node:?}");
 9798                    let parent = node.parent();
 9799                    log::info!("Parent: {parent:?}");
 9800                    let grandparent = parent.and_then(|x| x.parent());
 9801                    log::info!("Grandparent: {grandparent:?}");
 9802                }
 9803
 9804                selected_larger_node |= new_range != old_range;
 9805                Selection {
 9806                    id: selection.id,
 9807                    start: new_range.start,
 9808                    end: new_range.end,
 9809                    goal: SelectionGoal::None,
 9810                    reversed: selection.reversed,
 9811                }
 9812            })
 9813            .collect::<Vec<_>>();
 9814
 9815        if selected_larger_node {
 9816            stack.push(old_selections);
 9817            self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9818                s.select(new_selections);
 9819            });
 9820        }
 9821        self.select_larger_syntax_node_stack = stack;
 9822    }
 9823
 9824    pub fn select_smaller_syntax_node(
 9825        &mut self,
 9826        _: &SelectSmallerSyntaxNode,
 9827        window: &mut Window,
 9828        cx: &mut Context<Self>,
 9829    ) {
 9830        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
 9831        if let Some(selections) = stack.pop() {
 9832            self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9833                s.select(selections.to_vec());
 9834            });
 9835        }
 9836        self.select_larger_syntax_node_stack = stack;
 9837    }
 9838
 9839    fn refresh_runnables(&mut self, window: &mut Window, cx: &mut Context<Self>) -> Task<()> {
 9840        if !EditorSettings::get_global(cx).gutter.runnables {
 9841            self.clear_tasks();
 9842            return Task::ready(());
 9843        }
 9844        let project = self.project.as_ref().map(Entity::downgrade);
 9845        cx.spawn_in(window, |this, mut cx| async move {
 9846            cx.background_executor().timer(UPDATE_DEBOUNCE).await;
 9847            let Some(project) = project.and_then(|p| p.upgrade()) else {
 9848                return;
 9849            };
 9850            let Ok(display_snapshot) = this.update(&mut cx, |this, cx| {
 9851                this.display_map.update(cx, |map, cx| map.snapshot(cx))
 9852            }) else {
 9853                return;
 9854            };
 9855
 9856            let hide_runnables = project
 9857                .update(&mut cx, |project, cx| {
 9858                    // Do not display any test indicators in non-dev server remote projects.
 9859                    project.is_via_collab() && project.ssh_connection_string(cx).is_none()
 9860                })
 9861                .unwrap_or(true);
 9862            if hide_runnables {
 9863                return;
 9864            }
 9865            let new_rows =
 9866                cx.background_executor()
 9867                    .spawn({
 9868                        let snapshot = display_snapshot.clone();
 9869                        async move {
 9870                            Self::fetch_runnable_ranges(&snapshot, Anchor::min()..Anchor::max())
 9871                        }
 9872                    })
 9873                    .await;
 9874
 9875            let rows = Self::runnable_rows(project, display_snapshot, new_rows, cx.clone());
 9876            this.update(&mut cx, |this, _| {
 9877                this.clear_tasks();
 9878                for (key, value) in rows {
 9879                    this.insert_tasks(key, value);
 9880                }
 9881            })
 9882            .ok();
 9883        })
 9884    }
 9885    fn fetch_runnable_ranges(
 9886        snapshot: &DisplaySnapshot,
 9887        range: Range<Anchor>,
 9888    ) -> Vec<language::RunnableRange> {
 9889        snapshot.buffer_snapshot.runnable_ranges(range).collect()
 9890    }
 9891
 9892    fn runnable_rows(
 9893        project: Entity<Project>,
 9894        snapshot: DisplaySnapshot,
 9895        runnable_ranges: Vec<RunnableRange>,
 9896        mut cx: AsyncWindowContext,
 9897    ) -> Vec<((BufferId, u32), RunnableTasks)> {
 9898        runnable_ranges
 9899            .into_iter()
 9900            .filter_map(|mut runnable| {
 9901                let tasks = cx
 9902                    .update(|_, cx| Self::templates_with_tags(&project, &mut runnable.runnable, cx))
 9903                    .ok()?;
 9904                if tasks.is_empty() {
 9905                    return None;
 9906                }
 9907
 9908                let point = runnable.run_range.start.to_point(&snapshot.buffer_snapshot);
 9909
 9910                let row = snapshot
 9911                    .buffer_snapshot
 9912                    .buffer_line_for_row(MultiBufferRow(point.row))?
 9913                    .1
 9914                    .start
 9915                    .row;
 9916
 9917                let context_range =
 9918                    BufferOffset(runnable.full_range.start)..BufferOffset(runnable.full_range.end);
 9919                Some((
 9920                    (runnable.buffer_id, row),
 9921                    RunnableTasks {
 9922                        templates: tasks,
 9923                        offset: MultiBufferOffset(runnable.run_range.start),
 9924                        context_range,
 9925                        column: point.column,
 9926                        extra_variables: runnable.extra_captures,
 9927                    },
 9928                ))
 9929            })
 9930            .collect()
 9931    }
 9932
 9933    fn templates_with_tags(
 9934        project: &Entity<Project>,
 9935        runnable: &mut Runnable,
 9936        cx: &mut App,
 9937    ) -> Vec<(TaskSourceKind, TaskTemplate)> {
 9938        let (inventory, worktree_id, file) = project.read_with(cx, |project, cx| {
 9939            let (worktree_id, file) = project
 9940                .buffer_for_id(runnable.buffer, cx)
 9941                .and_then(|buffer| buffer.read(cx).file())
 9942                .map(|file| (file.worktree_id(cx), file.clone()))
 9943                .unzip();
 9944
 9945            (
 9946                project.task_store().read(cx).task_inventory().cloned(),
 9947                worktree_id,
 9948                file,
 9949            )
 9950        });
 9951
 9952        let tags = mem::take(&mut runnable.tags);
 9953        let mut tags: Vec<_> = tags
 9954            .into_iter()
 9955            .flat_map(|tag| {
 9956                let tag = tag.0.clone();
 9957                inventory
 9958                    .as_ref()
 9959                    .into_iter()
 9960                    .flat_map(|inventory| {
 9961                        inventory.read(cx).list_tasks(
 9962                            file.clone(),
 9963                            Some(runnable.language.clone()),
 9964                            worktree_id,
 9965                            cx,
 9966                        )
 9967                    })
 9968                    .filter(move |(_, template)| {
 9969                        template.tags.iter().any(|source_tag| source_tag == &tag)
 9970                    })
 9971            })
 9972            .sorted_by_key(|(kind, _)| kind.to_owned())
 9973            .collect();
 9974        if let Some((leading_tag_source, _)) = tags.first() {
 9975            // Strongest source wins; if we have worktree tag binding, prefer that to
 9976            // global and language bindings;
 9977            // if we have a global binding, prefer that to language binding.
 9978            let first_mismatch = tags
 9979                .iter()
 9980                .position(|(tag_source, _)| tag_source != leading_tag_source);
 9981            if let Some(index) = first_mismatch {
 9982                tags.truncate(index);
 9983            }
 9984        }
 9985
 9986        tags
 9987    }
 9988
 9989    pub fn move_to_enclosing_bracket(
 9990        &mut self,
 9991        _: &MoveToEnclosingBracket,
 9992        window: &mut Window,
 9993        cx: &mut Context<Self>,
 9994    ) {
 9995        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9996            s.move_offsets_with(|snapshot, selection| {
 9997                let Some(enclosing_bracket_ranges) =
 9998                    snapshot.enclosing_bracket_ranges(selection.start..selection.end)
 9999                else {
10000                    return;
10001                };
10002
10003                let mut best_length = usize::MAX;
10004                let mut best_inside = false;
10005                let mut best_in_bracket_range = false;
10006                let mut best_destination = None;
10007                for (open, close) in enclosing_bracket_ranges {
10008                    let close = close.to_inclusive();
10009                    let length = close.end() - open.start;
10010                    let inside = selection.start >= open.end && selection.end <= *close.start();
10011                    let in_bracket_range = open.to_inclusive().contains(&selection.head())
10012                        || close.contains(&selection.head());
10013
10014                    // If best is next to a bracket and current isn't, skip
10015                    if !in_bracket_range && best_in_bracket_range {
10016                        continue;
10017                    }
10018
10019                    // Prefer smaller lengths unless best is inside and current isn't
10020                    if length > best_length && (best_inside || !inside) {
10021                        continue;
10022                    }
10023
10024                    best_length = length;
10025                    best_inside = inside;
10026                    best_in_bracket_range = in_bracket_range;
10027                    best_destination = Some(
10028                        if close.contains(&selection.start) && close.contains(&selection.end) {
10029                            if inside {
10030                                open.end
10031                            } else {
10032                                open.start
10033                            }
10034                        } else if inside {
10035                            *close.start()
10036                        } else {
10037                            *close.end()
10038                        },
10039                    );
10040                }
10041
10042                if let Some(destination) = best_destination {
10043                    selection.collapse_to(destination, SelectionGoal::None);
10044                }
10045            })
10046        });
10047    }
10048
10049    pub fn undo_selection(
10050        &mut self,
10051        _: &UndoSelection,
10052        window: &mut Window,
10053        cx: &mut Context<Self>,
10054    ) {
10055        self.end_selection(window, cx);
10056        self.selection_history.mode = SelectionHistoryMode::Undoing;
10057        if let Some(entry) = self.selection_history.undo_stack.pop_back() {
10058            self.change_selections(None, window, cx, |s| {
10059                s.select_anchors(entry.selections.to_vec())
10060            });
10061            self.select_next_state = entry.select_next_state;
10062            self.select_prev_state = entry.select_prev_state;
10063            self.add_selections_state = entry.add_selections_state;
10064            self.request_autoscroll(Autoscroll::newest(), cx);
10065        }
10066        self.selection_history.mode = SelectionHistoryMode::Normal;
10067    }
10068
10069    pub fn redo_selection(
10070        &mut self,
10071        _: &RedoSelection,
10072        window: &mut Window,
10073        cx: &mut Context<Self>,
10074    ) {
10075        self.end_selection(window, cx);
10076        self.selection_history.mode = SelectionHistoryMode::Redoing;
10077        if let Some(entry) = self.selection_history.redo_stack.pop_back() {
10078            self.change_selections(None, window, cx, |s| {
10079                s.select_anchors(entry.selections.to_vec())
10080            });
10081            self.select_next_state = entry.select_next_state;
10082            self.select_prev_state = entry.select_prev_state;
10083            self.add_selections_state = entry.add_selections_state;
10084            self.request_autoscroll(Autoscroll::newest(), cx);
10085        }
10086        self.selection_history.mode = SelectionHistoryMode::Normal;
10087    }
10088
10089    pub fn expand_excerpts(
10090        &mut self,
10091        action: &ExpandExcerpts,
10092        _: &mut Window,
10093        cx: &mut Context<Self>,
10094    ) {
10095        self.expand_excerpts_for_direction(action.lines, ExpandExcerptDirection::UpAndDown, cx)
10096    }
10097
10098    pub fn expand_excerpts_down(
10099        &mut self,
10100        action: &ExpandExcerptsDown,
10101        _: &mut Window,
10102        cx: &mut Context<Self>,
10103    ) {
10104        self.expand_excerpts_for_direction(action.lines, ExpandExcerptDirection::Down, cx)
10105    }
10106
10107    pub fn expand_excerpts_up(
10108        &mut self,
10109        action: &ExpandExcerptsUp,
10110        _: &mut Window,
10111        cx: &mut Context<Self>,
10112    ) {
10113        self.expand_excerpts_for_direction(action.lines, ExpandExcerptDirection::Up, cx)
10114    }
10115
10116    pub fn expand_excerpts_for_direction(
10117        &mut self,
10118        lines: u32,
10119        direction: ExpandExcerptDirection,
10120
10121        cx: &mut Context<Self>,
10122    ) {
10123        let selections = self.selections.disjoint_anchors();
10124
10125        let lines = if lines == 0 {
10126            EditorSettings::get_global(cx).expand_excerpt_lines
10127        } else {
10128            lines
10129        };
10130
10131        self.buffer.update(cx, |buffer, cx| {
10132            let snapshot = buffer.snapshot(cx);
10133            let mut excerpt_ids = selections
10134                .iter()
10135                .flat_map(|selection| snapshot.excerpt_ids_for_range(selection.range()))
10136                .collect::<Vec<_>>();
10137            excerpt_ids.sort();
10138            excerpt_ids.dedup();
10139            buffer.expand_excerpts(excerpt_ids, lines, direction, cx)
10140        })
10141    }
10142
10143    pub fn expand_excerpt(
10144        &mut self,
10145        excerpt: ExcerptId,
10146        direction: ExpandExcerptDirection,
10147        cx: &mut Context<Self>,
10148    ) {
10149        let lines = EditorSettings::get_global(cx).expand_excerpt_lines;
10150        self.buffer.update(cx, |buffer, cx| {
10151            buffer.expand_excerpts([excerpt], lines, direction, cx)
10152        })
10153    }
10154
10155    pub fn go_to_singleton_buffer_point(
10156        &mut self,
10157        point: Point,
10158        window: &mut Window,
10159        cx: &mut Context<Self>,
10160    ) {
10161        self.go_to_singleton_buffer_range(point..point, window, cx);
10162    }
10163
10164    pub fn go_to_singleton_buffer_range(
10165        &mut self,
10166        range: Range<Point>,
10167        window: &mut Window,
10168        cx: &mut Context<Self>,
10169    ) {
10170        let multibuffer = self.buffer().read(cx);
10171        let Some(buffer) = multibuffer.as_singleton() else {
10172            return;
10173        };
10174        let Some(start) = multibuffer.buffer_point_to_anchor(&buffer, range.start, cx) else {
10175            return;
10176        };
10177        let Some(end) = multibuffer.buffer_point_to_anchor(&buffer, range.end, cx) else {
10178            return;
10179        };
10180        self.change_selections(Some(Autoscroll::center()), window, cx, |s| {
10181            s.select_anchor_ranges([start..end])
10182        });
10183    }
10184
10185    fn go_to_diagnostic(
10186        &mut self,
10187        _: &GoToDiagnostic,
10188        window: &mut Window,
10189        cx: &mut Context<Self>,
10190    ) {
10191        self.go_to_diagnostic_impl(Direction::Next, window, cx)
10192    }
10193
10194    fn go_to_prev_diagnostic(
10195        &mut self,
10196        _: &GoToPrevDiagnostic,
10197        window: &mut Window,
10198        cx: &mut Context<Self>,
10199    ) {
10200        self.go_to_diagnostic_impl(Direction::Prev, window, cx)
10201    }
10202
10203    pub fn go_to_diagnostic_impl(
10204        &mut self,
10205        direction: Direction,
10206        window: &mut Window,
10207        cx: &mut Context<Self>,
10208    ) {
10209        let buffer = self.buffer.read(cx).snapshot(cx);
10210        let selection = self.selections.newest::<usize>(cx);
10211
10212        // If there is an active Diagnostic Popover jump to its diagnostic instead.
10213        if direction == Direction::Next {
10214            if let Some(popover) = self.hover_state.diagnostic_popover.as_ref() {
10215                let Some(buffer_id) = popover.local_diagnostic.range.start.buffer_id else {
10216                    return;
10217                };
10218                self.activate_diagnostics(
10219                    buffer_id,
10220                    popover.local_diagnostic.diagnostic.group_id,
10221                    window,
10222                    cx,
10223                );
10224                if let Some(active_diagnostics) = self.active_diagnostics.as_ref() {
10225                    let primary_range_start = active_diagnostics.primary_range.start;
10226                    self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10227                        let mut new_selection = s.newest_anchor().clone();
10228                        new_selection.collapse_to(primary_range_start, SelectionGoal::None);
10229                        s.select_anchors(vec![new_selection.clone()]);
10230                    });
10231                    self.refresh_inline_completion(false, true, window, cx);
10232                }
10233                return;
10234            }
10235        }
10236
10237        let mut active_primary_range = self.active_diagnostics.as_ref().map(|active_diagnostics| {
10238            active_diagnostics
10239                .primary_range
10240                .to_offset(&buffer)
10241                .to_inclusive()
10242        });
10243        let mut search_start = if let Some(active_primary_range) = active_primary_range.as_ref() {
10244            if active_primary_range.contains(&selection.head()) {
10245                *active_primary_range.start()
10246            } else {
10247                selection.head()
10248            }
10249        } else {
10250            selection.head()
10251        };
10252        let snapshot = self.snapshot(window, cx);
10253        loop {
10254            let mut diagnostics;
10255            if direction == Direction::Prev {
10256                diagnostics = buffer
10257                    .diagnostics_in_range::<usize>(0..search_start)
10258                    .collect::<Vec<_>>();
10259                diagnostics.reverse();
10260            } else {
10261                diagnostics = buffer
10262                    .diagnostics_in_range::<usize>(search_start..buffer.len())
10263                    .collect::<Vec<_>>();
10264            };
10265            let group = diagnostics
10266                .into_iter()
10267                .filter(|diagnostic| !snapshot.intersects_fold(diagnostic.range.start))
10268                // relies on diagnostics_in_range to return diagnostics with the same starting range to
10269                // be sorted in a stable way
10270                // skip until we are at current active diagnostic, if it exists
10271                .skip_while(|entry| {
10272                    let is_in_range = match direction {
10273                        Direction::Prev => entry.range.end > search_start,
10274                        Direction::Next => entry.range.start < search_start,
10275                    };
10276                    is_in_range
10277                        && self
10278                            .active_diagnostics
10279                            .as_ref()
10280                            .is_some_and(|a| a.group_id != entry.diagnostic.group_id)
10281                })
10282                .find_map(|entry| {
10283                    if entry.diagnostic.is_primary
10284                        && entry.diagnostic.severity <= DiagnosticSeverity::WARNING
10285                        && entry.range.start != entry.range.end
10286                    {
10287                        let entry_group = entry.diagnostic.group_id;
10288                        let in_next_group = self.active_diagnostics.as_ref().map_or(
10289                            true,
10290                            |active| match direction {
10291                                Direction::Prev => {
10292                                    entry_group != active.group_id
10293                                        && (active.group_id == 0 || entry_group < active.group_id)
10294                                }
10295                                Direction::Next => {
10296                                    entry_group != active.group_id
10297                                        && (entry_group == 0 || entry_group > active.group_id)
10298                                }
10299                            },
10300                        );
10301                        if in_next_group {
10302                            return Some((entry.range, entry.diagnostic.group_id));
10303                        }
10304                    }
10305                    None
10306                });
10307
10308            if let Some((primary_range, group_id)) = group {
10309                let Some(buffer_id) = buffer.anchor_after(primary_range.start).buffer_id else {
10310                    return;
10311                };
10312                self.activate_diagnostics(buffer_id, group_id, window, cx);
10313                if self.active_diagnostics.is_some() {
10314                    self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10315                        s.select(vec![Selection {
10316                            id: selection.id,
10317                            start: primary_range.start,
10318                            end: primary_range.start,
10319                            reversed: false,
10320                            goal: SelectionGoal::None,
10321                        }]);
10322                    });
10323                    self.refresh_inline_completion(false, true, window, cx);
10324                }
10325                break;
10326            } else {
10327                // Cycle around to the start of the buffer, potentially moving back to the start of
10328                // the currently active diagnostic.
10329                active_primary_range.take();
10330                if direction == Direction::Prev {
10331                    if search_start == buffer.len() {
10332                        break;
10333                    } else {
10334                        search_start = buffer.len();
10335                    }
10336                } else if search_start == 0 {
10337                    break;
10338                } else {
10339                    search_start = 0;
10340                }
10341            }
10342        }
10343    }
10344
10345    fn go_to_next_hunk(&mut self, _: &GoToHunk, window: &mut Window, cx: &mut Context<Self>) {
10346        let snapshot = self.snapshot(window, cx);
10347        let selection = self.selections.newest::<Point>(cx);
10348        self.go_to_hunk_after_position(&snapshot, selection.head(), window, cx);
10349    }
10350
10351    fn go_to_hunk_after_position(
10352        &mut self,
10353        snapshot: &EditorSnapshot,
10354        position: Point,
10355        window: &mut Window,
10356        cx: &mut Context<Editor>,
10357    ) -> Option<MultiBufferDiffHunk> {
10358        let mut hunk = snapshot
10359            .buffer_snapshot
10360            .diff_hunks_in_range(position..snapshot.buffer_snapshot.max_point())
10361            .find(|hunk| hunk.row_range.start.0 > position.row);
10362        if hunk.is_none() {
10363            hunk = snapshot
10364                .buffer_snapshot
10365                .diff_hunks_in_range(Point::zero()..position)
10366                .find(|hunk| hunk.row_range.end.0 < position.row)
10367        }
10368        if let Some(hunk) = &hunk {
10369            let destination = Point::new(hunk.row_range.start.0, 0);
10370            self.unfold_ranges(&[destination..destination], false, false, cx);
10371            self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10372                s.select_ranges(vec![destination..destination]);
10373            });
10374        }
10375
10376        hunk
10377    }
10378
10379    fn go_to_prev_hunk(&mut self, _: &GoToPrevHunk, window: &mut Window, cx: &mut Context<Self>) {
10380        let snapshot = self.snapshot(window, cx);
10381        let selection = self.selections.newest::<Point>(cx);
10382        self.go_to_hunk_before_position(&snapshot, selection.head(), window, cx);
10383    }
10384
10385    fn go_to_hunk_before_position(
10386        &mut self,
10387        snapshot: &EditorSnapshot,
10388        position: Point,
10389        window: &mut Window,
10390        cx: &mut Context<Editor>,
10391    ) -> Option<MultiBufferDiffHunk> {
10392        let mut hunk = snapshot.buffer_snapshot.diff_hunk_before(position);
10393        if hunk.is_none() {
10394            hunk = snapshot.buffer_snapshot.diff_hunk_before(Point::MAX);
10395        }
10396        if let Some(hunk) = &hunk {
10397            let destination = Point::new(hunk.row_range.start.0, 0);
10398            self.unfold_ranges(&[destination..destination], false, false, cx);
10399            self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10400                s.select_ranges(vec![destination..destination]);
10401            });
10402        }
10403
10404        hunk
10405    }
10406
10407    pub fn go_to_definition(
10408        &mut self,
10409        _: &GoToDefinition,
10410        window: &mut Window,
10411        cx: &mut Context<Self>,
10412    ) -> Task<Result<Navigated>> {
10413        let definition =
10414            self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, false, window, cx);
10415        cx.spawn_in(window, |editor, mut cx| async move {
10416            if definition.await? == Navigated::Yes {
10417                return Ok(Navigated::Yes);
10418            }
10419            match editor.update_in(&mut cx, |editor, window, cx| {
10420                editor.find_all_references(&FindAllReferences, window, cx)
10421            })? {
10422                Some(references) => references.await,
10423                None => Ok(Navigated::No),
10424            }
10425        })
10426    }
10427
10428    pub fn go_to_declaration(
10429        &mut self,
10430        _: &GoToDeclaration,
10431        window: &mut Window,
10432        cx: &mut Context<Self>,
10433    ) -> Task<Result<Navigated>> {
10434        self.go_to_definition_of_kind(GotoDefinitionKind::Declaration, false, window, cx)
10435    }
10436
10437    pub fn go_to_declaration_split(
10438        &mut self,
10439        _: &GoToDeclaration,
10440        window: &mut Window,
10441        cx: &mut Context<Self>,
10442    ) -> Task<Result<Navigated>> {
10443        self.go_to_definition_of_kind(GotoDefinitionKind::Declaration, true, window, cx)
10444    }
10445
10446    pub fn go_to_implementation(
10447        &mut self,
10448        _: &GoToImplementation,
10449        window: &mut Window,
10450        cx: &mut Context<Self>,
10451    ) -> Task<Result<Navigated>> {
10452        self.go_to_definition_of_kind(GotoDefinitionKind::Implementation, false, window, cx)
10453    }
10454
10455    pub fn go_to_implementation_split(
10456        &mut self,
10457        _: &GoToImplementationSplit,
10458        window: &mut Window,
10459        cx: &mut Context<Self>,
10460    ) -> Task<Result<Navigated>> {
10461        self.go_to_definition_of_kind(GotoDefinitionKind::Implementation, true, window, cx)
10462    }
10463
10464    pub fn go_to_type_definition(
10465        &mut self,
10466        _: &GoToTypeDefinition,
10467        window: &mut Window,
10468        cx: &mut Context<Self>,
10469    ) -> Task<Result<Navigated>> {
10470        self.go_to_definition_of_kind(GotoDefinitionKind::Type, false, window, cx)
10471    }
10472
10473    pub fn go_to_definition_split(
10474        &mut self,
10475        _: &GoToDefinitionSplit,
10476        window: &mut Window,
10477        cx: &mut Context<Self>,
10478    ) -> Task<Result<Navigated>> {
10479        self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, true, window, cx)
10480    }
10481
10482    pub fn go_to_type_definition_split(
10483        &mut self,
10484        _: &GoToTypeDefinitionSplit,
10485        window: &mut Window,
10486        cx: &mut Context<Self>,
10487    ) -> Task<Result<Navigated>> {
10488        self.go_to_definition_of_kind(GotoDefinitionKind::Type, true, window, cx)
10489    }
10490
10491    fn go_to_definition_of_kind(
10492        &mut self,
10493        kind: GotoDefinitionKind,
10494        split: bool,
10495        window: &mut Window,
10496        cx: &mut Context<Self>,
10497    ) -> Task<Result<Navigated>> {
10498        let Some(provider) = self.semantics_provider.clone() else {
10499            return Task::ready(Ok(Navigated::No));
10500        };
10501        let head = self.selections.newest::<usize>(cx).head();
10502        let buffer = self.buffer.read(cx);
10503        let (buffer, head) = if let Some(text_anchor) = buffer.text_anchor_for_position(head, cx) {
10504            text_anchor
10505        } else {
10506            return Task::ready(Ok(Navigated::No));
10507        };
10508
10509        let Some(definitions) = provider.definitions(&buffer, head, kind, cx) else {
10510            return Task::ready(Ok(Navigated::No));
10511        };
10512
10513        cx.spawn_in(window, |editor, mut cx| async move {
10514            let definitions = definitions.await?;
10515            let navigated = editor
10516                .update_in(&mut cx, |editor, window, cx| {
10517                    editor.navigate_to_hover_links(
10518                        Some(kind),
10519                        definitions
10520                            .into_iter()
10521                            .filter(|location| {
10522                                hover_links::exclude_link_to_position(&buffer, &head, location, cx)
10523                            })
10524                            .map(HoverLink::Text)
10525                            .collect::<Vec<_>>(),
10526                        split,
10527                        window,
10528                        cx,
10529                    )
10530                })?
10531                .await?;
10532            anyhow::Ok(navigated)
10533        })
10534    }
10535
10536    pub fn open_url(&mut self, _: &OpenUrl, window: &mut Window, cx: &mut Context<Self>) {
10537        let selection = self.selections.newest_anchor();
10538        let head = selection.head();
10539        let tail = selection.tail();
10540
10541        let Some((buffer, start_position)) =
10542            self.buffer.read(cx).text_anchor_for_position(head, cx)
10543        else {
10544            return;
10545        };
10546
10547        let end_position = if head != tail {
10548            let Some((_, pos)) = self.buffer.read(cx).text_anchor_for_position(tail, cx) else {
10549                return;
10550            };
10551            Some(pos)
10552        } else {
10553            None
10554        };
10555
10556        let url_finder = cx.spawn_in(window, |editor, mut cx| async move {
10557            let url = if let Some(end_pos) = end_position {
10558                find_url_from_range(&buffer, start_position..end_pos, cx.clone())
10559            } else {
10560                find_url(&buffer, start_position, cx.clone()).map(|(_, url)| url)
10561            };
10562
10563            if let Some(url) = url {
10564                editor.update(&mut cx, |_, cx| {
10565                    cx.open_url(&url);
10566                })
10567            } else {
10568                Ok(())
10569            }
10570        });
10571
10572        url_finder.detach();
10573    }
10574
10575    pub fn open_selected_filename(
10576        &mut self,
10577        _: &OpenSelectedFilename,
10578        window: &mut Window,
10579        cx: &mut Context<Self>,
10580    ) {
10581        let Some(workspace) = self.workspace() else {
10582            return;
10583        };
10584
10585        let position = self.selections.newest_anchor().head();
10586
10587        let Some((buffer, buffer_position)) =
10588            self.buffer.read(cx).text_anchor_for_position(position, cx)
10589        else {
10590            return;
10591        };
10592
10593        let project = self.project.clone();
10594
10595        cx.spawn_in(window, |_, mut cx| async move {
10596            let result = find_file(&buffer, project, buffer_position, &mut cx).await;
10597
10598            if let Some((_, path)) = result {
10599                workspace
10600                    .update_in(&mut cx, |workspace, window, cx| {
10601                        workspace.open_resolved_path(path, window, cx)
10602                    })?
10603                    .await?;
10604            }
10605            anyhow::Ok(())
10606        })
10607        .detach();
10608    }
10609
10610    pub(crate) fn navigate_to_hover_links(
10611        &mut self,
10612        kind: Option<GotoDefinitionKind>,
10613        mut definitions: Vec<HoverLink>,
10614        split: bool,
10615        window: &mut Window,
10616        cx: &mut Context<Editor>,
10617    ) -> Task<Result<Navigated>> {
10618        // If there is one definition, just open it directly
10619        if definitions.len() == 1 {
10620            let definition = definitions.pop().unwrap();
10621
10622            enum TargetTaskResult {
10623                Location(Option<Location>),
10624                AlreadyNavigated,
10625            }
10626
10627            let target_task = match definition {
10628                HoverLink::Text(link) => {
10629                    Task::ready(anyhow::Ok(TargetTaskResult::Location(Some(link.target))))
10630                }
10631                HoverLink::InlayHint(lsp_location, server_id) => {
10632                    let computation =
10633                        self.compute_target_location(lsp_location, server_id, window, cx);
10634                    cx.background_executor().spawn(async move {
10635                        let location = computation.await?;
10636                        Ok(TargetTaskResult::Location(location))
10637                    })
10638                }
10639                HoverLink::Url(url) => {
10640                    cx.open_url(&url);
10641                    Task::ready(Ok(TargetTaskResult::AlreadyNavigated))
10642                }
10643                HoverLink::File(path) => {
10644                    if let Some(workspace) = self.workspace() {
10645                        cx.spawn_in(window, |_, mut cx| async move {
10646                            workspace
10647                                .update_in(&mut cx, |workspace, window, cx| {
10648                                    workspace.open_resolved_path(path, window, cx)
10649                                })?
10650                                .await
10651                                .map(|_| TargetTaskResult::AlreadyNavigated)
10652                        })
10653                    } else {
10654                        Task::ready(Ok(TargetTaskResult::Location(None)))
10655                    }
10656                }
10657            };
10658            cx.spawn_in(window, |editor, mut cx| async move {
10659                let target = match target_task.await.context("target resolution task")? {
10660                    TargetTaskResult::AlreadyNavigated => return Ok(Navigated::Yes),
10661                    TargetTaskResult::Location(None) => return Ok(Navigated::No),
10662                    TargetTaskResult::Location(Some(target)) => target,
10663                };
10664
10665                editor.update_in(&mut cx, |editor, window, cx| {
10666                    let Some(workspace) = editor.workspace() else {
10667                        return Navigated::No;
10668                    };
10669                    let pane = workspace.read(cx).active_pane().clone();
10670
10671                    let range = target.range.to_point(target.buffer.read(cx));
10672                    let range = editor.range_for_match(&range);
10673                    let range = collapse_multiline_range(range);
10674
10675                    if Some(&target.buffer) == editor.buffer.read(cx).as_singleton().as_ref() {
10676                        editor.go_to_singleton_buffer_range(range.clone(), window, cx);
10677                    } else {
10678                        window.defer(cx, move |window, cx| {
10679                            let target_editor: Entity<Self> =
10680                                workspace.update(cx, |workspace, cx| {
10681                                    let pane = if split {
10682                                        workspace.adjacent_pane(window, cx)
10683                                    } else {
10684                                        workspace.active_pane().clone()
10685                                    };
10686
10687                                    workspace.open_project_item(
10688                                        pane,
10689                                        target.buffer.clone(),
10690                                        true,
10691                                        true,
10692                                        window,
10693                                        cx,
10694                                    )
10695                                });
10696                            target_editor.update(cx, |target_editor, cx| {
10697                                // When selecting a definition in a different buffer, disable the nav history
10698                                // to avoid creating a history entry at the previous cursor location.
10699                                pane.update(cx, |pane, _| pane.disable_history());
10700                                target_editor.go_to_singleton_buffer_range(range, window, cx);
10701                                pane.update(cx, |pane, _| pane.enable_history());
10702                            });
10703                        });
10704                    }
10705                    Navigated::Yes
10706                })
10707            })
10708        } else if !definitions.is_empty() {
10709            cx.spawn_in(window, |editor, mut cx| async move {
10710                let (title, location_tasks, workspace) = editor
10711                    .update_in(&mut cx, |editor, window, cx| {
10712                        let tab_kind = match kind {
10713                            Some(GotoDefinitionKind::Implementation) => "Implementations",
10714                            _ => "Definitions",
10715                        };
10716                        let title = definitions
10717                            .iter()
10718                            .find_map(|definition| match definition {
10719                                HoverLink::Text(link) => link.origin.as_ref().map(|origin| {
10720                                    let buffer = origin.buffer.read(cx);
10721                                    format!(
10722                                        "{} for {}",
10723                                        tab_kind,
10724                                        buffer
10725                                            .text_for_range(origin.range.clone())
10726                                            .collect::<String>()
10727                                    )
10728                                }),
10729                                HoverLink::InlayHint(_, _) => None,
10730                                HoverLink::Url(_) => None,
10731                                HoverLink::File(_) => None,
10732                            })
10733                            .unwrap_or(tab_kind.to_string());
10734                        let location_tasks = definitions
10735                            .into_iter()
10736                            .map(|definition| match definition {
10737                                HoverLink::Text(link) => Task::ready(Ok(Some(link.target))),
10738                                HoverLink::InlayHint(lsp_location, server_id) => editor
10739                                    .compute_target_location(lsp_location, server_id, window, cx),
10740                                HoverLink::Url(_) => Task::ready(Ok(None)),
10741                                HoverLink::File(_) => Task::ready(Ok(None)),
10742                            })
10743                            .collect::<Vec<_>>();
10744                        (title, location_tasks, editor.workspace().clone())
10745                    })
10746                    .context("location tasks preparation")?;
10747
10748                let locations = future::join_all(location_tasks)
10749                    .await
10750                    .into_iter()
10751                    .filter_map(|location| location.transpose())
10752                    .collect::<Result<_>>()
10753                    .context("location tasks")?;
10754
10755                let Some(workspace) = workspace else {
10756                    return Ok(Navigated::No);
10757                };
10758                let opened = workspace
10759                    .update_in(&mut cx, |workspace, window, cx| {
10760                        Self::open_locations_in_multibuffer(
10761                            workspace,
10762                            locations,
10763                            title,
10764                            split,
10765                            MultibufferSelectionMode::First,
10766                            window,
10767                            cx,
10768                        )
10769                    })
10770                    .ok();
10771
10772                anyhow::Ok(Navigated::from_bool(opened.is_some()))
10773            })
10774        } else {
10775            Task::ready(Ok(Navigated::No))
10776        }
10777    }
10778
10779    fn compute_target_location(
10780        &self,
10781        lsp_location: lsp::Location,
10782        server_id: LanguageServerId,
10783        window: &mut Window,
10784        cx: &mut Context<Self>,
10785    ) -> Task<anyhow::Result<Option<Location>>> {
10786        let Some(project) = self.project.clone() else {
10787            return Task::ready(Ok(None));
10788        };
10789
10790        cx.spawn_in(window, move |editor, mut cx| async move {
10791            let location_task = editor.update(&mut cx, |_, cx| {
10792                project.update(cx, |project, cx| {
10793                    let language_server_name = project
10794                        .language_server_statuses(cx)
10795                        .find(|(id, _)| server_id == *id)
10796                        .map(|(_, status)| LanguageServerName::from(status.name.as_str()));
10797                    language_server_name.map(|language_server_name| {
10798                        project.open_local_buffer_via_lsp(
10799                            lsp_location.uri.clone(),
10800                            server_id,
10801                            language_server_name,
10802                            cx,
10803                        )
10804                    })
10805                })
10806            })?;
10807            let location = match location_task {
10808                Some(task) => Some({
10809                    let target_buffer_handle = task.await.context("open local buffer")?;
10810                    let range = target_buffer_handle.update(&mut cx, |target_buffer, _| {
10811                        let target_start = target_buffer
10812                            .clip_point_utf16(point_from_lsp(lsp_location.range.start), Bias::Left);
10813                        let target_end = target_buffer
10814                            .clip_point_utf16(point_from_lsp(lsp_location.range.end), Bias::Left);
10815                        target_buffer.anchor_after(target_start)
10816                            ..target_buffer.anchor_before(target_end)
10817                    })?;
10818                    Location {
10819                        buffer: target_buffer_handle,
10820                        range,
10821                    }
10822                }),
10823                None => None,
10824            };
10825            Ok(location)
10826        })
10827    }
10828
10829    pub fn find_all_references(
10830        &mut self,
10831        _: &FindAllReferences,
10832        window: &mut Window,
10833        cx: &mut Context<Self>,
10834    ) -> Option<Task<Result<Navigated>>> {
10835        let selection = self.selections.newest::<usize>(cx);
10836        let multi_buffer = self.buffer.read(cx);
10837        let head = selection.head();
10838
10839        let multi_buffer_snapshot = multi_buffer.snapshot(cx);
10840        let head_anchor = multi_buffer_snapshot.anchor_at(
10841            head,
10842            if head < selection.tail() {
10843                Bias::Right
10844            } else {
10845                Bias::Left
10846            },
10847        );
10848
10849        match self
10850            .find_all_references_task_sources
10851            .binary_search_by(|anchor| anchor.cmp(&head_anchor, &multi_buffer_snapshot))
10852        {
10853            Ok(_) => {
10854                log::info!(
10855                    "Ignoring repeated FindAllReferences invocation with the position of already running task"
10856                );
10857                return None;
10858            }
10859            Err(i) => {
10860                self.find_all_references_task_sources.insert(i, head_anchor);
10861            }
10862        }
10863
10864        let (buffer, head) = multi_buffer.text_anchor_for_position(head, cx)?;
10865        let workspace = self.workspace()?;
10866        let project = workspace.read(cx).project().clone();
10867        let references = project.update(cx, |project, cx| project.references(&buffer, head, cx));
10868        Some(cx.spawn_in(window, |editor, mut cx| async move {
10869            let _cleanup = defer({
10870                let mut cx = cx.clone();
10871                move || {
10872                    let _ = editor.update(&mut cx, |editor, _| {
10873                        if let Ok(i) =
10874                            editor
10875                                .find_all_references_task_sources
10876                                .binary_search_by(|anchor| {
10877                                    anchor.cmp(&head_anchor, &multi_buffer_snapshot)
10878                                })
10879                        {
10880                            editor.find_all_references_task_sources.remove(i);
10881                        }
10882                    });
10883                }
10884            });
10885
10886            let locations = references.await?;
10887            if locations.is_empty() {
10888                return anyhow::Ok(Navigated::No);
10889            }
10890
10891            workspace.update_in(&mut cx, |workspace, window, cx| {
10892                let title = locations
10893                    .first()
10894                    .as_ref()
10895                    .map(|location| {
10896                        let buffer = location.buffer.read(cx);
10897                        format!(
10898                            "References to `{}`",
10899                            buffer
10900                                .text_for_range(location.range.clone())
10901                                .collect::<String>()
10902                        )
10903                    })
10904                    .unwrap();
10905                Self::open_locations_in_multibuffer(
10906                    workspace,
10907                    locations,
10908                    title,
10909                    false,
10910                    MultibufferSelectionMode::First,
10911                    window,
10912                    cx,
10913                );
10914                Navigated::Yes
10915            })
10916        }))
10917    }
10918
10919    /// Opens a multibuffer with the given project locations in it
10920    pub fn open_locations_in_multibuffer(
10921        workspace: &mut Workspace,
10922        mut locations: Vec<Location>,
10923        title: String,
10924        split: bool,
10925        multibuffer_selection_mode: MultibufferSelectionMode,
10926        window: &mut Window,
10927        cx: &mut Context<Workspace>,
10928    ) {
10929        // If there are multiple definitions, open them in a multibuffer
10930        locations.sort_by_key(|location| location.buffer.read(cx).remote_id());
10931        let mut locations = locations.into_iter().peekable();
10932        let mut ranges = Vec::new();
10933        let capability = workspace.project().read(cx).capability();
10934
10935        let excerpt_buffer = cx.new(|cx| {
10936            let mut multibuffer = MultiBuffer::new(capability);
10937            while let Some(location) = locations.next() {
10938                let buffer = location.buffer.read(cx);
10939                let mut ranges_for_buffer = Vec::new();
10940                let range = location.range.to_offset(buffer);
10941                ranges_for_buffer.push(range.clone());
10942
10943                while let Some(next_location) = locations.peek() {
10944                    if next_location.buffer == location.buffer {
10945                        ranges_for_buffer.push(next_location.range.to_offset(buffer));
10946                        locations.next();
10947                    } else {
10948                        break;
10949                    }
10950                }
10951
10952                ranges_for_buffer.sort_by_key(|range| (range.start, Reverse(range.end)));
10953                ranges.extend(multibuffer.push_excerpts_with_context_lines(
10954                    location.buffer.clone(),
10955                    ranges_for_buffer,
10956                    DEFAULT_MULTIBUFFER_CONTEXT,
10957                    cx,
10958                ))
10959            }
10960
10961            multibuffer.with_title(title)
10962        });
10963
10964        let editor = cx.new(|cx| {
10965            Editor::for_multibuffer(
10966                excerpt_buffer,
10967                Some(workspace.project().clone()),
10968                true,
10969                window,
10970                cx,
10971            )
10972        });
10973        editor.update(cx, |editor, cx| {
10974            match multibuffer_selection_mode {
10975                MultibufferSelectionMode::First => {
10976                    if let Some(first_range) = ranges.first() {
10977                        editor.change_selections(None, window, cx, |selections| {
10978                            selections.clear_disjoint();
10979                            selections.select_anchor_ranges(std::iter::once(first_range.clone()));
10980                        });
10981                    }
10982                    editor.highlight_background::<Self>(
10983                        &ranges,
10984                        |theme| theme.editor_highlighted_line_background,
10985                        cx,
10986                    );
10987                }
10988                MultibufferSelectionMode::All => {
10989                    editor.change_selections(None, window, cx, |selections| {
10990                        selections.clear_disjoint();
10991                        selections.select_anchor_ranges(ranges);
10992                    });
10993                }
10994            }
10995            editor.register_buffers_with_language_servers(cx);
10996        });
10997
10998        let item = Box::new(editor);
10999        let item_id = item.item_id();
11000
11001        if split {
11002            workspace.split_item(SplitDirection::Right, item.clone(), window, cx);
11003        } else {
11004            let destination_index = workspace.active_pane().update(cx, |pane, cx| {
11005                if PreviewTabsSettings::get_global(cx).enable_preview_from_code_navigation {
11006                    pane.close_current_preview_item(window, cx)
11007                } else {
11008                    None
11009                }
11010            });
11011            workspace.add_item_to_active_pane(item.clone(), destination_index, true, window, cx);
11012        }
11013        workspace.active_pane().update(cx, |pane, cx| {
11014            pane.set_preview_item_id(Some(item_id), cx);
11015        });
11016    }
11017
11018    pub fn rename(
11019        &mut self,
11020        _: &Rename,
11021        window: &mut Window,
11022        cx: &mut Context<Self>,
11023    ) -> Option<Task<Result<()>>> {
11024        use language::ToOffset as _;
11025
11026        let provider = self.semantics_provider.clone()?;
11027        let selection = self.selections.newest_anchor().clone();
11028        let (cursor_buffer, cursor_buffer_position) = self
11029            .buffer
11030            .read(cx)
11031            .text_anchor_for_position(selection.head(), cx)?;
11032        let (tail_buffer, cursor_buffer_position_end) = self
11033            .buffer
11034            .read(cx)
11035            .text_anchor_for_position(selection.tail(), cx)?;
11036        if tail_buffer != cursor_buffer {
11037            return None;
11038        }
11039
11040        let snapshot = cursor_buffer.read(cx).snapshot();
11041        let cursor_buffer_offset = cursor_buffer_position.to_offset(&snapshot);
11042        let cursor_buffer_offset_end = cursor_buffer_position_end.to_offset(&snapshot);
11043        let prepare_rename = provider
11044            .range_for_rename(&cursor_buffer, cursor_buffer_position, cx)
11045            .unwrap_or_else(|| Task::ready(Ok(None)));
11046        drop(snapshot);
11047
11048        Some(cx.spawn_in(window, |this, mut cx| async move {
11049            let rename_range = if let Some(range) = prepare_rename.await? {
11050                Some(range)
11051            } else {
11052                this.update(&mut cx, |this, cx| {
11053                    let buffer = this.buffer.read(cx).snapshot(cx);
11054                    let mut buffer_highlights = this
11055                        .document_highlights_for_position(selection.head(), &buffer)
11056                        .filter(|highlight| {
11057                            highlight.start.excerpt_id == selection.head().excerpt_id
11058                                && highlight.end.excerpt_id == selection.head().excerpt_id
11059                        });
11060                    buffer_highlights
11061                        .next()
11062                        .map(|highlight| highlight.start.text_anchor..highlight.end.text_anchor)
11063                })?
11064            };
11065            if let Some(rename_range) = rename_range {
11066                this.update_in(&mut cx, |this, window, cx| {
11067                    let snapshot = cursor_buffer.read(cx).snapshot();
11068                    let rename_buffer_range = rename_range.to_offset(&snapshot);
11069                    let cursor_offset_in_rename_range =
11070                        cursor_buffer_offset.saturating_sub(rename_buffer_range.start);
11071                    let cursor_offset_in_rename_range_end =
11072                        cursor_buffer_offset_end.saturating_sub(rename_buffer_range.start);
11073
11074                    this.take_rename(false, window, cx);
11075                    let buffer = this.buffer.read(cx).read(cx);
11076                    let cursor_offset = selection.head().to_offset(&buffer);
11077                    let rename_start = cursor_offset.saturating_sub(cursor_offset_in_rename_range);
11078                    let rename_end = rename_start + rename_buffer_range.len();
11079                    let range = buffer.anchor_before(rename_start)..buffer.anchor_after(rename_end);
11080                    let mut old_highlight_id = None;
11081                    let old_name: Arc<str> = buffer
11082                        .chunks(rename_start..rename_end, true)
11083                        .map(|chunk| {
11084                            if old_highlight_id.is_none() {
11085                                old_highlight_id = chunk.syntax_highlight_id;
11086                            }
11087                            chunk.text
11088                        })
11089                        .collect::<String>()
11090                        .into();
11091
11092                    drop(buffer);
11093
11094                    // Position the selection in the rename editor so that it matches the current selection.
11095                    this.show_local_selections = false;
11096                    let rename_editor = cx.new(|cx| {
11097                        let mut editor = Editor::single_line(window, cx);
11098                        editor.buffer.update(cx, |buffer, cx| {
11099                            buffer.edit([(0..0, old_name.clone())], None, cx)
11100                        });
11101                        let rename_selection_range = match cursor_offset_in_rename_range
11102                            .cmp(&cursor_offset_in_rename_range_end)
11103                        {
11104                            Ordering::Equal => {
11105                                editor.select_all(&SelectAll, window, cx);
11106                                return editor;
11107                            }
11108                            Ordering::Less => {
11109                                cursor_offset_in_rename_range..cursor_offset_in_rename_range_end
11110                            }
11111                            Ordering::Greater => {
11112                                cursor_offset_in_rename_range_end..cursor_offset_in_rename_range
11113                            }
11114                        };
11115                        if rename_selection_range.end > old_name.len() {
11116                            editor.select_all(&SelectAll, window, cx);
11117                        } else {
11118                            editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
11119                                s.select_ranges([rename_selection_range]);
11120                            });
11121                        }
11122                        editor
11123                    });
11124                    cx.subscribe(&rename_editor, |_, _, e: &EditorEvent, cx| {
11125                        if e == &EditorEvent::Focused {
11126                            cx.emit(EditorEvent::FocusedIn)
11127                        }
11128                    })
11129                    .detach();
11130
11131                    let write_highlights =
11132                        this.clear_background_highlights::<DocumentHighlightWrite>(cx);
11133                    let read_highlights =
11134                        this.clear_background_highlights::<DocumentHighlightRead>(cx);
11135                    let ranges = write_highlights
11136                        .iter()
11137                        .flat_map(|(_, ranges)| ranges.iter())
11138                        .chain(read_highlights.iter().flat_map(|(_, ranges)| ranges.iter()))
11139                        .cloned()
11140                        .collect();
11141
11142                    this.highlight_text::<Rename>(
11143                        ranges,
11144                        HighlightStyle {
11145                            fade_out: Some(0.6),
11146                            ..Default::default()
11147                        },
11148                        cx,
11149                    );
11150                    let rename_focus_handle = rename_editor.focus_handle(cx);
11151                    window.focus(&rename_focus_handle);
11152                    let block_id = this.insert_blocks(
11153                        [BlockProperties {
11154                            style: BlockStyle::Flex,
11155                            placement: BlockPlacement::Below(range.start),
11156                            height: 1,
11157                            render: Arc::new({
11158                                let rename_editor = rename_editor.clone();
11159                                move |cx: &mut BlockContext| {
11160                                    let mut text_style = cx.editor_style.text.clone();
11161                                    if let Some(highlight_style) = old_highlight_id
11162                                        .and_then(|h| h.style(&cx.editor_style.syntax))
11163                                    {
11164                                        text_style = text_style.highlight(highlight_style);
11165                                    }
11166                                    div()
11167                                        .block_mouse_down()
11168                                        .pl(cx.anchor_x)
11169                                        .child(EditorElement::new(
11170                                            &rename_editor,
11171                                            EditorStyle {
11172                                                background: cx.theme().system().transparent,
11173                                                local_player: cx.editor_style.local_player,
11174                                                text: text_style,
11175                                                scrollbar_width: cx.editor_style.scrollbar_width,
11176                                                syntax: cx.editor_style.syntax.clone(),
11177                                                status: cx.editor_style.status.clone(),
11178                                                inlay_hints_style: HighlightStyle {
11179                                                    font_weight: Some(FontWeight::BOLD),
11180                                                    ..make_inlay_hints_style(cx.app)
11181                                                },
11182                                                inline_completion_styles: make_suggestion_styles(
11183                                                    cx.app,
11184                                                ),
11185                                                ..EditorStyle::default()
11186                                            },
11187                                        ))
11188                                        .into_any_element()
11189                                }
11190                            }),
11191                            priority: 0,
11192                        }],
11193                        Some(Autoscroll::fit()),
11194                        cx,
11195                    )[0];
11196                    this.pending_rename = Some(RenameState {
11197                        range,
11198                        old_name,
11199                        editor: rename_editor,
11200                        block_id,
11201                    });
11202                })?;
11203            }
11204
11205            Ok(())
11206        }))
11207    }
11208
11209    pub fn confirm_rename(
11210        &mut self,
11211        _: &ConfirmRename,
11212        window: &mut Window,
11213        cx: &mut Context<Self>,
11214    ) -> Option<Task<Result<()>>> {
11215        let rename = self.take_rename(false, window, cx)?;
11216        let workspace = self.workspace()?.downgrade();
11217        let (buffer, start) = self
11218            .buffer
11219            .read(cx)
11220            .text_anchor_for_position(rename.range.start, cx)?;
11221        let (end_buffer, _) = self
11222            .buffer
11223            .read(cx)
11224            .text_anchor_for_position(rename.range.end, cx)?;
11225        if buffer != end_buffer {
11226            return None;
11227        }
11228
11229        let old_name = rename.old_name;
11230        let new_name = rename.editor.read(cx).text(cx);
11231
11232        let rename = self.semantics_provider.as_ref()?.perform_rename(
11233            &buffer,
11234            start,
11235            new_name.clone(),
11236            cx,
11237        )?;
11238
11239        Some(cx.spawn_in(window, |editor, mut cx| async move {
11240            let project_transaction = rename.await?;
11241            Self::open_project_transaction(
11242                &editor,
11243                workspace,
11244                project_transaction,
11245                format!("Rename: {}{}", old_name, new_name),
11246                cx.clone(),
11247            )
11248            .await?;
11249
11250            editor.update(&mut cx, |editor, cx| {
11251                editor.refresh_document_highlights(cx);
11252            })?;
11253            Ok(())
11254        }))
11255    }
11256
11257    fn take_rename(
11258        &mut self,
11259        moving_cursor: bool,
11260        window: &mut Window,
11261        cx: &mut Context<Self>,
11262    ) -> Option<RenameState> {
11263        let rename = self.pending_rename.take()?;
11264        if rename.editor.focus_handle(cx).is_focused(window) {
11265            window.focus(&self.focus_handle);
11266        }
11267
11268        self.remove_blocks(
11269            [rename.block_id].into_iter().collect(),
11270            Some(Autoscroll::fit()),
11271            cx,
11272        );
11273        self.clear_highlights::<Rename>(cx);
11274        self.show_local_selections = true;
11275
11276        if moving_cursor {
11277            let cursor_in_rename_editor = rename.editor.update(cx, |editor, cx| {
11278                editor.selections.newest::<usize>(cx).head()
11279            });
11280
11281            // Update the selection to match the position of the selection inside
11282            // the rename editor.
11283            let snapshot = self.buffer.read(cx).read(cx);
11284            let rename_range = rename.range.to_offset(&snapshot);
11285            let cursor_in_editor = snapshot
11286                .clip_offset(rename_range.start + cursor_in_rename_editor, Bias::Left)
11287                .min(rename_range.end);
11288            drop(snapshot);
11289
11290            self.change_selections(None, window, cx, |s| {
11291                s.select_ranges(vec![cursor_in_editor..cursor_in_editor])
11292            });
11293        } else {
11294            self.refresh_document_highlights(cx);
11295        }
11296
11297        Some(rename)
11298    }
11299
11300    pub fn pending_rename(&self) -> Option<&RenameState> {
11301        self.pending_rename.as_ref()
11302    }
11303
11304    fn format(
11305        &mut self,
11306        _: &Format,
11307        window: &mut Window,
11308        cx: &mut Context<Self>,
11309    ) -> Option<Task<Result<()>>> {
11310        let project = match &self.project {
11311            Some(project) => project.clone(),
11312            None => return None,
11313        };
11314
11315        Some(self.perform_format(
11316            project,
11317            FormatTrigger::Manual,
11318            FormatTarget::Buffers,
11319            window,
11320            cx,
11321        ))
11322    }
11323
11324    fn format_selections(
11325        &mut self,
11326        _: &FormatSelections,
11327        window: &mut Window,
11328        cx: &mut Context<Self>,
11329    ) -> Option<Task<Result<()>>> {
11330        let project = match &self.project {
11331            Some(project) => project.clone(),
11332            None => return None,
11333        };
11334
11335        let ranges = self
11336            .selections
11337            .all_adjusted(cx)
11338            .into_iter()
11339            .map(|selection| selection.range())
11340            .collect_vec();
11341
11342        Some(self.perform_format(
11343            project,
11344            FormatTrigger::Manual,
11345            FormatTarget::Ranges(ranges),
11346            window,
11347            cx,
11348        ))
11349    }
11350
11351    fn perform_format(
11352        &mut self,
11353        project: Entity<Project>,
11354        trigger: FormatTrigger,
11355        target: FormatTarget,
11356        window: &mut Window,
11357        cx: &mut Context<Self>,
11358    ) -> Task<Result<()>> {
11359        let buffer = self.buffer.clone();
11360        let (buffers, target) = match target {
11361            FormatTarget::Buffers => {
11362                let mut buffers = buffer.read(cx).all_buffers();
11363                if trigger == FormatTrigger::Save {
11364                    buffers.retain(|buffer| buffer.read(cx).is_dirty());
11365                }
11366                (buffers, LspFormatTarget::Buffers)
11367            }
11368            FormatTarget::Ranges(selection_ranges) => {
11369                let multi_buffer = buffer.read(cx);
11370                let snapshot = multi_buffer.read(cx);
11371                let mut buffers = HashSet::default();
11372                let mut buffer_id_to_ranges: BTreeMap<BufferId, Vec<Range<text::Anchor>>> =
11373                    BTreeMap::new();
11374                for selection_range in selection_ranges {
11375                    for (buffer, buffer_range, _) in
11376                        snapshot.range_to_buffer_ranges(selection_range)
11377                    {
11378                        let buffer_id = buffer.remote_id();
11379                        let start = buffer.anchor_before(buffer_range.start);
11380                        let end = buffer.anchor_after(buffer_range.end);
11381                        buffers.insert(multi_buffer.buffer(buffer_id).unwrap());
11382                        buffer_id_to_ranges
11383                            .entry(buffer_id)
11384                            .and_modify(|buffer_ranges| buffer_ranges.push(start..end))
11385                            .or_insert_with(|| vec![start..end]);
11386                    }
11387                }
11388                (buffers, LspFormatTarget::Ranges(buffer_id_to_ranges))
11389            }
11390        };
11391
11392        let mut timeout = cx.background_executor().timer(FORMAT_TIMEOUT).fuse();
11393        let format = project.update(cx, |project, cx| {
11394            project.format(buffers, target, true, trigger, cx)
11395        });
11396
11397        cx.spawn_in(window, |_, mut cx| async move {
11398            let transaction = futures::select_biased! {
11399                () = timeout => {
11400                    log::warn!("timed out waiting for formatting");
11401                    None
11402                }
11403                transaction = format.log_err().fuse() => transaction,
11404            };
11405
11406            buffer
11407                .update(&mut cx, |buffer, cx| {
11408                    if let Some(transaction) = transaction {
11409                        if !buffer.is_singleton() {
11410                            buffer.push_transaction(&transaction.0, cx);
11411                        }
11412                    }
11413
11414                    cx.notify();
11415                })
11416                .ok();
11417
11418            Ok(())
11419        })
11420    }
11421
11422    fn restart_language_server(
11423        &mut self,
11424        _: &RestartLanguageServer,
11425        _: &mut Window,
11426        cx: &mut Context<Self>,
11427    ) {
11428        if let Some(project) = self.project.clone() {
11429            self.buffer.update(cx, |multi_buffer, cx| {
11430                project.update(cx, |project, cx| {
11431                    project.restart_language_servers_for_buffers(multi_buffer.all_buffers(), cx);
11432                });
11433            })
11434        }
11435    }
11436
11437    fn cancel_language_server_work(
11438        workspace: &mut Workspace,
11439        _: &actions::CancelLanguageServerWork,
11440        _: &mut Window,
11441        cx: &mut Context<Workspace>,
11442    ) {
11443        let project = workspace.project();
11444        let buffers = workspace
11445            .active_item(cx)
11446            .and_then(|item| item.act_as::<Editor>(cx))
11447            .map_or(HashSet::default(), |editor| {
11448                editor.read(cx).buffer.read(cx).all_buffers()
11449            });
11450        project.update(cx, |project, cx| {
11451            project.cancel_language_server_work_for_buffers(buffers, cx);
11452        });
11453    }
11454
11455    fn show_character_palette(
11456        &mut self,
11457        _: &ShowCharacterPalette,
11458        window: &mut Window,
11459        _: &mut Context<Self>,
11460    ) {
11461        window.show_character_palette();
11462    }
11463
11464    fn refresh_active_diagnostics(&mut self, cx: &mut Context<Editor>) {
11465        if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
11466            let buffer = self.buffer.read(cx).snapshot(cx);
11467            let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
11468            let primary_range_end = active_diagnostics.primary_range.end.to_offset(&buffer);
11469            let is_valid = buffer
11470                .diagnostics_in_range::<usize>(primary_range_start..primary_range_end)
11471                .any(|entry| {
11472                    entry.diagnostic.is_primary
11473                        && !entry.range.is_empty()
11474                        && entry.range.start == primary_range_start
11475                        && entry.diagnostic.message == active_diagnostics.primary_message
11476                });
11477
11478            if is_valid != active_diagnostics.is_valid {
11479                active_diagnostics.is_valid = is_valid;
11480                let mut new_styles = HashMap::default();
11481                for (block_id, diagnostic) in &active_diagnostics.blocks {
11482                    new_styles.insert(
11483                        *block_id,
11484                        diagnostic_block_renderer(diagnostic.clone(), None, true, is_valid),
11485                    );
11486                }
11487                self.display_map.update(cx, |display_map, _cx| {
11488                    display_map.replace_blocks(new_styles)
11489                });
11490            }
11491        }
11492    }
11493
11494    fn activate_diagnostics(
11495        &mut self,
11496        buffer_id: BufferId,
11497        group_id: usize,
11498        window: &mut Window,
11499        cx: &mut Context<Self>,
11500    ) {
11501        self.dismiss_diagnostics(cx);
11502        let snapshot = self.snapshot(window, cx);
11503        self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
11504            let buffer = self.buffer.read(cx).snapshot(cx);
11505
11506            let mut primary_range = None;
11507            let mut primary_message = None;
11508            let diagnostic_group = buffer
11509                .diagnostic_group(buffer_id, group_id)
11510                .filter_map(|entry| {
11511                    let start = entry.range.start;
11512                    let end = entry.range.end;
11513                    if snapshot.is_line_folded(MultiBufferRow(start.row))
11514                        && (start.row == end.row
11515                            || snapshot.is_line_folded(MultiBufferRow(end.row)))
11516                    {
11517                        return None;
11518                    }
11519                    if entry.diagnostic.is_primary {
11520                        primary_range = Some(entry.range.clone());
11521                        primary_message = Some(entry.diagnostic.message.clone());
11522                    }
11523                    Some(entry)
11524                })
11525                .collect::<Vec<_>>();
11526            let primary_range = primary_range?;
11527            let primary_message = primary_message?;
11528
11529            let blocks = display_map
11530                .insert_blocks(
11531                    diagnostic_group.iter().map(|entry| {
11532                        let diagnostic = entry.diagnostic.clone();
11533                        let message_height = diagnostic.message.matches('\n').count() as u32 + 1;
11534                        BlockProperties {
11535                            style: BlockStyle::Fixed,
11536                            placement: BlockPlacement::Below(
11537                                buffer.anchor_after(entry.range.start),
11538                            ),
11539                            height: message_height,
11540                            render: diagnostic_block_renderer(diagnostic, None, true, true),
11541                            priority: 0,
11542                        }
11543                    }),
11544                    cx,
11545                )
11546                .into_iter()
11547                .zip(diagnostic_group.into_iter().map(|entry| entry.diagnostic))
11548                .collect();
11549
11550            Some(ActiveDiagnosticGroup {
11551                primary_range: buffer.anchor_before(primary_range.start)
11552                    ..buffer.anchor_after(primary_range.end),
11553                primary_message,
11554                group_id,
11555                blocks,
11556                is_valid: true,
11557            })
11558        });
11559    }
11560
11561    fn dismiss_diagnostics(&mut self, cx: &mut Context<Self>) {
11562        if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
11563            self.display_map.update(cx, |display_map, cx| {
11564                display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx);
11565            });
11566            cx.notify();
11567        }
11568    }
11569
11570    pub fn set_selections_from_remote(
11571        &mut self,
11572        selections: Vec<Selection<Anchor>>,
11573        pending_selection: Option<Selection<Anchor>>,
11574        window: &mut Window,
11575        cx: &mut Context<Self>,
11576    ) {
11577        let old_cursor_position = self.selections.newest_anchor().head();
11578        self.selections.change_with(cx, |s| {
11579            s.select_anchors(selections);
11580            if let Some(pending_selection) = pending_selection {
11581                s.set_pending(pending_selection, SelectMode::Character);
11582            } else {
11583                s.clear_pending();
11584            }
11585        });
11586        self.selections_did_change(false, &old_cursor_position, true, window, cx);
11587    }
11588
11589    fn push_to_selection_history(&mut self) {
11590        self.selection_history.push(SelectionHistoryEntry {
11591            selections: self.selections.disjoint_anchors(),
11592            select_next_state: self.select_next_state.clone(),
11593            select_prev_state: self.select_prev_state.clone(),
11594            add_selections_state: self.add_selections_state.clone(),
11595        });
11596    }
11597
11598    pub fn transact(
11599        &mut self,
11600        window: &mut Window,
11601        cx: &mut Context<Self>,
11602        update: impl FnOnce(&mut Self, &mut Window, &mut Context<Self>),
11603    ) -> Option<TransactionId> {
11604        self.start_transaction_at(Instant::now(), window, cx);
11605        update(self, window, cx);
11606        self.end_transaction_at(Instant::now(), cx)
11607    }
11608
11609    pub fn start_transaction_at(
11610        &mut self,
11611        now: Instant,
11612        window: &mut Window,
11613        cx: &mut Context<Self>,
11614    ) {
11615        self.end_selection(window, cx);
11616        if let Some(tx_id) = self
11617            .buffer
11618            .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx))
11619        {
11620            self.selection_history
11621                .insert_transaction(tx_id, self.selections.disjoint_anchors());
11622            cx.emit(EditorEvent::TransactionBegun {
11623                transaction_id: tx_id,
11624            })
11625        }
11626    }
11627
11628    pub fn end_transaction_at(
11629        &mut self,
11630        now: Instant,
11631        cx: &mut Context<Self>,
11632    ) -> Option<TransactionId> {
11633        if let Some(transaction_id) = self
11634            .buffer
11635            .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
11636        {
11637            if let Some((_, end_selections)) =
11638                self.selection_history.transaction_mut(transaction_id)
11639            {
11640                *end_selections = Some(self.selections.disjoint_anchors());
11641            } else {
11642                log::error!("unexpectedly ended a transaction that wasn't started by this editor");
11643            }
11644
11645            cx.emit(EditorEvent::Edited { transaction_id });
11646            Some(transaction_id)
11647        } else {
11648            None
11649        }
11650    }
11651
11652    pub fn set_mark(&mut self, _: &actions::SetMark, window: &mut Window, cx: &mut Context<Self>) {
11653        if self.selection_mark_mode {
11654            self.change_selections(None, window, cx, |s| {
11655                s.move_with(|_, sel| {
11656                    sel.collapse_to(sel.head(), SelectionGoal::None);
11657                });
11658            })
11659        }
11660        self.selection_mark_mode = true;
11661        cx.notify();
11662    }
11663
11664    pub fn swap_selection_ends(
11665        &mut self,
11666        _: &actions::SwapSelectionEnds,
11667        window: &mut Window,
11668        cx: &mut Context<Self>,
11669    ) {
11670        self.change_selections(None, window, cx, |s| {
11671            s.move_with(|_, sel| {
11672                if sel.start != sel.end {
11673                    sel.reversed = !sel.reversed
11674                }
11675            });
11676        });
11677        self.request_autoscroll(Autoscroll::newest(), cx);
11678        cx.notify();
11679    }
11680
11681    pub fn toggle_fold(
11682        &mut self,
11683        _: &actions::ToggleFold,
11684        window: &mut Window,
11685        cx: &mut Context<Self>,
11686    ) {
11687        if self.is_singleton(cx) {
11688            let selection = self.selections.newest::<Point>(cx);
11689
11690            let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
11691            let range = if selection.is_empty() {
11692                let point = selection.head().to_display_point(&display_map);
11693                let start = DisplayPoint::new(point.row(), 0).to_point(&display_map);
11694                let end = DisplayPoint::new(point.row(), display_map.line_len(point.row()))
11695                    .to_point(&display_map);
11696                start..end
11697            } else {
11698                selection.range()
11699            };
11700            if display_map.folds_in_range(range).next().is_some() {
11701                self.unfold_lines(&Default::default(), window, cx)
11702            } else {
11703                self.fold(&Default::default(), window, cx)
11704            }
11705        } else {
11706            let multi_buffer_snapshot = self.buffer.read(cx).snapshot(cx);
11707            let buffer_ids: HashSet<_> = multi_buffer_snapshot
11708                .ranges_to_buffer_ranges(self.selections.disjoint_anchor_ranges())
11709                .map(|(snapshot, _, _)| snapshot.remote_id())
11710                .collect();
11711
11712            for buffer_id in buffer_ids {
11713                if self.is_buffer_folded(buffer_id, cx) {
11714                    self.unfold_buffer(buffer_id, cx);
11715                } else {
11716                    self.fold_buffer(buffer_id, cx);
11717                }
11718            }
11719        }
11720    }
11721
11722    pub fn toggle_fold_recursive(
11723        &mut self,
11724        _: &actions::ToggleFoldRecursive,
11725        window: &mut Window,
11726        cx: &mut Context<Self>,
11727    ) {
11728        let selection = self.selections.newest::<Point>(cx);
11729
11730        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
11731        let range = if selection.is_empty() {
11732            let point = selection.head().to_display_point(&display_map);
11733            let start = DisplayPoint::new(point.row(), 0).to_point(&display_map);
11734            let end = DisplayPoint::new(point.row(), display_map.line_len(point.row()))
11735                .to_point(&display_map);
11736            start..end
11737        } else {
11738            selection.range()
11739        };
11740        if display_map.folds_in_range(range).next().is_some() {
11741            self.unfold_recursive(&Default::default(), window, cx)
11742        } else {
11743            self.fold_recursive(&Default::default(), window, cx)
11744        }
11745    }
11746
11747    pub fn fold(&mut self, _: &actions::Fold, window: &mut Window, cx: &mut Context<Self>) {
11748        if self.is_singleton(cx) {
11749            let mut to_fold = Vec::new();
11750            let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
11751            let selections = self.selections.all_adjusted(cx);
11752
11753            for selection in selections {
11754                let range = selection.range().sorted();
11755                let buffer_start_row = range.start.row;
11756
11757                if range.start.row != range.end.row {
11758                    let mut found = false;
11759                    let mut row = range.start.row;
11760                    while row <= range.end.row {
11761                        if let Some(crease) = display_map.crease_for_buffer_row(MultiBufferRow(row))
11762                        {
11763                            found = true;
11764                            row = crease.range().end.row + 1;
11765                            to_fold.push(crease);
11766                        } else {
11767                            row += 1
11768                        }
11769                    }
11770                    if found {
11771                        continue;
11772                    }
11773                }
11774
11775                for row in (0..=range.start.row).rev() {
11776                    if let Some(crease) = display_map.crease_for_buffer_row(MultiBufferRow(row)) {
11777                        if crease.range().end.row >= buffer_start_row {
11778                            to_fold.push(crease);
11779                            if row <= range.start.row {
11780                                break;
11781                            }
11782                        }
11783                    }
11784                }
11785            }
11786
11787            self.fold_creases(to_fold, true, window, cx);
11788        } else {
11789            let multi_buffer_snapshot = self.buffer.read(cx).snapshot(cx);
11790
11791            let buffer_ids: HashSet<_> = multi_buffer_snapshot
11792                .ranges_to_buffer_ranges(self.selections.disjoint_anchor_ranges())
11793                .map(|(snapshot, _, _)| snapshot.remote_id())
11794                .collect();
11795            for buffer_id in buffer_ids {
11796                self.fold_buffer(buffer_id, cx);
11797            }
11798        }
11799    }
11800
11801    fn fold_at_level(
11802        &mut self,
11803        fold_at: &FoldAtLevel,
11804        window: &mut Window,
11805        cx: &mut Context<Self>,
11806    ) {
11807        if !self.buffer.read(cx).is_singleton() {
11808            return;
11809        }
11810
11811        let fold_at_level = fold_at.0;
11812        let snapshot = self.buffer.read(cx).snapshot(cx);
11813        let mut to_fold = Vec::new();
11814        let mut stack = vec![(0, snapshot.max_row().0, 1)];
11815
11816        while let Some((mut start_row, end_row, current_level)) = stack.pop() {
11817            while start_row < end_row {
11818                match self
11819                    .snapshot(window, cx)
11820                    .crease_for_buffer_row(MultiBufferRow(start_row))
11821                {
11822                    Some(crease) => {
11823                        let nested_start_row = crease.range().start.row + 1;
11824                        let nested_end_row = crease.range().end.row;
11825
11826                        if current_level < fold_at_level {
11827                            stack.push((nested_start_row, nested_end_row, current_level + 1));
11828                        } else if current_level == fold_at_level {
11829                            to_fold.push(crease);
11830                        }
11831
11832                        start_row = nested_end_row + 1;
11833                    }
11834                    None => start_row += 1,
11835                }
11836            }
11837        }
11838
11839        self.fold_creases(to_fold, true, window, cx);
11840    }
11841
11842    pub fn fold_all(&mut self, _: &actions::FoldAll, window: &mut Window, cx: &mut Context<Self>) {
11843        if self.buffer.read(cx).is_singleton() {
11844            let mut fold_ranges = Vec::new();
11845            let snapshot = self.buffer.read(cx).snapshot(cx);
11846
11847            for row in 0..snapshot.max_row().0 {
11848                if let Some(foldable_range) = self
11849                    .snapshot(window, cx)
11850                    .crease_for_buffer_row(MultiBufferRow(row))
11851                {
11852                    fold_ranges.push(foldable_range);
11853                }
11854            }
11855
11856            self.fold_creases(fold_ranges, true, window, cx);
11857        } else {
11858            self.toggle_fold_multiple_buffers = cx.spawn_in(window, |editor, mut cx| async move {
11859                editor
11860                    .update_in(&mut cx, |editor, _, cx| {
11861                        for buffer_id in editor.buffer.read(cx).excerpt_buffer_ids() {
11862                            editor.fold_buffer(buffer_id, cx);
11863                        }
11864                    })
11865                    .ok();
11866            });
11867        }
11868    }
11869
11870    pub fn fold_function_bodies(
11871        &mut self,
11872        _: &actions::FoldFunctionBodies,
11873        window: &mut Window,
11874        cx: &mut Context<Self>,
11875    ) {
11876        let snapshot = self.buffer.read(cx).snapshot(cx);
11877
11878        let ranges = snapshot
11879            .text_object_ranges(0..snapshot.len(), TreeSitterOptions::default())
11880            .filter_map(|(range, obj)| (obj == TextObject::InsideFunction).then_some(range))
11881            .collect::<Vec<_>>();
11882
11883        let creases = ranges
11884            .into_iter()
11885            .map(|range| Crease::simple(range, self.display_map.read(cx).fold_placeholder.clone()))
11886            .collect();
11887
11888        self.fold_creases(creases, true, window, cx);
11889    }
11890
11891    pub fn fold_recursive(
11892        &mut self,
11893        _: &actions::FoldRecursive,
11894        window: &mut Window,
11895        cx: &mut Context<Self>,
11896    ) {
11897        let mut to_fold = Vec::new();
11898        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
11899        let selections = self.selections.all_adjusted(cx);
11900
11901        for selection in selections {
11902            let range = selection.range().sorted();
11903            let buffer_start_row = range.start.row;
11904
11905            if range.start.row != range.end.row {
11906                let mut found = false;
11907                for row in range.start.row..=range.end.row {
11908                    if let Some(crease) = display_map.crease_for_buffer_row(MultiBufferRow(row)) {
11909                        found = true;
11910                        to_fold.push(crease);
11911                    }
11912                }
11913                if found {
11914                    continue;
11915                }
11916            }
11917
11918            for row in (0..=range.start.row).rev() {
11919                if let Some(crease) = display_map.crease_for_buffer_row(MultiBufferRow(row)) {
11920                    if crease.range().end.row >= buffer_start_row {
11921                        to_fold.push(crease);
11922                    } else {
11923                        break;
11924                    }
11925                }
11926            }
11927        }
11928
11929        self.fold_creases(to_fold, true, window, cx);
11930    }
11931
11932    pub fn fold_at(&mut self, fold_at: &FoldAt, window: &mut Window, cx: &mut Context<Self>) {
11933        let buffer_row = fold_at.buffer_row;
11934        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
11935
11936        if let Some(crease) = display_map.crease_for_buffer_row(buffer_row) {
11937            let autoscroll = self
11938                .selections
11939                .all::<Point>(cx)
11940                .iter()
11941                .any(|selection| crease.range().overlaps(&selection.range()));
11942
11943            self.fold_creases(vec![crease], autoscroll, window, cx);
11944        }
11945    }
11946
11947    pub fn unfold_lines(&mut self, _: &UnfoldLines, _window: &mut Window, cx: &mut Context<Self>) {
11948        if self.is_singleton(cx) {
11949            let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
11950            let buffer = &display_map.buffer_snapshot;
11951            let selections = self.selections.all::<Point>(cx);
11952            let ranges = selections
11953                .iter()
11954                .map(|s| {
11955                    let range = s.display_range(&display_map).sorted();
11956                    let mut start = range.start.to_point(&display_map);
11957                    let mut end = range.end.to_point(&display_map);
11958                    start.column = 0;
11959                    end.column = buffer.line_len(MultiBufferRow(end.row));
11960                    start..end
11961                })
11962                .collect::<Vec<_>>();
11963
11964            self.unfold_ranges(&ranges, true, true, cx);
11965        } else {
11966            let multi_buffer_snapshot = self.buffer.read(cx).snapshot(cx);
11967            let buffer_ids: HashSet<_> = multi_buffer_snapshot
11968                .ranges_to_buffer_ranges(self.selections.disjoint_anchor_ranges())
11969                .map(|(snapshot, _, _)| snapshot.remote_id())
11970                .collect();
11971            for buffer_id in buffer_ids {
11972                self.unfold_buffer(buffer_id, cx);
11973            }
11974        }
11975    }
11976
11977    pub fn unfold_recursive(
11978        &mut self,
11979        _: &UnfoldRecursive,
11980        _window: &mut Window,
11981        cx: &mut Context<Self>,
11982    ) {
11983        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
11984        let selections = self.selections.all::<Point>(cx);
11985        let ranges = selections
11986            .iter()
11987            .map(|s| {
11988                let mut range = s.display_range(&display_map).sorted();
11989                *range.start.column_mut() = 0;
11990                *range.end.column_mut() = display_map.line_len(range.end.row());
11991                let start = range.start.to_point(&display_map);
11992                let end = range.end.to_point(&display_map);
11993                start..end
11994            })
11995            .collect::<Vec<_>>();
11996
11997        self.unfold_ranges(&ranges, true, true, cx);
11998    }
11999
12000    pub fn unfold_at(
12001        &mut self,
12002        unfold_at: &UnfoldAt,
12003        _window: &mut Window,
12004        cx: &mut Context<Self>,
12005    ) {
12006        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
12007
12008        let intersection_range = Point::new(unfold_at.buffer_row.0, 0)
12009            ..Point::new(
12010                unfold_at.buffer_row.0,
12011                display_map.buffer_snapshot.line_len(unfold_at.buffer_row),
12012            );
12013
12014        let autoscroll = self
12015            .selections
12016            .all::<Point>(cx)
12017            .iter()
12018            .any(|selection| RangeExt::overlaps(&selection.range(), &intersection_range));
12019
12020        self.unfold_ranges(&[intersection_range], true, autoscroll, cx);
12021    }
12022
12023    pub fn unfold_all(
12024        &mut self,
12025        _: &actions::UnfoldAll,
12026        _window: &mut Window,
12027        cx: &mut Context<Self>,
12028    ) {
12029        if self.buffer.read(cx).is_singleton() {
12030            let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
12031            self.unfold_ranges(&[0..display_map.buffer_snapshot.len()], true, true, cx);
12032        } else {
12033            self.toggle_fold_multiple_buffers = cx.spawn(|editor, mut cx| async move {
12034                editor
12035                    .update(&mut cx, |editor, cx| {
12036                        for buffer_id in editor.buffer.read(cx).excerpt_buffer_ids() {
12037                            editor.unfold_buffer(buffer_id, cx);
12038                        }
12039                    })
12040                    .ok();
12041            });
12042        }
12043    }
12044
12045    pub fn fold_selected_ranges(
12046        &mut self,
12047        _: &FoldSelectedRanges,
12048        window: &mut Window,
12049        cx: &mut Context<Self>,
12050    ) {
12051        let selections = self.selections.all::<Point>(cx);
12052        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
12053        let line_mode = self.selections.line_mode;
12054        let ranges = selections
12055            .into_iter()
12056            .map(|s| {
12057                if line_mode {
12058                    let start = Point::new(s.start.row, 0);
12059                    let end = Point::new(
12060                        s.end.row,
12061                        display_map
12062                            .buffer_snapshot
12063                            .line_len(MultiBufferRow(s.end.row)),
12064                    );
12065                    Crease::simple(start..end, display_map.fold_placeholder.clone())
12066                } else {
12067                    Crease::simple(s.start..s.end, display_map.fold_placeholder.clone())
12068                }
12069            })
12070            .collect::<Vec<_>>();
12071        self.fold_creases(ranges, true, window, cx);
12072    }
12073
12074    pub fn fold_ranges<T: ToOffset + Clone>(
12075        &mut self,
12076        ranges: Vec<Range<T>>,
12077        auto_scroll: bool,
12078        window: &mut Window,
12079        cx: &mut Context<Self>,
12080    ) {
12081        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
12082        let ranges = ranges
12083            .into_iter()
12084            .map(|r| Crease::simple(r, display_map.fold_placeholder.clone()))
12085            .collect::<Vec<_>>();
12086        self.fold_creases(ranges, auto_scroll, window, cx);
12087    }
12088
12089    pub fn fold_creases<T: ToOffset + Clone>(
12090        &mut self,
12091        creases: Vec<Crease<T>>,
12092        auto_scroll: bool,
12093        window: &mut Window,
12094        cx: &mut Context<Self>,
12095    ) {
12096        if creases.is_empty() {
12097            return;
12098        }
12099
12100        let mut buffers_affected = HashSet::default();
12101        let multi_buffer = self.buffer().read(cx);
12102        for crease in &creases {
12103            if let Some((_, buffer, _)) =
12104                multi_buffer.excerpt_containing(crease.range().start.clone(), cx)
12105            {
12106                buffers_affected.insert(buffer.read(cx).remote_id());
12107            };
12108        }
12109
12110        self.display_map.update(cx, |map, cx| map.fold(creases, cx));
12111
12112        if auto_scroll {
12113            self.request_autoscroll(Autoscroll::fit(), cx);
12114        }
12115
12116        cx.notify();
12117
12118        if let Some(active_diagnostics) = self.active_diagnostics.take() {
12119            // Clear diagnostics block when folding a range that contains it.
12120            let snapshot = self.snapshot(window, cx);
12121            if snapshot.intersects_fold(active_diagnostics.primary_range.start) {
12122                drop(snapshot);
12123                self.active_diagnostics = Some(active_diagnostics);
12124                self.dismiss_diagnostics(cx);
12125            } else {
12126                self.active_diagnostics = Some(active_diagnostics);
12127            }
12128        }
12129
12130        self.scrollbar_marker_state.dirty = true;
12131    }
12132
12133    /// Removes any folds whose ranges intersect any of the given ranges.
12134    pub fn unfold_ranges<T: ToOffset + Clone>(
12135        &mut self,
12136        ranges: &[Range<T>],
12137        inclusive: bool,
12138        auto_scroll: bool,
12139        cx: &mut Context<Self>,
12140    ) {
12141        self.remove_folds_with(ranges, auto_scroll, cx, |map, cx| {
12142            map.unfold_intersecting(ranges.iter().cloned(), inclusive, cx)
12143        });
12144    }
12145
12146    pub fn fold_buffer(&mut self, buffer_id: BufferId, cx: &mut Context<Self>) {
12147        if self.buffer().read(cx).is_singleton() || self.is_buffer_folded(buffer_id, cx) {
12148            return;
12149        }
12150        let folded_excerpts = self.buffer().read(cx).excerpts_for_buffer(buffer_id, cx);
12151        self.display_map
12152            .update(cx, |display_map, cx| display_map.fold_buffer(buffer_id, cx));
12153        cx.emit(EditorEvent::BufferFoldToggled {
12154            ids: folded_excerpts.iter().map(|&(id, _)| id).collect(),
12155            folded: true,
12156        });
12157        cx.notify();
12158    }
12159
12160    pub fn unfold_buffer(&mut self, buffer_id: BufferId, cx: &mut Context<Self>) {
12161        if self.buffer().read(cx).is_singleton() || !self.is_buffer_folded(buffer_id, cx) {
12162            return;
12163        }
12164        let unfolded_excerpts = self.buffer().read(cx).excerpts_for_buffer(buffer_id, cx);
12165        self.display_map.update(cx, |display_map, cx| {
12166            display_map.unfold_buffer(buffer_id, cx);
12167        });
12168        cx.emit(EditorEvent::BufferFoldToggled {
12169            ids: unfolded_excerpts.iter().map(|&(id, _)| id).collect(),
12170            folded: false,
12171        });
12172        cx.notify();
12173    }
12174
12175    pub fn is_buffer_folded(&self, buffer: BufferId, cx: &App) -> bool {
12176        self.display_map.read(cx).is_buffer_folded(buffer)
12177    }
12178
12179    pub fn folded_buffers<'a>(&self, cx: &'a App) -> &'a HashSet<BufferId> {
12180        self.display_map.read(cx).folded_buffers()
12181    }
12182
12183    /// Removes any folds with the given ranges.
12184    pub fn remove_folds_with_type<T: ToOffset + Clone>(
12185        &mut self,
12186        ranges: &[Range<T>],
12187        type_id: TypeId,
12188        auto_scroll: bool,
12189        cx: &mut Context<Self>,
12190    ) {
12191        self.remove_folds_with(ranges, auto_scroll, cx, |map, cx| {
12192            map.remove_folds_with_type(ranges.iter().cloned(), type_id, cx)
12193        });
12194    }
12195
12196    fn remove_folds_with<T: ToOffset + Clone>(
12197        &mut self,
12198        ranges: &[Range<T>],
12199        auto_scroll: bool,
12200        cx: &mut Context<Self>,
12201        update: impl FnOnce(&mut DisplayMap, &mut Context<DisplayMap>),
12202    ) {
12203        if ranges.is_empty() {
12204            return;
12205        }
12206
12207        let mut buffers_affected = HashSet::default();
12208        let multi_buffer = self.buffer().read(cx);
12209        for range in ranges {
12210            if let Some((_, buffer, _)) = multi_buffer.excerpt_containing(range.start.clone(), cx) {
12211                buffers_affected.insert(buffer.read(cx).remote_id());
12212            };
12213        }
12214
12215        self.display_map.update(cx, update);
12216
12217        if auto_scroll {
12218            self.request_autoscroll(Autoscroll::fit(), cx);
12219        }
12220
12221        cx.notify();
12222        self.scrollbar_marker_state.dirty = true;
12223        self.active_indent_guides_state.dirty = true;
12224    }
12225
12226    pub fn default_fold_placeholder(&self, cx: &App) -> FoldPlaceholder {
12227        self.display_map.read(cx).fold_placeholder.clone()
12228    }
12229
12230    pub fn set_expand_all_diff_hunks(&mut self, cx: &mut App) {
12231        self.buffer.update(cx, |buffer, cx| {
12232            buffer.set_all_diff_hunks_expanded(cx);
12233        });
12234    }
12235
12236    pub fn expand_all_diff_hunks(
12237        &mut self,
12238        _: &ExpandAllHunkDiffs,
12239        _window: &mut Window,
12240        cx: &mut Context<Self>,
12241    ) {
12242        self.buffer.update(cx, |buffer, cx| {
12243            buffer.expand_diff_hunks(vec![Anchor::min()..Anchor::max()], cx)
12244        });
12245    }
12246
12247    pub fn toggle_selected_diff_hunks(
12248        &mut self,
12249        _: &ToggleSelectedDiffHunks,
12250        _window: &mut Window,
12251        cx: &mut Context<Self>,
12252    ) {
12253        let ranges: Vec<_> = self.selections.disjoint.iter().map(|s| s.range()).collect();
12254        self.toggle_diff_hunks_in_ranges(ranges, cx);
12255    }
12256
12257    pub fn expand_selected_diff_hunks(&mut self, cx: &mut Context<Self>) {
12258        let ranges: Vec<_> = self.selections.disjoint.iter().map(|s| s.range()).collect();
12259        self.buffer
12260            .update(cx, |buffer, cx| buffer.expand_diff_hunks(ranges, cx))
12261    }
12262
12263    pub fn clear_expanded_diff_hunks(&mut self, cx: &mut Context<Self>) -> bool {
12264        self.buffer.update(cx, |buffer, cx| {
12265            let ranges = vec![Anchor::min()..Anchor::max()];
12266            if !buffer.all_diff_hunks_expanded()
12267                && buffer.has_expanded_diff_hunks_in_ranges(&ranges, cx)
12268            {
12269                buffer.collapse_diff_hunks(ranges, cx);
12270                true
12271            } else {
12272                false
12273            }
12274        })
12275    }
12276
12277    fn toggle_diff_hunks_in_ranges(
12278        &mut self,
12279        ranges: Vec<Range<Anchor>>,
12280        cx: &mut Context<'_, Editor>,
12281    ) {
12282        self.buffer.update(cx, |buffer, cx| {
12283            let expand = !buffer.has_expanded_diff_hunks_in_ranges(&ranges, cx);
12284            buffer.expand_or_collapse_diff_hunks(ranges, expand, cx);
12285        })
12286    }
12287
12288    fn toggle_diff_hunks_in_ranges_narrow(
12289        &mut self,
12290        ranges: Vec<Range<Anchor>>,
12291        cx: &mut Context<'_, Editor>,
12292    ) {
12293        self.buffer.update(cx, |buffer, cx| {
12294            let expand = !buffer.has_expanded_diff_hunks_in_ranges(&ranges, cx);
12295            buffer.expand_or_collapse_diff_hunks_narrow(ranges, expand, cx);
12296        })
12297    }
12298
12299    pub(crate) fn apply_all_diff_hunks(
12300        &mut self,
12301        _: &ApplyAllDiffHunks,
12302        window: &mut Window,
12303        cx: &mut Context<Self>,
12304    ) {
12305        let buffers = self.buffer.read(cx).all_buffers();
12306        for branch_buffer in buffers {
12307            branch_buffer.update(cx, |branch_buffer, cx| {
12308                branch_buffer.merge_into_base(Vec::new(), cx);
12309            });
12310        }
12311
12312        if let Some(project) = self.project.clone() {
12313            self.save(true, project, window, cx).detach_and_log_err(cx);
12314        }
12315    }
12316
12317    pub(crate) fn apply_selected_diff_hunks(
12318        &mut self,
12319        _: &ApplyDiffHunk,
12320        window: &mut Window,
12321        cx: &mut Context<Self>,
12322    ) {
12323        let snapshot = self.snapshot(window, cx);
12324        let hunks = snapshot.hunks_for_ranges(self.selections.ranges(cx).into_iter());
12325        let mut ranges_by_buffer = HashMap::default();
12326        self.transact(window, cx, |editor, _window, cx| {
12327            for hunk in hunks {
12328                if let Some(buffer) = editor.buffer.read(cx).buffer(hunk.buffer_id) {
12329                    ranges_by_buffer
12330                        .entry(buffer.clone())
12331                        .or_insert_with(Vec::new)
12332                        .push(hunk.buffer_range.to_offset(buffer.read(cx)));
12333                }
12334            }
12335
12336            for (buffer, ranges) in ranges_by_buffer {
12337                buffer.update(cx, |buffer, cx| {
12338                    buffer.merge_into_base(ranges, cx);
12339                });
12340            }
12341        });
12342
12343        if let Some(project) = self.project.clone() {
12344            self.save(true, project, window, cx).detach_and_log_err(cx);
12345        }
12346    }
12347
12348    pub fn set_gutter_hovered(&mut self, hovered: bool, cx: &mut Context<Self>) {
12349        if hovered != self.gutter_hovered {
12350            self.gutter_hovered = hovered;
12351            cx.notify();
12352        }
12353    }
12354
12355    pub fn insert_blocks(
12356        &mut self,
12357        blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
12358        autoscroll: Option<Autoscroll>,
12359        cx: &mut Context<Self>,
12360    ) -> Vec<CustomBlockId> {
12361        let blocks = self
12362            .display_map
12363            .update(cx, |display_map, cx| display_map.insert_blocks(blocks, cx));
12364        if let Some(autoscroll) = autoscroll {
12365            self.request_autoscroll(autoscroll, cx);
12366        }
12367        cx.notify();
12368        blocks
12369    }
12370
12371    pub fn resize_blocks(
12372        &mut self,
12373        heights: HashMap<CustomBlockId, u32>,
12374        autoscroll: Option<Autoscroll>,
12375        cx: &mut Context<Self>,
12376    ) {
12377        self.display_map
12378            .update(cx, |display_map, cx| display_map.resize_blocks(heights, cx));
12379        if let Some(autoscroll) = autoscroll {
12380            self.request_autoscroll(autoscroll, cx);
12381        }
12382        cx.notify();
12383    }
12384
12385    pub fn replace_blocks(
12386        &mut self,
12387        renderers: HashMap<CustomBlockId, RenderBlock>,
12388        autoscroll: Option<Autoscroll>,
12389        cx: &mut Context<Self>,
12390    ) {
12391        self.display_map
12392            .update(cx, |display_map, _cx| display_map.replace_blocks(renderers));
12393        if let Some(autoscroll) = autoscroll {
12394            self.request_autoscroll(autoscroll, cx);
12395        }
12396        cx.notify();
12397    }
12398
12399    pub fn remove_blocks(
12400        &mut self,
12401        block_ids: HashSet<CustomBlockId>,
12402        autoscroll: Option<Autoscroll>,
12403        cx: &mut Context<Self>,
12404    ) {
12405        self.display_map.update(cx, |display_map, cx| {
12406            display_map.remove_blocks(block_ids, cx)
12407        });
12408        if let Some(autoscroll) = autoscroll {
12409            self.request_autoscroll(autoscroll, cx);
12410        }
12411        cx.notify();
12412    }
12413
12414    pub fn row_for_block(
12415        &self,
12416        block_id: CustomBlockId,
12417        cx: &mut Context<Self>,
12418    ) -> Option<DisplayRow> {
12419        self.display_map
12420            .update(cx, |map, cx| map.row_for_block(block_id, cx))
12421    }
12422
12423    pub(crate) fn set_focused_block(&mut self, focused_block: FocusedBlock) {
12424        self.focused_block = Some(focused_block);
12425    }
12426
12427    pub(crate) fn take_focused_block(&mut self) -> Option<FocusedBlock> {
12428        self.focused_block.take()
12429    }
12430
12431    pub fn insert_creases(
12432        &mut self,
12433        creases: impl IntoIterator<Item = Crease<Anchor>>,
12434        cx: &mut Context<Self>,
12435    ) -> Vec<CreaseId> {
12436        self.display_map
12437            .update(cx, |map, cx| map.insert_creases(creases, cx))
12438    }
12439
12440    pub fn remove_creases(
12441        &mut self,
12442        ids: impl IntoIterator<Item = CreaseId>,
12443        cx: &mut Context<Self>,
12444    ) {
12445        self.display_map
12446            .update(cx, |map, cx| map.remove_creases(ids, cx));
12447    }
12448
12449    pub fn longest_row(&self, cx: &mut App) -> DisplayRow {
12450        self.display_map
12451            .update(cx, |map, cx| map.snapshot(cx))
12452            .longest_row()
12453    }
12454
12455    pub fn max_point(&self, cx: &mut App) -> DisplayPoint {
12456        self.display_map
12457            .update(cx, |map, cx| map.snapshot(cx))
12458            .max_point()
12459    }
12460
12461    pub fn text(&self, cx: &App) -> String {
12462        self.buffer.read(cx).read(cx).text()
12463    }
12464
12465    pub fn is_empty(&self, cx: &App) -> bool {
12466        self.buffer.read(cx).read(cx).is_empty()
12467    }
12468
12469    pub fn text_option(&self, cx: &App) -> Option<String> {
12470        let text = self.text(cx);
12471        let text = text.trim();
12472
12473        if text.is_empty() {
12474            return None;
12475        }
12476
12477        Some(text.to_string())
12478    }
12479
12480    pub fn set_text(
12481        &mut self,
12482        text: impl Into<Arc<str>>,
12483        window: &mut Window,
12484        cx: &mut Context<Self>,
12485    ) {
12486        self.transact(window, cx, |this, _, cx| {
12487            this.buffer
12488                .read(cx)
12489                .as_singleton()
12490                .expect("you can only call set_text on editors for singleton buffers")
12491                .update(cx, |buffer, cx| buffer.set_text(text, cx));
12492        });
12493    }
12494
12495    pub fn display_text(&self, cx: &mut App) -> String {
12496        self.display_map
12497            .update(cx, |map, cx| map.snapshot(cx))
12498            .text()
12499    }
12500
12501    pub fn wrap_guides(&self, cx: &App) -> SmallVec<[(usize, bool); 2]> {
12502        let mut wrap_guides = smallvec::smallvec![];
12503
12504        if self.show_wrap_guides == Some(false) {
12505            return wrap_guides;
12506        }
12507
12508        let settings = self.buffer.read(cx).settings_at(0, cx);
12509        if settings.show_wrap_guides {
12510            if let SoftWrap::Column(soft_wrap) = self.soft_wrap_mode(cx) {
12511                wrap_guides.push((soft_wrap as usize, true));
12512            } else if let SoftWrap::Bounded(soft_wrap) = self.soft_wrap_mode(cx) {
12513                wrap_guides.push((soft_wrap as usize, true));
12514            }
12515            wrap_guides.extend(settings.wrap_guides.iter().map(|guide| (*guide, false)))
12516        }
12517
12518        wrap_guides
12519    }
12520
12521    pub fn soft_wrap_mode(&self, cx: &App) -> SoftWrap {
12522        let settings = self.buffer.read(cx).settings_at(0, cx);
12523        let mode = self.soft_wrap_mode_override.unwrap_or(settings.soft_wrap);
12524        match mode {
12525            language_settings::SoftWrap::PreferLine | language_settings::SoftWrap::None => {
12526                SoftWrap::None
12527            }
12528            language_settings::SoftWrap::EditorWidth => SoftWrap::EditorWidth,
12529            language_settings::SoftWrap::PreferredLineLength => {
12530                SoftWrap::Column(settings.preferred_line_length)
12531            }
12532            language_settings::SoftWrap::Bounded => {
12533                SoftWrap::Bounded(settings.preferred_line_length)
12534            }
12535        }
12536    }
12537
12538    pub fn set_soft_wrap_mode(
12539        &mut self,
12540        mode: language_settings::SoftWrap,
12541
12542        cx: &mut Context<Self>,
12543    ) {
12544        self.soft_wrap_mode_override = Some(mode);
12545        cx.notify();
12546    }
12547
12548    pub fn set_text_style_refinement(&mut self, style: TextStyleRefinement) {
12549        self.text_style_refinement = Some(style);
12550    }
12551
12552    /// called by the Element so we know what style we were most recently rendered with.
12553    pub(crate) fn set_style(
12554        &mut self,
12555        style: EditorStyle,
12556        window: &mut Window,
12557        cx: &mut Context<Self>,
12558    ) {
12559        let rem_size = window.rem_size();
12560        self.display_map.update(cx, |map, cx| {
12561            map.set_font(
12562                style.text.font(),
12563                style.text.font_size.to_pixels(rem_size),
12564                cx,
12565            )
12566        });
12567        self.style = Some(style);
12568    }
12569
12570    pub fn style(&self) -> Option<&EditorStyle> {
12571        self.style.as_ref()
12572    }
12573
12574    // Called by the element. This method is not designed to be called outside of the editor
12575    // element's layout code because it does not notify when rewrapping is computed synchronously.
12576    pub(crate) fn set_wrap_width(&self, width: Option<Pixels>, cx: &mut App) -> bool {
12577        self.display_map
12578            .update(cx, |map, cx| map.set_wrap_width(width, cx))
12579    }
12580
12581    pub fn set_soft_wrap(&mut self) {
12582        self.soft_wrap_mode_override = Some(language_settings::SoftWrap::EditorWidth)
12583    }
12584
12585    pub fn toggle_soft_wrap(&mut self, _: &ToggleSoftWrap, _: &mut Window, cx: &mut Context<Self>) {
12586        if self.soft_wrap_mode_override.is_some() {
12587            self.soft_wrap_mode_override.take();
12588        } else {
12589            let soft_wrap = match self.soft_wrap_mode(cx) {
12590                SoftWrap::GitDiff => return,
12591                SoftWrap::None => language_settings::SoftWrap::EditorWidth,
12592                SoftWrap::EditorWidth | SoftWrap::Column(_) | SoftWrap::Bounded(_) => {
12593                    language_settings::SoftWrap::None
12594                }
12595            };
12596            self.soft_wrap_mode_override = Some(soft_wrap);
12597        }
12598        cx.notify();
12599    }
12600
12601    pub fn toggle_tab_bar(&mut self, _: &ToggleTabBar, _: &mut Window, cx: &mut Context<Self>) {
12602        let Some(workspace) = self.workspace() else {
12603            return;
12604        };
12605        let fs = workspace.read(cx).app_state().fs.clone();
12606        let current_show = TabBarSettings::get_global(cx).show;
12607        update_settings_file::<TabBarSettings>(fs, cx, move |setting, _| {
12608            setting.show = Some(!current_show);
12609        });
12610    }
12611
12612    pub fn toggle_indent_guides(
12613        &mut self,
12614        _: &ToggleIndentGuides,
12615        _: &mut Window,
12616        cx: &mut Context<Self>,
12617    ) {
12618        let currently_enabled = self.should_show_indent_guides().unwrap_or_else(|| {
12619            self.buffer
12620                .read(cx)
12621                .settings_at(0, cx)
12622                .indent_guides
12623                .enabled
12624        });
12625        self.show_indent_guides = Some(!currently_enabled);
12626        cx.notify();
12627    }
12628
12629    fn should_show_indent_guides(&self) -> Option<bool> {
12630        self.show_indent_guides
12631    }
12632
12633    pub fn toggle_line_numbers(
12634        &mut self,
12635        _: &ToggleLineNumbers,
12636        _: &mut Window,
12637        cx: &mut Context<Self>,
12638    ) {
12639        let mut editor_settings = EditorSettings::get_global(cx).clone();
12640        editor_settings.gutter.line_numbers = !editor_settings.gutter.line_numbers;
12641        EditorSettings::override_global(editor_settings, cx);
12642    }
12643
12644    pub fn should_use_relative_line_numbers(&self, cx: &mut App) -> bool {
12645        self.use_relative_line_numbers
12646            .unwrap_or(EditorSettings::get_global(cx).relative_line_numbers)
12647    }
12648
12649    pub fn toggle_relative_line_numbers(
12650        &mut self,
12651        _: &ToggleRelativeLineNumbers,
12652        _: &mut Window,
12653        cx: &mut Context<Self>,
12654    ) {
12655        let is_relative = self.should_use_relative_line_numbers(cx);
12656        self.set_relative_line_number(Some(!is_relative), cx)
12657    }
12658
12659    pub fn set_relative_line_number(&mut self, is_relative: Option<bool>, cx: &mut Context<Self>) {
12660        self.use_relative_line_numbers = is_relative;
12661        cx.notify();
12662    }
12663
12664    pub fn set_show_gutter(&mut self, show_gutter: bool, cx: &mut Context<Self>) {
12665        self.show_gutter = show_gutter;
12666        cx.notify();
12667    }
12668
12669    pub fn set_show_scrollbars(&mut self, show_scrollbars: bool, cx: &mut Context<Self>) {
12670        self.show_scrollbars = show_scrollbars;
12671        cx.notify();
12672    }
12673
12674    pub fn set_show_line_numbers(&mut self, show_line_numbers: bool, cx: &mut Context<Self>) {
12675        self.show_line_numbers = Some(show_line_numbers);
12676        cx.notify();
12677    }
12678
12679    pub fn set_show_git_diff_gutter(&mut self, show_git_diff_gutter: bool, cx: &mut Context<Self>) {
12680        self.show_git_diff_gutter = Some(show_git_diff_gutter);
12681        cx.notify();
12682    }
12683
12684    pub fn set_show_code_actions(&mut self, show_code_actions: bool, cx: &mut Context<Self>) {
12685        self.show_code_actions = Some(show_code_actions);
12686        cx.notify();
12687    }
12688
12689    pub fn set_show_runnables(&mut self, show_runnables: bool, cx: &mut Context<Self>) {
12690        self.show_runnables = Some(show_runnables);
12691        cx.notify();
12692    }
12693
12694    pub fn set_masked(&mut self, masked: bool, cx: &mut Context<Self>) {
12695        if self.display_map.read(cx).masked != masked {
12696            self.display_map.update(cx, |map, _| map.masked = masked);
12697        }
12698        cx.notify()
12699    }
12700
12701    pub fn set_show_wrap_guides(&mut self, show_wrap_guides: bool, cx: &mut Context<Self>) {
12702        self.show_wrap_guides = Some(show_wrap_guides);
12703        cx.notify();
12704    }
12705
12706    pub fn set_show_indent_guides(&mut self, show_indent_guides: bool, cx: &mut Context<Self>) {
12707        self.show_indent_guides = Some(show_indent_guides);
12708        cx.notify();
12709    }
12710
12711    pub fn working_directory(&self, cx: &App) -> Option<PathBuf> {
12712        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
12713            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
12714                if let Some(dir) = file.abs_path(cx).parent() {
12715                    return Some(dir.to_owned());
12716                }
12717            }
12718
12719            if let Some(project_path) = buffer.read(cx).project_path(cx) {
12720                return Some(project_path.path.to_path_buf());
12721            }
12722        }
12723
12724        None
12725    }
12726
12727    fn target_file<'a>(&self, cx: &'a App) -> Option<&'a dyn language::LocalFile> {
12728        self.active_excerpt(cx)?
12729            .1
12730            .read(cx)
12731            .file()
12732            .and_then(|f| f.as_local())
12733    }
12734
12735    fn target_file_abs_path(&self, cx: &mut Context<Self>) -> Option<PathBuf> {
12736        self.active_excerpt(cx).and_then(|(_, buffer, _)| {
12737            let project_path = buffer.read(cx).project_path(cx)?;
12738            let project = self.project.as_ref()?.read(cx);
12739            project.absolute_path(&project_path, cx)
12740        })
12741    }
12742
12743    fn target_file_path(&self, cx: &mut Context<Self>) -> Option<PathBuf> {
12744        self.active_excerpt(cx).and_then(|(_, buffer, _)| {
12745            let project_path = buffer.read(cx).project_path(cx)?;
12746            let project = self.project.as_ref()?.read(cx);
12747            let entry = project.entry_for_path(&project_path, cx)?;
12748            let path = entry.path.to_path_buf();
12749            Some(path)
12750        })
12751    }
12752
12753    pub fn reveal_in_finder(
12754        &mut self,
12755        _: &RevealInFileManager,
12756        _window: &mut Window,
12757        cx: &mut Context<Self>,
12758    ) {
12759        if let Some(target) = self.target_file(cx) {
12760            cx.reveal_path(&target.abs_path(cx));
12761        }
12762    }
12763
12764    pub fn copy_path(&mut self, _: &CopyPath, _window: &mut Window, cx: &mut Context<Self>) {
12765        if let Some(path) = self.target_file_abs_path(cx) {
12766            if let Some(path) = path.to_str() {
12767                cx.write_to_clipboard(ClipboardItem::new_string(path.to_string()));
12768            }
12769        }
12770    }
12771
12772    pub fn copy_relative_path(
12773        &mut self,
12774        _: &CopyRelativePath,
12775        _window: &mut Window,
12776        cx: &mut Context<Self>,
12777    ) {
12778        if let Some(path) = self.target_file_path(cx) {
12779            if let Some(path) = path.to_str() {
12780                cx.write_to_clipboard(ClipboardItem::new_string(path.to_string()));
12781            }
12782        }
12783    }
12784
12785    pub fn toggle_git_blame(
12786        &mut self,
12787        _: &ToggleGitBlame,
12788        window: &mut Window,
12789        cx: &mut Context<Self>,
12790    ) {
12791        self.show_git_blame_gutter = !self.show_git_blame_gutter;
12792
12793        if self.show_git_blame_gutter && !self.has_blame_entries(cx) {
12794            self.start_git_blame(true, window, cx);
12795        }
12796
12797        cx.notify();
12798    }
12799
12800    pub fn toggle_git_blame_inline(
12801        &mut self,
12802        _: &ToggleGitBlameInline,
12803        window: &mut Window,
12804        cx: &mut Context<Self>,
12805    ) {
12806        self.toggle_git_blame_inline_internal(true, window, cx);
12807        cx.notify();
12808    }
12809
12810    pub fn git_blame_inline_enabled(&self) -> bool {
12811        self.git_blame_inline_enabled
12812    }
12813
12814    pub fn toggle_selection_menu(
12815        &mut self,
12816        _: &ToggleSelectionMenu,
12817        _: &mut Window,
12818        cx: &mut Context<Self>,
12819    ) {
12820        self.show_selection_menu = self
12821            .show_selection_menu
12822            .map(|show_selections_menu| !show_selections_menu)
12823            .or_else(|| Some(!EditorSettings::get_global(cx).toolbar.selections_menu));
12824
12825        cx.notify();
12826    }
12827
12828    pub fn selection_menu_enabled(&self, cx: &App) -> bool {
12829        self.show_selection_menu
12830            .unwrap_or_else(|| EditorSettings::get_global(cx).toolbar.selections_menu)
12831    }
12832
12833    fn start_git_blame(
12834        &mut self,
12835        user_triggered: bool,
12836        window: &mut Window,
12837        cx: &mut Context<Self>,
12838    ) {
12839        if let Some(project) = self.project.as_ref() {
12840            let Some(buffer) = self.buffer().read(cx).as_singleton() else {
12841                return;
12842            };
12843
12844            if buffer.read(cx).file().is_none() {
12845                return;
12846            }
12847
12848            let focused = self.focus_handle(cx).contains_focused(window, cx);
12849
12850            let project = project.clone();
12851            let blame = cx.new(|cx| GitBlame::new(buffer, project, user_triggered, focused, cx));
12852            self.blame_subscription =
12853                Some(cx.observe_in(&blame, window, |_, _, _, cx| cx.notify()));
12854            self.blame = Some(blame);
12855        }
12856    }
12857
12858    fn toggle_git_blame_inline_internal(
12859        &mut self,
12860        user_triggered: bool,
12861        window: &mut Window,
12862        cx: &mut Context<Self>,
12863    ) {
12864        if self.git_blame_inline_enabled {
12865            self.git_blame_inline_enabled = false;
12866            self.show_git_blame_inline = false;
12867            self.show_git_blame_inline_delay_task.take();
12868        } else {
12869            self.git_blame_inline_enabled = true;
12870            self.start_git_blame_inline(user_triggered, window, cx);
12871        }
12872
12873        cx.notify();
12874    }
12875
12876    fn start_git_blame_inline(
12877        &mut self,
12878        user_triggered: bool,
12879        window: &mut Window,
12880        cx: &mut Context<Self>,
12881    ) {
12882        self.start_git_blame(user_triggered, window, cx);
12883
12884        if ProjectSettings::get_global(cx)
12885            .git
12886            .inline_blame_delay()
12887            .is_some()
12888        {
12889            self.start_inline_blame_timer(window, cx);
12890        } else {
12891            self.show_git_blame_inline = true
12892        }
12893    }
12894
12895    pub fn blame(&self) -> Option<&Entity<GitBlame>> {
12896        self.blame.as_ref()
12897    }
12898
12899    pub fn show_git_blame_gutter(&self) -> bool {
12900        self.show_git_blame_gutter
12901    }
12902
12903    pub fn render_git_blame_gutter(&self, cx: &App) -> bool {
12904        self.show_git_blame_gutter && self.has_blame_entries(cx)
12905    }
12906
12907    pub fn render_git_blame_inline(&self, window: &Window, cx: &App) -> bool {
12908        self.show_git_blame_inline
12909            && self.focus_handle.is_focused(window)
12910            && !self.newest_selection_head_on_empty_line(cx)
12911            && self.has_blame_entries(cx)
12912    }
12913
12914    fn has_blame_entries(&self, cx: &App) -> bool {
12915        self.blame()
12916            .map_or(false, |blame| blame.read(cx).has_generated_entries())
12917    }
12918
12919    fn newest_selection_head_on_empty_line(&self, cx: &App) -> bool {
12920        let cursor_anchor = self.selections.newest_anchor().head();
12921
12922        let snapshot = self.buffer.read(cx).snapshot(cx);
12923        let buffer_row = MultiBufferRow(cursor_anchor.to_point(&snapshot).row);
12924
12925        snapshot.line_len(buffer_row) == 0
12926    }
12927
12928    fn get_permalink_to_line(&self, cx: &mut Context<Self>) -> Task<Result<url::Url>> {
12929        let buffer_and_selection = maybe!({
12930            let selection = self.selections.newest::<Point>(cx);
12931            let selection_range = selection.range();
12932
12933            let multi_buffer = self.buffer().read(cx);
12934            let multi_buffer_snapshot = multi_buffer.snapshot(cx);
12935            let buffer_ranges = multi_buffer_snapshot.range_to_buffer_ranges(selection_range);
12936
12937            let (buffer, range, _) = if selection.reversed {
12938                buffer_ranges.first()
12939            } else {
12940                buffer_ranges.last()
12941            }?;
12942
12943            let selection = text::ToPoint::to_point(&range.start, &buffer).row
12944                ..text::ToPoint::to_point(&range.end, &buffer).row;
12945            Some((
12946                multi_buffer.buffer(buffer.remote_id()).unwrap().clone(),
12947                selection,
12948            ))
12949        });
12950
12951        let Some((buffer, selection)) = buffer_and_selection else {
12952            return Task::ready(Err(anyhow!("failed to determine buffer and selection")));
12953        };
12954
12955        let Some(project) = self.project.as_ref() else {
12956            return Task::ready(Err(anyhow!("editor does not have project")));
12957        };
12958
12959        project.update(cx, |project, cx| {
12960            project.get_permalink_to_line(&buffer, selection, cx)
12961        })
12962    }
12963
12964    pub fn copy_permalink_to_line(
12965        &mut self,
12966        _: &CopyPermalinkToLine,
12967        window: &mut Window,
12968        cx: &mut Context<Self>,
12969    ) {
12970        let permalink_task = self.get_permalink_to_line(cx);
12971        let workspace = self.workspace();
12972
12973        cx.spawn_in(window, |_, mut cx| async move {
12974            match permalink_task.await {
12975                Ok(permalink) => {
12976                    cx.update(|_, cx| {
12977                        cx.write_to_clipboard(ClipboardItem::new_string(permalink.to_string()));
12978                    })
12979                    .ok();
12980                }
12981                Err(err) => {
12982                    let message = format!("Failed to copy permalink: {err}");
12983
12984                    Err::<(), anyhow::Error>(err).log_err();
12985
12986                    if let Some(workspace) = workspace {
12987                        workspace
12988                            .update_in(&mut cx, |workspace, _, cx| {
12989                                struct CopyPermalinkToLine;
12990
12991                                workspace.show_toast(
12992                                    Toast::new(
12993                                        NotificationId::unique::<CopyPermalinkToLine>(),
12994                                        message,
12995                                    ),
12996                                    cx,
12997                                )
12998                            })
12999                            .ok();
13000                    }
13001                }
13002            }
13003        })
13004        .detach();
13005    }
13006
13007    pub fn copy_file_location(
13008        &mut self,
13009        _: &CopyFileLocation,
13010        _: &mut Window,
13011        cx: &mut Context<Self>,
13012    ) {
13013        let selection = self.selections.newest::<Point>(cx).start.row + 1;
13014        if let Some(file) = self.target_file(cx) {
13015            if let Some(path) = file.path().to_str() {
13016                cx.write_to_clipboard(ClipboardItem::new_string(format!("{path}:{selection}")));
13017            }
13018        }
13019    }
13020
13021    pub fn open_permalink_to_line(
13022        &mut self,
13023        _: &OpenPermalinkToLine,
13024        window: &mut Window,
13025        cx: &mut Context<Self>,
13026    ) {
13027        let permalink_task = self.get_permalink_to_line(cx);
13028        let workspace = self.workspace();
13029
13030        cx.spawn_in(window, |_, mut cx| async move {
13031            match permalink_task.await {
13032                Ok(permalink) => {
13033                    cx.update(|_, cx| {
13034                        cx.open_url(permalink.as_ref());
13035                    })
13036                    .ok();
13037                }
13038                Err(err) => {
13039                    let message = format!("Failed to open permalink: {err}");
13040
13041                    Err::<(), anyhow::Error>(err).log_err();
13042
13043                    if let Some(workspace) = workspace {
13044                        workspace
13045                            .update(&mut cx, |workspace, cx| {
13046                                struct OpenPermalinkToLine;
13047
13048                                workspace.show_toast(
13049                                    Toast::new(
13050                                        NotificationId::unique::<OpenPermalinkToLine>(),
13051                                        message,
13052                                    ),
13053                                    cx,
13054                                )
13055                            })
13056                            .ok();
13057                    }
13058                }
13059            }
13060        })
13061        .detach();
13062    }
13063
13064    pub fn insert_uuid_v4(
13065        &mut self,
13066        _: &InsertUuidV4,
13067        window: &mut Window,
13068        cx: &mut Context<Self>,
13069    ) {
13070        self.insert_uuid(UuidVersion::V4, window, cx);
13071    }
13072
13073    pub fn insert_uuid_v7(
13074        &mut self,
13075        _: &InsertUuidV7,
13076        window: &mut Window,
13077        cx: &mut Context<Self>,
13078    ) {
13079        self.insert_uuid(UuidVersion::V7, window, cx);
13080    }
13081
13082    fn insert_uuid(&mut self, version: UuidVersion, window: &mut Window, cx: &mut Context<Self>) {
13083        self.transact(window, cx, |this, window, cx| {
13084            let edits = this
13085                .selections
13086                .all::<Point>(cx)
13087                .into_iter()
13088                .map(|selection| {
13089                    let uuid = match version {
13090                        UuidVersion::V4 => uuid::Uuid::new_v4(),
13091                        UuidVersion::V7 => uuid::Uuid::now_v7(),
13092                    };
13093
13094                    (selection.range(), uuid.to_string())
13095                });
13096            this.edit(edits, cx);
13097            this.refresh_inline_completion(true, false, window, cx);
13098        });
13099    }
13100
13101    pub fn open_selections_in_multibuffer(
13102        &mut self,
13103        _: &OpenSelectionsInMultibuffer,
13104        window: &mut Window,
13105        cx: &mut Context<Self>,
13106    ) {
13107        let multibuffer = self.buffer.read(cx);
13108
13109        let Some(buffer) = multibuffer.as_singleton() else {
13110            return;
13111        };
13112
13113        let Some(workspace) = self.workspace() else {
13114            return;
13115        };
13116
13117        let locations = self
13118            .selections
13119            .disjoint_anchors()
13120            .iter()
13121            .map(|range| Location {
13122                buffer: buffer.clone(),
13123                range: range.start.text_anchor..range.end.text_anchor,
13124            })
13125            .collect::<Vec<_>>();
13126
13127        let title = multibuffer.title(cx).to_string();
13128
13129        cx.spawn_in(window, |_, mut cx| async move {
13130            workspace.update_in(&mut cx, |workspace, window, cx| {
13131                Self::open_locations_in_multibuffer(
13132                    workspace,
13133                    locations,
13134                    format!("Selections for '{title}'"),
13135                    false,
13136                    MultibufferSelectionMode::All,
13137                    window,
13138                    cx,
13139                );
13140            })
13141        })
13142        .detach();
13143    }
13144
13145    /// Adds a row highlight for the given range. If a row has multiple highlights, the
13146    /// last highlight added will be used.
13147    ///
13148    /// If the range ends at the beginning of a line, then that line will not be highlighted.
13149    pub fn highlight_rows<T: 'static>(
13150        &mut self,
13151        range: Range<Anchor>,
13152        color: Hsla,
13153        should_autoscroll: bool,
13154        cx: &mut Context<Self>,
13155    ) {
13156        let snapshot = self.buffer().read(cx).snapshot(cx);
13157        let row_highlights = self.highlighted_rows.entry(TypeId::of::<T>()).or_default();
13158        let ix = row_highlights.binary_search_by(|highlight| {
13159            Ordering::Equal
13160                .then_with(|| highlight.range.start.cmp(&range.start, &snapshot))
13161                .then_with(|| highlight.range.end.cmp(&range.end, &snapshot))
13162        });
13163
13164        if let Err(mut ix) = ix {
13165            let index = post_inc(&mut self.highlight_order);
13166
13167            // If this range intersects with the preceding highlight, then merge it with
13168            // the preceding highlight. Otherwise insert a new highlight.
13169            let mut merged = false;
13170            if ix > 0 {
13171                let prev_highlight = &mut row_highlights[ix - 1];
13172                if prev_highlight
13173                    .range
13174                    .end
13175                    .cmp(&range.start, &snapshot)
13176                    .is_ge()
13177                {
13178                    ix -= 1;
13179                    if prev_highlight.range.end.cmp(&range.end, &snapshot).is_lt() {
13180                        prev_highlight.range.end = range.end;
13181                    }
13182                    merged = true;
13183                    prev_highlight.index = index;
13184                    prev_highlight.color = color;
13185                    prev_highlight.should_autoscroll = should_autoscroll;
13186                }
13187            }
13188
13189            if !merged {
13190                row_highlights.insert(
13191                    ix,
13192                    RowHighlight {
13193                        range: range.clone(),
13194                        index,
13195                        color,
13196                        should_autoscroll,
13197                    },
13198                );
13199            }
13200
13201            // If any of the following highlights intersect with this one, merge them.
13202            while let Some(next_highlight) = row_highlights.get(ix + 1) {
13203                let highlight = &row_highlights[ix];
13204                if next_highlight
13205                    .range
13206                    .start
13207                    .cmp(&highlight.range.end, &snapshot)
13208                    .is_le()
13209                {
13210                    if next_highlight
13211                        .range
13212                        .end
13213                        .cmp(&highlight.range.end, &snapshot)
13214                        .is_gt()
13215                    {
13216                        row_highlights[ix].range.end = next_highlight.range.end;
13217                    }
13218                    row_highlights.remove(ix + 1);
13219                } else {
13220                    break;
13221                }
13222            }
13223        }
13224    }
13225
13226    /// Remove any highlighted row ranges of the given type that intersect the
13227    /// given ranges.
13228    pub fn remove_highlighted_rows<T: 'static>(
13229        &mut self,
13230        ranges_to_remove: Vec<Range<Anchor>>,
13231        cx: &mut Context<Self>,
13232    ) {
13233        let snapshot = self.buffer().read(cx).snapshot(cx);
13234        let row_highlights = self.highlighted_rows.entry(TypeId::of::<T>()).or_default();
13235        let mut ranges_to_remove = ranges_to_remove.iter().peekable();
13236        row_highlights.retain(|highlight| {
13237            while let Some(range_to_remove) = ranges_to_remove.peek() {
13238                match range_to_remove.end.cmp(&highlight.range.start, &snapshot) {
13239                    Ordering::Less | Ordering::Equal => {
13240                        ranges_to_remove.next();
13241                    }
13242                    Ordering::Greater => {
13243                        match range_to_remove.start.cmp(&highlight.range.end, &snapshot) {
13244                            Ordering::Less | Ordering::Equal => {
13245                                return false;
13246                            }
13247                            Ordering::Greater => break,
13248                        }
13249                    }
13250                }
13251            }
13252
13253            true
13254        })
13255    }
13256
13257    /// Clear all anchor ranges for a certain highlight context type, so no corresponding rows will be highlighted.
13258    pub fn clear_row_highlights<T: 'static>(&mut self) {
13259        self.highlighted_rows.remove(&TypeId::of::<T>());
13260    }
13261
13262    /// For a highlight given context type, gets all anchor ranges that will be used for row highlighting.
13263    pub fn highlighted_rows<T: 'static>(&self) -> impl '_ + Iterator<Item = (Range<Anchor>, Hsla)> {
13264        self.highlighted_rows
13265            .get(&TypeId::of::<T>())
13266            .map_or(&[] as &[_], |vec| vec.as_slice())
13267            .iter()
13268            .map(|highlight| (highlight.range.clone(), highlight.color))
13269    }
13270
13271    /// Merges all anchor ranges for all context types ever set, picking the last highlight added in case of a row conflict.
13272    /// Returns a map of display rows that are highlighted and their corresponding highlight color.
13273    /// Allows to ignore certain kinds of highlights.
13274    pub fn highlighted_display_rows(
13275        &self,
13276        window: &mut Window,
13277        cx: &mut App,
13278    ) -> BTreeMap<DisplayRow, Hsla> {
13279        let snapshot = self.snapshot(window, cx);
13280        let mut used_highlight_orders = HashMap::default();
13281        self.highlighted_rows
13282            .iter()
13283            .flat_map(|(_, highlighted_rows)| highlighted_rows.iter())
13284            .fold(
13285                BTreeMap::<DisplayRow, Hsla>::new(),
13286                |mut unique_rows, highlight| {
13287                    let start = highlight.range.start.to_display_point(&snapshot);
13288                    let end = highlight.range.end.to_display_point(&snapshot);
13289                    let start_row = start.row().0;
13290                    let end_row = if highlight.range.end.text_anchor != text::Anchor::MAX
13291                        && end.column() == 0
13292                    {
13293                        end.row().0.saturating_sub(1)
13294                    } else {
13295                        end.row().0
13296                    };
13297                    for row in start_row..=end_row {
13298                        let used_index =
13299                            used_highlight_orders.entry(row).or_insert(highlight.index);
13300                        if highlight.index >= *used_index {
13301                            *used_index = highlight.index;
13302                            unique_rows.insert(DisplayRow(row), highlight.color);
13303                        }
13304                    }
13305                    unique_rows
13306                },
13307            )
13308    }
13309
13310    pub fn highlighted_display_row_for_autoscroll(
13311        &self,
13312        snapshot: &DisplaySnapshot,
13313    ) -> Option<DisplayRow> {
13314        self.highlighted_rows
13315            .values()
13316            .flat_map(|highlighted_rows| highlighted_rows.iter())
13317            .filter_map(|highlight| {
13318                if highlight.should_autoscroll {
13319                    Some(highlight.range.start.to_display_point(snapshot).row())
13320                } else {
13321                    None
13322                }
13323            })
13324            .min()
13325    }
13326
13327    pub fn set_search_within_ranges(&mut self, ranges: &[Range<Anchor>], cx: &mut Context<Self>) {
13328        self.highlight_background::<SearchWithinRange>(
13329            ranges,
13330            |colors| colors.editor_document_highlight_read_background,
13331            cx,
13332        )
13333    }
13334
13335    pub fn set_breadcrumb_header(&mut self, new_header: String) {
13336        self.breadcrumb_header = Some(new_header);
13337    }
13338
13339    pub fn clear_search_within_ranges(&mut self, cx: &mut Context<Self>) {
13340        self.clear_background_highlights::<SearchWithinRange>(cx);
13341    }
13342
13343    pub fn highlight_background<T: 'static>(
13344        &mut self,
13345        ranges: &[Range<Anchor>],
13346        color_fetcher: fn(&ThemeColors) -> Hsla,
13347        cx: &mut Context<Self>,
13348    ) {
13349        self.background_highlights
13350            .insert(TypeId::of::<T>(), (color_fetcher, Arc::from(ranges)));
13351        self.scrollbar_marker_state.dirty = true;
13352        cx.notify();
13353    }
13354
13355    pub fn clear_background_highlights<T: 'static>(
13356        &mut self,
13357        cx: &mut Context<Self>,
13358    ) -> Option<BackgroundHighlight> {
13359        let text_highlights = self.background_highlights.remove(&TypeId::of::<T>())?;
13360        if !text_highlights.1.is_empty() {
13361            self.scrollbar_marker_state.dirty = true;
13362            cx.notify();
13363        }
13364        Some(text_highlights)
13365    }
13366
13367    pub fn highlight_gutter<T: 'static>(
13368        &mut self,
13369        ranges: &[Range<Anchor>],
13370        color_fetcher: fn(&App) -> Hsla,
13371        cx: &mut Context<Self>,
13372    ) {
13373        self.gutter_highlights
13374            .insert(TypeId::of::<T>(), (color_fetcher, Arc::from(ranges)));
13375        cx.notify();
13376    }
13377
13378    pub fn clear_gutter_highlights<T: 'static>(
13379        &mut self,
13380        cx: &mut Context<Self>,
13381    ) -> Option<GutterHighlight> {
13382        cx.notify();
13383        self.gutter_highlights.remove(&TypeId::of::<T>())
13384    }
13385
13386    #[cfg(feature = "test-support")]
13387    pub fn all_text_background_highlights(
13388        &self,
13389        window: &mut Window,
13390        cx: &mut Context<Self>,
13391    ) -> Vec<(Range<DisplayPoint>, Hsla)> {
13392        let snapshot = self.snapshot(window, cx);
13393        let buffer = &snapshot.buffer_snapshot;
13394        let start = buffer.anchor_before(0);
13395        let end = buffer.anchor_after(buffer.len());
13396        let theme = cx.theme().colors();
13397        self.background_highlights_in_range(start..end, &snapshot, theme)
13398    }
13399
13400    #[cfg(feature = "test-support")]
13401    pub fn search_background_highlights(&mut self, cx: &mut Context<Self>) -> Vec<Range<Point>> {
13402        let snapshot = self.buffer().read(cx).snapshot(cx);
13403
13404        let highlights = self
13405            .background_highlights
13406            .get(&TypeId::of::<items::BufferSearchHighlights>());
13407
13408        if let Some((_color, ranges)) = highlights {
13409            ranges
13410                .iter()
13411                .map(|range| range.start.to_point(&snapshot)..range.end.to_point(&snapshot))
13412                .collect_vec()
13413        } else {
13414            vec![]
13415        }
13416    }
13417
13418    fn document_highlights_for_position<'a>(
13419        &'a self,
13420        position: Anchor,
13421        buffer: &'a MultiBufferSnapshot,
13422    ) -> impl 'a + Iterator<Item = &'a Range<Anchor>> {
13423        let read_highlights = self
13424            .background_highlights
13425            .get(&TypeId::of::<DocumentHighlightRead>())
13426            .map(|h| &h.1);
13427        let write_highlights = self
13428            .background_highlights
13429            .get(&TypeId::of::<DocumentHighlightWrite>())
13430            .map(|h| &h.1);
13431        let left_position = position.bias_left(buffer);
13432        let right_position = position.bias_right(buffer);
13433        read_highlights
13434            .into_iter()
13435            .chain(write_highlights)
13436            .flat_map(move |ranges| {
13437                let start_ix = match ranges.binary_search_by(|probe| {
13438                    let cmp = probe.end.cmp(&left_position, buffer);
13439                    if cmp.is_ge() {
13440                        Ordering::Greater
13441                    } else {
13442                        Ordering::Less
13443                    }
13444                }) {
13445                    Ok(i) | Err(i) => i,
13446                };
13447
13448                ranges[start_ix..]
13449                    .iter()
13450                    .take_while(move |range| range.start.cmp(&right_position, buffer).is_le())
13451            })
13452    }
13453
13454    pub fn has_background_highlights<T: 'static>(&self) -> bool {
13455        self.background_highlights
13456            .get(&TypeId::of::<T>())
13457            .map_or(false, |(_, highlights)| !highlights.is_empty())
13458    }
13459
13460    pub fn background_highlights_in_range(
13461        &self,
13462        search_range: Range<Anchor>,
13463        display_snapshot: &DisplaySnapshot,
13464        theme: &ThemeColors,
13465    ) -> Vec<(Range<DisplayPoint>, Hsla)> {
13466        let mut results = Vec::new();
13467        for (color_fetcher, ranges) in self.background_highlights.values() {
13468            let color = color_fetcher(theme);
13469            let start_ix = match ranges.binary_search_by(|probe| {
13470                let cmp = probe
13471                    .end
13472                    .cmp(&search_range.start, &display_snapshot.buffer_snapshot);
13473                if cmp.is_gt() {
13474                    Ordering::Greater
13475                } else {
13476                    Ordering::Less
13477                }
13478            }) {
13479                Ok(i) | Err(i) => i,
13480            };
13481            for range in &ranges[start_ix..] {
13482                if range
13483                    .start
13484                    .cmp(&search_range.end, &display_snapshot.buffer_snapshot)
13485                    .is_ge()
13486                {
13487                    break;
13488                }
13489
13490                let start = range.start.to_display_point(display_snapshot);
13491                let end = range.end.to_display_point(display_snapshot);
13492                results.push((start..end, color))
13493            }
13494        }
13495        results
13496    }
13497
13498    pub fn background_highlight_row_ranges<T: 'static>(
13499        &self,
13500        search_range: Range<Anchor>,
13501        display_snapshot: &DisplaySnapshot,
13502        count: usize,
13503    ) -> Vec<RangeInclusive<DisplayPoint>> {
13504        let mut results = Vec::new();
13505        let Some((_, ranges)) = self.background_highlights.get(&TypeId::of::<T>()) else {
13506            return vec![];
13507        };
13508
13509        let start_ix = match ranges.binary_search_by(|probe| {
13510            let cmp = probe
13511                .end
13512                .cmp(&search_range.start, &display_snapshot.buffer_snapshot);
13513            if cmp.is_gt() {
13514                Ordering::Greater
13515            } else {
13516                Ordering::Less
13517            }
13518        }) {
13519            Ok(i) | Err(i) => i,
13520        };
13521        let mut push_region = |start: Option<Point>, end: Option<Point>| {
13522            if let (Some(start_display), Some(end_display)) = (start, end) {
13523                results.push(
13524                    start_display.to_display_point(display_snapshot)
13525                        ..=end_display.to_display_point(display_snapshot),
13526                );
13527            }
13528        };
13529        let mut start_row: Option<Point> = None;
13530        let mut end_row: Option<Point> = None;
13531        if ranges.len() > count {
13532            return Vec::new();
13533        }
13534        for range in &ranges[start_ix..] {
13535            if range
13536                .start
13537                .cmp(&search_range.end, &display_snapshot.buffer_snapshot)
13538                .is_ge()
13539            {
13540                break;
13541            }
13542            let end = range.end.to_point(&display_snapshot.buffer_snapshot);
13543            if let Some(current_row) = &end_row {
13544                if end.row == current_row.row {
13545                    continue;
13546                }
13547            }
13548            let start = range.start.to_point(&display_snapshot.buffer_snapshot);
13549            if start_row.is_none() {
13550                assert_eq!(end_row, None);
13551                start_row = Some(start);
13552                end_row = Some(end);
13553                continue;
13554            }
13555            if let Some(current_end) = end_row.as_mut() {
13556                if start.row > current_end.row + 1 {
13557                    push_region(start_row, end_row);
13558                    start_row = Some(start);
13559                    end_row = Some(end);
13560                } else {
13561                    // Merge two hunks.
13562                    *current_end = end;
13563                }
13564            } else {
13565                unreachable!();
13566            }
13567        }
13568        // We might still have a hunk that was not rendered (if there was a search hit on the last line)
13569        push_region(start_row, end_row);
13570        results
13571    }
13572
13573    pub fn gutter_highlights_in_range(
13574        &self,
13575        search_range: Range<Anchor>,
13576        display_snapshot: &DisplaySnapshot,
13577        cx: &App,
13578    ) -> Vec<(Range<DisplayPoint>, Hsla)> {
13579        let mut results = Vec::new();
13580        for (color_fetcher, ranges) in self.gutter_highlights.values() {
13581            let color = color_fetcher(cx);
13582            let start_ix = match ranges.binary_search_by(|probe| {
13583                let cmp = probe
13584                    .end
13585                    .cmp(&search_range.start, &display_snapshot.buffer_snapshot);
13586                if cmp.is_gt() {
13587                    Ordering::Greater
13588                } else {
13589                    Ordering::Less
13590                }
13591            }) {
13592                Ok(i) | Err(i) => i,
13593            };
13594            for range in &ranges[start_ix..] {
13595                if range
13596                    .start
13597                    .cmp(&search_range.end, &display_snapshot.buffer_snapshot)
13598                    .is_ge()
13599                {
13600                    break;
13601                }
13602
13603                let start = range.start.to_display_point(display_snapshot);
13604                let end = range.end.to_display_point(display_snapshot);
13605                results.push((start..end, color))
13606            }
13607        }
13608        results
13609    }
13610
13611    /// Get the text ranges corresponding to the redaction query
13612    pub fn redacted_ranges(
13613        &self,
13614        search_range: Range<Anchor>,
13615        display_snapshot: &DisplaySnapshot,
13616        cx: &App,
13617    ) -> Vec<Range<DisplayPoint>> {
13618        display_snapshot
13619            .buffer_snapshot
13620            .redacted_ranges(search_range, |file| {
13621                if let Some(file) = file {
13622                    file.is_private()
13623                        && EditorSettings::get(
13624                            Some(SettingsLocation {
13625                                worktree_id: file.worktree_id(cx),
13626                                path: file.path().as_ref(),
13627                            }),
13628                            cx,
13629                        )
13630                        .redact_private_values
13631                } else {
13632                    false
13633                }
13634            })
13635            .map(|range| {
13636                range.start.to_display_point(display_snapshot)
13637                    ..range.end.to_display_point(display_snapshot)
13638            })
13639            .collect()
13640    }
13641
13642    pub fn highlight_text<T: 'static>(
13643        &mut self,
13644        ranges: Vec<Range<Anchor>>,
13645        style: HighlightStyle,
13646        cx: &mut Context<Self>,
13647    ) {
13648        self.display_map.update(cx, |map, _| {
13649            map.highlight_text(TypeId::of::<T>(), ranges, style)
13650        });
13651        cx.notify();
13652    }
13653
13654    pub(crate) fn highlight_inlays<T: 'static>(
13655        &mut self,
13656        highlights: Vec<InlayHighlight>,
13657        style: HighlightStyle,
13658        cx: &mut Context<Self>,
13659    ) {
13660        self.display_map.update(cx, |map, _| {
13661            map.highlight_inlays(TypeId::of::<T>(), highlights, style)
13662        });
13663        cx.notify();
13664    }
13665
13666    pub fn text_highlights<'a, T: 'static>(
13667        &'a self,
13668        cx: &'a App,
13669    ) -> Option<(HighlightStyle, &'a [Range<Anchor>])> {
13670        self.display_map.read(cx).text_highlights(TypeId::of::<T>())
13671    }
13672
13673    pub fn clear_highlights<T: 'static>(&mut self, cx: &mut Context<Self>) {
13674        let cleared = self
13675            .display_map
13676            .update(cx, |map, _| map.clear_highlights(TypeId::of::<T>()));
13677        if cleared {
13678            cx.notify();
13679        }
13680    }
13681
13682    pub fn show_local_cursors(&self, window: &mut Window, cx: &mut App) -> bool {
13683        (self.read_only(cx) || self.blink_manager.read(cx).visible())
13684            && self.focus_handle.is_focused(window)
13685    }
13686
13687    pub fn set_show_cursor_when_unfocused(&mut self, is_enabled: bool, cx: &mut Context<Self>) {
13688        self.show_cursor_when_unfocused = is_enabled;
13689        cx.notify();
13690    }
13691
13692    pub fn lsp_store(&self, cx: &App) -> Option<Entity<LspStore>> {
13693        self.project
13694            .as_ref()
13695            .map(|project| project.read(cx).lsp_store())
13696    }
13697
13698    fn on_buffer_changed(&mut self, _: Entity<MultiBuffer>, cx: &mut Context<Self>) {
13699        cx.notify();
13700    }
13701
13702    fn on_buffer_event(
13703        &mut self,
13704        multibuffer: &Entity<MultiBuffer>,
13705        event: &multi_buffer::Event,
13706        window: &mut Window,
13707        cx: &mut Context<Self>,
13708    ) {
13709        match event {
13710            multi_buffer::Event::Edited {
13711                singleton_buffer_edited,
13712                edited_buffer: buffer_edited,
13713            } => {
13714                self.scrollbar_marker_state.dirty = true;
13715                self.active_indent_guides_state.dirty = true;
13716                self.refresh_active_diagnostics(cx);
13717                self.refresh_code_actions(window, cx);
13718                if self.has_active_inline_completion() {
13719                    self.update_visible_inline_completion(window, cx);
13720                }
13721                if let Some(buffer) = buffer_edited {
13722                    let buffer_id = buffer.read(cx).remote_id();
13723                    if !self.registered_buffers.contains_key(&buffer_id) {
13724                        if let Some(lsp_store) = self.lsp_store(cx) {
13725                            lsp_store.update(cx, |lsp_store, cx| {
13726                                self.registered_buffers.insert(
13727                                    buffer_id,
13728                                    lsp_store.register_buffer_with_language_servers(&buffer, cx),
13729                                );
13730                            })
13731                        }
13732                    }
13733                }
13734                cx.emit(EditorEvent::BufferEdited);
13735                cx.emit(SearchEvent::MatchesInvalidated);
13736                if *singleton_buffer_edited {
13737                    if let Some(project) = &self.project {
13738                        let project = project.read(cx);
13739                        #[allow(clippy::mutable_key_type)]
13740                        let languages_affected = multibuffer
13741                            .read(cx)
13742                            .all_buffers()
13743                            .into_iter()
13744                            .filter_map(|buffer| {
13745                                let buffer = buffer.read(cx);
13746                                let language = buffer.language()?;
13747                                if project.is_local()
13748                                    && project
13749                                        .language_servers_for_local_buffer(buffer, cx)
13750                                        .count()
13751                                        == 0
13752                                {
13753                                    None
13754                                } else {
13755                                    Some(language)
13756                                }
13757                            })
13758                            .cloned()
13759                            .collect::<HashSet<_>>();
13760                        if !languages_affected.is_empty() {
13761                            self.refresh_inlay_hints(
13762                                InlayHintRefreshReason::BufferEdited(languages_affected),
13763                                cx,
13764                            );
13765                        }
13766                    }
13767                }
13768
13769                let Some(project) = &self.project else { return };
13770                let (telemetry, is_via_ssh) = {
13771                    let project = project.read(cx);
13772                    let telemetry = project.client().telemetry().clone();
13773                    let is_via_ssh = project.is_via_ssh();
13774                    (telemetry, is_via_ssh)
13775                };
13776                refresh_linked_ranges(self, window, cx);
13777                telemetry.log_edit_event("editor", is_via_ssh);
13778            }
13779            multi_buffer::Event::ExcerptsAdded {
13780                buffer,
13781                predecessor,
13782                excerpts,
13783            } => {
13784                self.tasks_update_task = Some(self.refresh_runnables(window, cx));
13785                let buffer_id = buffer.read(cx).remote_id();
13786                if self.buffer.read(cx).diff_for(buffer_id).is_none() {
13787                    if let Some(project) = &self.project {
13788                        get_uncommitted_diff_for_buffer(
13789                            project,
13790                            [buffer.clone()],
13791                            self.buffer.clone(),
13792                            cx,
13793                        );
13794                    }
13795                }
13796                cx.emit(EditorEvent::ExcerptsAdded {
13797                    buffer: buffer.clone(),
13798                    predecessor: *predecessor,
13799                    excerpts: excerpts.clone(),
13800                });
13801                self.refresh_inlay_hints(InlayHintRefreshReason::NewLinesShown, cx);
13802            }
13803            multi_buffer::Event::ExcerptsRemoved { ids } => {
13804                self.refresh_inlay_hints(InlayHintRefreshReason::ExcerptsRemoved(ids.clone()), cx);
13805                let buffer = self.buffer.read(cx);
13806                self.registered_buffers
13807                    .retain(|buffer_id, _| buffer.buffer(*buffer_id).is_some());
13808                cx.emit(EditorEvent::ExcerptsRemoved { ids: ids.clone() })
13809            }
13810            multi_buffer::Event::ExcerptsEdited { ids } => {
13811                cx.emit(EditorEvent::ExcerptsEdited { ids: ids.clone() })
13812            }
13813            multi_buffer::Event::ExcerptsExpanded { ids } => {
13814                self.refresh_inlay_hints(InlayHintRefreshReason::NewLinesShown, cx);
13815                cx.emit(EditorEvent::ExcerptsExpanded { ids: ids.clone() })
13816            }
13817            multi_buffer::Event::Reparsed(buffer_id) => {
13818                self.tasks_update_task = Some(self.refresh_runnables(window, cx));
13819
13820                cx.emit(EditorEvent::Reparsed(*buffer_id));
13821            }
13822            multi_buffer::Event::DiffHunksToggled => {
13823                self.tasks_update_task = Some(self.refresh_runnables(window, cx));
13824            }
13825            multi_buffer::Event::LanguageChanged(buffer_id) => {
13826                linked_editing_ranges::refresh_linked_ranges(self, window, cx);
13827                cx.emit(EditorEvent::Reparsed(*buffer_id));
13828                cx.notify();
13829            }
13830            multi_buffer::Event::DirtyChanged => cx.emit(EditorEvent::DirtyChanged),
13831            multi_buffer::Event::Saved => cx.emit(EditorEvent::Saved),
13832            multi_buffer::Event::FileHandleChanged | multi_buffer::Event::Reloaded => {
13833                cx.emit(EditorEvent::TitleChanged)
13834            }
13835            // multi_buffer::Event::DiffBaseChanged => {
13836            //     self.scrollbar_marker_state.dirty = true;
13837            //     cx.emit(EditorEvent::DiffBaseChanged);
13838            //     cx.notify();
13839            // }
13840            multi_buffer::Event::Closed => cx.emit(EditorEvent::Closed),
13841            multi_buffer::Event::DiagnosticsUpdated => {
13842                self.refresh_active_diagnostics(cx);
13843                self.scrollbar_marker_state.dirty = true;
13844                cx.notify();
13845            }
13846            _ => {}
13847        };
13848    }
13849
13850    fn on_display_map_changed(
13851        &mut self,
13852        _: Entity<DisplayMap>,
13853        _: &mut Window,
13854        cx: &mut Context<Self>,
13855    ) {
13856        cx.notify();
13857    }
13858
13859    fn settings_changed(&mut self, window: &mut Window, cx: &mut Context<Self>) {
13860        self.tasks_update_task = Some(self.refresh_runnables(window, cx));
13861        self.refresh_inline_completion(true, false, window, cx);
13862        self.refresh_inlay_hints(
13863            InlayHintRefreshReason::SettingsChange(inlay_hint_settings(
13864                self.selections.newest_anchor().head(),
13865                &self.buffer.read(cx).snapshot(cx),
13866                cx,
13867            )),
13868            cx,
13869        );
13870
13871        let old_cursor_shape = self.cursor_shape;
13872
13873        {
13874            let editor_settings = EditorSettings::get_global(cx);
13875            self.scroll_manager.vertical_scroll_margin = editor_settings.vertical_scroll_margin;
13876            self.show_breadcrumbs = editor_settings.toolbar.breadcrumbs;
13877            self.cursor_shape = editor_settings.cursor_shape.unwrap_or_default();
13878        }
13879
13880        if old_cursor_shape != self.cursor_shape {
13881            cx.emit(EditorEvent::CursorShapeChanged);
13882        }
13883
13884        let project_settings = ProjectSettings::get_global(cx);
13885        self.serialize_dirty_buffers = project_settings.session.restore_unsaved_buffers;
13886
13887        if self.mode == EditorMode::Full {
13888            let inline_blame_enabled = project_settings.git.inline_blame_enabled();
13889            if self.git_blame_inline_enabled != inline_blame_enabled {
13890                self.toggle_git_blame_inline_internal(false, window, cx);
13891            }
13892        }
13893
13894        cx.notify();
13895    }
13896
13897    pub fn set_searchable(&mut self, searchable: bool) {
13898        self.searchable = searchable;
13899    }
13900
13901    pub fn searchable(&self) -> bool {
13902        self.searchable
13903    }
13904
13905    fn open_proposed_changes_editor(
13906        &mut self,
13907        _: &OpenProposedChangesEditor,
13908        window: &mut Window,
13909        cx: &mut Context<Self>,
13910    ) {
13911        let Some(workspace) = self.workspace() else {
13912            cx.propagate();
13913            return;
13914        };
13915
13916        let selections = self.selections.all::<usize>(cx);
13917        let multi_buffer = self.buffer.read(cx);
13918        let multi_buffer_snapshot = multi_buffer.snapshot(cx);
13919        let mut new_selections_by_buffer = HashMap::default();
13920        for selection in selections {
13921            for (buffer, range, _) in
13922                multi_buffer_snapshot.range_to_buffer_ranges(selection.start..selection.end)
13923            {
13924                let mut range = range.to_point(buffer);
13925                range.start.column = 0;
13926                range.end.column = buffer.line_len(range.end.row);
13927                new_selections_by_buffer
13928                    .entry(multi_buffer.buffer(buffer.remote_id()).unwrap())
13929                    .or_insert(Vec::new())
13930                    .push(range)
13931            }
13932        }
13933
13934        let proposed_changes_buffers = new_selections_by_buffer
13935            .into_iter()
13936            .map(|(buffer, ranges)| ProposedChangeLocation { buffer, ranges })
13937            .collect::<Vec<_>>();
13938        let proposed_changes_editor = cx.new(|cx| {
13939            ProposedChangesEditor::new(
13940                "Proposed changes",
13941                proposed_changes_buffers,
13942                self.project.clone(),
13943                window,
13944                cx,
13945            )
13946        });
13947
13948        window.defer(cx, move |window, cx| {
13949            workspace.update(cx, |workspace, cx| {
13950                workspace.active_pane().update(cx, |pane, cx| {
13951                    pane.add_item(
13952                        Box::new(proposed_changes_editor),
13953                        true,
13954                        true,
13955                        None,
13956                        window,
13957                        cx,
13958                    );
13959                });
13960            });
13961        });
13962    }
13963
13964    pub fn open_excerpts_in_split(
13965        &mut self,
13966        _: &OpenExcerptsSplit,
13967        window: &mut Window,
13968        cx: &mut Context<Self>,
13969    ) {
13970        self.open_excerpts_common(None, true, window, cx)
13971    }
13972
13973    pub fn open_excerpts(&mut self, _: &OpenExcerpts, window: &mut Window, cx: &mut Context<Self>) {
13974        self.open_excerpts_common(None, false, window, cx)
13975    }
13976
13977    fn open_excerpts_common(
13978        &mut self,
13979        jump_data: Option<JumpData>,
13980        split: bool,
13981        window: &mut Window,
13982        cx: &mut Context<Self>,
13983    ) {
13984        let Some(workspace) = self.workspace() else {
13985            cx.propagate();
13986            return;
13987        };
13988
13989        if self.buffer.read(cx).is_singleton() {
13990            cx.propagate();
13991            return;
13992        }
13993
13994        let mut new_selections_by_buffer = HashMap::default();
13995        match &jump_data {
13996            Some(JumpData::MultiBufferPoint {
13997                excerpt_id,
13998                position,
13999                anchor,
14000                line_offset_from_top,
14001            }) => {
14002                let multi_buffer_snapshot = self.buffer.read(cx).snapshot(cx);
14003                if let Some(buffer) = multi_buffer_snapshot
14004                    .buffer_id_for_excerpt(*excerpt_id)
14005                    .and_then(|buffer_id| self.buffer.read(cx).buffer(buffer_id))
14006                {
14007                    let buffer_snapshot = buffer.read(cx).snapshot();
14008                    let jump_to_point = if buffer_snapshot.can_resolve(anchor) {
14009                        language::ToPoint::to_point(anchor, &buffer_snapshot)
14010                    } else {
14011                        buffer_snapshot.clip_point(*position, Bias::Left)
14012                    };
14013                    let jump_to_offset = buffer_snapshot.point_to_offset(jump_to_point);
14014                    new_selections_by_buffer.insert(
14015                        buffer,
14016                        (
14017                            vec![jump_to_offset..jump_to_offset],
14018                            Some(*line_offset_from_top),
14019                        ),
14020                    );
14021                }
14022            }
14023            Some(JumpData::MultiBufferRow {
14024                row,
14025                line_offset_from_top,
14026            }) => {
14027                let point = MultiBufferPoint::new(row.0, 0);
14028                if let Some((buffer, buffer_point, _)) =
14029                    self.buffer.read(cx).point_to_buffer_point(point, cx)
14030                {
14031                    let buffer_offset = buffer.read(cx).point_to_offset(buffer_point);
14032                    new_selections_by_buffer
14033                        .entry(buffer)
14034                        .or_insert((Vec::new(), Some(*line_offset_from_top)))
14035                        .0
14036                        .push(buffer_offset..buffer_offset)
14037                }
14038            }
14039            None => {
14040                let selections = self.selections.all::<usize>(cx);
14041                let multi_buffer = self.buffer.read(cx);
14042                for selection in selections {
14043                    for (buffer, mut range, _) in multi_buffer
14044                        .snapshot(cx)
14045                        .range_to_buffer_ranges(selection.range())
14046                    {
14047                        // When editing branch buffers, jump to the corresponding location
14048                        // in their base buffer.
14049                        let mut buffer_handle = multi_buffer.buffer(buffer.remote_id()).unwrap();
14050                        let buffer = buffer_handle.read(cx);
14051                        if let Some(base_buffer) = buffer.base_buffer() {
14052                            range = buffer.range_to_version(range, &base_buffer.read(cx).version());
14053                            buffer_handle = base_buffer;
14054                        }
14055
14056                        if selection.reversed {
14057                            mem::swap(&mut range.start, &mut range.end);
14058                        }
14059                        new_selections_by_buffer
14060                            .entry(buffer_handle)
14061                            .or_insert((Vec::new(), None))
14062                            .0
14063                            .push(range)
14064                    }
14065                }
14066            }
14067        }
14068
14069        if new_selections_by_buffer.is_empty() {
14070            return;
14071        }
14072
14073        // We defer the pane interaction because we ourselves are a workspace item
14074        // and activating a new item causes the pane to call a method on us reentrantly,
14075        // which panics if we're on the stack.
14076        window.defer(cx, move |window, cx| {
14077            workspace.update(cx, |workspace, cx| {
14078                let pane = if split {
14079                    workspace.adjacent_pane(window, cx)
14080                } else {
14081                    workspace.active_pane().clone()
14082                };
14083
14084                for (buffer, (ranges, scroll_offset)) in new_selections_by_buffer {
14085                    let editor = buffer
14086                        .read(cx)
14087                        .file()
14088                        .is_none()
14089                        .then(|| {
14090                            // Handle file-less buffers separately: those are not really the project items, so won't have a project path or entity id,
14091                            // so `workspace.open_project_item` will never find them, always opening a new editor.
14092                            // Instead, we try to activate the existing editor in the pane first.
14093                            let (editor, pane_item_index) =
14094                                pane.read(cx).items().enumerate().find_map(|(i, item)| {
14095                                    let editor = item.downcast::<Editor>()?;
14096                                    let singleton_buffer =
14097                                        editor.read(cx).buffer().read(cx).as_singleton()?;
14098                                    if singleton_buffer == buffer {
14099                                        Some((editor, i))
14100                                    } else {
14101                                        None
14102                                    }
14103                                })?;
14104                            pane.update(cx, |pane, cx| {
14105                                pane.activate_item(pane_item_index, true, true, window, cx)
14106                            });
14107                            Some(editor)
14108                        })
14109                        .flatten()
14110                        .unwrap_or_else(|| {
14111                            workspace.open_project_item::<Self>(
14112                                pane.clone(),
14113                                buffer,
14114                                true,
14115                                true,
14116                                window,
14117                                cx,
14118                            )
14119                        });
14120
14121                    editor.update(cx, |editor, cx| {
14122                        let autoscroll = match scroll_offset {
14123                            Some(scroll_offset) => Autoscroll::top_relative(scroll_offset as usize),
14124                            None => Autoscroll::newest(),
14125                        };
14126                        let nav_history = editor.nav_history.take();
14127                        editor.change_selections(Some(autoscroll), window, cx, |s| {
14128                            s.select_ranges(ranges);
14129                        });
14130                        editor.nav_history = nav_history;
14131                    });
14132                }
14133            })
14134        });
14135    }
14136
14137    fn marked_text_ranges(&self, cx: &App) -> Option<Vec<Range<OffsetUtf16>>> {
14138        let snapshot = self.buffer.read(cx).read(cx);
14139        let (_, ranges) = self.text_highlights::<InputComposition>(cx)?;
14140        Some(
14141            ranges
14142                .iter()
14143                .map(move |range| {
14144                    range.start.to_offset_utf16(&snapshot)..range.end.to_offset_utf16(&snapshot)
14145                })
14146                .collect(),
14147        )
14148    }
14149
14150    fn selection_replacement_ranges(
14151        &self,
14152        range: Range<OffsetUtf16>,
14153        cx: &mut App,
14154    ) -> Vec<Range<OffsetUtf16>> {
14155        let selections = self.selections.all::<OffsetUtf16>(cx);
14156        let newest_selection = selections
14157            .iter()
14158            .max_by_key(|selection| selection.id)
14159            .unwrap();
14160        let start_delta = range.start.0 as isize - newest_selection.start.0 as isize;
14161        let end_delta = range.end.0 as isize - newest_selection.end.0 as isize;
14162        let snapshot = self.buffer.read(cx).read(cx);
14163        selections
14164            .into_iter()
14165            .map(|mut selection| {
14166                selection.start.0 =
14167                    (selection.start.0 as isize).saturating_add(start_delta) as usize;
14168                selection.end.0 = (selection.end.0 as isize).saturating_add(end_delta) as usize;
14169                snapshot.clip_offset_utf16(selection.start, Bias::Left)
14170                    ..snapshot.clip_offset_utf16(selection.end, Bias::Right)
14171            })
14172            .collect()
14173    }
14174
14175    fn report_editor_event(
14176        &self,
14177        event_type: &'static str,
14178        file_extension: Option<String>,
14179        cx: &App,
14180    ) {
14181        if cfg!(any(test, feature = "test-support")) {
14182            return;
14183        }
14184
14185        let Some(project) = &self.project else { return };
14186
14187        // If None, we are in a file without an extension
14188        let file = self
14189            .buffer
14190            .read(cx)
14191            .as_singleton()
14192            .and_then(|b| b.read(cx).file());
14193        let file_extension = file_extension.or(file
14194            .as_ref()
14195            .and_then(|file| Path::new(file.file_name(cx)).extension())
14196            .and_then(|e| e.to_str())
14197            .map(|a| a.to_string()));
14198
14199        let vim_mode = cx
14200            .global::<SettingsStore>()
14201            .raw_user_settings()
14202            .get("vim_mode")
14203            == Some(&serde_json::Value::Bool(true));
14204
14205        let edit_predictions_provider = all_language_settings(file, cx).edit_predictions.provider;
14206        let copilot_enabled = edit_predictions_provider
14207            == language::language_settings::EditPredictionProvider::Copilot;
14208        let copilot_enabled_for_language = self
14209            .buffer
14210            .read(cx)
14211            .settings_at(0, cx)
14212            .show_edit_predictions;
14213
14214        let project = project.read(cx);
14215        telemetry::event!(
14216            event_type,
14217            file_extension,
14218            vim_mode,
14219            copilot_enabled,
14220            copilot_enabled_for_language,
14221            edit_predictions_provider,
14222            is_via_ssh = project.is_via_ssh(),
14223        );
14224    }
14225
14226    /// Copy the highlighted chunks to the clipboard as JSON. The format is an array of lines,
14227    /// with each line being an array of {text, highlight} objects.
14228    fn copy_highlight_json(
14229        &mut self,
14230        _: &CopyHighlightJson,
14231        window: &mut Window,
14232        cx: &mut Context<Self>,
14233    ) {
14234        #[derive(Serialize)]
14235        struct Chunk<'a> {
14236            text: String,
14237            highlight: Option<&'a str>,
14238        }
14239
14240        let snapshot = self.buffer.read(cx).snapshot(cx);
14241        let range = self
14242            .selected_text_range(false, window, cx)
14243            .and_then(|selection| {
14244                if selection.range.is_empty() {
14245                    None
14246                } else {
14247                    Some(selection.range)
14248                }
14249            })
14250            .unwrap_or_else(|| 0..snapshot.len());
14251
14252        let chunks = snapshot.chunks(range, true);
14253        let mut lines = Vec::new();
14254        let mut line: VecDeque<Chunk> = VecDeque::new();
14255
14256        let Some(style) = self.style.as_ref() else {
14257            return;
14258        };
14259
14260        for chunk in chunks {
14261            let highlight = chunk
14262                .syntax_highlight_id
14263                .and_then(|id| id.name(&style.syntax));
14264            let mut chunk_lines = chunk.text.split('\n').peekable();
14265            while let Some(text) = chunk_lines.next() {
14266                let mut merged_with_last_token = false;
14267                if let Some(last_token) = line.back_mut() {
14268                    if last_token.highlight == highlight {
14269                        last_token.text.push_str(text);
14270                        merged_with_last_token = true;
14271                    }
14272                }
14273
14274                if !merged_with_last_token {
14275                    line.push_back(Chunk {
14276                        text: text.into(),
14277                        highlight,
14278                    });
14279                }
14280
14281                if chunk_lines.peek().is_some() {
14282                    if line.len() > 1 && line.front().unwrap().text.is_empty() {
14283                        line.pop_front();
14284                    }
14285                    if line.len() > 1 && line.back().unwrap().text.is_empty() {
14286                        line.pop_back();
14287                    }
14288
14289                    lines.push(mem::take(&mut line));
14290                }
14291            }
14292        }
14293
14294        let Some(lines) = serde_json::to_string_pretty(&lines).log_err() else {
14295            return;
14296        };
14297        cx.write_to_clipboard(ClipboardItem::new_string(lines));
14298    }
14299
14300    pub fn open_context_menu(
14301        &mut self,
14302        _: &OpenContextMenu,
14303        window: &mut Window,
14304        cx: &mut Context<Self>,
14305    ) {
14306        self.request_autoscroll(Autoscroll::newest(), cx);
14307        let position = self.selections.newest_display(cx).start;
14308        mouse_context_menu::deploy_context_menu(self, None, position, window, cx);
14309    }
14310
14311    pub fn inlay_hint_cache(&self) -> &InlayHintCache {
14312        &self.inlay_hint_cache
14313    }
14314
14315    pub fn replay_insert_event(
14316        &mut self,
14317        text: &str,
14318        relative_utf16_range: Option<Range<isize>>,
14319        window: &mut Window,
14320        cx: &mut Context<Self>,
14321    ) {
14322        if !self.input_enabled {
14323            cx.emit(EditorEvent::InputIgnored { text: text.into() });
14324            return;
14325        }
14326        if let Some(relative_utf16_range) = relative_utf16_range {
14327            let selections = self.selections.all::<OffsetUtf16>(cx);
14328            self.change_selections(None, window, cx, |s| {
14329                let new_ranges = selections.into_iter().map(|range| {
14330                    let start = OffsetUtf16(
14331                        range
14332                            .head()
14333                            .0
14334                            .saturating_add_signed(relative_utf16_range.start),
14335                    );
14336                    let end = OffsetUtf16(
14337                        range
14338                            .head()
14339                            .0
14340                            .saturating_add_signed(relative_utf16_range.end),
14341                    );
14342                    start..end
14343                });
14344                s.select_ranges(new_ranges);
14345            });
14346        }
14347
14348        self.handle_input(text, window, cx);
14349    }
14350
14351    pub fn supports_inlay_hints(&self, cx: &App) -> bool {
14352        let Some(provider) = self.semantics_provider.as_ref() else {
14353            return false;
14354        };
14355
14356        let mut supports = false;
14357        self.buffer().read(cx).for_each_buffer(|buffer| {
14358            supports |= provider.supports_inlay_hints(buffer, cx);
14359        });
14360        supports
14361    }
14362    pub fn is_focused(&self, window: &mut Window) -> bool {
14363        self.focus_handle.is_focused(window)
14364    }
14365
14366    fn handle_focus(&mut self, window: &mut Window, cx: &mut Context<Self>) {
14367        cx.emit(EditorEvent::Focused);
14368
14369        if let Some(descendant) = self
14370            .last_focused_descendant
14371            .take()
14372            .and_then(|descendant| descendant.upgrade())
14373        {
14374            window.focus(&descendant);
14375        } else {
14376            if let Some(blame) = self.blame.as_ref() {
14377                blame.update(cx, GitBlame::focus)
14378            }
14379
14380            self.blink_manager.update(cx, BlinkManager::enable);
14381            self.show_cursor_names(window, cx);
14382            self.buffer.update(cx, |buffer, cx| {
14383                buffer.finalize_last_transaction(cx);
14384                if self.leader_peer_id.is_none() {
14385                    buffer.set_active_selections(
14386                        &self.selections.disjoint_anchors(),
14387                        self.selections.line_mode,
14388                        self.cursor_shape,
14389                        cx,
14390                    );
14391                }
14392            });
14393        }
14394    }
14395
14396    fn handle_focus_in(&mut self, _: &mut Window, cx: &mut Context<Self>) {
14397        cx.emit(EditorEvent::FocusedIn)
14398    }
14399
14400    fn handle_focus_out(
14401        &mut self,
14402        event: FocusOutEvent,
14403        _window: &mut Window,
14404        _cx: &mut Context<Self>,
14405    ) {
14406        if event.blurred != self.focus_handle {
14407            self.last_focused_descendant = Some(event.blurred);
14408        }
14409    }
14410
14411    pub fn handle_blur(&mut self, window: &mut Window, cx: &mut Context<Self>) {
14412        self.blink_manager.update(cx, BlinkManager::disable);
14413        self.buffer
14414            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
14415
14416        if let Some(blame) = self.blame.as_ref() {
14417            blame.update(cx, GitBlame::blur)
14418        }
14419        if !self.hover_state.focused(window, cx) {
14420            hide_hover(self, cx);
14421        }
14422
14423        self.hide_context_menu(window, cx);
14424        cx.emit(EditorEvent::Blurred);
14425        cx.notify();
14426    }
14427
14428    pub fn register_action<A: Action>(
14429        &mut self,
14430        listener: impl Fn(&A, &mut Window, &mut App) + 'static,
14431    ) -> Subscription {
14432        let id = self.next_editor_action_id.post_inc();
14433        let listener = Arc::new(listener);
14434        self.editor_actions.borrow_mut().insert(
14435            id,
14436            Box::new(move |window, _| {
14437                let listener = listener.clone();
14438                window.on_action(TypeId::of::<A>(), move |action, phase, window, cx| {
14439                    let action = action.downcast_ref().unwrap();
14440                    if phase == DispatchPhase::Bubble {
14441                        listener(action, window, cx)
14442                    }
14443                })
14444            }),
14445        );
14446
14447        let editor_actions = self.editor_actions.clone();
14448        Subscription::new(move || {
14449            editor_actions.borrow_mut().remove(&id);
14450        })
14451    }
14452
14453    pub fn file_header_size(&self) -> u32 {
14454        FILE_HEADER_HEIGHT
14455    }
14456
14457    pub fn revert(
14458        &mut self,
14459        revert_changes: HashMap<BufferId, Vec<(Range<text::Anchor>, Rope)>>,
14460        window: &mut Window,
14461        cx: &mut Context<Self>,
14462    ) {
14463        self.buffer().update(cx, |multi_buffer, cx| {
14464            for (buffer_id, changes) in revert_changes {
14465                if let Some(buffer) = multi_buffer.buffer(buffer_id) {
14466                    buffer.update(cx, |buffer, cx| {
14467                        buffer.edit(
14468                            changes.into_iter().map(|(range, text)| {
14469                                (range, text.to_string().map(Arc::<str>::from))
14470                            }),
14471                            None,
14472                            cx,
14473                        );
14474                    });
14475                }
14476            }
14477        });
14478        self.change_selections(None, window, cx, |selections| selections.refresh());
14479    }
14480
14481    pub fn to_pixel_point(
14482        &self,
14483        source: multi_buffer::Anchor,
14484        editor_snapshot: &EditorSnapshot,
14485        window: &mut Window,
14486    ) -> Option<gpui::Point<Pixels>> {
14487        let source_point = source.to_display_point(editor_snapshot);
14488        self.display_to_pixel_point(source_point, editor_snapshot, window)
14489    }
14490
14491    pub fn display_to_pixel_point(
14492        &self,
14493        source: DisplayPoint,
14494        editor_snapshot: &EditorSnapshot,
14495        window: &mut Window,
14496    ) -> Option<gpui::Point<Pixels>> {
14497        let line_height = self.style()?.text.line_height_in_pixels(window.rem_size());
14498        let text_layout_details = self.text_layout_details(window);
14499        let scroll_top = text_layout_details
14500            .scroll_anchor
14501            .scroll_position(editor_snapshot)
14502            .y;
14503
14504        if source.row().as_f32() < scroll_top.floor() {
14505            return None;
14506        }
14507        let source_x = editor_snapshot.x_for_display_point(source, &text_layout_details);
14508        let source_y = line_height * (source.row().as_f32() - scroll_top);
14509        Some(gpui::Point::new(source_x, source_y))
14510    }
14511
14512    pub fn has_visible_completions_menu(&self) -> bool {
14513        !self.previewing_inline_completion
14514            && self.context_menu.borrow().as_ref().map_or(false, |menu| {
14515                menu.visible() && matches!(menu, CodeContextMenu::Completions(_))
14516            })
14517    }
14518
14519    pub fn register_addon<T: Addon>(&mut self, instance: T) {
14520        self.addons
14521            .insert(std::any::TypeId::of::<T>(), Box::new(instance));
14522    }
14523
14524    pub fn unregister_addon<T: Addon>(&mut self) {
14525        self.addons.remove(&std::any::TypeId::of::<T>());
14526    }
14527
14528    pub fn addon<T: Addon>(&self) -> Option<&T> {
14529        let type_id = std::any::TypeId::of::<T>();
14530        self.addons
14531            .get(&type_id)
14532            .and_then(|item| item.to_any().downcast_ref::<T>())
14533    }
14534
14535    fn character_size(&self, window: &mut Window) -> gpui::Size<Pixels> {
14536        let text_layout_details = self.text_layout_details(window);
14537        let style = &text_layout_details.editor_style;
14538        let font_id = window.text_system().resolve_font(&style.text.font());
14539        let font_size = style.text.font_size.to_pixels(window.rem_size());
14540        let line_height = style.text.line_height_in_pixels(window.rem_size());
14541        let em_width = window.text_system().em_width(font_id, font_size).unwrap();
14542
14543        gpui::Size::new(em_width, line_height)
14544    }
14545}
14546
14547fn get_uncommitted_diff_for_buffer(
14548    project: &Entity<Project>,
14549    buffers: impl IntoIterator<Item = Entity<Buffer>>,
14550    buffer: Entity<MultiBuffer>,
14551    cx: &mut App,
14552) {
14553    let mut tasks = Vec::new();
14554    project.update(cx, |project, cx| {
14555        for buffer in buffers {
14556            tasks.push(project.open_uncommitted_diff(buffer.clone(), cx))
14557        }
14558    });
14559    cx.spawn(|mut cx| async move {
14560        let diffs = futures::future::join_all(tasks).await;
14561        buffer
14562            .update(&mut cx, |buffer, cx| {
14563                for diff in diffs.into_iter().flatten() {
14564                    buffer.add_diff(diff, cx);
14565                }
14566            })
14567            .ok();
14568    })
14569    .detach();
14570}
14571
14572fn char_len_with_expanded_tabs(offset: usize, text: &str, tab_size: NonZeroU32) -> usize {
14573    let tab_size = tab_size.get() as usize;
14574    let mut width = offset;
14575
14576    for ch in text.chars() {
14577        width += if ch == '\t' {
14578            tab_size - (width % tab_size)
14579        } else {
14580            1
14581        };
14582    }
14583
14584    width - offset
14585}
14586
14587#[cfg(test)]
14588mod tests {
14589    use super::*;
14590
14591    #[test]
14592    fn test_string_size_with_expanded_tabs() {
14593        let nz = |val| NonZeroU32::new(val).unwrap();
14594        assert_eq!(char_len_with_expanded_tabs(0, "", nz(4)), 0);
14595        assert_eq!(char_len_with_expanded_tabs(0, "hello", nz(4)), 5);
14596        assert_eq!(char_len_with_expanded_tabs(0, "\thello", nz(4)), 9);
14597        assert_eq!(char_len_with_expanded_tabs(0, "abc\tab", nz(4)), 6);
14598        assert_eq!(char_len_with_expanded_tabs(0, "hello\t", nz(4)), 8);
14599        assert_eq!(char_len_with_expanded_tabs(0, "\t\t", nz(8)), 16);
14600        assert_eq!(char_len_with_expanded_tabs(0, "x\t", nz(8)), 8);
14601        assert_eq!(char_len_with_expanded_tabs(7, "x\t", nz(8)), 9);
14602    }
14603}
14604
14605/// Tokenizes a string into runs of text that should stick together, or that is whitespace.
14606struct WordBreakingTokenizer<'a> {
14607    input: &'a str,
14608}
14609
14610impl<'a> WordBreakingTokenizer<'a> {
14611    fn new(input: &'a str) -> Self {
14612        Self { input }
14613    }
14614}
14615
14616fn is_char_ideographic(ch: char) -> bool {
14617    use unicode_script::Script::*;
14618    use unicode_script::UnicodeScript;
14619    matches!(ch.script(), Han | Tangut | Yi)
14620}
14621
14622fn is_grapheme_ideographic(text: &str) -> bool {
14623    text.chars().any(is_char_ideographic)
14624}
14625
14626fn is_grapheme_whitespace(text: &str) -> bool {
14627    text.chars().any(|x| x.is_whitespace())
14628}
14629
14630fn should_stay_with_preceding_ideograph(text: &str) -> bool {
14631    text.chars().next().map_or(false, |ch| {
14632        matches!(ch, '。' | '、' | ',' | '?' | '!' | ':' | ';' | '…')
14633    })
14634}
14635
14636#[derive(PartialEq, Eq, Debug, Clone, Copy)]
14637struct WordBreakToken<'a> {
14638    token: &'a str,
14639    grapheme_len: usize,
14640    is_whitespace: bool,
14641}
14642
14643impl<'a> Iterator for WordBreakingTokenizer<'a> {
14644    /// Yields a span, the count of graphemes in the token, and whether it was
14645    /// whitespace. Note that it also breaks at word boundaries.
14646    type Item = WordBreakToken<'a>;
14647
14648    fn next(&mut self) -> Option<Self::Item> {
14649        use unicode_segmentation::UnicodeSegmentation;
14650        if self.input.is_empty() {
14651            return None;
14652        }
14653
14654        let mut iter = self.input.graphemes(true).peekable();
14655        let mut offset = 0;
14656        let mut graphemes = 0;
14657        if let Some(first_grapheme) = iter.next() {
14658            let is_whitespace = is_grapheme_whitespace(first_grapheme);
14659            offset += first_grapheme.len();
14660            graphemes += 1;
14661            if is_grapheme_ideographic(first_grapheme) && !is_whitespace {
14662                if let Some(grapheme) = iter.peek().copied() {
14663                    if should_stay_with_preceding_ideograph(grapheme) {
14664                        offset += grapheme.len();
14665                        graphemes += 1;
14666                    }
14667                }
14668            } else {
14669                let mut words = self.input[offset..].split_word_bound_indices().peekable();
14670                let mut next_word_bound = words.peek().copied();
14671                if next_word_bound.map_or(false, |(i, _)| i == 0) {
14672                    next_word_bound = words.next();
14673                }
14674                while let Some(grapheme) = iter.peek().copied() {
14675                    if next_word_bound.map_or(false, |(i, _)| i == offset) {
14676                        break;
14677                    };
14678                    if is_grapheme_whitespace(grapheme) != is_whitespace {
14679                        break;
14680                    };
14681                    offset += grapheme.len();
14682                    graphemes += 1;
14683                    iter.next();
14684                }
14685            }
14686            let token = &self.input[..offset];
14687            self.input = &self.input[offset..];
14688            if is_whitespace {
14689                Some(WordBreakToken {
14690                    token: " ",
14691                    grapheme_len: 1,
14692                    is_whitespace: true,
14693                })
14694            } else {
14695                Some(WordBreakToken {
14696                    token,
14697                    grapheme_len: graphemes,
14698                    is_whitespace: false,
14699                })
14700            }
14701        } else {
14702            None
14703        }
14704    }
14705}
14706
14707#[test]
14708fn test_word_breaking_tokenizer() {
14709    let tests: &[(&str, &[(&str, usize, bool)])] = &[
14710        ("", &[]),
14711        ("  ", &[(" ", 1, true)]),
14712        ("Ʒ", &[("Ʒ", 1, false)]),
14713        ("Ǽ", &[("Ǽ", 1, false)]),
14714        ("", &[("", 1, false)]),
14715        ("⋑⋑", &[("⋑⋑", 2, false)]),
14716        (
14717            "原理,进而",
14718            &[
14719                ("", 1, false),
14720                ("理,", 2, false),
14721                ("", 1, false),
14722                ("", 1, false),
14723            ],
14724        ),
14725        (
14726            "hello world",
14727            &[("hello", 5, false), (" ", 1, true), ("world", 5, false)],
14728        ),
14729        (
14730            "hello, world",
14731            &[("hello,", 6, false), (" ", 1, true), ("world", 5, false)],
14732        ),
14733        (
14734            "  hello world",
14735            &[
14736                (" ", 1, true),
14737                ("hello", 5, false),
14738                (" ", 1, true),
14739                ("world", 5, false),
14740            ],
14741        ),
14742        (
14743            "这是什么 \n 钢笔",
14744            &[
14745                ("", 1, false),
14746                ("", 1, false),
14747                ("", 1, false),
14748                ("", 1, false),
14749                (" ", 1, true),
14750                ("", 1, false),
14751                ("", 1, false),
14752            ],
14753        ),
14754        (" mutton", &[(" ", 1, true), ("mutton", 6, false)]),
14755    ];
14756
14757    for (input, result) in tests {
14758        assert_eq!(
14759            WordBreakingTokenizer::new(input).collect::<Vec<_>>(),
14760            result
14761                .iter()
14762                .copied()
14763                .map(|(token, grapheme_len, is_whitespace)| WordBreakToken {
14764                    token,
14765                    grapheme_len,
14766                    is_whitespace,
14767                })
14768                .collect::<Vec<_>>()
14769        );
14770    }
14771}
14772
14773fn wrap_with_prefix(
14774    line_prefix: String,
14775    unwrapped_text: String,
14776    wrap_column: usize,
14777    tab_size: NonZeroU32,
14778) -> String {
14779    let line_prefix_len = char_len_with_expanded_tabs(0, &line_prefix, tab_size);
14780    let mut wrapped_text = String::new();
14781    let mut current_line = line_prefix.clone();
14782
14783    let tokenizer = WordBreakingTokenizer::new(&unwrapped_text);
14784    let mut current_line_len = line_prefix_len;
14785    for WordBreakToken {
14786        token,
14787        grapheme_len,
14788        is_whitespace,
14789    } in tokenizer
14790    {
14791        if current_line_len + grapheme_len > wrap_column && current_line_len != line_prefix_len {
14792            wrapped_text.push_str(current_line.trim_end());
14793            wrapped_text.push('\n');
14794            current_line.truncate(line_prefix.len());
14795            current_line_len = line_prefix_len;
14796            if !is_whitespace {
14797                current_line.push_str(token);
14798                current_line_len += grapheme_len;
14799            }
14800        } else if !is_whitespace {
14801            current_line.push_str(token);
14802            current_line_len += grapheme_len;
14803        } else if current_line_len != line_prefix_len {
14804            current_line.push(' ');
14805            current_line_len += 1;
14806        }
14807    }
14808
14809    if !current_line.is_empty() {
14810        wrapped_text.push_str(&current_line);
14811    }
14812    wrapped_text
14813}
14814
14815#[test]
14816fn test_wrap_with_prefix() {
14817    assert_eq!(
14818        wrap_with_prefix(
14819            "# ".to_string(),
14820            "abcdefg".to_string(),
14821            4,
14822            NonZeroU32::new(4).unwrap()
14823        ),
14824        "# abcdefg"
14825    );
14826    assert_eq!(
14827        wrap_with_prefix(
14828            "".to_string(),
14829            "\thello world".to_string(),
14830            8,
14831            NonZeroU32::new(4).unwrap()
14832        ),
14833        "hello\nworld"
14834    );
14835    assert_eq!(
14836        wrap_with_prefix(
14837            "// ".to_string(),
14838            "xx \nyy zz aa bb cc".to_string(),
14839            12,
14840            NonZeroU32::new(4).unwrap()
14841        ),
14842        "// xx yy zz\n// aa bb cc"
14843    );
14844    assert_eq!(
14845        wrap_with_prefix(
14846            String::new(),
14847            "这是什么 \n 钢笔".to_string(),
14848            3,
14849            NonZeroU32::new(4).unwrap()
14850        ),
14851        "这是什\n么 钢\n"
14852    );
14853}
14854
14855pub trait CollaborationHub {
14856    fn collaborators<'a>(&self, cx: &'a App) -> &'a HashMap<PeerId, Collaborator>;
14857    fn user_participant_indices<'a>(&self, cx: &'a App) -> &'a HashMap<u64, ParticipantIndex>;
14858    fn user_names(&self, cx: &App) -> HashMap<u64, SharedString>;
14859}
14860
14861impl CollaborationHub for Entity<Project> {
14862    fn collaborators<'a>(&self, cx: &'a App) -> &'a HashMap<PeerId, Collaborator> {
14863        self.read(cx).collaborators()
14864    }
14865
14866    fn user_participant_indices<'a>(&self, cx: &'a App) -> &'a HashMap<u64, ParticipantIndex> {
14867        self.read(cx).user_store().read(cx).participant_indices()
14868    }
14869
14870    fn user_names(&self, cx: &App) -> HashMap<u64, SharedString> {
14871        let this = self.read(cx);
14872        let user_ids = this.collaborators().values().map(|c| c.user_id);
14873        this.user_store().read_with(cx, |user_store, cx| {
14874            user_store.participant_names(user_ids, cx)
14875        })
14876    }
14877}
14878
14879pub trait SemanticsProvider {
14880    fn hover(
14881        &self,
14882        buffer: &Entity<Buffer>,
14883        position: text::Anchor,
14884        cx: &mut App,
14885    ) -> Option<Task<Vec<project::Hover>>>;
14886
14887    fn inlay_hints(
14888        &self,
14889        buffer_handle: Entity<Buffer>,
14890        range: Range<text::Anchor>,
14891        cx: &mut App,
14892    ) -> Option<Task<anyhow::Result<Vec<InlayHint>>>>;
14893
14894    fn resolve_inlay_hint(
14895        &self,
14896        hint: InlayHint,
14897        buffer_handle: Entity<Buffer>,
14898        server_id: LanguageServerId,
14899        cx: &mut App,
14900    ) -> Option<Task<anyhow::Result<InlayHint>>>;
14901
14902    fn supports_inlay_hints(&self, buffer: &Entity<Buffer>, cx: &App) -> bool;
14903
14904    fn document_highlights(
14905        &self,
14906        buffer: &Entity<Buffer>,
14907        position: text::Anchor,
14908        cx: &mut App,
14909    ) -> Option<Task<Result<Vec<DocumentHighlight>>>>;
14910
14911    fn definitions(
14912        &self,
14913        buffer: &Entity<Buffer>,
14914        position: text::Anchor,
14915        kind: GotoDefinitionKind,
14916        cx: &mut App,
14917    ) -> Option<Task<Result<Vec<LocationLink>>>>;
14918
14919    fn range_for_rename(
14920        &self,
14921        buffer: &Entity<Buffer>,
14922        position: text::Anchor,
14923        cx: &mut App,
14924    ) -> Option<Task<Result<Option<Range<text::Anchor>>>>>;
14925
14926    fn perform_rename(
14927        &self,
14928        buffer: &Entity<Buffer>,
14929        position: text::Anchor,
14930        new_name: String,
14931        cx: &mut App,
14932    ) -> Option<Task<Result<ProjectTransaction>>>;
14933}
14934
14935pub trait CompletionProvider {
14936    fn completions(
14937        &self,
14938        buffer: &Entity<Buffer>,
14939        buffer_position: text::Anchor,
14940        trigger: CompletionContext,
14941        window: &mut Window,
14942        cx: &mut Context<Editor>,
14943    ) -> Task<Result<Vec<Completion>>>;
14944
14945    fn resolve_completions(
14946        &self,
14947        buffer: Entity<Buffer>,
14948        completion_indices: Vec<usize>,
14949        completions: Rc<RefCell<Box<[Completion]>>>,
14950        cx: &mut Context<Editor>,
14951    ) -> Task<Result<bool>>;
14952
14953    fn apply_additional_edits_for_completion(
14954        &self,
14955        _buffer: Entity<Buffer>,
14956        _completions: Rc<RefCell<Box<[Completion]>>>,
14957        _completion_index: usize,
14958        _push_to_history: bool,
14959        _cx: &mut Context<Editor>,
14960    ) -> Task<Result<Option<language::Transaction>>> {
14961        Task::ready(Ok(None))
14962    }
14963
14964    fn is_completion_trigger(
14965        &self,
14966        buffer: &Entity<Buffer>,
14967        position: language::Anchor,
14968        text: &str,
14969        trigger_in_words: bool,
14970        cx: &mut Context<Editor>,
14971    ) -> bool;
14972
14973    fn sort_completions(&self) -> bool {
14974        true
14975    }
14976}
14977
14978pub trait CodeActionProvider {
14979    fn id(&self) -> Arc<str>;
14980
14981    fn code_actions(
14982        &self,
14983        buffer: &Entity<Buffer>,
14984        range: Range<text::Anchor>,
14985        window: &mut Window,
14986        cx: &mut App,
14987    ) -> Task<Result<Vec<CodeAction>>>;
14988
14989    fn apply_code_action(
14990        &self,
14991        buffer_handle: Entity<Buffer>,
14992        action: CodeAction,
14993        excerpt_id: ExcerptId,
14994        push_to_history: bool,
14995        window: &mut Window,
14996        cx: &mut App,
14997    ) -> Task<Result<ProjectTransaction>>;
14998}
14999
15000impl CodeActionProvider for Entity<Project> {
15001    fn id(&self) -> Arc<str> {
15002        "project".into()
15003    }
15004
15005    fn code_actions(
15006        &self,
15007        buffer: &Entity<Buffer>,
15008        range: Range<text::Anchor>,
15009        _window: &mut Window,
15010        cx: &mut App,
15011    ) -> Task<Result<Vec<CodeAction>>> {
15012        self.update(cx, |project, cx| {
15013            project.code_actions(buffer, range, None, cx)
15014        })
15015    }
15016
15017    fn apply_code_action(
15018        &self,
15019        buffer_handle: Entity<Buffer>,
15020        action: CodeAction,
15021        _excerpt_id: ExcerptId,
15022        push_to_history: bool,
15023        _window: &mut Window,
15024        cx: &mut App,
15025    ) -> Task<Result<ProjectTransaction>> {
15026        self.update(cx, |project, cx| {
15027            project.apply_code_action(buffer_handle, action, push_to_history, cx)
15028        })
15029    }
15030}
15031
15032fn snippet_completions(
15033    project: &Project,
15034    buffer: &Entity<Buffer>,
15035    buffer_position: text::Anchor,
15036    cx: &mut App,
15037) -> Task<Result<Vec<Completion>>> {
15038    let language = buffer.read(cx).language_at(buffer_position);
15039    let language_name = language.as_ref().map(|language| language.lsp_id());
15040    let snippet_store = project.snippets().read(cx);
15041    let snippets = snippet_store.snippets_for(language_name, cx);
15042
15043    if snippets.is_empty() {
15044        return Task::ready(Ok(vec![]));
15045    }
15046    let snapshot = buffer.read(cx).text_snapshot();
15047    let chars: String = snapshot
15048        .reversed_chars_for_range(text::Anchor::MIN..buffer_position)
15049        .collect();
15050
15051    let scope = language.map(|language| language.default_scope());
15052    let executor = cx.background_executor().clone();
15053
15054    cx.background_executor().spawn(async move {
15055        let classifier = CharClassifier::new(scope).for_completion(true);
15056        let mut last_word = chars
15057            .chars()
15058            .take_while(|c| classifier.is_word(*c))
15059            .collect::<String>();
15060        last_word = last_word.chars().rev().collect();
15061
15062        if last_word.is_empty() {
15063            return Ok(vec![]);
15064        }
15065
15066        let as_offset = text::ToOffset::to_offset(&buffer_position, &snapshot);
15067        let to_lsp = |point: &text::Anchor| {
15068            let end = text::ToPointUtf16::to_point_utf16(point, &snapshot);
15069            point_to_lsp(end)
15070        };
15071        let lsp_end = to_lsp(&buffer_position);
15072
15073        let candidates = snippets
15074            .iter()
15075            .enumerate()
15076            .flat_map(|(ix, snippet)| {
15077                snippet
15078                    .prefix
15079                    .iter()
15080                    .map(move |prefix| StringMatchCandidate::new(ix, &prefix))
15081            })
15082            .collect::<Vec<StringMatchCandidate>>();
15083
15084        let mut matches = fuzzy::match_strings(
15085            &candidates,
15086            &last_word,
15087            last_word.chars().any(|c| c.is_uppercase()),
15088            100,
15089            &Default::default(),
15090            executor,
15091        )
15092        .await;
15093
15094        // Remove all candidates where the query's start does not match the start of any word in the candidate
15095        if let Some(query_start) = last_word.chars().next() {
15096            matches.retain(|string_match| {
15097                split_words(&string_match.string).any(|word| {
15098                    // Check that the first codepoint of the word as lowercase matches the first
15099                    // codepoint of the query as lowercase
15100                    word.chars()
15101                        .flat_map(|codepoint| codepoint.to_lowercase())
15102                        .zip(query_start.to_lowercase())
15103                        .all(|(word_cp, query_cp)| word_cp == query_cp)
15104                })
15105            });
15106        }
15107
15108        let matched_strings = matches
15109            .into_iter()
15110            .map(|m| m.string)
15111            .collect::<HashSet<_>>();
15112
15113        let result: Vec<Completion> = snippets
15114            .into_iter()
15115            .filter_map(|snippet| {
15116                let matching_prefix = snippet
15117                    .prefix
15118                    .iter()
15119                    .find(|prefix| matched_strings.contains(*prefix))?;
15120                let start = as_offset - last_word.len();
15121                let start = snapshot.anchor_before(start);
15122                let range = start..buffer_position;
15123                let lsp_start = to_lsp(&start);
15124                let lsp_range = lsp::Range {
15125                    start: lsp_start,
15126                    end: lsp_end,
15127                };
15128                Some(Completion {
15129                    old_range: range,
15130                    new_text: snippet.body.clone(),
15131                    resolved: false,
15132                    label: CodeLabel {
15133                        text: matching_prefix.clone(),
15134                        runs: vec![],
15135                        filter_range: 0..matching_prefix.len(),
15136                    },
15137                    server_id: LanguageServerId(usize::MAX),
15138                    documentation: snippet
15139                        .description
15140                        .clone()
15141                        .map(CompletionDocumentation::SingleLine),
15142                    lsp_completion: lsp::CompletionItem {
15143                        label: snippet.prefix.first().unwrap().clone(),
15144                        kind: Some(CompletionItemKind::SNIPPET),
15145                        label_details: snippet.description.as_ref().map(|description| {
15146                            lsp::CompletionItemLabelDetails {
15147                                detail: Some(description.clone()),
15148                                description: None,
15149                            }
15150                        }),
15151                        insert_text_format: Some(InsertTextFormat::SNIPPET),
15152                        text_edit: Some(lsp::CompletionTextEdit::InsertAndReplace(
15153                            lsp::InsertReplaceEdit {
15154                                new_text: snippet.body.clone(),
15155                                insert: lsp_range,
15156                                replace: lsp_range,
15157                            },
15158                        )),
15159                        filter_text: Some(snippet.body.clone()),
15160                        sort_text: Some(char::MAX.to_string()),
15161                        ..Default::default()
15162                    },
15163                    confirm: None,
15164                })
15165            })
15166            .collect();
15167
15168        Ok(result)
15169    })
15170}
15171
15172impl CompletionProvider for Entity<Project> {
15173    fn completions(
15174        &self,
15175        buffer: &Entity<Buffer>,
15176        buffer_position: text::Anchor,
15177        options: CompletionContext,
15178        _window: &mut Window,
15179        cx: &mut Context<Editor>,
15180    ) -> Task<Result<Vec<Completion>>> {
15181        self.update(cx, |project, cx| {
15182            let snippets = snippet_completions(project, buffer, buffer_position, cx);
15183            let project_completions = project.completions(buffer, buffer_position, options, cx);
15184            cx.background_executor().spawn(async move {
15185                let mut completions = project_completions.await?;
15186                let snippets_completions = snippets.await?;
15187                completions.extend(snippets_completions);
15188                Ok(completions)
15189            })
15190        })
15191    }
15192
15193    fn resolve_completions(
15194        &self,
15195        buffer: Entity<Buffer>,
15196        completion_indices: Vec<usize>,
15197        completions: Rc<RefCell<Box<[Completion]>>>,
15198        cx: &mut Context<Editor>,
15199    ) -> Task<Result<bool>> {
15200        self.update(cx, |project, cx| {
15201            project.lsp_store().update(cx, |lsp_store, cx| {
15202                lsp_store.resolve_completions(buffer, completion_indices, completions, cx)
15203            })
15204        })
15205    }
15206
15207    fn apply_additional_edits_for_completion(
15208        &self,
15209        buffer: Entity<Buffer>,
15210        completions: Rc<RefCell<Box<[Completion]>>>,
15211        completion_index: usize,
15212        push_to_history: bool,
15213        cx: &mut Context<Editor>,
15214    ) -> Task<Result<Option<language::Transaction>>> {
15215        self.update(cx, |project, cx| {
15216            project.lsp_store().update(cx, |lsp_store, cx| {
15217                lsp_store.apply_additional_edits_for_completion(
15218                    buffer,
15219                    completions,
15220                    completion_index,
15221                    push_to_history,
15222                    cx,
15223                )
15224            })
15225        })
15226    }
15227
15228    fn is_completion_trigger(
15229        &self,
15230        buffer: &Entity<Buffer>,
15231        position: language::Anchor,
15232        text: &str,
15233        trigger_in_words: bool,
15234        cx: &mut Context<Editor>,
15235    ) -> bool {
15236        let mut chars = text.chars();
15237        let char = if let Some(char) = chars.next() {
15238            char
15239        } else {
15240            return false;
15241        };
15242        if chars.next().is_some() {
15243            return false;
15244        }
15245
15246        let buffer = buffer.read(cx);
15247        let snapshot = buffer.snapshot();
15248        if !snapshot.settings_at(position, cx).show_completions_on_input {
15249            return false;
15250        }
15251        let classifier = snapshot.char_classifier_at(position).for_completion(true);
15252        if trigger_in_words && classifier.is_word(char) {
15253            return true;
15254        }
15255
15256        buffer.completion_triggers().contains(text)
15257    }
15258}
15259
15260impl SemanticsProvider for Entity<Project> {
15261    fn hover(
15262        &self,
15263        buffer: &Entity<Buffer>,
15264        position: text::Anchor,
15265        cx: &mut App,
15266    ) -> Option<Task<Vec<project::Hover>>> {
15267        Some(self.update(cx, |project, cx| project.hover(buffer, position, cx)))
15268    }
15269
15270    fn document_highlights(
15271        &self,
15272        buffer: &Entity<Buffer>,
15273        position: text::Anchor,
15274        cx: &mut App,
15275    ) -> Option<Task<Result<Vec<DocumentHighlight>>>> {
15276        Some(self.update(cx, |project, cx| {
15277            project.document_highlights(buffer, position, cx)
15278        }))
15279    }
15280
15281    fn definitions(
15282        &self,
15283        buffer: &Entity<Buffer>,
15284        position: text::Anchor,
15285        kind: GotoDefinitionKind,
15286        cx: &mut App,
15287    ) -> Option<Task<Result<Vec<LocationLink>>>> {
15288        Some(self.update(cx, |project, cx| match kind {
15289            GotoDefinitionKind::Symbol => project.definition(&buffer, position, cx),
15290            GotoDefinitionKind::Declaration => project.declaration(&buffer, position, cx),
15291            GotoDefinitionKind::Type => project.type_definition(&buffer, position, cx),
15292            GotoDefinitionKind::Implementation => project.implementation(&buffer, position, cx),
15293        }))
15294    }
15295
15296    fn supports_inlay_hints(&self, buffer: &Entity<Buffer>, cx: &App) -> bool {
15297        // TODO: make this work for remote projects
15298        self.read(cx)
15299            .language_servers_for_local_buffer(buffer.read(cx), cx)
15300            .any(
15301                |(_, server)| match server.capabilities().inlay_hint_provider {
15302                    Some(lsp::OneOf::Left(enabled)) => enabled,
15303                    Some(lsp::OneOf::Right(_)) => true,
15304                    None => false,
15305                },
15306            )
15307    }
15308
15309    fn inlay_hints(
15310        &self,
15311        buffer_handle: Entity<Buffer>,
15312        range: Range<text::Anchor>,
15313        cx: &mut App,
15314    ) -> Option<Task<anyhow::Result<Vec<InlayHint>>>> {
15315        Some(self.update(cx, |project, cx| {
15316            project.inlay_hints(buffer_handle, range, cx)
15317        }))
15318    }
15319
15320    fn resolve_inlay_hint(
15321        &self,
15322        hint: InlayHint,
15323        buffer_handle: Entity<Buffer>,
15324        server_id: LanguageServerId,
15325        cx: &mut App,
15326    ) -> Option<Task<anyhow::Result<InlayHint>>> {
15327        Some(self.update(cx, |project, cx| {
15328            project.resolve_inlay_hint(hint, buffer_handle, server_id, cx)
15329        }))
15330    }
15331
15332    fn range_for_rename(
15333        &self,
15334        buffer: &Entity<Buffer>,
15335        position: text::Anchor,
15336        cx: &mut App,
15337    ) -> Option<Task<Result<Option<Range<text::Anchor>>>>> {
15338        Some(self.update(cx, |project, cx| {
15339            let buffer = buffer.clone();
15340            let task = project.prepare_rename(buffer.clone(), position, cx);
15341            cx.spawn(|_, mut cx| async move {
15342                Ok(match task.await? {
15343                    PrepareRenameResponse::Success(range) => Some(range),
15344                    PrepareRenameResponse::InvalidPosition => None,
15345                    PrepareRenameResponse::OnlyUnpreparedRenameSupported => {
15346                        // Fallback on using TreeSitter info to determine identifier range
15347                        buffer.update(&mut cx, |buffer, _| {
15348                            let snapshot = buffer.snapshot();
15349                            let (range, kind) = snapshot.surrounding_word(position);
15350                            if kind != Some(CharKind::Word) {
15351                                return None;
15352                            }
15353                            Some(
15354                                snapshot.anchor_before(range.start)
15355                                    ..snapshot.anchor_after(range.end),
15356                            )
15357                        })?
15358                    }
15359                })
15360            })
15361        }))
15362    }
15363
15364    fn perform_rename(
15365        &self,
15366        buffer: &Entity<Buffer>,
15367        position: text::Anchor,
15368        new_name: String,
15369        cx: &mut App,
15370    ) -> Option<Task<Result<ProjectTransaction>>> {
15371        Some(self.update(cx, |project, cx| {
15372            project.perform_rename(buffer.clone(), position, new_name, cx)
15373        }))
15374    }
15375}
15376
15377fn inlay_hint_settings(
15378    location: Anchor,
15379    snapshot: &MultiBufferSnapshot,
15380    cx: &mut Context<Editor>,
15381) -> InlayHintSettings {
15382    let file = snapshot.file_at(location);
15383    let language = snapshot.language_at(location).map(|l| l.name());
15384    language_settings(language, file, cx).inlay_hints
15385}
15386
15387fn consume_contiguous_rows(
15388    contiguous_row_selections: &mut Vec<Selection<Point>>,
15389    selection: &Selection<Point>,
15390    display_map: &DisplaySnapshot,
15391    selections: &mut Peekable<std::slice::Iter<Selection<Point>>>,
15392) -> (MultiBufferRow, MultiBufferRow) {
15393    contiguous_row_selections.push(selection.clone());
15394    let start_row = MultiBufferRow(selection.start.row);
15395    let mut end_row = ending_row(selection, display_map);
15396
15397    while let Some(next_selection) = selections.peek() {
15398        if next_selection.start.row <= end_row.0 {
15399            end_row = ending_row(next_selection, display_map);
15400            contiguous_row_selections.push(selections.next().unwrap().clone());
15401        } else {
15402            break;
15403        }
15404    }
15405    (start_row, end_row)
15406}
15407
15408fn ending_row(next_selection: &Selection<Point>, display_map: &DisplaySnapshot) -> MultiBufferRow {
15409    if next_selection.end.column > 0 || next_selection.is_empty() {
15410        MultiBufferRow(display_map.next_line_boundary(next_selection.end).0.row + 1)
15411    } else {
15412        MultiBufferRow(next_selection.end.row)
15413    }
15414}
15415
15416impl EditorSnapshot {
15417    pub fn remote_selections_in_range<'a>(
15418        &'a self,
15419        range: &'a Range<Anchor>,
15420        collaboration_hub: &dyn CollaborationHub,
15421        cx: &'a App,
15422    ) -> impl 'a + Iterator<Item = RemoteSelection> {
15423        let participant_names = collaboration_hub.user_names(cx);
15424        let participant_indices = collaboration_hub.user_participant_indices(cx);
15425        let collaborators_by_peer_id = collaboration_hub.collaborators(cx);
15426        let collaborators_by_replica_id = collaborators_by_peer_id
15427            .iter()
15428            .map(|(_, collaborator)| (collaborator.replica_id, collaborator))
15429            .collect::<HashMap<_, _>>();
15430        self.buffer_snapshot
15431            .selections_in_range(range, false)
15432            .filter_map(move |(replica_id, line_mode, cursor_shape, selection)| {
15433                let collaborator = collaborators_by_replica_id.get(&replica_id)?;
15434                let participant_index = participant_indices.get(&collaborator.user_id).copied();
15435                let user_name = participant_names.get(&collaborator.user_id).cloned();
15436                Some(RemoteSelection {
15437                    replica_id,
15438                    selection,
15439                    cursor_shape,
15440                    line_mode,
15441                    participant_index,
15442                    peer_id: collaborator.peer_id,
15443                    user_name,
15444                })
15445            })
15446    }
15447
15448    pub fn hunks_for_ranges(
15449        &self,
15450        ranges: impl Iterator<Item = Range<Point>>,
15451    ) -> Vec<MultiBufferDiffHunk> {
15452        let mut hunks = Vec::new();
15453        let mut processed_buffer_rows: HashMap<BufferId, HashSet<Range<text::Anchor>>> =
15454            HashMap::default();
15455        for query_range in ranges {
15456            let query_rows =
15457                MultiBufferRow(query_range.start.row)..MultiBufferRow(query_range.end.row + 1);
15458            for hunk in self.buffer_snapshot.diff_hunks_in_range(
15459                Point::new(query_rows.start.0, 0)..Point::new(query_rows.end.0, 0),
15460            ) {
15461                // Deleted hunk is an empty row range, no caret can be placed there and Zed allows to revert it
15462                // when the caret is just above or just below the deleted hunk.
15463                let allow_adjacent = hunk.status() == DiffHunkStatus::Removed;
15464                let related_to_selection = if allow_adjacent {
15465                    hunk.row_range.overlaps(&query_rows)
15466                        || hunk.row_range.start == query_rows.end
15467                        || hunk.row_range.end == query_rows.start
15468                } else {
15469                    hunk.row_range.overlaps(&query_rows)
15470                };
15471                if related_to_selection {
15472                    if !processed_buffer_rows
15473                        .entry(hunk.buffer_id)
15474                        .or_default()
15475                        .insert(hunk.buffer_range.start..hunk.buffer_range.end)
15476                    {
15477                        continue;
15478                    }
15479                    hunks.push(hunk);
15480                }
15481            }
15482        }
15483
15484        hunks
15485    }
15486
15487    pub fn language_at<T: ToOffset>(&self, position: T) -> Option<&Arc<Language>> {
15488        self.display_snapshot.buffer_snapshot.language_at(position)
15489    }
15490
15491    pub fn is_focused(&self) -> bool {
15492        self.is_focused
15493    }
15494
15495    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
15496        self.placeholder_text.as_ref()
15497    }
15498
15499    pub fn scroll_position(&self) -> gpui::Point<f32> {
15500        self.scroll_anchor.scroll_position(&self.display_snapshot)
15501    }
15502
15503    fn gutter_dimensions(
15504        &self,
15505        font_id: FontId,
15506        font_size: Pixels,
15507        max_line_number_width: Pixels,
15508        cx: &App,
15509    ) -> Option<GutterDimensions> {
15510        if !self.show_gutter {
15511            return None;
15512        }
15513
15514        let descent = cx.text_system().descent(font_id, font_size);
15515        let em_width = cx.text_system().em_width(font_id, font_size).log_err()?;
15516        let em_advance = cx.text_system().em_advance(font_id, font_size).log_err()?;
15517
15518        let show_git_gutter = self.show_git_diff_gutter.unwrap_or_else(|| {
15519            matches!(
15520                ProjectSettings::get_global(cx).git.git_gutter,
15521                Some(GitGutterSetting::TrackedFiles)
15522            )
15523        });
15524        let gutter_settings = EditorSettings::get_global(cx).gutter;
15525        let show_line_numbers = self
15526            .show_line_numbers
15527            .unwrap_or(gutter_settings.line_numbers);
15528        let line_gutter_width = if show_line_numbers {
15529            // Avoid flicker-like gutter resizes when the line number gains another digit and only resize the gutter on files with N*10^5 lines.
15530            let min_width_for_number_on_gutter = em_advance * 4.0;
15531            max_line_number_width.max(min_width_for_number_on_gutter)
15532        } else {
15533            0.0.into()
15534        };
15535
15536        let show_code_actions = self
15537            .show_code_actions
15538            .unwrap_or(gutter_settings.code_actions);
15539
15540        let show_runnables = self.show_runnables.unwrap_or(gutter_settings.runnables);
15541
15542        let git_blame_entries_width =
15543            self.git_blame_gutter_max_author_length
15544                .map(|max_author_length| {
15545                    const MAX_RELATIVE_TIMESTAMP: &str = "60 minutes ago";
15546
15547                    /// The number of characters to dedicate to gaps and margins.
15548                    const SPACING_WIDTH: usize = 4;
15549
15550                    let max_char_count = max_author_length
15551                        .min(GIT_BLAME_MAX_AUTHOR_CHARS_DISPLAYED)
15552                        + ::git::SHORT_SHA_LENGTH
15553                        + MAX_RELATIVE_TIMESTAMP.len()
15554                        + SPACING_WIDTH;
15555
15556                    em_advance * max_char_count
15557                });
15558
15559        let mut left_padding = git_blame_entries_width.unwrap_or(Pixels::ZERO);
15560        left_padding += if show_code_actions || show_runnables {
15561            em_width * 3.0
15562        } else if show_git_gutter && show_line_numbers {
15563            em_width * 2.0
15564        } else if show_git_gutter || show_line_numbers {
15565            em_width
15566        } else {
15567            px(0.)
15568        };
15569
15570        let right_padding = if gutter_settings.folds && show_line_numbers {
15571            em_width * 4.0
15572        } else if gutter_settings.folds {
15573            em_width * 3.0
15574        } else if show_line_numbers {
15575            em_width
15576        } else {
15577            px(0.)
15578        };
15579
15580        Some(GutterDimensions {
15581            left_padding,
15582            right_padding,
15583            width: line_gutter_width + left_padding + right_padding,
15584            margin: -descent,
15585            git_blame_entries_width,
15586        })
15587    }
15588
15589    pub fn render_crease_toggle(
15590        &self,
15591        buffer_row: MultiBufferRow,
15592        row_contains_cursor: bool,
15593        editor: Entity<Editor>,
15594        window: &mut Window,
15595        cx: &mut App,
15596    ) -> Option<AnyElement> {
15597        let folded = self.is_line_folded(buffer_row);
15598        let mut is_foldable = false;
15599
15600        if let Some(crease) = self
15601            .crease_snapshot
15602            .query_row(buffer_row, &self.buffer_snapshot)
15603        {
15604            is_foldable = true;
15605            match crease {
15606                Crease::Inline { render_toggle, .. } | Crease::Block { render_toggle, .. } => {
15607                    if let Some(render_toggle) = render_toggle {
15608                        let toggle_callback =
15609                            Arc::new(move |folded, window: &mut Window, cx: &mut App| {
15610                                if folded {
15611                                    editor.update(cx, |editor, cx| {
15612                                        editor.fold_at(&crate::FoldAt { buffer_row }, window, cx)
15613                                    });
15614                                } else {
15615                                    editor.update(cx, |editor, cx| {
15616                                        editor.unfold_at(
15617                                            &crate::UnfoldAt { buffer_row },
15618                                            window,
15619                                            cx,
15620                                        )
15621                                    });
15622                                }
15623                            });
15624                        return Some((render_toggle)(
15625                            buffer_row,
15626                            folded,
15627                            toggle_callback,
15628                            window,
15629                            cx,
15630                        ));
15631                    }
15632                }
15633            }
15634        }
15635
15636        is_foldable |= self.starts_indent(buffer_row);
15637
15638        if folded || (is_foldable && (row_contains_cursor || self.gutter_hovered)) {
15639            Some(
15640                Disclosure::new(("gutter_crease", buffer_row.0), !folded)
15641                    .toggle_state(folded)
15642                    .on_click(window.listener_for(&editor, move |this, _e, window, cx| {
15643                        if folded {
15644                            this.unfold_at(&UnfoldAt { buffer_row }, window, cx);
15645                        } else {
15646                            this.fold_at(&FoldAt { buffer_row }, window, cx);
15647                        }
15648                    }))
15649                    .into_any_element(),
15650            )
15651        } else {
15652            None
15653        }
15654    }
15655
15656    pub fn render_crease_trailer(
15657        &self,
15658        buffer_row: MultiBufferRow,
15659        window: &mut Window,
15660        cx: &mut App,
15661    ) -> Option<AnyElement> {
15662        let folded = self.is_line_folded(buffer_row);
15663        if let Crease::Inline { render_trailer, .. } = self
15664            .crease_snapshot
15665            .query_row(buffer_row, &self.buffer_snapshot)?
15666        {
15667            let render_trailer = render_trailer.as_ref()?;
15668            Some(render_trailer(buffer_row, folded, window, cx))
15669        } else {
15670            None
15671        }
15672    }
15673}
15674
15675impl Deref for EditorSnapshot {
15676    type Target = DisplaySnapshot;
15677
15678    fn deref(&self) -> &Self::Target {
15679        &self.display_snapshot
15680    }
15681}
15682
15683#[derive(Clone, Debug, PartialEq, Eq)]
15684pub enum EditorEvent {
15685    InputIgnored {
15686        text: Arc<str>,
15687    },
15688    InputHandled {
15689        utf16_range_to_replace: Option<Range<isize>>,
15690        text: Arc<str>,
15691    },
15692    ExcerptsAdded {
15693        buffer: Entity<Buffer>,
15694        predecessor: ExcerptId,
15695        excerpts: Vec<(ExcerptId, ExcerptRange<language::Anchor>)>,
15696    },
15697    ExcerptsRemoved {
15698        ids: Vec<ExcerptId>,
15699    },
15700    BufferFoldToggled {
15701        ids: Vec<ExcerptId>,
15702        folded: bool,
15703    },
15704    ExcerptsEdited {
15705        ids: Vec<ExcerptId>,
15706    },
15707    ExcerptsExpanded {
15708        ids: Vec<ExcerptId>,
15709    },
15710    BufferEdited,
15711    Edited {
15712        transaction_id: clock::Lamport,
15713    },
15714    Reparsed(BufferId),
15715    Focused,
15716    FocusedIn,
15717    Blurred,
15718    DirtyChanged,
15719    Saved,
15720    TitleChanged,
15721    DiffBaseChanged,
15722    SelectionsChanged {
15723        local: bool,
15724    },
15725    ScrollPositionChanged {
15726        local: bool,
15727        autoscroll: bool,
15728    },
15729    Closed,
15730    TransactionUndone {
15731        transaction_id: clock::Lamport,
15732    },
15733    TransactionBegun {
15734        transaction_id: clock::Lamport,
15735    },
15736    Reloaded,
15737    CursorShapeChanged,
15738}
15739
15740impl EventEmitter<EditorEvent> for Editor {}
15741
15742impl Focusable for Editor {
15743    fn focus_handle(&self, _cx: &App) -> FocusHandle {
15744        self.focus_handle.clone()
15745    }
15746}
15747
15748impl Render for Editor {
15749    fn render<'a>(&mut self, _: &mut Window, cx: &mut Context<'a, Self>) -> impl IntoElement {
15750        let settings = ThemeSettings::get_global(cx);
15751
15752        let mut text_style = match self.mode {
15753            EditorMode::SingleLine { .. } | EditorMode::AutoHeight { .. } => TextStyle {
15754                color: cx.theme().colors().editor_foreground,
15755                font_family: settings.ui_font.family.clone(),
15756                font_features: settings.ui_font.features.clone(),
15757                font_fallbacks: settings.ui_font.fallbacks.clone(),
15758                font_size: rems(0.875).into(),
15759                font_weight: settings.ui_font.weight,
15760                line_height: relative(settings.buffer_line_height.value()),
15761                ..Default::default()
15762            },
15763            EditorMode::Full => TextStyle {
15764                color: cx.theme().colors().editor_foreground,
15765                font_family: settings.buffer_font.family.clone(),
15766                font_features: settings.buffer_font.features.clone(),
15767                font_fallbacks: settings.buffer_font.fallbacks.clone(),
15768                font_size: settings.buffer_font_size().into(),
15769                font_weight: settings.buffer_font.weight,
15770                line_height: relative(settings.buffer_line_height.value()),
15771                ..Default::default()
15772            },
15773        };
15774        if let Some(text_style_refinement) = &self.text_style_refinement {
15775            text_style.refine(text_style_refinement)
15776        }
15777
15778        let background = match self.mode {
15779            EditorMode::SingleLine { .. } => cx.theme().system().transparent,
15780            EditorMode::AutoHeight { max_lines: _ } => cx.theme().system().transparent,
15781            EditorMode::Full => cx.theme().colors().editor_background,
15782        };
15783
15784        EditorElement::new(
15785            &cx.entity(),
15786            EditorStyle {
15787                background,
15788                local_player: cx.theme().players().local(),
15789                text: text_style,
15790                scrollbar_width: EditorElement::SCROLLBAR_WIDTH,
15791                syntax: cx.theme().syntax().clone(),
15792                status: cx.theme().status().clone(),
15793                inlay_hints_style: make_inlay_hints_style(cx),
15794                inline_completion_styles: make_suggestion_styles(cx),
15795                unnecessary_code_fade: ThemeSettings::get_global(cx).unnecessary_code_fade,
15796            },
15797        )
15798    }
15799}
15800
15801impl EntityInputHandler for Editor {
15802    fn text_for_range(
15803        &mut self,
15804        range_utf16: Range<usize>,
15805        adjusted_range: &mut Option<Range<usize>>,
15806        _: &mut Window,
15807        cx: &mut Context<Self>,
15808    ) -> Option<String> {
15809        let snapshot = self.buffer.read(cx).read(cx);
15810        let start = snapshot.clip_offset_utf16(OffsetUtf16(range_utf16.start), Bias::Left);
15811        let end = snapshot.clip_offset_utf16(OffsetUtf16(range_utf16.end), Bias::Right);
15812        if (start.0..end.0) != range_utf16 {
15813            adjusted_range.replace(start.0..end.0);
15814        }
15815        Some(snapshot.text_for_range(start..end).collect())
15816    }
15817
15818    fn selected_text_range(
15819        &mut self,
15820        ignore_disabled_input: bool,
15821        _: &mut Window,
15822        cx: &mut Context<Self>,
15823    ) -> Option<UTF16Selection> {
15824        // Prevent the IME menu from appearing when holding down an alphabetic key
15825        // while input is disabled.
15826        if !ignore_disabled_input && !self.input_enabled {
15827            return None;
15828        }
15829
15830        let selection = self.selections.newest::<OffsetUtf16>(cx);
15831        let range = selection.range();
15832
15833        Some(UTF16Selection {
15834            range: range.start.0..range.end.0,
15835            reversed: selection.reversed,
15836        })
15837    }
15838
15839    fn marked_text_range(&self, _: &mut Window, cx: &mut Context<Self>) -> Option<Range<usize>> {
15840        let snapshot = self.buffer.read(cx).read(cx);
15841        let range = self.text_highlights::<InputComposition>(cx)?.1.first()?;
15842        Some(range.start.to_offset_utf16(&snapshot).0..range.end.to_offset_utf16(&snapshot).0)
15843    }
15844
15845    fn unmark_text(&mut self, _: &mut Window, cx: &mut Context<Self>) {
15846        self.clear_highlights::<InputComposition>(cx);
15847        self.ime_transaction.take();
15848    }
15849
15850    fn replace_text_in_range(
15851        &mut self,
15852        range_utf16: Option<Range<usize>>,
15853        text: &str,
15854        window: &mut Window,
15855        cx: &mut Context<Self>,
15856    ) {
15857        if !self.input_enabled {
15858            cx.emit(EditorEvent::InputIgnored { text: text.into() });
15859            return;
15860        }
15861
15862        self.transact(window, cx, |this, window, cx| {
15863            let new_selected_ranges = if let Some(range_utf16) = range_utf16 {
15864                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
15865                Some(this.selection_replacement_ranges(range_utf16, cx))
15866            } else {
15867                this.marked_text_ranges(cx)
15868            };
15869
15870            let range_to_replace = new_selected_ranges.as_ref().and_then(|ranges_to_replace| {
15871                let newest_selection_id = this.selections.newest_anchor().id;
15872                this.selections
15873                    .all::<OffsetUtf16>(cx)
15874                    .iter()
15875                    .zip(ranges_to_replace.iter())
15876                    .find_map(|(selection, range)| {
15877                        if selection.id == newest_selection_id {
15878                            Some(
15879                                (range.start.0 as isize - selection.head().0 as isize)
15880                                    ..(range.end.0 as isize - selection.head().0 as isize),
15881                            )
15882                        } else {
15883                            None
15884                        }
15885                    })
15886            });
15887
15888            cx.emit(EditorEvent::InputHandled {
15889                utf16_range_to_replace: range_to_replace,
15890                text: text.into(),
15891            });
15892
15893            if let Some(new_selected_ranges) = new_selected_ranges {
15894                this.change_selections(None, window, cx, |selections| {
15895                    selections.select_ranges(new_selected_ranges)
15896                });
15897                this.backspace(&Default::default(), window, cx);
15898            }
15899
15900            this.handle_input(text, window, cx);
15901        });
15902
15903        if let Some(transaction) = self.ime_transaction {
15904            self.buffer.update(cx, |buffer, cx| {
15905                buffer.group_until_transaction(transaction, cx);
15906            });
15907        }
15908
15909        self.unmark_text(window, cx);
15910    }
15911
15912    fn replace_and_mark_text_in_range(
15913        &mut self,
15914        range_utf16: Option<Range<usize>>,
15915        text: &str,
15916        new_selected_range_utf16: Option<Range<usize>>,
15917        window: &mut Window,
15918        cx: &mut Context<Self>,
15919    ) {
15920        if !self.input_enabled {
15921            return;
15922        }
15923
15924        let transaction = self.transact(window, cx, |this, window, cx| {
15925            let ranges_to_replace = if let Some(mut marked_ranges) = this.marked_text_ranges(cx) {
15926                let snapshot = this.buffer.read(cx).read(cx);
15927                if let Some(relative_range_utf16) = range_utf16.as_ref() {
15928                    for marked_range in &mut marked_ranges {
15929                        marked_range.end.0 = marked_range.start.0 + relative_range_utf16.end;
15930                        marked_range.start.0 += relative_range_utf16.start;
15931                        marked_range.start =
15932                            snapshot.clip_offset_utf16(marked_range.start, Bias::Left);
15933                        marked_range.end =
15934                            snapshot.clip_offset_utf16(marked_range.end, Bias::Right);
15935                    }
15936                }
15937                Some(marked_ranges)
15938            } else if let Some(range_utf16) = range_utf16 {
15939                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
15940                Some(this.selection_replacement_ranges(range_utf16, cx))
15941            } else {
15942                None
15943            };
15944
15945            let range_to_replace = ranges_to_replace.as_ref().and_then(|ranges_to_replace| {
15946                let newest_selection_id = this.selections.newest_anchor().id;
15947                this.selections
15948                    .all::<OffsetUtf16>(cx)
15949                    .iter()
15950                    .zip(ranges_to_replace.iter())
15951                    .find_map(|(selection, range)| {
15952                        if selection.id == newest_selection_id {
15953                            Some(
15954                                (range.start.0 as isize - selection.head().0 as isize)
15955                                    ..(range.end.0 as isize - selection.head().0 as isize),
15956                            )
15957                        } else {
15958                            None
15959                        }
15960                    })
15961            });
15962
15963            cx.emit(EditorEvent::InputHandled {
15964                utf16_range_to_replace: range_to_replace,
15965                text: text.into(),
15966            });
15967
15968            if let Some(ranges) = ranges_to_replace {
15969                this.change_selections(None, window, cx, |s| s.select_ranges(ranges));
15970            }
15971
15972            let marked_ranges = {
15973                let snapshot = this.buffer.read(cx).read(cx);
15974                this.selections
15975                    .disjoint_anchors()
15976                    .iter()
15977                    .map(|selection| {
15978                        selection.start.bias_left(&snapshot)..selection.end.bias_right(&snapshot)
15979                    })
15980                    .collect::<Vec<_>>()
15981            };
15982
15983            if text.is_empty() {
15984                this.unmark_text(window, cx);
15985            } else {
15986                this.highlight_text::<InputComposition>(
15987                    marked_ranges.clone(),
15988                    HighlightStyle {
15989                        underline: Some(UnderlineStyle {
15990                            thickness: px(1.),
15991                            color: None,
15992                            wavy: false,
15993                        }),
15994                        ..Default::default()
15995                    },
15996                    cx,
15997                );
15998            }
15999
16000            // Disable auto-closing when composing text (i.e. typing a `"` on a Brazilian keyboard)
16001            let use_autoclose = this.use_autoclose;
16002            let use_auto_surround = this.use_auto_surround;
16003            this.set_use_autoclose(false);
16004            this.set_use_auto_surround(false);
16005            this.handle_input(text, window, cx);
16006            this.set_use_autoclose(use_autoclose);
16007            this.set_use_auto_surround(use_auto_surround);
16008
16009            if let Some(new_selected_range) = new_selected_range_utf16 {
16010                let snapshot = this.buffer.read(cx).read(cx);
16011                let new_selected_ranges = marked_ranges
16012                    .into_iter()
16013                    .map(|marked_range| {
16014                        let insertion_start = marked_range.start.to_offset_utf16(&snapshot).0;
16015                        let new_start = OffsetUtf16(new_selected_range.start + insertion_start);
16016                        let new_end = OffsetUtf16(new_selected_range.end + insertion_start);
16017                        snapshot.clip_offset_utf16(new_start, Bias::Left)
16018                            ..snapshot.clip_offset_utf16(new_end, Bias::Right)
16019                    })
16020                    .collect::<Vec<_>>();
16021
16022                drop(snapshot);
16023                this.change_selections(None, window, cx, |selections| {
16024                    selections.select_ranges(new_selected_ranges)
16025                });
16026            }
16027        });
16028
16029        self.ime_transaction = self.ime_transaction.or(transaction);
16030        if let Some(transaction) = self.ime_transaction {
16031            self.buffer.update(cx, |buffer, cx| {
16032                buffer.group_until_transaction(transaction, cx);
16033            });
16034        }
16035
16036        if self.text_highlights::<InputComposition>(cx).is_none() {
16037            self.ime_transaction.take();
16038        }
16039    }
16040
16041    fn bounds_for_range(
16042        &mut self,
16043        range_utf16: Range<usize>,
16044        element_bounds: gpui::Bounds<Pixels>,
16045        window: &mut Window,
16046        cx: &mut Context<Self>,
16047    ) -> Option<gpui::Bounds<Pixels>> {
16048        let text_layout_details = self.text_layout_details(window);
16049        let gpui::Size {
16050            width: em_width,
16051            height: line_height,
16052        } = self.character_size(window);
16053
16054        let snapshot = self.snapshot(window, cx);
16055        let scroll_position = snapshot.scroll_position();
16056        let scroll_left = scroll_position.x * em_width;
16057
16058        let start = OffsetUtf16(range_utf16.start).to_display_point(&snapshot);
16059        let x = snapshot.x_for_display_point(start, &text_layout_details) - scroll_left
16060            + self.gutter_dimensions.width
16061            + self.gutter_dimensions.margin;
16062        let y = line_height * (start.row().as_f32() - scroll_position.y);
16063
16064        Some(Bounds {
16065            origin: element_bounds.origin + point(x, y),
16066            size: size(em_width, line_height),
16067        })
16068    }
16069
16070    fn character_index_for_point(
16071        &mut self,
16072        point: gpui::Point<Pixels>,
16073        _window: &mut Window,
16074        _cx: &mut Context<Self>,
16075    ) -> Option<usize> {
16076        let position_map = self.last_position_map.as_ref()?;
16077        if !position_map.text_hitbox.contains(&point) {
16078            return None;
16079        }
16080        let display_point = position_map.point_for_position(point).previous_valid;
16081        let anchor = position_map
16082            .snapshot
16083            .display_point_to_anchor(display_point, Bias::Left);
16084        let utf16_offset = anchor.to_offset_utf16(&position_map.snapshot.buffer_snapshot);
16085        Some(utf16_offset.0)
16086    }
16087}
16088
16089trait SelectionExt {
16090    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
16091    fn spanned_rows(
16092        &self,
16093        include_end_if_at_line_start: bool,
16094        map: &DisplaySnapshot,
16095    ) -> Range<MultiBufferRow>;
16096}
16097
16098impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
16099    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
16100        let start = self
16101            .start
16102            .to_point(&map.buffer_snapshot)
16103            .to_display_point(map);
16104        let end = self
16105            .end
16106            .to_point(&map.buffer_snapshot)
16107            .to_display_point(map);
16108        if self.reversed {
16109            end..start
16110        } else {
16111            start..end
16112        }
16113    }
16114
16115    fn spanned_rows(
16116        &self,
16117        include_end_if_at_line_start: bool,
16118        map: &DisplaySnapshot,
16119    ) -> Range<MultiBufferRow> {
16120        let start = self.start.to_point(&map.buffer_snapshot);
16121        let mut end = self.end.to_point(&map.buffer_snapshot);
16122        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
16123            end.row -= 1;
16124        }
16125
16126        let buffer_start = map.prev_line_boundary(start).0;
16127        let buffer_end = map.next_line_boundary(end).0;
16128        MultiBufferRow(buffer_start.row)..MultiBufferRow(buffer_end.row + 1)
16129    }
16130}
16131
16132impl<T: InvalidationRegion> InvalidationStack<T> {
16133    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
16134    where
16135        S: Clone + ToOffset,
16136    {
16137        while let Some(region) = self.last() {
16138            let all_selections_inside_invalidation_ranges =
16139                if selections.len() == region.ranges().len() {
16140                    selections
16141                        .iter()
16142                        .zip(region.ranges().iter().map(|r| r.to_offset(buffer)))
16143                        .all(|(selection, invalidation_range)| {
16144                            let head = selection.head().to_offset(buffer);
16145                            invalidation_range.start <= head && invalidation_range.end >= head
16146                        })
16147                } else {
16148                    false
16149                };
16150
16151            if all_selections_inside_invalidation_ranges {
16152                break;
16153            } else {
16154                self.pop();
16155            }
16156        }
16157    }
16158}
16159
16160impl<T> Default for InvalidationStack<T> {
16161    fn default() -> Self {
16162        Self(Default::default())
16163    }
16164}
16165
16166impl<T> Deref for InvalidationStack<T> {
16167    type Target = Vec<T>;
16168
16169    fn deref(&self) -> &Self::Target {
16170        &self.0
16171    }
16172}
16173
16174impl<T> DerefMut for InvalidationStack<T> {
16175    fn deref_mut(&mut self) -> &mut Self::Target {
16176        &mut self.0
16177    }
16178}
16179
16180impl InvalidationRegion for SnippetState {
16181    fn ranges(&self) -> &[Range<Anchor>] {
16182        &self.ranges[self.active_index]
16183    }
16184}
16185
16186pub fn diagnostic_block_renderer(
16187    diagnostic: Diagnostic,
16188    max_message_rows: Option<u8>,
16189    allow_closing: bool,
16190    _is_valid: bool,
16191) -> RenderBlock {
16192    let (text_without_backticks, code_ranges) =
16193        highlight_diagnostic_message(&diagnostic, max_message_rows);
16194
16195    Arc::new(move |cx: &mut BlockContext| {
16196        let group_id: SharedString = cx.block_id.to_string().into();
16197
16198        let mut text_style = cx.window.text_style().clone();
16199        text_style.color = diagnostic_style(diagnostic.severity, cx.theme().status());
16200        let theme_settings = ThemeSettings::get_global(cx);
16201        text_style.font_family = theme_settings.buffer_font.family.clone();
16202        text_style.font_style = theme_settings.buffer_font.style;
16203        text_style.font_features = theme_settings.buffer_font.features.clone();
16204        text_style.font_weight = theme_settings.buffer_font.weight;
16205
16206        let multi_line_diagnostic = diagnostic.message.contains('\n');
16207
16208        let buttons = |diagnostic: &Diagnostic| {
16209            if multi_line_diagnostic {
16210                v_flex()
16211            } else {
16212                h_flex()
16213            }
16214            .when(allow_closing, |div| {
16215                div.children(diagnostic.is_primary.then(|| {
16216                    IconButton::new("close-block", IconName::XCircle)
16217                        .icon_color(Color::Muted)
16218                        .size(ButtonSize::Compact)
16219                        .style(ButtonStyle::Transparent)
16220                        .visible_on_hover(group_id.clone())
16221                        .on_click(move |_click, window, cx| {
16222                            window.dispatch_action(Box::new(Cancel), cx)
16223                        })
16224                        .tooltip(|window, cx| {
16225                            Tooltip::for_action("Close Diagnostics", &Cancel, window, cx)
16226                        })
16227                }))
16228            })
16229            .child(
16230                IconButton::new("copy-block", IconName::Copy)
16231                    .icon_color(Color::Muted)
16232                    .size(ButtonSize::Compact)
16233                    .style(ButtonStyle::Transparent)
16234                    .visible_on_hover(group_id.clone())
16235                    .on_click({
16236                        let message = diagnostic.message.clone();
16237                        move |_click, _, cx| {
16238                            cx.write_to_clipboard(ClipboardItem::new_string(message.clone()))
16239                        }
16240                    })
16241                    .tooltip(Tooltip::text("Copy diagnostic message")),
16242            )
16243        };
16244
16245        let icon_size = buttons(&diagnostic).into_any_element().layout_as_root(
16246            AvailableSpace::min_size(),
16247            cx.window,
16248            cx.app,
16249        );
16250
16251        h_flex()
16252            .id(cx.block_id)
16253            .group(group_id.clone())
16254            .relative()
16255            .size_full()
16256            .block_mouse_down()
16257            .pl(cx.gutter_dimensions.width)
16258            .w(cx.max_width - cx.gutter_dimensions.full_width())
16259            .child(
16260                div()
16261                    .flex()
16262                    .w(cx.anchor_x - cx.gutter_dimensions.width - icon_size.width)
16263                    .flex_shrink(),
16264            )
16265            .child(buttons(&diagnostic))
16266            .child(div().flex().flex_shrink_0().child(
16267                StyledText::new(text_without_backticks.clone()).with_highlights(
16268                    &text_style,
16269                    code_ranges.iter().map(|range| {
16270                        (
16271                            range.clone(),
16272                            HighlightStyle {
16273                                font_weight: Some(FontWeight::BOLD),
16274                                ..Default::default()
16275                            },
16276                        )
16277                    }),
16278                ),
16279            ))
16280            .into_any_element()
16281    })
16282}
16283
16284fn inline_completion_edit_text(
16285    current_snapshot: &BufferSnapshot,
16286    edits: &[(Range<Anchor>, String)],
16287    edit_preview: &EditPreview,
16288    include_deletions: bool,
16289    cx: &App,
16290) -> HighlightedText {
16291    let edits = edits
16292        .iter()
16293        .map(|(anchor, text)| {
16294            (
16295                anchor.start.text_anchor..anchor.end.text_anchor,
16296                text.clone(),
16297            )
16298        })
16299        .collect::<Vec<_>>();
16300
16301    edit_preview.highlight_edits(current_snapshot, &edits, include_deletions, cx)
16302}
16303
16304pub fn highlight_diagnostic_message(
16305    diagnostic: &Diagnostic,
16306    mut max_message_rows: Option<u8>,
16307) -> (SharedString, Vec<Range<usize>>) {
16308    let mut text_without_backticks = String::new();
16309    let mut code_ranges = Vec::new();
16310
16311    if let Some(source) = &diagnostic.source {
16312        text_without_backticks.push_str(source);
16313        code_ranges.push(0..source.len());
16314        text_without_backticks.push_str(": ");
16315    }
16316
16317    let mut prev_offset = 0;
16318    let mut in_code_block = false;
16319    let has_row_limit = max_message_rows.is_some();
16320    let mut newline_indices = diagnostic
16321        .message
16322        .match_indices('\n')
16323        .filter(|_| has_row_limit)
16324        .map(|(ix, _)| ix)
16325        .fuse()
16326        .peekable();
16327
16328    for (quote_ix, _) in diagnostic
16329        .message
16330        .match_indices('`')
16331        .chain([(diagnostic.message.len(), "")])
16332    {
16333        let mut first_newline_ix = None;
16334        let mut last_newline_ix = None;
16335        while let Some(newline_ix) = newline_indices.peek() {
16336            if *newline_ix < quote_ix {
16337                if first_newline_ix.is_none() {
16338                    first_newline_ix = Some(*newline_ix);
16339                }
16340                last_newline_ix = Some(*newline_ix);
16341
16342                if let Some(rows_left) = &mut max_message_rows {
16343                    if *rows_left == 0 {
16344                        break;
16345                    } else {
16346                        *rows_left -= 1;
16347                    }
16348                }
16349                let _ = newline_indices.next();
16350            } else {
16351                break;
16352            }
16353        }
16354        let prev_len = text_without_backticks.len();
16355        let new_text = &diagnostic.message[prev_offset..first_newline_ix.unwrap_or(quote_ix)];
16356        text_without_backticks.push_str(new_text);
16357        if in_code_block {
16358            code_ranges.push(prev_len..text_without_backticks.len());
16359        }
16360        prev_offset = last_newline_ix.unwrap_or(quote_ix) + 1;
16361        in_code_block = !in_code_block;
16362        if first_newline_ix.map_or(false, |newline_ix| newline_ix < quote_ix) {
16363            text_without_backticks.push_str("...");
16364            break;
16365        }
16366    }
16367
16368    (text_without_backticks.into(), code_ranges)
16369}
16370
16371fn diagnostic_style(severity: DiagnosticSeverity, colors: &StatusColors) -> Hsla {
16372    match severity {
16373        DiagnosticSeverity::ERROR => colors.error,
16374        DiagnosticSeverity::WARNING => colors.warning,
16375        DiagnosticSeverity::INFORMATION => colors.info,
16376        DiagnosticSeverity::HINT => colors.info,
16377        _ => colors.ignored,
16378    }
16379}
16380
16381pub fn styled_runs_for_code_label<'a>(
16382    label: &'a CodeLabel,
16383    syntax_theme: &'a theme::SyntaxTheme,
16384) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
16385    let fade_out = HighlightStyle {
16386        fade_out: Some(0.35),
16387        ..Default::default()
16388    };
16389
16390    let mut prev_end = label.filter_range.end;
16391    label
16392        .runs
16393        .iter()
16394        .enumerate()
16395        .flat_map(move |(ix, (range, highlight_id))| {
16396            let style = if let Some(style) = highlight_id.style(syntax_theme) {
16397                style
16398            } else {
16399                return Default::default();
16400            };
16401            let mut muted_style = style;
16402            muted_style.highlight(fade_out);
16403
16404            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
16405            if range.start >= label.filter_range.end {
16406                if range.start > prev_end {
16407                    runs.push((prev_end..range.start, fade_out));
16408                }
16409                runs.push((range.clone(), muted_style));
16410            } else if range.end <= label.filter_range.end {
16411                runs.push((range.clone(), style));
16412            } else {
16413                runs.push((range.start..label.filter_range.end, style));
16414                runs.push((label.filter_range.end..range.end, muted_style));
16415            }
16416            prev_end = cmp::max(prev_end, range.end);
16417
16418            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
16419                runs.push((prev_end..label.text.len(), fade_out));
16420            }
16421
16422            runs
16423        })
16424}
16425
16426pub(crate) fn split_words(text: &str) -> impl std::iter::Iterator<Item = &str> + '_ {
16427    let mut prev_index = 0;
16428    let mut prev_codepoint: Option<char> = None;
16429    text.char_indices()
16430        .chain([(text.len(), '\0')])
16431        .filter_map(move |(index, codepoint)| {
16432            let prev_codepoint = prev_codepoint.replace(codepoint)?;
16433            let is_boundary = index == text.len()
16434                || !prev_codepoint.is_uppercase() && codepoint.is_uppercase()
16435                || !prev_codepoint.is_alphanumeric() && codepoint.is_alphanumeric();
16436            if is_boundary {
16437                let chunk = &text[prev_index..index];
16438                prev_index = index;
16439                Some(chunk)
16440            } else {
16441                None
16442            }
16443        })
16444}
16445
16446pub trait RangeToAnchorExt: Sized {
16447    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor>;
16448
16449    fn to_display_points(self, snapshot: &EditorSnapshot) -> Range<DisplayPoint> {
16450        let anchor_range = self.to_anchors(&snapshot.buffer_snapshot);
16451        anchor_range.start.to_display_point(snapshot)..anchor_range.end.to_display_point(snapshot)
16452    }
16453}
16454
16455impl<T: ToOffset> RangeToAnchorExt for Range<T> {
16456    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor> {
16457        let start_offset = self.start.to_offset(snapshot);
16458        let end_offset = self.end.to_offset(snapshot);
16459        if start_offset == end_offset {
16460            snapshot.anchor_before(start_offset)..snapshot.anchor_before(end_offset)
16461        } else {
16462            snapshot.anchor_after(self.start)..snapshot.anchor_before(self.end)
16463        }
16464    }
16465}
16466
16467pub trait RowExt {
16468    fn as_f32(&self) -> f32;
16469
16470    fn next_row(&self) -> Self;
16471
16472    fn previous_row(&self) -> Self;
16473
16474    fn minus(&self, other: Self) -> u32;
16475}
16476
16477impl RowExt for DisplayRow {
16478    fn as_f32(&self) -> f32 {
16479        self.0 as f32
16480    }
16481
16482    fn next_row(&self) -> Self {
16483        Self(self.0 + 1)
16484    }
16485
16486    fn previous_row(&self) -> Self {
16487        Self(self.0.saturating_sub(1))
16488    }
16489
16490    fn minus(&self, other: Self) -> u32 {
16491        self.0 - other.0
16492    }
16493}
16494
16495impl RowExt for MultiBufferRow {
16496    fn as_f32(&self) -> f32 {
16497        self.0 as f32
16498    }
16499
16500    fn next_row(&self) -> Self {
16501        Self(self.0 + 1)
16502    }
16503
16504    fn previous_row(&self) -> Self {
16505        Self(self.0.saturating_sub(1))
16506    }
16507
16508    fn minus(&self, other: Self) -> u32 {
16509        self.0 - other.0
16510    }
16511}
16512
16513trait RowRangeExt {
16514    type Row;
16515
16516    fn len(&self) -> usize;
16517
16518    fn iter_rows(&self) -> impl DoubleEndedIterator<Item = Self::Row>;
16519}
16520
16521impl RowRangeExt for Range<MultiBufferRow> {
16522    type Row = MultiBufferRow;
16523
16524    fn len(&self) -> usize {
16525        (self.end.0 - self.start.0) as usize
16526    }
16527
16528    fn iter_rows(&self) -> impl DoubleEndedIterator<Item = MultiBufferRow> {
16529        (self.start.0..self.end.0).map(MultiBufferRow)
16530    }
16531}
16532
16533impl RowRangeExt for Range<DisplayRow> {
16534    type Row = DisplayRow;
16535
16536    fn len(&self) -> usize {
16537        (self.end.0 - self.start.0) as usize
16538    }
16539
16540    fn iter_rows(&self) -> impl DoubleEndedIterator<Item = DisplayRow> {
16541        (self.start.0..self.end.0).map(DisplayRow)
16542    }
16543}
16544
16545/// If select range has more than one line, we
16546/// just point the cursor to range.start.
16547fn collapse_multiline_range(range: Range<Point>) -> Range<Point> {
16548    if range.start.row == range.end.row {
16549        range
16550    } else {
16551        range.start..range.start
16552    }
16553}
16554pub struct KillRing(ClipboardItem);
16555impl Global for KillRing {}
16556
16557const UPDATE_DEBOUNCE: Duration = Duration::from_millis(50);
16558
16559fn all_edits_insertions_or_deletions(
16560    edits: &Vec<(Range<Anchor>, String)>,
16561    snapshot: &MultiBufferSnapshot,
16562) -> bool {
16563    let mut all_insertions = true;
16564    let mut all_deletions = true;
16565
16566    for (range, new_text) in edits.iter() {
16567        let range_is_empty = range.to_offset(&snapshot).is_empty();
16568        let text_is_empty = new_text.is_empty();
16569
16570        if range_is_empty != text_is_empty {
16571            if range_is_empty {
16572                all_deletions = false;
16573            } else {
16574                all_insertions = false;
16575            }
16576        } else {
16577            return false;
16578        }
16579
16580        if !all_insertions && !all_deletions {
16581            return false;
16582        }
16583    }
16584    all_insertions || all_deletions
16585}