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 blink_manager;
   17mod clangd_ext;
   18mod code_context_menus;
   19pub mod commit_tooltip;
   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 jsx_tag_auto_close;
   32mod linked_editing_ranges;
   33mod lsp_ext;
   34mod mouse_context_menu;
   35pub mod movement;
   36mod persistence;
   37mod proposed_changes_editor;
   38mod rust_analyzer_ext;
   39pub mod scroll;
   40mod selections_collection;
   41pub mod tasks;
   42
   43#[cfg(test)]
   44mod editor_tests;
   45#[cfg(test)]
   46mod inline_completion_tests;
   47mod signature_help;
   48#[cfg(any(test, feature = "test-support"))]
   49pub mod test;
   50
   51pub(crate) use actions::*;
   52pub use actions::{AcceptEditPrediction, OpenExcerpts, OpenExcerptsSplit};
   53use aho_corasick::AhoCorasick;
   54use anyhow::{anyhow, Context as _, Result};
   55use blink_manager::BlinkManager;
   56use buffer_diff::DiffHunkStatus;
   57use client::{Collaborator, ParticipantIndex};
   58use clock::ReplicaId;
   59use collections::{BTreeMap, HashMap, HashSet, VecDeque};
   60use convert_case::{Case, Casing};
   61use display_map::*;
   62pub use display_map::{DisplayPoint, FoldPlaceholder};
   63pub use editor_settings::{
   64    CurrentLineHighlight, EditorSettings, ScrollBeyondLastLine, SearchSettings, ShowScrollbar,
   65};
   66pub use editor_settings_controls::*;
   67use element::{layout_line, AcceptEditPredictionBinding, LineWithInvisibles, PositionMap};
   68pub use element::{
   69    CursorLayout, EditorElement, HighlightedRange, HighlightedRangeLine, PointForPosition,
   70};
   71use futures::{
   72    future::{self, Shared},
   73    FutureExt,
   74};
   75use fuzzy::StringMatchCandidate;
   76
   77use ::git::Restore;
   78use code_context_menus::{
   79    AvailableCodeAction, CodeActionContents, CodeActionsItem, CodeActionsMenu, CodeContextMenu,
   80    CompletionsMenu, ContextMenuOrigin,
   81};
   82use git::blame::GitBlame;
   83use gpui::{
   84    div, impl_actions, point, prelude::*, pulsating_between, px, relative, size, Action, Animation,
   85    AnimationExt, AnyElement, App, AsyncWindowContext, AvailableSpace, Background, Bounds,
   86    ClipboardEntry, ClipboardItem, Context, DispatchPhase, Edges, Entity, EntityInputHandler,
   87    EventEmitter, FocusHandle, FocusOutEvent, Focusable, FontId, FontWeight, Global,
   88    HighlightStyle, Hsla, KeyContext, Modifiers, MouseButton, MouseDownEvent, PaintQuad,
   89    ParentElement, Pixels, Render, SharedString, Size, Stateful, Styled, StyledText, Subscription,
   90    Task, TextStyle, TextStyleRefinement, UTF16Selection, UnderlineStyle, UniformListScrollHandle,
   91    WeakEntity, WeakFocusHandle, Window,
   92};
   93use highlight_matching_bracket::refresh_matching_bracket_highlights;
   94use hover_popover::{hide_hover, HoverState};
   95use indent_guides::ActiveIndentGuidesState;
   96use inlay_hint_cache::{InlayHintCache, InlaySplice, InvalidationStrategy};
   97pub use inline_completion::Direction;
   98use inline_completion::{EditPredictionProvider, InlineCompletionProviderHandle};
   99pub use items::MAX_TAB_TITLE_LEN;
  100use itertools::Itertools;
  101use language::{
  102    language_settings::{
  103        self, all_language_settings, language_settings, InlayHintSettings, RewrapBehavior,
  104        WordsCompletionMode,
  105    },
  106    point_from_lsp, text_diff_with_options, AutoindentMode, BracketMatch, BracketPair, Buffer,
  107    Capability, CharKind, CodeLabel, CursorShape, Diagnostic, DiffOptions, EditPredictionsMode,
  108    EditPreview, HighlightedText, IndentKind, IndentSize, Language, OffsetRangeExt, Point,
  109    Selection, SelectionGoal, TextObject, TransactionId, TreeSitterOptions,
  110};
  111use language::{point_to_lsp, BufferRow, CharClassifier, Runnable, RunnableRange};
  112use linked_editing_ranges::refresh_linked_ranges;
  113use mouse_context_menu::MouseContextMenu;
  114use persistence::DB;
  115pub use proposed_changes_editor::{
  116    ProposedChangeLocation, ProposedChangesEditor, ProposedChangesEditorToolbar,
  117};
  118use smallvec::smallvec;
  119use std::iter::Peekable;
  120use task::{ResolvedTask, TaskTemplate, TaskVariables};
  121
  122use hover_links::{find_file, HoverLink, HoveredLinkState, InlayHighlight};
  123pub use lsp::CompletionContext;
  124use lsp::{
  125    CodeActionKind, CompletionItemKind, CompletionTriggerKind, DiagnosticSeverity,
  126    InsertTextFormat, LanguageServerId, LanguageServerName,
  127};
  128
  129use language::BufferSnapshot;
  130use movement::TextLayoutDetails;
  131pub use multi_buffer::{
  132    Anchor, AnchorRangeExt, ExcerptId, ExcerptRange, MultiBuffer, MultiBufferSnapshot, RowInfo,
  133    ToOffset, ToPoint,
  134};
  135use multi_buffer::{
  136    ExcerptInfo, ExpandExcerptDirection, MultiBufferDiffHunk, MultiBufferPoint, MultiBufferRow,
  137    MultiOrSingleBufferOffsetRange, ToOffsetUtf16,
  138};
  139use project::{
  140    lsp_store::{CompletionDocumentation, FormatTrigger, LspFormatTarget, OpenLspBufferHandle},
  141    project_settings::{GitGutterSetting, ProjectSettings},
  142    CodeAction, Completion, CompletionIntent, CompletionSource, DocumentHighlight, InlayHint,
  143    Location, LocationLink, PrepareRenameResponse, Project, ProjectItem, ProjectTransaction,
  144    TaskSourceKind,
  145};
  146use rand::prelude::*;
  147use rpc::{proto::*, ErrorExt};
  148use scroll::{Autoscroll, OngoingScroll, ScrollAnchor, ScrollManager, ScrollbarAutoHide};
  149use selections_collection::{
  150    resolve_selections, MutableSelectionsCollection, SelectionsCollection,
  151};
  152use serde::{Deserialize, Serialize};
  153use settings::{update_settings_file, Settings, SettingsLocation, SettingsStore};
  154use smallvec::SmallVec;
  155use snippet::Snippet;
  156use std::{
  157    any::TypeId,
  158    borrow::Cow,
  159    cell::RefCell,
  160    cmp::{self, Ordering, Reverse},
  161    mem,
  162    num::NonZeroU32,
  163    ops::{ControlFlow, Deref, DerefMut, Not as _, Range, RangeInclusive},
  164    path::{Path, PathBuf},
  165    rc::Rc,
  166    sync::Arc,
  167    time::{Duration, Instant},
  168};
  169pub use sum_tree::Bias;
  170use sum_tree::TreeMap;
  171use text::{BufferId, OffsetUtf16, Rope};
  172use theme::{
  173    observe_buffer_font_size_adjustment, ActiveTheme, PlayerColor, StatusColors, SyntaxTheme,
  174    ThemeColors, ThemeSettings,
  175};
  176use ui::{
  177    h_flex, prelude::*, ButtonSize, ButtonStyle, Disclosure, IconButton, IconName, IconSize, Key,
  178    Tooltip,
  179};
  180use util::{defer, maybe, post_inc, RangeExt, ResultExt, TryFutureExt};
  181use workspace::{
  182    item::{ItemHandle, PreviewTabsSettings},
  183    ItemId, RestoreOnStartupBehavior,
  184};
  185use workspace::{
  186    notifications::{DetachAndPromptErr, NotificationId, NotifyTaskExt},
  187    WorkspaceSettings,
  188};
  189use workspace::{
  190    searchable::SearchEvent, ItemNavHistory, SplitDirection, ViewId, Workspace, WorkspaceId,
  191};
  192use workspace::{Item as WorkspaceItem, OpenInTerminal, OpenTerminal, TabBarSettings, Toast};
  193
  194use crate::hover_links::{find_url, find_url_from_range};
  195use crate::signature_help::{SignatureHelpHiddenBy, SignatureHelpState};
  196
  197pub const FILE_HEADER_HEIGHT: u32 = 2;
  198pub const MULTI_BUFFER_EXCERPT_HEADER_HEIGHT: u32 = 1;
  199pub const DEFAULT_MULTIBUFFER_CONTEXT: u32 = 2;
  200const CURSOR_BLINK_INTERVAL: Duration = Duration::from_millis(500);
  201const MAX_LINE_LEN: usize = 1024;
  202const MIN_NAVIGATION_HISTORY_ROW_DELTA: i64 = 10;
  203const MAX_SELECTION_HISTORY_LEN: usize = 1024;
  204pub(crate) const CURSORS_VISIBLE_FOR: Duration = Duration::from_millis(2000);
  205#[doc(hidden)]
  206pub const CODE_ACTIONS_DEBOUNCE_TIMEOUT: Duration = Duration::from_millis(250);
  207
  208pub(crate) const CODE_ACTION_TIMEOUT: Duration = Duration::from_secs(5);
  209pub(crate) const FORMAT_TIMEOUT: Duration = Duration::from_secs(5);
  210pub(crate) const SCROLL_CENTER_TOP_BOTTOM_DEBOUNCE_TIMEOUT: Duration = Duration::from_secs(1);
  211
  212pub(crate) const EDIT_PREDICTION_KEY_CONTEXT: &str = "edit_prediction";
  213pub(crate) const EDIT_PREDICTION_CONFLICT_KEY_CONTEXT: &str = "edit_prediction_conflict";
  214
  215const COLUMNAR_SELECTION_MODIFIERS: Modifiers = Modifiers {
  216    alt: true,
  217    shift: true,
  218    control: false,
  219    platform: false,
  220    function: false,
  221};
  222
  223#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
  224pub enum InlayId {
  225    InlineCompletion(usize),
  226    Hint(usize),
  227}
  228
  229impl InlayId {
  230    fn id(&self) -> usize {
  231        match self {
  232            Self::InlineCompletion(id) => *id,
  233            Self::Hint(id) => *id,
  234        }
  235    }
  236}
  237
  238enum DocumentHighlightRead {}
  239enum DocumentHighlightWrite {}
  240enum InputComposition {}
  241enum SelectedTextHighlight {}
  242
  243#[derive(Debug, Copy, Clone, PartialEq, Eq)]
  244pub enum Navigated {
  245    Yes,
  246    No,
  247}
  248
  249impl Navigated {
  250    pub fn from_bool(yes: bool) -> Navigated {
  251        if yes {
  252            Navigated::Yes
  253        } else {
  254            Navigated::No
  255        }
  256    }
  257}
  258
  259#[derive(Debug, Clone, PartialEq, Eq)]
  260enum DisplayDiffHunk {
  261    Folded {
  262        display_row: DisplayRow,
  263    },
  264    Unfolded {
  265        is_created_file: bool,
  266        diff_base_byte_range: Range<usize>,
  267        display_row_range: Range<DisplayRow>,
  268        multi_buffer_range: Range<Anchor>,
  269        status: DiffHunkStatus,
  270    },
  271}
  272
  273pub fn init_settings(cx: &mut App) {
  274    EditorSettings::register(cx);
  275}
  276
  277pub fn init(cx: &mut App) {
  278    init_settings(cx);
  279
  280    workspace::register_project_item::<Editor>(cx);
  281    workspace::FollowableViewRegistry::register::<Editor>(cx);
  282    workspace::register_serializable_item::<Editor>(cx);
  283
  284    cx.observe_new(
  285        |workspace: &mut Workspace, _: Option<&mut Window>, _cx: &mut Context<Workspace>| {
  286            workspace.register_action(Editor::new_file);
  287            workspace.register_action(Editor::new_file_vertical);
  288            workspace.register_action(Editor::new_file_horizontal);
  289            workspace.register_action(Editor::cancel_language_server_work);
  290        },
  291    )
  292    .detach();
  293
  294    cx.on_action(move |_: &workspace::NewFile, cx| {
  295        let app_state = workspace::AppState::global(cx);
  296        if let Some(app_state) = app_state.upgrade() {
  297            workspace::open_new(
  298                Default::default(),
  299                app_state,
  300                cx,
  301                |workspace, window, cx| {
  302                    Editor::new_file(workspace, &Default::default(), window, cx)
  303                },
  304            )
  305            .detach();
  306        }
  307    });
  308    cx.on_action(move |_: &workspace::NewWindow, cx| {
  309        let app_state = workspace::AppState::global(cx);
  310        if let Some(app_state) = app_state.upgrade() {
  311            workspace::open_new(
  312                Default::default(),
  313                app_state,
  314                cx,
  315                |workspace, window, cx| {
  316                    cx.activate(true);
  317                    Editor::new_file(workspace, &Default::default(), window, cx)
  318                },
  319            )
  320            .detach();
  321        }
  322    });
  323}
  324
  325pub struct SearchWithinRange;
  326
  327trait InvalidationRegion {
  328    fn ranges(&self) -> &[Range<Anchor>];
  329}
  330
  331#[derive(Clone, Debug, PartialEq)]
  332pub enum SelectPhase {
  333    Begin {
  334        position: DisplayPoint,
  335        add: bool,
  336        click_count: usize,
  337    },
  338    BeginColumnar {
  339        position: DisplayPoint,
  340        reset: bool,
  341        goal_column: u32,
  342    },
  343    Extend {
  344        position: DisplayPoint,
  345        click_count: usize,
  346    },
  347    Update {
  348        position: DisplayPoint,
  349        goal_column: u32,
  350        scroll_delta: gpui::Point<f32>,
  351    },
  352    End,
  353}
  354
  355#[derive(Clone, Debug)]
  356pub enum SelectMode {
  357    Character,
  358    Word(Range<Anchor>),
  359    Line(Range<Anchor>),
  360    All,
  361}
  362
  363#[derive(Copy, Clone, PartialEq, Eq, Debug)]
  364pub enum EditorMode {
  365    SingleLine { auto_width: bool },
  366    AutoHeight { max_lines: usize },
  367    Full,
  368}
  369
  370#[derive(Copy, Clone, Debug)]
  371pub enum SoftWrap {
  372    /// Prefer not to wrap at all.
  373    ///
  374    /// Note: this is currently internal, as actually limited by [`crate::MAX_LINE_LEN`] until it wraps.
  375    /// The mode is used inside git diff hunks, where it's seems currently more useful to not wrap as much as possible.
  376    GitDiff,
  377    /// Prefer a single line generally, unless an overly long line is encountered.
  378    None,
  379    /// Soft wrap lines that exceed the editor width.
  380    EditorWidth,
  381    /// Soft wrap lines at the preferred line length.
  382    Column(u32),
  383    /// Soft wrap line at the preferred line length or the editor width (whichever is smaller).
  384    Bounded(u32),
  385}
  386
  387#[derive(Clone)]
  388pub struct EditorStyle {
  389    pub background: Hsla,
  390    pub local_player: PlayerColor,
  391    pub text: TextStyle,
  392    pub scrollbar_width: Pixels,
  393    pub syntax: Arc<SyntaxTheme>,
  394    pub status: StatusColors,
  395    pub inlay_hints_style: HighlightStyle,
  396    pub inline_completion_styles: InlineCompletionStyles,
  397    pub unnecessary_code_fade: f32,
  398}
  399
  400impl Default for EditorStyle {
  401    fn default() -> Self {
  402        Self {
  403            background: Hsla::default(),
  404            local_player: PlayerColor::default(),
  405            text: TextStyle::default(),
  406            scrollbar_width: Pixels::default(),
  407            syntax: Default::default(),
  408            // HACK: Status colors don't have a real default.
  409            // We should look into removing the status colors from the editor
  410            // style and retrieve them directly from the theme.
  411            status: StatusColors::dark(),
  412            inlay_hints_style: HighlightStyle::default(),
  413            inline_completion_styles: InlineCompletionStyles {
  414                insertion: HighlightStyle::default(),
  415                whitespace: HighlightStyle::default(),
  416            },
  417            unnecessary_code_fade: Default::default(),
  418        }
  419    }
  420}
  421
  422pub fn make_inlay_hints_style(cx: &mut App) -> HighlightStyle {
  423    let show_background = language_settings::language_settings(None, None, cx)
  424        .inlay_hints
  425        .show_background;
  426
  427    HighlightStyle {
  428        color: Some(cx.theme().status().hint),
  429        background_color: show_background.then(|| cx.theme().status().hint_background),
  430        ..HighlightStyle::default()
  431    }
  432}
  433
  434pub fn make_suggestion_styles(cx: &mut App) -> InlineCompletionStyles {
  435    InlineCompletionStyles {
  436        insertion: HighlightStyle {
  437            color: Some(cx.theme().status().predictive),
  438            ..HighlightStyle::default()
  439        },
  440        whitespace: HighlightStyle {
  441            background_color: Some(cx.theme().status().created_background),
  442            ..HighlightStyle::default()
  443        },
  444    }
  445}
  446
  447type CompletionId = usize;
  448
  449pub(crate) enum EditDisplayMode {
  450    TabAccept,
  451    DiffPopover,
  452    Inline,
  453}
  454
  455enum InlineCompletion {
  456    Edit {
  457        edits: Vec<(Range<Anchor>, String)>,
  458        edit_preview: Option<EditPreview>,
  459        display_mode: EditDisplayMode,
  460        snapshot: BufferSnapshot,
  461    },
  462    Move {
  463        target: Anchor,
  464        snapshot: BufferSnapshot,
  465    },
  466}
  467
  468struct InlineCompletionState {
  469    inlay_ids: Vec<InlayId>,
  470    completion: InlineCompletion,
  471    completion_id: Option<SharedString>,
  472    invalidation_range: Range<Anchor>,
  473}
  474
  475enum EditPredictionSettings {
  476    Disabled,
  477    Enabled {
  478        show_in_menu: bool,
  479        preview_requires_modifier: bool,
  480    },
  481}
  482
  483enum InlineCompletionHighlight {}
  484
  485#[derive(Debug, Clone)]
  486struct InlineDiagnostic {
  487    message: SharedString,
  488    group_id: usize,
  489    is_primary: bool,
  490    start: Point,
  491    severity: DiagnosticSeverity,
  492}
  493
  494pub enum MenuInlineCompletionsPolicy {
  495    Never,
  496    ByProvider,
  497}
  498
  499pub enum EditPredictionPreview {
  500    /// Modifier is not pressed
  501    Inactive { released_too_fast: bool },
  502    /// Modifier pressed
  503    Active {
  504        since: Instant,
  505        previous_scroll_position: Option<ScrollAnchor>,
  506    },
  507}
  508
  509impl EditPredictionPreview {
  510    pub fn released_too_fast(&self) -> bool {
  511        match self {
  512            EditPredictionPreview::Inactive { released_too_fast } => *released_too_fast,
  513            EditPredictionPreview::Active { .. } => false,
  514        }
  515    }
  516
  517    pub fn set_previous_scroll_position(&mut self, scroll_position: Option<ScrollAnchor>) {
  518        if let EditPredictionPreview::Active {
  519            previous_scroll_position,
  520            ..
  521        } = self
  522        {
  523            *previous_scroll_position = scroll_position;
  524        }
  525    }
  526}
  527
  528#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Debug, Default)]
  529struct EditorActionId(usize);
  530
  531impl EditorActionId {
  532    pub fn post_inc(&mut self) -> Self {
  533        let answer = self.0;
  534
  535        *self = Self(answer + 1);
  536
  537        Self(answer)
  538    }
  539}
  540
  541// type GetFieldEditorTheme = dyn Fn(&theme::Theme) -> theme::FieldEditor;
  542// type OverrideTextStyle = dyn Fn(&EditorStyle) -> Option<HighlightStyle>;
  543
  544type BackgroundHighlight = (fn(&ThemeColors) -> Hsla, Arc<[Range<Anchor>]>);
  545type GutterHighlight = (fn(&App) -> Hsla, Arc<[Range<Anchor>]>);
  546
  547#[derive(Default)]
  548struct ScrollbarMarkerState {
  549    scrollbar_size: Size<Pixels>,
  550    dirty: bool,
  551    markers: Arc<[PaintQuad]>,
  552    pending_refresh: Option<Task<Result<()>>>,
  553}
  554
  555impl ScrollbarMarkerState {
  556    fn should_refresh(&self, scrollbar_size: Size<Pixels>) -> bool {
  557        self.pending_refresh.is_none() && (self.scrollbar_size != scrollbar_size || self.dirty)
  558    }
  559}
  560
  561#[derive(Clone, Debug)]
  562struct RunnableTasks {
  563    templates: Vec<(TaskSourceKind, TaskTemplate)>,
  564    offset: multi_buffer::Anchor,
  565    // We need the column at which the task context evaluation should take place (when we're spawning it via gutter).
  566    column: u32,
  567    // Values of all named captures, including those starting with '_'
  568    extra_variables: HashMap<String, String>,
  569    // Full range of the tagged region. We use it to determine which `extra_variables` to grab for context resolution in e.g. a modal.
  570    context_range: Range<BufferOffset>,
  571}
  572
  573impl RunnableTasks {
  574    fn resolve<'a>(
  575        &'a self,
  576        cx: &'a task::TaskContext,
  577    ) -> impl Iterator<Item = (TaskSourceKind, ResolvedTask)> + 'a {
  578        self.templates.iter().filter_map(|(kind, template)| {
  579            template
  580                .resolve_task(&kind.to_id_base(), cx)
  581                .map(|task| (kind.clone(), task))
  582        })
  583    }
  584}
  585
  586#[derive(Clone)]
  587struct ResolvedTasks {
  588    templates: SmallVec<[(TaskSourceKind, ResolvedTask); 1]>,
  589    position: Anchor,
  590}
  591#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
  592struct BufferOffset(usize);
  593
  594// Addons allow storing per-editor state in other crates (e.g. Vim)
  595pub trait Addon: 'static {
  596    fn extend_key_context(&self, _: &mut KeyContext, _: &App) {}
  597
  598    fn render_buffer_header_controls(
  599        &self,
  600        _: &ExcerptInfo,
  601        _: &Window,
  602        _: &App,
  603    ) -> Option<AnyElement> {
  604        None
  605    }
  606
  607    fn to_any(&self) -> &dyn std::any::Any;
  608}
  609
  610/// Zed's primary implementation of text input, allowing users to edit a [`MultiBuffer`].
  611///
  612/// See the [module level documentation](self) for more information.
  613pub struct Editor {
  614    focus_handle: FocusHandle,
  615    last_focused_descendant: Option<WeakFocusHandle>,
  616    /// The text buffer being edited
  617    buffer: Entity<MultiBuffer>,
  618    /// Map of how text in the buffer should be displayed.
  619    /// Handles soft wraps, folds, fake inlay text insertions, etc.
  620    pub display_map: Entity<DisplayMap>,
  621    pub selections: SelectionsCollection,
  622    pub scroll_manager: ScrollManager,
  623    /// When inline assist editors are linked, they all render cursors because
  624    /// typing enters text into each of them, even the ones that aren't focused.
  625    pub(crate) show_cursor_when_unfocused: bool,
  626    columnar_selection_tail: Option<Anchor>,
  627    add_selections_state: Option<AddSelectionsState>,
  628    select_next_state: Option<SelectNextState>,
  629    select_prev_state: Option<SelectNextState>,
  630    selection_history: SelectionHistory,
  631    autoclose_regions: Vec<AutocloseRegion>,
  632    snippet_stack: InvalidationStack<SnippetState>,
  633    select_larger_syntax_node_stack: Vec<Box<[Selection<usize>]>>,
  634    ime_transaction: Option<TransactionId>,
  635    active_diagnostics: Option<ActiveDiagnosticGroup>,
  636    show_inline_diagnostics: bool,
  637    inline_diagnostics_update: Task<()>,
  638    inline_diagnostics_enabled: bool,
  639    inline_diagnostics: Vec<(Anchor, InlineDiagnostic)>,
  640    soft_wrap_mode_override: Option<language_settings::SoftWrap>,
  641    hard_wrap: Option<usize>,
  642
  643    // TODO: make this a access method
  644    pub project: Option<Entity<Project>>,
  645    semantics_provider: Option<Rc<dyn SemanticsProvider>>,
  646    completion_provider: Option<Box<dyn CompletionProvider>>,
  647    collaboration_hub: Option<Box<dyn CollaborationHub>>,
  648    blink_manager: Entity<BlinkManager>,
  649    show_cursor_names: bool,
  650    hovered_cursors: HashMap<HoveredCursor, Task<()>>,
  651    pub show_local_selections: bool,
  652    mode: EditorMode,
  653    show_breadcrumbs: bool,
  654    show_gutter: bool,
  655    show_scrollbars: bool,
  656    show_line_numbers: Option<bool>,
  657    use_relative_line_numbers: Option<bool>,
  658    show_git_diff_gutter: Option<bool>,
  659    show_code_actions: Option<bool>,
  660    show_runnables: Option<bool>,
  661    show_wrap_guides: Option<bool>,
  662    show_indent_guides: Option<bool>,
  663    placeholder_text: Option<Arc<str>>,
  664    highlight_order: usize,
  665    highlighted_rows: HashMap<TypeId, Vec<RowHighlight>>,
  666    background_highlights: TreeMap<TypeId, BackgroundHighlight>,
  667    gutter_highlights: TreeMap<TypeId, GutterHighlight>,
  668    scrollbar_marker_state: ScrollbarMarkerState,
  669    active_indent_guides_state: ActiveIndentGuidesState,
  670    nav_history: Option<ItemNavHistory>,
  671    context_menu: RefCell<Option<CodeContextMenu>>,
  672    mouse_context_menu: Option<MouseContextMenu>,
  673    completion_tasks: Vec<(CompletionId, Task<Option<()>>)>,
  674    signature_help_state: SignatureHelpState,
  675    auto_signature_help: Option<bool>,
  676    find_all_references_task_sources: Vec<Anchor>,
  677    next_completion_id: CompletionId,
  678    available_code_actions: Option<(Location, Rc<[AvailableCodeAction]>)>,
  679    code_actions_task: Option<Task<Result<()>>>,
  680    selection_highlight_task: Option<Task<()>>,
  681    document_highlights_task: Option<Task<()>>,
  682    linked_editing_range_task: Option<Task<Option<()>>>,
  683    linked_edit_ranges: linked_editing_ranges::LinkedEditingRanges,
  684    pending_rename: Option<RenameState>,
  685    searchable: bool,
  686    cursor_shape: CursorShape,
  687    current_line_highlight: Option<CurrentLineHighlight>,
  688    collapse_matches: bool,
  689    autoindent_mode: Option<AutoindentMode>,
  690    workspace: Option<(WeakEntity<Workspace>, Option<WorkspaceId>)>,
  691    input_enabled: bool,
  692    use_modal_editing: bool,
  693    read_only: bool,
  694    leader_peer_id: Option<PeerId>,
  695    remote_id: Option<ViewId>,
  696    hover_state: HoverState,
  697    pending_mouse_down: Option<Rc<RefCell<Option<MouseDownEvent>>>>,
  698    gutter_hovered: bool,
  699    hovered_link_state: Option<HoveredLinkState>,
  700    edit_prediction_provider: Option<RegisteredInlineCompletionProvider>,
  701    code_action_providers: Vec<Rc<dyn CodeActionProvider>>,
  702    active_inline_completion: Option<InlineCompletionState>,
  703    /// Used to prevent flickering as the user types while the menu is open
  704    stale_inline_completion_in_menu: Option<InlineCompletionState>,
  705    edit_prediction_settings: EditPredictionSettings,
  706    inline_completions_hidden_for_vim_mode: bool,
  707    show_inline_completions_override: Option<bool>,
  708    menu_inline_completions_policy: MenuInlineCompletionsPolicy,
  709    edit_prediction_preview: EditPredictionPreview,
  710    edit_prediction_indent_conflict: bool,
  711    edit_prediction_requires_modifier_in_indent_conflict: bool,
  712    inlay_hint_cache: InlayHintCache,
  713    next_inlay_id: usize,
  714    _subscriptions: Vec<Subscription>,
  715    pixel_position_of_newest_cursor: Option<gpui::Point<Pixels>>,
  716    gutter_dimensions: GutterDimensions,
  717    style: Option<EditorStyle>,
  718    text_style_refinement: Option<TextStyleRefinement>,
  719    next_editor_action_id: EditorActionId,
  720    editor_actions:
  721        Rc<RefCell<BTreeMap<EditorActionId, Box<dyn Fn(&mut Window, &mut Context<Self>)>>>>,
  722    use_autoclose: bool,
  723    use_auto_surround: bool,
  724    auto_replace_emoji_shortcode: bool,
  725    jsx_tag_auto_close_enabled_in_any_buffer: bool,
  726    show_git_blame_gutter: bool,
  727    show_git_blame_inline: bool,
  728    show_git_blame_inline_delay_task: Option<Task<()>>,
  729    git_blame_inline_tooltip: Option<WeakEntity<crate::commit_tooltip::CommitTooltip>>,
  730    git_blame_inline_enabled: bool,
  731    serialize_dirty_buffers: bool,
  732    show_selection_menu: Option<bool>,
  733    blame: Option<Entity<GitBlame>>,
  734    blame_subscription: Option<Subscription>,
  735    custom_context_menu: Option<
  736        Box<
  737            dyn 'static
  738                + Fn(
  739                    &mut Self,
  740                    DisplayPoint,
  741                    &mut Window,
  742                    &mut Context<Self>,
  743                ) -> Option<Entity<ui::ContextMenu>>,
  744        >,
  745    >,
  746    last_bounds: Option<Bounds<Pixels>>,
  747    last_position_map: Option<Rc<PositionMap>>,
  748    expect_bounds_change: Option<Bounds<Pixels>>,
  749    tasks: BTreeMap<(BufferId, BufferRow), RunnableTasks>,
  750    tasks_update_task: Option<Task<()>>,
  751    in_project_search: bool,
  752    previous_search_ranges: Option<Arc<[Range<Anchor>]>>,
  753    breadcrumb_header: Option<String>,
  754    focused_block: Option<FocusedBlock>,
  755    next_scroll_position: NextScrollCursorCenterTopBottom,
  756    addons: HashMap<TypeId, Box<dyn Addon>>,
  757    registered_buffers: HashMap<BufferId, OpenLspBufferHandle>,
  758    load_diff_task: Option<Shared<Task<()>>>,
  759    selection_mark_mode: bool,
  760    toggle_fold_multiple_buffers: Task<()>,
  761    _scroll_cursor_center_top_bottom_task: Task<()>,
  762    serialize_selections: Task<()>,
  763}
  764
  765#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)]
  766enum NextScrollCursorCenterTopBottom {
  767    #[default]
  768    Center,
  769    Top,
  770    Bottom,
  771}
  772
  773impl NextScrollCursorCenterTopBottom {
  774    fn next(&self) -> Self {
  775        match self {
  776            Self::Center => Self::Top,
  777            Self::Top => Self::Bottom,
  778            Self::Bottom => Self::Center,
  779        }
  780    }
  781}
  782
  783#[derive(Clone)]
  784pub struct EditorSnapshot {
  785    pub mode: EditorMode,
  786    show_gutter: bool,
  787    show_line_numbers: Option<bool>,
  788    show_git_diff_gutter: Option<bool>,
  789    show_code_actions: Option<bool>,
  790    show_runnables: Option<bool>,
  791    git_blame_gutter_max_author_length: Option<usize>,
  792    pub display_snapshot: DisplaySnapshot,
  793    pub placeholder_text: Option<Arc<str>>,
  794    is_focused: bool,
  795    scroll_anchor: ScrollAnchor,
  796    ongoing_scroll: OngoingScroll,
  797    current_line_highlight: CurrentLineHighlight,
  798    gutter_hovered: bool,
  799}
  800
  801const GIT_BLAME_MAX_AUTHOR_CHARS_DISPLAYED: usize = 20;
  802
  803#[derive(Default, Debug, Clone, Copy)]
  804pub struct GutterDimensions {
  805    pub left_padding: Pixels,
  806    pub right_padding: Pixels,
  807    pub width: Pixels,
  808    pub margin: Pixels,
  809    pub git_blame_entries_width: Option<Pixels>,
  810}
  811
  812impl GutterDimensions {
  813    /// The full width of the space taken up by the gutter.
  814    pub fn full_width(&self) -> Pixels {
  815        self.margin + self.width
  816    }
  817
  818    /// The width of the space reserved for the fold indicators,
  819    /// use alongside 'justify_end' and `gutter_width` to
  820    /// right align content with the line numbers
  821    pub fn fold_area_width(&self) -> Pixels {
  822        self.margin + self.right_padding
  823    }
  824}
  825
  826#[derive(Debug)]
  827pub struct RemoteSelection {
  828    pub replica_id: ReplicaId,
  829    pub selection: Selection<Anchor>,
  830    pub cursor_shape: CursorShape,
  831    pub peer_id: PeerId,
  832    pub line_mode: bool,
  833    pub participant_index: Option<ParticipantIndex>,
  834    pub user_name: Option<SharedString>,
  835}
  836
  837#[derive(Clone, Debug)]
  838struct SelectionHistoryEntry {
  839    selections: Arc<[Selection<Anchor>]>,
  840    select_next_state: Option<SelectNextState>,
  841    select_prev_state: Option<SelectNextState>,
  842    add_selections_state: Option<AddSelectionsState>,
  843}
  844
  845enum SelectionHistoryMode {
  846    Normal,
  847    Undoing,
  848    Redoing,
  849}
  850
  851#[derive(Clone, PartialEq, Eq, Hash)]
  852struct HoveredCursor {
  853    replica_id: u16,
  854    selection_id: usize,
  855}
  856
  857impl Default for SelectionHistoryMode {
  858    fn default() -> Self {
  859        Self::Normal
  860    }
  861}
  862
  863#[derive(Default)]
  864struct SelectionHistory {
  865    #[allow(clippy::type_complexity)]
  866    selections_by_transaction:
  867        HashMap<TransactionId, (Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)>,
  868    mode: SelectionHistoryMode,
  869    undo_stack: VecDeque<SelectionHistoryEntry>,
  870    redo_stack: VecDeque<SelectionHistoryEntry>,
  871}
  872
  873impl SelectionHistory {
  874    fn insert_transaction(
  875        &mut self,
  876        transaction_id: TransactionId,
  877        selections: Arc<[Selection<Anchor>]>,
  878    ) {
  879        self.selections_by_transaction
  880            .insert(transaction_id, (selections, None));
  881    }
  882
  883    #[allow(clippy::type_complexity)]
  884    fn transaction(
  885        &self,
  886        transaction_id: TransactionId,
  887    ) -> Option<&(Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)> {
  888        self.selections_by_transaction.get(&transaction_id)
  889    }
  890
  891    #[allow(clippy::type_complexity)]
  892    fn transaction_mut(
  893        &mut self,
  894        transaction_id: TransactionId,
  895    ) -> Option<&mut (Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)> {
  896        self.selections_by_transaction.get_mut(&transaction_id)
  897    }
  898
  899    fn push(&mut self, entry: SelectionHistoryEntry) {
  900        if !entry.selections.is_empty() {
  901            match self.mode {
  902                SelectionHistoryMode::Normal => {
  903                    self.push_undo(entry);
  904                    self.redo_stack.clear();
  905                }
  906                SelectionHistoryMode::Undoing => self.push_redo(entry),
  907                SelectionHistoryMode::Redoing => self.push_undo(entry),
  908            }
  909        }
  910    }
  911
  912    fn push_undo(&mut self, entry: SelectionHistoryEntry) {
  913        if self
  914            .undo_stack
  915            .back()
  916            .map_or(true, |e| e.selections != entry.selections)
  917        {
  918            self.undo_stack.push_back(entry);
  919            if self.undo_stack.len() > MAX_SELECTION_HISTORY_LEN {
  920                self.undo_stack.pop_front();
  921            }
  922        }
  923    }
  924
  925    fn push_redo(&mut self, entry: SelectionHistoryEntry) {
  926        if self
  927            .redo_stack
  928            .back()
  929            .map_or(true, |e| e.selections != entry.selections)
  930        {
  931            self.redo_stack.push_back(entry);
  932            if self.redo_stack.len() > MAX_SELECTION_HISTORY_LEN {
  933                self.redo_stack.pop_front();
  934            }
  935        }
  936    }
  937}
  938
  939struct RowHighlight {
  940    index: usize,
  941    range: Range<Anchor>,
  942    color: Hsla,
  943    should_autoscroll: bool,
  944}
  945
  946#[derive(Clone, Debug)]
  947struct AddSelectionsState {
  948    above: bool,
  949    stack: Vec<usize>,
  950}
  951
  952#[derive(Clone)]
  953struct SelectNextState {
  954    query: AhoCorasick,
  955    wordwise: bool,
  956    done: bool,
  957}
  958
  959impl std::fmt::Debug for SelectNextState {
  960    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  961        f.debug_struct(std::any::type_name::<Self>())
  962            .field("wordwise", &self.wordwise)
  963            .field("done", &self.done)
  964            .finish()
  965    }
  966}
  967
  968#[derive(Debug)]
  969struct AutocloseRegion {
  970    selection_id: usize,
  971    range: Range<Anchor>,
  972    pair: BracketPair,
  973}
  974
  975#[derive(Debug)]
  976struct SnippetState {
  977    ranges: Vec<Vec<Range<Anchor>>>,
  978    active_index: usize,
  979    choices: Vec<Option<Vec<String>>>,
  980}
  981
  982#[doc(hidden)]
  983pub struct RenameState {
  984    pub range: Range<Anchor>,
  985    pub old_name: Arc<str>,
  986    pub editor: Entity<Editor>,
  987    block_id: CustomBlockId,
  988}
  989
  990struct InvalidationStack<T>(Vec<T>);
  991
  992struct RegisteredInlineCompletionProvider {
  993    provider: Arc<dyn InlineCompletionProviderHandle>,
  994    _subscription: Subscription,
  995}
  996
  997#[derive(Debug, PartialEq, Eq)]
  998struct ActiveDiagnosticGroup {
  999    primary_range: Range<Anchor>,
 1000    primary_message: String,
 1001    group_id: usize,
 1002    blocks: HashMap<CustomBlockId, Diagnostic>,
 1003    is_valid: bool,
 1004}
 1005
 1006#[derive(Serialize, Deserialize, Clone, Debug)]
 1007pub struct ClipboardSelection {
 1008    /// The number of bytes in this selection.
 1009    pub len: usize,
 1010    /// Whether this was a full-line selection.
 1011    pub is_entire_line: bool,
 1012    /// The indentation of the first line when this content was originally copied.
 1013    pub first_line_indent: u32,
 1014}
 1015
 1016#[derive(Debug)]
 1017pub(crate) struct NavigationData {
 1018    cursor_anchor: Anchor,
 1019    cursor_position: Point,
 1020    scroll_anchor: ScrollAnchor,
 1021    scroll_top_row: u32,
 1022}
 1023
 1024#[derive(Debug, Clone, Copy, PartialEq, Eq)]
 1025pub enum GotoDefinitionKind {
 1026    Symbol,
 1027    Declaration,
 1028    Type,
 1029    Implementation,
 1030}
 1031
 1032#[derive(Debug, Clone)]
 1033enum InlayHintRefreshReason {
 1034    ModifiersChanged(bool),
 1035    Toggle(bool),
 1036    SettingsChange(InlayHintSettings),
 1037    NewLinesShown,
 1038    BufferEdited(HashSet<Arc<Language>>),
 1039    RefreshRequested,
 1040    ExcerptsRemoved(Vec<ExcerptId>),
 1041}
 1042
 1043impl InlayHintRefreshReason {
 1044    fn description(&self) -> &'static str {
 1045        match self {
 1046            Self::ModifiersChanged(_) => "modifiers changed",
 1047            Self::Toggle(_) => "toggle",
 1048            Self::SettingsChange(_) => "settings change",
 1049            Self::NewLinesShown => "new lines shown",
 1050            Self::BufferEdited(_) => "buffer edited",
 1051            Self::RefreshRequested => "refresh requested",
 1052            Self::ExcerptsRemoved(_) => "excerpts removed",
 1053        }
 1054    }
 1055}
 1056
 1057pub enum FormatTarget {
 1058    Buffers,
 1059    Ranges(Vec<Range<MultiBufferPoint>>),
 1060}
 1061
 1062pub(crate) struct FocusedBlock {
 1063    id: BlockId,
 1064    focus_handle: WeakFocusHandle,
 1065}
 1066
 1067#[derive(Clone)]
 1068enum JumpData {
 1069    MultiBufferRow {
 1070        row: MultiBufferRow,
 1071        line_offset_from_top: u32,
 1072    },
 1073    MultiBufferPoint {
 1074        excerpt_id: ExcerptId,
 1075        position: Point,
 1076        anchor: text::Anchor,
 1077        line_offset_from_top: u32,
 1078    },
 1079}
 1080
 1081pub enum MultibufferSelectionMode {
 1082    First,
 1083    All,
 1084}
 1085
 1086impl Editor {
 1087    pub fn single_line(window: &mut Window, cx: &mut Context<Self>) -> Self {
 1088        let buffer = cx.new(|cx| Buffer::local("", cx));
 1089        let buffer = cx.new(|cx| MultiBuffer::singleton(buffer, cx));
 1090        Self::new(
 1091            EditorMode::SingleLine { auto_width: false },
 1092            buffer,
 1093            None,
 1094            window,
 1095            cx,
 1096        )
 1097    }
 1098
 1099    pub fn multi_line(window: &mut Window, cx: &mut Context<Self>) -> Self {
 1100        let buffer = cx.new(|cx| Buffer::local("", cx));
 1101        let buffer = cx.new(|cx| MultiBuffer::singleton(buffer, cx));
 1102        Self::new(EditorMode::Full, buffer, None, window, cx)
 1103    }
 1104
 1105    pub fn auto_width(window: &mut Window, cx: &mut Context<Self>) -> Self {
 1106        let buffer = cx.new(|cx| Buffer::local("", cx));
 1107        let buffer = cx.new(|cx| MultiBuffer::singleton(buffer, cx));
 1108        Self::new(
 1109            EditorMode::SingleLine { auto_width: true },
 1110            buffer,
 1111            None,
 1112            window,
 1113            cx,
 1114        )
 1115    }
 1116
 1117    pub fn auto_height(max_lines: usize, window: &mut Window, cx: &mut Context<Self>) -> Self {
 1118        let buffer = cx.new(|cx| Buffer::local("", cx));
 1119        let buffer = cx.new(|cx| MultiBuffer::singleton(buffer, cx));
 1120        Self::new(
 1121            EditorMode::AutoHeight { max_lines },
 1122            buffer,
 1123            None,
 1124            window,
 1125            cx,
 1126        )
 1127    }
 1128
 1129    pub fn for_buffer(
 1130        buffer: Entity<Buffer>,
 1131        project: Option<Entity<Project>>,
 1132        window: &mut Window,
 1133        cx: &mut Context<Self>,
 1134    ) -> Self {
 1135        let buffer = cx.new(|cx| MultiBuffer::singleton(buffer, cx));
 1136        Self::new(EditorMode::Full, buffer, project, window, cx)
 1137    }
 1138
 1139    pub fn for_multibuffer(
 1140        buffer: Entity<MultiBuffer>,
 1141        project: Option<Entity<Project>>,
 1142        window: &mut Window,
 1143        cx: &mut Context<Self>,
 1144    ) -> Self {
 1145        Self::new(EditorMode::Full, buffer, project, window, cx)
 1146    }
 1147
 1148    pub fn clone(&self, window: &mut Window, cx: &mut Context<Self>) -> Self {
 1149        let mut clone = Self::new(
 1150            self.mode,
 1151            self.buffer.clone(),
 1152            self.project.clone(),
 1153            window,
 1154            cx,
 1155        );
 1156        self.display_map.update(cx, |display_map, cx| {
 1157            let snapshot = display_map.snapshot(cx);
 1158            clone.display_map.update(cx, |display_map, cx| {
 1159                display_map.set_state(&snapshot, cx);
 1160            });
 1161        });
 1162        clone.selections.clone_state(&self.selections);
 1163        clone.scroll_manager.clone_state(&self.scroll_manager);
 1164        clone.searchable = self.searchable;
 1165        clone
 1166    }
 1167
 1168    pub fn new(
 1169        mode: EditorMode,
 1170        buffer: Entity<MultiBuffer>,
 1171        project: Option<Entity<Project>>,
 1172        window: &mut Window,
 1173        cx: &mut Context<Self>,
 1174    ) -> Self {
 1175        let style = window.text_style();
 1176        let font_size = style.font_size.to_pixels(window.rem_size());
 1177        let editor = cx.entity().downgrade();
 1178        let fold_placeholder = FoldPlaceholder {
 1179            constrain_width: true,
 1180            render: Arc::new(move |fold_id, fold_range, cx| {
 1181                let editor = editor.clone();
 1182                div()
 1183                    .id(fold_id)
 1184                    .bg(cx.theme().colors().ghost_element_background)
 1185                    .hover(|style| style.bg(cx.theme().colors().ghost_element_hover))
 1186                    .active(|style| style.bg(cx.theme().colors().ghost_element_active))
 1187                    .rounded_xs()
 1188                    .size_full()
 1189                    .cursor_pointer()
 1190                    .child("")
 1191                    .on_mouse_down(MouseButton::Left, |_, _, cx| cx.stop_propagation())
 1192                    .on_click(move |_, _window, cx| {
 1193                        editor
 1194                            .update(cx, |editor, cx| {
 1195                                editor.unfold_ranges(
 1196                                    &[fold_range.start..fold_range.end],
 1197                                    true,
 1198                                    false,
 1199                                    cx,
 1200                                );
 1201                                cx.stop_propagation();
 1202                            })
 1203                            .ok();
 1204                    })
 1205                    .into_any()
 1206            }),
 1207            merge_adjacent: true,
 1208            ..Default::default()
 1209        };
 1210        let display_map = cx.new(|cx| {
 1211            DisplayMap::new(
 1212                buffer.clone(),
 1213                style.font(),
 1214                font_size,
 1215                None,
 1216                FILE_HEADER_HEIGHT,
 1217                MULTI_BUFFER_EXCERPT_HEADER_HEIGHT,
 1218                fold_placeholder,
 1219                cx,
 1220            )
 1221        });
 1222
 1223        let selections = SelectionsCollection::new(display_map.clone(), buffer.clone());
 1224
 1225        let blink_manager = cx.new(|cx| BlinkManager::new(CURSOR_BLINK_INTERVAL, cx));
 1226
 1227        let soft_wrap_mode_override = matches!(mode, EditorMode::SingleLine { .. })
 1228            .then(|| language_settings::SoftWrap::None);
 1229
 1230        let mut project_subscriptions = Vec::new();
 1231        if mode == EditorMode::Full {
 1232            if let Some(project) = project.as_ref() {
 1233                project_subscriptions.push(cx.subscribe_in(
 1234                    project,
 1235                    window,
 1236                    |editor, _, event, window, cx| {
 1237                        if let project::Event::RefreshInlayHints = event {
 1238                            editor
 1239                                .refresh_inlay_hints(InlayHintRefreshReason::RefreshRequested, cx);
 1240                        } else if let project::Event::SnippetEdit(id, snippet_edits) = event {
 1241                            if let Some(buffer) = editor.buffer.read(cx).buffer(*id) {
 1242                                let focus_handle = editor.focus_handle(cx);
 1243                                if focus_handle.is_focused(window) {
 1244                                    let snapshot = buffer.read(cx).snapshot();
 1245                                    for (range, snippet) in snippet_edits {
 1246                                        let editor_range =
 1247                                            language::range_from_lsp(*range).to_offset(&snapshot);
 1248                                        editor
 1249                                            .insert_snippet(
 1250                                                &[editor_range],
 1251                                                snippet.clone(),
 1252                                                window,
 1253                                                cx,
 1254                                            )
 1255                                            .ok();
 1256                                    }
 1257                                }
 1258                            }
 1259                        }
 1260                    },
 1261                ));
 1262                if let Some(task_inventory) = project
 1263                    .read(cx)
 1264                    .task_store()
 1265                    .read(cx)
 1266                    .task_inventory()
 1267                    .cloned()
 1268                {
 1269                    project_subscriptions.push(cx.observe_in(
 1270                        &task_inventory,
 1271                        window,
 1272                        |editor, _, window, cx| {
 1273                            editor.tasks_update_task = Some(editor.refresh_runnables(window, cx));
 1274                        },
 1275                    ));
 1276                }
 1277            }
 1278        }
 1279
 1280        let buffer_snapshot = buffer.read(cx).snapshot(cx);
 1281
 1282        let inlay_hint_settings =
 1283            inlay_hint_settings(selections.newest_anchor().head(), &buffer_snapshot, cx);
 1284        let focus_handle = cx.focus_handle();
 1285        cx.on_focus(&focus_handle, window, Self::handle_focus)
 1286            .detach();
 1287        cx.on_focus_in(&focus_handle, window, Self::handle_focus_in)
 1288            .detach();
 1289        cx.on_focus_out(&focus_handle, window, Self::handle_focus_out)
 1290            .detach();
 1291        cx.on_blur(&focus_handle, window, Self::handle_blur)
 1292            .detach();
 1293
 1294        let show_indent_guides = if matches!(mode, EditorMode::SingleLine { .. }) {
 1295            Some(false)
 1296        } else {
 1297            None
 1298        };
 1299
 1300        let mut code_action_providers = Vec::new();
 1301        let mut load_uncommitted_diff = None;
 1302        if let Some(project) = project.clone() {
 1303            load_uncommitted_diff = Some(
 1304                get_uncommitted_diff_for_buffer(
 1305                    &project,
 1306                    buffer.read(cx).all_buffers(),
 1307                    buffer.clone(),
 1308                    cx,
 1309                )
 1310                .shared(),
 1311            );
 1312            code_action_providers.push(Rc::new(project) as Rc<_>);
 1313        }
 1314
 1315        let mut this = Self {
 1316            focus_handle,
 1317            show_cursor_when_unfocused: false,
 1318            last_focused_descendant: None,
 1319            buffer: buffer.clone(),
 1320            display_map: display_map.clone(),
 1321            selections,
 1322            scroll_manager: ScrollManager::new(cx),
 1323            columnar_selection_tail: None,
 1324            add_selections_state: None,
 1325            select_next_state: None,
 1326            select_prev_state: None,
 1327            selection_history: Default::default(),
 1328            autoclose_regions: Default::default(),
 1329            snippet_stack: Default::default(),
 1330            select_larger_syntax_node_stack: Vec::new(),
 1331            ime_transaction: Default::default(),
 1332            active_diagnostics: None,
 1333            show_inline_diagnostics: ProjectSettings::get_global(cx).diagnostics.inline.enabled,
 1334            inline_diagnostics_update: Task::ready(()),
 1335            inline_diagnostics: Vec::new(),
 1336            soft_wrap_mode_override,
 1337            hard_wrap: None,
 1338            completion_provider: project.clone().map(|project| Box::new(project) as _),
 1339            semantics_provider: project.clone().map(|project| Rc::new(project) as _),
 1340            collaboration_hub: project.clone().map(|project| Box::new(project) as _),
 1341            project,
 1342            blink_manager: blink_manager.clone(),
 1343            show_local_selections: true,
 1344            show_scrollbars: true,
 1345            mode,
 1346            show_breadcrumbs: EditorSettings::get_global(cx).toolbar.breadcrumbs,
 1347            show_gutter: mode == EditorMode::Full,
 1348            show_line_numbers: None,
 1349            use_relative_line_numbers: None,
 1350            show_git_diff_gutter: None,
 1351            show_code_actions: None,
 1352            show_runnables: None,
 1353            show_wrap_guides: None,
 1354            show_indent_guides,
 1355            placeholder_text: None,
 1356            highlight_order: 0,
 1357            highlighted_rows: HashMap::default(),
 1358            background_highlights: Default::default(),
 1359            gutter_highlights: TreeMap::default(),
 1360            scrollbar_marker_state: ScrollbarMarkerState::default(),
 1361            active_indent_guides_state: ActiveIndentGuidesState::default(),
 1362            nav_history: None,
 1363            context_menu: RefCell::new(None),
 1364            mouse_context_menu: None,
 1365            completion_tasks: Default::default(),
 1366            signature_help_state: SignatureHelpState::default(),
 1367            auto_signature_help: None,
 1368            find_all_references_task_sources: Vec::new(),
 1369            next_completion_id: 0,
 1370            next_inlay_id: 0,
 1371            code_action_providers,
 1372            available_code_actions: Default::default(),
 1373            code_actions_task: Default::default(),
 1374            selection_highlight_task: Default::default(),
 1375            document_highlights_task: Default::default(),
 1376            linked_editing_range_task: Default::default(),
 1377            pending_rename: Default::default(),
 1378            searchable: true,
 1379            cursor_shape: EditorSettings::get_global(cx)
 1380                .cursor_shape
 1381                .unwrap_or_default(),
 1382            current_line_highlight: None,
 1383            autoindent_mode: Some(AutoindentMode::EachLine),
 1384            collapse_matches: false,
 1385            workspace: None,
 1386            input_enabled: true,
 1387            use_modal_editing: mode == EditorMode::Full,
 1388            read_only: false,
 1389            use_autoclose: true,
 1390            use_auto_surround: true,
 1391            auto_replace_emoji_shortcode: false,
 1392            jsx_tag_auto_close_enabled_in_any_buffer: false,
 1393            leader_peer_id: None,
 1394            remote_id: None,
 1395            hover_state: Default::default(),
 1396            pending_mouse_down: None,
 1397            hovered_link_state: Default::default(),
 1398            edit_prediction_provider: None,
 1399            active_inline_completion: None,
 1400            stale_inline_completion_in_menu: None,
 1401            edit_prediction_preview: EditPredictionPreview::Inactive {
 1402                released_too_fast: false,
 1403            },
 1404            inline_diagnostics_enabled: mode == EditorMode::Full,
 1405            inlay_hint_cache: InlayHintCache::new(inlay_hint_settings),
 1406
 1407            gutter_hovered: false,
 1408            pixel_position_of_newest_cursor: None,
 1409            last_bounds: None,
 1410            last_position_map: None,
 1411            expect_bounds_change: None,
 1412            gutter_dimensions: GutterDimensions::default(),
 1413            style: None,
 1414            show_cursor_names: false,
 1415            hovered_cursors: Default::default(),
 1416            next_editor_action_id: EditorActionId::default(),
 1417            editor_actions: Rc::default(),
 1418            inline_completions_hidden_for_vim_mode: false,
 1419            show_inline_completions_override: None,
 1420            menu_inline_completions_policy: MenuInlineCompletionsPolicy::ByProvider,
 1421            edit_prediction_settings: EditPredictionSettings::Disabled,
 1422            edit_prediction_indent_conflict: false,
 1423            edit_prediction_requires_modifier_in_indent_conflict: true,
 1424            custom_context_menu: None,
 1425            show_git_blame_gutter: false,
 1426            show_git_blame_inline: false,
 1427            show_selection_menu: None,
 1428            show_git_blame_inline_delay_task: None,
 1429            git_blame_inline_tooltip: None,
 1430            git_blame_inline_enabled: ProjectSettings::get_global(cx).git.inline_blame_enabled(),
 1431            serialize_dirty_buffers: ProjectSettings::get_global(cx)
 1432                .session
 1433                .restore_unsaved_buffers,
 1434            blame: None,
 1435            blame_subscription: None,
 1436            tasks: Default::default(),
 1437            _subscriptions: vec![
 1438                cx.observe(&buffer, Self::on_buffer_changed),
 1439                cx.subscribe_in(&buffer, window, Self::on_buffer_event),
 1440                cx.observe_in(&display_map, window, Self::on_display_map_changed),
 1441                cx.observe(&blink_manager, |_, _, cx| cx.notify()),
 1442                cx.observe_global_in::<SettingsStore>(window, Self::settings_changed),
 1443                observe_buffer_font_size_adjustment(cx, |_, cx| cx.notify()),
 1444                cx.observe_window_activation(window, |editor, window, cx| {
 1445                    let active = window.is_window_active();
 1446                    editor.blink_manager.update(cx, |blink_manager, cx| {
 1447                        if active {
 1448                            blink_manager.enable(cx);
 1449                        } else {
 1450                            blink_manager.disable(cx);
 1451                        }
 1452                    });
 1453                }),
 1454            ],
 1455            tasks_update_task: None,
 1456            linked_edit_ranges: Default::default(),
 1457            in_project_search: false,
 1458            previous_search_ranges: None,
 1459            breadcrumb_header: None,
 1460            focused_block: None,
 1461            next_scroll_position: NextScrollCursorCenterTopBottom::default(),
 1462            addons: HashMap::default(),
 1463            registered_buffers: HashMap::default(),
 1464            _scroll_cursor_center_top_bottom_task: Task::ready(()),
 1465            selection_mark_mode: false,
 1466            toggle_fold_multiple_buffers: Task::ready(()),
 1467            serialize_selections: Task::ready(()),
 1468            text_style_refinement: None,
 1469            load_diff_task: load_uncommitted_diff,
 1470        };
 1471        this.tasks_update_task = Some(this.refresh_runnables(window, cx));
 1472        this._subscriptions.extend(project_subscriptions);
 1473
 1474        this.end_selection(window, cx);
 1475        this.scroll_manager.show_scrollbar(window, cx);
 1476        jsx_tag_auto_close::refresh_enabled_in_any_buffer(&mut this, &buffer, cx);
 1477
 1478        if mode == EditorMode::Full {
 1479            let should_auto_hide_scrollbars = cx.should_auto_hide_scrollbars();
 1480            cx.set_global(ScrollbarAutoHide(should_auto_hide_scrollbars));
 1481
 1482            if this.git_blame_inline_enabled {
 1483                this.git_blame_inline_enabled = true;
 1484                this.start_git_blame_inline(false, window, cx);
 1485            }
 1486
 1487            if let Some(buffer) = buffer.read(cx).as_singleton() {
 1488                if let Some(project) = this.project.as_ref() {
 1489                    let handle = project.update(cx, |project, cx| {
 1490                        project.register_buffer_with_language_servers(&buffer, cx)
 1491                    });
 1492                    this.registered_buffers
 1493                        .insert(buffer.read(cx).remote_id(), handle);
 1494                }
 1495            }
 1496        }
 1497
 1498        this.report_editor_event("Editor Opened", None, cx);
 1499        this
 1500    }
 1501
 1502    pub fn mouse_menu_is_focused(&self, window: &Window, cx: &App) -> bool {
 1503        self.mouse_context_menu
 1504            .as_ref()
 1505            .is_some_and(|menu| menu.context_menu.focus_handle(cx).is_focused(window))
 1506    }
 1507
 1508    fn key_context(&self, window: &Window, cx: &App) -> KeyContext {
 1509        self.key_context_internal(self.has_active_inline_completion(), window, cx)
 1510    }
 1511
 1512    fn key_context_internal(
 1513        &self,
 1514        has_active_edit_prediction: bool,
 1515        window: &Window,
 1516        cx: &App,
 1517    ) -> KeyContext {
 1518        let mut key_context = KeyContext::new_with_defaults();
 1519        key_context.add("Editor");
 1520        let mode = match self.mode {
 1521            EditorMode::SingleLine { .. } => "single_line",
 1522            EditorMode::AutoHeight { .. } => "auto_height",
 1523            EditorMode::Full => "full",
 1524        };
 1525
 1526        if EditorSettings::jupyter_enabled(cx) {
 1527            key_context.add("jupyter");
 1528        }
 1529
 1530        key_context.set("mode", mode);
 1531        if self.pending_rename.is_some() {
 1532            key_context.add("renaming");
 1533        }
 1534
 1535        match self.context_menu.borrow().as_ref() {
 1536            Some(CodeContextMenu::Completions(_)) => {
 1537                key_context.add("menu");
 1538                key_context.add("showing_completions");
 1539            }
 1540            Some(CodeContextMenu::CodeActions(_)) => {
 1541                key_context.add("menu");
 1542                key_context.add("showing_code_actions")
 1543            }
 1544            None => {}
 1545        }
 1546
 1547        // Disable vim contexts when a sub-editor (e.g. rename/inline assistant) is focused.
 1548        if !self.focus_handle(cx).contains_focused(window, cx)
 1549            || (self.is_focused(window) || self.mouse_menu_is_focused(window, cx))
 1550        {
 1551            for addon in self.addons.values() {
 1552                addon.extend_key_context(&mut key_context, cx)
 1553            }
 1554        }
 1555
 1556        if let Some(singleton_buffer) = self.buffer.read(cx).as_singleton() {
 1557            if let Some(extension) = singleton_buffer
 1558                .read(cx)
 1559                .file()
 1560                .and_then(|file| file.path().extension()?.to_str())
 1561            {
 1562                key_context.set("extension", extension.to_string());
 1563            }
 1564        } else {
 1565            key_context.add("multibuffer");
 1566        }
 1567
 1568        if has_active_edit_prediction {
 1569            if self.edit_prediction_in_conflict() {
 1570                key_context.add(EDIT_PREDICTION_CONFLICT_KEY_CONTEXT);
 1571            } else {
 1572                key_context.add(EDIT_PREDICTION_KEY_CONTEXT);
 1573                key_context.add("copilot_suggestion");
 1574            }
 1575        }
 1576
 1577        if self.selection_mark_mode {
 1578            key_context.add("selection_mode");
 1579        }
 1580
 1581        key_context
 1582    }
 1583
 1584    pub fn edit_prediction_in_conflict(&self) -> bool {
 1585        if !self.show_edit_predictions_in_menu() {
 1586            return false;
 1587        }
 1588
 1589        let showing_completions = self
 1590            .context_menu
 1591            .borrow()
 1592            .as_ref()
 1593            .map_or(false, |context| {
 1594                matches!(context, CodeContextMenu::Completions(_))
 1595            });
 1596
 1597        showing_completions
 1598            || self.edit_prediction_requires_modifier()
 1599            // Require modifier key when the cursor is on leading whitespace, to allow `tab`
 1600            // bindings to insert tab characters.
 1601            || (self.edit_prediction_requires_modifier_in_indent_conflict && self.edit_prediction_indent_conflict)
 1602    }
 1603
 1604    pub fn accept_edit_prediction_keybind(
 1605        &self,
 1606        window: &Window,
 1607        cx: &App,
 1608    ) -> AcceptEditPredictionBinding {
 1609        let key_context = self.key_context_internal(true, window, cx);
 1610        let in_conflict = self.edit_prediction_in_conflict();
 1611
 1612        AcceptEditPredictionBinding(
 1613            window
 1614                .bindings_for_action_in_context(&AcceptEditPrediction, key_context)
 1615                .into_iter()
 1616                .filter(|binding| {
 1617                    !in_conflict
 1618                        || binding
 1619                            .keystrokes()
 1620                            .first()
 1621                            .map_or(false, |keystroke| keystroke.modifiers.modified())
 1622                })
 1623                .rev()
 1624                .min_by_key(|binding| {
 1625                    binding
 1626                        .keystrokes()
 1627                        .first()
 1628                        .map_or(u8::MAX, |k| k.modifiers.number_of_modifiers())
 1629                }),
 1630        )
 1631    }
 1632
 1633    pub fn new_file(
 1634        workspace: &mut Workspace,
 1635        _: &workspace::NewFile,
 1636        window: &mut Window,
 1637        cx: &mut Context<Workspace>,
 1638    ) {
 1639        Self::new_in_workspace(workspace, window, cx).detach_and_prompt_err(
 1640            "Failed to create buffer",
 1641            window,
 1642            cx,
 1643            |e, _, _| match e.error_code() {
 1644                ErrorCode::RemoteUpgradeRequired => Some(format!(
 1645                "The remote instance of Zed does not support this yet. It must be upgraded to {}",
 1646                e.error_tag("required").unwrap_or("the latest version")
 1647            )),
 1648                _ => None,
 1649            },
 1650        );
 1651    }
 1652
 1653    pub fn new_in_workspace(
 1654        workspace: &mut Workspace,
 1655        window: &mut Window,
 1656        cx: &mut Context<Workspace>,
 1657    ) -> Task<Result<Entity<Editor>>> {
 1658        let project = workspace.project().clone();
 1659        let create = project.update(cx, |project, cx| project.create_buffer(cx));
 1660
 1661        cx.spawn_in(window, |workspace, mut cx| async move {
 1662            let buffer = create.await?;
 1663            workspace.update_in(&mut cx, |workspace, window, cx| {
 1664                let editor =
 1665                    cx.new(|cx| Editor::for_buffer(buffer, Some(project.clone()), window, cx));
 1666                workspace.add_item_to_active_pane(Box::new(editor.clone()), None, true, window, cx);
 1667                editor
 1668            })
 1669        })
 1670    }
 1671
 1672    fn new_file_vertical(
 1673        workspace: &mut Workspace,
 1674        _: &workspace::NewFileSplitVertical,
 1675        window: &mut Window,
 1676        cx: &mut Context<Workspace>,
 1677    ) {
 1678        Self::new_file_in_direction(workspace, SplitDirection::vertical(cx), window, cx)
 1679    }
 1680
 1681    fn new_file_horizontal(
 1682        workspace: &mut Workspace,
 1683        _: &workspace::NewFileSplitHorizontal,
 1684        window: &mut Window,
 1685        cx: &mut Context<Workspace>,
 1686    ) {
 1687        Self::new_file_in_direction(workspace, SplitDirection::horizontal(cx), window, cx)
 1688    }
 1689
 1690    fn new_file_in_direction(
 1691        workspace: &mut Workspace,
 1692        direction: SplitDirection,
 1693        window: &mut Window,
 1694        cx: &mut Context<Workspace>,
 1695    ) {
 1696        let project = workspace.project().clone();
 1697        let create = project.update(cx, |project, cx| project.create_buffer(cx));
 1698
 1699        cx.spawn_in(window, |workspace, mut cx| async move {
 1700            let buffer = create.await?;
 1701            workspace.update_in(&mut cx, move |workspace, window, cx| {
 1702                workspace.split_item(
 1703                    direction,
 1704                    Box::new(
 1705                        cx.new(|cx| Editor::for_buffer(buffer, Some(project.clone()), window, cx)),
 1706                    ),
 1707                    window,
 1708                    cx,
 1709                )
 1710            })?;
 1711            anyhow::Ok(())
 1712        })
 1713        .detach_and_prompt_err("Failed to create buffer", window, cx, |e, _, _| {
 1714            match e.error_code() {
 1715                ErrorCode::RemoteUpgradeRequired => Some(format!(
 1716                "The remote instance of Zed does not support this yet. It must be upgraded to {}",
 1717                e.error_tag("required").unwrap_or("the latest version")
 1718            )),
 1719                _ => None,
 1720            }
 1721        });
 1722    }
 1723
 1724    pub fn leader_peer_id(&self) -> Option<PeerId> {
 1725        self.leader_peer_id
 1726    }
 1727
 1728    pub fn buffer(&self) -> &Entity<MultiBuffer> {
 1729        &self.buffer
 1730    }
 1731
 1732    pub fn workspace(&self) -> Option<Entity<Workspace>> {
 1733        self.workspace.as_ref()?.0.upgrade()
 1734    }
 1735
 1736    pub fn title<'a>(&self, cx: &'a App) -> Cow<'a, str> {
 1737        self.buffer().read(cx).title(cx)
 1738    }
 1739
 1740    pub fn snapshot(&self, window: &mut Window, cx: &mut App) -> EditorSnapshot {
 1741        let git_blame_gutter_max_author_length = self
 1742            .render_git_blame_gutter(cx)
 1743            .then(|| {
 1744                if let Some(blame) = self.blame.as_ref() {
 1745                    let max_author_length =
 1746                        blame.update(cx, |blame, cx| blame.max_author_length(cx));
 1747                    Some(max_author_length)
 1748                } else {
 1749                    None
 1750                }
 1751            })
 1752            .flatten();
 1753
 1754        EditorSnapshot {
 1755            mode: self.mode,
 1756            show_gutter: self.show_gutter,
 1757            show_line_numbers: self.show_line_numbers,
 1758            show_git_diff_gutter: self.show_git_diff_gutter,
 1759            show_code_actions: self.show_code_actions,
 1760            show_runnables: self.show_runnables,
 1761            git_blame_gutter_max_author_length,
 1762            display_snapshot: self.display_map.update(cx, |map, cx| map.snapshot(cx)),
 1763            scroll_anchor: self.scroll_manager.anchor(),
 1764            ongoing_scroll: self.scroll_manager.ongoing_scroll(),
 1765            placeholder_text: self.placeholder_text.clone(),
 1766            is_focused: self.focus_handle.is_focused(window),
 1767            current_line_highlight: self
 1768                .current_line_highlight
 1769                .unwrap_or_else(|| EditorSettings::get_global(cx).current_line_highlight),
 1770            gutter_hovered: self.gutter_hovered,
 1771        }
 1772    }
 1773
 1774    pub fn language_at<T: ToOffset>(&self, point: T, cx: &App) -> Option<Arc<Language>> {
 1775        self.buffer.read(cx).language_at(point, cx)
 1776    }
 1777
 1778    pub fn file_at<T: ToOffset>(&self, point: T, cx: &App) -> Option<Arc<dyn language::File>> {
 1779        self.buffer.read(cx).read(cx).file_at(point).cloned()
 1780    }
 1781
 1782    pub fn active_excerpt(
 1783        &self,
 1784        cx: &App,
 1785    ) -> Option<(ExcerptId, Entity<Buffer>, Range<text::Anchor>)> {
 1786        self.buffer
 1787            .read(cx)
 1788            .excerpt_containing(self.selections.newest_anchor().head(), cx)
 1789    }
 1790
 1791    pub fn mode(&self) -> EditorMode {
 1792        self.mode
 1793    }
 1794
 1795    pub fn collaboration_hub(&self) -> Option<&dyn CollaborationHub> {
 1796        self.collaboration_hub.as_deref()
 1797    }
 1798
 1799    pub fn set_collaboration_hub(&mut self, hub: Box<dyn CollaborationHub>) {
 1800        self.collaboration_hub = Some(hub);
 1801    }
 1802
 1803    pub fn set_in_project_search(&mut self, in_project_search: bool) {
 1804        self.in_project_search = in_project_search;
 1805    }
 1806
 1807    pub fn set_custom_context_menu(
 1808        &mut self,
 1809        f: impl 'static
 1810            + Fn(
 1811                &mut Self,
 1812                DisplayPoint,
 1813                &mut Window,
 1814                &mut Context<Self>,
 1815            ) -> Option<Entity<ui::ContextMenu>>,
 1816    ) {
 1817        self.custom_context_menu = Some(Box::new(f))
 1818    }
 1819
 1820    pub fn set_completion_provider(&mut self, provider: Option<Box<dyn CompletionProvider>>) {
 1821        self.completion_provider = provider;
 1822    }
 1823
 1824    pub fn semantics_provider(&self) -> Option<Rc<dyn SemanticsProvider>> {
 1825        self.semantics_provider.clone()
 1826    }
 1827
 1828    pub fn set_semantics_provider(&mut self, provider: Option<Rc<dyn SemanticsProvider>>) {
 1829        self.semantics_provider = provider;
 1830    }
 1831
 1832    pub fn set_edit_prediction_provider<T>(
 1833        &mut self,
 1834        provider: Option<Entity<T>>,
 1835        window: &mut Window,
 1836        cx: &mut Context<Self>,
 1837    ) where
 1838        T: EditPredictionProvider,
 1839    {
 1840        self.edit_prediction_provider =
 1841            provider.map(|provider| RegisteredInlineCompletionProvider {
 1842                _subscription: cx.observe_in(&provider, window, |this, _, window, cx| {
 1843                    if this.focus_handle.is_focused(window) {
 1844                        this.update_visible_inline_completion(window, cx);
 1845                    }
 1846                }),
 1847                provider: Arc::new(provider),
 1848            });
 1849        self.update_edit_prediction_settings(cx);
 1850        self.refresh_inline_completion(false, false, window, cx);
 1851    }
 1852
 1853    pub fn placeholder_text(&self) -> Option<&str> {
 1854        self.placeholder_text.as_deref()
 1855    }
 1856
 1857    pub fn set_placeholder_text(
 1858        &mut self,
 1859        placeholder_text: impl Into<Arc<str>>,
 1860        cx: &mut Context<Self>,
 1861    ) {
 1862        let placeholder_text = Some(placeholder_text.into());
 1863        if self.placeholder_text != placeholder_text {
 1864            self.placeholder_text = placeholder_text;
 1865            cx.notify();
 1866        }
 1867    }
 1868
 1869    pub fn set_cursor_shape(&mut self, cursor_shape: CursorShape, cx: &mut Context<Self>) {
 1870        self.cursor_shape = cursor_shape;
 1871
 1872        // Disrupt blink for immediate user feedback that the cursor shape has changed
 1873        self.blink_manager.update(cx, BlinkManager::show_cursor);
 1874
 1875        cx.notify();
 1876    }
 1877
 1878    pub fn set_current_line_highlight(
 1879        &mut self,
 1880        current_line_highlight: Option<CurrentLineHighlight>,
 1881    ) {
 1882        self.current_line_highlight = current_line_highlight;
 1883    }
 1884
 1885    pub fn set_collapse_matches(&mut self, collapse_matches: bool) {
 1886        self.collapse_matches = collapse_matches;
 1887    }
 1888
 1889    fn register_buffers_with_language_servers(&mut self, cx: &mut Context<Self>) {
 1890        let buffers = self.buffer.read(cx).all_buffers();
 1891        let Some(project) = self.project.as_ref() else {
 1892            return;
 1893        };
 1894        project.update(cx, |project, cx| {
 1895            for buffer in buffers {
 1896                self.registered_buffers
 1897                    .entry(buffer.read(cx).remote_id())
 1898                    .or_insert_with(|| project.register_buffer_with_language_servers(&buffer, cx));
 1899            }
 1900        })
 1901    }
 1902
 1903    pub fn range_for_match<T: std::marker::Copy>(&self, range: &Range<T>) -> Range<T> {
 1904        if self.collapse_matches {
 1905            return range.start..range.start;
 1906        }
 1907        range.clone()
 1908    }
 1909
 1910    pub fn set_clip_at_line_ends(&mut self, clip: bool, cx: &mut Context<Self>) {
 1911        if self.display_map.read(cx).clip_at_line_ends != clip {
 1912            self.display_map
 1913                .update(cx, |map, _| map.clip_at_line_ends = clip);
 1914        }
 1915    }
 1916
 1917    pub fn set_input_enabled(&mut self, input_enabled: bool) {
 1918        self.input_enabled = input_enabled;
 1919    }
 1920
 1921    pub fn set_inline_completions_hidden_for_vim_mode(
 1922        &mut self,
 1923        hidden: bool,
 1924        window: &mut Window,
 1925        cx: &mut Context<Self>,
 1926    ) {
 1927        if hidden != self.inline_completions_hidden_for_vim_mode {
 1928            self.inline_completions_hidden_for_vim_mode = hidden;
 1929            if hidden {
 1930                self.update_visible_inline_completion(window, cx);
 1931            } else {
 1932                self.refresh_inline_completion(true, false, window, cx);
 1933            }
 1934        }
 1935    }
 1936
 1937    pub fn set_menu_inline_completions_policy(&mut self, value: MenuInlineCompletionsPolicy) {
 1938        self.menu_inline_completions_policy = value;
 1939    }
 1940
 1941    pub fn set_autoindent(&mut self, autoindent: bool) {
 1942        if autoindent {
 1943            self.autoindent_mode = Some(AutoindentMode::EachLine);
 1944        } else {
 1945            self.autoindent_mode = None;
 1946        }
 1947    }
 1948
 1949    pub fn read_only(&self, cx: &App) -> bool {
 1950        self.read_only || self.buffer.read(cx).read_only()
 1951    }
 1952
 1953    pub fn set_read_only(&mut self, read_only: bool) {
 1954        self.read_only = read_only;
 1955    }
 1956
 1957    pub fn set_use_autoclose(&mut self, autoclose: bool) {
 1958        self.use_autoclose = autoclose;
 1959    }
 1960
 1961    pub fn set_use_auto_surround(&mut self, auto_surround: bool) {
 1962        self.use_auto_surround = auto_surround;
 1963    }
 1964
 1965    pub fn set_auto_replace_emoji_shortcode(&mut self, auto_replace: bool) {
 1966        self.auto_replace_emoji_shortcode = auto_replace;
 1967    }
 1968
 1969    pub fn toggle_edit_predictions(
 1970        &mut self,
 1971        _: &ToggleEditPrediction,
 1972        window: &mut Window,
 1973        cx: &mut Context<Self>,
 1974    ) {
 1975        if self.show_inline_completions_override.is_some() {
 1976            self.set_show_edit_predictions(None, window, cx);
 1977        } else {
 1978            let show_edit_predictions = !self.edit_predictions_enabled();
 1979            self.set_show_edit_predictions(Some(show_edit_predictions), window, cx);
 1980        }
 1981    }
 1982
 1983    pub fn set_show_edit_predictions(
 1984        &mut self,
 1985        show_edit_predictions: Option<bool>,
 1986        window: &mut Window,
 1987        cx: &mut Context<Self>,
 1988    ) {
 1989        self.show_inline_completions_override = show_edit_predictions;
 1990        self.update_edit_prediction_settings(cx);
 1991
 1992        if let Some(false) = show_edit_predictions {
 1993            self.discard_inline_completion(false, cx);
 1994        } else {
 1995            self.refresh_inline_completion(false, true, window, cx);
 1996        }
 1997    }
 1998
 1999    fn inline_completions_disabled_in_scope(
 2000        &self,
 2001        buffer: &Entity<Buffer>,
 2002        buffer_position: language::Anchor,
 2003        cx: &App,
 2004    ) -> bool {
 2005        let snapshot = buffer.read(cx).snapshot();
 2006        let settings = snapshot.settings_at(buffer_position, cx);
 2007
 2008        let Some(scope) = snapshot.language_scope_at(buffer_position) else {
 2009            return false;
 2010        };
 2011
 2012        scope.override_name().map_or(false, |scope_name| {
 2013            settings
 2014                .edit_predictions_disabled_in
 2015                .iter()
 2016                .any(|s| s == scope_name)
 2017        })
 2018    }
 2019
 2020    pub fn set_use_modal_editing(&mut self, to: bool) {
 2021        self.use_modal_editing = to;
 2022    }
 2023
 2024    pub fn use_modal_editing(&self) -> bool {
 2025        self.use_modal_editing
 2026    }
 2027
 2028    fn selections_did_change(
 2029        &mut self,
 2030        local: bool,
 2031        old_cursor_position: &Anchor,
 2032        show_completions: bool,
 2033        window: &mut Window,
 2034        cx: &mut Context<Self>,
 2035    ) {
 2036        window.invalidate_character_coordinates();
 2037
 2038        // Copy selections to primary selection buffer
 2039        #[cfg(any(target_os = "linux", target_os = "freebsd"))]
 2040        if local {
 2041            let selections = self.selections.all::<usize>(cx);
 2042            let buffer_handle = self.buffer.read(cx).read(cx);
 2043
 2044            let mut text = String::new();
 2045            for (index, selection) in selections.iter().enumerate() {
 2046                let text_for_selection = buffer_handle
 2047                    .text_for_range(selection.start..selection.end)
 2048                    .collect::<String>();
 2049
 2050                text.push_str(&text_for_selection);
 2051                if index != selections.len() - 1 {
 2052                    text.push('\n');
 2053                }
 2054            }
 2055
 2056            if !text.is_empty() {
 2057                cx.write_to_primary(ClipboardItem::new_string(text));
 2058            }
 2059        }
 2060
 2061        if self.focus_handle.is_focused(window) && self.leader_peer_id.is_none() {
 2062            self.buffer.update(cx, |buffer, cx| {
 2063                buffer.set_active_selections(
 2064                    &self.selections.disjoint_anchors(),
 2065                    self.selections.line_mode,
 2066                    self.cursor_shape,
 2067                    cx,
 2068                )
 2069            });
 2070        }
 2071        let display_map = self
 2072            .display_map
 2073            .update(cx, |display_map, cx| display_map.snapshot(cx));
 2074        let buffer = &display_map.buffer_snapshot;
 2075        self.add_selections_state = None;
 2076        self.select_next_state = None;
 2077        self.select_prev_state = None;
 2078        self.select_larger_syntax_node_stack.clear();
 2079        self.invalidate_autoclose_regions(&self.selections.disjoint_anchors(), buffer);
 2080        self.snippet_stack
 2081            .invalidate(&self.selections.disjoint_anchors(), buffer);
 2082        self.take_rename(false, window, cx);
 2083
 2084        let new_cursor_position = self.selections.newest_anchor().head();
 2085
 2086        self.push_to_nav_history(
 2087            *old_cursor_position,
 2088            Some(new_cursor_position.to_point(buffer)),
 2089            cx,
 2090        );
 2091
 2092        if local {
 2093            let new_cursor_position = self.selections.newest_anchor().head();
 2094            let mut context_menu = self.context_menu.borrow_mut();
 2095            let completion_menu = match context_menu.as_ref() {
 2096                Some(CodeContextMenu::Completions(menu)) => Some(menu),
 2097                _ => {
 2098                    *context_menu = None;
 2099                    None
 2100                }
 2101            };
 2102            if let Some(buffer_id) = new_cursor_position.buffer_id {
 2103                if !self.registered_buffers.contains_key(&buffer_id) {
 2104                    if let Some(project) = self.project.as_ref() {
 2105                        project.update(cx, |project, cx| {
 2106                            let Some(buffer) = self.buffer.read(cx).buffer(buffer_id) else {
 2107                                return;
 2108                            };
 2109                            self.registered_buffers.insert(
 2110                                buffer_id,
 2111                                project.register_buffer_with_language_servers(&buffer, cx),
 2112                            );
 2113                        })
 2114                    }
 2115                }
 2116            }
 2117
 2118            if let Some(completion_menu) = completion_menu {
 2119                let cursor_position = new_cursor_position.to_offset(buffer);
 2120                let (word_range, kind) =
 2121                    buffer.surrounding_word(completion_menu.initial_position, true);
 2122                if kind == Some(CharKind::Word)
 2123                    && word_range.to_inclusive().contains(&cursor_position)
 2124                {
 2125                    let mut completion_menu = completion_menu.clone();
 2126                    drop(context_menu);
 2127
 2128                    let query = Self::completion_query(buffer, cursor_position);
 2129                    cx.spawn(move |this, mut cx| async move {
 2130                        completion_menu
 2131                            .filter(query.as_deref(), cx.background_executor().clone())
 2132                            .await;
 2133
 2134                        this.update(&mut cx, |this, cx| {
 2135                            let mut context_menu = this.context_menu.borrow_mut();
 2136                            let Some(CodeContextMenu::Completions(menu)) = context_menu.as_ref()
 2137                            else {
 2138                                return;
 2139                            };
 2140
 2141                            if menu.id > completion_menu.id {
 2142                                return;
 2143                            }
 2144
 2145                            *context_menu = Some(CodeContextMenu::Completions(completion_menu));
 2146                            drop(context_menu);
 2147                            cx.notify();
 2148                        })
 2149                    })
 2150                    .detach();
 2151
 2152                    if show_completions {
 2153                        self.show_completions(&ShowCompletions { trigger: None }, window, cx);
 2154                    }
 2155                } else {
 2156                    drop(context_menu);
 2157                    self.hide_context_menu(window, cx);
 2158                }
 2159            } else {
 2160                drop(context_menu);
 2161            }
 2162
 2163            hide_hover(self, cx);
 2164
 2165            if old_cursor_position.to_display_point(&display_map).row()
 2166                != new_cursor_position.to_display_point(&display_map).row()
 2167            {
 2168                self.available_code_actions.take();
 2169            }
 2170            self.refresh_code_actions(window, cx);
 2171            self.refresh_document_highlights(cx);
 2172            self.refresh_selected_text_highlights(window, cx);
 2173            refresh_matching_bracket_highlights(self, window, cx);
 2174            self.update_visible_inline_completion(window, cx);
 2175            self.edit_prediction_requires_modifier_in_indent_conflict = true;
 2176            linked_editing_ranges::refresh_linked_ranges(self, window, cx);
 2177            if self.git_blame_inline_enabled {
 2178                self.start_inline_blame_timer(window, cx);
 2179            }
 2180        }
 2181
 2182        self.blink_manager.update(cx, BlinkManager::pause_blinking);
 2183        cx.emit(EditorEvent::SelectionsChanged { local });
 2184
 2185        let selections = &self.selections.disjoint;
 2186        if selections.len() == 1 {
 2187            cx.emit(SearchEvent::ActiveMatchChanged)
 2188        }
 2189        if local
 2190            && self.is_singleton(cx)
 2191            && WorkspaceSettings::get(None, cx).restore_on_startup != RestoreOnStartupBehavior::None
 2192        {
 2193            if let Some(workspace_id) = self.workspace.as_ref().and_then(|workspace| workspace.1) {
 2194                let background_executor = cx.background_executor().clone();
 2195                let editor_id = cx.entity().entity_id().as_u64() as ItemId;
 2196                let snapshot = self.buffer().read(cx).snapshot(cx);
 2197                let selections = selections.clone();
 2198                self.serialize_selections = cx.background_spawn(async move {
 2199                    background_executor.timer(Duration::from_millis(100)).await;
 2200                    let selections = selections
 2201                        .iter()
 2202                        .map(|selection| {
 2203                            (
 2204                                selection.start.to_offset(&snapshot),
 2205                                selection.end.to_offset(&snapshot),
 2206                            )
 2207                        })
 2208                        .collect();
 2209                    DB.save_editor_selections(editor_id, workspace_id, selections)
 2210                        .await
 2211                        .with_context(|| format!("persisting editor selections for editor {editor_id}, workspace {workspace_id:?}"))
 2212                        .log_err();
 2213                });
 2214            }
 2215        }
 2216
 2217        cx.notify();
 2218    }
 2219
 2220    pub fn sync_selections(
 2221        &mut self,
 2222        other: Entity<Editor>,
 2223        cx: &mut Context<Self>,
 2224    ) -> gpui::Subscription {
 2225        let other_selections = other.read(cx).selections.disjoint.to_vec();
 2226        self.selections.change_with(cx, |selections| {
 2227            selections.select_anchors(other_selections);
 2228        });
 2229
 2230        let other_subscription =
 2231            cx.subscribe(&other, |this, other, other_evt, cx| match other_evt {
 2232                EditorEvent::SelectionsChanged { local: true } => {
 2233                    let other_selections = other.read(cx).selections.disjoint.to_vec();
 2234                    if other_selections.is_empty() {
 2235                        return;
 2236                    }
 2237                    this.selections.change_with(cx, |selections| {
 2238                        selections.select_anchors(other_selections);
 2239                    });
 2240                }
 2241                _ => {}
 2242            });
 2243
 2244        let this_subscription =
 2245            cx.subscribe_self::<EditorEvent>(move |this, this_evt, cx| match this_evt {
 2246                EditorEvent::SelectionsChanged { local: true } => {
 2247                    let these_selections = this.selections.disjoint.to_vec();
 2248                    if these_selections.is_empty() {
 2249                        return;
 2250                    }
 2251                    other.update(cx, |other_editor, cx| {
 2252                        other_editor.selections.change_with(cx, |selections| {
 2253                            selections.select_anchors(these_selections);
 2254                        })
 2255                    });
 2256                }
 2257                _ => {}
 2258            });
 2259
 2260        Subscription::join(other_subscription, this_subscription)
 2261    }
 2262
 2263    pub fn change_selections<R>(
 2264        &mut self,
 2265        autoscroll: Option<Autoscroll>,
 2266        window: &mut Window,
 2267        cx: &mut Context<Self>,
 2268        change: impl FnOnce(&mut MutableSelectionsCollection<'_>) -> R,
 2269    ) -> R {
 2270        self.change_selections_inner(autoscroll, true, window, cx, change)
 2271    }
 2272
 2273    fn change_selections_inner<R>(
 2274        &mut self,
 2275        autoscroll: Option<Autoscroll>,
 2276        request_completions: bool,
 2277        window: &mut Window,
 2278        cx: &mut Context<Self>,
 2279        change: impl FnOnce(&mut MutableSelectionsCollection<'_>) -> R,
 2280    ) -> R {
 2281        let old_cursor_position = self.selections.newest_anchor().head();
 2282        self.push_to_selection_history();
 2283
 2284        let (changed, result) = self.selections.change_with(cx, change);
 2285
 2286        if changed {
 2287            if let Some(autoscroll) = autoscroll {
 2288                self.request_autoscroll(autoscroll, cx);
 2289            }
 2290            self.selections_did_change(true, &old_cursor_position, request_completions, window, cx);
 2291
 2292            if self.should_open_signature_help_automatically(
 2293                &old_cursor_position,
 2294                self.signature_help_state.backspace_pressed(),
 2295                cx,
 2296            ) {
 2297                self.show_signature_help(&ShowSignatureHelp, window, cx);
 2298            }
 2299            self.signature_help_state.set_backspace_pressed(false);
 2300        }
 2301
 2302        result
 2303    }
 2304
 2305    pub fn edit<I, S, T>(&mut self, edits: I, cx: &mut Context<Self>)
 2306    where
 2307        I: IntoIterator<Item = (Range<S>, T)>,
 2308        S: ToOffset,
 2309        T: Into<Arc<str>>,
 2310    {
 2311        if self.read_only(cx) {
 2312            return;
 2313        }
 2314
 2315        self.buffer
 2316            .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
 2317    }
 2318
 2319    pub fn edit_with_autoindent<I, S, T>(&mut self, edits: I, cx: &mut Context<Self>)
 2320    where
 2321        I: IntoIterator<Item = (Range<S>, T)>,
 2322        S: ToOffset,
 2323        T: Into<Arc<str>>,
 2324    {
 2325        if self.read_only(cx) {
 2326            return;
 2327        }
 2328
 2329        self.buffer.update(cx, |buffer, cx| {
 2330            buffer.edit(edits, self.autoindent_mode.clone(), cx)
 2331        });
 2332    }
 2333
 2334    pub fn edit_with_block_indent<I, S, T>(
 2335        &mut self,
 2336        edits: I,
 2337        original_indent_columns: Vec<Option<u32>>,
 2338        cx: &mut Context<Self>,
 2339    ) where
 2340        I: IntoIterator<Item = (Range<S>, T)>,
 2341        S: ToOffset,
 2342        T: Into<Arc<str>>,
 2343    {
 2344        if self.read_only(cx) {
 2345            return;
 2346        }
 2347
 2348        self.buffer.update(cx, |buffer, cx| {
 2349            buffer.edit(
 2350                edits,
 2351                Some(AutoindentMode::Block {
 2352                    original_indent_columns,
 2353                }),
 2354                cx,
 2355            )
 2356        });
 2357    }
 2358
 2359    fn select(&mut self, phase: SelectPhase, window: &mut Window, cx: &mut Context<Self>) {
 2360        self.hide_context_menu(window, cx);
 2361
 2362        match phase {
 2363            SelectPhase::Begin {
 2364                position,
 2365                add,
 2366                click_count,
 2367            } => self.begin_selection(position, add, click_count, window, cx),
 2368            SelectPhase::BeginColumnar {
 2369                position,
 2370                goal_column,
 2371                reset,
 2372            } => self.begin_columnar_selection(position, goal_column, reset, window, cx),
 2373            SelectPhase::Extend {
 2374                position,
 2375                click_count,
 2376            } => self.extend_selection(position, click_count, window, cx),
 2377            SelectPhase::Update {
 2378                position,
 2379                goal_column,
 2380                scroll_delta,
 2381            } => self.update_selection(position, goal_column, scroll_delta, window, cx),
 2382            SelectPhase::End => self.end_selection(window, cx),
 2383        }
 2384    }
 2385
 2386    fn extend_selection(
 2387        &mut self,
 2388        position: DisplayPoint,
 2389        click_count: usize,
 2390        window: &mut Window,
 2391        cx: &mut Context<Self>,
 2392    ) {
 2393        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 2394        let tail = self.selections.newest::<usize>(cx).tail();
 2395        self.begin_selection(position, false, click_count, window, cx);
 2396
 2397        let position = position.to_offset(&display_map, Bias::Left);
 2398        let tail_anchor = display_map.buffer_snapshot.anchor_before(tail);
 2399
 2400        let mut pending_selection = self
 2401            .selections
 2402            .pending_anchor()
 2403            .expect("extend_selection not called with pending selection");
 2404        if position >= tail {
 2405            pending_selection.start = tail_anchor;
 2406        } else {
 2407            pending_selection.end = tail_anchor;
 2408            pending_selection.reversed = true;
 2409        }
 2410
 2411        let mut pending_mode = self.selections.pending_mode().unwrap();
 2412        match &mut pending_mode {
 2413            SelectMode::Word(range) | SelectMode::Line(range) => *range = tail_anchor..tail_anchor,
 2414            _ => {}
 2415        }
 2416
 2417        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 2418            s.set_pending(pending_selection, pending_mode)
 2419        });
 2420    }
 2421
 2422    fn begin_selection(
 2423        &mut self,
 2424        position: DisplayPoint,
 2425        add: bool,
 2426        click_count: usize,
 2427        window: &mut Window,
 2428        cx: &mut Context<Self>,
 2429    ) {
 2430        if !self.focus_handle.is_focused(window) {
 2431            self.last_focused_descendant = None;
 2432            window.focus(&self.focus_handle);
 2433        }
 2434
 2435        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 2436        let buffer = &display_map.buffer_snapshot;
 2437        let newest_selection = self.selections.newest_anchor().clone();
 2438        let position = display_map.clip_point(position, Bias::Left);
 2439
 2440        let start;
 2441        let end;
 2442        let mode;
 2443        let mut auto_scroll;
 2444        match click_count {
 2445            1 => {
 2446                start = buffer.anchor_before(position.to_point(&display_map));
 2447                end = start;
 2448                mode = SelectMode::Character;
 2449                auto_scroll = true;
 2450            }
 2451            2 => {
 2452                let range = movement::surrounding_word(&display_map, position);
 2453                start = buffer.anchor_before(range.start.to_point(&display_map));
 2454                end = buffer.anchor_before(range.end.to_point(&display_map));
 2455                mode = SelectMode::Word(start..end);
 2456                auto_scroll = true;
 2457            }
 2458            3 => {
 2459                let position = display_map
 2460                    .clip_point(position, Bias::Left)
 2461                    .to_point(&display_map);
 2462                let line_start = display_map.prev_line_boundary(position).0;
 2463                let next_line_start = buffer.clip_point(
 2464                    display_map.next_line_boundary(position).0 + Point::new(1, 0),
 2465                    Bias::Left,
 2466                );
 2467                start = buffer.anchor_before(line_start);
 2468                end = buffer.anchor_before(next_line_start);
 2469                mode = SelectMode::Line(start..end);
 2470                auto_scroll = true;
 2471            }
 2472            _ => {
 2473                start = buffer.anchor_before(0);
 2474                end = buffer.anchor_before(buffer.len());
 2475                mode = SelectMode::All;
 2476                auto_scroll = false;
 2477            }
 2478        }
 2479        auto_scroll &= EditorSettings::get_global(cx).autoscroll_on_clicks;
 2480
 2481        let point_to_delete: Option<usize> = {
 2482            let selected_points: Vec<Selection<Point>> =
 2483                self.selections.disjoint_in_range(start..end, cx);
 2484
 2485            if !add || click_count > 1 {
 2486                None
 2487            } else if !selected_points.is_empty() {
 2488                Some(selected_points[0].id)
 2489            } else {
 2490                let clicked_point_already_selected =
 2491                    self.selections.disjoint.iter().find(|selection| {
 2492                        selection.start.to_point(buffer) == start.to_point(buffer)
 2493                            || selection.end.to_point(buffer) == end.to_point(buffer)
 2494                    });
 2495
 2496                clicked_point_already_selected.map(|selection| selection.id)
 2497            }
 2498        };
 2499
 2500        let selections_count = self.selections.count();
 2501
 2502        self.change_selections(auto_scroll.then(Autoscroll::newest), window, cx, |s| {
 2503            if let Some(point_to_delete) = point_to_delete {
 2504                s.delete(point_to_delete);
 2505
 2506                if selections_count == 1 {
 2507                    s.set_pending_anchor_range(start..end, mode);
 2508                }
 2509            } else {
 2510                if !add {
 2511                    s.clear_disjoint();
 2512                } else if click_count > 1 {
 2513                    s.delete(newest_selection.id)
 2514                }
 2515
 2516                s.set_pending_anchor_range(start..end, mode);
 2517            }
 2518        });
 2519    }
 2520
 2521    fn begin_columnar_selection(
 2522        &mut self,
 2523        position: DisplayPoint,
 2524        goal_column: u32,
 2525        reset: bool,
 2526        window: &mut Window,
 2527        cx: &mut Context<Self>,
 2528    ) {
 2529        if !self.focus_handle.is_focused(window) {
 2530            self.last_focused_descendant = None;
 2531            window.focus(&self.focus_handle);
 2532        }
 2533
 2534        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 2535
 2536        if reset {
 2537            let pointer_position = display_map
 2538                .buffer_snapshot
 2539                .anchor_before(position.to_point(&display_map));
 2540
 2541            self.change_selections(Some(Autoscroll::newest()), window, cx, |s| {
 2542                s.clear_disjoint();
 2543                s.set_pending_anchor_range(
 2544                    pointer_position..pointer_position,
 2545                    SelectMode::Character,
 2546                );
 2547            });
 2548        }
 2549
 2550        let tail = self.selections.newest::<Point>(cx).tail();
 2551        self.columnar_selection_tail = Some(display_map.buffer_snapshot.anchor_before(tail));
 2552
 2553        if !reset {
 2554            self.select_columns(
 2555                tail.to_display_point(&display_map),
 2556                position,
 2557                goal_column,
 2558                &display_map,
 2559                window,
 2560                cx,
 2561            );
 2562        }
 2563    }
 2564
 2565    fn update_selection(
 2566        &mut self,
 2567        position: DisplayPoint,
 2568        goal_column: u32,
 2569        scroll_delta: gpui::Point<f32>,
 2570        window: &mut Window,
 2571        cx: &mut Context<Self>,
 2572    ) {
 2573        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 2574
 2575        if let Some(tail) = self.columnar_selection_tail.as_ref() {
 2576            let tail = tail.to_display_point(&display_map);
 2577            self.select_columns(tail, position, goal_column, &display_map, window, cx);
 2578        } else if let Some(mut pending) = self.selections.pending_anchor() {
 2579            let buffer = self.buffer.read(cx).snapshot(cx);
 2580            let head;
 2581            let tail;
 2582            let mode = self.selections.pending_mode().unwrap();
 2583            match &mode {
 2584                SelectMode::Character => {
 2585                    head = position.to_point(&display_map);
 2586                    tail = pending.tail().to_point(&buffer);
 2587                }
 2588                SelectMode::Word(original_range) => {
 2589                    let original_display_range = original_range.start.to_display_point(&display_map)
 2590                        ..original_range.end.to_display_point(&display_map);
 2591                    let original_buffer_range = original_display_range.start.to_point(&display_map)
 2592                        ..original_display_range.end.to_point(&display_map);
 2593                    if movement::is_inside_word(&display_map, position)
 2594                        || original_display_range.contains(&position)
 2595                    {
 2596                        let word_range = movement::surrounding_word(&display_map, position);
 2597                        if word_range.start < original_display_range.start {
 2598                            head = word_range.start.to_point(&display_map);
 2599                        } else {
 2600                            head = word_range.end.to_point(&display_map);
 2601                        }
 2602                    } else {
 2603                        head = position.to_point(&display_map);
 2604                    }
 2605
 2606                    if head <= original_buffer_range.start {
 2607                        tail = original_buffer_range.end;
 2608                    } else {
 2609                        tail = original_buffer_range.start;
 2610                    }
 2611                }
 2612                SelectMode::Line(original_range) => {
 2613                    let original_range = original_range.to_point(&display_map.buffer_snapshot);
 2614
 2615                    let position = display_map
 2616                        .clip_point(position, Bias::Left)
 2617                        .to_point(&display_map);
 2618                    let line_start = display_map.prev_line_boundary(position).0;
 2619                    let next_line_start = buffer.clip_point(
 2620                        display_map.next_line_boundary(position).0 + Point::new(1, 0),
 2621                        Bias::Left,
 2622                    );
 2623
 2624                    if line_start < original_range.start {
 2625                        head = line_start
 2626                    } else {
 2627                        head = next_line_start
 2628                    }
 2629
 2630                    if head <= original_range.start {
 2631                        tail = original_range.end;
 2632                    } else {
 2633                        tail = original_range.start;
 2634                    }
 2635                }
 2636                SelectMode::All => {
 2637                    return;
 2638                }
 2639            };
 2640
 2641            if head < tail {
 2642                pending.start = buffer.anchor_before(head);
 2643                pending.end = buffer.anchor_before(tail);
 2644                pending.reversed = true;
 2645            } else {
 2646                pending.start = buffer.anchor_before(tail);
 2647                pending.end = buffer.anchor_before(head);
 2648                pending.reversed = false;
 2649            }
 2650
 2651            self.change_selections(None, window, cx, |s| {
 2652                s.set_pending(pending, mode);
 2653            });
 2654        } else {
 2655            log::error!("update_selection dispatched with no pending selection");
 2656            return;
 2657        }
 2658
 2659        self.apply_scroll_delta(scroll_delta, window, cx);
 2660        cx.notify();
 2661    }
 2662
 2663    fn end_selection(&mut self, window: &mut Window, cx: &mut Context<Self>) {
 2664        self.columnar_selection_tail.take();
 2665        if self.selections.pending_anchor().is_some() {
 2666            let selections = self.selections.all::<usize>(cx);
 2667            self.change_selections(None, window, cx, |s| {
 2668                s.select(selections);
 2669                s.clear_pending();
 2670            });
 2671        }
 2672    }
 2673
 2674    fn select_columns(
 2675        &mut self,
 2676        tail: DisplayPoint,
 2677        head: DisplayPoint,
 2678        goal_column: u32,
 2679        display_map: &DisplaySnapshot,
 2680        window: &mut Window,
 2681        cx: &mut Context<Self>,
 2682    ) {
 2683        let start_row = cmp::min(tail.row(), head.row());
 2684        let end_row = cmp::max(tail.row(), head.row());
 2685        let start_column = cmp::min(tail.column(), goal_column);
 2686        let end_column = cmp::max(tail.column(), goal_column);
 2687        let reversed = start_column < tail.column();
 2688
 2689        let selection_ranges = (start_row.0..=end_row.0)
 2690            .map(DisplayRow)
 2691            .filter_map(|row| {
 2692                if start_column <= display_map.line_len(row) && !display_map.is_block_line(row) {
 2693                    let start = display_map
 2694                        .clip_point(DisplayPoint::new(row, start_column), Bias::Left)
 2695                        .to_point(display_map);
 2696                    let end = display_map
 2697                        .clip_point(DisplayPoint::new(row, end_column), Bias::Right)
 2698                        .to_point(display_map);
 2699                    if reversed {
 2700                        Some(end..start)
 2701                    } else {
 2702                        Some(start..end)
 2703                    }
 2704                } else {
 2705                    None
 2706                }
 2707            })
 2708            .collect::<Vec<_>>();
 2709
 2710        self.change_selections(None, window, cx, |s| {
 2711            s.select_ranges(selection_ranges);
 2712        });
 2713        cx.notify();
 2714    }
 2715
 2716    pub fn has_pending_nonempty_selection(&self) -> bool {
 2717        let pending_nonempty_selection = match self.selections.pending_anchor() {
 2718            Some(Selection { start, end, .. }) => start != end,
 2719            None => false,
 2720        };
 2721
 2722        pending_nonempty_selection
 2723            || (self.columnar_selection_tail.is_some() && self.selections.disjoint.len() > 1)
 2724    }
 2725
 2726    pub fn has_pending_selection(&self) -> bool {
 2727        self.selections.pending_anchor().is_some() || self.columnar_selection_tail.is_some()
 2728    }
 2729
 2730    pub fn cancel(&mut self, _: &Cancel, window: &mut Window, cx: &mut Context<Self>) {
 2731        self.selection_mark_mode = false;
 2732
 2733        if self.clear_expanded_diff_hunks(cx) {
 2734            cx.notify();
 2735            return;
 2736        }
 2737        if self.dismiss_menus_and_popups(true, window, cx) {
 2738            return;
 2739        }
 2740
 2741        if self.mode == EditorMode::Full
 2742            && self.change_selections(Some(Autoscroll::fit()), window, cx, |s| s.try_cancel())
 2743        {
 2744            return;
 2745        }
 2746
 2747        cx.propagate();
 2748    }
 2749
 2750    pub fn dismiss_menus_and_popups(
 2751        &mut self,
 2752        is_user_requested: bool,
 2753        window: &mut Window,
 2754        cx: &mut Context<Self>,
 2755    ) -> bool {
 2756        if self.take_rename(false, window, cx).is_some() {
 2757            return true;
 2758        }
 2759
 2760        if hide_hover(self, cx) {
 2761            return true;
 2762        }
 2763
 2764        if self.hide_signature_help(cx, SignatureHelpHiddenBy::Escape) {
 2765            return true;
 2766        }
 2767
 2768        if self.hide_context_menu(window, cx).is_some() {
 2769            return true;
 2770        }
 2771
 2772        if self.mouse_context_menu.take().is_some() {
 2773            return true;
 2774        }
 2775
 2776        if is_user_requested && self.discard_inline_completion(true, cx) {
 2777            return true;
 2778        }
 2779
 2780        if self.snippet_stack.pop().is_some() {
 2781            return true;
 2782        }
 2783
 2784        if self.mode == EditorMode::Full && self.active_diagnostics.is_some() {
 2785            self.dismiss_diagnostics(cx);
 2786            return true;
 2787        }
 2788
 2789        false
 2790    }
 2791
 2792    fn linked_editing_ranges_for(
 2793        &self,
 2794        selection: Range<text::Anchor>,
 2795        cx: &App,
 2796    ) -> Option<HashMap<Entity<Buffer>, Vec<Range<text::Anchor>>>> {
 2797        if self.linked_edit_ranges.is_empty() {
 2798            return None;
 2799        }
 2800        let ((base_range, linked_ranges), buffer_snapshot, buffer) =
 2801            selection.end.buffer_id.and_then(|end_buffer_id| {
 2802                if selection.start.buffer_id != Some(end_buffer_id) {
 2803                    return None;
 2804                }
 2805                let buffer = self.buffer.read(cx).buffer(end_buffer_id)?;
 2806                let snapshot = buffer.read(cx).snapshot();
 2807                self.linked_edit_ranges
 2808                    .get(end_buffer_id, selection.start..selection.end, &snapshot)
 2809                    .map(|ranges| (ranges, snapshot, buffer))
 2810            })?;
 2811        use text::ToOffset as TO;
 2812        // find offset from the start of current range to current cursor position
 2813        let start_byte_offset = TO::to_offset(&base_range.start, &buffer_snapshot);
 2814
 2815        let start_offset = TO::to_offset(&selection.start, &buffer_snapshot);
 2816        let start_difference = start_offset - start_byte_offset;
 2817        let end_offset = TO::to_offset(&selection.end, &buffer_snapshot);
 2818        let end_difference = end_offset - start_byte_offset;
 2819        // Current range has associated linked ranges.
 2820        let mut linked_edits = HashMap::<_, Vec<_>>::default();
 2821        for range in linked_ranges.iter() {
 2822            let start_offset = TO::to_offset(&range.start, &buffer_snapshot);
 2823            let end_offset = start_offset + end_difference;
 2824            let start_offset = start_offset + start_difference;
 2825            if start_offset > buffer_snapshot.len() || end_offset > buffer_snapshot.len() {
 2826                continue;
 2827            }
 2828            if self.selections.disjoint_anchor_ranges().any(|s| {
 2829                if s.start.buffer_id != selection.start.buffer_id
 2830                    || s.end.buffer_id != selection.end.buffer_id
 2831                {
 2832                    return false;
 2833                }
 2834                TO::to_offset(&s.start.text_anchor, &buffer_snapshot) <= end_offset
 2835                    && TO::to_offset(&s.end.text_anchor, &buffer_snapshot) >= start_offset
 2836            }) {
 2837                continue;
 2838            }
 2839            let start = buffer_snapshot.anchor_after(start_offset);
 2840            let end = buffer_snapshot.anchor_after(end_offset);
 2841            linked_edits
 2842                .entry(buffer.clone())
 2843                .or_default()
 2844                .push(start..end);
 2845        }
 2846        Some(linked_edits)
 2847    }
 2848
 2849    pub fn handle_input(&mut self, text: &str, window: &mut Window, cx: &mut Context<Self>) {
 2850        let text: Arc<str> = text.into();
 2851
 2852        if self.read_only(cx) {
 2853            return;
 2854        }
 2855
 2856        let selections = self.selections.all_adjusted(cx);
 2857        let mut bracket_inserted = false;
 2858        let mut edits = Vec::new();
 2859        let mut linked_edits = HashMap::<_, Vec<_>>::default();
 2860        let mut new_selections = Vec::with_capacity(selections.len());
 2861        let mut new_autoclose_regions = Vec::new();
 2862        let snapshot = self.buffer.read(cx).read(cx);
 2863
 2864        for (selection, autoclose_region) in
 2865            self.selections_with_autoclose_regions(selections, &snapshot)
 2866        {
 2867            if let Some(scope) = snapshot.language_scope_at(selection.head()) {
 2868                // Determine if the inserted text matches the opening or closing
 2869                // bracket of any of this language's bracket pairs.
 2870                let mut bracket_pair = None;
 2871                let mut is_bracket_pair_start = false;
 2872                let mut is_bracket_pair_end = false;
 2873                if !text.is_empty() {
 2874                    // `text` can be empty when a user is using IME (e.g. Chinese Wubi Simplified)
 2875                    //  and they are removing the character that triggered IME popup.
 2876                    for (pair, enabled) in scope.brackets() {
 2877                        if !pair.close && !pair.surround {
 2878                            continue;
 2879                        }
 2880
 2881                        if enabled && pair.start.ends_with(text.as_ref()) {
 2882                            let prefix_len = pair.start.len() - text.len();
 2883                            let preceding_text_matches_prefix = prefix_len == 0
 2884                                || (selection.start.column >= (prefix_len as u32)
 2885                                    && snapshot.contains_str_at(
 2886                                        Point::new(
 2887                                            selection.start.row,
 2888                                            selection.start.column - (prefix_len as u32),
 2889                                        ),
 2890                                        &pair.start[..prefix_len],
 2891                                    ));
 2892                            if preceding_text_matches_prefix {
 2893                                bracket_pair = Some(pair.clone());
 2894                                is_bracket_pair_start = true;
 2895                                break;
 2896                            }
 2897                        }
 2898                        if pair.end.as_str() == text.as_ref() {
 2899                            bracket_pair = Some(pair.clone());
 2900                            is_bracket_pair_end = true;
 2901                            break;
 2902                        }
 2903                    }
 2904                }
 2905
 2906                if let Some(bracket_pair) = bracket_pair {
 2907                    let snapshot_settings = snapshot.language_settings_at(selection.start, cx);
 2908                    let autoclose = self.use_autoclose && snapshot_settings.use_autoclose;
 2909                    let auto_surround =
 2910                        self.use_auto_surround && snapshot_settings.use_auto_surround;
 2911                    if selection.is_empty() {
 2912                        if is_bracket_pair_start {
 2913                            // If the inserted text is a suffix of an opening bracket and the
 2914                            // selection is preceded by the rest of the opening bracket, then
 2915                            // insert the closing bracket.
 2916                            let following_text_allows_autoclose = snapshot
 2917                                .chars_at(selection.start)
 2918                                .next()
 2919                                .map_or(true, |c| scope.should_autoclose_before(c));
 2920
 2921                            let is_closing_quote = if bracket_pair.end == bracket_pair.start
 2922                                && bracket_pair.start.len() == 1
 2923                            {
 2924                                let target = bracket_pair.start.chars().next().unwrap();
 2925                                let current_line_count = snapshot
 2926                                    .reversed_chars_at(selection.start)
 2927                                    .take_while(|&c| c != '\n')
 2928                                    .filter(|&c| c == target)
 2929                                    .count();
 2930                                current_line_count % 2 == 1
 2931                            } else {
 2932                                false
 2933                            };
 2934
 2935                            if autoclose
 2936                                && bracket_pair.close
 2937                                && following_text_allows_autoclose
 2938                                && !is_closing_quote
 2939                            {
 2940                                let anchor = snapshot.anchor_before(selection.end);
 2941                                new_selections.push((selection.map(|_| anchor), text.len()));
 2942                                new_autoclose_regions.push((
 2943                                    anchor,
 2944                                    text.len(),
 2945                                    selection.id,
 2946                                    bracket_pair.clone(),
 2947                                ));
 2948                                edits.push((
 2949                                    selection.range(),
 2950                                    format!("{}{}", text, bracket_pair.end).into(),
 2951                                ));
 2952                                bracket_inserted = true;
 2953                                continue;
 2954                            }
 2955                        }
 2956
 2957                        if let Some(region) = autoclose_region {
 2958                            // If the selection is followed by an auto-inserted closing bracket,
 2959                            // then don't insert that closing bracket again; just move the selection
 2960                            // past the closing bracket.
 2961                            let should_skip = selection.end == region.range.end.to_point(&snapshot)
 2962                                && text.as_ref() == region.pair.end.as_str();
 2963                            if should_skip {
 2964                                let anchor = snapshot.anchor_after(selection.end);
 2965                                new_selections
 2966                                    .push((selection.map(|_| anchor), region.pair.end.len()));
 2967                                continue;
 2968                            }
 2969                        }
 2970
 2971                        let always_treat_brackets_as_autoclosed = snapshot
 2972                            .language_settings_at(selection.start, cx)
 2973                            .always_treat_brackets_as_autoclosed;
 2974                        if always_treat_brackets_as_autoclosed
 2975                            && is_bracket_pair_end
 2976                            && snapshot.contains_str_at(selection.end, text.as_ref())
 2977                        {
 2978                            // Otherwise, when `always_treat_brackets_as_autoclosed` is set to `true
 2979                            // and the inserted text is a closing bracket and the selection is followed
 2980                            // by the closing bracket then move the selection past the closing bracket.
 2981                            let anchor = snapshot.anchor_after(selection.end);
 2982                            new_selections.push((selection.map(|_| anchor), text.len()));
 2983                            continue;
 2984                        }
 2985                    }
 2986                    // If an opening bracket is 1 character long and is typed while
 2987                    // text is selected, then surround that text with the bracket pair.
 2988                    else if auto_surround
 2989                        && bracket_pair.surround
 2990                        && is_bracket_pair_start
 2991                        && bracket_pair.start.chars().count() == 1
 2992                    {
 2993                        edits.push((selection.start..selection.start, text.clone()));
 2994                        edits.push((
 2995                            selection.end..selection.end,
 2996                            bracket_pair.end.as_str().into(),
 2997                        ));
 2998                        bracket_inserted = true;
 2999                        new_selections.push((
 3000                            Selection {
 3001                                id: selection.id,
 3002                                start: snapshot.anchor_after(selection.start),
 3003                                end: snapshot.anchor_before(selection.end),
 3004                                reversed: selection.reversed,
 3005                                goal: selection.goal,
 3006                            },
 3007                            0,
 3008                        ));
 3009                        continue;
 3010                    }
 3011                }
 3012            }
 3013
 3014            if self.auto_replace_emoji_shortcode
 3015                && selection.is_empty()
 3016                && text.as_ref().ends_with(':')
 3017            {
 3018                if let Some(possible_emoji_short_code) =
 3019                    Self::find_possible_emoji_shortcode_at_position(&snapshot, selection.start)
 3020                {
 3021                    if !possible_emoji_short_code.is_empty() {
 3022                        if let Some(emoji) = emojis::get_by_shortcode(&possible_emoji_short_code) {
 3023                            let emoji_shortcode_start = Point::new(
 3024                                selection.start.row,
 3025                                selection.start.column - possible_emoji_short_code.len() as u32 - 1,
 3026                            );
 3027
 3028                            // Remove shortcode from buffer
 3029                            edits.push((
 3030                                emoji_shortcode_start..selection.start,
 3031                                "".to_string().into(),
 3032                            ));
 3033                            new_selections.push((
 3034                                Selection {
 3035                                    id: selection.id,
 3036                                    start: snapshot.anchor_after(emoji_shortcode_start),
 3037                                    end: snapshot.anchor_before(selection.start),
 3038                                    reversed: selection.reversed,
 3039                                    goal: selection.goal,
 3040                                },
 3041                                0,
 3042                            ));
 3043
 3044                            // Insert emoji
 3045                            let selection_start_anchor = snapshot.anchor_after(selection.start);
 3046                            new_selections.push((selection.map(|_| selection_start_anchor), 0));
 3047                            edits.push((selection.start..selection.end, emoji.to_string().into()));
 3048
 3049                            continue;
 3050                        }
 3051                    }
 3052                }
 3053            }
 3054
 3055            // If not handling any auto-close operation, then just replace the selected
 3056            // text with the given input and move the selection to the end of the
 3057            // newly inserted text.
 3058            let anchor = snapshot.anchor_after(selection.end);
 3059            if !self.linked_edit_ranges.is_empty() {
 3060                let start_anchor = snapshot.anchor_before(selection.start);
 3061
 3062                let is_word_char = text.chars().next().map_or(true, |char| {
 3063                    let classifier = snapshot.char_classifier_at(start_anchor.to_offset(&snapshot));
 3064                    classifier.is_word(char)
 3065                });
 3066
 3067                if is_word_char {
 3068                    if let Some(ranges) = self
 3069                        .linked_editing_ranges_for(start_anchor.text_anchor..anchor.text_anchor, cx)
 3070                    {
 3071                        for (buffer, edits) in ranges {
 3072                            linked_edits
 3073                                .entry(buffer.clone())
 3074                                .or_default()
 3075                                .extend(edits.into_iter().map(|range| (range, text.clone())));
 3076                        }
 3077                    }
 3078                }
 3079            }
 3080
 3081            new_selections.push((selection.map(|_| anchor), 0));
 3082            edits.push((selection.start..selection.end, text.clone()));
 3083        }
 3084
 3085        drop(snapshot);
 3086
 3087        self.transact(window, cx, |this, window, cx| {
 3088            let initial_buffer_versions =
 3089                jsx_tag_auto_close::construct_initial_buffer_versions_map(this, &edits, cx);
 3090
 3091            this.buffer.update(cx, |buffer, cx| {
 3092                buffer.edit(edits, this.autoindent_mode.clone(), cx);
 3093            });
 3094            for (buffer, edits) in linked_edits {
 3095                buffer.update(cx, |buffer, cx| {
 3096                    let snapshot = buffer.snapshot();
 3097                    let edits = edits
 3098                        .into_iter()
 3099                        .map(|(range, text)| {
 3100                            use text::ToPoint as TP;
 3101                            let end_point = TP::to_point(&range.end, &snapshot);
 3102                            let start_point = TP::to_point(&range.start, &snapshot);
 3103                            (start_point..end_point, text)
 3104                        })
 3105                        .sorted_by_key(|(range, _)| range.start)
 3106                        .collect::<Vec<_>>();
 3107                    buffer.edit(edits, None, cx);
 3108                })
 3109            }
 3110            let new_anchor_selections = new_selections.iter().map(|e| &e.0);
 3111            let new_selection_deltas = new_selections.iter().map(|e| e.1);
 3112            let map = this.display_map.update(cx, |map, cx| map.snapshot(cx));
 3113            let new_selections = resolve_selections::<usize, _>(new_anchor_selections, &map)
 3114                .zip(new_selection_deltas)
 3115                .map(|(selection, delta)| Selection {
 3116                    id: selection.id,
 3117                    start: selection.start + delta,
 3118                    end: selection.end + delta,
 3119                    reversed: selection.reversed,
 3120                    goal: SelectionGoal::None,
 3121                })
 3122                .collect::<Vec<_>>();
 3123
 3124            let mut i = 0;
 3125            for (position, delta, selection_id, pair) in new_autoclose_regions {
 3126                let position = position.to_offset(&map.buffer_snapshot) + delta;
 3127                let start = map.buffer_snapshot.anchor_before(position);
 3128                let end = map.buffer_snapshot.anchor_after(position);
 3129                while let Some(existing_state) = this.autoclose_regions.get(i) {
 3130                    match existing_state.range.start.cmp(&start, &map.buffer_snapshot) {
 3131                        Ordering::Less => i += 1,
 3132                        Ordering::Greater => break,
 3133                        Ordering::Equal => {
 3134                            match end.cmp(&existing_state.range.end, &map.buffer_snapshot) {
 3135                                Ordering::Less => i += 1,
 3136                                Ordering::Equal => break,
 3137                                Ordering::Greater => break,
 3138                            }
 3139                        }
 3140                    }
 3141                }
 3142                this.autoclose_regions.insert(
 3143                    i,
 3144                    AutocloseRegion {
 3145                        selection_id,
 3146                        range: start..end,
 3147                        pair,
 3148                    },
 3149                );
 3150            }
 3151
 3152            let had_active_inline_completion = this.has_active_inline_completion();
 3153            this.change_selections_inner(Some(Autoscroll::fit()), false, window, cx, |s| {
 3154                s.select(new_selections)
 3155            });
 3156
 3157            if !bracket_inserted {
 3158                if let Some(on_type_format_task) =
 3159                    this.trigger_on_type_formatting(text.to_string(), window, cx)
 3160                {
 3161                    on_type_format_task.detach_and_log_err(cx);
 3162                }
 3163            }
 3164
 3165            let editor_settings = EditorSettings::get_global(cx);
 3166            if bracket_inserted
 3167                && (editor_settings.auto_signature_help
 3168                    || editor_settings.show_signature_help_after_edits)
 3169            {
 3170                this.show_signature_help(&ShowSignatureHelp, window, cx);
 3171            }
 3172
 3173            let trigger_in_words =
 3174                this.show_edit_predictions_in_menu() || !had_active_inline_completion;
 3175            if this.hard_wrap.is_some() {
 3176                let latest: Range<Point> = this.selections.newest(cx).range();
 3177                if latest.is_empty()
 3178                    && this
 3179                        .buffer()
 3180                        .read(cx)
 3181                        .snapshot(cx)
 3182                        .line_len(MultiBufferRow(latest.start.row))
 3183                        == latest.start.column
 3184                {
 3185                    this.rewrap_impl(true, cx)
 3186                }
 3187            }
 3188            this.trigger_completion_on_input(&text, trigger_in_words, window, cx);
 3189            linked_editing_ranges::refresh_linked_ranges(this, window, cx);
 3190            this.refresh_inline_completion(true, false, window, cx);
 3191            jsx_tag_auto_close::handle_from(this, initial_buffer_versions, window, cx);
 3192        });
 3193    }
 3194
 3195    fn find_possible_emoji_shortcode_at_position(
 3196        snapshot: &MultiBufferSnapshot,
 3197        position: Point,
 3198    ) -> Option<String> {
 3199        let mut chars = Vec::new();
 3200        let mut found_colon = false;
 3201        for char in snapshot.reversed_chars_at(position).take(100) {
 3202            // Found a possible emoji shortcode in the middle of the buffer
 3203            if found_colon {
 3204                if char.is_whitespace() {
 3205                    chars.reverse();
 3206                    return Some(chars.iter().collect());
 3207                }
 3208                // If the previous character is not a whitespace, we are in the middle of a word
 3209                // and we only want to complete the shortcode if the word is made up of other emojis
 3210                let mut containing_word = String::new();
 3211                for ch in snapshot
 3212                    .reversed_chars_at(position)
 3213                    .skip(chars.len() + 1)
 3214                    .take(100)
 3215                {
 3216                    if ch.is_whitespace() {
 3217                        break;
 3218                    }
 3219                    containing_word.push(ch);
 3220                }
 3221                let containing_word = containing_word.chars().rev().collect::<String>();
 3222                if util::word_consists_of_emojis(containing_word.as_str()) {
 3223                    chars.reverse();
 3224                    return Some(chars.iter().collect());
 3225                }
 3226            }
 3227
 3228            if char.is_whitespace() || !char.is_ascii() {
 3229                return None;
 3230            }
 3231            if char == ':' {
 3232                found_colon = true;
 3233            } else {
 3234                chars.push(char);
 3235            }
 3236        }
 3237        // Found a possible emoji shortcode at the beginning of the buffer
 3238        chars.reverse();
 3239        Some(chars.iter().collect())
 3240    }
 3241
 3242    pub fn newline(&mut self, _: &Newline, window: &mut Window, cx: &mut Context<Self>) {
 3243        self.transact(window, cx, |this, window, cx| {
 3244            let (edits, selection_fixup_info): (Vec<_>, Vec<_>) = {
 3245                let selections = this.selections.all::<usize>(cx);
 3246                let multi_buffer = this.buffer.read(cx);
 3247                let buffer = multi_buffer.snapshot(cx);
 3248                selections
 3249                    .iter()
 3250                    .map(|selection| {
 3251                        let start_point = selection.start.to_point(&buffer);
 3252                        let mut indent =
 3253                            buffer.indent_size_for_line(MultiBufferRow(start_point.row));
 3254                        indent.len = cmp::min(indent.len, start_point.column);
 3255                        let start = selection.start;
 3256                        let end = selection.end;
 3257                        let selection_is_empty = start == end;
 3258                        let language_scope = buffer.language_scope_at(start);
 3259                        let (comment_delimiter, insert_extra_newline) = if let Some(language) =
 3260                            &language_scope
 3261                        {
 3262                            let insert_extra_newline =
 3263                                insert_extra_newline_brackets(&buffer, start..end, language)
 3264                                    || insert_extra_newline_tree_sitter(&buffer, start..end);
 3265
 3266                            // Comment extension on newline is allowed only for cursor selections
 3267                            let comment_delimiter = maybe!({
 3268                                if !selection_is_empty {
 3269                                    return None;
 3270                                }
 3271
 3272                                if !multi_buffer.language_settings(cx).extend_comment_on_newline {
 3273                                    return None;
 3274                                }
 3275
 3276                                let delimiters = language.line_comment_prefixes();
 3277                                let max_len_of_delimiter =
 3278                                    delimiters.iter().map(|delimiter| delimiter.len()).max()?;
 3279                                let (snapshot, range) =
 3280                                    buffer.buffer_line_for_row(MultiBufferRow(start_point.row))?;
 3281
 3282                                let mut index_of_first_non_whitespace = 0;
 3283                                let comment_candidate = snapshot
 3284                                    .chars_for_range(range)
 3285                                    .skip_while(|c| {
 3286                                        let should_skip = c.is_whitespace();
 3287                                        if should_skip {
 3288                                            index_of_first_non_whitespace += 1;
 3289                                        }
 3290                                        should_skip
 3291                                    })
 3292                                    .take(max_len_of_delimiter)
 3293                                    .collect::<String>();
 3294                                let comment_prefix = delimiters.iter().find(|comment_prefix| {
 3295                                    comment_candidate.starts_with(comment_prefix.as_ref())
 3296                                })?;
 3297                                let cursor_is_placed_after_comment_marker =
 3298                                    index_of_first_non_whitespace + comment_prefix.len()
 3299                                        <= start_point.column as usize;
 3300                                if cursor_is_placed_after_comment_marker {
 3301                                    Some(comment_prefix.clone())
 3302                                } else {
 3303                                    None
 3304                                }
 3305                            });
 3306                            (comment_delimiter, insert_extra_newline)
 3307                        } else {
 3308                            (None, false)
 3309                        };
 3310
 3311                        let capacity_for_delimiter = comment_delimiter
 3312                            .as_deref()
 3313                            .map(str::len)
 3314                            .unwrap_or_default();
 3315                        let mut new_text =
 3316                            String::with_capacity(1 + capacity_for_delimiter + indent.len as usize);
 3317                        new_text.push('\n');
 3318                        new_text.extend(indent.chars());
 3319                        if let Some(delimiter) = &comment_delimiter {
 3320                            new_text.push_str(delimiter);
 3321                        }
 3322                        if insert_extra_newline {
 3323                            new_text = new_text.repeat(2);
 3324                        }
 3325
 3326                        let anchor = buffer.anchor_after(end);
 3327                        let new_selection = selection.map(|_| anchor);
 3328                        (
 3329                            (start..end, new_text),
 3330                            (insert_extra_newline, new_selection),
 3331                        )
 3332                    })
 3333                    .unzip()
 3334            };
 3335
 3336            this.edit_with_autoindent(edits, cx);
 3337            let buffer = this.buffer.read(cx).snapshot(cx);
 3338            let new_selections = selection_fixup_info
 3339                .into_iter()
 3340                .map(|(extra_newline_inserted, new_selection)| {
 3341                    let mut cursor = new_selection.end.to_point(&buffer);
 3342                    if extra_newline_inserted {
 3343                        cursor.row -= 1;
 3344                        cursor.column = buffer.line_len(MultiBufferRow(cursor.row));
 3345                    }
 3346                    new_selection.map(|_| cursor)
 3347                })
 3348                .collect();
 3349
 3350            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 3351                s.select(new_selections)
 3352            });
 3353            this.refresh_inline_completion(true, false, window, cx);
 3354        });
 3355    }
 3356
 3357    pub fn newline_above(&mut self, _: &NewlineAbove, window: &mut Window, cx: &mut Context<Self>) {
 3358        let buffer = self.buffer.read(cx);
 3359        let snapshot = buffer.snapshot(cx);
 3360
 3361        let mut edits = Vec::new();
 3362        let mut rows = Vec::new();
 3363
 3364        for (rows_inserted, selection) in self.selections.all_adjusted(cx).into_iter().enumerate() {
 3365            let cursor = selection.head();
 3366            let row = cursor.row;
 3367
 3368            let start_of_line = snapshot.clip_point(Point::new(row, 0), Bias::Left);
 3369
 3370            let newline = "\n".to_string();
 3371            edits.push((start_of_line..start_of_line, newline));
 3372
 3373            rows.push(row + rows_inserted as u32);
 3374        }
 3375
 3376        self.transact(window, cx, |editor, window, cx| {
 3377            editor.edit(edits, cx);
 3378
 3379            editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 3380                let mut index = 0;
 3381                s.move_cursors_with(|map, _, _| {
 3382                    let row = rows[index];
 3383                    index += 1;
 3384
 3385                    let point = Point::new(row, 0);
 3386                    let boundary = map.next_line_boundary(point).1;
 3387                    let clipped = map.clip_point(boundary, Bias::Left);
 3388
 3389                    (clipped, SelectionGoal::None)
 3390                });
 3391            });
 3392
 3393            let mut indent_edits = Vec::new();
 3394            let multibuffer_snapshot = editor.buffer.read(cx).snapshot(cx);
 3395            for row in rows {
 3396                let indents = multibuffer_snapshot.suggested_indents(row..row + 1, cx);
 3397                for (row, indent) in indents {
 3398                    if indent.len == 0 {
 3399                        continue;
 3400                    }
 3401
 3402                    let text = match indent.kind {
 3403                        IndentKind::Space => " ".repeat(indent.len as usize),
 3404                        IndentKind::Tab => "\t".repeat(indent.len as usize),
 3405                    };
 3406                    let point = Point::new(row.0, 0);
 3407                    indent_edits.push((point..point, text));
 3408                }
 3409            }
 3410            editor.edit(indent_edits, cx);
 3411        });
 3412    }
 3413
 3414    pub fn newline_below(&mut self, _: &NewlineBelow, window: &mut Window, cx: &mut Context<Self>) {
 3415        let buffer = self.buffer.read(cx);
 3416        let snapshot = buffer.snapshot(cx);
 3417
 3418        let mut edits = Vec::new();
 3419        let mut rows = Vec::new();
 3420        let mut rows_inserted = 0;
 3421
 3422        for selection in self.selections.all_adjusted(cx) {
 3423            let cursor = selection.head();
 3424            let row = cursor.row;
 3425
 3426            let point = Point::new(row + 1, 0);
 3427            let start_of_line = snapshot.clip_point(point, Bias::Left);
 3428
 3429            let newline = "\n".to_string();
 3430            edits.push((start_of_line..start_of_line, newline));
 3431
 3432            rows_inserted += 1;
 3433            rows.push(row + rows_inserted);
 3434        }
 3435
 3436        self.transact(window, cx, |editor, window, cx| {
 3437            editor.edit(edits, cx);
 3438
 3439            editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 3440                let mut index = 0;
 3441                s.move_cursors_with(|map, _, _| {
 3442                    let row = rows[index];
 3443                    index += 1;
 3444
 3445                    let point = Point::new(row, 0);
 3446                    let boundary = map.next_line_boundary(point).1;
 3447                    let clipped = map.clip_point(boundary, Bias::Left);
 3448
 3449                    (clipped, SelectionGoal::None)
 3450                });
 3451            });
 3452
 3453            let mut indent_edits = Vec::new();
 3454            let multibuffer_snapshot = editor.buffer.read(cx).snapshot(cx);
 3455            for row in rows {
 3456                let indents = multibuffer_snapshot.suggested_indents(row..row + 1, cx);
 3457                for (row, indent) in indents {
 3458                    if indent.len == 0 {
 3459                        continue;
 3460                    }
 3461
 3462                    let text = match indent.kind {
 3463                        IndentKind::Space => " ".repeat(indent.len as usize),
 3464                        IndentKind::Tab => "\t".repeat(indent.len as usize),
 3465                    };
 3466                    let point = Point::new(row.0, 0);
 3467                    indent_edits.push((point..point, text));
 3468                }
 3469            }
 3470            editor.edit(indent_edits, cx);
 3471        });
 3472    }
 3473
 3474    pub fn insert(&mut self, text: &str, window: &mut Window, cx: &mut Context<Self>) {
 3475        let autoindent = text.is_empty().not().then(|| AutoindentMode::Block {
 3476            original_indent_columns: Vec::new(),
 3477        });
 3478        self.insert_with_autoindent_mode(text, autoindent, window, cx);
 3479    }
 3480
 3481    fn insert_with_autoindent_mode(
 3482        &mut self,
 3483        text: &str,
 3484        autoindent_mode: Option<AutoindentMode>,
 3485        window: &mut Window,
 3486        cx: &mut Context<Self>,
 3487    ) {
 3488        if self.read_only(cx) {
 3489            return;
 3490        }
 3491
 3492        let text: Arc<str> = text.into();
 3493        self.transact(window, cx, |this, window, cx| {
 3494            let old_selections = this.selections.all_adjusted(cx);
 3495            let selection_anchors = this.buffer.update(cx, |buffer, cx| {
 3496                let anchors = {
 3497                    let snapshot = buffer.read(cx);
 3498                    old_selections
 3499                        .iter()
 3500                        .map(|s| {
 3501                            let anchor = snapshot.anchor_after(s.head());
 3502                            s.map(|_| anchor)
 3503                        })
 3504                        .collect::<Vec<_>>()
 3505                };
 3506                buffer.edit(
 3507                    old_selections
 3508                        .iter()
 3509                        .map(|s| (s.start..s.end, text.clone())),
 3510                    autoindent_mode,
 3511                    cx,
 3512                );
 3513                anchors
 3514            });
 3515
 3516            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 3517                s.select_anchors(selection_anchors);
 3518            });
 3519
 3520            cx.notify();
 3521        });
 3522    }
 3523
 3524    fn trigger_completion_on_input(
 3525        &mut self,
 3526        text: &str,
 3527        trigger_in_words: bool,
 3528        window: &mut Window,
 3529        cx: &mut Context<Self>,
 3530    ) {
 3531        if self.is_completion_trigger(text, trigger_in_words, cx) {
 3532            self.show_completions(
 3533                &ShowCompletions {
 3534                    trigger: Some(text.to_owned()).filter(|x| !x.is_empty()),
 3535                },
 3536                window,
 3537                cx,
 3538            );
 3539        } else {
 3540            self.hide_context_menu(window, cx);
 3541        }
 3542    }
 3543
 3544    fn is_completion_trigger(
 3545        &self,
 3546        text: &str,
 3547        trigger_in_words: bool,
 3548        cx: &mut Context<Self>,
 3549    ) -> bool {
 3550        let position = self.selections.newest_anchor().head();
 3551        let multibuffer = self.buffer.read(cx);
 3552        let Some(buffer) = position
 3553            .buffer_id
 3554            .and_then(|buffer_id| multibuffer.buffer(buffer_id).clone())
 3555        else {
 3556            return false;
 3557        };
 3558
 3559        if let Some(completion_provider) = &self.completion_provider {
 3560            completion_provider.is_completion_trigger(
 3561                &buffer,
 3562                position.text_anchor,
 3563                text,
 3564                trigger_in_words,
 3565                cx,
 3566            )
 3567        } else {
 3568            false
 3569        }
 3570    }
 3571
 3572    /// If any empty selections is touching the start of its innermost containing autoclose
 3573    /// region, expand it to select the brackets.
 3574    fn select_autoclose_pair(&mut self, window: &mut Window, cx: &mut Context<Self>) {
 3575        let selections = self.selections.all::<usize>(cx);
 3576        let buffer = self.buffer.read(cx).read(cx);
 3577        let new_selections = self
 3578            .selections_with_autoclose_regions(selections, &buffer)
 3579            .map(|(mut selection, region)| {
 3580                if !selection.is_empty() {
 3581                    return selection;
 3582                }
 3583
 3584                if let Some(region) = region {
 3585                    let mut range = region.range.to_offset(&buffer);
 3586                    if selection.start == range.start && range.start >= region.pair.start.len() {
 3587                        range.start -= region.pair.start.len();
 3588                        if buffer.contains_str_at(range.start, &region.pair.start)
 3589                            && buffer.contains_str_at(range.end, &region.pair.end)
 3590                        {
 3591                            range.end += region.pair.end.len();
 3592                            selection.start = range.start;
 3593                            selection.end = range.end;
 3594
 3595                            return selection;
 3596                        }
 3597                    }
 3598                }
 3599
 3600                let always_treat_brackets_as_autoclosed = buffer
 3601                    .language_settings_at(selection.start, cx)
 3602                    .always_treat_brackets_as_autoclosed;
 3603
 3604                if !always_treat_brackets_as_autoclosed {
 3605                    return selection;
 3606                }
 3607
 3608                if let Some(scope) = buffer.language_scope_at(selection.start) {
 3609                    for (pair, enabled) in scope.brackets() {
 3610                        if !enabled || !pair.close {
 3611                            continue;
 3612                        }
 3613
 3614                        if buffer.contains_str_at(selection.start, &pair.end) {
 3615                            let pair_start_len = pair.start.len();
 3616                            if buffer.contains_str_at(
 3617                                selection.start.saturating_sub(pair_start_len),
 3618                                &pair.start,
 3619                            ) {
 3620                                selection.start -= pair_start_len;
 3621                                selection.end += pair.end.len();
 3622
 3623                                return selection;
 3624                            }
 3625                        }
 3626                    }
 3627                }
 3628
 3629                selection
 3630            })
 3631            .collect();
 3632
 3633        drop(buffer);
 3634        self.change_selections(None, window, cx, |selections| {
 3635            selections.select(new_selections)
 3636        });
 3637    }
 3638
 3639    /// Iterate the given selections, and for each one, find the smallest surrounding
 3640    /// autoclose region. This uses the ordering of the selections and the autoclose
 3641    /// regions to avoid repeated comparisons.
 3642    fn selections_with_autoclose_regions<'a, D: ToOffset + Clone>(
 3643        &'a self,
 3644        selections: impl IntoIterator<Item = Selection<D>>,
 3645        buffer: &'a MultiBufferSnapshot,
 3646    ) -> impl Iterator<Item = (Selection<D>, Option<&'a AutocloseRegion>)> {
 3647        let mut i = 0;
 3648        let mut regions = self.autoclose_regions.as_slice();
 3649        selections.into_iter().map(move |selection| {
 3650            let range = selection.start.to_offset(buffer)..selection.end.to_offset(buffer);
 3651
 3652            let mut enclosing = None;
 3653            while let Some(pair_state) = regions.get(i) {
 3654                if pair_state.range.end.to_offset(buffer) < range.start {
 3655                    regions = &regions[i + 1..];
 3656                    i = 0;
 3657                } else if pair_state.range.start.to_offset(buffer) > range.end {
 3658                    break;
 3659                } else {
 3660                    if pair_state.selection_id == selection.id {
 3661                        enclosing = Some(pair_state);
 3662                    }
 3663                    i += 1;
 3664                }
 3665            }
 3666
 3667            (selection, enclosing)
 3668        })
 3669    }
 3670
 3671    /// Remove any autoclose regions that no longer contain their selection.
 3672    fn invalidate_autoclose_regions(
 3673        &mut self,
 3674        mut selections: &[Selection<Anchor>],
 3675        buffer: &MultiBufferSnapshot,
 3676    ) {
 3677        self.autoclose_regions.retain(|state| {
 3678            let mut i = 0;
 3679            while let Some(selection) = selections.get(i) {
 3680                if selection.end.cmp(&state.range.start, buffer).is_lt() {
 3681                    selections = &selections[1..];
 3682                    continue;
 3683                }
 3684                if selection.start.cmp(&state.range.end, buffer).is_gt() {
 3685                    break;
 3686                }
 3687                if selection.id == state.selection_id {
 3688                    return true;
 3689                } else {
 3690                    i += 1;
 3691                }
 3692            }
 3693            false
 3694        });
 3695    }
 3696
 3697    fn completion_query(buffer: &MultiBufferSnapshot, position: impl ToOffset) -> Option<String> {
 3698        let offset = position.to_offset(buffer);
 3699        let (word_range, kind) = buffer.surrounding_word(offset, true);
 3700        if offset > word_range.start && kind == Some(CharKind::Word) {
 3701            Some(
 3702                buffer
 3703                    .text_for_range(word_range.start..offset)
 3704                    .collect::<String>(),
 3705            )
 3706        } else {
 3707            None
 3708        }
 3709    }
 3710
 3711    pub fn toggle_inlay_hints(
 3712        &mut self,
 3713        _: &ToggleInlayHints,
 3714        _: &mut Window,
 3715        cx: &mut Context<Self>,
 3716    ) {
 3717        self.refresh_inlay_hints(
 3718            InlayHintRefreshReason::Toggle(!self.inlay_hints_enabled()),
 3719            cx,
 3720        );
 3721    }
 3722
 3723    pub fn inlay_hints_enabled(&self) -> bool {
 3724        self.inlay_hint_cache.enabled
 3725    }
 3726
 3727    fn refresh_inlay_hints(&mut self, reason: InlayHintRefreshReason, cx: &mut Context<Self>) {
 3728        if self.semantics_provider.is_none() || self.mode != EditorMode::Full {
 3729            return;
 3730        }
 3731
 3732        let reason_description = reason.description();
 3733        let ignore_debounce = matches!(
 3734            reason,
 3735            InlayHintRefreshReason::SettingsChange(_)
 3736                | InlayHintRefreshReason::Toggle(_)
 3737                | InlayHintRefreshReason::ExcerptsRemoved(_)
 3738                | InlayHintRefreshReason::ModifiersChanged(_)
 3739        );
 3740        let (invalidate_cache, required_languages) = match reason {
 3741            InlayHintRefreshReason::ModifiersChanged(enabled) => {
 3742                match self.inlay_hint_cache.modifiers_override(enabled) {
 3743                    Some(enabled) => {
 3744                        if enabled {
 3745                            (InvalidationStrategy::RefreshRequested, None)
 3746                        } else {
 3747                            self.splice_inlays(
 3748                                &self
 3749                                    .visible_inlay_hints(cx)
 3750                                    .iter()
 3751                                    .map(|inlay| inlay.id)
 3752                                    .collect::<Vec<InlayId>>(),
 3753                                Vec::new(),
 3754                                cx,
 3755                            );
 3756                            return;
 3757                        }
 3758                    }
 3759                    None => return,
 3760                }
 3761            }
 3762            InlayHintRefreshReason::Toggle(enabled) => {
 3763                if self.inlay_hint_cache.toggle(enabled) {
 3764                    if enabled {
 3765                        (InvalidationStrategy::RefreshRequested, None)
 3766                    } else {
 3767                        self.splice_inlays(
 3768                            &self
 3769                                .visible_inlay_hints(cx)
 3770                                .iter()
 3771                                .map(|inlay| inlay.id)
 3772                                .collect::<Vec<InlayId>>(),
 3773                            Vec::new(),
 3774                            cx,
 3775                        );
 3776                        return;
 3777                    }
 3778                } else {
 3779                    return;
 3780                }
 3781            }
 3782            InlayHintRefreshReason::SettingsChange(new_settings) => {
 3783                match self.inlay_hint_cache.update_settings(
 3784                    &self.buffer,
 3785                    new_settings,
 3786                    self.visible_inlay_hints(cx),
 3787                    cx,
 3788                ) {
 3789                    ControlFlow::Break(Some(InlaySplice {
 3790                        to_remove,
 3791                        to_insert,
 3792                    })) => {
 3793                        self.splice_inlays(&to_remove, to_insert, cx);
 3794                        return;
 3795                    }
 3796                    ControlFlow::Break(None) => return,
 3797                    ControlFlow::Continue(()) => (InvalidationStrategy::RefreshRequested, None),
 3798                }
 3799            }
 3800            InlayHintRefreshReason::ExcerptsRemoved(excerpts_removed) => {
 3801                if let Some(InlaySplice {
 3802                    to_remove,
 3803                    to_insert,
 3804                }) = self.inlay_hint_cache.remove_excerpts(excerpts_removed)
 3805                {
 3806                    self.splice_inlays(&to_remove, to_insert, cx);
 3807                }
 3808                return;
 3809            }
 3810            InlayHintRefreshReason::NewLinesShown => (InvalidationStrategy::None, None),
 3811            InlayHintRefreshReason::BufferEdited(buffer_languages) => {
 3812                (InvalidationStrategy::BufferEdited, Some(buffer_languages))
 3813            }
 3814            InlayHintRefreshReason::RefreshRequested => {
 3815                (InvalidationStrategy::RefreshRequested, None)
 3816            }
 3817        };
 3818
 3819        if let Some(InlaySplice {
 3820            to_remove,
 3821            to_insert,
 3822        }) = self.inlay_hint_cache.spawn_hint_refresh(
 3823            reason_description,
 3824            self.excerpts_for_inlay_hints_query(required_languages.as_ref(), cx),
 3825            invalidate_cache,
 3826            ignore_debounce,
 3827            cx,
 3828        ) {
 3829            self.splice_inlays(&to_remove, to_insert, cx);
 3830        }
 3831    }
 3832
 3833    fn visible_inlay_hints(&self, cx: &Context<Editor>) -> Vec<Inlay> {
 3834        self.display_map
 3835            .read(cx)
 3836            .current_inlays()
 3837            .filter(move |inlay| matches!(inlay.id, InlayId::Hint(_)))
 3838            .cloned()
 3839            .collect()
 3840    }
 3841
 3842    pub fn excerpts_for_inlay_hints_query(
 3843        &self,
 3844        restrict_to_languages: Option<&HashSet<Arc<Language>>>,
 3845        cx: &mut Context<Editor>,
 3846    ) -> HashMap<ExcerptId, (Entity<Buffer>, clock::Global, Range<usize>)> {
 3847        let Some(project) = self.project.as_ref() else {
 3848            return HashMap::default();
 3849        };
 3850        let project = project.read(cx);
 3851        let multi_buffer = self.buffer().read(cx);
 3852        let multi_buffer_snapshot = multi_buffer.snapshot(cx);
 3853        let multi_buffer_visible_start = self
 3854            .scroll_manager
 3855            .anchor()
 3856            .anchor
 3857            .to_point(&multi_buffer_snapshot);
 3858        let multi_buffer_visible_end = multi_buffer_snapshot.clip_point(
 3859            multi_buffer_visible_start
 3860                + Point::new(self.visible_line_count().unwrap_or(0.).ceil() as u32, 0),
 3861            Bias::Left,
 3862        );
 3863        let multi_buffer_visible_range = multi_buffer_visible_start..multi_buffer_visible_end;
 3864        multi_buffer_snapshot
 3865            .range_to_buffer_ranges(multi_buffer_visible_range)
 3866            .into_iter()
 3867            .filter(|(_, excerpt_visible_range, _)| !excerpt_visible_range.is_empty())
 3868            .filter_map(|(buffer, excerpt_visible_range, excerpt_id)| {
 3869                let buffer_file = project::File::from_dyn(buffer.file())?;
 3870                let buffer_worktree = project.worktree_for_id(buffer_file.worktree_id(cx), cx)?;
 3871                let worktree_entry = buffer_worktree
 3872                    .read(cx)
 3873                    .entry_for_id(buffer_file.project_entry_id(cx)?)?;
 3874                if worktree_entry.is_ignored {
 3875                    return None;
 3876                }
 3877
 3878                let language = buffer.language()?;
 3879                if let Some(restrict_to_languages) = restrict_to_languages {
 3880                    if !restrict_to_languages.contains(language) {
 3881                        return None;
 3882                    }
 3883                }
 3884                Some((
 3885                    excerpt_id,
 3886                    (
 3887                        multi_buffer.buffer(buffer.remote_id()).unwrap(),
 3888                        buffer.version().clone(),
 3889                        excerpt_visible_range,
 3890                    ),
 3891                ))
 3892            })
 3893            .collect()
 3894    }
 3895
 3896    pub fn text_layout_details(&self, window: &mut Window) -> TextLayoutDetails {
 3897        TextLayoutDetails {
 3898            text_system: window.text_system().clone(),
 3899            editor_style: self.style.clone().unwrap(),
 3900            rem_size: window.rem_size(),
 3901            scroll_anchor: self.scroll_manager.anchor(),
 3902            visible_rows: self.visible_line_count(),
 3903            vertical_scroll_margin: self.scroll_manager.vertical_scroll_margin,
 3904        }
 3905    }
 3906
 3907    pub fn splice_inlays(
 3908        &self,
 3909        to_remove: &[InlayId],
 3910        to_insert: Vec<Inlay>,
 3911        cx: &mut Context<Self>,
 3912    ) {
 3913        self.display_map.update(cx, |display_map, cx| {
 3914            display_map.splice_inlays(to_remove, to_insert, cx)
 3915        });
 3916        cx.notify();
 3917    }
 3918
 3919    fn trigger_on_type_formatting(
 3920        &self,
 3921        input: String,
 3922        window: &mut Window,
 3923        cx: &mut Context<Self>,
 3924    ) -> Option<Task<Result<()>>> {
 3925        if input.len() != 1 {
 3926            return None;
 3927        }
 3928
 3929        let project = self.project.as_ref()?;
 3930        let position = self.selections.newest_anchor().head();
 3931        let (buffer, buffer_position) = self
 3932            .buffer
 3933            .read(cx)
 3934            .text_anchor_for_position(position, cx)?;
 3935
 3936        let settings = language_settings::language_settings(
 3937            buffer
 3938                .read(cx)
 3939                .language_at(buffer_position)
 3940                .map(|l| l.name()),
 3941            buffer.read(cx).file(),
 3942            cx,
 3943        );
 3944        if !settings.use_on_type_format {
 3945            return None;
 3946        }
 3947
 3948        // OnTypeFormatting returns a list of edits, no need to pass them between Zed instances,
 3949        // hence we do LSP request & edit on host side only — add formats to host's history.
 3950        let push_to_lsp_host_history = true;
 3951        // If this is not the host, append its history with new edits.
 3952        let push_to_client_history = project.read(cx).is_via_collab();
 3953
 3954        let on_type_formatting = project.update(cx, |project, cx| {
 3955            project.on_type_format(
 3956                buffer.clone(),
 3957                buffer_position,
 3958                input,
 3959                push_to_lsp_host_history,
 3960                cx,
 3961            )
 3962        });
 3963        Some(cx.spawn_in(window, |editor, mut cx| async move {
 3964            if let Some(transaction) = on_type_formatting.await? {
 3965                if push_to_client_history {
 3966                    buffer
 3967                        .update(&mut cx, |buffer, _| {
 3968                            buffer.push_transaction(transaction, Instant::now());
 3969                        })
 3970                        .ok();
 3971                }
 3972                editor.update(&mut cx, |editor, cx| {
 3973                    editor.refresh_document_highlights(cx);
 3974                })?;
 3975            }
 3976            Ok(())
 3977        }))
 3978    }
 3979
 3980    pub fn show_completions(
 3981        &mut self,
 3982        options: &ShowCompletions,
 3983        window: &mut Window,
 3984        cx: &mut Context<Self>,
 3985    ) {
 3986        if self.pending_rename.is_some() {
 3987            return;
 3988        }
 3989
 3990        let Some(provider) = self.completion_provider.as_ref() else {
 3991            return;
 3992        };
 3993
 3994        if !self.snippet_stack.is_empty() && self.context_menu.borrow().as_ref().is_some() {
 3995            return;
 3996        }
 3997
 3998        let position = self.selections.newest_anchor().head();
 3999        if position.diff_base_anchor.is_some() {
 4000            return;
 4001        }
 4002        let (buffer, buffer_position) =
 4003            if let Some(output) = self.buffer.read(cx).text_anchor_for_position(position, cx) {
 4004                output
 4005            } else {
 4006                return;
 4007            };
 4008        let buffer_snapshot = buffer.read(cx).snapshot();
 4009        let show_completion_documentation = buffer_snapshot
 4010            .settings_at(buffer_position, cx)
 4011            .show_completion_documentation;
 4012
 4013        let query = Self::completion_query(&self.buffer.read(cx).read(cx), position);
 4014
 4015        let trigger_kind = match &options.trigger {
 4016            Some(trigger) if buffer.read(cx).completion_triggers().contains(trigger) => {
 4017                CompletionTriggerKind::TRIGGER_CHARACTER
 4018            }
 4019            _ => CompletionTriggerKind::INVOKED,
 4020        };
 4021        let completion_context = CompletionContext {
 4022            trigger_character: options.trigger.as_ref().and_then(|trigger| {
 4023                if trigger_kind == CompletionTriggerKind::TRIGGER_CHARACTER {
 4024                    Some(String::from(trigger))
 4025                } else {
 4026                    None
 4027                }
 4028            }),
 4029            trigger_kind,
 4030        };
 4031        let completions =
 4032            provider.completions(&buffer, buffer_position, completion_context, window, cx);
 4033        let (old_range, word_kind) = buffer_snapshot.surrounding_word(buffer_position);
 4034        let (old_range, word_to_exclude) = if word_kind == Some(CharKind::Word) {
 4035            let word_to_exclude = buffer_snapshot
 4036                .text_for_range(old_range.clone())
 4037                .collect::<String>();
 4038            (
 4039                buffer_snapshot.anchor_before(old_range.start)
 4040                    ..buffer_snapshot.anchor_after(old_range.end),
 4041                Some(word_to_exclude),
 4042            )
 4043        } else {
 4044            (buffer_position..buffer_position, None)
 4045        };
 4046
 4047        let completion_settings = language_settings(
 4048            buffer_snapshot
 4049                .language_at(buffer_position)
 4050                .map(|language| language.name()),
 4051            buffer_snapshot.file(),
 4052            cx,
 4053        )
 4054        .completions;
 4055
 4056        // The document can be large, so stay in reasonable bounds when searching for words,
 4057        // otherwise completion pop-up might be slow to appear.
 4058        const WORD_LOOKUP_ROWS: u32 = 5_000;
 4059        let buffer_row = text::ToPoint::to_point(&buffer_position, &buffer_snapshot).row;
 4060        let min_word_search = buffer_snapshot.clip_point(
 4061            Point::new(buffer_row.saturating_sub(WORD_LOOKUP_ROWS), 0),
 4062            Bias::Left,
 4063        );
 4064        let max_word_search = buffer_snapshot.clip_point(
 4065            Point::new(buffer_row + WORD_LOOKUP_ROWS, 0).min(buffer_snapshot.max_point()),
 4066            Bias::Right,
 4067        );
 4068        let word_search_range = buffer_snapshot.point_to_offset(min_word_search)
 4069            ..buffer_snapshot.point_to_offset(max_word_search);
 4070        let words = match completion_settings.words {
 4071            WordsCompletionMode::Disabled => Task::ready(HashMap::default()),
 4072            WordsCompletionMode::Enabled | WordsCompletionMode::Fallback => {
 4073                cx.background_spawn(async move {
 4074                    buffer_snapshot.words_in_range(None, word_search_range)
 4075                })
 4076            }
 4077        };
 4078        let sort_completions = provider.sort_completions();
 4079
 4080        let id = post_inc(&mut self.next_completion_id);
 4081        let task = cx.spawn_in(window, |editor, mut cx| {
 4082            async move {
 4083                editor.update(&mut cx, |this, _| {
 4084                    this.completion_tasks.retain(|(task_id, _)| *task_id >= id);
 4085                })?;
 4086                let mut completions = completions.await.log_err().unwrap_or_default();
 4087
 4088                match completion_settings.words {
 4089                    WordsCompletionMode::Enabled => {
 4090                        let mut words = words.await;
 4091                        if let Some(word_to_exclude) = &word_to_exclude {
 4092                            words.remove(word_to_exclude);
 4093                        }
 4094                        for lsp_completion in &completions {
 4095                            words.remove(&lsp_completion.new_text);
 4096                        }
 4097                        completions.extend(words.into_iter().map(|(word, word_range)| {
 4098                            Completion {
 4099                                old_range: old_range.clone(),
 4100                                new_text: word.clone(),
 4101                                label: CodeLabel::plain(word, None),
 4102                                documentation: None,
 4103                                source: CompletionSource::BufferWord {
 4104                                    word_range,
 4105                                    resolved: false,
 4106                                },
 4107                                confirm: None,
 4108                            }
 4109                        }));
 4110                    }
 4111                    WordsCompletionMode::Fallback => {
 4112                        if completions.is_empty() {
 4113                            completions.extend(
 4114                                words
 4115                                    .await
 4116                                    .into_iter()
 4117                                    .filter(|(word, _)| word_to_exclude.as_ref() != Some(word))
 4118                                    .map(|(word, word_range)| Completion {
 4119                                        old_range: old_range.clone(),
 4120                                        new_text: word.clone(),
 4121                                        label: CodeLabel::plain(word, None),
 4122                                        documentation: None,
 4123                                        source: CompletionSource::BufferWord {
 4124                                            word_range,
 4125                                            resolved: false,
 4126                                        },
 4127                                        confirm: None,
 4128                                    }),
 4129                            );
 4130                        }
 4131                    }
 4132                    WordsCompletionMode::Disabled => {}
 4133                }
 4134
 4135                let menu = if completions.is_empty() {
 4136                    None
 4137                } else {
 4138                    let mut menu = CompletionsMenu::new(
 4139                        id,
 4140                        sort_completions,
 4141                        show_completion_documentation,
 4142                        position,
 4143                        buffer.clone(),
 4144                        completions.into(),
 4145                    );
 4146
 4147                    menu.filter(query.as_deref(), cx.background_executor().clone())
 4148                        .await;
 4149
 4150                    menu.visible().then_some(menu)
 4151                };
 4152
 4153                editor.update_in(&mut cx, |editor, window, cx| {
 4154                    match editor.context_menu.borrow().as_ref() {
 4155                        None => {}
 4156                        Some(CodeContextMenu::Completions(prev_menu)) => {
 4157                            if prev_menu.id > id {
 4158                                return;
 4159                            }
 4160                        }
 4161                        _ => return,
 4162                    }
 4163
 4164                    if editor.focus_handle.is_focused(window) && menu.is_some() {
 4165                        let mut menu = menu.unwrap();
 4166                        menu.resolve_visible_completions(editor.completion_provider.as_deref(), cx);
 4167
 4168                        *editor.context_menu.borrow_mut() =
 4169                            Some(CodeContextMenu::Completions(menu));
 4170
 4171                        if editor.show_edit_predictions_in_menu() {
 4172                            editor.update_visible_inline_completion(window, cx);
 4173                        } else {
 4174                            editor.discard_inline_completion(false, cx);
 4175                        }
 4176
 4177                        cx.notify();
 4178                    } else if editor.completion_tasks.len() <= 1 {
 4179                        // If there are no more completion tasks and the last menu was
 4180                        // empty, we should hide it.
 4181                        let was_hidden = editor.hide_context_menu(window, cx).is_none();
 4182                        // If it was already hidden and we don't show inline
 4183                        // completions in the menu, we should also show the
 4184                        // inline-completion when available.
 4185                        if was_hidden && editor.show_edit_predictions_in_menu() {
 4186                            editor.update_visible_inline_completion(window, cx);
 4187                        }
 4188                    }
 4189                })?;
 4190
 4191                Ok::<_, anyhow::Error>(())
 4192            }
 4193            .log_err()
 4194        });
 4195
 4196        self.completion_tasks.push((id, task));
 4197    }
 4198
 4199    pub fn confirm_completion(
 4200        &mut self,
 4201        action: &ConfirmCompletion,
 4202        window: &mut Window,
 4203        cx: &mut Context<Self>,
 4204    ) -> Option<Task<Result<()>>> {
 4205        self.do_completion(action.item_ix, CompletionIntent::Complete, window, cx)
 4206    }
 4207
 4208    pub fn compose_completion(
 4209        &mut self,
 4210        action: &ComposeCompletion,
 4211        window: &mut Window,
 4212        cx: &mut Context<Self>,
 4213    ) -> Option<Task<Result<()>>> {
 4214        self.do_completion(action.item_ix, CompletionIntent::Compose, window, cx)
 4215    }
 4216
 4217    fn do_completion(
 4218        &mut self,
 4219        item_ix: Option<usize>,
 4220        intent: CompletionIntent,
 4221        window: &mut Window,
 4222        cx: &mut Context<Editor>,
 4223    ) -> Option<Task<std::result::Result<(), anyhow::Error>>> {
 4224        use language::ToOffset as _;
 4225
 4226        let completions_menu =
 4227            if let CodeContextMenu::Completions(menu) = self.hide_context_menu(window, cx)? {
 4228                menu
 4229            } else {
 4230                return None;
 4231            };
 4232
 4233        let entries = completions_menu.entries.borrow();
 4234        let mat = entries.get(item_ix.unwrap_or(completions_menu.selected_item))?;
 4235        if self.show_edit_predictions_in_menu() {
 4236            self.discard_inline_completion(true, cx);
 4237        }
 4238        let candidate_id = mat.candidate_id;
 4239        drop(entries);
 4240
 4241        let buffer_handle = completions_menu.buffer;
 4242        let completion = completions_menu
 4243            .completions
 4244            .borrow()
 4245            .get(candidate_id)?
 4246            .clone();
 4247        cx.stop_propagation();
 4248
 4249        let snippet;
 4250        let text;
 4251
 4252        if completion.is_snippet() {
 4253            snippet = Some(Snippet::parse(&completion.new_text).log_err()?);
 4254            text = snippet.as_ref().unwrap().text.clone();
 4255        } else {
 4256            snippet = None;
 4257            text = completion.new_text.clone();
 4258        };
 4259        let selections = self.selections.all::<usize>(cx);
 4260        let buffer = buffer_handle.read(cx);
 4261        let old_range = completion.old_range.to_offset(buffer);
 4262        let old_text = buffer.text_for_range(old_range.clone()).collect::<String>();
 4263
 4264        let newest_selection = self.selections.newest_anchor();
 4265        if newest_selection.start.buffer_id != Some(buffer_handle.read(cx).remote_id()) {
 4266            return None;
 4267        }
 4268
 4269        let lookbehind = newest_selection
 4270            .start
 4271            .text_anchor
 4272            .to_offset(buffer)
 4273            .saturating_sub(old_range.start);
 4274        let lookahead = old_range
 4275            .end
 4276            .saturating_sub(newest_selection.end.text_anchor.to_offset(buffer));
 4277        let mut common_prefix_len = old_text
 4278            .bytes()
 4279            .zip(text.bytes())
 4280            .take_while(|(a, b)| a == b)
 4281            .count();
 4282
 4283        let snapshot = self.buffer.read(cx).snapshot(cx);
 4284        let mut range_to_replace: Option<Range<isize>> = None;
 4285        let mut ranges = Vec::new();
 4286        let mut linked_edits = HashMap::<_, Vec<_>>::default();
 4287        for selection in &selections {
 4288            if snapshot.contains_str_at(selection.start.saturating_sub(lookbehind), &old_text) {
 4289                let start = selection.start.saturating_sub(lookbehind);
 4290                let end = selection.end + lookahead;
 4291                if selection.id == newest_selection.id {
 4292                    range_to_replace = Some(
 4293                        ((start + common_prefix_len) as isize - selection.start as isize)
 4294                            ..(end as isize - selection.start as isize),
 4295                    );
 4296                }
 4297                ranges.push(start + common_prefix_len..end);
 4298            } else {
 4299                common_prefix_len = 0;
 4300                ranges.clear();
 4301                ranges.extend(selections.iter().map(|s| {
 4302                    if s.id == newest_selection.id {
 4303                        range_to_replace = Some(
 4304                            old_range.start.to_offset_utf16(&snapshot).0 as isize
 4305                                - selection.start as isize
 4306                                ..old_range.end.to_offset_utf16(&snapshot).0 as isize
 4307                                    - selection.start as isize,
 4308                        );
 4309                        old_range.clone()
 4310                    } else {
 4311                        s.start..s.end
 4312                    }
 4313                }));
 4314                break;
 4315            }
 4316            if !self.linked_edit_ranges.is_empty() {
 4317                let start_anchor = snapshot.anchor_before(selection.head());
 4318                let end_anchor = snapshot.anchor_after(selection.tail());
 4319                if let Some(ranges) = self
 4320                    .linked_editing_ranges_for(start_anchor.text_anchor..end_anchor.text_anchor, cx)
 4321                {
 4322                    for (buffer, edits) in ranges {
 4323                        linked_edits.entry(buffer.clone()).or_default().extend(
 4324                            edits
 4325                                .into_iter()
 4326                                .map(|range| (range, text[common_prefix_len..].to_owned())),
 4327                        );
 4328                    }
 4329                }
 4330            }
 4331        }
 4332        let text = &text[common_prefix_len..];
 4333
 4334        cx.emit(EditorEvent::InputHandled {
 4335            utf16_range_to_replace: range_to_replace,
 4336            text: text.into(),
 4337        });
 4338
 4339        self.transact(window, cx, |this, window, cx| {
 4340            if let Some(mut snippet) = snippet {
 4341                snippet.text = text.to_string();
 4342                for tabstop in snippet
 4343                    .tabstops
 4344                    .iter_mut()
 4345                    .flat_map(|tabstop| tabstop.ranges.iter_mut())
 4346                {
 4347                    tabstop.start -= common_prefix_len as isize;
 4348                    tabstop.end -= common_prefix_len as isize;
 4349                }
 4350
 4351                this.insert_snippet(&ranges, snippet, window, cx).log_err();
 4352            } else {
 4353                this.buffer.update(cx, |buffer, cx| {
 4354                    buffer.edit(
 4355                        ranges.iter().map(|range| (range.clone(), text)),
 4356                        this.autoindent_mode.clone(),
 4357                        cx,
 4358                    );
 4359                });
 4360            }
 4361            for (buffer, edits) in linked_edits {
 4362                buffer.update(cx, |buffer, cx| {
 4363                    let snapshot = buffer.snapshot();
 4364                    let edits = edits
 4365                        .into_iter()
 4366                        .map(|(range, text)| {
 4367                            use text::ToPoint as TP;
 4368                            let end_point = TP::to_point(&range.end, &snapshot);
 4369                            let start_point = TP::to_point(&range.start, &snapshot);
 4370                            (start_point..end_point, text)
 4371                        })
 4372                        .sorted_by_key(|(range, _)| range.start)
 4373                        .collect::<Vec<_>>();
 4374                    buffer.edit(edits, None, cx);
 4375                })
 4376            }
 4377
 4378            this.refresh_inline_completion(true, false, window, cx);
 4379        });
 4380
 4381        let show_new_completions_on_confirm = completion
 4382            .confirm
 4383            .as_ref()
 4384            .map_or(false, |confirm| confirm(intent, window, cx));
 4385        if show_new_completions_on_confirm {
 4386            self.show_completions(&ShowCompletions { trigger: None }, window, cx);
 4387        }
 4388
 4389        let provider = self.completion_provider.as_ref()?;
 4390        drop(completion);
 4391        let apply_edits = provider.apply_additional_edits_for_completion(
 4392            buffer_handle,
 4393            completions_menu.completions.clone(),
 4394            candidate_id,
 4395            true,
 4396            cx,
 4397        );
 4398
 4399        let editor_settings = EditorSettings::get_global(cx);
 4400        if editor_settings.show_signature_help_after_edits || editor_settings.auto_signature_help {
 4401            // After the code completion is finished, users often want to know what signatures are needed.
 4402            // so we should automatically call signature_help
 4403            self.show_signature_help(&ShowSignatureHelp, window, cx);
 4404        }
 4405
 4406        Some(cx.foreground_executor().spawn(async move {
 4407            apply_edits.await?;
 4408            Ok(())
 4409        }))
 4410    }
 4411
 4412    pub fn toggle_code_actions(
 4413        &mut self,
 4414        action: &ToggleCodeActions,
 4415        window: &mut Window,
 4416        cx: &mut Context<Self>,
 4417    ) {
 4418        let mut context_menu = self.context_menu.borrow_mut();
 4419        if let Some(CodeContextMenu::CodeActions(code_actions)) = context_menu.as_ref() {
 4420            if code_actions.deployed_from_indicator == action.deployed_from_indicator {
 4421                // Toggle if we're selecting the same one
 4422                *context_menu = None;
 4423                cx.notify();
 4424                return;
 4425            } else {
 4426                // Otherwise, clear it and start a new one
 4427                *context_menu = None;
 4428                cx.notify();
 4429            }
 4430        }
 4431        drop(context_menu);
 4432        let snapshot = self.snapshot(window, cx);
 4433        let deployed_from_indicator = action.deployed_from_indicator;
 4434        let mut task = self.code_actions_task.take();
 4435        let action = action.clone();
 4436        cx.spawn_in(window, |editor, mut cx| async move {
 4437            while let Some(prev_task) = task {
 4438                prev_task.await.log_err();
 4439                task = editor.update(&mut cx, |this, _| this.code_actions_task.take())?;
 4440            }
 4441
 4442            let spawned_test_task = editor.update_in(&mut cx, |editor, window, cx| {
 4443                if editor.focus_handle.is_focused(window) {
 4444                    let multibuffer_point = action
 4445                        .deployed_from_indicator
 4446                        .map(|row| DisplayPoint::new(row, 0).to_point(&snapshot))
 4447                        .unwrap_or_else(|| editor.selections.newest::<Point>(cx).head());
 4448                    let (buffer, buffer_row) = snapshot
 4449                        .buffer_snapshot
 4450                        .buffer_line_for_row(MultiBufferRow(multibuffer_point.row))
 4451                        .and_then(|(buffer_snapshot, range)| {
 4452                            editor
 4453                                .buffer
 4454                                .read(cx)
 4455                                .buffer(buffer_snapshot.remote_id())
 4456                                .map(|buffer| (buffer, range.start.row))
 4457                        })?;
 4458                    let (_, code_actions) = editor
 4459                        .available_code_actions
 4460                        .clone()
 4461                        .and_then(|(location, code_actions)| {
 4462                            let snapshot = location.buffer.read(cx).snapshot();
 4463                            let point_range = location.range.to_point(&snapshot);
 4464                            let point_range = point_range.start.row..=point_range.end.row;
 4465                            if point_range.contains(&buffer_row) {
 4466                                Some((location, code_actions))
 4467                            } else {
 4468                                None
 4469                            }
 4470                        })
 4471                        .unzip();
 4472                    let buffer_id = buffer.read(cx).remote_id();
 4473                    let tasks = editor
 4474                        .tasks
 4475                        .get(&(buffer_id, buffer_row))
 4476                        .map(|t| Arc::new(t.to_owned()));
 4477                    if tasks.is_none() && code_actions.is_none() {
 4478                        return None;
 4479                    }
 4480
 4481                    editor.completion_tasks.clear();
 4482                    editor.discard_inline_completion(false, cx);
 4483                    let task_context =
 4484                        tasks
 4485                            .as_ref()
 4486                            .zip(editor.project.clone())
 4487                            .map(|(tasks, project)| {
 4488                                Self::build_tasks_context(&project, &buffer, buffer_row, tasks, cx)
 4489                            });
 4490
 4491                    Some(cx.spawn_in(window, |editor, mut cx| async move {
 4492                        let task_context = match task_context {
 4493                            Some(task_context) => task_context.await,
 4494                            None => None,
 4495                        };
 4496                        let resolved_tasks =
 4497                            tasks.zip(task_context).map(|(tasks, task_context)| {
 4498                                Rc::new(ResolvedTasks {
 4499                                    templates: tasks.resolve(&task_context).collect(),
 4500                                    position: snapshot.buffer_snapshot.anchor_before(Point::new(
 4501                                        multibuffer_point.row,
 4502                                        tasks.column,
 4503                                    )),
 4504                                })
 4505                            });
 4506                        let spawn_straight_away = resolved_tasks
 4507                            .as_ref()
 4508                            .map_or(false, |tasks| tasks.templates.len() == 1)
 4509                            && code_actions
 4510                                .as_ref()
 4511                                .map_or(true, |actions| actions.is_empty());
 4512                        if let Ok(task) = editor.update_in(&mut cx, |editor, window, cx| {
 4513                            *editor.context_menu.borrow_mut() =
 4514                                Some(CodeContextMenu::CodeActions(CodeActionsMenu {
 4515                                    buffer,
 4516                                    actions: CodeActionContents {
 4517                                        tasks: resolved_tasks,
 4518                                        actions: code_actions,
 4519                                    },
 4520                                    selected_item: Default::default(),
 4521                                    scroll_handle: UniformListScrollHandle::default(),
 4522                                    deployed_from_indicator,
 4523                                }));
 4524                            if spawn_straight_away {
 4525                                if let Some(task) = editor.confirm_code_action(
 4526                                    &ConfirmCodeAction { item_ix: Some(0) },
 4527                                    window,
 4528                                    cx,
 4529                                ) {
 4530                                    cx.notify();
 4531                                    return task;
 4532                                }
 4533                            }
 4534                            cx.notify();
 4535                            Task::ready(Ok(()))
 4536                        }) {
 4537                            task.await
 4538                        } else {
 4539                            Ok(())
 4540                        }
 4541                    }))
 4542                } else {
 4543                    Some(Task::ready(Ok(())))
 4544                }
 4545            })?;
 4546            if let Some(task) = spawned_test_task {
 4547                task.await?;
 4548            }
 4549
 4550            Ok::<_, anyhow::Error>(())
 4551        })
 4552        .detach_and_log_err(cx);
 4553    }
 4554
 4555    pub fn confirm_code_action(
 4556        &mut self,
 4557        action: &ConfirmCodeAction,
 4558        window: &mut Window,
 4559        cx: &mut Context<Self>,
 4560    ) -> Option<Task<Result<()>>> {
 4561        let actions_menu =
 4562            if let CodeContextMenu::CodeActions(menu) = self.hide_context_menu(window, cx)? {
 4563                menu
 4564            } else {
 4565                return None;
 4566            };
 4567        let action_ix = action.item_ix.unwrap_or(actions_menu.selected_item);
 4568        let action = actions_menu.actions.get(action_ix)?;
 4569        let title = action.label();
 4570        let buffer = actions_menu.buffer;
 4571        let workspace = self.workspace()?;
 4572
 4573        match action {
 4574            CodeActionsItem::Task(task_source_kind, resolved_task) => {
 4575                workspace.update(cx, |workspace, cx| {
 4576                    workspace::tasks::schedule_resolved_task(
 4577                        workspace,
 4578                        task_source_kind,
 4579                        resolved_task,
 4580                        false,
 4581                        cx,
 4582                    );
 4583
 4584                    Some(Task::ready(Ok(())))
 4585                })
 4586            }
 4587            CodeActionsItem::CodeAction {
 4588                excerpt_id,
 4589                action,
 4590                provider,
 4591            } => {
 4592                let apply_code_action =
 4593                    provider.apply_code_action(buffer, action, excerpt_id, true, window, cx);
 4594                let workspace = workspace.downgrade();
 4595                Some(cx.spawn_in(window, |editor, cx| async move {
 4596                    let project_transaction = apply_code_action.await?;
 4597                    Self::open_project_transaction(
 4598                        &editor,
 4599                        workspace,
 4600                        project_transaction,
 4601                        title,
 4602                        cx,
 4603                    )
 4604                    .await
 4605                }))
 4606            }
 4607        }
 4608    }
 4609
 4610    pub async fn open_project_transaction(
 4611        this: &WeakEntity<Editor>,
 4612        workspace: WeakEntity<Workspace>,
 4613        transaction: ProjectTransaction,
 4614        title: String,
 4615        mut cx: AsyncWindowContext,
 4616    ) -> Result<()> {
 4617        let mut entries = transaction.0.into_iter().collect::<Vec<_>>();
 4618        cx.update(|_, cx| {
 4619            entries.sort_unstable_by_key(|(buffer, _)| {
 4620                buffer.read(cx).file().map(|f| f.path().clone())
 4621            });
 4622        })?;
 4623
 4624        // If the project transaction's edits are all contained within this editor, then
 4625        // avoid opening a new editor to display them.
 4626
 4627        if let Some((buffer, transaction)) = entries.first() {
 4628            if entries.len() == 1 {
 4629                let excerpt = this.update(&mut cx, |editor, cx| {
 4630                    editor
 4631                        .buffer()
 4632                        .read(cx)
 4633                        .excerpt_containing(editor.selections.newest_anchor().head(), cx)
 4634                })?;
 4635                if let Some((_, excerpted_buffer, excerpt_range)) = excerpt {
 4636                    if excerpted_buffer == *buffer {
 4637                        let all_edits_within_excerpt = buffer.read_with(&cx, |buffer, _| {
 4638                            let excerpt_range = excerpt_range.to_offset(buffer);
 4639                            buffer
 4640                                .edited_ranges_for_transaction::<usize>(transaction)
 4641                                .all(|range| {
 4642                                    excerpt_range.start <= range.start
 4643                                        && excerpt_range.end >= range.end
 4644                                })
 4645                        })?;
 4646
 4647                        if all_edits_within_excerpt {
 4648                            return Ok(());
 4649                        }
 4650                    }
 4651                }
 4652            }
 4653        } else {
 4654            return Ok(());
 4655        }
 4656
 4657        let mut ranges_to_highlight = Vec::new();
 4658        let excerpt_buffer = cx.new(|cx| {
 4659            let mut multibuffer = MultiBuffer::new(Capability::ReadWrite).with_title(title);
 4660            for (buffer_handle, transaction) in &entries {
 4661                let buffer = buffer_handle.read(cx);
 4662                ranges_to_highlight.extend(
 4663                    multibuffer.push_excerpts_with_context_lines(
 4664                        buffer_handle.clone(),
 4665                        buffer
 4666                            .edited_ranges_for_transaction::<usize>(transaction)
 4667                            .collect(),
 4668                        DEFAULT_MULTIBUFFER_CONTEXT,
 4669                        cx,
 4670                    ),
 4671                );
 4672            }
 4673            multibuffer.push_transaction(entries.iter().map(|(b, t)| (b, t)), cx);
 4674            multibuffer
 4675        })?;
 4676
 4677        workspace.update_in(&mut cx, |workspace, window, cx| {
 4678            let project = workspace.project().clone();
 4679            let editor =
 4680                cx.new(|cx| Editor::for_multibuffer(excerpt_buffer, Some(project), window, cx));
 4681            workspace.add_item_to_active_pane(Box::new(editor.clone()), None, true, window, cx);
 4682            editor.update(cx, |editor, cx| {
 4683                editor.highlight_background::<Self>(
 4684                    &ranges_to_highlight,
 4685                    |theme| theme.editor_highlighted_line_background,
 4686                    cx,
 4687                );
 4688            });
 4689        })?;
 4690
 4691        Ok(())
 4692    }
 4693
 4694    pub fn clear_code_action_providers(&mut self) {
 4695        self.code_action_providers.clear();
 4696        self.available_code_actions.take();
 4697    }
 4698
 4699    pub fn add_code_action_provider(
 4700        &mut self,
 4701        provider: Rc<dyn CodeActionProvider>,
 4702        window: &mut Window,
 4703        cx: &mut Context<Self>,
 4704    ) {
 4705        if self
 4706            .code_action_providers
 4707            .iter()
 4708            .any(|existing_provider| existing_provider.id() == provider.id())
 4709        {
 4710            return;
 4711        }
 4712
 4713        self.code_action_providers.push(provider);
 4714        self.refresh_code_actions(window, cx);
 4715    }
 4716
 4717    pub fn remove_code_action_provider(
 4718        &mut self,
 4719        id: Arc<str>,
 4720        window: &mut Window,
 4721        cx: &mut Context<Self>,
 4722    ) {
 4723        self.code_action_providers
 4724            .retain(|provider| provider.id() != id);
 4725        self.refresh_code_actions(window, cx);
 4726    }
 4727
 4728    fn refresh_code_actions(&mut self, window: &mut Window, cx: &mut Context<Self>) -> Option<()> {
 4729        let buffer = self.buffer.read(cx);
 4730        let newest_selection = self.selections.newest_anchor().clone();
 4731        if newest_selection.head().diff_base_anchor.is_some() {
 4732            return None;
 4733        }
 4734        let (start_buffer, start) = buffer.text_anchor_for_position(newest_selection.start, cx)?;
 4735        let (end_buffer, end) = buffer.text_anchor_for_position(newest_selection.end, cx)?;
 4736        if start_buffer != end_buffer {
 4737            return None;
 4738        }
 4739
 4740        self.code_actions_task = Some(cx.spawn_in(window, |this, mut cx| async move {
 4741            cx.background_executor()
 4742                .timer(CODE_ACTIONS_DEBOUNCE_TIMEOUT)
 4743                .await;
 4744
 4745            let (providers, tasks) = this.update_in(&mut cx, |this, window, cx| {
 4746                let providers = this.code_action_providers.clone();
 4747                let tasks = this
 4748                    .code_action_providers
 4749                    .iter()
 4750                    .map(|provider| provider.code_actions(&start_buffer, start..end, window, cx))
 4751                    .collect::<Vec<_>>();
 4752                (providers, tasks)
 4753            })?;
 4754
 4755            let mut actions = Vec::new();
 4756            for (provider, provider_actions) in
 4757                providers.into_iter().zip(future::join_all(tasks).await)
 4758            {
 4759                if let Some(provider_actions) = provider_actions.log_err() {
 4760                    actions.extend(provider_actions.into_iter().map(|action| {
 4761                        AvailableCodeAction {
 4762                            excerpt_id: newest_selection.start.excerpt_id,
 4763                            action,
 4764                            provider: provider.clone(),
 4765                        }
 4766                    }));
 4767                }
 4768            }
 4769
 4770            this.update(&mut cx, |this, cx| {
 4771                this.available_code_actions = if actions.is_empty() {
 4772                    None
 4773                } else {
 4774                    Some((
 4775                        Location {
 4776                            buffer: start_buffer,
 4777                            range: start..end,
 4778                        },
 4779                        actions.into(),
 4780                    ))
 4781                };
 4782                cx.notify();
 4783            })
 4784        }));
 4785        None
 4786    }
 4787
 4788    fn start_inline_blame_timer(&mut self, window: &mut Window, cx: &mut Context<Self>) {
 4789        if let Some(delay) = ProjectSettings::get_global(cx).git.inline_blame_delay() {
 4790            self.show_git_blame_inline = false;
 4791
 4792            self.show_git_blame_inline_delay_task =
 4793                Some(cx.spawn_in(window, |this, mut cx| async move {
 4794                    cx.background_executor().timer(delay).await;
 4795
 4796                    this.update(&mut cx, |this, cx| {
 4797                        this.show_git_blame_inline = true;
 4798                        cx.notify();
 4799                    })
 4800                    .log_err();
 4801                }));
 4802        }
 4803    }
 4804
 4805    fn refresh_document_highlights(&mut self, cx: &mut Context<Self>) -> Option<()> {
 4806        if self.pending_rename.is_some() {
 4807            return None;
 4808        }
 4809
 4810        let provider = self.semantics_provider.clone()?;
 4811        let buffer = self.buffer.read(cx);
 4812        let newest_selection = self.selections.newest_anchor().clone();
 4813        let cursor_position = newest_selection.head();
 4814        let (cursor_buffer, cursor_buffer_position) =
 4815            buffer.text_anchor_for_position(cursor_position, cx)?;
 4816        let (tail_buffer, _) = buffer.text_anchor_for_position(newest_selection.tail(), cx)?;
 4817        if cursor_buffer != tail_buffer {
 4818            return None;
 4819        }
 4820        let debounce = EditorSettings::get_global(cx).lsp_highlight_debounce;
 4821        self.document_highlights_task = Some(cx.spawn(|this, mut cx| async move {
 4822            cx.background_executor()
 4823                .timer(Duration::from_millis(debounce))
 4824                .await;
 4825
 4826            let highlights = if let Some(highlights) = cx
 4827                .update(|cx| {
 4828                    provider.document_highlights(&cursor_buffer, cursor_buffer_position, cx)
 4829                })
 4830                .ok()
 4831                .flatten()
 4832            {
 4833                highlights.await.log_err()
 4834            } else {
 4835                None
 4836            };
 4837
 4838            if let Some(highlights) = highlights {
 4839                this.update(&mut cx, |this, cx| {
 4840                    if this.pending_rename.is_some() {
 4841                        return;
 4842                    }
 4843
 4844                    let buffer_id = cursor_position.buffer_id;
 4845                    let buffer = this.buffer.read(cx);
 4846                    if !buffer
 4847                        .text_anchor_for_position(cursor_position, cx)
 4848                        .map_or(false, |(buffer, _)| buffer == cursor_buffer)
 4849                    {
 4850                        return;
 4851                    }
 4852
 4853                    let cursor_buffer_snapshot = cursor_buffer.read(cx);
 4854                    let mut write_ranges = Vec::new();
 4855                    let mut read_ranges = Vec::new();
 4856                    for highlight in highlights {
 4857                        for (excerpt_id, excerpt_range) in
 4858                            buffer.excerpts_for_buffer(cursor_buffer.read(cx).remote_id(), cx)
 4859                        {
 4860                            let start = highlight
 4861                                .range
 4862                                .start
 4863                                .max(&excerpt_range.context.start, cursor_buffer_snapshot);
 4864                            let end = highlight
 4865                                .range
 4866                                .end
 4867                                .min(&excerpt_range.context.end, cursor_buffer_snapshot);
 4868                            if start.cmp(&end, cursor_buffer_snapshot).is_ge() {
 4869                                continue;
 4870                            }
 4871
 4872                            let range = Anchor {
 4873                                buffer_id,
 4874                                excerpt_id,
 4875                                text_anchor: start,
 4876                                diff_base_anchor: None,
 4877                            }..Anchor {
 4878                                buffer_id,
 4879                                excerpt_id,
 4880                                text_anchor: end,
 4881                                diff_base_anchor: None,
 4882                            };
 4883                            if highlight.kind == lsp::DocumentHighlightKind::WRITE {
 4884                                write_ranges.push(range);
 4885                            } else {
 4886                                read_ranges.push(range);
 4887                            }
 4888                        }
 4889                    }
 4890
 4891                    this.highlight_background::<DocumentHighlightRead>(
 4892                        &read_ranges,
 4893                        |theme| theme.editor_document_highlight_read_background,
 4894                        cx,
 4895                    );
 4896                    this.highlight_background::<DocumentHighlightWrite>(
 4897                        &write_ranges,
 4898                        |theme| theme.editor_document_highlight_write_background,
 4899                        cx,
 4900                    );
 4901                    cx.notify();
 4902                })
 4903                .log_err();
 4904            }
 4905        }));
 4906        None
 4907    }
 4908
 4909    pub fn refresh_selected_text_highlights(
 4910        &mut self,
 4911        window: &mut Window,
 4912        cx: &mut Context<Editor>,
 4913    ) {
 4914        self.selection_highlight_task.take();
 4915        if !EditorSettings::get_global(cx).selection_highlight {
 4916            self.clear_background_highlights::<SelectedTextHighlight>(cx);
 4917            return;
 4918        }
 4919        if self.selections.count() != 1 || self.selections.line_mode {
 4920            self.clear_background_highlights::<SelectedTextHighlight>(cx);
 4921            return;
 4922        }
 4923        let selection = self.selections.newest::<Point>(cx);
 4924        if selection.is_empty() || selection.start.row != selection.end.row {
 4925            self.clear_background_highlights::<SelectedTextHighlight>(cx);
 4926            return;
 4927        }
 4928        let debounce = EditorSettings::get_global(cx).selection_highlight_debounce;
 4929        self.selection_highlight_task = Some(cx.spawn_in(window, |editor, mut cx| async move {
 4930            cx.background_executor()
 4931                .timer(Duration::from_millis(debounce))
 4932                .await;
 4933            let Some(Some(matches_task)) = editor
 4934                .update_in(&mut cx, |editor, _, cx| {
 4935                    if editor.selections.count() != 1 || editor.selections.line_mode {
 4936                        editor.clear_background_highlights::<SelectedTextHighlight>(cx);
 4937                        return None;
 4938                    }
 4939                    let selection = editor.selections.newest::<Point>(cx);
 4940                    if selection.is_empty() || selection.start.row != selection.end.row {
 4941                        editor.clear_background_highlights::<SelectedTextHighlight>(cx);
 4942                        return None;
 4943                    }
 4944                    let buffer = editor.buffer().read(cx).snapshot(cx);
 4945                    let query = buffer.text_for_range(selection.range()).collect::<String>();
 4946                    if query.trim().is_empty() {
 4947                        editor.clear_background_highlights::<SelectedTextHighlight>(cx);
 4948                        return None;
 4949                    }
 4950                    Some(cx.background_spawn(async move {
 4951                        let mut ranges = Vec::new();
 4952                        let selection_anchors = selection.range().to_anchors(&buffer);
 4953                        for range in [buffer.anchor_before(0)..buffer.anchor_after(buffer.len())] {
 4954                            for (search_buffer, search_range, excerpt_id) in
 4955                                buffer.range_to_buffer_ranges(range)
 4956                            {
 4957                                ranges.extend(
 4958                                    project::search::SearchQuery::text(
 4959                                        query.clone(),
 4960                                        false,
 4961                                        false,
 4962                                        false,
 4963                                        Default::default(),
 4964                                        Default::default(),
 4965                                        None,
 4966                                    )
 4967                                    .unwrap()
 4968                                    .search(search_buffer, Some(search_range.clone()))
 4969                                    .await
 4970                                    .into_iter()
 4971                                    .filter_map(
 4972                                        |match_range| {
 4973                                            let start = search_buffer.anchor_after(
 4974                                                search_range.start + match_range.start,
 4975                                            );
 4976                                            let end = search_buffer.anchor_before(
 4977                                                search_range.start + match_range.end,
 4978                                            );
 4979                                            let range = Anchor::range_in_buffer(
 4980                                                excerpt_id,
 4981                                                search_buffer.remote_id(),
 4982                                                start..end,
 4983                                            );
 4984                                            (range != selection_anchors).then_some(range)
 4985                                        },
 4986                                    ),
 4987                                );
 4988                            }
 4989                        }
 4990                        ranges
 4991                    }))
 4992                })
 4993                .log_err()
 4994            else {
 4995                return;
 4996            };
 4997            let matches = matches_task.await;
 4998            editor
 4999                .update_in(&mut cx, |editor, _, cx| {
 5000                    editor.clear_background_highlights::<SelectedTextHighlight>(cx);
 5001                    if !matches.is_empty() {
 5002                        editor.highlight_background::<SelectedTextHighlight>(
 5003                            &matches,
 5004                            |theme| theme.editor_document_highlight_bracket_background,
 5005                            cx,
 5006                        )
 5007                    }
 5008                })
 5009                .log_err();
 5010        }));
 5011    }
 5012
 5013    pub fn refresh_inline_completion(
 5014        &mut self,
 5015        debounce: bool,
 5016        user_requested: bool,
 5017        window: &mut Window,
 5018        cx: &mut Context<Self>,
 5019    ) -> Option<()> {
 5020        let provider = self.edit_prediction_provider()?;
 5021        let cursor = self.selections.newest_anchor().head();
 5022        let (buffer, cursor_buffer_position) =
 5023            self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
 5024
 5025        if !self.edit_predictions_enabled_in_buffer(&buffer, cursor_buffer_position, cx) {
 5026            self.discard_inline_completion(false, cx);
 5027            return None;
 5028        }
 5029
 5030        if !user_requested
 5031            && (!self.should_show_edit_predictions()
 5032                || !self.is_focused(window)
 5033                || buffer.read(cx).is_empty())
 5034        {
 5035            self.discard_inline_completion(false, cx);
 5036            return None;
 5037        }
 5038
 5039        self.update_visible_inline_completion(window, cx);
 5040        provider.refresh(
 5041            self.project.clone(),
 5042            buffer,
 5043            cursor_buffer_position,
 5044            debounce,
 5045            cx,
 5046        );
 5047        Some(())
 5048    }
 5049
 5050    fn show_edit_predictions_in_menu(&self) -> bool {
 5051        match self.edit_prediction_settings {
 5052            EditPredictionSettings::Disabled => false,
 5053            EditPredictionSettings::Enabled { show_in_menu, .. } => show_in_menu,
 5054        }
 5055    }
 5056
 5057    pub fn edit_predictions_enabled(&self) -> bool {
 5058        match self.edit_prediction_settings {
 5059            EditPredictionSettings::Disabled => false,
 5060            EditPredictionSettings::Enabled { .. } => true,
 5061        }
 5062    }
 5063
 5064    fn edit_prediction_requires_modifier(&self) -> bool {
 5065        match self.edit_prediction_settings {
 5066            EditPredictionSettings::Disabled => false,
 5067            EditPredictionSettings::Enabled {
 5068                preview_requires_modifier,
 5069                ..
 5070            } => preview_requires_modifier,
 5071        }
 5072    }
 5073
 5074    pub fn update_edit_prediction_settings(&mut self, cx: &mut Context<Self>) {
 5075        if self.edit_prediction_provider.is_none() {
 5076            self.edit_prediction_settings = EditPredictionSettings::Disabled;
 5077        } else {
 5078            let selection = self.selections.newest_anchor();
 5079            let cursor = selection.head();
 5080
 5081            if let Some((buffer, cursor_buffer_position)) =
 5082                self.buffer.read(cx).text_anchor_for_position(cursor, cx)
 5083            {
 5084                self.edit_prediction_settings =
 5085                    self.edit_prediction_settings_at_position(&buffer, cursor_buffer_position, cx);
 5086            }
 5087        }
 5088    }
 5089
 5090    fn edit_prediction_settings_at_position(
 5091        &self,
 5092        buffer: &Entity<Buffer>,
 5093        buffer_position: language::Anchor,
 5094        cx: &App,
 5095    ) -> EditPredictionSettings {
 5096        if self.mode != EditorMode::Full
 5097            || !self.show_inline_completions_override.unwrap_or(true)
 5098            || self.inline_completions_disabled_in_scope(buffer, buffer_position, cx)
 5099        {
 5100            return EditPredictionSettings::Disabled;
 5101        }
 5102
 5103        let buffer = buffer.read(cx);
 5104
 5105        let file = buffer.file();
 5106
 5107        if !language_settings(buffer.language().map(|l| l.name()), file, cx).show_edit_predictions {
 5108            return EditPredictionSettings::Disabled;
 5109        };
 5110
 5111        let by_provider = matches!(
 5112            self.menu_inline_completions_policy,
 5113            MenuInlineCompletionsPolicy::ByProvider
 5114        );
 5115
 5116        let show_in_menu = by_provider
 5117            && self
 5118                .edit_prediction_provider
 5119                .as_ref()
 5120                .map_or(false, |provider| {
 5121                    provider.provider.show_completions_in_menu()
 5122                });
 5123
 5124        let preview_requires_modifier =
 5125            all_language_settings(file, cx).edit_predictions_mode() == EditPredictionsMode::Subtle;
 5126
 5127        EditPredictionSettings::Enabled {
 5128            show_in_menu,
 5129            preview_requires_modifier,
 5130        }
 5131    }
 5132
 5133    fn should_show_edit_predictions(&self) -> bool {
 5134        self.snippet_stack.is_empty() && self.edit_predictions_enabled()
 5135    }
 5136
 5137    pub fn edit_prediction_preview_is_active(&self) -> bool {
 5138        matches!(
 5139            self.edit_prediction_preview,
 5140            EditPredictionPreview::Active { .. }
 5141        )
 5142    }
 5143
 5144    pub fn edit_predictions_enabled_at_cursor(&self, cx: &App) -> bool {
 5145        let cursor = self.selections.newest_anchor().head();
 5146        if let Some((buffer, cursor_position)) =
 5147            self.buffer.read(cx).text_anchor_for_position(cursor, cx)
 5148        {
 5149            self.edit_predictions_enabled_in_buffer(&buffer, cursor_position, cx)
 5150        } else {
 5151            false
 5152        }
 5153    }
 5154
 5155    fn edit_predictions_enabled_in_buffer(
 5156        &self,
 5157        buffer: &Entity<Buffer>,
 5158        buffer_position: language::Anchor,
 5159        cx: &App,
 5160    ) -> bool {
 5161        maybe!({
 5162            let provider = self.edit_prediction_provider()?;
 5163            if !provider.is_enabled(&buffer, buffer_position, cx) {
 5164                return Some(false);
 5165            }
 5166            let buffer = buffer.read(cx);
 5167            let Some(file) = buffer.file() else {
 5168                return Some(true);
 5169            };
 5170            let settings = all_language_settings(Some(file), cx);
 5171            Some(settings.edit_predictions_enabled_for_file(file, cx))
 5172        })
 5173        .unwrap_or(false)
 5174    }
 5175
 5176    fn cycle_inline_completion(
 5177        &mut self,
 5178        direction: Direction,
 5179        window: &mut Window,
 5180        cx: &mut Context<Self>,
 5181    ) -> Option<()> {
 5182        let provider = self.edit_prediction_provider()?;
 5183        let cursor = self.selections.newest_anchor().head();
 5184        let (buffer, cursor_buffer_position) =
 5185            self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
 5186        if self.inline_completions_hidden_for_vim_mode || !self.should_show_edit_predictions() {
 5187            return None;
 5188        }
 5189
 5190        provider.cycle(buffer, cursor_buffer_position, direction, cx);
 5191        self.update_visible_inline_completion(window, cx);
 5192
 5193        Some(())
 5194    }
 5195
 5196    pub fn show_inline_completion(
 5197        &mut self,
 5198        _: &ShowEditPrediction,
 5199        window: &mut Window,
 5200        cx: &mut Context<Self>,
 5201    ) {
 5202        if !self.has_active_inline_completion() {
 5203            self.refresh_inline_completion(false, true, window, cx);
 5204            return;
 5205        }
 5206
 5207        self.update_visible_inline_completion(window, cx);
 5208    }
 5209
 5210    pub fn display_cursor_names(
 5211        &mut self,
 5212        _: &DisplayCursorNames,
 5213        window: &mut Window,
 5214        cx: &mut Context<Self>,
 5215    ) {
 5216        self.show_cursor_names(window, cx);
 5217    }
 5218
 5219    fn show_cursor_names(&mut self, window: &mut Window, cx: &mut Context<Self>) {
 5220        self.show_cursor_names = true;
 5221        cx.notify();
 5222        cx.spawn_in(window, |this, mut cx| async move {
 5223            cx.background_executor().timer(CURSORS_VISIBLE_FOR).await;
 5224            this.update(&mut cx, |this, cx| {
 5225                this.show_cursor_names = false;
 5226                cx.notify()
 5227            })
 5228            .ok()
 5229        })
 5230        .detach();
 5231    }
 5232
 5233    pub fn next_edit_prediction(
 5234        &mut self,
 5235        _: &NextEditPrediction,
 5236        window: &mut Window,
 5237        cx: &mut Context<Self>,
 5238    ) {
 5239        if self.has_active_inline_completion() {
 5240            self.cycle_inline_completion(Direction::Next, window, cx);
 5241        } else {
 5242            let is_copilot_disabled = self
 5243                .refresh_inline_completion(false, true, window, cx)
 5244                .is_none();
 5245            if is_copilot_disabled {
 5246                cx.propagate();
 5247            }
 5248        }
 5249    }
 5250
 5251    pub fn previous_edit_prediction(
 5252        &mut self,
 5253        _: &PreviousEditPrediction,
 5254        window: &mut Window,
 5255        cx: &mut Context<Self>,
 5256    ) {
 5257        if self.has_active_inline_completion() {
 5258            self.cycle_inline_completion(Direction::Prev, window, cx);
 5259        } else {
 5260            let is_copilot_disabled = self
 5261                .refresh_inline_completion(false, true, window, cx)
 5262                .is_none();
 5263            if is_copilot_disabled {
 5264                cx.propagate();
 5265            }
 5266        }
 5267    }
 5268
 5269    pub fn accept_edit_prediction(
 5270        &mut self,
 5271        _: &AcceptEditPrediction,
 5272        window: &mut Window,
 5273        cx: &mut Context<Self>,
 5274    ) {
 5275        if self.show_edit_predictions_in_menu() {
 5276            self.hide_context_menu(window, cx);
 5277        }
 5278
 5279        let Some(active_inline_completion) = self.active_inline_completion.as_ref() else {
 5280            return;
 5281        };
 5282
 5283        self.report_inline_completion_event(
 5284            active_inline_completion.completion_id.clone(),
 5285            true,
 5286            cx,
 5287        );
 5288
 5289        match &active_inline_completion.completion {
 5290            InlineCompletion::Move { target, .. } => {
 5291                let target = *target;
 5292
 5293                if let Some(position_map) = &self.last_position_map {
 5294                    if position_map
 5295                        .visible_row_range
 5296                        .contains(&target.to_display_point(&position_map.snapshot).row())
 5297                        || !self.edit_prediction_requires_modifier()
 5298                    {
 5299                        self.unfold_ranges(&[target..target], true, false, cx);
 5300                        // Note that this is also done in vim's handler of the Tab action.
 5301                        self.change_selections(
 5302                            Some(Autoscroll::newest()),
 5303                            window,
 5304                            cx,
 5305                            |selections| {
 5306                                selections.select_anchor_ranges([target..target]);
 5307                            },
 5308                        );
 5309                        self.clear_row_highlights::<EditPredictionPreview>();
 5310
 5311                        self.edit_prediction_preview
 5312                            .set_previous_scroll_position(None);
 5313                    } else {
 5314                        self.edit_prediction_preview
 5315                            .set_previous_scroll_position(Some(
 5316                                position_map.snapshot.scroll_anchor,
 5317                            ));
 5318
 5319                        self.highlight_rows::<EditPredictionPreview>(
 5320                            target..target,
 5321                            cx.theme().colors().editor_highlighted_line_background,
 5322                            true,
 5323                            cx,
 5324                        );
 5325                        self.request_autoscroll(Autoscroll::fit(), cx);
 5326                    }
 5327                }
 5328            }
 5329            InlineCompletion::Edit { edits, .. } => {
 5330                if let Some(provider) = self.edit_prediction_provider() {
 5331                    provider.accept(cx);
 5332                }
 5333
 5334                let snapshot = self.buffer.read(cx).snapshot(cx);
 5335                let last_edit_end = edits.last().unwrap().0.end.bias_right(&snapshot);
 5336
 5337                self.buffer.update(cx, |buffer, cx| {
 5338                    buffer.edit(edits.iter().cloned(), None, cx)
 5339                });
 5340
 5341                self.change_selections(None, window, cx, |s| {
 5342                    s.select_anchor_ranges([last_edit_end..last_edit_end])
 5343                });
 5344
 5345                self.update_visible_inline_completion(window, cx);
 5346                if self.active_inline_completion.is_none() {
 5347                    self.refresh_inline_completion(true, true, window, cx);
 5348                }
 5349
 5350                cx.notify();
 5351            }
 5352        }
 5353
 5354        self.edit_prediction_requires_modifier_in_indent_conflict = false;
 5355    }
 5356
 5357    pub fn accept_partial_inline_completion(
 5358        &mut self,
 5359        _: &AcceptPartialEditPrediction,
 5360        window: &mut Window,
 5361        cx: &mut Context<Self>,
 5362    ) {
 5363        let Some(active_inline_completion) = self.active_inline_completion.as_ref() else {
 5364            return;
 5365        };
 5366        if self.selections.count() != 1 {
 5367            return;
 5368        }
 5369
 5370        self.report_inline_completion_event(
 5371            active_inline_completion.completion_id.clone(),
 5372            true,
 5373            cx,
 5374        );
 5375
 5376        match &active_inline_completion.completion {
 5377            InlineCompletion::Move { target, .. } => {
 5378                let target = *target;
 5379                self.change_selections(Some(Autoscroll::newest()), window, cx, |selections| {
 5380                    selections.select_anchor_ranges([target..target]);
 5381                });
 5382            }
 5383            InlineCompletion::Edit { edits, .. } => {
 5384                // Find an insertion that starts at the cursor position.
 5385                let snapshot = self.buffer.read(cx).snapshot(cx);
 5386                let cursor_offset = self.selections.newest::<usize>(cx).head();
 5387                let insertion = edits.iter().find_map(|(range, text)| {
 5388                    let range = range.to_offset(&snapshot);
 5389                    if range.is_empty() && range.start == cursor_offset {
 5390                        Some(text)
 5391                    } else {
 5392                        None
 5393                    }
 5394                });
 5395
 5396                if let Some(text) = insertion {
 5397                    let mut partial_completion = text
 5398                        .chars()
 5399                        .by_ref()
 5400                        .take_while(|c| c.is_alphabetic())
 5401                        .collect::<String>();
 5402                    if partial_completion.is_empty() {
 5403                        partial_completion = text
 5404                            .chars()
 5405                            .by_ref()
 5406                            .take_while(|c| c.is_whitespace() || !c.is_alphabetic())
 5407                            .collect::<String>();
 5408                    }
 5409
 5410                    cx.emit(EditorEvent::InputHandled {
 5411                        utf16_range_to_replace: None,
 5412                        text: partial_completion.clone().into(),
 5413                    });
 5414
 5415                    self.insert_with_autoindent_mode(&partial_completion, None, window, cx);
 5416
 5417                    self.refresh_inline_completion(true, true, window, cx);
 5418                    cx.notify();
 5419                } else {
 5420                    self.accept_edit_prediction(&Default::default(), window, cx);
 5421                }
 5422            }
 5423        }
 5424    }
 5425
 5426    fn discard_inline_completion(
 5427        &mut self,
 5428        should_report_inline_completion_event: bool,
 5429        cx: &mut Context<Self>,
 5430    ) -> bool {
 5431        if should_report_inline_completion_event {
 5432            let completion_id = self
 5433                .active_inline_completion
 5434                .as_ref()
 5435                .and_then(|active_completion| active_completion.completion_id.clone());
 5436
 5437            self.report_inline_completion_event(completion_id, false, cx);
 5438        }
 5439
 5440        if let Some(provider) = self.edit_prediction_provider() {
 5441            provider.discard(cx);
 5442        }
 5443
 5444        self.take_active_inline_completion(cx)
 5445    }
 5446
 5447    fn report_inline_completion_event(&self, id: Option<SharedString>, accepted: bool, cx: &App) {
 5448        let Some(provider) = self.edit_prediction_provider() else {
 5449            return;
 5450        };
 5451
 5452        let Some((_, buffer, _)) = self
 5453            .buffer
 5454            .read(cx)
 5455            .excerpt_containing(self.selections.newest_anchor().head(), cx)
 5456        else {
 5457            return;
 5458        };
 5459
 5460        let extension = buffer
 5461            .read(cx)
 5462            .file()
 5463            .and_then(|file| Some(file.path().extension()?.to_string_lossy().to_string()));
 5464
 5465        let event_type = match accepted {
 5466            true => "Edit Prediction Accepted",
 5467            false => "Edit Prediction Discarded",
 5468        };
 5469        telemetry::event!(
 5470            event_type,
 5471            provider = provider.name(),
 5472            prediction_id = id,
 5473            suggestion_accepted = accepted,
 5474            file_extension = extension,
 5475        );
 5476    }
 5477
 5478    pub fn has_active_inline_completion(&self) -> bool {
 5479        self.active_inline_completion.is_some()
 5480    }
 5481
 5482    fn take_active_inline_completion(&mut self, cx: &mut Context<Self>) -> bool {
 5483        let Some(active_inline_completion) = self.active_inline_completion.take() else {
 5484            return false;
 5485        };
 5486
 5487        self.splice_inlays(&active_inline_completion.inlay_ids, Default::default(), cx);
 5488        self.clear_highlights::<InlineCompletionHighlight>(cx);
 5489        self.stale_inline_completion_in_menu = Some(active_inline_completion);
 5490        true
 5491    }
 5492
 5493    /// Returns true when we're displaying the edit prediction popover below the cursor
 5494    /// like we are not previewing and the LSP autocomplete menu is visible
 5495    /// or we are in `when_holding_modifier` mode.
 5496    pub fn edit_prediction_visible_in_cursor_popover(&self, has_completion: bool) -> bool {
 5497        if self.edit_prediction_preview_is_active()
 5498            || !self.show_edit_predictions_in_menu()
 5499            || !self.edit_predictions_enabled()
 5500        {
 5501            return false;
 5502        }
 5503
 5504        if self.has_visible_completions_menu() {
 5505            return true;
 5506        }
 5507
 5508        has_completion && self.edit_prediction_requires_modifier()
 5509    }
 5510
 5511    fn handle_modifiers_changed(
 5512        &mut self,
 5513        modifiers: Modifiers,
 5514        position_map: &PositionMap,
 5515        window: &mut Window,
 5516        cx: &mut Context<Self>,
 5517    ) {
 5518        if self.show_edit_predictions_in_menu() {
 5519            self.update_edit_prediction_preview(&modifiers, window, cx);
 5520        }
 5521
 5522        self.update_selection_mode(&modifiers, position_map, window, cx);
 5523
 5524        let mouse_position = window.mouse_position();
 5525        if !position_map.text_hitbox.is_hovered(window) {
 5526            return;
 5527        }
 5528
 5529        self.update_hovered_link(
 5530            position_map.point_for_position(mouse_position),
 5531            &position_map.snapshot,
 5532            modifiers,
 5533            window,
 5534            cx,
 5535        )
 5536    }
 5537
 5538    fn update_selection_mode(
 5539        &mut self,
 5540        modifiers: &Modifiers,
 5541        position_map: &PositionMap,
 5542        window: &mut Window,
 5543        cx: &mut Context<Self>,
 5544    ) {
 5545        if modifiers != &COLUMNAR_SELECTION_MODIFIERS || self.selections.pending.is_none() {
 5546            return;
 5547        }
 5548
 5549        let mouse_position = window.mouse_position();
 5550        let point_for_position = position_map.point_for_position(mouse_position);
 5551        let position = point_for_position.previous_valid;
 5552
 5553        self.select(
 5554            SelectPhase::BeginColumnar {
 5555                position,
 5556                reset: false,
 5557                goal_column: point_for_position.exact_unclipped.column(),
 5558            },
 5559            window,
 5560            cx,
 5561        );
 5562    }
 5563
 5564    fn update_edit_prediction_preview(
 5565        &mut self,
 5566        modifiers: &Modifiers,
 5567        window: &mut Window,
 5568        cx: &mut Context<Self>,
 5569    ) {
 5570        let accept_keybind = self.accept_edit_prediction_keybind(window, cx);
 5571        let Some(accept_keystroke) = accept_keybind.keystroke() else {
 5572            return;
 5573        };
 5574
 5575        if &accept_keystroke.modifiers == modifiers && accept_keystroke.modifiers.modified() {
 5576            if matches!(
 5577                self.edit_prediction_preview,
 5578                EditPredictionPreview::Inactive { .. }
 5579            ) {
 5580                self.edit_prediction_preview = EditPredictionPreview::Active {
 5581                    previous_scroll_position: None,
 5582                    since: Instant::now(),
 5583                };
 5584
 5585                self.update_visible_inline_completion(window, cx);
 5586                cx.notify();
 5587            }
 5588        } else if let EditPredictionPreview::Active {
 5589            previous_scroll_position,
 5590            since,
 5591        } = self.edit_prediction_preview
 5592        {
 5593            if let (Some(previous_scroll_position), Some(position_map)) =
 5594                (previous_scroll_position, self.last_position_map.as_ref())
 5595            {
 5596                self.set_scroll_position(
 5597                    previous_scroll_position
 5598                        .scroll_position(&position_map.snapshot.display_snapshot),
 5599                    window,
 5600                    cx,
 5601                );
 5602            }
 5603
 5604            self.edit_prediction_preview = EditPredictionPreview::Inactive {
 5605                released_too_fast: since.elapsed() < Duration::from_millis(200),
 5606            };
 5607            self.clear_row_highlights::<EditPredictionPreview>();
 5608            self.update_visible_inline_completion(window, cx);
 5609            cx.notify();
 5610        }
 5611    }
 5612
 5613    fn update_visible_inline_completion(
 5614        &mut self,
 5615        _window: &mut Window,
 5616        cx: &mut Context<Self>,
 5617    ) -> Option<()> {
 5618        let selection = self.selections.newest_anchor();
 5619        let cursor = selection.head();
 5620        let multibuffer = self.buffer.read(cx).snapshot(cx);
 5621        let offset_selection = selection.map(|endpoint| endpoint.to_offset(&multibuffer));
 5622        let excerpt_id = cursor.excerpt_id;
 5623
 5624        let show_in_menu = self.show_edit_predictions_in_menu();
 5625        let completions_menu_has_precedence = !show_in_menu
 5626            && (self.context_menu.borrow().is_some()
 5627                || (!self.completion_tasks.is_empty() && !self.has_active_inline_completion()));
 5628
 5629        if completions_menu_has_precedence
 5630            || !offset_selection.is_empty()
 5631            || self
 5632                .active_inline_completion
 5633                .as_ref()
 5634                .map_or(false, |completion| {
 5635                    let invalidation_range = completion.invalidation_range.to_offset(&multibuffer);
 5636                    let invalidation_range = invalidation_range.start..=invalidation_range.end;
 5637                    !invalidation_range.contains(&offset_selection.head())
 5638                })
 5639        {
 5640            self.discard_inline_completion(false, cx);
 5641            return None;
 5642        }
 5643
 5644        self.take_active_inline_completion(cx);
 5645        let Some(provider) = self.edit_prediction_provider() else {
 5646            self.edit_prediction_settings = EditPredictionSettings::Disabled;
 5647            return None;
 5648        };
 5649
 5650        let (buffer, cursor_buffer_position) =
 5651            self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
 5652
 5653        self.edit_prediction_settings =
 5654            self.edit_prediction_settings_at_position(&buffer, cursor_buffer_position, cx);
 5655
 5656        self.edit_prediction_indent_conflict = multibuffer.is_line_whitespace_upto(cursor);
 5657
 5658        if self.edit_prediction_indent_conflict {
 5659            let cursor_point = cursor.to_point(&multibuffer);
 5660
 5661            let indents = multibuffer.suggested_indents(cursor_point.row..cursor_point.row + 1, cx);
 5662
 5663            if let Some((_, indent)) = indents.iter().next() {
 5664                if indent.len == cursor_point.column {
 5665                    self.edit_prediction_indent_conflict = false;
 5666                }
 5667            }
 5668        }
 5669
 5670        let inline_completion = provider.suggest(&buffer, cursor_buffer_position, cx)?;
 5671        let edits = inline_completion
 5672            .edits
 5673            .into_iter()
 5674            .flat_map(|(range, new_text)| {
 5675                let start = multibuffer.anchor_in_excerpt(excerpt_id, range.start)?;
 5676                let end = multibuffer.anchor_in_excerpt(excerpt_id, range.end)?;
 5677                Some((start..end, new_text))
 5678            })
 5679            .collect::<Vec<_>>();
 5680        if edits.is_empty() {
 5681            return None;
 5682        }
 5683
 5684        let first_edit_start = edits.first().unwrap().0.start;
 5685        let first_edit_start_point = first_edit_start.to_point(&multibuffer);
 5686        let edit_start_row = first_edit_start_point.row.saturating_sub(2);
 5687
 5688        let last_edit_end = edits.last().unwrap().0.end;
 5689        let last_edit_end_point = last_edit_end.to_point(&multibuffer);
 5690        let edit_end_row = cmp::min(multibuffer.max_point().row, last_edit_end_point.row + 2);
 5691
 5692        let cursor_row = cursor.to_point(&multibuffer).row;
 5693
 5694        let snapshot = multibuffer.buffer_for_excerpt(excerpt_id).cloned()?;
 5695
 5696        let mut inlay_ids = Vec::new();
 5697        let invalidation_row_range;
 5698        let move_invalidation_row_range = if cursor_row < edit_start_row {
 5699            Some(cursor_row..edit_end_row)
 5700        } else if cursor_row > edit_end_row {
 5701            Some(edit_start_row..cursor_row)
 5702        } else {
 5703            None
 5704        };
 5705        let is_move =
 5706            move_invalidation_row_range.is_some() || self.inline_completions_hidden_for_vim_mode;
 5707        let completion = if is_move {
 5708            invalidation_row_range =
 5709                move_invalidation_row_range.unwrap_or(edit_start_row..edit_end_row);
 5710            let target = first_edit_start;
 5711            InlineCompletion::Move { target, snapshot }
 5712        } else {
 5713            let show_completions_in_buffer = !self.edit_prediction_visible_in_cursor_popover(true)
 5714                && !self.inline_completions_hidden_for_vim_mode;
 5715
 5716            if show_completions_in_buffer {
 5717                if edits
 5718                    .iter()
 5719                    .all(|(range, _)| range.to_offset(&multibuffer).is_empty())
 5720                {
 5721                    let mut inlays = Vec::new();
 5722                    for (range, new_text) in &edits {
 5723                        let inlay = Inlay::inline_completion(
 5724                            post_inc(&mut self.next_inlay_id),
 5725                            range.start,
 5726                            new_text.as_str(),
 5727                        );
 5728                        inlay_ids.push(inlay.id);
 5729                        inlays.push(inlay);
 5730                    }
 5731
 5732                    self.splice_inlays(&[], inlays, cx);
 5733                } else {
 5734                    let background_color = cx.theme().status().deleted_background;
 5735                    self.highlight_text::<InlineCompletionHighlight>(
 5736                        edits.iter().map(|(range, _)| range.clone()).collect(),
 5737                        HighlightStyle {
 5738                            background_color: Some(background_color),
 5739                            ..Default::default()
 5740                        },
 5741                        cx,
 5742                    );
 5743                }
 5744            }
 5745
 5746            invalidation_row_range = edit_start_row..edit_end_row;
 5747
 5748            let display_mode = if all_edits_insertions_or_deletions(&edits, &multibuffer) {
 5749                if provider.show_tab_accept_marker() {
 5750                    EditDisplayMode::TabAccept
 5751                } else {
 5752                    EditDisplayMode::Inline
 5753                }
 5754            } else {
 5755                EditDisplayMode::DiffPopover
 5756            };
 5757
 5758            InlineCompletion::Edit {
 5759                edits,
 5760                edit_preview: inline_completion.edit_preview,
 5761                display_mode,
 5762                snapshot,
 5763            }
 5764        };
 5765
 5766        let invalidation_range = multibuffer
 5767            .anchor_before(Point::new(invalidation_row_range.start, 0))
 5768            ..multibuffer.anchor_after(Point::new(
 5769                invalidation_row_range.end,
 5770                multibuffer.line_len(MultiBufferRow(invalidation_row_range.end)),
 5771            ));
 5772
 5773        self.stale_inline_completion_in_menu = None;
 5774        self.active_inline_completion = Some(InlineCompletionState {
 5775            inlay_ids,
 5776            completion,
 5777            completion_id: inline_completion.id,
 5778            invalidation_range,
 5779        });
 5780
 5781        cx.notify();
 5782
 5783        Some(())
 5784    }
 5785
 5786    pub fn edit_prediction_provider(&self) -> Option<Arc<dyn InlineCompletionProviderHandle>> {
 5787        Some(self.edit_prediction_provider.as_ref()?.provider.clone())
 5788    }
 5789
 5790    fn render_code_actions_indicator(
 5791        &self,
 5792        _style: &EditorStyle,
 5793        row: DisplayRow,
 5794        is_active: bool,
 5795        cx: &mut Context<Self>,
 5796    ) -> Option<IconButton> {
 5797        if self.available_code_actions.is_some() {
 5798            Some(
 5799                IconButton::new("code_actions_indicator", ui::IconName::Bolt)
 5800                    .shape(ui::IconButtonShape::Square)
 5801                    .icon_size(IconSize::XSmall)
 5802                    .icon_color(Color::Muted)
 5803                    .toggle_state(is_active)
 5804                    .tooltip({
 5805                        let focus_handle = self.focus_handle.clone();
 5806                        move |window, cx| {
 5807                            Tooltip::for_action_in(
 5808                                "Toggle Code Actions",
 5809                                &ToggleCodeActions {
 5810                                    deployed_from_indicator: None,
 5811                                },
 5812                                &focus_handle,
 5813                                window,
 5814                                cx,
 5815                            )
 5816                        }
 5817                    })
 5818                    .on_click(cx.listener(move |editor, _e, window, cx| {
 5819                        window.focus(&editor.focus_handle(cx));
 5820                        editor.toggle_code_actions(
 5821                            &ToggleCodeActions {
 5822                                deployed_from_indicator: Some(row),
 5823                            },
 5824                            window,
 5825                            cx,
 5826                        );
 5827                    })),
 5828            )
 5829        } else {
 5830            None
 5831        }
 5832    }
 5833
 5834    fn clear_tasks(&mut self) {
 5835        self.tasks.clear()
 5836    }
 5837
 5838    fn insert_tasks(&mut self, key: (BufferId, BufferRow), value: RunnableTasks) {
 5839        if self.tasks.insert(key, value).is_some() {
 5840            // This case should hopefully be rare, but just in case...
 5841            log::error!("multiple different run targets found on a single line, only the last target will be rendered")
 5842        }
 5843    }
 5844
 5845    fn build_tasks_context(
 5846        project: &Entity<Project>,
 5847        buffer: &Entity<Buffer>,
 5848        buffer_row: u32,
 5849        tasks: &Arc<RunnableTasks>,
 5850        cx: &mut Context<Self>,
 5851    ) -> Task<Option<task::TaskContext>> {
 5852        let position = Point::new(buffer_row, tasks.column);
 5853        let range_start = buffer.read(cx).anchor_at(position, Bias::Right);
 5854        let location = Location {
 5855            buffer: buffer.clone(),
 5856            range: range_start..range_start,
 5857        };
 5858        // Fill in the environmental variables from the tree-sitter captures
 5859        let mut captured_task_variables = TaskVariables::default();
 5860        for (capture_name, value) in tasks.extra_variables.clone() {
 5861            captured_task_variables.insert(
 5862                task::VariableName::Custom(capture_name.into()),
 5863                value.clone(),
 5864            );
 5865        }
 5866        project.update(cx, |project, cx| {
 5867            project.task_store().update(cx, |task_store, cx| {
 5868                task_store.task_context_for_location(captured_task_variables, location, cx)
 5869            })
 5870        })
 5871    }
 5872
 5873    pub fn spawn_nearest_task(
 5874        &mut self,
 5875        action: &SpawnNearestTask,
 5876        window: &mut Window,
 5877        cx: &mut Context<Self>,
 5878    ) {
 5879        let Some((workspace, _)) = self.workspace.clone() else {
 5880            return;
 5881        };
 5882        let Some(project) = self.project.clone() else {
 5883            return;
 5884        };
 5885
 5886        // Try to find a closest, enclosing node using tree-sitter that has a
 5887        // task
 5888        let Some((buffer, buffer_row, tasks)) = self
 5889            .find_enclosing_node_task(cx)
 5890            // Or find the task that's closest in row-distance.
 5891            .or_else(|| self.find_closest_task(cx))
 5892        else {
 5893            return;
 5894        };
 5895
 5896        let reveal_strategy = action.reveal;
 5897        let task_context = Self::build_tasks_context(&project, &buffer, buffer_row, &tasks, cx);
 5898        cx.spawn_in(window, |_, mut cx| async move {
 5899            let context = task_context.await?;
 5900            let (task_source_kind, mut resolved_task) = tasks.resolve(&context).next()?;
 5901
 5902            let resolved = resolved_task.resolved.as_mut()?;
 5903            resolved.reveal = reveal_strategy;
 5904
 5905            workspace
 5906                .update(&mut cx, |workspace, cx| {
 5907                    workspace::tasks::schedule_resolved_task(
 5908                        workspace,
 5909                        task_source_kind,
 5910                        resolved_task,
 5911                        false,
 5912                        cx,
 5913                    );
 5914                })
 5915                .ok()
 5916        })
 5917        .detach();
 5918    }
 5919
 5920    fn find_closest_task(
 5921        &mut self,
 5922        cx: &mut Context<Self>,
 5923    ) -> Option<(Entity<Buffer>, u32, Arc<RunnableTasks>)> {
 5924        let cursor_row = self.selections.newest_adjusted(cx).head().row;
 5925
 5926        let ((buffer_id, row), tasks) = self
 5927            .tasks
 5928            .iter()
 5929            .min_by_key(|((_, row), _)| cursor_row.abs_diff(*row))?;
 5930
 5931        let buffer = self.buffer.read(cx).buffer(*buffer_id)?;
 5932        let tasks = Arc::new(tasks.to_owned());
 5933        Some((buffer, *row, tasks))
 5934    }
 5935
 5936    fn find_enclosing_node_task(
 5937        &mut self,
 5938        cx: &mut Context<Self>,
 5939    ) -> Option<(Entity<Buffer>, u32, Arc<RunnableTasks>)> {
 5940        let snapshot = self.buffer.read(cx).snapshot(cx);
 5941        let offset = self.selections.newest::<usize>(cx).head();
 5942        let excerpt = snapshot.excerpt_containing(offset..offset)?;
 5943        let buffer_id = excerpt.buffer().remote_id();
 5944
 5945        let layer = excerpt.buffer().syntax_layer_at(offset)?;
 5946        let mut cursor = layer.node().walk();
 5947
 5948        while cursor.goto_first_child_for_byte(offset).is_some() {
 5949            if cursor.node().end_byte() == offset {
 5950                cursor.goto_next_sibling();
 5951            }
 5952        }
 5953
 5954        // Ascend to the smallest ancestor that contains the range and has a task.
 5955        loop {
 5956            let node = cursor.node();
 5957            let node_range = node.byte_range();
 5958            let symbol_start_row = excerpt.buffer().offset_to_point(node.start_byte()).row;
 5959
 5960            // Check if this node contains our offset
 5961            if node_range.start <= offset && node_range.end >= offset {
 5962                // If it contains offset, check for task
 5963                if let Some(tasks) = self.tasks.get(&(buffer_id, symbol_start_row)) {
 5964                    let buffer = self.buffer.read(cx).buffer(buffer_id)?;
 5965                    return Some((buffer, symbol_start_row, Arc::new(tasks.to_owned())));
 5966                }
 5967            }
 5968
 5969            if !cursor.goto_parent() {
 5970                break;
 5971            }
 5972        }
 5973        None
 5974    }
 5975
 5976    fn render_run_indicator(
 5977        &self,
 5978        _style: &EditorStyle,
 5979        is_active: bool,
 5980        row: DisplayRow,
 5981        cx: &mut Context<Self>,
 5982    ) -> IconButton {
 5983        IconButton::new(("run_indicator", row.0 as usize), ui::IconName::Play)
 5984            .shape(ui::IconButtonShape::Square)
 5985            .icon_size(IconSize::XSmall)
 5986            .icon_color(Color::Muted)
 5987            .toggle_state(is_active)
 5988            .on_click(cx.listener(move |editor, _e, window, cx| {
 5989                window.focus(&editor.focus_handle(cx));
 5990                editor.toggle_code_actions(
 5991                    &ToggleCodeActions {
 5992                        deployed_from_indicator: Some(row),
 5993                    },
 5994                    window,
 5995                    cx,
 5996                );
 5997            }))
 5998    }
 5999
 6000    pub fn context_menu_visible(&self) -> bool {
 6001        !self.edit_prediction_preview_is_active()
 6002            && self
 6003                .context_menu
 6004                .borrow()
 6005                .as_ref()
 6006                .map_or(false, |menu| menu.visible())
 6007    }
 6008
 6009    fn context_menu_origin(&self) -> Option<ContextMenuOrigin> {
 6010        self.context_menu
 6011            .borrow()
 6012            .as_ref()
 6013            .map(|menu| menu.origin())
 6014    }
 6015
 6016    const EDIT_PREDICTION_POPOVER_PADDING_X: Pixels = Pixels(24.);
 6017    const EDIT_PREDICTION_POPOVER_PADDING_Y: Pixels = Pixels(2.);
 6018
 6019    fn render_edit_prediction_popover(
 6020        &mut self,
 6021        text_bounds: &Bounds<Pixels>,
 6022        content_origin: gpui::Point<Pixels>,
 6023        editor_snapshot: &EditorSnapshot,
 6024        visible_row_range: Range<DisplayRow>,
 6025        scroll_top: f32,
 6026        scroll_bottom: f32,
 6027        line_layouts: &[LineWithInvisibles],
 6028        line_height: Pixels,
 6029        scroll_pixel_position: gpui::Point<Pixels>,
 6030        newest_selection_head: Option<DisplayPoint>,
 6031        editor_width: Pixels,
 6032        style: &EditorStyle,
 6033        window: &mut Window,
 6034        cx: &mut App,
 6035    ) -> Option<(AnyElement, gpui::Point<Pixels>)> {
 6036        let active_inline_completion = self.active_inline_completion.as_ref()?;
 6037
 6038        if self.edit_prediction_visible_in_cursor_popover(true) {
 6039            return None;
 6040        }
 6041
 6042        match &active_inline_completion.completion {
 6043            InlineCompletion::Move { target, .. } => {
 6044                let target_display_point = target.to_display_point(editor_snapshot);
 6045
 6046                if self.edit_prediction_requires_modifier() {
 6047                    if !self.edit_prediction_preview_is_active() {
 6048                        return None;
 6049                    }
 6050
 6051                    self.render_edit_prediction_modifier_jump_popover(
 6052                        text_bounds,
 6053                        content_origin,
 6054                        visible_row_range,
 6055                        line_layouts,
 6056                        line_height,
 6057                        scroll_pixel_position,
 6058                        newest_selection_head,
 6059                        target_display_point,
 6060                        window,
 6061                        cx,
 6062                    )
 6063                } else {
 6064                    self.render_edit_prediction_eager_jump_popover(
 6065                        text_bounds,
 6066                        content_origin,
 6067                        editor_snapshot,
 6068                        visible_row_range,
 6069                        scroll_top,
 6070                        scroll_bottom,
 6071                        line_height,
 6072                        scroll_pixel_position,
 6073                        target_display_point,
 6074                        editor_width,
 6075                        window,
 6076                        cx,
 6077                    )
 6078                }
 6079            }
 6080            InlineCompletion::Edit {
 6081                display_mode: EditDisplayMode::Inline,
 6082                ..
 6083            } => None,
 6084            InlineCompletion::Edit {
 6085                display_mode: EditDisplayMode::TabAccept,
 6086                edits,
 6087                ..
 6088            } => {
 6089                let range = &edits.first()?.0;
 6090                let target_display_point = range.end.to_display_point(editor_snapshot);
 6091
 6092                self.render_edit_prediction_end_of_line_popover(
 6093                    "Accept",
 6094                    editor_snapshot,
 6095                    visible_row_range,
 6096                    target_display_point,
 6097                    line_height,
 6098                    scroll_pixel_position,
 6099                    content_origin,
 6100                    editor_width,
 6101                    window,
 6102                    cx,
 6103                )
 6104            }
 6105            InlineCompletion::Edit {
 6106                edits,
 6107                edit_preview,
 6108                display_mode: EditDisplayMode::DiffPopover,
 6109                snapshot,
 6110            } => self.render_edit_prediction_diff_popover(
 6111                text_bounds,
 6112                content_origin,
 6113                editor_snapshot,
 6114                visible_row_range,
 6115                line_layouts,
 6116                line_height,
 6117                scroll_pixel_position,
 6118                newest_selection_head,
 6119                editor_width,
 6120                style,
 6121                edits,
 6122                edit_preview,
 6123                snapshot,
 6124                window,
 6125                cx,
 6126            ),
 6127        }
 6128    }
 6129
 6130    fn render_edit_prediction_modifier_jump_popover(
 6131        &mut self,
 6132        text_bounds: &Bounds<Pixels>,
 6133        content_origin: gpui::Point<Pixels>,
 6134        visible_row_range: Range<DisplayRow>,
 6135        line_layouts: &[LineWithInvisibles],
 6136        line_height: Pixels,
 6137        scroll_pixel_position: gpui::Point<Pixels>,
 6138        newest_selection_head: Option<DisplayPoint>,
 6139        target_display_point: DisplayPoint,
 6140        window: &mut Window,
 6141        cx: &mut App,
 6142    ) -> Option<(AnyElement, gpui::Point<Pixels>)> {
 6143        let scrolled_content_origin =
 6144            content_origin - gpui::Point::new(scroll_pixel_position.x, Pixels(0.0));
 6145
 6146        const SCROLL_PADDING_Y: Pixels = px(12.);
 6147
 6148        if target_display_point.row() < visible_row_range.start {
 6149            return self.render_edit_prediction_scroll_popover(
 6150                |_| SCROLL_PADDING_Y,
 6151                IconName::ArrowUp,
 6152                visible_row_range,
 6153                line_layouts,
 6154                newest_selection_head,
 6155                scrolled_content_origin,
 6156                window,
 6157                cx,
 6158            );
 6159        } else if target_display_point.row() >= visible_row_range.end {
 6160            return self.render_edit_prediction_scroll_popover(
 6161                |size| text_bounds.size.height - size.height - SCROLL_PADDING_Y,
 6162                IconName::ArrowDown,
 6163                visible_row_range,
 6164                line_layouts,
 6165                newest_selection_head,
 6166                scrolled_content_origin,
 6167                window,
 6168                cx,
 6169            );
 6170        }
 6171
 6172        const POLE_WIDTH: Pixels = px(2.);
 6173
 6174        let line_layout =
 6175            line_layouts.get(target_display_point.row().minus(visible_row_range.start) as usize)?;
 6176        let target_column = target_display_point.column() as usize;
 6177
 6178        let target_x = line_layout.x_for_index(target_column);
 6179        let target_y =
 6180            (target_display_point.row().as_f32() * line_height) - scroll_pixel_position.y;
 6181
 6182        let flag_on_right = target_x < text_bounds.size.width / 2.;
 6183
 6184        let mut border_color = Self::edit_prediction_callout_popover_border_color(cx);
 6185        border_color.l += 0.001;
 6186
 6187        let mut element = v_flex()
 6188            .items_end()
 6189            .when(flag_on_right, |el| el.items_start())
 6190            .child(if flag_on_right {
 6191                self.render_edit_prediction_line_popover("Jump", None, window, cx)?
 6192                    .rounded_bl(px(0.))
 6193                    .rounded_tl(px(0.))
 6194                    .border_l_2()
 6195                    .border_color(border_color)
 6196            } else {
 6197                self.render_edit_prediction_line_popover("Jump", None, window, cx)?
 6198                    .rounded_br(px(0.))
 6199                    .rounded_tr(px(0.))
 6200                    .border_r_2()
 6201                    .border_color(border_color)
 6202            })
 6203            .child(div().w(POLE_WIDTH).bg(border_color).h(line_height))
 6204            .into_any();
 6205
 6206        let size = element.layout_as_root(AvailableSpace::min_size(), window, cx);
 6207
 6208        let mut origin = scrolled_content_origin + point(target_x, target_y)
 6209            - point(
 6210                if flag_on_right {
 6211                    POLE_WIDTH
 6212                } else {
 6213                    size.width - POLE_WIDTH
 6214                },
 6215                size.height - line_height,
 6216            );
 6217
 6218        origin.x = origin.x.max(content_origin.x);
 6219
 6220        element.prepaint_at(origin, window, cx);
 6221
 6222        Some((element, origin))
 6223    }
 6224
 6225    fn render_edit_prediction_scroll_popover(
 6226        &mut self,
 6227        to_y: impl Fn(Size<Pixels>) -> Pixels,
 6228        scroll_icon: IconName,
 6229        visible_row_range: Range<DisplayRow>,
 6230        line_layouts: &[LineWithInvisibles],
 6231        newest_selection_head: Option<DisplayPoint>,
 6232        scrolled_content_origin: gpui::Point<Pixels>,
 6233        window: &mut Window,
 6234        cx: &mut App,
 6235    ) -> Option<(AnyElement, gpui::Point<Pixels>)> {
 6236        let mut element = self
 6237            .render_edit_prediction_line_popover("Scroll", Some(scroll_icon), window, cx)?
 6238            .into_any();
 6239
 6240        let size = element.layout_as_root(AvailableSpace::min_size(), window, cx);
 6241
 6242        let cursor = newest_selection_head?;
 6243        let cursor_row_layout =
 6244            line_layouts.get(cursor.row().minus(visible_row_range.start) as usize)?;
 6245        let cursor_column = cursor.column() as usize;
 6246
 6247        let cursor_character_x = cursor_row_layout.x_for_index(cursor_column);
 6248
 6249        let origin = scrolled_content_origin + point(cursor_character_x, to_y(size));
 6250
 6251        element.prepaint_at(origin, window, cx);
 6252        Some((element, origin))
 6253    }
 6254
 6255    fn render_edit_prediction_eager_jump_popover(
 6256        &mut self,
 6257        text_bounds: &Bounds<Pixels>,
 6258        content_origin: gpui::Point<Pixels>,
 6259        editor_snapshot: &EditorSnapshot,
 6260        visible_row_range: Range<DisplayRow>,
 6261        scroll_top: f32,
 6262        scroll_bottom: f32,
 6263        line_height: Pixels,
 6264        scroll_pixel_position: gpui::Point<Pixels>,
 6265        target_display_point: DisplayPoint,
 6266        editor_width: Pixels,
 6267        window: &mut Window,
 6268        cx: &mut App,
 6269    ) -> Option<(AnyElement, gpui::Point<Pixels>)> {
 6270        if target_display_point.row().as_f32() < scroll_top {
 6271            let mut element = self
 6272                .render_edit_prediction_line_popover(
 6273                    "Jump to Edit",
 6274                    Some(IconName::ArrowUp),
 6275                    window,
 6276                    cx,
 6277                )?
 6278                .into_any();
 6279
 6280            let size = element.layout_as_root(AvailableSpace::min_size(), window, cx);
 6281            let offset = point(
 6282                (text_bounds.size.width - size.width) / 2.,
 6283                Self::EDIT_PREDICTION_POPOVER_PADDING_Y,
 6284            );
 6285
 6286            let origin = text_bounds.origin + offset;
 6287            element.prepaint_at(origin, window, cx);
 6288            Some((element, origin))
 6289        } else if (target_display_point.row().as_f32() + 1.) > scroll_bottom {
 6290            let mut element = self
 6291                .render_edit_prediction_line_popover(
 6292                    "Jump to Edit",
 6293                    Some(IconName::ArrowDown),
 6294                    window,
 6295                    cx,
 6296                )?
 6297                .into_any();
 6298
 6299            let size = element.layout_as_root(AvailableSpace::min_size(), window, cx);
 6300            let offset = point(
 6301                (text_bounds.size.width - size.width) / 2.,
 6302                text_bounds.size.height - size.height - Self::EDIT_PREDICTION_POPOVER_PADDING_Y,
 6303            );
 6304
 6305            let origin = text_bounds.origin + offset;
 6306            element.prepaint_at(origin, window, cx);
 6307            Some((element, origin))
 6308        } else {
 6309            self.render_edit_prediction_end_of_line_popover(
 6310                "Jump to Edit",
 6311                editor_snapshot,
 6312                visible_row_range,
 6313                target_display_point,
 6314                line_height,
 6315                scroll_pixel_position,
 6316                content_origin,
 6317                editor_width,
 6318                window,
 6319                cx,
 6320            )
 6321        }
 6322    }
 6323
 6324    fn render_edit_prediction_end_of_line_popover(
 6325        self: &mut Editor,
 6326        label: &'static str,
 6327        editor_snapshot: &EditorSnapshot,
 6328        visible_row_range: Range<DisplayRow>,
 6329        target_display_point: DisplayPoint,
 6330        line_height: Pixels,
 6331        scroll_pixel_position: gpui::Point<Pixels>,
 6332        content_origin: gpui::Point<Pixels>,
 6333        editor_width: Pixels,
 6334        window: &mut Window,
 6335        cx: &mut App,
 6336    ) -> Option<(AnyElement, gpui::Point<Pixels>)> {
 6337        let target_line_end = DisplayPoint::new(
 6338            target_display_point.row(),
 6339            editor_snapshot.line_len(target_display_point.row()),
 6340        );
 6341
 6342        let mut element = self
 6343            .render_edit_prediction_line_popover(label, None, window, cx)?
 6344            .into_any();
 6345
 6346        let size = element.layout_as_root(AvailableSpace::min_size(), window, cx);
 6347
 6348        let line_origin = self.display_to_pixel_point(target_line_end, editor_snapshot, window)?;
 6349
 6350        let start_point = content_origin - point(scroll_pixel_position.x, Pixels::ZERO);
 6351        let mut origin = start_point
 6352            + line_origin
 6353            + point(Self::EDIT_PREDICTION_POPOVER_PADDING_X, Pixels::ZERO);
 6354        origin.x = origin.x.max(content_origin.x);
 6355
 6356        let max_x = content_origin.x + editor_width - size.width;
 6357
 6358        if origin.x > max_x {
 6359            let offset = line_height + Self::EDIT_PREDICTION_POPOVER_PADDING_Y;
 6360
 6361            let icon = if visible_row_range.contains(&(target_display_point.row() + 2)) {
 6362                origin.y += offset;
 6363                IconName::ArrowUp
 6364            } else {
 6365                origin.y -= offset;
 6366                IconName::ArrowDown
 6367            };
 6368
 6369            element = self
 6370                .render_edit_prediction_line_popover(label, Some(icon), window, cx)?
 6371                .into_any();
 6372
 6373            let size = element.layout_as_root(AvailableSpace::min_size(), window, cx);
 6374
 6375            origin.x = content_origin.x + editor_width - size.width - px(2.);
 6376        }
 6377
 6378        element.prepaint_at(origin, window, cx);
 6379        Some((element, origin))
 6380    }
 6381
 6382    fn render_edit_prediction_diff_popover(
 6383        self: &Editor,
 6384        text_bounds: &Bounds<Pixels>,
 6385        content_origin: gpui::Point<Pixels>,
 6386        editor_snapshot: &EditorSnapshot,
 6387        visible_row_range: Range<DisplayRow>,
 6388        line_layouts: &[LineWithInvisibles],
 6389        line_height: Pixels,
 6390        scroll_pixel_position: gpui::Point<Pixels>,
 6391        newest_selection_head: Option<DisplayPoint>,
 6392        editor_width: Pixels,
 6393        style: &EditorStyle,
 6394        edits: &Vec<(Range<Anchor>, String)>,
 6395        edit_preview: &Option<language::EditPreview>,
 6396        snapshot: &language::BufferSnapshot,
 6397        window: &mut Window,
 6398        cx: &mut App,
 6399    ) -> Option<(AnyElement, gpui::Point<Pixels>)> {
 6400        let edit_start = edits
 6401            .first()
 6402            .unwrap()
 6403            .0
 6404            .start
 6405            .to_display_point(editor_snapshot);
 6406        let edit_end = edits
 6407            .last()
 6408            .unwrap()
 6409            .0
 6410            .end
 6411            .to_display_point(editor_snapshot);
 6412
 6413        let is_visible = visible_row_range.contains(&edit_start.row())
 6414            || visible_row_range.contains(&edit_end.row());
 6415        if !is_visible {
 6416            return None;
 6417        }
 6418
 6419        let highlighted_edits =
 6420            crate::inline_completion_edit_text(&snapshot, edits, edit_preview.as_ref()?, false, cx);
 6421
 6422        let styled_text = highlighted_edits.to_styled_text(&style.text);
 6423        let line_count = highlighted_edits.text.lines().count();
 6424
 6425        const BORDER_WIDTH: Pixels = px(1.);
 6426
 6427        let keybind = self.render_edit_prediction_accept_keybind(window, cx);
 6428        let has_keybind = keybind.is_some();
 6429
 6430        let mut element = h_flex()
 6431            .items_start()
 6432            .child(
 6433                h_flex()
 6434                    .bg(cx.theme().colors().editor_background)
 6435                    .border(BORDER_WIDTH)
 6436                    .shadow_sm()
 6437                    .border_color(cx.theme().colors().border)
 6438                    .rounded_l_lg()
 6439                    .when(line_count > 1, |el| el.rounded_br_lg())
 6440                    .pr_1()
 6441                    .child(styled_text),
 6442            )
 6443            .child(
 6444                h_flex()
 6445                    .h(line_height + BORDER_WIDTH * px(2.))
 6446                    .px_1p5()
 6447                    .gap_1()
 6448                    // Workaround: For some reason, there's a gap if we don't do this
 6449                    .ml(-BORDER_WIDTH)
 6450                    .shadow(smallvec![gpui::BoxShadow {
 6451                        color: gpui::black().opacity(0.05),
 6452                        offset: point(px(1.), px(1.)),
 6453                        blur_radius: px(2.),
 6454                        spread_radius: px(0.),
 6455                    }])
 6456                    .bg(Editor::edit_prediction_line_popover_bg_color(cx))
 6457                    .border(BORDER_WIDTH)
 6458                    .border_color(cx.theme().colors().border)
 6459                    .rounded_r_lg()
 6460                    .id("edit_prediction_diff_popover_keybind")
 6461                    .when(!has_keybind, |el| {
 6462                        let status_colors = cx.theme().status();
 6463
 6464                        el.bg(status_colors.error_background)
 6465                            .border_color(status_colors.error.opacity(0.6))
 6466                            .child(Icon::new(IconName::Info).color(Color::Error))
 6467                            .cursor_default()
 6468                            .hoverable_tooltip(move |_window, cx| {
 6469                                cx.new(|_| MissingEditPredictionKeybindingTooltip).into()
 6470                            })
 6471                    })
 6472                    .children(keybind),
 6473            )
 6474            .into_any();
 6475
 6476        let longest_row =
 6477            editor_snapshot.longest_row_in_range(edit_start.row()..edit_end.row() + 1);
 6478        let longest_line_width = if visible_row_range.contains(&longest_row) {
 6479            line_layouts[(longest_row.0 - visible_row_range.start.0) as usize].width
 6480        } else {
 6481            layout_line(
 6482                longest_row,
 6483                editor_snapshot,
 6484                style,
 6485                editor_width,
 6486                |_| false,
 6487                window,
 6488                cx,
 6489            )
 6490            .width
 6491        };
 6492
 6493        let viewport_bounds =
 6494            Bounds::new(Default::default(), window.viewport_size()).extend(Edges {
 6495                right: -EditorElement::SCROLLBAR_WIDTH,
 6496                ..Default::default()
 6497            });
 6498
 6499        let x_after_longest =
 6500            text_bounds.origin.x + longest_line_width + Self::EDIT_PREDICTION_POPOVER_PADDING_X
 6501                - scroll_pixel_position.x;
 6502
 6503        let element_bounds = element.layout_as_root(AvailableSpace::min_size(), window, cx);
 6504
 6505        // Fully visible if it can be displayed within the window (allow overlapping other
 6506        // panes). However, this is only allowed if the popover starts within text_bounds.
 6507        let can_position_to_the_right = x_after_longest < text_bounds.right()
 6508            && x_after_longest + element_bounds.width < viewport_bounds.right();
 6509
 6510        let mut origin = if can_position_to_the_right {
 6511            point(
 6512                x_after_longest,
 6513                text_bounds.origin.y + edit_start.row().as_f32() * line_height
 6514                    - scroll_pixel_position.y,
 6515            )
 6516        } else {
 6517            let cursor_row = newest_selection_head.map(|head| head.row());
 6518            let above_edit = edit_start
 6519                .row()
 6520                .0
 6521                .checked_sub(line_count as u32)
 6522                .map(DisplayRow);
 6523            let below_edit = Some(edit_end.row() + 1);
 6524            let above_cursor =
 6525                cursor_row.and_then(|row| row.0.checked_sub(line_count as u32).map(DisplayRow));
 6526            let below_cursor = cursor_row.map(|cursor_row| cursor_row + 1);
 6527
 6528            // Place the edit popover adjacent to the edit if there is a location
 6529            // available that is onscreen and does not obscure the cursor. Otherwise,
 6530            // place it adjacent to the cursor.
 6531            let row_target = [above_edit, below_edit, above_cursor, below_cursor]
 6532                .into_iter()
 6533                .flatten()
 6534                .find(|&start_row| {
 6535                    let end_row = start_row + line_count as u32;
 6536                    visible_row_range.contains(&start_row)
 6537                        && visible_row_range.contains(&end_row)
 6538                        && cursor_row.map_or(true, |cursor_row| {
 6539                            !((start_row..end_row).contains(&cursor_row))
 6540                        })
 6541                })?;
 6542
 6543            content_origin
 6544                + point(
 6545                    -scroll_pixel_position.x,
 6546                    row_target.as_f32() * line_height - scroll_pixel_position.y,
 6547                )
 6548        };
 6549
 6550        origin.x -= BORDER_WIDTH;
 6551
 6552        window.defer_draw(element, origin, 1);
 6553
 6554        // Do not return an element, since it will already be drawn due to defer_draw.
 6555        None
 6556    }
 6557
 6558    fn edit_prediction_cursor_popover_height(&self) -> Pixels {
 6559        px(30.)
 6560    }
 6561
 6562    fn current_user_player_color(&self, cx: &mut App) -> PlayerColor {
 6563        if self.read_only(cx) {
 6564            cx.theme().players().read_only()
 6565        } else {
 6566            self.style.as_ref().unwrap().local_player
 6567        }
 6568    }
 6569
 6570    fn render_edit_prediction_accept_keybind(
 6571        &self,
 6572        window: &mut Window,
 6573        cx: &App,
 6574    ) -> Option<AnyElement> {
 6575        let accept_binding = self.accept_edit_prediction_keybind(window, cx);
 6576        let accept_keystroke = accept_binding.keystroke()?;
 6577
 6578        let is_platform_style_mac = PlatformStyle::platform() == PlatformStyle::Mac;
 6579
 6580        let modifiers_color = if accept_keystroke.modifiers == window.modifiers() {
 6581            Color::Accent
 6582        } else {
 6583            Color::Muted
 6584        };
 6585
 6586        h_flex()
 6587            .px_0p5()
 6588            .when(is_platform_style_mac, |parent| parent.gap_0p5())
 6589            .font(theme::ThemeSettings::get_global(cx).buffer_font.clone())
 6590            .text_size(TextSize::XSmall.rems(cx))
 6591            .child(h_flex().children(ui::render_modifiers(
 6592                &accept_keystroke.modifiers,
 6593                PlatformStyle::platform(),
 6594                Some(modifiers_color),
 6595                Some(IconSize::XSmall.rems().into()),
 6596                true,
 6597            )))
 6598            .when(is_platform_style_mac, |parent| {
 6599                parent.child(accept_keystroke.key.clone())
 6600            })
 6601            .when(!is_platform_style_mac, |parent| {
 6602                parent.child(
 6603                    Key::new(
 6604                        util::capitalize(&accept_keystroke.key),
 6605                        Some(Color::Default),
 6606                    )
 6607                    .size(Some(IconSize::XSmall.rems().into())),
 6608                )
 6609            })
 6610            .into_any()
 6611            .into()
 6612    }
 6613
 6614    fn render_edit_prediction_line_popover(
 6615        &self,
 6616        label: impl Into<SharedString>,
 6617        icon: Option<IconName>,
 6618        window: &mut Window,
 6619        cx: &App,
 6620    ) -> Option<Stateful<Div>> {
 6621        let padding_right = if icon.is_some() { px(4.) } else { px(8.) };
 6622
 6623        let keybind = self.render_edit_prediction_accept_keybind(window, cx);
 6624        let has_keybind = keybind.is_some();
 6625
 6626        let result = h_flex()
 6627            .id("ep-line-popover")
 6628            .py_0p5()
 6629            .pl_1()
 6630            .pr(padding_right)
 6631            .gap_1()
 6632            .rounded_md()
 6633            .border_1()
 6634            .bg(Self::edit_prediction_line_popover_bg_color(cx))
 6635            .border_color(Self::edit_prediction_callout_popover_border_color(cx))
 6636            .shadow_sm()
 6637            .when(!has_keybind, |el| {
 6638                let status_colors = cx.theme().status();
 6639
 6640                el.bg(status_colors.error_background)
 6641                    .border_color(status_colors.error.opacity(0.6))
 6642                    .pl_2()
 6643                    .child(Icon::new(IconName::ZedPredictError).color(Color::Error))
 6644                    .cursor_default()
 6645                    .hoverable_tooltip(move |_window, cx| {
 6646                        cx.new(|_| MissingEditPredictionKeybindingTooltip).into()
 6647                    })
 6648            })
 6649            .children(keybind)
 6650            .child(
 6651                Label::new(label)
 6652                    .size(LabelSize::Small)
 6653                    .when(!has_keybind, |el| {
 6654                        el.color(cx.theme().status().error.into()).strikethrough()
 6655                    }),
 6656            )
 6657            .when(!has_keybind, |el| {
 6658                el.child(
 6659                    h_flex().ml_1().child(
 6660                        Icon::new(IconName::Info)
 6661                            .size(IconSize::Small)
 6662                            .color(cx.theme().status().error.into()),
 6663                    ),
 6664                )
 6665            })
 6666            .when_some(icon, |element, icon| {
 6667                element.child(
 6668                    div()
 6669                        .mt(px(1.5))
 6670                        .child(Icon::new(icon).size(IconSize::Small)),
 6671                )
 6672            });
 6673
 6674        Some(result)
 6675    }
 6676
 6677    fn edit_prediction_line_popover_bg_color(cx: &App) -> Hsla {
 6678        let accent_color = cx.theme().colors().text_accent;
 6679        let editor_bg_color = cx.theme().colors().editor_background;
 6680        editor_bg_color.blend(accent_color.opacity(0.1))
 6681    }
 6682
 6683    fn edit_prediction_callout_popover_border_color(cx: &App) -> Hsla {
 6684        let accent_color = cx.theme().colors().text_accent;
 6685        let editor_bg_color = cx.theme().colors().editor_background;
 6686        editor_bg_color.blend(accent_color.opacity(0.6))
 6687    }
 6688
 6689    fn render_edit_prediction_cursor_popover(
 6690        &self,
 6691        min_width: Pixels,
 6692        max_width: Pixels,
 6693        cursor_point: Point,
 6694        style: &EditorStyle,
 6695        accept_keystroke: Option<&gpui::Keystroke>,
 6696        _window: &Window,
 6697        cx: &mut Context<Editor>,
 6698    ) -> Option<AnyElement> {
 6699        let provider = self.edit_prediction_provider.as_ref()?;
 6700
 6701        if provider.provider.needs_terms_acceptance(cx) {
 6702            return Some(
 6703                h_flex()
 6704                    .min_w(min_width)
 6705                    .flex_1()
 6706                    .px_2()
 6707                    .py_1()
 6708                    .gap_3()
 6709                    .elevation_2(cx)
 6710                    .hover(|style| style.bg(cx.theme().colors().element_hover))
 6711                    .id("accept-terms")
 6712                    .cursor_pointer()
 6713                    .on_mouse_down(MouseButton::Left, |_, window, _| window.prevent_default())
 6714                    .on_click(cx.listener(|this, _event, window, cx| {
 6715                        cx.stop_propagation();
 6716                        this.report_editor_event("Edit Prediction Provider ToS Clicked", None, cx);
 6717                        window.dispatch_action(
 6718                            zed_actions::OpenZedPredictOnboarding.boxed_clone(),
 6719                            cx,
 6720                        );
 6721                    }))
 6722                    .child(
 6723                        h_flex()
 6724                            .flex_1()
 6725                            .gap_2()
 6726                            .child(Icon::new(IconName::ZedPredict))
 6727                            .child(Label::new("Accept Terms of Service"))
 6728                            .child(div().w_full())
 6729                            .child(
 6730                                Icon::new(IconName::ArrowUpRight)
 6731                                    .color(Color::Muted)
 6732                                    .size(IconSize::Small),
 6733                            )
 6734                            .into_any_element(),
 6735                    )
 6736                    .into_any(),
 6737            );
 6738        }
 6739
 6740        let is_refreshing = provider.provider.is_refreshing(cx);
 6741
 6742        fn pending_completion_container() -> Div {
 6743            h_flex()
 6744                .h_full()
 6745                .flex_1()
 6746                .gap_2()
 6747                .child(Icon::new(IconName::ZedPredict))
 6748        }
 6749
 6750        let completion = match &self.active_inline_completion {
 6751            Some(prediction) => {
 6752                if !self.has_visible_completions_menu() {
 6753                    const RADIUS: Pixels = px(6.);
 6754                    const BORDER_WIDTH: Pixels = px(1.);
 6755
 6756                    return Some(
 6757                        h_flex()
 6758                            .elevation_2(cx)
 6759                            .border(BORDER_WIDTH)
 6760                            .border_color(cx.theme().colors().border)
 6761                            .when(accept_keystroke.is_none(), |el| {
 6762                                el.border_color(cx.theme().status().error)
 6763                            })
 6764                            .rounded(RADIUS)
 6765                            .rounded_tl(px(0.))
 6766                            .overflow_hidden()
 6767                            .child(div().px_1p5().child(match &prediction.completion {
 6768                                InlineCompletion::Move { target, snapshot } => {
 6769                                    use text::ToPoint as _;
 6770                                    if target.text_anchor.to_point(&snapshot).row > cursor_point.row
 6771                                    {
 6772                                        Icon::new(IconName::ZedPredictDown)
 6773                                    } else {
 6774                                        Icon::new(IconName::ZedPredictUp)
 6775                                    }
 6776                                }
 6777                                InlineCompletion::Edit { .. } => Icon::new(IconName::ZedPredict),
 6778                            }))
 6779                            .child(
 6780                                h_flex()
 6781                                    .gap_1()
 6782                                    .py_1()
 6783                                    .px_2()
 6784                                    .rounded_r(RADIUS - BORDER_WIDTH)
 6785                                    .border_l_1()
 6786                                    .border_color(cx.theme().colors().border)
 6787                                    .bg(Self::edit_prediction_line_popover_bg_color(cx))
 6788                                    .when(self.edit_prediction_preview.released_too_fast(), |el| {
 6789                                        el.child(
 6790                                            Label::new("Hold")
 6791                                                .size(LabelSize::Small)
 6792                                                .when(accept_keystroke.is_none(), |el| {
 6793                                                    el.strikethrough()
 6794                                                })
 6795                                                .line_height_style(LineHeightStyle::UiLabel),
 6796                                        )
 6797                                    })
 6798                                    .id("edit_prediction_cursor_popover_keybind")
 6799                                    .when(accept_keystroke.is_none(), |el| {
 6800                                        let status_colors = cx.theme().status();
 6801
 6802                                        el.bg(status_colors.error_background)
 6803                                            .border_color(status_colors.error.opacity(0.6))
 6804                                            .child(Icon::new(IconName::Info).color(Color::Error))
 6805                                            .cursor_default()
 6806                                            .hoverable_tooltip(move |_window, cx| {
 6807                                                cx.new(|_| MissingEditPredictionKeybindingTooltip)
 6808                                                    .into()
 6809                                            })
 6810                                    })
 6811                                    .when_some(
 6812                                        accept_keystroke.as_ref(),
 6813                                        |el, accept_keystroke| {
 6814                                            el.child(h_flex().children(ui::render_modifiers(
 6815                                                &accept_keystroke.modifiers,
 6816                                                PlatformStyle::platform(),
 6817                                                Some(Color::Default),
 6818                                                Some(IconSize::XSmall.rems().into()),
 6819                                                false,
 6820                                            )))
 6821                                        },
 6822                                    ),
 6823                            )
 6824                            .into_any(),
 6825                    );
 6826                }
 6827
 6828                self.render_edit_prediction_cursor_popover_preview(
 6829                    prediction,
 6830                    cursor_point,
 6831                    style,
 6832                    cx,
 6833                )?
 6834            }
 6835
 6836            None if is_refreshing => match &self.stale_inline_completion_in_menu {
 6837                Some(stale_completion) => self.render_edit_prediction_cursor_popover_preview(
 6838                    stale_completion,
 6839                    cursor_point,
 6840                    style,
 6841                    cx,
 6842                )?,
 6843
 6844                None => {
 6845                    pending_completion_container().child(Label::new("...").size(LabelSize::Small))
 6846                }
 6847            },
 6848
 6849            None => pending_completion_container().child(Label::new("No Prediction")),
 6850        };
 6851
 6852        let completion = if is_refreshing {
 6853            completion
 6854                .with_animation(
 6855                    "loading-completion",
 6856                    Animation::new(Duration::from_secs(2))
 6857                        .repeat()
 6858                        .with_easing(pulsating_between(0.4, 0.8)),
 6859                    |label, delta| label.opacity(delta),
 6860                )
 6861                .into_any_element()
 6862        } else {
 6863            completion.into_any_element()
 6864        };
 6865
 6866        let has_completion = self.active_inline_completion.is_some();
 6867
 6868        let is_platform_style_mac = PlatformStyle::platform() == PlatformStyle::Mac;
 6869        Some(
 6870            h_flex()
 6871                .min_w(min_width)
 6872                .max_w(max_width)
 6873                .flex_1()
 6874                .elevation_2(cx)
 6875                .border_color(cx.theme().colors().border)
 6876                .child(
 6877                    div()
 6878                        .flex_1()
 6879                        .py_1()
 6880                        .px_2()
 6881                        .overflow_hidden()
 6882                        .child(completion),
 6883                )
 6884                .when_some(accept_keystroke, |el, accept_keystroke| {
 6885                    if !accept_keystroke.modifiers.modified() {
 6886                        return el;
 6887                    }
 6888
 6889                    el.child(
 6890                        h_flex()
 6891                            .h_full()
 6892                            .border_l_1()
 6893                            .rounded_r_lg()
 6894                            .border_color(cx.theme().colors().border)
 6895                            .bg(Self::edit_prediction_line_popover_bg_color(cx))
 6896                            .gap_1()
 6897                            .py_1()
 6898                            .px_2()
 6899                            .child(
 6900                                h_flex()
 6901                                    .font(theme::ThemeSettings::get_global(cx).buffer_font.clone())
 6902                                    .when(is_platform_style_mac, |parent| parent.gap_1())
 6903                                    .child(h_flex().children(ui::render_modifiers(
 6904                                        &accept_keystroke.modifiers,
 6905                                        PlatformStyle::platform(),
 6906                                        Some(if !has_completion {
 6907                                            Color::Muted
 6908                                        } else {
 6909                                            Color::Default
 6910                                        }),
 6911                                        None,
 6912                                        false,
 6913                                    ))),
 6914                            )
 6915                            .child(Label::new("Preview").into_any_element())
 6916                            .opacity(if has_completion { 1.0 } else { 0.4 }),
 6917                    )
 6918                })
 6919                .into_any(),
 6920        )
 6921    }
 6922
 6923    fn render_edit_prediction_cursor_popover_preview(
 6924        &self,
 6925        completion: &InlineCompletionState,
 6926        cursor_point: Point,
 6927        style: &EditorStyle,
 6928        cx: &mut Context<Editor>,
 6929    ) -> Option<Div> {
 6930        use text::ToPoint as _;
 6931
 6932        fn render_relative_row_jump(
 6933            prefix: impl Into<String>,
 6934            current_row: u32,
 6935            target_row: u32,
 6936        ) -> Div {
 6937            let (row_diff, arrow) = if target_row < current_row {
 6938                (current_row - target_row, IconName::ArrowUp)
 6939            } else {
 6940                (target_row - current_row, IconName::ArrowDown)
 6941            };
 6942
 6943            h_flex()
 6944                .child(
 6945                    Label::new(format!("{}{}", prefix.into(), row_diff))
 6946                        .color(Color::Muted)
 6947                        .size(LabelSize::Small),
 6948                )
 6949                .child(Icon::new(arrow).color(Color::Muted).size(IconSize::Small))
 6950        }
 6951
 6952        match &completion.completion {
 6953            InlineCompletion::Move {
 6954                target, snapshot, ..
 6955            } => Some(
 6956                h_flex()
 6957                    .px_2()
 6958                    .gap_2()
 6959                    .flex_1()
 6960                    .child(
 6961                        if target.text_anchor.to_point(&snapshot).row > cursor_point.row {
 6962                            Icon::new(IconName::ZedPredictDown)
 6963                        } else {
 6964                            Icon::new(IconName::ZedPredictUp)
 6965                        },
 6966                    )
 6967                    .child(Label::new("Jump to Edit")),
 6968            ),
 6969
 6970            InlineCompletion::Edit {
 6971                edits,
 6972                edit_preview,
 6973                snapshot,
 6974                display_mode: _,
 6975            } => {
 6976                let first_edit_row = edits.first()?.0.start.text_anchor.to_point(&snapshot).row;
 6977
 6978                let (highlighted_edits, has_more_lines) = crate::inline_completion_edit_text(
 6979                    &snapshot,
 6980                    &edits,
 6981                    edit_preview.as_ref()?,
 6982                    true,
 6983                    cx,
 6984                )
 6985                .first_line_preview();
 6986
 6987                let styled_text = gpui::StyledText::new(highlighted_edits.text)
 6988                    .with_default_highlights(&style.text, highlighted_edits.highlights);
 6989
 6990                let preview = h_flex()
 6991                    .gap_1()
 6992                    .min_w_16()
 6993                    .child(styled_text)
 6994                    .when(has_more_lines, |parent| parent.child(""));
 6995
 6996                let left = if first_edit_row != cursor_point.row {
 6997                    render_relative_row_jump("", cursor_point.row, first_edit_row)
 6998                        .into_any_element()
 6999                } else {
 7000                    Icon::new(IconName::ZedPredict).into_any_element()
 7001                };
 7002
 7003                Some(
 7004                    h_flex()
 7005                        .h_full()
 7006                        .flex_1()
 7007                        .gap_2()
 7008                        .pr_1()
 7009                        .overflow_x_hidden()
 7010                        .font(theme::ThemeSettings::get_global(cx).buffer_font.clone())
 7011                        .child(left)
 7012                        .child(preview),
 7013                )
 7014            }
 7015        }
 7016    }
 7017
 7018    fn render_context_menu(
 7019        &self,
 7020        style: &EditorStyle,
 7021        max_height_in_lines: u32,
 7022        y_flipped: bool,
 7023        window: &mut Window,
 7024        cx: &mut Context<Editor>,
 7025    ) -> Option<AnyElement> {
 7026        let menu = self.context_menu.borrow();
 7027        let menu = menu.as_ref()?;
 7028        if !menu.visible() {
 7029            return None;
 7030        };
 7031        Some(menu.render(style, max_height_in_lines, y_flipped, window, cx))
 7032    }
 7033
 7034    fn render_context_menu_aside(
 7035        &mut self,
 7036        max_size: Size<Pixels>,
 7037        window: &mut Window,
 7038        cx: &mut Context<Editor>,
 7039    ) -> Option<AnyElement> {
 7040        self.context_menu.borrow_mut().as_mut().and_then(|menu| {
 7041            if menu.visible() {
 7042                menu.render_aside(self, max_size, window, cx)
 7043            } else {
 7044                None
 7045            }
 7046        })
 7047    }
 7048
 7049    fn hide_context_menu(
 7050        &mut self,
 7051        window: &mut Window,
 7052        cx: &mut Context<Self>,
 7053    ) -> Option<CodeContextMenu> {
 7054        cx.notify();
 7055        self.completion_tasks.clear();
 7056        let context_menu = self.context_menu.borrow_mut().take();
 7057        self.stale_inline_completion_in_menu.take();
 7058        self.update_visible_inline_completion(window, cx);
 7059        context_menu
 7060    }
 7061
 7062    fn show_snippet_choices(
 7063        &mut self,
 7064        choices: &Vec<String>,
 7065        selection: Range<Anchor>,
 7066        cx: &mut Context<Self>,
 7067    ) {
 7068        if selection.start.buffer_id.is_none() {
 7069            return;
 7070        }
 7071        let buffer_id = selection.start.buffer_id.unwrap();
 7072        let buffer = self.buffer().read(cx).buffer(buffer_id);
 7073        let id = post_inc(&mut self.next_completion_id);
 7074
 7075        if let Some(buffer) = buffer {
 7076            *self.context_menu.borrow_mut() = Some(CodeContextMenu::Completions(
 7077                CompletionsMenu::new_snippet_choices(id, true, choices, selection, buffer),
 7078            ));
 7079        }
 7080    }
 7081
 7082    pub fn insert_snippet(
 7083        &mut self,
 7084        insertion_ranges: &[Range<usize>],
 7085        snippet: Snippet,
 7086        window: &mut Window,
 7087        cx: &mut Context<Self>,
 7088    ) -> Result<()> {
 7089        struct Tabstop<T> {
 7090            is_end_tabstop: bool,
 7091            ranges: Vec<Range<T>>,
 7092            choices: Option<Vec<String>>,
 7093        }
 7094
 7095        let tabstops = self.buffer.update(cx, |buffer, cx| {
 7096            let snippet_text: Arc<str> = snippet.text.clone().into();
 7097            buffer.edit(
 7098                insertion_ranges
 7099                    .iter()
 7100                    .cloned()
 7101                    .map(|range| (range, snippet_text.clone())),
 7102                Some(AutoindentMode::EachLine),
 7103                cx,
 7104            );
 7105
 7106            let snapshot = &*buffer.read(cx);
 7107            let snippet = &snippet;
 7108            snippet
 7109                .tabstops
 7110                .iter()
 7111                .map(|tabstop| {
 7112                    let is_end_tabstop = tabstop.ranges.first().map_or(false, |tabstop| {
 7113                        tabstop.is_empty() && tabstop.start == snippet.text.len() as isize
 7114                    });
 7115                    let mut tabstop_ranges = tabstop
 7116                        .ranges
 7117                        .iter()
 7118                        .flat_map(|tabstop_range| {
 7119                            let mut delta = 0_isize;
 7120                            insertion_ranges.iter().map(move |insertion_range| {
 7121                                let insertion_start = insertion_range.start as isize + delta;
 7122                                delta +=
 7123                                    snippet.text.len() as isize - insertion_range.len() as isize;
 7124
 7125                                let start = ((insertion_start + tabstop_range.start) as usize)
 7126                                    .min(snapshot.len());
 7127                                let end = ((insertion_start + tabstop_range.end) as usize)
 7128                                    .min(snapshot.len());
 7129                                snapshot.anchor_before(start)..snapshot.anchor_after(end)
 7130                            })
 7131                        })
 7132                        .collect::<Vec<_>>();
 7133                    tabstop_ranges.sort_unstable_by(|a, b| a.start.cmp(&b.start, snapshot));
 7134
 7135                    Tabstop {
 7136                        is_end_tabstop,
 7137                        ranges: tabstop_ranges,
 7138                        choices: tabstop.choices.clone(),
 7139                    }
 7140                })
 7141                .collect::<Vec<_>>()
 7142        });
 7143        if let Some(tabstop) = tabstops.first() {
 7144            self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 7145                s.select_ranges(tabstop.ranges.iter().cloned());
 7146            });
 7147
 7148            if let Some(choices) = &tabstop.choices {
 7149                if let Some(selection) = tabstop.ranges.first() {
 7150                    self.show_snippet_choices(choices, selection.clone(), cx)
 7151                }
 7152            }
 7153
 7154            // If we're already at the last tabstop and it's at the end of the snippet,
 7155            // we're done, we don't need to keep the state around.
 7156            if !tabstop.is_end_tabstop {
 7157                let choices = tabstops
 7158                    .iter()
 7159                    .map(|tabstop| tabstop.choices.clone())
 7160                    .collect();
 7161
 7162                let ranges = tabstops
 7163                    .into_iter()
 7164                    .map(|tabstop| tabstop.ranges)
 7165                    .collect::<Vec<_>>();
 7166
 7167                self.snippet_stack.push(SnippetState {
 7168                    active_index: 0,
 7169                    ranges,
 7170                    choices,
 7171                });
 7172            }
 7173
 7174            // Check whether the just-entered snippet ends with an auto-closable bracket.
 7175            if self.autoclose_regions.is_empty() {
 7176                let snapshot = self.buffer.read(cx).snapshot(cx);
 7177                for selection in &mut self.selections.all::<Point>(cx) {
 7178                    let selection_head = selection.head();
 7179                    let Some(scope) = snapshot.language_scope_at(selection_head) else {
 7180                        continue;
 7181                    };
 7182
 7183                    let mut bracket_pair = None;
 7184                    let next_chars = snapshot.chars_at(selection_head).collect::<String>();
 7185                    let prev_chars = snapshot
 7186                        .reversed_chars_at(selection_head)
 7187                        .collect::<String>();
 7188                    for (pair, enabled) in scope.brackets() {
 7189                        if enabled
 7190                            && pair.close
 7191                            && prev_chars.starts_with(pair.start.as_str())
 7192                            && next_chars.starts_with(pair.end.as_str())
 7193                        {
 7194                            bracket_pair = Some(pair.clone());
 7195                            break;
 7196                        }
 7197                    }
 7198                    if let Some(pair) = bracket_pair {
 7199                        let start = snapshot.anchor_after(selection_head);
 7200                        let end = snapshot.anchor_after(selection_head);
 7201                        self.autoclose_regions.push(AutocloseRegion {
 7202                            selection_id: selection.id,
 7203                            range: start..end,
 7204                            pair,
 7205                        });
 7206                    }
 7207                }
 7208            }
 7209        }
 7210        Ok(())
 7211    }
 7212
 7213    pub fn move_to_next_snippet_tabstop(
 7214        &mut self,
 7215        window: &mut Window,
 7216        cx: &mut Context<Self>,
 7217    ) -> bool {
 7218        self.move_to_snippet_tabstop(Bias::Right, window, cx)
 7219    }
 7220
 7221    pub fn move_to_prev_snippet_tabstop(
 7222        &mut self,
 7223        window: &mut Window,
 7224        cx: &mut Context<Self>,
 7225    ) -> bool {
 7226        self.move_to_snippet_tabstop(Bias::Left, window, cx)
 7227    }
 7228
 7229    pub fn move_to_snippet_tabstop(
 7230        &mut self,
 7231        bias: Bias,
 7232        window: &mut Window,
 7233        cx: &mut Context<Self>,
 7234    ) -> bool {
 7235        if let Some(mut snippet) = self.snippet_stack.pop() {
 7236            match bias {
 7237                Bias::Left => {
 7238                    if snippet.active_index > 0 {
 7239                        snippet.active_index -= 1;
 7240                    } else {
 7241                        self.snippet_stack.push(snippet);
 7242                        return false;
 7243                    }
 7244                }
 7245                Bias::Right => {
 7246                    if snippet.active_index + 1 < snippet.ranges.len() {
 7247                        snippet.active_index += 1;
 7248                    } else {
 7249                        self.snippet_stack.push(snippet);
 7250                        return false;
 7251                    }
 7252                }
 7253            }
 7254            if let Some(current_ranges) = snippet.ranges.get(snippet.active_index) {
 7255                self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 7256                    s.select_anchor_ranges(current_ranges.iter().cloned())
 7257                });
 7258
 7259                if let Some(choices) = &snippet.choices[snippet.active_index] {
 7260                    if let Some(selection) = current_ranges.first() {
 7261                        self.show_snippet_choices(&choices, selection.clone(), cx);
 7262                    }
 7263                }
 7264
 7265                // If snippet state is not at the last tabstop, push it back on the stack
 7266                if snippet.active_index + 1 < snippet.ranges.len() {
 7267                    self.snippet_stack.push(snippet);
 7268                }
 7269                return true;
 7270            }
 7271        }
 7272
 7273        false
 7274    }
 7275
 7276    pub fn clear(&mut self, window: &mut Window, cx: &mut Context<Self>) {
 7277        self.transact(window, cx, |this, window, cx| {
 7278            this.select_all(&SelectAll, window, cx);
 7279            this.insert("", window, cx);
 7280        });
 7281    }
 7282
 7283    pub fn backspace(&mut self, _: &Backspace, window: &mut Window, cx: &mut Context<Self>) {
 7284        self.transact(window, cx, |this, window, cx| {
 7285            this.select_autoclose_pair(window, cx);
 7286            let mut linked_ranges = HashMap::<_, Vec<_>>::default();
 7287            if !this.linked_edit_ranges.is_empty() {
 7288                let selections = this.selections.all::<MultiBufferPoint>(cx);
 7289                let snapshot = this.buffer.read(cx).snapshot(cx);
 7290
 7291                for selection in selections.iter() {
 7292                    let selection_start = snapshot.anchor_before(selection.start).text_anchor;
 7293                    let selection_end = snapshot.anchor_after(selection.end).text_anchor;
 7294                    if selection_start.buffer_id != selection_end.buffer_id {
 7295                        continue;
 7296                    }
 7297                    if let Some(ranges) =
 7298                        this.linked_editing_ranges_for(selection_start..selection_end, cx)
 7299                    {
 7300                        for (buffer, entries) in ranges {
 7301                            linked_ranges.entry(buffer).or_default().extend(entries);
 7302                        }
 7303                    }
 7304                }
 7305            }
 7306
 7307            let mut selections = this.selections.all::<MultiBufferPoint>(cx);
 7308            if !this.selections.line_mode {
 7309                let display_map = this.display_map.update(cx, |map, cx| map.snapshot(cx));
 7310                for selection in &mut selections {
 7311                    if selection.is_empty() {
 7312                        let old_head = selection.head();
 7313                        let mut new_head =
 7314                            movement::left(&display_map, old_head.to_display_point(&display_map))
 7315                                .to_point(&display_map);
 7316                        if let Some((buffer, line_buffer_range)) = display_map
 7317                            .buffer_snapshot
 7318                            .buffer_line_for_row(MultiBufferRow(old_head.row))
 7319                        {
 7320                            let indent_size =
 7321                                buffer.indent_size_for_line(line_buffer_range.start.row);
 7322                            let indent_len = match indent_size.kind {
 7323                                IndentKind::Space => {
 7324                                    buffer.settings_at(line_buffer_range.start, cx).tab_size
 7325                                }
 7326                                IndentKind::Tab => NonZeroU32::new(1).unwrap(),
 7327                            };
 7328                            if old_head.column <= indent_size.len && old_head.column > 0 {
 7329                                let indent_len = indent_len.get();
 7330                                new_head = cmp::min(
 7331                                    new_head,
 7332                                    MultiBufferPoint::new(
 7333                                        old_head.row,
 7334                                        ((old_head.column - 1) / indent_len) * indent_len,
 7335                                    ),
 7336                                );
 7337                            }
 7338                        }
 7339
 7340                        selection.set_head(new_head, SelectionGoal::None);
 7341                    }
 7342                }
 7343            }
 7344
 7345            this.signature_help_state.set_backspace_pressed(true);
 7346            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 7347                s.select(selections)
 7348            });
 7349            this.insert("", window, cx);
 7350            let empty_str: Arc<str> = Arc::from("");
 7351            for (buffer, edits) in linked_ranges {
 7352                let snapshot = buffer.read(cx).snapshot();
 7353                use text::ToPoint as TP;
 7354
 7355                let edits = edits
 7356                    .into_iter()
 7357                    .map(|range| {
 7358                        let end_point = TP::to_point(&range.end, &snapshot);
 7359                        let mut start_point = TP::to_point(&range.start, &snapshot);
 7360
 7361                        if end_point == start_point {
 7362                            let offset = text::ToOffset::to_offset(&range.start, &snapshot)
 7363                                .saturating_sub(1);
 7364                            start_point =
 7365                                snapshot.clip_point(TP::to_point(&offset, &snapshot), Bias::Left);
 7366                        };
 7367
 7368                        (start_point..end_point, empty_str.clone())
 7369                    })
 7370                    .sorted_by_key(|(range, _)| range.start)
 7371                    .collect::<Vec<_>>();
 7372                buffer.update(cx, |this, cx| {
 7373                    this.edit(edits, None, cx);
 7374                })
 7375            }
 7376            this.refresh_inline_completion(true, false, window, cx);
 7377            linked_editing_ranges::refresh_linked_ranges(this, window, cx);
 7378        });
 7379    }
 7380
 7381    pub fn delete(&mut self, _: &Delete, window: &mut Window, cx: &mut Context<Self>) {
 7382        self.transact(window, cx, |this, window, cx| {
 7383            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 7384                let line_mode = s.line_mode;
 7385                s.move_with(|map, selection| {
 7386                    if selection.is_empty() && !line_mode {
 7387                        let cursor = movement::right(map, selection.head());
 7388                        selection.end = cursor;
 7389                        selection.reversed = true;
 7390                        selection.goal = SelectionGoal::None;
 7391                    }
 7392                })
 7393            });
 7394            this.insert("", window, cx);
 7395            this.refresh_inline_completion(true, false, window, cx);
 7396        });
 7397    }
 7398
 7399    pub fn backtab(&mut self, _: &Backtab, window: &mut Window, cx: &mut Context<Self>) {
 7400        if self.move_to_prev_snippet_tabstop(window, cx) {
 7401            return;
 7402        }
 7403
 7404        self.outdent(&Outdent, window, cx);
 7405    }
 7406
 7407    pub fn tab(&mut self, _: &Tab, window: &mut Window, cx: &mut Context<Self>) {
 7408        if self.move_to_next_snippet_tabstop(window, cx) || self.read_only(cx) {
 7409            return;
 7410        }
 7411
 7412        let mut selections = self.selections.all_adjusted(cx);
 7413        let buffer = self.buffer.read(cx);
 7414        let snapshot = buffer.snapshot(cx);
 7415        let rows_iter = selections.iter().map(|s| s.head().row);
 7416        let suggested_indents = snapshot.suggested_indents(rows_iter, cx);
 7417
 7418        let mut edits = Vec::new();
 7419        let mut prev_edited_row = 0;
 7420        let mut row_delta = 0;
 7421        for selection in &mut selections {
 7422            if selection.start.row != prev_edited_row {
 7423                row_delta = 0;
 7424            }
 7425            prev_edited_row = selection.end.row;
 7426
 7427            // If the selection is non-empty, then increase the indentation of the selected lines.
 7428            if !selection.is_empty() {
 7429                row_delta =
 7430                    Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
 7431                continue;
 7432            }
 7433
 7434            // If the selection is empty and the cursor is in the leading whitespace before the
 7435            // suggested indentation, then auto-indent the line.
 7436            let cursor = selection.head();
 7437            let current_indent = snapshot.indent_size_for_line(MultiBufferRow(cursor.row));
 7438            if let Some(suggested_indent) =
 7439                suggested_indents.get(&MultiBufferRow(cursor.row)).copied()
 7440            {
 7441                if cursor.column < suggested_indent.len
 7442                    && cursor.column <= current_indent.len
 7443                    && current_indent.len <= suggested_indent.len
 7444                {
 7445                    selection.start = Point::new(cursor.row, suggested_indent.len);
 7446                    selection.end = selection.start;
 7447                    if row_delta == 0 {
 7448                        edits.extend(Buffer::edit_for_indent_size_adjustment(
 7449                            cursor.row,
 7450                            current_indent,
 7451                            suggested_indent,
 7452                        ));
 7453                        row_delta = suggested_indent.len - current_indent.len;
 7454                    }
 7455                    continue;
 7456                }
 7457            }
 7458
 7459            // Otherwise, insert a hard or soft tab.
 7460            let settings = buffer.language_settings_at(cursor, cx);
 7461            let tab_size = if settings.hard_tabs {
 7462                IndentSize::tab()
 7463            } else {
 7464                let tab_size = settings.tab_size.get();
 7465                let char_column = snapshot
 7466                    .text_for_range(Point::new(cursor.row, 0)..cursor)
 7467                    .flat_map(str::chars)
 7468                    .count()
 7469                    + row_delta as usize;
 7470                let chars_to_next_tab_stop = tab_size - (char_column as u32 % tab_size);
 7471                IndentSize::spaces(chars_to_next_tab_stop)
 7472            };
 7473            selection.start = Point::new(cursor.row, cursor.column + row_delta + tab_size.len);
 7474            selection.end = selection.start;
 7475            edits.push((cursor..cursor, tab_size.chars().collect::<String>()));
 7476            row_delta += tab_size.len;
 7477        }
 7478
 7479        self.transact(window, cx, |this, window, cx| {
 7480            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
 7481            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 7482                s.select(selections)
 7483            });
 7484            this.refresh_inline_completion(true, false, window, cx);
 7485        });
 7486    }
 7487
 7488    pub fn indent(&mut self, _: &Indent, window: &mut Window, cx: &mut Context<Self>) {
 7489        if self.read_only(cx) {
 7490            return;
 7491        }
 7492        let mut selections = self.selections.all::<Point>(cx);
 7493        let mut prev_edited_row = 0;
 7494        let mut row_delta = 0;
 7495        let mut edits = Vec::new();
 7496        let buffer = self.buffer.read(cx);
 7497        let snapshot = buffer.snapshot(cx);
 7498        for selection in &mut selections {
 7499            if selection.start.row != prev_edited_row {
 7500                row_delta = 0;
 7501            }
 7502            prev_edited_row = selection.end.row;
 7503
 7504            row_delta =
 7505                Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
 7506        }
 7507
 7508        self.transact(window, cx, |this, window, cx| {
 7509            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
 7510            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 7511                s.select(selections)
 7512            });
 7513        });
 7514    }
 7515
 7516    fn indent_selection(
 7517        buffer: &MultiBuffer,
 7518        snapshot: &MultiBufferSnapshot,
 7519        selection: &mut Selection<Point>,
 7520        edits: &mut Vec<(Range<Point>, String)>,
 7521        delta_for_start_row: u32,
 7522        cx: &App,
 7523    ) -> u32 {
 7524        let settings = buffer.language_settings_at(selection.start, cx);
 7525        let tab_size = settings.tab_size.get();
 7526        let indent_kind = if settings.hard_tabs {
 7527            IndentKind::Tab
 7528        } else {
 7529            IndentKind::Space
 7530        };
 7531        let mut start_row = selection.start.row;
 7532        let mut end_row = selection.end.row + 1;
 7533
 7534        // If a selection ends at the beginning of a line, don't indent
 7535        // that last line.
 7536        if selection.end.column == 0 && selection.end.row > selection.start.row {
 7537            end_row -= 1;
 7538        }
 7539
 7540        // Avoid re-indenting a row that has already been indented by a
 7541        // previous selection, but still update this selection's column
 7542        // to reflect that indentation.
 7543        if delta_for_start_row > 0 {
 7544            start_row += 1;
 7545            selection.start.column += delta_for_start_row;
 7546            if selection.end.row == selection.start.row {
 7547                selection.end.column += delta_for_start_row;
 7548            }
 7549        }
 7550
 7551        let mut delta_for_end_row = 0;
 7552        let has_multiple_rows = start_row + 1 != end_row;
 7553        for row in start_row..end_row {
 7554            let current_indent = snapshot.indent_size_for_line(MultiBufferRow(row));
 7555            let indent_delta = match (current_indent.kind, indent_kind) {
 7556                (IndentKind::Space, IndentKind::Space) => {
 7557                    let columns_to_next_tab_stop = tab_size - (current_indent.len % tab_size);
 7558                    IndentSize::spaces(columns_to_next_tab_stop)
 7559                }
 7560                (IndentKind::Tab, IndentKind::Space) => IndentSize::spaces(tab_size),
 7561                (_, IndentKind::Tab) => IndentSize::tab(),
 7562            };
 7563
 7564            let start = if has_multiple_rows || current_indent.len < selection.start.column {
 7565                0
 7566            } else {
 7567                selection.start.column
 7568            };
 7569            let row_start = Point::new(row, start);
 7570            edits.push((
 7571                row_start..row_start,
 7572                indent_delta.chars().collect::<String>(),
 7573            ));
 7574
 7575            // Update this selection's endpoints to reflect the indentation.
 7576            if row == selection.start.row {
 7577                selection.start.column += indent_delta.len;
 7578            }
 7579            if row == selection.end.row {
 7580                selection.end.column += indent_delta.len;
 7581                delta_for_end_row = indent_delta.len;
 7582            }
 7583        }
 7584
 7585        if selection.start.row == selection.end.row {
 7586            delta_for_start_row + delta_for_end_row
 7587        } else {
 7588            delta_for_end_row
 7589        }
 7590    }
 7591
 7592    pub fn outdent(&mut self, _: &Outdent, window: &mut Window, cx: &mut Context<Self>) {
 7593        if self.read_only(cx) {
 7594            return;
 7595        }
 7596        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 7597        let selections = self.selections.all::<Point>(cx);
 7598        let mut deletion_ranges = Vec::new();
 7599        let mut last_outdent = None;
 7600        {
 7601            let buffer = self.buffer.read(cx);
 7602            let snapshot = buffer.snapshot(cx);
 7603            for selection in &selections {
 7604                let settings = buffer.language_settings_at(selection.start, cx);
 7605                let tab_size = settings.tab_size.get();
 7606                let mut rows = selection.spanned_rows(false, &display_map);
 7607
 7608                // Avoid re-outdenting a row that has already been outdented by a
 7609                // previous selection.
 7610                if let Some(last_row) = last_outdent {
 7611                    if last_row == rows.start {
 7612                        rows.start = rows.start.next_row();
 7613                    }
 7614                }
 7615                let has_multiple_rows = rows.len() > 1;
 7616                for row in rows.iter_rows() {
 7617                    let indent_size = snapshot.indent_size_for_line(row);
 7618                    if indent_size.len > 0 {
 7619                        let deletion_len = match indent_size.kind {
 7620                            IndentKind::Space => {
 7621                                let columns_to_prev_tab_stop = indent_size.len % tab_size;
 7622                                if columns_to_prev_tab_stop == 0 {
 7623                                    tab_size
 7624                                } else {
 7625                                    columns_to_prev_tab_stop
 7626                                }
 7627                            }
 7628                            IndentKind::Tab => 1,
 7629                        };
 7630                        let start = if has_multiple_rows
 7631                            || deletion_len > selection.start.column
 7632                            || indent_size.len < selection.start.column
 7633                        {
 7634                            0
 7635                        } else {
 7636                            selection.start.column - deletion_len
 7637                        };
 7638                        deletion_ranges.push(
 7639                            Point::new(row.0, start)..Point::new(row.0, start + deletion_len),
 7640                        );
 7641                        last_outdent = Some(row);
 7642                    }
 7643                }
 7644            }
 7645        }
 7646
 7647        self.transact(window, cx, |this, window, cx| {
 7648            this.buffer.update(cx, |buffer, cx| {
 7649                let empty_str: Arc<str> = Arc::default();
 7650                buffer.edit(
 7651                    deletion_ranges
 7652                        .into_iter()
 7653                        .map(|range| (range, empty_str.clone())),
 7654                    None,
 7655                    cx,
 7656                );
 7657            });
 7658            let selections = this.selections.all::<usize>(cx);
 7659            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 7660                s.select(selections)
 7661            });
 7662        });
 7663    }
 7664
 7665    pub fn autoindent(&mut self, _: &AutoIndent, window: &mut Window, cx: &mut Context<Self>) {
 7666        if self.read_only(cx) {
 7667            return;
 7668        }
 7669        let selections = self
 7670            .selections
 7671            .all::<usize>(cx)
 7672            .into_iter()
 7673            .map(|s| s.range());
 7674
 7675        self.transact(window, cx, |this, window, cx| {
 7676            this.buffer.update(cx, |buffer, cx| {
 7677                buffer.autoindent_ranges(selections, cx);
 7678            });
 7679            let selections = this.selections.all::<usize>(cx);
 7680            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 7681                s.select(selections)
 7682            });
 7683        });
 7684    }
 7685
 7686    pub fn delete_line(&mut self, _: &DeleteLine, window: &mut Window, cx: &mut Context<Self>) {
 7687        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 7688        let selections = self.selections.all::<Point>(cx);
 7689
 7690        let mut new_cursors = Vec::new();
 7691        let mut edit_ranges = Vec::new();
 7692        let mut selections = selections.iter().peekable();
 7693        while let Some(selection) = selections.next() {
 7694            let mut rows = selection.spanned_rows(false, &display_map);
 7695            let goal_display_column = selection.head().to_display_point(&display_map).column();
 7696
 7697            // Accumulate contiguous regions of rows that we want to delete.
 7698            while let Some(next_selection) = selections.peek() {
 7699                let next_rows = next_selection.spanned_rows(false, &display_map);
 7700                if next_rows.start <= rows.end {
 7701                    rows.end = next_rows.end;
 7702                    selections.next().unwrap();
 7703                } else {
 7704                    break;
 7705                }
 7706            }
 7707
 7708            let buffer = &display_map.buffer_snapshot;
 7709            let mut edit_start = Point::new(rows.start.0, 0).to_offset(buffer);
 7710            let edit_end;
 7711            let cursor_buffer_row;
 7712            if buffer.max_point().row >= rows.end.0 {
 7713                // If there's a line after the range, delete the \n from the end of the row range
 7714                // and position the cursor on the next line.
 7715                edit_end = Point::new(rows.end.0, 0).to_offset(buffer);
 7716                cursor_buffer_row = rows.end;
 7717            } else {
 7718                // If there isn't a line after the range, delete the \n from the line before the
 7719                // start of the row range and position the cursor there.
 7720                edit_start = edit_start.saturating_sub(1);
 7721                edit_end = buffer.len();
 7722                cursor_buffer_row = rows.start.previous_row();
 7723            }
 7724
 7725            let mut cursor = Point::new(cursor_buffer_row.0, 0).to_display_point(&display_map);
 7726            *cursor.column_mut() =
 7727                cmp::min(goal_display_column, display_map.line_len(cursor.row()));
 7728
 7729            new_cursors.push((
 7730                selection.id,
 7731                buffer.anchor_after(cursor.to_point(&display_map)),
 7732            ));
 7733            edit_ranges.push(edit_start..edit_end);
 7734        }
 7735
 7736        self.transact(window, cx, |this, window, cx| {
 7737            let buffer = this.buffer.update(cx, |buffer, cx| {
 7738                let empty_str: Arc<str> = Arc::default();
 7739                buffer.edit(
 7740                    edit_ranges
 7741                        .into_iter()
 7742                        .map(|range| (range, empty_str.clone())),
 7743                    None,
 7744                    cx,
 7745                );
 7746                buffer.snapshot(cx)
 7747            });
 7748            let new_selections = new_cursors
 7749                .into_iter()
 7750                .map(|(id, cursor)| {
 7751                    let cursor = cursor.to_point(&buffer);
 7752                    Selection {
 7753                        id,
 7754                        start: cursor,
 7755                        end: cursor,
 7756                        reversed: false,
 7757                        goal: SelectionGoal::None,
 7758                    }
 7759                })
 7760                .collect();
 7761
 7762            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 7763                s.select(new_selections);
 7764            });
 7765        });
 7766    }
 7767
 7768    pub fn join_lines_impl(
 7769        &mut self,
 7770        insert_whitespace: bool,
 7771        window: &mut Window,
 7772        cx: &mut Context<Self>,
 7773    ) {
 7774        if self.read_only(cx) {
 7775            return;
 7776        }
 7777        let mut row_ranges = Vec::<Range<MultiBufferRow>>::new();
 7778        for selection in self.selections.all::<Point>(cx) {
 7779            let start = MultiBufferRow(selection.start.row);
 7780            // Treat single line selections as if they include the next line. Otherwise this action
 7781            // would do nothing for single line selections individual cursors.
 7782            let end = if selection.start.row == selection.end.row {
 7783                MultiBufferRow(selection.start.row + 1)
 7784            } else {
 7785                MultiBufferRow(selection.end.row)
 7786            };
 7787
 7788            if let Some(last_row_range) = row_ranges.last_mut() {
 7789                if start <= last_row_range.end {
 7790                    last_row_range.end = end;
 7791                    continue;
 7792                }
 7793            }
 7794            row_ranges.push(start..end);
 7795        }
 7796
 7797        let snapshot = self.buffer.read(cx).snapshot(cx);
 7798        let mut cursor_positions = Vec::new();
 7799        for row_range in &row_ranges {
 7800            let anchor = snapshot.anchor_before(Point::new(
 7801                row_range.end.previous_row().0,
 7802                snapshot.line_len(row_range.end.previous_row()),
 7803            ));
 7804            cursor_positions.push(anchor..anchor);
 7805        }
 7806
 7807        self.transact(window, cx, |this, window, cx| {
 7808            for row_range in row_ranges.into_iter().rev() {
 7809                for row in row_range.iter_rows().rev() {
 7810                    let end_of_line = Point::new(row.0, snapshot.line_len(row));
 7811                    let next_line_row = row.next_row();
 7812                    let indent = snapshot.indent_size_for_line(next_line_row);
 7813                    let start_of_next_line = Point::new(next_line_row.0, indent.len);
 7814
 7815                    let replace =
 7816                        if snapshot.line_len(next_line_row) > indent.len && insert_whitespace {
 7817                            " "
 7818                        } else {
 7819                            ""
 7820                        };
 7821
 7822                    this.buffer.update(cx, |buffer, cx| {
 7823                        buffer.edit([(end_of_line..start_of_next_line, replace)], None, cx)
 7824                    });
 7825                }
 7826            }
 7827
 7828            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 7829                s.select_anchor_ranges(cursor_positions)
 7830            });
 7831        });
 7832    }
 7833
 7834    pub fn join_lines(&mut self, _: &JoinLines, window: &mut Window, cx: &mut Context<Self>) {
 7835        self.join_lines_impl(true, window, cx);
 7836    }
 7837
 7838    pub fn sort_lines_case_sensitive(
 7839        &mut self,
 7840        _: &SortLinesCaseSensitive,
 7841        window: &mut Window,
 7842        cx: &mut Context<Self>,
 7843    ) {
 7844        self.manipulate_lines(window, cx, |lines| lines.sort())
 7845    }
 7846
 7847    pub fn sort_lines_case_insensitive(
 7848        &mut self,
 7849        _: &SortLinesCaseInsensitive,
 7850        window: &mut Window,
 7851        cx: &mut Context<Self>,
 7852    ) {
 7853        self.manipulate_lines(window, cx, |lines| {
 7854            lines.sort_by_key(|line| line.to_lowercase())
 7855        })
 7856    }
 7857
 7858    pub fn unique_lines_case_insensitive(
 7859        &mut self,
 7860        _: &UniqueLinesCaseInsensitive,
 7861        window: &mut Window,
 7862        cx: &mut Context<Self>,
 7863    ) {
 7864        self.manipulate_lines(window, cx, |lines| {
 7865            let mut seen = HashSet::default();
 7866            lines.retain(|line| seen.insert(line.to_lowercase()));
 7867        })
 7868    }
 7869
 7870    pub fn unique_lines_case_sensitive(
 7871        &mut self,
 7872        _: &UniqueLinesCaseSensitive,
 7873        window: &mut Window,
 7874        cx: &mut Context<Self>,
 7875    ) {
 7876        self.manipulate_lines(window, cx, |lines| {
 7877            let mut seen = HashSet::default();
 7878            lines.retain(|line| seen.insert(*line));
 7879        })
 7880    }
 7881
 7882    pub fn reload_file(&mut self, _: &ReloadFile, window: &mut Window, cx: &mut Context<Self>) {
 7883        let Some(project) = self.project.clone() else {
 7884            return;
 7885        };
 7886        self.reload(project, window, cx)
 7887            .detach_and_notify_err(window, cx);
 7888    }
 7889
 7890    pub fn restore_file(
 7891        &mut self,
 7892        _: &::git::RestoreFile,
 7893        window: &mut Window,
 7894        cx: &mut Context<Self>,
 7895    ) {
 7896        let mut buffer_ids = HashSet::default();
 7897        let snapshot = self.buffer().read(cx).snapshot(cx);
 7898        for selection in self.selections.all::<usize>(cx) {
 7899            buffer_ids.extend(snapshot.buffer_ids_for_range(selection.range()))
 7900        }
 7901
 7902        let buffer = self.buffer().read(cx);
 7903        let ranges = buffer_ids
 7904            .into_iter()
 7905            .flat_map(|buffer_id| buffer.excerpt_ranges_for_buffer(buffer_id, cx))
 7906            .collect::<Vec<_>>();
 7907
 7908        self.restore_hunks_in_ranges(ranges, window, cx);
 7909    }
 7910
 7911    pub fn git_restore(&mut self, _: &Restore, window: &mut Window, cx: &mut Context<Self>) {
 7912        let selections = self
 7913            .selections
 7914            .all(cx)
 7915            .into_iter()
 7916            .map(|s| s.range())
 7917            .collect();
 7918        self.restore_hunks_in_ranges(selections, window, cx);
 7919    }
 7920
 7921    fn restore_hunks_in_ranges(
 7922        &mut self,
 7923        ranges: Vec<Range<Point>>,
 7924        window: &mut Window,
 7925        cx: &mut Context<Editor>,
 7926    ) {
 7927        let mut revert_changes = HashMap::default();
 7928        let chunk_by = self
 7929            .snapshot(window, cx)
 7930            .hunks_for_ranges(ranges)
 7931            .into_iter()
 7932            .chunk_by(|hunk| hunk.buffer_id);
 7933        for (buffer_id, hunks) in &chunk_by {
 7934            let hunks = hunks.collect::<Vec<_>>();
 7935            for hunk in &hunks {
 7936                self.prepare_restore_change(&mut revert_changes, hunk, cx);
 7937            }
 7938            self.do_stage_or_unstage(false, buffer_id, hunks.into_iter(), cx);
 7939        }
 7940        drop(chunk_by);
 7941        if !revert_changes.is_empty() {
 7942            self.transact(window, cx, |editor, window, cx| {
 7943                editor.restore(revert_changes, window, cx);
 7944            });
 7945        }
 7946    }
 7947
 7948    pub fn open_active_item_in_terminal(
 7949        &mut self,
 7950        _: &OpenInTerminal,
 7951        window: &mut Window,
 7952        cx: &mut Context<Self>,
 7953    ) {
 7954        if let Some(working_directory) = self.active_excerpt(cx).and_then(|(_, buffer, _)| {
 7955            let project_path = buffer.read(cx).project_path(cx)?;
 7956            let project = self.project.as_ref()?.read(cx);
 7957            let entry = project.entry_for_path(&project_path, cx)?;
 7958            let parent = match &entry.canonical_path {
 7959                Some(canonical_path) => canonical_path.to_path_buf(),
 7960                None => project.absolute_path(&project_path, cx)?,
 7961            }
 7962            .parent()?
 7963            .to_path_buf();
 7964            Some(parent)
 7965        }) {
 7966            window.dispatch_action(OpenTerminal { working_directory }.boxed_clone(), cx);
 7967        }
 7968    }
 7969
 7970    pub fn prepare_restore_change(
 7971        &self,
 7972        revert_changes: &mut HashMap<BufferId, Vec<(Range<text::Anchor>, Rope)>>,
 7973        hunk: &MultiBufferDiffHunk,
 7974        cx: &mut App,
 7975    ) -> Option<()> {
 7976        if hunk.is_created_file() {
 7977            return None;
 7978        }
 7979        let buffer = self.buffer.read(cx);
 7980        let diff = buffer.diff_for(hunk.buffer_id)?;
 7981        let buffer = buffer.buffer(hunk.buffer_id)?;
 7982        let buffer = buffer.read(cx);
 7983        let original_text = diff
 7984            .read(cx)
 7985            .base_text()
 7986            .as_rope()
 7987            .slice(hunk.diff_base_byte_range.clone());
 7988        let buffer_snapshot = buffer.snapshot();
 7989        let buffer_revert_changes = revert_changes.entry(buffer.remote_id()).or_default();
 7990        if let Err(i) = buffer_revert_changes.binary_search_by(|probe| {
 7991            probe
 7992                .0
 7993                .start
 7994                .cmp(&hunk.buffer_range.start, &buffer_snapshot)
 7995                .then(probe.0.end.cmp(&hunk.buffer_range.end, &buffer_snapshot))
 7996        }) {
 7997            buffer_revert_changes.insert(i, (hunk.buffer_range.clone(), original_text));
 7998            Some(())
 7999        } else {
 8000            None
 8001        }
 8002    }
 8003
 8004    pub fn reverse_lines(&mut self, _: &ReverseLines, window: &mut Window, cx: &mut Context<Self>) {
 8005        self.manipulate_lines(window, cx, |lines| lines.reverse())
 8006    }
 8007
 8008    pub fn shuffle_lines(&mut self, _: &ShuffleLines, window: &mut Window, cx: &mut Context<Self>) {
 8009        self.manipulate_lines(window, cx, |lines| lines.shuffle(&mut thread_rng()))
 8010    }
 8011
 8012    fn manipulate_lines<Fn>(
 8013        &mut self,
 8014        window: &mut Window,
 8015        cx: &mut Context<Self>,
 8016        mut callback: Fn,
 8017    ) where
 8018        Fn: FnMut(&mut Vec<&str>),
 8019    {
 8020        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8021        let buffer = self.buffer.read(cx).snapshot(cx);
 8022
 8023        let mut edits = Vec::new();
 8024
 8025        let selections = self.selections.all::<Point>(cx);
 8026        let mut selections = selections.iter().peekable();
 8027        let mut contiguous_row_selections = Vec::new();
 8028        let mut new_selections = Vec::new();
 8029        let mut added_lines = 0;
 8030        let mut removed_lines = 0;
 8031
 8032        while let Some(selection) = selections.next() {
 8033            let (start_row, end_row) = consume_contiguous_rows(
 8034                &mut contiguous_row_selections,
 8035                selection,
 8036                &display_map,
 8037                &mut selections,
 8038            );
 8039
 8040            let start_point = Point::new(start_row.0, 0);
 8041            let end_point = Point::new(
 8042                end_row.previous_row().0,
 8043                buffer.line_len(end_row.previous_row()),
 8044            );
 8045            let text = buffer
 8046                .text_for_range(start_point..end_point)
 8047                .collect::<String>();
 8048
 8049            let mut lines = text.split('\n').collect_vec();
 8050
 8051            let lines_before = lines.len();
 8052            callback(&mut lines);
 8053            let lines_after = lines.len();
 8054
 8055            edits.push((start_point..end_point, lines.join("\n")));
 8056
 8057            // Selections must change based on added and removed line count
 8058            let start_row =
 8059                MultiBufferRow(start_point.row + added_lines as u32 - removed_lines as u32);
 8060            let end_row = MultiBufferRow(start_row.0 + lines_after.saturating_sub(1) as u32);
 8061            new_selections.push(Selection {
 8062                id: selection.id,
 8063                start: start_row,
 8064                end: end_row,
 8065                goal: SelectionGoal::None,
 8066                reversed: selection.reversed,
 8067            });
 8068
 8069            if lines_after > lines_before {
 8070                added_lines += lines_after - lines_before;
 8071            } else if lines_before > lines_after {
 8072                removed_lines += lines_before - lines_after;
 8073            }
 8074        }
 8075
 8076        self.transact(window, cx, |this, window, cx| {
 8077            let buffer = this.buffer.update(cx, |buffer, cx| {
 8078                buffer.edit(edits, None, cx);
 8079                buffer.snapshot(cx)
 8080            });
 8081
 8082            // Recalculate offsets on newly edited buffer
 8083            let new_selections = new_selections
 8084                .iter()
 8085                .map(|s| {
 8086                    let start_point = Point::new(s.start.0, 0);
 8087                    let end_point = Point::new(s.end.0, buffer.line_len(s.end));
 8088                    Selection {
 8089                        id: s.id,
 8090                        start: buffer.point_to_offset(start_point),
 8091                        end: buffer.point_to_offset(end_point),
 8092                        goal: s.goal,
 8093                        reversed: s.reversed,
 8094                    }
 8095                })
 8096                .collect();
 8097
 8098            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8099                s.select(new_selections);
 8100            });
 8101
 8102            this.request_autoscroll(Autoscroll::fit(), cx);
 8103        });
 8104    }
 8105
 8106    pub fn convert_to_upper_case(
 8107        &mut self,
 8108        _: &ConvertToUpperCase,
 8109        window: &mut Window,
 8110        cx: &mut Context<Self>,
 8111    ) {
 8112        self.manipulate_text(window, cx, |text| text.to_uppercase())
 8113    }
 8114
 8115    pub fn convert_to_lower_case(
 8116        &mut self,
 8117        _: &ConvertToLowerCase,
 8118        window: &mut Window,
 8119        cx: &mut Context<Self>,
 8120    ) {
 8121        self.manipulate_text(window, cx, |text| text.to_lowercase())
 8122    }
 8123
 8124    pub fn convert_to_title_case(
 8125        &mut self,
 8126        _: &ConvertToTitleCase,
 8127        window: &mut Window,
 8128        cx: &mut Context<Self>,
 8129    ) {
 8130        self.manipulate_text(window, cx, |text| {
 8131            text.split('\n')
 8132                .map(|line| line.to_case(Case::Title))
 8133                .join("\n")
 8134        })
 8135    }
 8136
 8137    pub fn convert_to_snake_case(
 8138        &mut self,
 8139        _: &ConvertToSnakeCase,
 8140        window: &mut Window,
 8141        cx: &mut Context<Self>,
 8142    ) {
 8143        self.manipulate_text(window, cx, |text| text.to_case(Case::Snake))
 8144    }
 8145
 8146    pub fn convert_to_kebab_case(
 8147        &mut self,
 8148        _: &ConvertToKebabCase,
 8149        window: &mut Window,
 8150        cx: &mut Context<Self>,
 8151    ) {
 8152        self.manipulate_text(window, cx, |text| text.to_case(Case::Kebab))
 8153    }
 8154
 8155    pub fn convert_to_upper_camel_case(
 8156        &mut self,
 8157        _: &ConvertToUpperCamelCase,
 8158        window: &mut Window,
 8159        cx: &mut Context<Self>,
 8160    ) {
 8161        self.manipulate_text(window, cx, |text| {
 8162            text.split('\n')
 8163                .map(|line| line.to_case(Case::UpperCamel))
 8164                .join("\n")
 8165        })
 8166    }
 8167
 8168    pub fn convert_to_lower_camel_case(
 8169        &mut self,
 8170        _: &ConvertToLowerCamelCase,
 8171        window: &mut Window,
 8172        cx: &mut Context<Self>,
 8173    ) {
 8174        self.manipulate_text(window, cx, |text| text.to_case(Case::Camel))
 8175    }
 8176
 8177    pub fn convert_to_opposite_case(
 8178        &mut self,
 8179        _: &ConvertToOppositeCase,
 8180        window: &mut Window,
 8181        cx: &mut Context<Self>,
 8182    ) {
 8183        self.manipulate_text(window, cx, |text| {
 8184            text.chars()
 8185                .fold(String::with_capacity(text.len()), |mut t, c| {
 8186                    if c.is_uppercase() {
 8187                        t.extend(c.to_lowercase());
 8188                    } else {
 8189                        t.extend(c.to_uppercase());
 8190                    }
 8191                    t
 8192                })
 8193        })
 8194    }
 8195
 8196    fn manipulate_text<Fn>(&mut self, window: &mut Window, cx: &mut Context<Self>, mut callback: Fn)
 8197    where
 8198        Fn: FnMut(&str) -> String,
 8199    {
 8200        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8201        let buffer = self.buffer.read(cx).snapshot(cx);
 8202
 8203        let mut new_selections = Vec::new();
 8204        let mut edits = Vec::new();
 8205        let mut selection_adjustment = 0i32;
 8206
 8207        for selection in self.selections.all::<usize>(cx) {
 8208            let selection_is_empty = selection.is_empty();
 8209
 8210            let (start, end) = if selection_is_empty {
 8211                let word_range = movement::surrounding_word(
 8212                    &display_map,
 8213                    selection.start.to_display_point(&display_map),
 8214                );
 8215                let start = word_range.start.to_offset(&display_map, Bias::Left);
 8216                let end = word_range.end.to_offset(&display_map, Bias::Left);
 8217                (start, end)
 8218            } else {
 8219                (selection.start, selection.end)
 8220            };
 8221
 8222            let text = buffer.text_for_range(start..end).collect::<String>();
 8223            let old_length = text.len() as i32;
 8224            let text = callback(&text);
 8225
 8226            new_selections.push(Selection {
 8227                start: (start as i32 - selection_adjustment) as usize,
 8228                end: ((start + text.len()) as i32 - selection_adjustment) as usize,
 8229                goal: SelectionGoal::None,
 8230                ..selection
 8231            });
 8232
 8233            selection_adjustment += old_length - text.len() as i32;
 8234
 8235            edits.push((start..end, text));
 8236        }
 8237
 8238        self.transact(window, cx, |this, window, cx| {
 8239            this.buffer.update(cx, |buffer, cx| {
 8240                buffer.edit(edits, None, cx);
 8241            });
 8242
 8243            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8244                s.select(new_selections);
 8245            });
 8246
 8247            this.request_autoscroll(Autoscroll::fit(), cx);
 8248        });
 8249    }
 8250
 8251    pub fn duplicate(
 8252        &mut self,
 8253        upwards: bool,
 8254        whole_lines: bool,
 8255        window: &mut Window,
 8256        cx: &mut Context<Self>,
 8257    ) {
 8258        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8259        let buffer = &display_map.buffer_snapshot;
 8260        let selections = self.selections.all::<Point>(cx);
 8261
 8262        let mut edits = Vec::new();
 8263        let mut selections_iter = selections.iter().peekable();
 8264        while let Some(selection) = selections_iter.next() {
 8265            let mut rows = selection.spanned_rows(false, &display_map);
 8266            // duplicate line-wise
 8267            if whole_lines || selection.start == selection.end {
 8268                // Avoid duplicating the same lines twice.
 8269                while let Some(next_selection) = selections_iter.peek() {
 8270                    let next_rows = next_selection.spanned_rows(false, &display_map);
 8271                    if next_rows.start < rows.end {
 8272                        rows.end = next_rows.end;
 8273                        selections_iter.next().unwrap();
 8274                    } else {
 8275                        break;
 8276                    }
 8277                }
 8278
 8279                // Copy the text from the selected row region and splice it either at the start
 8280                // or end of the region.
 8281                let start = Point::new(rows.start.0, 0);
 8282                let end = Point::new(
 8283                    rows.end.previous_row().0,
 8284                    buffer.line_len(rows.end.previous_row()),
 8285                );
 8286                let text = buffer
 8287                    .text_for_range(start..end)
 8288                    .chain(Some("\n"))
 8289                    .collect::<String>();
 8290                let insert_location = if upwards {
 8291                    Point::new(rows.end.0, 0)
 8292                } else {
 8293                    start
 8294                };
 8295                edits.push((insert_location..insert_location, text));
 8296            } else {
 8297                // duplicate character-wise
 8298                let start = selection.start;
 8299                let end = selection.end;
 8300                let text = buffer.text_for_range(start..end).collect::<String>();
 8301                edits.push((selection.end..selection.end, text));
 8302            }
 8303        }
 8304
 8305        self.transact(window, cx, |this, _, cx| {
 8306            this.buffer.update(cx, |buffer, cx| {
 8307                buffer.edit(edits, None, cx);
 8308            });
 8309
 8310            this.request_autoscroll(Autoscroll::fit(), cx);
 8311        });
 8312    }
 8313
 8314    pub fn duplicate_line_up(
 8315        &mut self,
 8316        _: &DuplicateLineUp,
 8317        window: &mut Window,
 8318        cx: &mut Context<Self>,
 8319    ) {
 8320        self.duplicate(true, true, window, cx);
 8321    }
 8322
 8323    pub fn duplicate_line_down(
 8324        &mut self,
 8325        _: &DuplicateLineDown,
 8326        window: &mut Window,
 8327        cx: &mut Context<Self>,
 8328    ) {
 8329        self.duplicate(false, true, window, cx);
 8330    }
 8331
 8332    pub fn duplicate_selection(
 8333        &mut self,
 8334        _: &DuplicateSelection,
 8335        window: &mut Window,
 8336        cx: &mut Context<Self>,
 8337    ) {
 8338        self.duplicate(false, false, window, cx);
 8339    }
 8340
 8341    pub fn move_line_up(&mut self, _: &MoveLineUp, window: &mut Window, cx: &mut Context<Self>) {
 8342        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8343        let buffer = self.buffer.read(cx).snapshot(cx);
 8344
 8345        let mut edits = Vec::new();
 8346        let mut unfold_ranges = Vec::new();
 8347        let mut refold_creases = Vec::new();
 8348
 8349        let selections = self.selections.all::<Point>(cx);
 8350        let mut selections = selections.iter().peekable();
 8351        let mut contiguous_row_selections = Vec::new();
 8352        let mut new_selections = Vec::new();
 8353
 8354        while let Some(selection) = selections.next() {
 8355            // Find all the selections that span a contiguous row range
 8356            let (start_row, end_row) = consume_contiguous_rows(
 8357                &mut contiguous_row_selections,
 8358                selection,
 8359                &display_map,
 8360                &mut selections,
 8361            );
 8362
 8363            // Move the text spanned by the row range to be before the line preceding the row range
 8364            if start_row.0 > 0 {
 8365                let range_to_move = Point::new(
 8366                    start_row.previous_row().0,
 8367                    buffer.line_len(start_row.previous_row()),
 8368                )
 8369                    ..Point::new(
 8370                        end_row.previous_row().0,
 8371                        buffer.line_len(end_row.previous_row()),
 8372                    );
 8373                let insertion_point = display_map
 8374                    .prev_line_boundary(Point::new(start_row.previous_row().0, 0))
 8375                    .0;
 8376
 8377                // Don't move lines across excerpts
 8378                if buffer
 8379                    .excerpt_containing(insertion_point..range_to_move.end)
 8380                    .is_some()
 8381                {
 8382                    let text = buffer
 8383                        .text_for_range(range_to_move.clone())
 8384                        .flat_map(|s| s.chars())
 8385                        .skip(1)
 8386                        .chain(['\n'])
 8387                        .collect::<String>();
 8388
 8389                    edits.push((
 8390                        buffer.anchor_after(range_to_move.start)
 8391                            ..buffer.anchor_before(range_to_move.end),
 8392                        String::new(),
 8393                    ));
 8394                    let insertion_anchor = buffer.anchor_after(insertion_point);
 8395                    edits.push((insertion_anchor..insertion_anchor, text));
 8396
 8397                    let row_delta = range_to_move.start.row - insertion_point.row + 1;
 8398
 8399                    // Move selections up
 8400                    new_selections.extend(contiguous_row_selections.drain(..).map(
 8401                        |mut selection| {
 8402                            selection.start.row -= row_delta;
 8403                            selection.end.row -= row_delta;
 8404                            selection
 8405                        },
 8406                    ));
 8407
 8408                    // Move folds up
 8409                    unfold_ranges.push(range_to_move.clone());
 8410                    for fold in display_map.folds_in_range(
 8411                        buffer.anchor_before(range_to_move.start)
 8412                            ..buffer.anchor_after(range_to_move.end),
 8413                    ) {
 8414                        let mut start = fold.range.start.to_point(&buffer);
 8415                        let mut end = fold.range.end.to_point(&buffer);
 8416                        start.row -= row_delta;
 8417                        end.row -= row_delta;
 8418                        refold_creases.push(Crease::simple(start..end, fold.placeholder.clone()));
 8419                    }
 8420                }
 8421            }
 8422
 8423            // If we didn't move line(s), preserve the existing selections
 8424            new_selections.append(&mut contiguous_row_selections);
 8425        }
 8426
 8427        self.transact(window, cx, |this, window, cx| {
 8428            this.unfold_ranges(&unfold_ranges, true, true, cx);
 8429            this.buffer.update(cx, |buffer, cx| {
 8430                for (range, text) in edits {
 8431                    buffer.edit([(range, text)], None, cx);
 8432                }
 8433            });
 8434            this.fold_creases(refold_creases, true, window, cx);
 8435            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8436                s.select(new_selections);
 8437            })
 8438        });
 8439    }
 8440
 8441    pub fn move_line_down(
 8442        &mut self,
 8443        _: &MoveLineDown,
 8444        window: &mut Window,
 8445        cx: &mut Context<Self>,
 8446    ) {
 8447        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8448        let buffer = self.buffer.read(cx).snapshot(cx);
 8449
 8450        let mut edits = Vec::new();
 8451        let mut unfold_ranges = Vec::new();
 8452        let mut refold_creases = Vec::new();
 8453
 8454        let selections = self.selections.all::<Point>(cx);
 8455        let mut selections = selections.iter().peekable();
 8456        let mut contiguous_row_selections = Vec::new();
 8457        let mut new_selections = Vec::new();
 8458
 8459        while let Some(selection) = selections.next() {
 8460            // Find all the selections that span a contiguous row range
 8461            let (start_row, end_row) = consume_contiguous_rows(
 8462                &mut contiguous_row_selections,
 8463                selection,
 8464                &display_map,
 8465                &mut selections,
 8466            );
 8467
 8468            // Move the text spanned by the row range to be after the last line of the row range
 8469            if end_row.0 <= buffer.max_point().row {
 8470                let range_to_move =
 8471                    MultiBufferPoint::new(start_row.0, 0)..MultiBufferPoint::new(end_row.0, 0);
 8472                let insertion_point = display_map
 8473                    .next_line_boundary(MultiBufferPoint::new(end_row.0, 0))
 8474                    .0;
 8475
 8476                // Don't move lines across excerpt boundaries
 8477                if buffer
 8478                    .excerpt_containing(range_to_move.start..insertion_point)
 8479                    .is_some()
 8480                {
 8481                    let mut text = String::from("\n");
 8482                    text.extend(buffer.text_for_range(range_to_move.clone()));
 8483                    text.pop(); // Drop trailing newline
 8484                    edits.push((
 8485                        buffer.anchor_after(range_to_move.start)
 8486                            ..buffer.anchor_before(range_to_move.end),
 8487                        String::new(),
 8488                    ));
 8489                    let insertion_anchor = buffer.anchor_after(insertion_point);
 8490                    edits.push((insertion_anchor..insertion_anchor, text));
 8491
 8492                    let row_delta = insertion_point.row - range_to_move.end.row + 1;
 8493
 8494                    // Move selections down
 8495                    new_selections.extend(contiguous_row_selections.drain(..).map(
 8496                        |mut selection| {
 8497                            selection.start.row += row_delta;
 8498                            selection.end.row += row_delta;
 8499                            selection
 8500                        },
 8501                    ));
 8502
 8503                    // Move folds down
 8504                    unfold_ranges.push(range_to_move.clone());
 8505                    for fold in display_map.folds_in_range(
 8506                        buffer.anchor_before(range_to_move.start)
 8507                            ..buffer.anchor_after(range_to_move.end),
 8508                    ) {
 8509                        let mut start = fold.range.start.to_point(&buffer);
 8510                        let mut end = fold.range.end.to_point(&buffer);
 8511                        start.row += row_delta;
 8512                        end.row += row_delta;
 8513                        refold_creases.push(Crease::simple(start..end, fold.placeholder.clone()));
 8514                    }
 8515                }
 8516            }
 8517
 8518            // If we didn't move line(s), preserve the existing selections
 8519            new_selections.append(&mut contiguous_row_selections);
 8520        }
 8521
 8522        self.transact(window, cx, |this, window, cx| {
 8523            this.unfold_ranges(&unfold_ranges, true, true, cx);
 8524            this.buffer.update(cx, |buffer, cx| {
 8525                for (range, text) in edits {
 8526                    buffer.edit([(range, text)], None, cx);
 8527                }
 8528            });
 8529            this.fold_creases(refold_creases, true, window, cx);
 8530            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8531                s.select(new_selections)
 8532            });
 8533        });
 8534    }
 8535
 8536    pub fn transpose(&mut self, _: &Transpose, window: &mut Window, cx: &mut Context<Self>) {
 8537        let text_layout_details = &self.text_layout_details(window);
 8538        self.transact(window, cx, |this, window, cx| {
 8539            let edits = this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8540                let mut edits: Vec<(Range<usize>, String)> = Default::default();
 8541                let line_mode = s.line_mode;
 8542                s.move_with(|display_map, selection| {
 8543                    if !selection.is_empty() || line_mode {
 8544                        return;
 8545                    }
 8546
 8547                    let mut head = selection.head();
 8548                    let mut transpose_offset = head.to_offset(display_map, Bias::Right);
 8549                    if head.column() == display_map.line_len(head.row()) {
 8550                        transpose_offset = display_map
 8551                            .buffer_snapshot
 8552                            .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
 8553                    }
 8554
 8555                    if transpose_offset == 0 {
 8556                        return;
 8557                    }
 8558
 8559                    *head.column_mut() += 1;
 8560                    head = display_map.clip_point(head, Bias::Right);
 8561                    let goal = SelectionGoal::HorizontalPosition(
 8562                        display_map
 8563                            .x_for_display_point(head, text_layout_details)
 8564                            .into(),
 8565                    );
 8566                    selection.collapse_to(head, goal);
 8567
 8568                    let transpose_start = display_map
 8569                        .buffer_snapshot
 8570                        .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
 8571                    if edits.last().map_or(true, |e| e.0.end <= transpose_start) {
 8572                        let transpose_end = display_map
 8573                            .buffer_snapshot
 8574                            .clip_offset(transpose_offset + 1, Bias::Right);
 8575                        if let Some(ch) =
 8576                            display_map.buffer_snapshot.chars_at(transpose_start).next()
 8577                        {
 8578                            edits.push((transpose_start..transpose_offset, String::new()));
 8579                            edits.push((transpose_end..transpose_end, ch.to_string()));
 8580                        }
 8581                    }
 8582                });
 8583                edits
 8584            });
 8585            this.buffer
 8586                .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
 8587            let selections = this.selections.all::<usize>(cx);
 8588            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8589                s.select(selections);
 8590            });
 8591        });
 8592    }
 8593
 8594    pub fn rewrap(&mut self, _: &Rewrap, _: &mut Window, cx: &mut Context<Self>) {
 8595        self.rewrap_impl(false, cx)
 8596    }
 8597
 8598    pub fn rewrap_impl(&mut self, override_language_settings: bool, cx: &mut Context<Self>) {
 8599        let buffer = self.buffer.read(cx).snapshot(cx);
 8600        let selections = self.selections.all::<Point>(cx);
 8601        let mut selections = selections.iter().peekable();
 8602
 8603        let mut edits = Vec::new();
 8604        let mut rewrapped_row_ranges = Vec::<RangeInclusive<u32>>::new();
 8605
 8606        while let Some(selection) = selections.next() {
 8607            let mut start_row = selection.start.row;
 8608            let mut end_row = selection.end.row;
 8609
 8610            // Skip selections that overlap with a range that has already been rewrapped.
 8611            let selection_range = start_row..end_row;
 8612            if rewrapped_row_ranges
 8613                .iter()
 8614                .any(|range| range.overlaps(&selection_range))
 8615            {
 8616                continue;
 8617            }
 8618
 8619            let tab_size = buffer.language_settings_at(selection.head(), cx).tab_size;
 8620
 8621            // Since not all lines in the selection may be at the same indent
 8622            // level, choose the indent size that is the most common between all
 8623            // of the lines.
 8624            //
 8625            // If there is a tie, we use the deepest indent.
 8626            let (indent_size, indent_end) = {
 8627                let mut indent_size_occurrences = HashMap::default();
 8628                let mut rows_by_indent_size = HashMap::<IndentSize, Vec<u32>>::default();
 8629
 8630                for row in start_row..=end_row {
 8631                    let indent = buffer.indent_size_for_line(MultiBufferRow(row));
 8632                    rows_by_indent_size.entry(indent).or_default().push(row);
 8633                    *indent_size_occurrences.entry(indent).or_insert(0) += 1;
 8634                }
 8635
 8636                let indent_size = indent_size_occurrences
 8637                    .into_iter()
 8638                    .max_by_key(|(indent, count)| (*count, indent.len_with_expanded_tabs(tab_size)))
 8639                    .map(|(indent, _)| indent)
 8640                    .unwrap_or_default();
 8641                let row = rows_by_indent_size[&indent_size][0];
 8642                let indent_end = Point::new(row, indent_size.len);
 8643
 8644                (indent_size, indent_end)
 8645            };
 8646
 8647            let mut line_prefix = indent_size.chars().collect::<String>();
 8648
 8649            let mut inside_comment = false;
 8650            if let Some(comment_prefix) =
 8651                buffer
 8652                    .language_scope_at(selection.head())
 8653                    .and_then(|language| {
 8654                        language
 8655                            .line_comment_prefixes()
 8656                            .iter()
 8657                            .find(|prefix| buffer.contains_str_at(indent_end, prefix))
 8658                            .cloned()
 8659                    })
 8660            {
 8661                line_prefix.push_str(&comment_prefix);
 8662                inside_comment = true;
 8663            }
 8664
 8665            let language_settings = buffer.language_settings_at(selection.head(), cx);
 8666            let allow_rewrap_based_on_language = match language_settings.allow_rewrap {
 8667                RewrapBehavior::InComments => inside_comment,
 8668                RewrapBehavior::InSelections => !selection.is_empty(),
 8669                RewrapBehavior::Anywhere => true,
 8670            };
 8671
 8672            let should_rewrap = override_language_settings
 8673                || allow_rewrap_based_on_language
 8674                || self.hard_wrap.is_some();
 8675            if !should_rewrap {
 8676                continue;
 8677            }
 8678
 8679            if selection.is_empty() {
 8680                'expand_upwards: while start_row > 0 {
 8681                    let prev_row = start_row - 1;
 8682                    if buffer.contains_str_at(Point::new(prev_row, 0), &line_prefix)
 8683                        && buffer.line_len(MultiBufferRow(prev_row)) as usize > line_prefix.len()
 8684                    {
 8685                        start_row = prev_row;
 8686                    } else {
 8687                        break 'expand_upwards;
 8688                    }
 8689                }
 8690
 8691                'expand_downwards: while end_row < buffer.max_point().row {
 8692                    let next_row = end_row + 1;
 8693                    if buffer.contains_str_at(Point::new(next_row, 0), &line_prefix)
 8694                        && buffer.line_len(MultiBufferRow(next_row)) as usize > line_prefix.len()
 8695                    {
 8696                        end_row = next_row;
 8697                    } else {
 8698                        break 'expand_downwards;
 8699                    }
 8700                }
 8701            }
 8702
 8703            let start = Point::new(start_row, 0);
 8704            let start_offset = start.to_offset(&buffer);
 8705            let end = Point::new(end_row, buffer.line_len(MultiBufferRow(end_row)));
 8706            let selection_text = buffer.text_for_range(start..end).collect::<String>();
 8707            let Some(lines_without_prefixes) = selection_text
 8708                .lines()
 8709                .map(|line| {
 8710                    line.strip_prefix(&line_prefix)
 8711                        .or_else(|| line.trim_start().strip_prefix(&line_prefix.trim_start()))
 8712                        .ok_or_else(|| {
 8713                            anyhow!("line did not start with prefix {line_prefix:?}: {line:?}")
 8714                        })
 8715                })
 8716                .collect::<Result<Vec<_>, _>>()
 8717                .log_err()
 8718            else {
 8719                continue;
 8720            };
 8721
 8722            let wrap_column = self.hard_wrap.unwrap_or_else(|| {
 8723                buffer
 8724                    .language_settings_at(Point::new(start_row, 0), cx)
 8725                    .preferred_line_length as usize
 8726            });
 8727            let wrapped_text = wrap_with_prefix(
 8728                line_prefix,
 8729                lines_without_prefixes.join(" "),
 8730                wrap_column,
 8731                tab_size,
 8732            );
 8733
 8734            // TODO: should always use char-based diff while still supporting cursor behavior that
 8735            // matches vim.
 8736            let mut diff_options = DiffOptions::default();
 8737            if override_language_settings {
 8738                diff_options.max_word_diff_len = 0;
 8739                diff_options.max_word_diff_line_count = 0;
 8740            } else {
 8741                diff_options.max_word_diff_len = usize::MAX;
 8742                diff_options.max_word_diff_line_count = usize::MAX;
 8743            }
 8744
 8745            for (old_range, new_text) in
 8746                text_diff_with_options(&selection_text, &wrapped_text, diff_options)
 8747            {
 8748                let edit_start = buffer.anchor_after(start_offset + old_range.start);
 8749                let edit_end = buffer.anchor_after(start_offset + old_range.end);
 8750                edits.push((edit_start..edit_end, new_text));
 8751            }
 8752
 8753            rewrapped_row_ranges.push(start_row..=end_row);
 8754        }
 8755
 8756        self.buffer
 8757            .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
 8758    }
 8759
 8760    pub fn cut_common(&mut self, window: &mut Window, cx: &mut Context<Self>) -> ClipboardItem {
 8761        let mut text = String::new();
 8762        let buffer = self.buffer.read(cx).snapshot(cx);
 8763        let mut selections = self.selections.all::<Point>(cx);
 8764        let mut clipboard_selections = Vec::with_capacity(selections.len());
 8765        {
 8766            let max_point = buffer.max_point();
 8767            let mut is_first = true;
 8768            for selection in &mut selections {
 8769                let is_entire_line = selection.is_empty() || self.selections.line_mode;
 8770                if is_entire_line {
 8771                    selection.start = Point::new(selection.start.row, 0);
 8772                    if !selection.is_empty() && selection.end.column == 0 {
 8773                        selection.end = cmp::min(max_point, selection.end);
 8774                    } else {
 8775                        selection.end = cmp::min(max_point, Point::new(selection.end.row + 1, 0));
 8776                    }
 8777                    selection.goal = SelectionGoal::None;
 8778                }
 8779                if is_first {
 8780                    is_first = false;
 8781                } else {
 8782                    text += "\n";
 8783                }
 8784                let mut len = 0;
 8785                for chunk in buffer.text_for_range(selection.start..selection.end) {
 8786                    text.push_str(chunk);
 8787                    len += chunk.len();
 8788                }
 8789                clipboard_selections.push(ClipboardSelection {
 8790                    len,
 8791                    is_entire_line,
 8792                    first_line_indent: buffer
 8793                        .indent_size_for_line(MultiBufferRow(selection.start.row))
 8794                        .len,
 8795                });
 8796            }
 8797        }
 8798
 8799        self.transact(window, cx, |this, window, cx| {
 8800            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8801                s.select(selections);
 8802            });
 8803            this.insert("", window, cx);
 8804        });
 8805        ClipboardItem::new_string_with_json_metadata(text, clipboard_selections)
 8806    }
 8807
 8808    pub fn cut(&mut self, _: &Cut, window: &mut Window, cx: &mut Context<Self>) {
 8809        let item = self.cut_common(window, cx);
 8810        cx.write_to_clipboard(item);
 8811    }
 8812
 8813    pub fn kill_ring_cut(&mut self, _: &KillRingCut, window: &mut Window, cx: &mut Context<Self>) {
 8814        self.change_selections(None, window, cx, |s| {
 8815            s.move_with(|snapshot, sel| {
 8816                if sel.is_empty() {
 8817                    sel.end = DisplayPoint::new(sel.end.row(), snapshot.line_len(sel.end.row()))
 8818                }
 8819            });
 8820        });
 8821        let item = self.cut_common(window, cx);
 8822        cx.set_global(KillRing(item))
 8823    }
 8824
 8825    pub fn kill_ring_yank(
 8826        &mut self,
 8827        _: &KillRingYank,
 8828        window: &mut Window,
 8829        cx: &mut Context<Self>,
 8830    ) {
 8831        let (text, metadata) = if let Some(KillRing(item)) = cx.try_global() {
 8832            if let Some(ClipboardEntry::String(kill_ring)) = item.entries().first() {
 8833                (kill_ring.text().to_string(), kill_ring.metadata_json())
 8834            } else {
 8835                return;
 8836            }
 8837        } else {
 8838            return;
 8839        };
 8840        self.do_paste(&text, metadata, false, window, cx);
 8841    }
 8842
 8843    pub fn copy(&mut self, _: &Copy, _: &mut Window, cx: &mut Context<Self>) {
 8844        let selections = self.selections.all::<Point>(cx);
 8845        let buffer = self.buffer.read(cx).read(cx);
 8846        let mut text = String::new();
 8847
 8848        let mut clipboard_selections = Vec::with_capacity(selections.len());
 8849        {
 8850            let max_point = buffer.max_point();
 8851            let mut is_first = true;
 8852            for selection in selections.iter() {
 8853                let mut start = selection.start;
 8854                let mut end = selection.end;
 8855                let is_entire_line = selection.is_empty() || self.selections.line_mode;
 8856                if is_entire_line {
 8857                    start = Point::new(start.row, 0);
 8858                    end = cmp::min(max_point, Point::new(end.row + 1, 0));
 8859                }
 8860                if is_first {
 8861                    is_first = false;
 8862                } else {
 8863                    text += "\n";
 8864                }
 8865                let mut len = 0;
 8866                for chunk in buffer.text_for_range(start..end) {
 8867                    text.push_str(chunk);
 8868                    len += chunk.len();
 8869                }
 8870                clipboard_selections.push(ClipboardSelection {
 8871                    len,
 8872                    is_entire_line,
 8873                    first_line_indent: buffer.indent_size_for_line(MultiBufferRow(start.row)).len,
 8874                });
 8875            }
 8876        }
 8877
 8878        cx.write_to_clipboard(ClipboardItem::new_string_with_json_metadata(
 8879            text,
 8880            clipboard_selections,
 8881        ));
 8882    }
 8883
 8884    pub fn do_paste(
 8885        &mut self,
 8886        text: &String,
 8887        clipboard_selections: Option<Vec<ClipboardSelection>>,
 8888        handle_entire_lines: bool,
 8889        window: &mut Window,
 8890        cx: &mut Context<Self>,
 8891    ) {
 8892        if self.read_only(cx) {
 8893            return;
 8894        }
 8895
 8896        let clipboard_text = Cow::Borrowed(text);
 8897
 8898        self.transact(window, cx, |this, window, cx| {
 8899            if let Some(mut clipboard_selections) = clipboard_selections {
 8900                let old_selections = this.selections.all::<usize>(cx);
 8901                let all_selections_were_entire_line =
 8902                    clipboard_selections.iter().all(|s| s.is_entire_line);
 8903                let first_selection_indent_column =
 8904                    clipboard_selections.first().map(|s| s.first_line_indent);
 8905                if clipboard_selections.len() != old_selections.len() {
 8906                    clipboard_selections.drain(..);
 8907                }
 8908                let cursor_offset = this.selections.last::<usize>(cx).head();
 8909                let mut auto_indent_on_paste = true;
 8910
 8911                this.buffer.update(cx, |buffer, cx| {
 8912                    let snapshot = buffer.read(cx);
 8913                    auto_indent_on_paste = snapshot
 8914                        .language_settings_at(cursor_offset, cx)
 8915                        .auto_indent_on_paste;
 8916
 8917                    let mut start_offset = 0;
 8918                    let mut edits = Vec::new();
 8919                    let mut original_indent_columns = Vec::new();
 8920                    for (ix, selection) in old_selections.iter().enumerate() {
 8921                        let to_insert;
 8922                        let entire_line;
 8923                        let original_indent_column;
 8924                        if let Some(clipboard_selection) = clipboard_selections.get(ix) {
 8925                            let end_offset = start_offset + clipboard_selection.len;
 8926                            to_insert = &clipboard_text[start_offset..end_offset];
 8927                            entire_line = clipboard_selection.is_entire_line;
 8928                            start_offset = end_offset + 1;
 8929                            original_indent_column = Some(clipboard_selection.first_line_indent);
 8930                        } else {
 8931                            to_insert = clipboard_text.as_str();
 8932                            entire_line = all_selections_were_entire_line;
 8933                            original_indent_column = first_selection_indent_column
 8934                        }
 8935
 8936                        // If the corresponding selection was empty when this slice of the
 8937                        // clipboard text was written, then the entire line containing the
 8938                        // selection was copied. If this selection is also currently empty,
 8939                        // then paste the line before the current line of the buffer.
 8940                        let range = if selection.is_empty() && handle_entire_lines && entire_line {
 8941                            let column = selection.start.to_point(&snapshot).column as usize;
 8942                            let line_start = selection.start - column;
 8943                            line_start..line_start
 8944                        } else {
 8945                            selection.range()
 8946                        };
 8947
 8948                        edits.push((range, to_insert));
 8949                        original_indent_columns.push(original_indent_column);
 8950                    }
 8951                    drop(snapshot);
 8952
 8953                    buffer.edit(
 8954                        edits,
 8955                        if auto_indent_on_paste {
 8956                            Some(AutoindentMode::Block {
 8957                                original_indent_columns,
 8958                            })
 8959                        } else {
 8960                            None
 8961                        },
 8962                        cx,
 8963                    );
 8964                });
 8965
 8966                let selections = this.selections.all::<usize>(cx);
 8967                this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8968                    s.select(selections)
 8969                });
 8970            } else {
 8971                this.insert(&clipboard_text, window, cx);
 8972            }
 8973        });
 8974    }
 8975
 8976    pub fn paste(&mut self, _: &Paste, window: &mut Window, cx: &mut Context<Self>) {
 8977        if let Some(item) = cx.read_from_clipboard() {
 8978            let entries = item.entries();
 8979
 8980            match entries.first() {
 8981                // For now, we only support applying metadata if there's one string. In the future, we can incorporate all the selections
 8982                // of all the pasted entries.
 8983                Some(ClipboardEntry::String(clipboard_string)) if entries.len() == 1 => self
 8984                    .do_paste(
 8985                        clipboard_string.text(),
 8986                        clipboard_string.metadata_json::<Vec<ClipboardSelection>>(),
 8987                        true,
 8988                        window,
 8989                        cx,
 8990                    ),
 8991                _ => self.do_paste(&item.text().unwrap_or_default(), None, true, window, cx),
 8992            }
 8993        }
 8994    }
 8995
 8996    pub fn undo(&mut self, _: &Undo, window: &mut Window, cx: &mut Context<Self>) {
 8997        if self.read_only(cx) {
 8998            return;
 8999        }
 9000
 9001        if let Some(transaction_id) = self.buffer.update(cx, |buffer, cx| buffer.undo(cx)) {
 9002            if let Some((selections, _)) =
 9003                self.selection_history.transaction(transaction_id).cloned()
 9004            {
 9005                self.change_selections(None, window, cx, |s| {
 9006                    s.select_anchors(selections.to_vec());
 9007                });
 9008            } else {
 9009                log::error!(
 9010                    "No entry in selection_history found for undo. \
 9011                     This may correspond to a bug where undo does not update the selection. \
 9012                     If this is occurring, please add details to \
 9013                     https://github.com/zed-industries/zed/issues/22692"
 9014                );
 9015            }
 9016            self.request_autoscroll(Autoscroll::fit(), cx);
 9017            self.unmark_text(window, cx);
 9018            self.refresh_inline_completion(true, false, window, cx);
 9019            cx.emit(EditorEvent::Edited { transaction_id });
 9020            cx.emit(EditorEvent::TransactionUndone { transaction_id });
 9021        }
 9022    }
 9023
 9024    pub fn redo(&mut self, _: &Redo, window: &mut Window, cx: &mut Context<Self>) {
 9025        if self.read_only(cx) {
 9026            return;
 9027        }
 9028
 9029        if let Some(transaction_id) = self.buffer.update(cx, |buffer, cx| buffer.redo(cx)) {
 9030            if let Some((_, Some(selections))) =
 9031                self.selection_history.transaction(transaction_id).cloned()
 9032            {
 9033                self.change_selections(None, window, cx, |s| {
 9034                    s.select_anchors(selections.to_vec());
 9035                });
 9036            } else {
 9037                log::error!(
 9038                    "No entry in selection_history found for redo. \
 9039                     This may correspond to a bug where undo does not update the selection. \
 9040                     If this is occurring, please add details to \
 9041                     https://github.com/zed-industries/zed/issues/22692"
 9042                );
 9043            }
 9044            self.request_autoscroll(Autoscroll::fit(), cx);
 9045            self.unmark_text(window, cx);
 9046            self.refresh_inline_completion(true, false, window, cx);
 9047            cx.emit(EditorEvent::Edited { transaction_id });
 9048        }
 9049    }
 9050
 9051    pub fn finalize_last_transaction(&mut self, cx: &mut Context<Self>) {
 9052        self.buffer
 9053            .update(cx, |buffer, cx| buffer.finalize_last_transaction(cx));
 9054    }
 9055
 9056    pub fn group_until_transaction(&mut self, tx_id: TransactionId, cx: &mut Context<Self>) {
 9057        self.buffer
 9058            .update(cx, |buffer, cx| buffer.group_until_transaction(tx_id, cx));
 9059    }
 9060
 9061    pub fn move_left(&mut self, _: &MoveLeft, window: &mut Window, cx: &mut Context<Self>) {
 9062        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9063            let line_mode = s.line_mode;
 9064            s.move_with(|map, selection| {
 9065                let cursor = if selection.is_empty() && !line_mode {
 9066                    movement::left(map, selection.start)
 9067                } else {
 9068                    selection.start
 9069                };
 9070                selection.collapse_to(cursor, SelectionGoal::None);
 9071            });
 9072        })
 9073    }
 9074
 9075    pub fn select_left(&mut self, _: &SelectLeft, window: &mut Window, cx: &mut Context<Self>) {
 9076        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9077            s.move_heads_with(|map, head, _| (movement::left(map, head), SelectionGoal::None));
 9078        })
 9079    }
 9080
 9081    pub fn move_right(&mut self, _: &MoveRight, window: &mut Window, cx: &mut Context<Self>) {
 9082        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9083            let line_mode = s.line_mode;
 9084            s.move_with(|map, selection| {
 9085                let cursor = if selection.is_empty() && !line_mode {
 9086                    movement::right(map, selection.end)
 9087                } else {
 9088                    selection.end
 9089                };
 9090                selection.collapse_to(cursor, SelectionGoal::None)
 9091            });
 9092        })
 9093    }
 9094
 9095    pub fn select_right(&mut self, _: &SelectRight, window: &mut Window, cx: &mut Context<Self>) {
 9096        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9097            s.move_heads_with(|map, head, _| (movement::right(map, head), SelectionGoal::None));
 9098        })
 9099    }
 9100
 9101    pub fn move_up(&mut self, _: &MoveUp, window: &mut Window, cx: &mut Context<Self>) {
 9102        if self.take_rename(true, window, cx).is_some() {
 9103            return;
 9104        }
 9105
 9106        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 9107            cx.propagate();
 9108            return;
 9109        }
 9110
 9111        let text_layout_details = &self.text_layout_details(window);
 9112        let selection_count = self.selections.count();
 9113        let first_selection = self.selections.first_anchor();
 9114
 9115        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9116            let line_mode = s.line_mode;
 9117            s.move_with(|map, selection| {
 9118                if !selection.is_empty() && !line_mode {
 9119                    selection.goal = SelectionGoal::None;
 9120                }
 9121                let (cursor, goal) = movement::up(
 9122                    map,
 9123                    selection.start,
 9124                    selection.goal,
 9125                    false,
 9126                    text_layout_details,
 9127                );
 9128                selection.collapse_to(cursor, goal);
 9129            });
 9130        });
 9131
 9132        if selection_count == 1 && first_selection.range() == self.selections.first_anchor().range()
 9133        {
 9134            cx.propagate();
 9135        }
 9136    }
 9137
 9138    pub fn move_up_by_lines(
 9139        &mut self,
 9140        action: &MoveUpByLines,
 9141        window: &mut Window,
 9142        cx: &mut Context<Self>,
 9143    ) {
 9144        if self.take_rename(true, window, cx).is_some() {
 9145            return;
 9146        }
 9147
 9148        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 9149            cx.propagate();
 9150            return;
 9151        }
 9152
 9153        let text_layout_details = &self.text_layout_details(window);
 9154
 9155        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9156            let line_mode = s.line_mode;
 9157            s.move_with(|map, selection| {
 9158                if !selection.is_empty() && !line_mode {
 9159                    selection.goal = SelectionGoal::None;
 9160                }
 9161                let (cursor, goal) = movement::up_by_rows(
 9162                    map,
 9163                    selection.start,
 9164                    action.lines,
 9165                    selection.goal,
 9166                    false,
 9167                    text_layout_details,
 9168                );
 9169                selection.collapse_to(cursor, goal);
 9170            });
 9171        })
 9172    }
 9173
 9174    pub fn move_down_by_lines(
 9175        &mut self,
 9176        action: &MoveDownByLines,
 9177        window: &mut Window,
 9178        cx: &mut Context<Self>,
 9179    ) {
 9180        if self.take_rename(true, window, cx).is_some() {
 9181            return;
 9182        }
 9183
 9184        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 9185            cx.propagate();
 9186            return;
 9187        }
 9188
 9189        let text_layout_details = &self.text_layout_details(window);
 9190
 9191        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9192            let line_mode = s.line_mode;
 9193            s.move_with(|map, selection| {
 9194                if !selection.is_empty() && !line_mode {
 9195                    selection.goal = SelectionGoal::None;
 9196                }
 9197                let (cursor, goal) = movement::down_by_rows(
 9198                    map,
 9199                    selection.start,
 9200                    action.lines,
 9201                    selection.goal,
 9202                    false,
 9203                    text_layout_details,
 9204                );
 9205                selection.collapse_to(cursor, goal);
 9206            });
 9207        })
 9208    }
 9209
 9210    pub fn select_down_by_lines(
 9211        &mut self,
 9212        action: &SelectDownByLines,
 9213        window: &mut Window,
 9214        cx: &mut Context<Self>,
 9215    ) {
 9216        let text_layout_details = &self.text_layout_details(window);
 9217        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9218            s.move_heads_with(|map, head, goal| {
 9219                movement::down_by_rows(map, head, action.lines, goal, false, text_layout_details)
 9220            })
 9221        })
 9222    }
 9223
 9224    pub fn select_up_by_lines(
 9225        &mut self,
 9226        action: &SelectUpByLines,
 9227        window: &mut Window,
 9228        cx: &mut Context<Self>,
 9229    ) {
 9230        let text_layout_details = &self.text_layout_details(window);
 9231        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9232            s.move_heads_with(|map, head, goal| {
 9233                movement::up_by_rows(map, head, action.lines, goal, false, text_layout_details)
 9234            })
 9235        })
 9236    }
 9237
 9238    pub fn select_page_up(
 9239        &mut self,
 9240        _: &SelectPageUp,
 9241        window: &mut Window,
 9242        cx: &mut Context<Self>,
 9243    ) {
 9244        let Some(row_count) = self.visible_row_count() else {
 9245            return;
 9246        };
 9247
 9248        let text_layout_details = &self.text_layout_details(window);
 9249
 9250        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9251            s.move_heads_with(|map, head, goal| {
 9252                movement::up_by_rows(map, head, row_count, goal, false, text_layout_details)
 9253            })
 9254        })
 9255    }
 9256
 9257    pub fn move_page_up(
 9258        &mut self,
 9259        action: &MovePageUp,
 9260        window: &mut Window,
 9261        cx: &mut Context<Self>,
 9262    ) {
 9263        if self.take_rename(true, window, cx).is_some() {
 9264            return;
 9265        }
 9266
 9267        if self
 9268            .context_menu
 9269            .borrow_mut()
 9270            .as_mut()
 9271            .map(|menu| menu.select_first(self.completion_provider.as_deref(), cx))
 9272            .unwrap_or(false)
 9273        {
 9274            return;
 9275        }
 9276
 9277        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 9278            cx.propagate();
 9279            return;
 9280        }
 9281
 9282        let Some(row_count) = self.visible_row_count() else {
 9283            return;
 9284        };
 9285
 9286        let autoscroll = if action.center_cursor {
 9287            Autoscroll::center()
 9288        } else {
 9289            Autoscroll::fit()
 9290        };
 9291
 9292        let text_layout_details = &self.text_layout_details(window);
 9293
 9294        self.change_selections(Some(autoscroll), window, cx, |s| {
 9295            let line_mode = s.line_mode;
 9296            s.move_with(|map, selection| {
 9297                if !selection.is_empty() && !line_mode {
 9298                    selection.goal = SelectionGoal::None;
 9299                }
 9300                let (cursor, goal) = movement::up_by_rows(
 9301                    map,
 9302                    selection.end,
 9303                    row_count,
 9304                    selection.goal,
 9305                    false,
 9306                    text_layout_details,
 9307                );
 9308                selection.collapse_to(cursor, goal);
 9309            });
 9310        });
 9311    }
 9312
 9313    pub fn select_up(&mut self, _: &SelectUp, window: &mut Window, cx: &mut Context<Self>) {
 9314        let text_layout_details = &self.text_layout_details(window);
 9315        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9316            s.move_heads_with(|map, head, goal| {
 9317                movement::up(map, head, goal, false, text_layout_details)
 9318            })
 9319        })
 9320    }
 9321
 9322    pub fn move_down(&mut self, _: &MoveDown, window: &mut Window, cx: &mut Context<Self>) {
 9323        self.take_rename(true, window, cx);
 9324
 9325        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 9326            cx.propagate();
 9327            return;
 9328        }
 9329
 9330        let text_layout_details = &self.text_layout_details(window);
 9331        let selection_count = self.selections.count();
 9332        let first_selection = self.selections.first_anchor();
 9333
 9334        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9335            let line_mode = s.line_mode;
 9336            s.move_with(|map, selection| {
 9337                if !selection.is_empty() && !line_mode {
 9338                    selection.goal = SelectionGoal::None;
 9339                }
 9340                let (cursor, goal) = movement::down(
 9341                    map,
 9342                    selection.end,
 9343                    selection.goal,
 9344                    false,
 9345                    text_layout_details,
 9346                );
 9347                selection.collapse_to(cursor, goal);
 9348            });
 9349        });
 9350
 9351        if selection_count == 1 && first_selection.range() == self.selections.first_anchor().range()
 9352        {
 9353            cx.propagate();
 9354        }
 9355    }
 9356
 9357    pub fn select_page_down(
 9358        &mut self,
 9359        _: &SelectPageDown,
 9360        window: &mut Window,
 9361        cx: &mut Context<Self>,
 9362    ) {
 9363        let Some(row_count) = self.visible_row_count() else {
 9364            return;
 9365        };
 9366
 9367        let text_layout_details = &self.text_layout_details(window);
 9368
 9369        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9370            s.move_heads_with(|map, head, goal| {
 9371                movement::down_by_rows(map, head, row_count, goal, false, text_layout_details)
 9372            })
 9373        })
 9374    }
 9375
 9376    pub fn move_page_down(
 9377        &mut self,
 9378        action: &MovePageDown,
 9379        window: &mut Window,
 9380        cx: &mut Context<Self>,
 9381    ) {
 9382        if self.take_rename(true, window, cx).is_some() {
 9383            return;
 9384        }
 9385
 9386        if self
 9387            .context_menu
 9388            .borrow_mut()
 9389            .as_mut()
 9390            .map(|menu| menu.select_last(self.completion_provider.as_deref(), cx))
 9391            .unwrap_or(false)
 9392        {
 9393            return;
 9394        }
 9395
 9396        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 9397            cx.propagate();
 9398            return;
 9399        }
 9400
 9401        let Some(row_count) = self.visible_row_count() else {
 9402            return;
 9403        };
 9404
 9405        let autoscroll = if action.center_cursor {
 9406            Autoscroll::center()
 9407        } else {
 9408            Autoscroll::fit()
 9409        };
 9410
 9411        let text_layout_details = &self.text_layout_details(window);
 9412        self.change_selections(Some(autoscroll), window, cx, |s| {
 9413            let line_mode = s.line_mode;
 9414            s.move_with(|map, selection| {
 9415                if !selection.is_empty() && !line_mode {
 9416                    selection.goal = SelectionGoal::None;
 9417                }
 9418                let (cursor, goal) = movement::down_by_rows(
 9419                    map,
 9420                    selection.end,
 9421                    row_count,
 9422                    selection.goal,
 9423                    false,
 9424                    text_layout_details,
 9425                );
 9426                selection.collapse_to(cursor, goal);
 9427            });
 9428        });
 9429    }
 9430
 9431    pub fn select_down(&mut self, _: &SelectDown, window: &mut Window, cx: &mut Context<Self>) {
 9432        let text_layout_details = &self.text_layout_details(window);
 9433        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9434            s.move_heads_with(|map, head, goal| {
 9435                movement::down(map, head, goal, false, text_layout_details)
 9436            })
 9437        });
 9438    }
 9439
 9440    pub fn context_menu_first(
 9441        &mut self,
 9442        _: &ContextMenuFirst,
 9443        _window: &mut Window,
 9444        cx: &mut Context<Self>,
 9445    ) {
 9446        if let Some(context_menu) = self.context_menu.borrow_mut().as_mut() {
 9447            context_menu.select_first(self.completion_provider.as_deref(), cx);
 9448        }
 9449    }
 9450
 9451    pub fn context_menu_prev(
 9452        &mut self,
 9453        _: &ContextMenuPrevious,
 9454        _window: &mut Window,
 9455        cx: &mut Context<Self>,
 9456    ) {
 9457        if let Some(context_menu) = self.context_menu.borrow_mut().as_mut() {
 9458            context_menu.select_prev(self.completion_provider.as_deref(), cx);
 9459        }
 9460    }
 9461
 9462    pub fn context_menu_next(
 9463        &mut self,
 9464        _: &ContextMenuNext,
 9465        _window: &mut Window,
 9466        cx: &mut Context<Self>,
 9467    ) {
 9468        if let Some(context_menu) = self.context_menu.borrow_mut().as_mut() {
 9469            context_menu.select_next(self.completion_provider.as_deref(), cx);
 9470        }
 9471    }
 9472
 9473    pub fn context_menu_last(
 9474        &mut self,
 9475        _: &ContextMenuLast,
 9476        _window: &mut Window,
 9477        cx: &mut Context<Self>,
 9478    ) {
 9479        if let Some(context_menu) = self.context_menu.borrow_mut().as_mut() {
 9480            context_menu.select_last(self.completion_provider.as_deref(), cx);
 9481        }
 9482    }
 9483
 9484    pub fn move_to_previous_word_start(
 9485        &mut self,
 9486        _: &MoveToPreviousWordStart,
 9487        window: &mut Window,
 9488        cx: &mut Context<Self>,
 9489    ) {
 9490        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9491            s.move_cursors_with(|map, head, _| {
 9492                (
 9493                    movement::previous_word_start(map, head),
 9494                    SelectionGoal::None,
 9495                )
 9496            });
 9497        })
 9498    }
 9499
 9500    pub fn move_to_previous_subword_start(
 9501        &mut self,
 9502        _: &MoveToPreviousSubwordStart,
 9503        window: &mut Window,
 9504        cx: &mut Context<Self>,
 9505    ) {
 9506        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9507            s.move_cursors_with(|map, head, _| {
 9508                (
 9509                    movement::previous_subword_start(map, head),
 9510                    SelectionGoal::None,
 9511                )
 9512            });
 9513        })
 9514    }
 9515
 9516    pub fn select_to_previous_word_start(
 9517        &mut self,
 9518        _: &SelectToPreviousWordStart,
 9519        window: &mut Window,
 9520        cx: &mut Context<Self>,
 9521    ) {
 9522        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9523            s.move_heads_with(|map, head, _| {
 9524                (
 9525                    movement::previous_word_start(map, head),
 9526                    SelectionGoal::None,
 9527                )
 9528            });
 9529        })
 9530    }
 9531
 9532    pub fn select_to_previous_subword_start(
 9533        &mut self,
 9534        _: &SelectToPreviousSubwordStart,
 9535        window: &mut Window,
 9536        cx: &mut Context<Self>,
 9537    ) {
 9538        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9539            s.move_heads_with(|map, head, _| {
 9540                (
 9541                    movement::previous_subword_start(map, head),
 9542                    SelectionGoal::None,
 9543                )
 9544            });
 9545        })
 9546    }
 9547
 9548    pub fn delete_to_previous_word_start(
 9549        &mut self,
 9550        action: &DeleteToPreviousWordStart,
 9551        window: &mut Window,
 9552        cx: &mut Context<Self>,
 9553    ) {
 9554        self.transact(window, cx, |this, window, cx| {
 9555            this.select_autoclose_pair(window, cx);
 9556            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9557                let line_mode = s.line_mode;
 9558                s.move_with(|map, selection| {
 9559                    if selection.is_empty() && !line_mode {
 9560                        let cursor = if action.ignore_newlines {
 9561                            movement::previous_word_start(map, selection.head())
 9562                        } else {
 9563                            movement::previous_word_start_or_newline(map, selection.head())
 9564                        };
 9565                        selection.set_head(cursor, SelectionGoal::None);
 9566                    }
 9567                });
 9568            });
 9569            this.insert("", window, cx);
 9570        });
 9571    }
 9572
 9573    pub fn delete_to_previous_subword_start(
 9574        &mut self,
 9575        _: &DeleteToPreviousSubwordStart,
 9576        window: &mut Window,
 9577        cx: &mut Context<Self>,
 9578    ) {
 9579        self.transact(window, cx, |this, window, cx| {
 9580            this.select_autoclose_pair(window, cx);
 9581            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9582                let line_mode = s.line_mode;
 9583                s.move_with(|map, selection| {
 9584                    if selection.is_empty() && !line_mode {
 9585                        let cursor = movement::previous_subword_start(map, selection.head());
 9586                        selection.set_head(cursor, SelectionGoal::None);
 9587                    }
 9588                });
 9589            });
 9590            this.insert("", window, cx);
 9591        });
 9592    }
 9593
 9594    pub fn move_to_next_word_end(
 9595        &mut self,
 9596        _: &MoveToNextWordEnd,
 9597        window: &mut Window,
 9598        cx: &mut Context<Self>,
 9599    ) {
 9600        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9601            s.move_cursors_with(|map, head, _| {
 9602                (movement::next_word_end(map, head), SelectionGoal::None)
 9603            });
 9604        })
 9605    }
 9606
 9607    pub fn move_to_next_subword_end(
 9608        &mut self,
 9609        _: &MoveToNextSubwordEnd,
 9610        window: &mut Window,
 9611        cx: &mut Context<Self>,
 9612    ) {
 9613        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9614            s.move_cursors_with(|map, head, _| {
 9615                (movement::next_subword_end(map, head), SelectionGoal::None)
 9616            });
 9617        })
 9618    }
 9619
 9620    pub fn select_to_next_word_end(
 9621        &mut self,
 9622        _: &SelectToNextWordEnd,
 9623        window: &mut Window,
 9624        cx: &mut Context<Self>,
 9625    ) {
 9626        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9627            s.move_heads_with(|map, head, _| {
 9628                (movement::next_word_end(map, head), SelectionGoal::None)
 9629            });
 9630        })
 9631    }
 9632
 9633    pub fn select_to_next_subword_end(
 9634        &mut self,
 9635        _: &SelectToNextSubwordEnd,
 9636        window: &mut Window,
 9637        cx: &mut Context<Self>,
 9638    ) {
 9639        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9640            s.move_heads_with(|map, head, _| {
 9641                (movement::next_subword_end(map, head), SelectionGoal::None)
 9642            });
 9643        })
 9644    }
 9645
 9646    pub fn delete_to_next_word_end(
 9647        &mut self,
 9648        action: &DeleteToNextWordEnd,
 9649        window: &mut Window,
 9650        cx: &mut Context<Self>,
 9651    ) {
 9652        self.transact(window, cx, |this, window, cx| {
 9653            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9654                let line_mode = s.line_mode;
 9655                s.move_with(|map, selection| {
 9656                    if selection.is_empty() && !line_mode {
 9657                        let cursor = if action.ignore_newlines {
 9658                            movement::next_word_end(map, selection.head())
 9659                        } else {
 9660                            movement::next_word_end_or_newline(map, selection.head())
 9661                        };
 9662                        selection.set_head(cursor, SelectionGoal::None);
 9663                    }
 9664                });
 9665            });
 9666            this.insert("", window, cx);
 9667        });
 9668    }
 9669
 9670    pub fn delete_to_next_subword_end(
 9671        &mut self,
 9672        _: &DeleteToNextSubwordEnd,
 9673        window: &mut Window,
 9674        cx: &mut Context<Self>,
 9675    ) {
 9676        self.transact(window, cx, |this, window, cx| {
 9677            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9678                s.move_with(|map, selection| {
 9679                    if selection.is_empty() {
 9680                        let cursor = movement::next_subword_end(map, selection.head());
 9681                        selection.set_head(cursor, SelectionGoal::None);
 9682                    }
 9683                });
 9684            });
 9685            this.insert("", window, cx);
 9686        });
 9687    }
 9688
 9689    pub fn move_to_beginning_of_line(
 9690        &mut self,
 9691        action: &MoveToBeginningOfLine,
 9692        window: &mut Window,
 9693        cx: &mut Context<Self>,
 9694    ) {
 9695        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9696            s.move_cursors_with(|map, head, _| {
 9697                (
 9698                    movement::indented_line_beginning(
 9699                        map,
 9700                        head,
 9701                        action.stop_at_soft_wraps,
 9702                        action.stop_at_indent,
 9703                    ),
 9704                    SelectionGoal::None,
 9705                )
 9706            });
 9707        })
 9708    }
 9709
 9710    pub fn select_to_beginning_of_line(
 9711        &mut self,
 9712        action: &SelectToBeginningOfLine,
 9713        window: &mut Window,
 9714        cx: &mut Context<Self>,
 9715    ) {
 9716        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9717            s.move_heads_with(|map, head, _| {
 9718                (
 9719                    movement::indented_line_beginning(
 9720                        map,
 9721                        head,
 9722                        action.stop_at_soft_wraps,
 9723                        action.stop_at_indent,
 9724                    ),
 9725                    SelectionGoal::None,
 9726                )
 9727            });
 9728        });
 9729    }
 9730
 9731    pub fn delete_to_beginning_of_line(
 9732        &mut self,
 9733        action: &DeleteToBeginningOfLine,
 9734        window: &mut Window,
 9735        cx: &mut Context<Self>,
 9736    ) {
 9737        self.transact(window, cx, |this, window, cx| {
 9738            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9739                s.move_with(|_, selection| {
 9740                    selection.reversed = true;
 9741                });
 9742            });
 9743
 9744            this.select_to_beginning_of_line(
 9745                &SelectToBeginningOfLine {
 9746                    stop_at_soft_wraps: false,
 9747                    stop_at_indent: action.stop_at_indent,
 9748                },
 9749                window,
 9750                cx,
 9751            );
 9752            this.backspace(&Backspace, window, cx);
 9753        });
 9754    }
 9755
 9756    pub fn move_to_end_of_line(
 9757        &mut self,
 9758        action: &MoveToEndOfLine,
 9759        window: &mut Window,
 9760        cx: &mut Context<Self>,
 9761    ) {
 9762        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9763            s.move_cursors_with(|map, head, _| {
 9764                (
 9765                    movement::line_end(map, head, action.stop_at_soft_wraps),
 9766                    SelectionGoal::None,
 9767                )
 9768            });
 9769        })
 9770    }
 9771
 9772    pub fn select_to_end_of_line(
 9773        &mut self,
 9774        action: &SelectToEndOfLine,
 9775        window: &mut Window,
 9776        cx: &mut Context<Self>,
 9777    ) {
 9778        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9779            s.move_heads_with(|map, head, _| {
 9780                (
 9781                    movement::line_end(map, head, action.stop_at_soft_wraps),
 9782                    SelectionGoal::None,
 9783                )
 9784            });
 9785        })
 9786    }
 9787
 9788    pub fn delete_to_end_of_line(
 9789        &mut self,
 9790        _: &DeleteToEndOfLine,
 9791        window: &mut Window,
 9792        cx: &mut Context<Self>,
 9793    ) {
 9794        self.transact(window, cx, |this, window, cx| {
 9795            this.select_to_end_of_line(
 9796                &SelectToEndOfLine {
 9797                    stop_at_soft_wraps: false,
 9798                },
 9799                window,
 9800                cx,
 9801            );
 9802            this.delete(&Delete, window, cx);
 9803        });
 9804    }
 9805
 9806    pub fn cut_to_end_of_line(
 9807        &mut self,
 9808        _: &CutToEndOfLine,
 9809        window: &mut Window,
 9810        cx: &mut Context<Self>,
 9811    ) {
 9812        self.transact(window, cx, |this, window, cx| {
 9813            this.select_to_end_of_line(
 9814                &SelectToEndOfLine {
 9815                    stop_at_soft_wraps: false,
 9816                },
 9817                window,
 9818                cx,
 9819            );
 9820            this.cut(&Cut, window, cx);
 9821        });
 9822    }
 9823
 9824    pub fn move_to_start_of_paragraph(
 9825        &mut self,
 9826        _: &MoveToStartOfParagraph,
 9827        window: &mut Window,
 9828        cx: &mut Context<Self>,
 9829    ) {
 9830        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 9831            cx.propagate();
 9832            return;
 9833        }
 9834
 9835        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9836            s.move_with(|map, selection| {
 9837                selection.collapse_to(
 9838                    movement::start_of_paragraph(map, selection.head(), 1),
 9839                    SelectionGoal::None,
 9840                )
 9841            });
 9842        })
 9843    }
 9844
 9845    pub fn move_to_end_of_paragraph(
 9846        &mut self,
 9847        _: &MoveToEndOfParagraph,
 9848        window: &mut Window,
 9849        cx: &mut Context<Self>,
 9850    ) {
 9851        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 9852            cx.propagate();
 9853            return;
 9854        }
 9855
 9856        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9857            s.move_with(|map, selection| {
 9858                selection.collapse_to(
 9859                    movement::end_of_paragraph(map, selection.head(), 1),
 9860                    SelectionGoal::None,
 9861                )
 9862            });
 9863        })
 9864    }
 9865
 9866    pub fn select_to_start_of_paragraph(
 9867        &mut self,
 9868        _: &SelectToStartOfParagraph,
 9869        window: &mut Window,
 9870        cx: &mut Context<Self>,
 9871    ) {
 9872        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 9873            cx.propagate();
 9874            return;
 9875        }
 9876
 9877        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9878            s.move_heads_with(|map, head, _| {
 9879                (
 9880                    movement::start_of_paragraph(map, head, 1),
 9881                    SelectionGoal::None,
 9882                )
 9883            });
 9884        })
 9885    }
 9886
 9887    pub fn select_to_end_of_paragraph(
 9888        &mut self,
 9889        _: &SelectToEndOfParagraph,
 9890        window: &mut Window,
 9891        cx: &mut Context<Self>,
 9892    ) {
 9893        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 9894            cx.propagate();
 9895            return;
 9896        }
 9897
 9898        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9899            s.move_heads_with(|map, head, _| {
 9900                (
 9901                    movement::end_of_paragraph(map, head, 1),
 9902                    SelectionGoal::None,
 9903                )
 9904            });
 9905        })
 9906    }
 9907
 9908    pub fn move_to_start_of_excerpt(
 9909        &mut self,
 9910        _: &MoveToStartOfExcerpt,
 9911        window: &mut Window,
 9912        cx: &mut Context<Self>,
 9913    ) {
 9914        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 9915            cx.propagate();
 9916            return;
 9917        }
 9918
 9919        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9920            s.move_with(|map, selection| {
 9921                selection.collapse_to(
 9922                    movement::start_of_excerpt(
 9923                        map,
 9924                        selection.head(),
 9925                        workspace::searchable::Direction::Prev,
 9926                    ),
 9927                    SelectionGoal::None,
 9928                )
 9929            });
 9930        })
 9931    }
 9932
 9933    pub fn move_to_start_of_next_excerpt(
 9934        &mut self,
 9935        _: &MoveToStartOfNextExcerpt,
 9936        window: &mut Window,
 9937        cx: &mut Context<Self>,
 9938    ) {
 9939        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 9940            cx.propagate();
 9941            return;
 9942        }
 9943
 9944        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9945            s.move_with(|map, selection| {
 9946                selection.collapse_to(
 9947                    movement::start_of_excerpt(
 9948                        map,
 9949                        selection.head(),
 9950                        workspace::searchable::Direction::Next,
 9951                    ),
 9952                    SelectionGoal::None,
 9953                )
 9954            });
 9955        })
 9956    }
 9957
 9958    pub fn move_to_end_of_excerpt(
 9959        &mut self,
 9960        _: &MoveToEndOfExcerpt,
 9961        window: &mut Window,
 9962        cx: &mut Context<Self>,
 9963    ) {
 9964        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 9965            cx.propagate();
 9966            return;
 9967        }
 9968
 9969        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9970            s.move_with(|map, selection| {
 9971                selection.collapse_to(
 9972                    movement::end_of_excerpt(
 9973                        map,
 9974                        selection.head(),
 9975                        workspace::searchable::Direction::Next,
 9976                    ),
 9977                    SelectionGoal::None,
 9978                )
 9979            });
 9980        })
 9981    }
 9982
 9983    pub fn move_to_end_of_previous_excerpt(
 9984        &mut self,
 9985        _: &MoveToEndOfPreviousExcerpt,
 9986        window: &mut Window,
 9987        cx: &mut Context<Self>,
 9988    ) {
 9989        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 9990            cx.propagate();
 9991            return;
 9992        }
 9993
 9994        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9995            s.move_with(|map, selection| {
 9996                selection.collapse_to(
 9997                    movement::end_of_excerpt(
 9998                        map,
 9999                        selection.head(),
10000                        workspace::searchable::Direction::Prev,
10001                    ),
10002                    SelectionGoal::None,
10003                )
10004            });
10005        })
10006    }
10007
10008    pub fn select_to_start_of_excerpt(
10009        &mut self,
10010        _: &SelectToStartOfExcerpt,
10011        window: &mut Window,
10012        cx: &mut Context<Self>,
10013    ) {
10014        if matches!(self.mode, EditorMode::SingleLine { .. }) {
10015            cx.propagate();
10016            return;
10017        }
10018
10019        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10020            s.move_heads_with(|map, head, _| {
10021                (
10022                    movement::start_of_excerpt(map, head, workspace::searchable::Direction::Prev),
10023                    SelectionGoal::None,
10024                )
10025            });
10026        })
10027    }
10028
10029    pub fn select_to_start_of_next_excerpt(
10030        &mut self,
10031        _: &SelectToStartOfNextExcerpt,
10032        window: &mut Window,
10033        cx: &mut Context<Self>,
10034    ) {
10035        if matches!(self.mode, EditorMode::SingleLine { .. }) {
10036            cx.propagate();
10037            return;
10038        }
10039
10040        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10041            s.move_heads_with(|map, head, _| {
10042                (
10043                    movement::start_of_excerpt(map, head, workspace::searchable::Direction::Next),
10044                    SelectionGoal::None,
10045                )
10046            });
10047        })
10048    }
10049
10050    pub fn select_to_end_of_excerpt(
10051        &mut self,
10052        _: &SelectToEndOfExcerpt,
10053        window: &mut Window,
10054        cx: &mut Context<Self>,
10055    ) {
10056        if matches!(self.mode, EditorMode::SingleLine { .. }) {
10057            cx.propagate();
10058            return;
10059        }
10060
10061        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10062            s.move_heads_with(|map, head, _| {
10063                (
10064                    movement::end_of_excerpt(map, head, workspace::searchable::Direction::Next),
10065                    SelectionGoal::None,
10066                )
10067            });
10068        })
10069    }
10070
10071    pub fn select_to_end_of_previous_excerpt(
10072        &mut self,
10073        _: &SelectToEndOfPreviousExcerpt,
10074        window: &mut Window,
10075        cx: &mut Context<Self>,
10076    ) {
10077        if matches!(self.mode, EditorMode::SingleLine { .. }) {
10078            cx.propagate();
10079            return;
10080        }
10081
10082        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10083            s.move_heads_with(|map, head, _| {
10084                (
10085                    movement::end_of_excerpt(map, head, workspace::searchable::Direction::Prev),
10086                    SelectionGoal::None,
10087                )
10088            });
10089        })
10090    }
10091
10092    pub fn move_to_beginning(
10093        &mut self,
10094        _: &MoveToBeginning,
10095        window: &mut Window,
10096        cx: &mut Context<Self>,
10097    ) {
10098        if matches!(self.mode, EditorMode::SingleLine { .. }) {
10099            cx.propagate();
10100            return;
10101        }
10102
10103        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10104            s.select_ranges(vec![0..0]);
10105        });
10106    }
10107
10108    pub fn select_to_beginning(
10109        &mut self,
10110        _: &SelectToBeginning,
10111        window: &mut Window,
10112        cx: &mut Context<Self>,
10113    ) {
10114        let mut selection = self.selections.last::<Point>(cx);
10115        selection.set_head(Point::zero(), SelectionGoal::None);
10116
10117        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10118            s.select(vec![selection]);
10119        });
10120    }
10121
10122    pub fn move_to_end(&mut self, _: &MoveToEnd, window: &mut Window, cx: &mut Context<Self>) {
10123        if matches!(self.mode, EditorMode::SingleLine { .. }) {
10124            cx.propagate();
10125            return;
10126        }
10127
10128        let cursor = self.buffer.read(cx).read(cx).len();
10129        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10130            s.select_ranges(vec![cursor..cursor])
10131        });
10132    }
10133
10134    pub fn set_nav_history(&mut self, nav_history: Option<ItemNavHistory>) {
10135        self.nav_history = nav_history;
10136    }
10137
10138    pub fn nav_history(&self) -> Option<&ItemNavHistory> {
10139        self.nav_history.as_ref()
10140    }
10141
10142    fn push_to_nav_history(
10143        &mut self,
10144        cursor_anchor: Anchor,
10145        new_position: Option<Point>,
10146        cx: &mut Context<Self>,
10147    ) {
10148        if let Some(nav_history) = self.nav_history.as_mut() {
10149            let buffer = self.buffer.read(cx).read(cx);
10150            let cursor_position = cursor_anchor.to_point(&buffer);
10151            let scroll_state = self.scroll_manager.anchor();
10152            let scroll_top_row = scroll_state.top_row(&buffer);
10153            drop(buffer);
10154
10155            if let Some(new_position) = new_position {
10156                let row_delta = (new_position.row as i64 - cursor_position.row as i64).abs();
10157                if row_delta < MIN_NAVIGATION_HISTORY_ROW_DELTA {
10158                    return;
10159                }
10160            }
10161
10162            nav_history.push(
10163                Some(NavigationData {
10164                    cursor_anchor,
10165                    cursor_position,
10166                    scroll_anchor: scroll_state,
10167                    scroll_top_row,
10168                }),
10169                cx,
10170            );
10171        }
10172    }
10173
10174    pub fn select_to_end(&mut self, _: &SelectToEnd, window: &mut Window, cx: &mut Context<Self>) {
10175        let buffer = self.buffer.read(cx).snapshot(cx);
10176        let mut selection = self.selections.first::<usize>(cx);
10177        selection.set_head(buffer.len(), SelectionGoal::None);
10178        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10179            s.select(vec![selection]);
10180        });
10181    }
10182
10183    pub fn select_all(&mut self, _: &SelectAll, window: &mut Window, cx: &mut Context<Self>) {
10184        let end = self.buffer.read(cx).read(cx).len();
10185        self.change_selections(None, window, cx, |s| {
10186            s.select_ranges(vec![0..end]);
10187        });
10188    }
10189
10190    pub fn select_line(&mut self, _: &SelectLine, window: &mut Window, cx: &mut Context<Self>) {
10191        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
10192        let mut selections = self.selections.all::<Point>(cx);
10193        let max_point = display_map.buffer_snapshot.max_point();
10194        for selection in &mut selections {
10195            let rows = selection.spanned_rows(true, &display_map);
10196            selection.start = Point::new(rows.start.0, 0);
10197            selection.end = cmp::min(max_point, Point::new(rows.end.0, 0));
10198            selection.reversed = false;
10199        }
10200        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10201            s.select(selections);
10202        });
10203    }
10204
10205    pub fn split_selection_into_lines(
10206        &mut self,
10207        _: &SplitSelectionIntoLines,
10208        window: &mut Window,
10209        cx: &mut Context<Self>,
10210    ) {
10211        let selections = self
10212            .selections
10213            .all::<Point>(cx)
10214            .into_iter()
10215            .map(|selection| selection.start..selection.end)
10216            .collect::<Vec<_>>();
10217        self.unfold_ranges(&selections, true, true, cx);
10218
10219        let mut new_selection_ranges = Vec::new();
10220        {
10221            let buffer = self.buffer.read(cx).read(cx);
10222            for selection in selections {
10223                for row in selection.start.row..selection.end.row {
10224                    let cursor = Point::new(row, buffer.line_len(MultiBufferRow(row)));
10225                    new_selection_ranges.push(cursor..cursor);
10226                }
10227
10228                let is_multiline_selection = selection.start.row != selection.end.row;
10229                // Don't insert last one if it's a multi-line selection ending at the start of a line,
10230                // so this action feels more ergonomic when paired with other selection operations
10231                let should_skip_last = is_multiline_selection && selection.end.column == 0;
10232                if !should_skip_last {
10233                    new_selection_ranges.push(selection.end..selection.end);
10234                }
10235            }
10236        }
10237        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10238            s.select_ranges(new_selection_ranges);
10239        });
10240    }
10241
10242    pub fn add_selection_above(
10243        &mut self,
10244        _: &AddSelectionAbove,
10245        window: &mut Window,
10246        cx: &mut Context<Self>,
10247    ) {
10248        self.add_selection(true, window, cx);
10249    }
10250
10251    pub fn add_selection_below(
10252        &mut self,
10253        _: &AddSelectionBelow,
10254        window: &mut Window,
10255        cx: &mut Context<Self>,
10256    ) {
10257        self.add_selection(false, window, cx);
10258    }
10259
10260    fn add_selection(&mut self, above: bool, window: &mut Window, cx: &mut Context<Self>) {
10261        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
10262        let mut selections = self.selections.all::<Point>(cx);
10263        let text_layout_details = self.text_layout_details(window);
10264        let mut state = self.add_selections_state.take().unwrap_or_else(|| {
10265            let oldest_selection = selections.iter().min_by_key(|s| s.id).unwrap().clone();
10266            let range = oldest_selection.display_range(&display_map).sorted();
10267
10268            let start_x = display_map.x_for_display_point(range.start, &text_layout_details);
10269            let end_x = display_map.x_for_display_point(range.end, &text_layout_details);
10270            let positions = start_x.min(end_x)..start_x.max(end_x);
10271
10272            selections.clear();
10273            let mut stack = Vec::new();
10274            for row in range.start.row().0..=range.end.row().0 {
10275                if let Some(selection) = self.selections.build_columnar_selection(
10276                    &display_map,
10277                    DisplayRow(row),
10278                    &positions,
10279                    oldest_selection.reversed,
10280                    &text_layout_details,
10281                ) {
10282                    stack.push(selection.id);
10283                    selections.push(selection);
10284                }
10285            }
10286
10287            if above {
10288                stack.reverse();
10289            }
10290
10291            AddSelectionsState { above, stack }
10292        });
10293
10294        let last_added_selection = *state.stack.last().unwrap();
10295        let mut new_selections = Vec::new();
10296        if above == state.above {
10297            let end_row = if above {
10298                DisplayRow(0)
10299            } else {
10300                display_map.max_point().row()
10301            };
10302
10303            'outer: for selection in selections {
10304                if selection.id == last_added_selection {
10305                    let range = selection.display_range(&display_map).sorted();
10306                    debug_assert_eq!(range.start.row(), range.end.row());
10307                    let mut row = range.start.row();
10308                    let positions =
10309                        if let SelectionGoal::HorizontalRange { start, end } = selection.goal {
10310                            px(start)..px(end)
10311                        } else {
10312                            let start_x =
10313                                display_map.x_for_display_point(range.start, &text_layout_details);
10314                            let end_x =
10315                                display_map.x_for_display_point(range.end, &text_layout_details);
10316                            start_x.min(end_x)..start_x.max(end_x)
10317                        };
10318
10319                    while row != end_row {
10320                        if above {
10321                            row.0 -= 1;
10322                        } else {
10323                            row.0 += 1;
10324                        }
10325
10326                        if let Some(new_selection) = self.selections.build_columnar_selection(
10327                            &display_map,
10328                            row,
10329                            &positions,
10330                            selection.reversed,
10331                            &text_layout_details,
10332                        ) {
10333                            state.stack.push(new_selection.id);
10334                            if above {
10335                                new_selections.push(new_selection);
10336                                new_selections.push(selection);
10337                            } else {
10338                                new_selections.push(selection);
10339                                new_selections.push(new_selection);
10340                            }
10341
10342                            continue 'outer;
10343                        }
10344                    }
10345                }
10346
10347                new_selections.push(selection);
10348            }
10349        } else {
10350            new_selections = selections;
10351            new_selections.retain(|s| s.id != last_added_selection);
10352            state.stack.pop();
10353        }
10354
10355        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10356            s.select(new_selections);
10357        });
10358        if state.stack.len() > 1 {
10359            self.add_selections_state = Some(state);
10360        }
10361    }
10362
10363    pub fn select_next_match_internal(
10364        &mut self,
10365        display_map: &DisplaySnapshot,
10366        replace_newest: bool,
10367        autoscroll: Option<Autoscroll>,
10368        window: &mut Window,
10369        cx: &mut Context<Self>,
10370    ) -> Result<()> {
10371        fn select_next_match_ranges(
10372            this: &mut Editor,
10373            range: Range<usize>,
10374            replace_newest: bool,
10375            auto_scroll: Option<Autoscroll>,
10376            window: &mut Window,
10377            cx: &mut Context<Editor>,
10378        ) {
10379            this.unfold_ranges(&[range.clone()], false, true, cx);
10380            this.change_selections(auto_scroll, window, cx, |s| {
10381                if replace_newest {
10382                    s.delete(s.newest_anchor().id);
10383                }
10384                s.insert_range(range.clone());
10385            });
10386        }
10387
10388        let buffer = &display_map.buffer_snapshot;
10389        let mut selections = self.selections.all::<usize>(cx);
10390        if let Some(mut select_next_state) = self.select_next_state.take() {
10391            let query = &select_next_state.query;
10392            if !select_next_state.done {
10393                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
10394                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
10395                let mut next_selected_range = None;
10396
10397                let bytes_after_last_selection =
10398                    buffer.bytes_in_range(last_selection.end..buffer.len());
10399                let bytes_before_first_selection = buffer.bytes_in_range(0..first_selection.start);
10400                let query_matches = query
10401                    .stream_find_iter(bytes_after_last_selection)
10402                    .map(|result| (last_selection.end, result))
10403                    .chain(
10404                        query
10405                            .stream_find_iter(bytes_before_first_selection)
10406                            .map(|result| (0, result)),
10407                    );
10408
10409                for (start_offset, query_match) in query_matches {
10410                    let query_match = query_match.unwrap(); // can only fail due to I/O
10411                    let offset_range =
10412                        start_offset + query_match.start()..start_offset + query_match.end();
10413                    let display_range = offset_range.start.to_display_point(display_map)
10414                        ..offset_range.end.to_display_point(display_map);
10415
10416                    if !select_next_state.wordwise
10417                        || (!movement::is_inside_word(display_map, display_range.start)
10418                            && !movement::is_inside_word(display_map, display_range.end))
10419                    {
10420                        // TODO: This is n^2, because we might check all the selections
10421                        if !selections
10422                            .iter()
10423                            .any(|selection| selection.range().overlaps(&offset_range))
10424                        {
10425                            next_selected_range = Some(offset_range);
10426                            break;
10427                        }
10428                    }
10429                }
10430
10431                if let Some(next_selected_range) = next_selected_range {
10432                    select_next_match_ranges(
10433                        self,
10434                        next_selected_range,
10435                        replace_newest,
10436                        autoscroll,
10437                        window,
10438                        cx,
10439                    );
10440                } else {
10441                    select_next_state.done = true;
10442                }
10443            }
10444
10445            self.select_next_state = Some(select_next_state);
10446        } else {
10447            let mut only_carets = true;
10448            let mut same_text_selected = true;
10449            let mut selected_text = None;
10450
10451            let mut selections_iter = selections.iter().peekable();
10452            while let Some(selection) = selections_iter.next() {
10453                if selection.start != selection.end {
10454                    only_carets = false;
10455                }
10456
10457                if same_text_selected {
10458                    if selected_text.is_none() {
10459                        selected_text =
10460                            Some(buffer.text_for_range(selection.range()).collect::<String>());
10461                    }
10462
10463                    if let Some(next_selection) = selections_iter.peek() {
10464                        if next_selection.range().len() == selection.range().len() {
10465                            let next_selected_text = buffer
10466                                .text_for_range(next_selection.range())
10467                                .collect::<String>();
10468                            if Some(next_selected_text) != selected_text {
10469                                same_text_selected = false;
10470                                selected_text = None;
10471                            }
10472                        } else {
10473                            same_text_selected = false;
10474                            selected_text = None;
10475                        }
10476                    }
10477                }
10478            }
10479
10480            if only_carets {
10481                for selection in &mut selections {
10482                    let word_range = movement::surrounding_word(
10483                        display_map,
10484                        selection.start.to_display_point(display_map),
10485                    );
10486                    selection.start = word_range.start.to_offset(display_map, Bias::Left);
10487                    selection.end = word_range.end.to_offset(display_map, Bias::Left);
10488                    selection.goal = SelectionGoal::None;
10489                    selection.reversed = false;
10490                    select_next_match_ranges(
10491                        self,
10492                        selection.start..selection.end,
10493                        replace_newest,
10494                        autoscroll,
10495                        window,
10496                        cx,
10497                    );
10498                }
10499
10500                if selections.len() == 1 {
10501                    let selection = selections
10502                        .last()
10503                        .expect("ensured that there's only one selection");
10504                    let query = buffer
10505                        .text_for_range(selection.start..selection.end)
10506                        .collect::<String>();
10507                    let is_empty = query.is_empty();
10508                    let select_state = SelectNextState {
10509                        query: AhoCorasick::new(&[query])?,
10510                        wordwise: true,
10511                        done: is_empty,
10512                    };
10513                    self.select_next_state = Some(select_state);
10514                } else {
10515                    self.select_next_state = None;
10516                }
10517            } else if let Some(selected_text) = selected_text {
10518                self.select_next_state = Some(SelectNextState {
10519                    query: AhoCorasick::new(&[selected_text])?,
10520                    wordwise: false,
10521                    done: false,
10522                });
10523                self.select_next_match_internal(
10524                    display_map,
10525                    replace_newest,
10526                    autoscroll,
10527                    window,
10528                    cx,
10529                )?;
10530            }
10531        }
10532        Ok(())
10533    }
10534
10535    pub fn select_all_matches(
10536        &mut self,
10537        _action: &SelectAllMatches,
10538        window: &mut Window,
10539        cx: &mut Context<Self>,
10540    ) -> Result<()> {
10541        self.push_to_selection_history();
10542        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
10543
10544        self.select_next_match_internal(&display_map, false, None, window, cx)?;
10545        let Some(select_next_state) = self.select_next_state.as_mut() else {
10546            return Ok(());
10547        };
10548        if select_next_state.done {
10549            return Ok(());
10550        }
10551
10552        let mut new_selections = self.selections.all::<usize>(cx);
10553
10554        let buffer = &display_map.buffer_snapshot;
10555        let query_matches = select_next_state
10556            .query
10557            .stream_find_iter(buffer.bytes_in_range(0..buffer.len()));
10558
10559        for query_match in query_matches {
10560            let query_match = query_match.unwrap(); // can only fail due to I/O
10561            let offset_range = query_match.start()..query_match.end();
10562            let display_range = offset_range.start.to_display_point(&display_map)
10563                ..offset_range.end.to_display_point(&display_map);
10564
10565            if !select_next_state.wordwise
10566                || (!movement::is_inside_word(&display_map, display_range.start)
10567                    && !movement::is_inside_word(&display_map, display_range.end))
10568            {
10569                self.selections.change_with(cx, |selections| {
10570                    new_selections.push(Selection {
10571                        id: selections.new_selection_id(),
10572                        start: offset_range.start,
10573                        end: offset_range.end,
10574                        reversed: false,
10575                        goal: SelectionGoal::None,
10576                    });
10577                });
10578            }
10579        }
10580
10581        new_selections.sort_by_key(|selection| selection.start);
10582        let mut ix = 0;
10583        while ix + 1 < new_selections.len() {
10584            let current_selection = &new_selections[ix];
10585            let next_selection = &new_selections[ix + 1];
10586            if current_selection.range().overlaps(&next_selection.range()) {
10587                if current_selection.id < next_selection.id {
10588                    new_selections.remove(ix + 1);
10589                } else {
10590                    new_selections.remove(ix);
10591                }
10592            } else {
10593                ix += 1;
10594            }
10595        }
10596
10597        let reversed = self.selections.oldest::<usize>(cx).reversed;
10598
10599        for selection in new_selections.iter_mut() {
10600            selection.reversed = reversed;
10601        }
10602
10603        select_next_state.done = true;
10604        self.unfold_ranges(
10605            &new_selections
10606                .iter()
10607                .map(|selection| selection.range())
10608                .collect::<Vec<_>>(),
10609            false,
10610            false,
10611            cx,
10612        );
10613        self.change_selections(Some(Autoscroll::fit()), window, cx, |selections| {
10614            selections.select(new_selections)
10615        });
10616
10617        Ok(())
10618    }
10619
10620    pub fn select_next(
10621        &mut self,
10622        action: &SelectNext,
10623        window: &mut Window,
10624        cx: &mut Context<Self>,
10625    ) -> Result<()> {
10626        self.push_to_selection_history();
10627        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
10628        self.select_next_match_internal(
10629            &display_map,
10630            action.replace_newest,
10631            Some(Autoscroll::newest()),
10632            window,
10633            cx,
10634        )?;
10635        Ok(())
10636    }
10637
10638    pub fn select_previous(
10639        &mut self,
10640        action: &SelectPrevious,
10641        window: &mut Window,
10642        cx: &mut Context<Self>,
10643    ) -> Result<()> {
10644        self.push_to_selection_history();
10645        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
10646        let buffer = &display_map.buffer_snapshot;
10647        let mut selections = self.selections.all::<usize>(cx);
10648        if let Some(mut select_prev_state) = self.select_prev_state.take() {
10649            let query = &select_prev_state.query;
10650            if !select_prev_state.done {
10651                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
10652                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
10653                let mut next_selected_range = None;
10654                // When we're iterating matches backwards, the oldest match will actually be the furthest one in the buffer.
10655                let bytes_before_last_selection =
10656                    buffer.reversed_bytes_in_range(0..last_selection.start);
10657                let bytes_after_first_selection =
10658                    buffer.reversed_bytes_in_range(first_selection.end..buffer.len());
10659                let query_matches = query
10660                    .stream_find_iter(bytes_before_last_selection)
10661                    .map(|result| (last_selection.start, result))
10662                    .chain(
10663                        query
10664                            .stream_find_iter(bytes_after_first_selection)
10665                            .map(|result| (buffer.len(), result)),
10666                    );
10667                for (end_offset, query_match) in query_matches {
10668                    let query_match = query_match.unwrap(); // can only fail due to I/O
10669                    let offset_range =
10670                        end_offset - query_match.end()..end_offset - query_match.start();
10671                    let display_range = offset_range.start.to_display_point(&display_map)
10672                        ..offset_range.end.to_display_point(&display_map);
10673
10674                    if !select_prev_state.wordwise
10675                        || (!movement::is_inside_word(&display_map, display_range.start)
10676                            && !movement::is_inside_word(&display_map, display_range.end))
10677                    {
10678                        next_selected_range = Some(offset_range);
10679                        break;
10680                    }
10681                }
10682
10683                if let Some(next_selected_range) = next_selected_range {
10684                    self.unfold_ranges(&[next_selected_range.clone()], false, true, cx);
10685                    self.change_selections(Some(Autoscroll::newest()), window, cx, |s| {
10686                        if action.replace_newest {
10687                            s.delete(s.newest_anchor().id);
10688                        }
10689                        s.insert_range(next_selected_range);
10690                    });
10691                } else {
10692                    select_prev_state.done = true;
10693                }
10694            }
10695
10696            self.select_prev_state = Some(select_prev_state);
10697        } else {
10698            let mut only_carets = true;
10699            let mut same_text_selected = true;
10700            let mut selected_text = None;
10701
10702            let mut selections_iter = selections.iter().peekable();
10703            while let Some(selection) = selections_iter.next() {
10704                if selection.start != selection.end {
10705                    only_carets = false;
10706                }
10707
10708                if same_text_selected {
10709                    if selected_text.is_none() {
10710                        selected_text =
10711                            Some(buffer.text_for_range(selection.range()).collect::<String>());
10712                    }
10713
10714                    if let Some(next_selection) = selections_iter.peek() {
10715                        if next_selection.range().len() == selection.range().len() {
10716                            let next_selected_text = buffer
10717                                .text_for_range(next_selection.range())
10718                                .collect::<String>();
10719                            if Some(next_selected_text) != selected_text {
10720                                same_text_selected = false;
10721                                selected_text = None;
10722                            }
10723                        } else {
10724                            same_text_selected = false;
10725                            selected_text = None;
10726                        }
10727                    }
10728                }
10729            }
10730
10731            if only_carets {
10732                for selection in &mut selections {
10733                    let word_range = movement::surrounding_word(
10734                        &display_map,
10735                        selection.start.to_display_point(&display_map),
10736                    );
10737                    selection.start = word_range.start.to_offset(&display_map, Bias::Left);
10738                    selection.end = word_range.end.to_offset(&display_map, Bias::Left);
10739                    selection.goal = SelectionGoal::None;
10740                    selection.reversed = false;
10741                }
10742                if selections.len() == 1 {
10743                    let selection = selections
10744                        .last()
10745                        .expect("ensured that there's only one selection");
10746                    let query = buffer
10747                        .text_for_range(selection.start..selection.end)
10748                        .collect::<String>();
10749                    let is_empty = query.is_empty();
10750                    let select_state = SelectNextState {
10751                        query: AhoCorasick::new(&[query.chars().rev().collect::<String>()])?,
10752                        wordwise: true,
10753                        done: is_empty,
10754                    };
10755                    self.select_prev_state = Some(select_state);
10756                } else {
10757                    self.select_prev_state = None;
10758                }
10759
10760                self.unfold_ranges(
10761                    &selections.iter().map(|s| s.range()).collect::<Vec<_>>(),
10762                    false,
10763                    true,
10764                    cx,
10765                );
10766                self.change_selections(Some(Autoscroll::newest()), window, cx, |s| {
10767                    s.select(selections);
10768                });
10769            } else if let Some(selected_text) = selected_text {
10770                self.select_prev_state = Some(SelectNextState {
10771                    query: AhoCorasick::new(&[selected_text.chars().rev().collect::<String>()])?,
10772                    wordwise: false,
10773                    done: false,
10774                });
10775                self.select_previous(action, window, cx)?;
10776            }
10777        }
10778        Ok(())
10779    }
10780
10781    pub fn toggle_comments(
10782        &mut self,
10783        action: &ToggleComments,
10784        window: &mut Window,
10785        cx: &mut Context<Self>,
10786    ) {
10787        if self.read_only(cx) {
10788            return;
10789        }
10790        let text_layout_details = &self.text_layout_details(window);
10791        self.transact(window, cx, |this, window, cx| {
10792            let mut selections = this.selections.all::<MultiBufferPoint>(cx);
10793            let mut edits = Vec::new();
10794            let mut selection_edit_ranges = Vec::new();
10795            let mut last_toggled_row = None;
10796            let snapshot = this.buffer.read(cx).read(cx);
10797            let empty_str: Arc<str> = Arc::default();
10798            let mut suffixes_inserted = Vec::new();
10799            let ignore_indent = action.ignore_indent;
10800
10801            fn comment_prefix_range(
10802                snapshot: &MultiBufferSnapshot,
10803                row: MultiBufferRow,
10804                comment_prefix: &str,
10805                comment_prefix_whitespace: &str,
10806                ignore_indent: bool,
10807            ) -> Range<Point> {
10808                let indent_size = if ignore_indent {
10809                    0
10810                } else {
10811                    snapshot.indent_size_for_line(row).len
10812                };
10813
10814                let start = Point::new(row.0, indent_size);
10815
10816                let mut line_bytes = snapshot
10817                    .bytes_in_range(start..snapshot.max_point())
10818                    .flatten()
10819                    .copied();
10820
10821                // If this line currently begins with the line comment prefix, then record
10822                // the range containing the prefix.
10823                if line_bytes
10824                    .by_ref()
10825                    .take(comment_prefix.len())
10826                    .eq(comment_prefix.bytes())
10827                {
10828                    // Include any whitespace that matches the comment prefix.
10829                    let matching_whitespace_len = line_bytes
10830                        .zip(comment_prefix_whitespace.bytes())
10831                        .take_while(|(a, b)| a == b)
10832                        .count() as u32;
10833                    let end = Point::new(
10834                        start.row,
10835                        start.column + comment_prefix.len() as u32 + matching_whitespace_len,
10836                    );
10837                    start..end
10838                } else {
10839                    start..start
10840                }
10841            }
10842
10843            fn comment_suffix_range(
10844                snapshot: &MultiBufferSnapshot,
10845                row: MultiBufferRow,
10846                comment_suffix: &str,
10847                comment_suffix_has_leading_space: bool,
10848            ) -> Range<Point> {
10849                let end = Point::new(row.0, snapshot.line_len(row));
10850                let suffix_start_column = end.column.saturating_sub(comment_suffix.len() as u32);
10851
10852                let mut line_end_bytes = snapshot
10853                    .bytes_in_range(Point::new(end.row, suffix_start_column.saturating_sub(1))..end)
10854                    .flatten()
10855                    .copied();
10856
10857                let leading_space_len = if suffix_start_column > 0
10858                    && line_end_bytes.next() == Some(b' ')
10859                    && comment_suffix_has_leading_space
10860                {
10861                    1
10862                } else {
10863                    0
10864                };
10865
10866                // If this line currently begins with the line comment prefix, then record
10867                // the range containing the prefix.
10868                if line_end_bytes.by_ref().eq(comment_suffix.bytes()) {
10869                    let start = Point::new(end.row, suffix_start_column - leading_space_len);
10870                    start..end
10871                } else {
10872                    end..end
10873                }
10874            }
10875
10876            // TODO: Handle selections that cross excerpts
10877            for selection in &mut selections {
10878                let start_column = snapshot
10879                    .indent_size_for_line(MultiBufferRow(selection.start.row))
10880                    .len;
10881                let language = if let Some(language) =
10882                    snapshot.language_scope_at(Point::new(selection.start.row, start_column))
10883                {
10884                    language
10885                } else {
10886                    continue;
10887                };
10888
10889                selection_edit_ranges.clear();
10890
10891                // If multiple selections contain a given row, avoid processing that
10892                // row more than once.
10893                let mut start_row = MultiBufferRow(selection.start.row);
10894                if last_toggled_row == Some(start_row) {
10895                    start_row = start_row.next_row();
10896                }
10897                let end_row =
10898                    if selection.end.row > selection.start.row && selection.end.column == 0 {
10899                        MultiBufferRow(selection.end.row - 1)
10900                    } else {
10901                        MultiBufferRow(selection.end.row)
10902                    };
10903                last_toggled_row = Some(end_row);
10904
10905                if start_row > end_row {
10906                    continue;
10907                }
10908
10909                // If the language has line comments, toggle those.
10910                let mut full_comment_prefixes = language.line_comment_prefixes().to_vec();
10911
10912                // If ignore_indent is set, trim spaces from the right side of all full_comment_prefixes
10913                if ignore_indent {
10914                    full_comment_prefixes = full_comment_prefixes
10915                        .into_iter()
10916                        .map(|s| Arc::from(s.trim_end()))
10917                        .collect();
10918                }
10919
10920                if !full_comment_prefixes.is_empty() {
10921                    let first_prefix = full_comment_prefixes
10922                        .first()
10923                        .expect("prefixes is non-empty");
10924                    let prefix_trimmed_lengths = full_comment_prefixes
10925                        .iter()
10926                        .map(|p| p.trim_end_matches(' ').len())
10927                        .collect::<SmallVec<[usize; 4]>>();
10928
10929                    let mut all_selection_lines_are_comments = true;
10930
10931                    for row in start_row.0..=end_row.0 {
10932                        let row = MultiBufferRow(row);
10933                        if start_row < end_row && snapshot.is_line_blank(row) {
10934                            continue;
10935                        }
10936
10937                        let prefix_range = full_comment_prefixes
10938                            .iter()
10939                            .zip(prefix_trimmed_lengths.iter().copied())
10940                            .map(|(prefix, trimmed_prefix_len)| {
10941                                comment_prefix_range(
10942                                    snapshot.deref(),
10943                                    row,
10944                                    &prefix[..trimmed_prefix_len],
10945                                    &prefix[trimmed_prefix_len..],
10946                                    ignore_indent,
10947                                )
10948                            })
10949                            .max_by_key(|range| range.end.column - range.start.column)
10950                            .expect("prefixes is non-empty");
10951
10952                        if prefix_range.is_empty() {
10953                            all_selection_lines_are_comments = false;
10954                        }
10955
10956                        selection_edit_ranges.push(prefix_range);
10957                    }
10958
10959                    if all_selection_lines_are_comments {
10960                        edits.extend(
10961                            selection_edit_ranges
10962                                .iter()
10963                                .cloned()
10964                                .map(|range| (range, empty_str.clone())),
10965                        );
10966                    } else {
10967                        let min_column = selection_edit_ranges
10968                            .iter()
10969                            .map(|range| range.start.column)
10970                            .min()
10971                            .unwrap_or(0);
10972                        edits.extend(selection_edit_ranges.iter().map(|range| {
10973                            let position = Point::new(range.start.row, min_column);
10974                            (position..position, first_prefix.clone())
10975                        }));
10976                    }
10977                } else if let Some((full_comment_prefix, comment_suffix)) =
10978                    language.block_comment_delimiters()
10979                {
10980                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
10981                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
10982                    let prefix_range = comment_prefix_range(
10983                        snapshot.deref(),
10984                        start_row,
10985                        comment_prefix,
10986                        comment_prefix_whitespace,
10987                        ignore_indent,
10988                    );
10989                    let suffix_range = comment_suffix_range(
10990                        snapshot.deref(),
10991                        end_row,
10992                        comment_suffix.trim_start_matches(' '),
10993                        comment_suffix.starts_with(' '),
10994                    );
10995
10996                    if prefix_range.is_empty() || suffix_range.is_empty() {
10997                        edits.push((
10998                            prefix_range.start..prefix_range.start,
10999                            full_comment_prefix.clone(),
11000                        ));
11001                        edits.push((suffix_range.end..suffix_range.end, comment_suffix.clone()));
11002                        suffixes_inserted.push((end_row, comment_suffix.len()));
11003                    } else {
11004                        edits.push((prefix_range, empty_str.clone()));
11005                        edits.push((suffix_range, empty_str.clone()));
11006                    }
11007                } else {
11008                    continue;
11009                }
11010            }
11011
11012            drop(snapshot);
11013            this.buffer.update(cx, |buffer, cx| {
11014                buffer.edit(edits, None, cx);
11015            });
11016
11017            // Adjust selections so that they end before any comment suffixes that
11018            // were inserted.
11019            let mut suffixes_inserted = suffixes_inserted.into_iter().peekable();
11020            let mut selections = this.selections.all::<Point>(cx);
11021            let snapshot = this.buffer.read(cx).read(cx);
11022            for selection in &mut selections {
11023                while let Some((row, suffix_len)) = suffixes_inserted.peek().copied() {
11024                    match row.cmp(&MultiBufferRow(selection.end.row)) {
11025                        Ordering::Less => {
11026                            suffixes_inserted.next();
11027                            continue;
11028                        }
11029                        Ordering::Greater => break,
11030                        Ordering::Equal => {
11031                            if selection.end.column == snapshot.line_len(row) {
11032                                if selection.is_empty() {
11033                                    selection.start.column -= suffix_len as u32;
11034                                }
11035                                selection.end.column -= suffix_len as u32;
11036                            }
11037                            break;
11038                        }
11039                    }
11040                }
11041            }
11042
11043            drop(snapshot);
11044            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
11045                s.select(selections)
11046            });
11047
11048            let selections = this.selections.all::<Point>(cx);
11049            let selections_on_single_row = selections.windows(2).all(|selections| {
11050                selections[0].start.row == selections[1].start.row
11051                    && selections[0].end.row == selections[1].end.row
11052                    && selections[0].start.row == selections[0].end.row
11053            });
11054            let selections_selecting = selections
11055                .iter()
11056                .any(|selection| selection.start != selection.end);
11057            let advance_downwards = action.advance_downwards
11058                && selections_on_single_row
11059                && !selections_selecting
11060                && !matches!(this.mode, EditorMode::SingleLine { .. });
11061
11062            if advance_downwards {
11063                let snapshot = this.buffer.read(cx).snapshot(cx);
11064
11065                this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
11066                    s.move_cursors_with(|display_snapshot, display_point, _| {
11067                        let mut point = display_point.to_point(display_snapshot);
11068                        point.row += 1;
11069                        point = snapshot.clip_point(point, Bias::Left);
11070                        let display_point = point.to_display_point(display_snapshot);
11071                        let goal = SelectionGoal::HorizontalPosition(
11072                            display_snapshot
11073                                .x_for_display_point(display_point, text_layout_details)
11074                                .into(),
11075                        );
11076                        (display_point, goal)
11077                    })
11078                });
11079            }
11080        });
11081    }
11082
11083    pub fn select_enclosing_symbol(
11084        &mut self,
11085        _: &SelectEnclosingSymbol,
11086        window: &mut Window,
11087        cx: &mut Context<Self>,
11088    ) {
11089        let buffer = self.buffer.read(cx).snapshot(cx);
11090        let old_selections = self.selections.all::<usize>(cx).into_boxed_slice();
11091
11092        fn update_selection(
11093            selection: &Selection<usize>,
11094            buffer_snap: &MultiBufferSnapshot,
11095        ) -> Option<Selection<usize>> {
11096            let cursor = selection.head();
11097            let (_buffer_id, symbols) = buffer_snap.symbols_containing(cursor, None)?;
11098            for symbol in symbols.iter().rev() {
11099                let start = symbol.range.start.to_offset(buffer_snap);
11100                let end = symbol.range.end.to_offset(buffer_snap);
11101                let new_range = start..end;
11102                if start < selection.start || end > selection.end {
11103                    return Some(Selection {
11104                        id: selection.id,
11105                        start: new_range.start,
11106                        end: new_range.end,
11107                        goal: SelectionGoal::None,
11108                        reversed: selection.reversed,
11109                    });
11110                }
11111            }
11112            None
11113        }
11114
11115        let mut selected_larger_symbol = false;
11116        let new_selections = old_selections
11117            .iter()
11118            .map(|selection| match update_selection(selection, &buffer) {
11119                Some(new_selection) => {
11120                    if new_selection.range() != selection.range() {
11121                        selected_larger_symbol = true;
11122                    }
11123                    new_selection
11124                }
11125                None => selection.clone(),
11126            })
11127            .collect::<Vec<_>>();
11128
11129        if selected_larger_symbol {
11130            self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
11131                s.select(new_selections);
11132            });
11133        }
11134    }
11135
11136    pub fn select_larger_syntax_node(
11137        &mut self,
11138        _: &SelectLargerSyntaxNode,
11139        window: &mut Window,
11140        cx: &mut Context<Self>,
11141    ) {
11142        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
11143        let buffer = self.buffer.read(cx).snapshot(cx);
11144        let old_selections = self.selections.all::<usize>(cx).into_boxed_slice();
11145
11146        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
11147        let mut selected_larger_node = false;
11148        let new_selections = old_selections
11149            .iter()
11150            .map(|selection| {
11151                let old_range = selection.start..selection.end;
11152                let mut new_range = old_range.clone();
11153                let mut new_node = None;
11154                while let Some((node, containing_range)) = buffer.syntax_ancestor(new_range.clone())
11155                {
11156                    new_node = Some(node);
11157                    new_range = match containing_range {
11158                        MultiOrSingleBufferOffsetRange::Single(_) => break,
11159                        MultiOrSingleBufferOffsetRange::Multi(range) => range,
11160                    };
11161                    if !display_map.intersects_fold(new_range.start)
11162                        && !display_map.intersects_fold(new_range.end)
11163                    {
11164                        break;
11165                    }
11166                }
11167
11168                if let Some(node) = new_node {
11169                    // Log the ancestor, to support using this action as a way to explore TreeSitter
11170                    // nodes. Parent and grandparent are also logged because this operation will not
11171                    // visit nodes that have the same range as their parent.
11172                    log::info!("Node: {node:?}");
11173                    let parent = node.parent();
11174                    log::info!("Parent: {parent:?}");
11175                    let grandparent = parent.and_then(|x| x.parent());
11176                    log::info!("Grandparent: {grandparent:?}");
11177                }
11178
11179                selected_larger_node |= new_range != old_range;
11180                Selection {
11181                    id: selection.id,
11182                    start: new_range.start,
11183                    end: new_range.end,
11184                    goal: SelectionGoal::None,
11185                    reversed: selection.reversed,
11186                }
11187            })
11188            .collect::<Vec<_>>();
11189
11190        if selected_larger_node {
11191            stack.push(old_selections);
11192            self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
11193                s.select(new_selections);
11194            });
11195        }
11196        self.select_larger_syntax_node_stack = stack;
11197    }
11198
11199    pub fn select_smaller_syntax_node(
11200        &mut self,
11201        _: &SelectSmallerSyntaxNode,
11202        window: &mut Window,
11203        cx: &mut Context<Self>,
11204    ) {
11205        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
11206        if let Some(selections) = stack.pop() {
11207            self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
11208                s.select(selections.to_vec());
11209            });
11210        }
11211        self.select_larger_syntax_node_stack = stack;
11212    }
11213
11214    fn refresh_runnables(&mut self, window: &mut Window, cx: &mut Context<Self>) -> Task<()> {
11215        if !EditorSettings::get_global(cx).gutter.runnables {
11216            self.clear_tasks();
11217            return Task::ready(());
11218        }
11219        let project = self.project.as_ref().map(Entity::downgrade);
11220        cx.spawn_in(window, |this, mut cx| async move {
11221            cx.background_executor().timer(UPDATE_DEBOUNCE).await;
11222            let Some(project) = project.and_then(|p| p.upgrade()) else {
11223                return;
11224            };
11225            let Ok(display_snapshot) = this.update(&mut cx, |this, cx| {
11226                this.display_map.update(cx, |map, cx| map.snapshot(cx))
11227            }) else {
11228                return;
11229            };
11230
11231            let hide_runnables = project
11232                .update(&mut cx, |project, cx| {
11233                    // Do not display any test indicators in non-dev server remote projects.
11234                    project.is_via_collab() && project.ssh_connection_string(cx).is_none()
11235                })
11236                .unwrap_or(true);
11237            if hide_runnables {
11238                return;
11239            }
11240            let new_rows =
11241                cx.background_spawn({
11242                    let snapshot = display_snapshot.clone();
11243                    async move {
11244                        Self::fetch_runnable_ranges(&snapshot, Anchor::min()..Anchor::max())
11245                    }
11246                })
11247                    .await;
11248
11249            let rows = Self::runnable_rows(project, display_snapshot, new_rows, cx.clone());
11250            this.update(&mut cx, |this, _| {
11251                this.clear_tasks();
11252                for (key, value) in rows {
11253                    this.insert_tasks(key, value);
11254                }
11255            })
11256            .ok();
11257        })
11258    }
11259    fn fetch_runnable_ranges(
11260        snapshot: &DisplaySnapshot,
11261        range: Range<Anchor>,
11262    ) -> Vec<language::RunnableRange> {
11263        snapshot.buffer_snapshot.runnable_ranges(range).collect()
11264    }
11265
11266    fn runnable_rows(
11267        project: Entity<Project>,
11268        snapshot: DisplaySnapshot,
11269        runnable_ranges: Vec<RunnableRange>,
11270        mut cx: AsyncWindowContext,
11271    ) -> Vec<((BufferId, u32), RunnableTasks)> {
11272        runnable_ranges
11273            .into_iter()
11274            .filter_map(|mut runnable| {
11275                let tasks = cx
11276                    .update(|_, cx| Self::templates_with_tags(&project, &mut runnable.runnable, cx))
11277                    .ok()?;
11278                if tasks.is_empty() {
11279                    return None;
11280                }
11281
11282                let point = runnable.run_range.start.to_point(&snapshot.buffer_snapshot);
11283
11284                let row = snapshot
11285                    .buffer_snapshot
11286                    .buffer_line_for_row(MultiBufferRow(point.row))?
11287                    .1
11288                    .start
11289                    .row;
11290
11291                let context_range =
11292                    BufferOffset(runnable.full_range.start)..BufferOffset(runnable.full_range.end);
11293                Some((
11294                    (runnable.buffer_id, row),
11295                    RunnableTasks {
11296                        templates: tasks,
11297                        offset: snapshot
11298                            .buffer_snapshot
11299                            .anchor_before(runnable.run_range.start),
11300                        context_range,
11301                        column: point.column,
11302                        extra_variables: runnable.extra_captures,
11303                    },
11304                ))
11305            })
11306            .collect()
11307    }
11308
11309    fn templates_with_tags(
11310        project: &Entity<Project>,
11311        runnable: &mut Runnable,
11312        cx: &mut App,
11313    ) -> Vec<(TaskSourceKind, TaskTemplate)> {
11314        let (inventory, worktree_id, file) = project.read_with(cx, |project, cx| {
11315            let (worktree_id, file) = project
11316                .buffer_for_id(runnable.buffer, cx)
11317                .and_then(|buffer| buffer.read(cx).file())
11318                .map(|file| (file.worktree_id(cx), file.clone()))
11319                .unzip();
11320
11321            (
11322                project.task_store().read(cx).task_inventory().cloned(),
11323                worktree_id,
11324                file,
11325            )
11326        });
11327
11328        let tags = mem::take(&mut runnable.tags);
11329        let mut tags: Vec<_> = tags
11330            .into_iter()
11331            .flat_map(|tag| {
11332                let tag = tag.0.clone();
11333                inventory
11334                    .as_ref()
11335                    .into_iter()
11336                    .flat_map(|inventory| {
11337                        inventory.read(cx).list_tasks(
11338                            file.clone(),
11339                            Some(runnable.language.clone()),
11340                            worktree_id,
11341                            cx,
11342                        )
11343                    })
11344                    .filter(move |(_, template)| {
11345                        template.tags.iter().any(|source_tag| source_tag == &tag)
11346                    })
11347            })
11348            .sorted_by_key(|(kind, _)| kind.to_owned())
11349            .collect();
11350        if let Some((leading_tag_source, _)) = tags.first() {
11351            // Strongest source wins; if we have worktree tag binding, prefer that to
11352            // global and language bindings;
11353            // if we have a global binding, prefer that to language binding.
11354            let first_mismatch = tags
11355                .iter()
11356                .position(|(tag_source, _)| tag_source != leading_tag_source);
11357            if let Some(index) = first_mismatch {
11358                tags.truncate(index);
11359            }
11360        }
11361
11362        tags
11363    }
11364
11365    pub fn move_to_enclosing_bracket(
11366        &mut self,
11367        _: &MoveToEnclosingBracket,
11368        window: &mut Window,
11369        cx: &mut Context<Self>,
11370    ) {
11371        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
11372            s.move_offsets_with(|snapshot, selection| {
11373                let Some(enclosing_bracket_ranges) =
11374                    snapshot.enclosing_bracket_ranges(selection.start..selection.end)
11375                else {
11376                    return;
11377                };
11378
11379                let mut best_length = usize::MAX;
11380                let mut best_inside = false;
11381                let mut best_in_bracket_range = false;
11382                let mut best_destination = None;
11383                for (open, close) in enclosing_bracket_ranges {
11384                    let close = close.to_inclusive();
11385                    let length = close.end() - open.start;
11386                    let inside = selection.start >= open.end && selection.end <= *close.start();
11387                    let in_bracket_range = open.to_inclusive().contains(&selection.head())
11388                        || close.contains(&selection.head());
11389
11390                    // If best is next to a bracket and current isn't, skip
11391                    if !in_bracket_range && best_in_bracket_range {
11392                        continue;
11393                    }
11394
11395                    // Prefer smaller lengths unless best is inside and current isn't
11396                    if length > best_length && (best_inside || !inside) {
11397                        continue;
11398                    }
11399
11400                    best_length = length;
11401                    best_inside = inside;
11402                    best_in_bracket_range = in_bracket_range;
11403                    best_destination = Some(
11404                        if close.contains(&selection.start) && close.contains(&selection.end) {
11405                            if inside {
11406                                open.end
11407                            } else {
11408                                open.start
11409                            }
11410                        } else if inside {
11411                            *close.start()
11412                        } else {
11413                            *close.end()
11414                        },
11415                    );
11416                }
11417
11418                if let Some(destination) = best_destination {
11419                    selection.collapse_to(destination, SelectionGoal::None);
11420                }
11421            })
11422        });
11423    }
11424
11425    pub fn undo_selection(
11426        &mut self,
11427        _: &UndoSelection,
11428        window: &mut Window,
11429        cx: &mut Context<Self>,
11430    ) {
11431        self.end_selection(window, cx);
11432        self.selection_history.mode = SelectionHistoryMode::Undoing;
11433        if let Some(entry) = self.selection_history.undo_stack.pop_back() {
11434            self.change_selections(None, window, cx, |s| {
11435                s.select_anchors(entry.selections.to_vec())
11436            });
11437            self.select_next_state = entry.select_next_state;
11438            self.select_prev_state = entry.select_prev_state;
11439            self.add_selections_state = entry.add_selections_state;
11440            self.request_autoscroll(Autoscroll::newest(), cx);
11441        }
11442        self.selection_history.mode = SelectionHistoryMode::Normal;
11443    }
11444
11445    pub fn redo_selection(
11446        &mut self,
11447        _: &RedoSelection,
11448        window: &mut Window,
11449        cx: &mut Context<Self>,
11450    ) {
11451        self.end_selection(window, cx);
11452        self.selection_history.mode = SelectionHistoryMode::Redoing;
11453        if let Some(entry) = self.selection_history.redo_stack.pop_back() {
11454            self.change_selections(None, window, cx, |s| {
11455                s.select_anchors(entry.selections.to_vec())
11456            });
11457            self.select_next_state = entry.select_next_state;
11458            self.select_prev_state = entry.select_prev_state;
11459            self.add_selections_state = entry.add_selections_state;
11460            self.request_autoscroll(Autoscroll::newest(), cx);
11461        }
11462        self.selection_history.mode = SelectionHistoryMode::Normal;
11463    }
11464
11465    pub fn expand_excerpts(
11466        &mut self,
11467        action: &ExpandExcerpts,
11468        _: &mut Window,
11469        cx: &mut Context<Self>,
11470    ) {
11471        self.expand_excerpts_for_direction(action.lines, ExpandExcerptDirection::UpAndDown, cx)
11472    }
11473
11474    pub fn expand_excerpts_down(
11475        &mut self,
11476        action: &ExpandExcerptsDown,
11477        _: &mut Window,
11478        cx: &mut Context<Self>,
11479    ) {
11480        self.expand_excerpts_for_direction(action.lines, ExpandExcerptDirection::Down, cx)
11481    }
11482
11483    pub fn expand_excerpts_up(
11484        &mut self,
11485        action: &ExpandExcerptsUp,
11486        _: &mut Window,
11487        cx: &mut Context<Self>,
11488    ) {
11489        self.expand_excerpts_for_direction(action.lines, ExpandExcerptDirection::Up, cx)
11490    }
11491
11492    pub fn expand_excerpts_for_direction(
11493        &mut self,
11494        lines: u32,
11495        direction: ExpandExcerptDirection,
11496
11497        cx: &mut Context<Self>,
11498    ) {
11499        let selections = self.selections.disjoint_anchors();
11500
11501        let lines = if lines == 0 {
11502            EditorSettings::get_global(cx).expand_excerpt_lines
11503        } else {
11504            lines
11505        };
11506
11507        self.buffer.update(cx, |buffer, cx| {
11508            let snapshot = buffer.snapshot(cx);
11509            let mut excerpt_ids = selections
11510                .iter()
11511                .flat_map(|selection| snapshot.excerpt_ids_for_range(selection.range()))
11512                .collect::<Vec<_>>();
11513            excerpt_ids.sort();
11514            excerpt_ids.dedup();
11515            buffer.expand_excerpts(excerpt_ids, lines, direction, cx)
11516        })
11517    }
11518
11519    pub fn expand_excerpt(
11520        &mut self,
11521        excerpt: ExcerptId,
11522        direction: ExpandExcerptDirection,
11523        cx: &mut Context<Self>,
11524    ) {
11525        let lines = EditorSettings::get_global(cx).expand_excerpt_lines;
11526        self.buffer.update(cx, |buffer, cx| {
11527            buffer.expand_excerpts([excerpt], lines, direction, cx)
11528        })
11529    }
11530
11531    pub fn go_to_singleton_buffer_point(
11532        &mut self,
11533        point: Point,
11534        window: &mut Window,
11535        cx: &mut Context<Self>,
11536    ) {
11537        self.go_to_singleton_buffer_range(point..point, window, cx);
11538    }
11539
11540    pub fn go_to_singleton_buffer_range(
11541        &mut self,
11542        range: Range<Point>,
11543        window: &mut Window,
11544        cx: &mut Context<Self>,
11545    ) {
11546        let multibuffer = self.buffer().read(cx);
11547        let Some(buffer) = multibuffer.as_singleton() else {
11548            return;
11549        };
11550        let Some(start) = multibuffer.buffer_point_to_anchor(&buffer, range.start, cx) else {
11551            return;
11552        };
11553        let Some(end) = multibuffer.buffer_point_to_anchor(&buffer, range.end, cx) else {
11554            return;
11555        };
11556        self.change_selections(Some(Autoscroll::center()), window, cx, |s| {
11557            s.select_anchor_ranges([start..end])
11558        });
11559    }
11560
11561    fn go_to_diagnostic(
11562        &mut self,
11563        _: &GoToDiagnostic,
11564        window: &mut Window,
11565        cx: &mut Context<Self>,
11566    ) {
11567        self.go_to_diagnostic_impl(Direction::Next, window, cx)
11568    }
11569
11570    fn go_to_prev_diagnostic(
11571        &mut self,
11572        _: &GoToPreviousDiagnostic,
11573        window: &mut Window,
11574        cx: &mut Context<Self>,
11575    ) {
11576        self.go_to_diagnostic_impl(Direction::Prev, window, cx)
11577    }
11578
11579    pub fn go_to_diagnostic_impl(
11580        &mut self,
11581        direction: Direction,
11582        window: &mut Window,
11583        cx: &mut Context<Self>,
11584    ) {
11585        let buffer = self.buffer.read(cx).snapshot(cx);
11586        let selection = self.selections.newest::<usize>(cx);
11587
11588        // If there is an active Diagnostic Popover jump to its diagnostic instead.
11589        if direction == Direction::Next {
11590            if let Some(popover) = self.hover_state.diagnostic_popover.as_ref() {
11591                let Some(buffer_id) = popover.local_diagnostic.range.start.buffer_id else {
11592                    return;
11593                };
11594                self.activate_diagnostics(
11595                    buffer_id,
11596                    popover.local_diagnostic.diagnostic.group_id,
11597                    window,
11598                    cx,
11599                );
11600                if let Some(active_diagnostics) = self.active_diagnostics.as_ref() {
11601                    let primary_range_start = active_diagnostics.primary_range.start;
11602                    self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
11603                        let mut new_selection = s.newest_anchor().clone();
11604                        new_selection.collapse_to(primary_range_start, SelectionGoal::None);
11605                        s.select_anchors(vec![new_selection.clone()]);
11606                    });
11607                    self.refresh_inline_completion(false, true, window, cx);
11608                }
11609                return;
11610            }
11611        }
11612
11613        let active_group_id = self
11614            .active_diagnostics
11615            .as_ref()
11616            .map(|active_group| active_group.group_id);
11617        let active_primary_range = self.active_diagnostics.as_ref().map(|active_diagnostics| {
11618            active_diagnostics
11619                .primary_range
11620                .to_offset(&buffer)
11621                .to_inclusive()
11622        });
11623        let search_start = if let Some(active_primary_range) = active_primary_range.as_ref() {
11624            if active_primary_range.contains(&selection.head()) {
11625                *active_primary_range.start()
11626            } else {
11627                selection.head()
11628            }
11629        } else {
11630            selection.head()
11631        };
11632
11633        let snapshot = self.snapshot(window, cx);
11634        let primary_diagnostics_before = buffer
11635            .diagnostics_in_range::<usize>(0..search_start)
11636            .filter(|entry| entry.diagnostic.is_primary)
11637            .filter(|entry| entry.range.start != entry.range.end)
11638            .filter(|entry| entry.diagnostic.severity <= DiagnosticSeverity::WARNING)
11639            .filter(|entry| !snapshot.intersects_fold(entry.range.start))
11640            .collect::<Vec<_>>();
11641        let last_same_group_diagnostic_before = active_group_id.and_then(|active_group_id| {
11642            primary_diagnostics_before
11643                .iter()
11644                .position(|entry| entry.diagnostic.group_id == active_group_id)
11645        });
11646
11647        let primary_diagnostics_after = buffer
11648            .diagnostics_in_range::<usize>(search_start..buffer.len())
11649            .filter(|entry| entry.diagnostic.is_primary)
11650            .filter(|entry| entry.range.start != entry.range.end)
11651            .filter(|entry| entry.diagnostic.severity <= DiagnosticSeverity::WARNING)
11652            .filter(|diagnostic| !snapshot.intersects_fold(diagnostic.range.start))
11653            .collect::<Vec<_>>();
11654        let last_same_group_diagnostic_after = active_group_id.and_then(|active_group_id| {
11655            primary_diagnostics_after
11656                .iter()
11657                .enumerate()
11658                .rev()
11659                .find_map(|(i, entry)| {
11660                    if entry.diagnostic.group_id == active_group_id {
11661                        Some(i)
11662                    } else {
11663                        None
11664                    }
11665                })
11666        });
11667
11668        let next_primary_diagnostic = match direction {
11669            Direction::Prev => primary_diagnostics_before
11670                .iter()
11671                .take(last_same_group_diagnostic_before.unwrap_or(usize::MAX))
11672                .rev()
11673                .next(),
11674            Direction::Next => primary_diagnostics_after
11675                .iter()
11676                .skip(
11677                    last_same_group_diagnostic_after
11678                        .map(|index| index + 1)
11679                        .unwrap_or(0),
11680                )
11681                .next(),
11682        };
11683
11684        // Cycle around to the start of the buffer, potentially moving back to the start of
11685        // the currently active diagnostic.
11686        let cycle_around = || match direction {
11687            Direction::Prev => primary_diagnostics_after
11688                .iter()
11689                .rev()
11690                .chain(primary_diagnostics_before.iter().rev())
11691                .next(),
11692            Direction::Next => primary_diagnostics_before
11693                .iter()
11694                .chain(primary_diagnostics_after.iter())
11695                .next(),
11696        };
11697
11698        if let Some((primary_range, group_id)) = next_primary_diagnostic
11699            .or_else(cycle_around)
11700            .map(|entry| (&entry.range, entry.diagnostic.group_id))
11701        {
11702            let Some(buffer_id) = buffer.anchor_after(primary_range.start).buffer_id else {
11703                return;
11704            };
11705            self.activate_diagnostics(buffer_id, group_id, window, cx);
11706            if self.active_diagnostics.is_some() {
11707                self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
11708                    s.select(vec![Selection {
11709                        id: selection.id,
11710                        start: primary_range.start,
11711                        end: primary_range.start,
11712                        reversed: false,
11713                        goal: SelectionGoal::None,
11714                    }]);
11715                });
11716                self.refresh_inline_completion(false, true, window, cx);
11717            }
11718        }
11719    }
11720
11721    fn go_to_next_hunk(&mut self, _: &GoToHunk, window: &mut Window, cx: &mut Context<Self>) {
11722        let snapshot = self.snapshot(window, cx);
11723        let selection = self.selections.newest::<Point>(cx);
11724        self.go_to_hunk_before_or_after_position(
11725            &snapshot,
11726            selection.head(),
11727            Direction::Next,
11728            window,
11729            cx,
11730        );
11731    }
11732
11733    fn go_to_hunk_before_or_after_position(
11734        &mut self,
11735        snapshot: &EditorSnapshot,
11736        position: Point,
11737        direction: Direction,
11738        window: &mut Window,
11739        cx: &mut Context<Editor>,
11740    ) {
11741        let row = if direction == Direction::Next {
11742            self.hunk_after_position(snapshot, position)
11743                .map(|hunk| hunk.row_range.start)
11744        } else {
11745            self.hunk_before_position(snapshot, position)
11746        };
11747
11748        if let Some(row) = row {
11749            let destination = Point::new(row.0, 0);
11750            let autoscroll = Autoscroll::center();
11751
11752            self.unfold_ranges(&[destination..destination], false, false, cx);
11753            self.change_selections(Some(autoscroll), window, cx, |s| {
11754                s.select_ranges([destination..destination]);
11755            });
11756        }
11757    }
11758
11759    fn hunk_after_position(
11760        &mut self,
11761        snapshot: &EditorSnapshot,
11762        position: Point,
11763    ) -> Option<MultiBufferDiffHunk> {
11764        snapshot
11765            .buffer_snapshot
11766            .diff_hunks_in_range(position..snapshot.buffer_snapshot.max_point())
11767            .find(|hunk| hunk.row_range.start.0 > position.row)
11768            .or_else(|| {
11769                snapshot
11770                    .buffer_snapshot
11771                    .diff_hunks_in_range(Point::zero()..position)
11772                    .find(|hunk| hunk.row_range.end.0 < position.row)
11773            })
11774    }
11775
11776    fn go_to_prev_hunk(
11777        &mut self,
11778        _: &GoToPreviousHunk,
11779        window: &mut Window,
11780        cx: &mut Context<Self>,
11781    ) {
11782        let snapshot = self.snapshot(window, cx);
11783        let selection = self.selections.newest::<Point>(cx);
11784        self.go_to_hunk_before_or_after_position(
11785            &snapshot,
11786            selection.head(),
11787            Direction::Prev,
11788            window,
11789            cx,
11790        );
11791    }
11792
11793    fn hunk_before_position(
11794        &mut self,
11795        snapshot: &EditorSnapshot,
11796        position: Point,
11797    ) -> Option<MultiBufferRow> {
11798        snapshot
11799            .buffer_snapshot
11800            .diff_hunk_before(position)
11801            .or_else(|| snapshot.buffer_snapshot.diff_hunk_before(Point::MAX))
11802    }
11803
11804    pub fn go_to_definition(
11805        &mut self,
11806        _: &GoToDefinition,
11807        window: &mut Window,
11808        cx: &mut Context<Self>,
11809    ) -> Task<Result<Navigated>> {
11810        let definition =
11811            self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, false, window, cx);
11812        cx.spawn_in(window, |editor, mut cx| async move {
11813            if definition.await? == Navigated::Yes {
11814                return Ok(Navigated::Yes);
11815            }
11816            match editor.update_in(&mut cx, |editor, window, cx| {
11817                editor.find_all_references(&FindAllReferences, window, cx)
11818            })? {
11819                Some(references) => references.await,
11820                None => Ok(Navigated::No),
11821            }
11822        })
11823    }
11824
11825    pub fn go_to_declaration(
11826        &mut self,
11827        _: &GoToDeclaration,
11828        window: &mut Window,
11829        cx: &mut Context<Self>,
11830    ) -> Task<Result<Navigated>> {
11831        self.go_to_definition_of_kind(GotoDefinitionKind::Declaration, false, window, cx)
11832    }
11833
11834    pub fn go_to_declaration_split(
11835        &mut self,
11836        _: &GoToDeclaration,
11837        window: &mut Window,
11838        cx: &mut Context<Self>,
11839    ) -> Task<Result<Navigated>> {
11840        self.go_to_definition_of_kind(GotoDefinitionKind::Declaration, true, window, cx)
11841    }
11842
11843    pub fn go_to_implementation(
11844        &mut self,
11845        _: &GoToImplementation,
11846        window: &mut Window,
11847        cx: &mut Context<Self>,
11848    ) -> Task<Result<Navigated>> {
11849        self.go_to_definition_of_kind(GotoDefinitionKind::Implementation, false, window, cx)
11850    }
11851
11852    pub fn go_to_implementation_split(
11853        &mut self,
11854        _: &GoToImplementationSplit,
11855        window: &mut Window,
11856        cx: &mut Context<Self>,
11857    ) -> Task<Result<Navigated>> {
11858        self.go_to_definition_of_kind(GotoDefinitionKind::Implementation, true, window, cx)
11859    }
11860
11861    pub fn go_to_type_definition(
11862        &mut self,
11863        _: &GoToTypeDefinition,
11864        window: &mut Window,
11865        cx: &mut Context<Self>,
11866    ) -> Task<Result<Navigated>> {
11867        self.go_to_definition_of_kind(GotoDefinitionKind::Type, false, window, cx)
11868    }
11869
11870    pub fn go_to_definition_split(
11871        &mut self,
11872        _: &GoToDefinitionSplit,
11873        window: &mut Window,
11874        cx: &mut Context<Self>,
11875    ) -> Task<Result<Navigated>> {
11876        self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, true, window, cx)
11877    }
11878
11879    pub fn go_to_type_definition_split(
11880        &mut self,
11881        _: &GoToTypeDefinitionSplit,
11882        window: &mut Window,
11883        cx: &mut Context<Self>,
11884    ) -> Task<Result<Navigated>> {
11885        self.go_to_definition_of_kind(GotoDefinitionKind::Type, true, window, cx)
11886    }
11887
11888    fn go_to_definition_of_kind(
11889        &mut self,
11890        kind: GotoDefinitionKind,
11891        split: bool,
11892        window: &mut Window,
11893        cx: &mut Context<Self>,
11894    ) -> Task<Result<Navigated>> {
11895        let Some(provider) = self.semantics_provider.clone() else {
11896            return Task::ready(Ok(Navigated::No));
11897        };
11898        let head = self.selections.newest::<usize>(cx).head();
11899        let buffer = self.buffer.read(cx);
11900        let (buffer, head) = if let Some(text_anchor) = buffer.text_anchor_for_position(head, cx) {
11901            text_anchor
11902        } else {
11903            return Task::ready(Ok(Navigated::No));
11904        };
11905
11906        let Some(definitions) = provider.definitions(&buffer, head, kind, cx) else {
11907            return Task::ready(Ok(Navigated::No));
11908        };
11909
11910        cx.spawn_in(window, |editor, mut cx| async move {
11911            let definitions = definitions.await?;
11912            let navigated = editor
11913                .update_in(&mut cx, |editor, window, cx| {
11914                    editor.navigate_to_hover_links(
11915                        Some(kind),
11916                        definitions
11917                            .into_iter()
11918                            .filter(|location| {
11919                                hover_links::exclude_link_to_position(&buffer, &head, location, cx)
11920                            })
11921                            .map(HoverLink::Text)
11922                            .collect::<Vec<_>>(),
11923                        split,
11924                        window,
11925                        cx,
11926                    )
11927                })?
11928                .await?;
11929            anyhow::Ok(navigated)
11930        })
11931    }
11932
11933    pub fn open_url(&mut self, _: &OpenUrl, window: &mut Window, cx: &mut Context<Self>) {
11934        let selection = self.selections.newest_anchor();
11935        let head = selection.head();
11936        let tail = selection.tail();
11937
11938        let Some((buffer, start_position)) =
11939            self.buffer.read(cx).text_anchor_for_position(head, cx)
11940        else {
11941            return;
11942        };
11943
11944        let end_position = if head != tail {
11945            let Some((_, pos)) = self.buffer.read(cx).text_anchor_for_position(tail, cx) else {
11946                return;
11947            };
11948            Some(pos)
11949        } else {
11950            None
11951        };
11952
11953        let url_finder = cx.spawn_in(window, |editor, mut cx| async move {
11954            let url = if let Some(end_pos) = end_position {
11955                find_url_from_range(&buffer, start_position..end_pos, cx.clone())
11956            } else {
11957                find_url(&buffer, start_position, cx.clone()).map(|(_, url)| url)
11958            };
11959
11960            if let Some(url) = url {
11961                editor.update(&mut cx, |_, cx| {
11962                    cx.open_url(&url);
11963                })
11964            } else {
11965                Ok(())
11966            }
11967        });
11968
11969        url_finder.detach();
11970    }
11971
11972    pub fn open_selected_filename(
11973        &mut self,
11974        _: &OpenSelectedFilename,
11975        window: &mut Window,
11976        cx: &mut Context<Self>,
11977    ) {
11978        let Some(workspace) = self.workspace() else {
11979            return;
11980        };
11981
11982        let position = self.selections.newest_anchor().head();
11983
11984        let Some((buffer, buffer_position)) =
11985            self.buffer.read(cx).text_anchor_for_position(position, cx)
11986        else {
11987            return;
11988        };
11989
11990        let project = self.project.clone();
11991
11992        cx.spawn_in(window, |_, mut cx| async move {
11993            let result = find_file(&buffer, project, buffer_position, &mut cx).await;
11994
11995            if let Some((_, path)) = result {
11996                workspace
11997                    .update_in(&mut cx, |workspace, window, cx| {
11998                        workspace.open_resolved_path(path, window, cx)
11999                    })?
12000                    .await?;
12001            }
12002            anyhow::Ok(())
12003        })
12004        .detach();
12005    }
12006
12007    pub(crate) fn navigate_to_hover_links(
12008        &mut self,
12009        kind: Option<GotoDefinitionKind>,
12010        mut definitions: Vec<HoverLink>,
12011        split: bool,
12012        window: &mut Window,
12013        cx: &mut Context<Editor>,
12014    ) -> Task<Result<Navigated>> {
12015        // If there is one definition, just open it directly
12016        if definitions.len() == 1 {
12017            let definition = definitions.pop().unwrap();
12018
12019            enum TargetTaskResult {
12020                Location(Option<Location>),
12021                AlreadyNavigated,
12022            }
12023
12024            let target_task = match definition {
12025                HoverLink::Text(link) => {
12026                    Task::ready(anyhow::Ok(TargetTaskResult::Location(Some(link.target))))
12027                }
12028                HoverLink::InlayHint(lsp_location, server_id) => {
12029                    let computation =
12030                        self.compute_target_location(lsp_location, server_id, window, cx);
12031                    cx.background_spawn(async move {
12032                        let location = computation.await?;
12033                        Ok(TargetTaskResult::Location(location))
12034                    })
12035                }
12036                HoverLink::Url(url) => {
12037                    cx.open_url(&url);
12038                    Task::ready(Ok(TargetTaskResult::AlreadyNavigated))
12039                }
12040                HoverLink::File(path) => {
12041                    if let Some(workspace) = self.workspace() {
12042                        cx.spawn_in(window, |_, mut cx| async move {
12043                            workspace
12044                                .update_in(&mut cx, |workspace, window, cx| {
12045                                    workspace.open_resolved_path(path, window, cx)
12046                                })?
12047                                .await
12048                                .map(|_| TargetTaskResult::AlreadyNavigated)
12049                        })
12050                    } else {
12051                        Task::ready(Ok(TargetTaskResult::Location(None)))
12052                    }
12053                }
12054            };
12055            cx.spawn_in(window, |editor, mut cx| async move {
12056                let target = match target_task.await.context("target resolution task")? {
12057                    TargetTaskResult::AlreadyNavigated => return Ok(Navigated::Yes),
12058                    TargetTaskResult::Location(None) => return Ok(Navigated::No),
12059                    TargetTaskResult::Location(Some(target)) => target,
12060                };
12061
12062                editor.update_in(&mut cx, |editor, window, cx| {
12063                    let Some(workspace) = editor.workspace() else {
12064                        return Navigated::No;
12065                    };
12066                    let pane = workspace.read(cx).active_pane().clone();
12067
12068                    let range = target.range.to_point(target.buffer.read(cx));
12069                    let range = editor.range_for_match(&range);
12070                    let range = collapse_multiline_range(range);
12071
12072                    if !split
12073                        && Some(&target.buffer) == editor.buffer.read(cx).as_singleton().as_ref()
12074                    {
12075                        editor.go_to_singleton_buffer_range(range.clone(), window, cx);
12076                    } else {
12077                        window.defer(cx, move |window, cx| {
12078                            let target_editor: Entity<Self> =
12079                                workspace.update(cx, |workspace, cx| {
12080                                    let pane = if split {
12081                                        workspace.adjacent_pane(window, cx)
12082                                    } else {
12083                                        workspace.active_pane().clone()
12084                                    };
12085
12086                                    workspace.open_project_item(
12087                                        pane,
12088                                        target.buffer.clone(),
12089                                        true,
12090                                        true,
12091                                        window,
12092                                        cx,
12093                                    )
12094                                });
12095                            target_editor.update(cx, |target_editor, cx| {
12096                                // When selecting a definition in a different buffer, disable the nav history
12097                                // to avoid creating a history entry at the previous cursor location.
12098                                pane.update(cx, |pane, _| pane.disable_history());
12099                                target_editor.go_to_singleton_buffer_range(range, window, cx);
12100                                pane.update(cx, |pane, _| pane.enable_history());
12101                            });
12102                        });
12103                    }
12104                    Navigated::Yes
12105                })
12106            })
12107        } else if !definitions.is_empty() {
12108            cx.spawn_in(window, |editor, mut cx| async move {
12109                let (title, location_tasks, workspace) = editor
12110                    .update_in(&mut cx, |editor, window, cx| {
12111                        let tab_kind = match kind {
12112                            Some(GotoDefinitionKind::Implementation) => "Implementations",
12113                            _ => "Definitions",
12114                        };
12115                        let title = definitions
12116                            .iter()
12117                            .find_map(|definition| match definition {
12118                                HoverLink::Text(link) => link.origin.as_ref().map(|origin| {
12119                                    let buffer = origin.buffer.read(cx);
12120                                    format!(
12121                                        "{} for {}",
12122                                        tab_kind,
12123                                        buffer
12124                                            .text_for_range(origin.range.clone())
12125                                            .collect::<String>()
12126                                    )
12127                                }),
12128                                HoverLink::InlayHint(_, _) => None,
12129                                HoverLink::Url(_) => None,
12130                                HoverLink::File(_) => None,
12131                            })
12132                            .unwrap_or(tab_kind.to_string());
12133                        let location_tasks = definitions
12134                            .into_iter()
12135                            .map(|definition| match definition {
12136                                HoverLink::Text(link) => Task::ready(Ok(Some(link.target))),
12137                                HoverLink::InlayHint(lsp_location, server_id) => editor
12138                                    .compute_target_location(lsp_location, server_id, window, cx),
12139                                HoverLink::Url(_) => Task::ready(Ok(None)),
12140                                HoverLink::File(_) => Task::ready(Ok(None)),
12141                            })
12142                            .collect::<Vec<_>>();
12143                        (title, location_tasks, editor.workspace().clone())
12144                    })
12145                    .context("location tasks preparation")?;
12146
12147                let locations = future::join_all(location_tasks)
12148                    .await
12149                    .into_iter()
12150                    .filter_map(|location| location.transpose())
12151                    .collect::<Result<_>>()
12152                    .context("location tasks")?;
12153
12154                let Some(workspace) = workspace else {
12155                    return Ok(Navigated::No);
12156                };
12157                let opened = workspace
12158                    .update_in(&mut cx, |workspace, window, cx| {
12159                        Self::open_locations_in_multibuffer(
12160                            workspace,
12161                            locations,
12162                            title,
12163                            split,
12164                            MultibufferSelectionMode::First,
12165                            window,
12166                            cx,
12167                        )
12168                    })
12169                    .ok();
12170
12171                anyhow::Ok(Navigated::from_bool(opened.is_some()))
12172            })
12173        } else {
12174            Task::ready(Ok(Navigated::No))
12175        }
12176    }
12177
12178    fn compute_target_location(
12179        &self,
12180        lsp_location: lsp::Location,
12181        server_id: LanguageServerId,
12182        window: &mut Window,
12183        cx: &mut Context<Self>,
12184    ) -> Task<anyhow::Result<Option<Location>>> {
12185        let Some(project) = self.project.clone() else {
12186            return Task::ready(Ok(None));
12187        };
12188
12189        cx.spawn_in(window, move |editor, mut cx| async move {
12190            let location_task = editor.update(&mut cx, |_, cx| {
12191                project.update(cx, |project, cx| {
12192                    let language_server_name = project
12193                        .language_server_statuses(cx)
12194                        .find(|(id, _)| server_id == *id)
12195                        .map(|(_, status)| LanguageServerName::from(status.name.as_str()));
12196                    language_server_name.map(|language_server_name| {
12197                        project.open_local_buffer_via_lsp(
12198                            lsp_location.uri.clone(),
12199                            server_id,
12200                            language_server_name,
12201                            cx,
12202                        )
12203                    })
12204                })
12205            })?;
12206            let location = match location_task {
12207                Some(task) => Some({
12208                    let target_buffer_handle = task.await.context("open local buffer")?;
12209                    let range = target_buffer_handle.update(&mut cx, |target_buffer, _| {
12210                        let target_start = target_buffer
12211                            .clip_point_utf16(point_from_lsp(lsp_location.range.start), Bias::Left);
12212                        let target_end = target_buffer
12213                            .clip_point_utf16(point_from_lsp(lsp_location.range.end), Bias::Left);
12214                        target_buffer.anchor_after(target_start)
12215                            ..target_buffer.anchor_before(target_end)
12216                    })?;
12217                    Location {
12218                        buffer: target_buffer_handle,
12219                        range,
12220                    }
12221                }),
12222                None => None,
12223            };
12224            Ok(location)
12225        })
12226    }
12227
12228    pub fn find_all_references(
12229        &mut self,
12230        _: &FindAllReferences,
12231        window: &mut Window,
12232        cx: &mut Context<Self>,
12233    ) -> Option<Task<Result<Navigated>>> {
12234        let selection = self.selections.newest::<usize>(cx);
12235        let multi_buffer = self.buffer.read(cx);
12236        let head = selection.head();
12237
12238        let multi_buffer_snapshot = multi_buffer.snapshot(cx);
12239        let head_anchor = multi_buffer_snapshot.anchor_at(
12240            head,
12241            if head < selection.tail() {
12242                Bias::Right
12243            } else {
12244                Bias::Left
12245            },
12246        );
12247
12248        match self
12249            .find_all_references_task_sources
12250            .binary_search_by(|anchor| anchor.cmp(&head_anchor, &multi_buffer_snapshot))
12251        {
12252            Ok(_) => {
12253                log::info!(
12254                    "Ignoring repeated FindAllReferences invocation with the position of already running task"
12255                );
12256                return None;
12257            }
12258            Err(i) => {
12259                self.find_all_references_task_sources.insert(i, head_anchor);
12260            }
12261        }
12262
12263        let (buffer, head) = multi_buffer.text_anchor_for_position(head, cx)?;
12264        let workspace = self.workspace()?;
12265        let project = workspace.read(cx).project().clone();
12266        let references = project.update(cx, |project, cx| project.references(&buffer, head, cx));
12267        Some(cx.spawn_in(window, |editor, mut cx| async move {
12268            let _cleanup = defer({
12269                let mut cx = cx.clone();
12270                move || {
12271                    let _ = editor.update(&mut cx, |editor, _| {
12272                        if let Ok(i) =
12273                            editor
12274                                .find_all_references_task_sources
12275                                .binary_search_by(|anchor| {
12276                                    anchor.cmp(&head_anchor, &multi_buffer_snapshot)
12277                                })
12278                        {
12279                            editor.find_all_references_task_sources.remove(i);
12280                        }
12281                    });
12282                }
12283            });
12284
12285            let locations = references.await?;
12286            if locations.is_empty() {
12287                return anyhow::Ok(Navigated::No);
12288            }
12289
12290            workspace.update_in(&mut cx, |workspace, window, cx| {
12291                let title = locations
12292                    .first()
12293                    .as_ref()
12294                    .map(|location| {
12295                        let buffer = location.buffer.read(cx);
12296                        format!(
12297                            "References to `{}`",
12298                            buffer
12299                                .text_for_range(location.range.clone())
12300                                .collect::<String>()
12301                        )
12302                    })
12303                    .unwrap();
12304                Self::open_locations_in_multibuffer(
12305                    workspace,
12306                    locations,
12307                    title,
12308                    false,
12309                    MultibufferSelectionMode::First,
12310                    window,
12311                    cx,
12312                );
12313                Navigated::Yes
12314            })
12315        }))
12316    }
12317
12318    /// Opens a multibuffer with the given project locations in it
12319    pub fn open_locations_in_multibuffer(
12320        workspace: &mut Workspace,
12321        mut locations: Vec<Location>,
12322        title: String,
12323        split: bool,
12324        multibuffer_selection_mode: MultibufferSelectionMode,
12325        window: &mut Window,
12326        cx: &mut Context<Workspace>,
12327    ) {
12328        // If there are multiple definitions, open them in a multibuffer
12329        locations.sort_by_key(|location| location.buffer.read(cx).remote_id());
12330        let mut locations = locations.into_iter().peekable();
12331        let mut ranges = Vec::new();
12332        let capability = workspace.project().read(cx).capability();
12333
12334        let excerpt_buffer = cx.new(|cx| {
12335            let mut multibuffer = MultiBuffer::new(capability);
12336            while let Some(location) = locations.next() {
12337                let buffer = location.buffer.read(cx);
12338                let mut ranges_for_buffer = Vec::new();
12339                let range = location.range.to_offset(buffer);
12340                ranges_for_buffer.push(range.clone());
12341
12342                while let Some(next_location) = locations.peek() {
12343                    if next_location.buffer == location.buffer {
12344                        ranges_for_buffer.push(next_location.range.to_offset(buffer));
12345                        locations.next();
12346                    } else {
12347                        break;
12348                    }
12349                }
12350
12351                ranges_for_buffer.sort_by_key(|range| (range.start, Reverse(range.end)));
12352                ranges.extend(multibuffer.push_excerpts_with_context_lines(
12353                    location.buffer.clone(),
12354                    ranges_for_buffer,
12355                    DEFAULT_MULTIBUFFER_CONTEXT,
12356                    cx,
12357                ))
12358            }
12359
12360            multibuffer.with_title(title)
12361        });
12362
12363        let editor = cx.new(|cx| {
12364            Editor::for_multibuffer(
12365                excerpt_buffer,
12366                Some(workspace.project().clone()),
12367                window,
12368                cx,
12369            )
12370        });
12371        editor.update(cx, |editor, cx| {
12372            match multibuffer_selection_mode {
12373                MultibufferSelectionMode::First => {
12374                    if let Some(first_range) = ranges.first() {
12375                        editor.change_selections(None, window, cx, |selections| {
12376                            selections.clear_disjoint();
12377                            selections.select_anchor_ranges(std::iter::once(first_range.clone()));
12378                        });
12379                    }
12380                    editor.highlight_background::<Self>(
12381                        &ranges,
12382                        |theme| theme.editor_highlighted_line_background,
12383                        cx,
12384                    );
12385                }
12386                MultibufferSelectionMode::All => {
12387                    editor.change_selections(None, window, cx, |selections| {
12388                        selections.clear_disjoint();
12389                        selections.select_anchor_ranges(ranges);
12390                    });
12391                }
12392            }
12393            editor.register_buffers_with_language_servers(cx);
12394        });
12395
12396        let item = Box::new(editor);
12397        let item_id = item.item_id();
12398
12399        if split {
12400            workspace.split_item(SplitDirection::Right, item.clone(), window, cx);
12401        } else {
12402            let destination_index = workspace.active_pane().update(cx, |pane, cx| {
12403                if PreviewTabsSettings::get_global(cx).enable_preview_from_code_navigation {
12404                    pane.close_current_preview_item(window, cx)
12405                } else {
12406                    None
12407                }
12408            });
12409            workspace.add_item_to_active_pane(item.clone(), destination_index, true, window, cx);
12410        }
12411        workspace.active_pane().update(cx, |pane, cx| {
12412            pane.set_preview_item_id(Some(item_id), cx);
12413        });
12414    }
12415
12416    pub fn rename(
12417        &mut self,
12418        _: &Rename,
12419        window: &mut Window,
12420        cx: &mut Context<Self>,
12421    ) -> Option<Task<Result<()>>> {
12422        use language::ToOffset as _;
12423
12424        let provider = self.semantics_provider.clone()?;
12425        let selection = self.selections.newest_anchor().clone();
12426        let (cursor_buffer, cursor_buffer_position) = self
12427            .buffer
12428            .read(cx)
12429            .text_anchor_for_position(selection.head(), cx)?;
12430        let (tail_buffer, cursor_buffer_position_end) = self
12431            .buffer
12432            .read(cx)
12433            .text_anchor_for_position(selection.tail(), cx)?;
12434        if tail_buffer != cursor_buffer {
12435            return None;
12436        }
12437
12438        let snapshot = cursor_buffer.read(cx).snapshot();
12439        let cursor_buffer_offset = cursor_buffer_position.to_offset(&snapshot);
12440        let cursor_buffer_offset_end = cursor_buffer_position_end.to_offset(&snapshot);
12441        let prepare_rename = provider
12442            .range_for_rename(&cursor_buffer, cursor_buffer_position, cx)
12443            .unwrap_or_else(|| Task::ready(Ok(None)));
12444        drop(snapshot);
12445
12446        Some(cx.spawn_in(window, |this, mut cx| async move {
12447            let rename_range = if let Some(range) = prepare_rename.await? {
12448                Some(range)
12449            } else {
12450                this.update(&mut cx, |this, cx| {
12451                    let buffer = this.buffer.read(cx).snapshot(cx);
12452                    let mut buffer_highlights = this
12453                        .document_highlights_for_position(selection.head(), &buffer)
12454                        .filter(|highlight| {
12455                            highlight.start.excerpt_id == selection.head().excerpt_id
12456                                && highlight.end.excerpt_id == selection.head().excerpt_id
12457                        });
12458                    buffer_highlights
12459                        .next()
12460                        .map(|highlight| highlight.start.text_anchor..highlight.end.text_anchor)
12461                })?
12462            };
12463            if let Some(rename_range) = rename_range {
12464                this.update_in(&mut cx, |this, window, cx| {
12465                    let snapshot = cursor_buffer.read(cx).snapshot();
12466                    let rename_buffer_range = rename_range.to_offset(&snapshot);
12467                    let cursor_offset_in_rename_range =
12468                        cursor_buffer_offset.saturating_sub(rename_buffer_range.start);
12469                    let cursor_offset_in_rename_range_end =
12470                        cursor_buffer_offset_end.saturating_sub(rename_buffer_range.start);
12471
12472                    this.take_rename(false, window, cx);
12473                    let buffer = this.buffer.read(cx).read(cx);
12474                    let cursor_offset = selection.head().to_offset(&buffer);
12475                    let rename_start = cursor_offset.saturating_sub(cursor_offset_in_rename_range);
12476                    let rename_end = rename_start + rename_buffer_range.len();
12477                    let range = buffer.anchor_before(rename_start)..buffer.anchor_after(rename_end);
12478                    let mut old_highlight_id = None;
12479                    let old_name: Arc<str> = buffer
12480                        .chunks(rename_start..rename_end, true)
12481                        .map(|chunk| {
12482                            if old_highlight_id.is_none() {
12483                                old_highlight_id = chunk.syntax_highlight_id;
12484                            }
12485                            chunk.text
12486                        })
12487                        .collect::<String>()
12488                        .into();
12489
12490                    drop(buffer);
12491
12492                    // Position the selection in the rename editor so that it matches the current selection.
12493                    this.show_local_selections = false;
12494                    let rename_editor = cx.new(|cx| {
12495                        let mut editor = Editor::single_line(window, cx);
12496                        editor.buffer.update(cx, |buffer, cx| {
12497                            buffer.edit([(0..0, old_name.clone())], None, cx)
12498                        });
12499                        let rename_selection_range = match cursor_offset_in_rename_range
12500                            .cmp(&cursor_offset_in_rename_range_end)
12501                        {
12502                            Ordering::Equal => {
12503                                editor.select_all(&SelectAll, window, cx);
12504                                return editor;
12505                            }
12506                            Ordering::Less => {
12507                                cursor_offset_in_rename_range..cursor_offset_in_rename_range_end
12508                            }
12509                            Ordering::Greater => {
12510                                cursor_offset_in_rename_range_end..cursor_offset_in_rename_range
12511                            }
12512                        };
12513                        if rename_selection_range.end > old_name.len() {
12514                            editor.select_all(&SelectAll, window, cx);
12515                        } else {
12516                            editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
12517                                s.select_ranges([rename_selection_range]);
12518                            });
12519                        }
12520                        editor
12521                    });
12522                    cx.subscribe(&rename_editor, |_, _, e: &EditorEvent, cx| {
12523                        if e == &EditorEvent::Focused {
12524                            cx.emit(EditorEvent::FocusedIn)
12525                        }
12526                    })
12527                    .detach();
12528
12529                    let write_highlights =
12530                        this.clear_background_highlights::<DocumentHighlightWrite>(cx);
12531                    let read_highlights =
12532                        this.clear_background_highlights::<DocumentHighlightRead>(cx);
12533                    let ranges = write_highlights
12534                        .iter()
12535                        .flat_map(|(_, ranges)| ranges.iter())
12536                        .chain(read_highlights.iter().flat_map(|(_, ranges)| ranges.iter()))
12537                        .cloned()
12538                        .collect();
12539
12540                    this.highlight_text::<Rename>(
12541                        ranges,
12542                        HighlightStyle {
12543                            fade_out: Some(0.6),
12544                            ..Default::default()
12545                        },
12546                        cx,
12547                    );
12548                    let rename_focus_handle = rename_editor.focus_handle(cx);
12549                    window.focus(&rename_focus_handle);
12550                    let block_id = this.insert_blocks(
12551                        [BlockProperties {
12552                            style: BlockStyle::Flex,
12553                            placement: BlockPlacement::Below(range.start),
12554                            height: 1,
12555                            render: Arc::new({
12556                                let rename_editor = rename_editor.clone();
12557                                move |cx: &mut BlockContext| {
12558                                    let mut text_style = cx.editor_style.text.clone();
12559                                    if let Some(highlight_style) = old_highlight_id
12560                                        .and_then(|h| h.style(&cx.editor_style.syntax))
12561                                    {
12562                                        text_style = text_style.highlight(highlight_style);
12563                                    }
12564                                    div()
12565                                        .block_mouse_down()
12566                                        .pl(cx.anchor_x)
12567                                        .child(EditorElement::new(
12568                                            &rename_editor,
12569                                            EditorStyle {
12570                                                background: cx.theme().system().transparent,
12571                                                local_player: cx.editor_style.local_player,
12572                                                text: text_style,
12573                                                scrollbar_width: cx.editor_style.scrollbar_width,
12574                                                syntax: cx.editor_style.syntax.clone(),
12575                                                status: cx.editor_style.status.clone(),
12576                                                inlay_hints_style: HighlightStyle {
12577                                                    font_weight: Some(FontWeight::BOLD),
12578                                                    ..make_inlay_hints_style(cx.app)
12579                                                },
12580                                                inline_completion_styles: make_suggestion_styles(
12581                                                    cx.app,
12582                                                ),
12583                                                ..EditorStyle::default()
12584                                            },
12585                                        ))
12586                                        .into_any_element()
12587                                }
12588                            }),
12589                            priority: 0,
12590                        }],
12591                        Some(Autoscroll::fit()),
12592                        cx,
12593                    )[0];
12594                    this.pending_rename = Some(RenameState {
12595                        range,
12596                        old_name,
12597                        editor: rename_editor,
12598                        block_id,
12599                    });
12600                })?;
12601            }
12602
12603            Ok(())
12604        }))
12605    }
12606
12607    pub fn confirm_rename(
12608        &mut self,
12609        _: &ConfirmRename,
12610        window: &mut Window,
12611        cx: &mut Context<Self>,
12612    ) -> Option<Task<Result<()>>> {
12613        let rename = self.take_rename(false, window, cx)?;
12614        let workspace = self.workspace()?.downgrade();
12615        let (buffer, start) = self
12616            .buffer
12617            .read(cx)
12618            .text_anchor_for_position(rename.range.start, cx)?;
12619        let (end_buffer, _) = self
12620            .buffer
12621            .read(cx)
12622            .text_anchor_for_position(rename.range.end, cx)?;
12623        if buffer != end_buffer {
12624            return None;
12625        }
12626
12627        let old_name = rename.old_name;
12628        let new_name = rename.editor.read(cx).text(cx);
12629
12630        let rename = self.semantics_provider.as_ref()?.perform_rename(
12631            &buffer,
12632            start,
12633            new_name.clone(),
12634            cx,
12635        )?;
12636
12637        Some(cx.spawn_in(window, |editor, mut cx| async move {
12638            let project_transaction = rename.await?;
12639            Self::open_project_transaction(
12640                &editor,
12641                workspace,
12642                project_transaction,
12643                format!("Rename: {}{}", old_name, new_name),
12644                cx.clone(),
12645            )
12646            .await?;
12647
12648            editor.update(&mut cx, |editor, cx| {
12649                editor.refresh_document_highlights(cx);
12650            })?;
12651            Ok(())
12652        }))
12653    }
12654
12655    fn take_rename(
12656        &mut self,
12657        moving_cursor: bool,
12658        window: &mut Window,
12659        cx: &mut Context<Self>,
12660    ) -> Option<RenameState> {
12661        let rename = self.pending_rename.take()?;
12662        if rename.editor.focus_handle(cx).is_focused(window) {
12663            window.focus(&self.focus_handle);
12664        }
12665
12666        self.remove_blocks(
12667            [rename.block_id].into_iter().collect(),
12668            Some(Autoscroll::fit()),
12669            cx,
12670        );
12671        self.clear_highlights::<Rename>(cx);
12672        self.show_local_selections = true;
12673
12674        if moving_cursor {
12675            let cursor_in_rename_editor = rename.editor.update(cx, |editor, cx| {
12676                editor.selections.newest::<usize>(cx).head()
12677            });
12678
12679            // Update the selection to match the position of the selection inside
12680            // the rename editor.
12681            let snapshot = self.buffer.read(cx).read(cx);
12682            let rename_range = rename.range.to_offset(&snapshot);
12683            let cursor_in_editor = snapshot
12684                .clip_offset(rename_range.start + cursor_in_rename_editor, Bias::Left)
12685                .min(rename_range.end);
12686            drop(snapshot);
12687
12688            self.change_selections(None, window, cx, |s| {
12689                s.select_ranges(vec![cursor_in_editor..cursor_in_editor])
12690            });
12691        } else {
12692            self.refresh_document_highlights(cx);
12693        }
12694
12695        Some(rename)
12696    }
12697
12698    pub fn pending_rename(&self) -> Option<&RenameState> {
12699        self.pending_rename.as_ref()
12700    }
12701
12702    fn format(
12703        &mut self,
12704        _: &Format,
12705        window: &mut Window,
12706        cx: &mut Context<Self>,
12707    ) -> Option<Task<Result<()>>> {
12708        let project = match &self.project {
12709            Some(project) => project.clone(),
12710            None => return None,
12711        };
12712
12713        Some(self.perform_format(
12714            project,
12715            FormatTrigger::Manual,
12716            FormatTarget::Buffers,
12717            window,
12718            cx,
12719        ))
12720    }
12721
12722    fn format_selections(
12723        &mut self,
12724        _: &FormatSelections,
12725        window: &mut Window,
12726        cx: &mut Context<Self>,
12727    ) -> Option<Task<Result<()>>> {
12728        let project = match &self.project {
12729            Some(project) => project.clone(),
12730            None => return None,
12731        };
12732
12733        let ranges = self
12734            .selections
12735            .all_adjusted(cx)
12736            .into_iter()
12737            .map(|selection| selection.range())
12738            .collect_vec();
12739
12740        Some(self.perform_format(
12741            project,
12742            FormatTrigger::Manual,
12743            FormatTarget::Ranges(ranges),
12744            window,
12745            cx,
12746        ))
12747    }
12748
12749    fn perform_format(
12750        &mut self,
12751        project: Entity<Project>,
12752        trigger: FormatTrigger,
12753        target: FormatTarget,
12754        window: &mut Window,
12755        cx: &mut Context<Self>,
12756    ) -> Task<Result<()>> {
12757        let buffer = self.buffer.clone();
12758        let (buffers, target) = match target {
12759            FormatTarget::Buffers => {
12760                let mut buffers = buffer.read(cx).all_buffers();
12761                if trigger == FormatTrigger::Save {
12762                    buffers.retain(|buffer| buffer.read(cx).is_dirty());
12763                }
12764                (buffers, LspFormatTarget::Buffers)
12765            }
12766            FormatTarget::Ranges(selection_ranges) => {
12767                let multi_buffer = buffer.read(cx);
12768                let snapshot = multi_buffer.read(cx);
12769                let mut buffers = HashSet::default();
12770                let mut buffer_id_to_ranges: BTreeMap<BufferId, Vec<Range<text::Anchor>>> =
12771                    BTreeMap::new();
12772                for selection_range in selection_ranges {
12773                    for (buffer, buffer_range, _) in
12774                        snapshot.range_to_buffer_ranges(selection_range)
12775                    {
12776                        let buffer_id = buffer.remote_id();
12777                        let start = buffer.anchor_before(buffer_range.start);
12778                        let end = buffer.anchor_after(buffer_range.end);
12779                        buffers.insert(multi_buffer.buffer(buffer_id).unwrap());
12780                        buffer_id_to_ranges
12781                            .entry(buffer_id)
12782                            .and_modify(|buffer_ranges| buffer_ranges.push(start..end))
12783                            .or_insert_with(|| vec![start..end]);
12784                    }
12785                }
12786                (buffers, LspFormatTarget::Ranges(buffer_id_to_ranges))
12787            }
12788        };
12789
12790        let mut timeout = cx.background_executor().timer(FORMAT_TIMEOUT).fuse();
12791        let format = project.update(cx, |project, cx| {
12792            project.format(buffers, target, true, trigger, cx)
12793        });
12794
12795        cx.spawn_in(window, |_, mut cx| async move {
12796            let transaction = futures::select_biased! {
12797                () = timeout => {
12798                    log::warn!("timed out waiting for formatting");
12799                    None
12800                }
12801                transaction = format.log_err().fuse() => transaction,
12802            };
12803
12804            buffer
12805                .update(&mut cx, |buffer, cx| {
12806                    if let Some(transaction) = transaction {
12807                        if !buffer.is_singleton() {
12808                            buffer.push_transaction(&transaction.0, cx);
12809                        }
12810                    }
12811                    cx.notify();
12812                })
12813                .ok();
12814
12815            Ok(())
12816        })
12817    }
12818
12819    fn organize_imports(
12820        &mut self,
12821        _: &OrganizeImports,
12822        window: &mut Window,
12823        cx: &mut Context<Self>,
12824    ) -> Option<Task<Result<()>>> {
12825        let project = match &self.project {
12826            Some(project) => project.clone(),
12827            None => return None,
12828        };
12829        Some(self.perform_code_action_kind(
12830            project,
12831            CodeActionKind::SOURCE_ORGANIZE_IMPORTS,
12832            window,
12833            cx,
12834        ))
12835    }
12836
12837    fn perform_code_action_kind(
12838        &mut self,
12839        project: Entity<Project>,
12840        kind: CodeActionKind,
12841        window: &mut Window,
12842        cx: &mut Context<Self>,
12843    ) -> Task<Result<()>> {
12844        let buffer = self.buffer.clone();
12845        let buffers = buffer.read(cx).all_buffers();
12846        let mut timeout = cx.background_executor().timer(CODE_ACTION_TIMEOUT).fuse();
12847        let apply_action = project.update(cx, |project, cx| {
12848            project.apply_code_action_kind(buffers, kind, true, cx)
12849        });
12850        cx.spawn_in(window, |_, mut cx| async move {
12851            let transaction = futures::select_biased! {
12852                () = timeout => {
12853                    log::warn!("timed out waiting for executing code action");
12854                    None
12855                }
12856                transaction = apply_action.log_err().fuse() => transaction,
12857            };
12858            buffer
12859                .update(&mut cx, |buffer, cx| {
12860                    // check if we need this
12861                    if let Some(transaction) = transaction {
12862                        if !buffer.is_singleton() {
12863                            buffer.push_transaction(&transaction.0, cx);
12864                        }
12865                    }
12866                    cx.notify();
12867                })
12868                .ok();
12869            Ok(())
12870        })
12871    }
12872
12873    fn restart_language_server(
12874        &mut self,
12875        _: &RestartLanguageServer,
12876        _: &mut Window,
12877        cx: &mut Context<Self>,
12878    ) {
12879        if let Some(project) = self.project.clone() {
12880            self.buffer.update(cx, |multi_buffer, cx| {
12881                project.update(cx, |project, cx| {
12882                    project.restart_language_servers_for_buffers(
12883                        multi_buffer.all_buffers().into_iter().collect(),
12884                        cx,
12885                    );
12886                });
12887            })
12888        }
12889    }
12890
12891    fn cancel_language_server_work(
12892        workspace: &mut Workspace,
12893        _: &actions::CancelLanguageServerWork,
12894        _: &mut Window,
12895        cx: &mut Context<Workspace>,
12896    ) {
12897        let project = workspace.project();
12898        let buffers = workspace
12899            .active_item(cx)
12900            .and_then(|item| item.act_as::<Editor>(cx))
12901            .map_or(HashSet::default(), |editor| {
12902                editor.read(cx).buffer.read(cx).all_buffers()
12903            });
12904        project.update(cx, |project, cx| {
12905            project.cancel_language_server_work_for_buffers(buffers, cx);
12906        });
12907    }
12908
12909    fn show_character_palette(
12910        &mut self,
12911        _: &ShowCharacterPalette,
12912        window: &mut Window,
12913        _: &mut Context<Self>,
12914    ) {
12915        window.show_character_palette();
12916    }
12917
12918    fn refresh_active_diagnostics(&mut self, cx: &mut Context<Editor>) {
12919        if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
12920            let buffer = self.buffer.read(cx).snapshot(cx);
12921            let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
12922            let primary_range_end = active_diagnostics.primary_range.end.to_offset(&buffer);
12923            let is_valid = buffer
12924                .diagnostics_in_range::<usize>(primary_range_start..primary_range_end)
12925                .any(|entry| {
12926                    entry.diagnostic.is_primary
12927                        && !entry.range.is_empty()
12928                        && entry.range.start == primary_range_start
12929                        && entry.diagnostic.message == active_diagnostics.primary_message
12930                });
12931
12932            if is_valid != active_diagnostics.is_valid {
12933                active_diagnostics.is_valid = is_valid;
12934                if is_valid {
12935                    let mut new_styles = HashMap::default();
12936                    for (block_id, diagnostic) in &active_diagnostics.blocks {
12937                        new_styles.insert(
12938                            *block_id,
12939                            diagnostic_block_renderer(diagnostic.clone(), None, true),
12940                        );
12941                    }
12942                    self.display_map.update(cx, |display_map, _cx| {
12943                        display_map.replace_blocks(new_styles);
12944                    });
12945                } else {
12946                    self.dismiss_diagnostics(cx);
12947                }
12948            }
12949        }
12950    }
12951
12952    fn activate_diagnostics(
12953        &mut self,
12954        buffer_id: BufferId,
12955        group_id: usize,
12956        window: &mut Window,
12957        cx: &mut Context<Self>,
12958    ) {
12959        self.dismiss_diagnostics(cx);
12960        let snapshot = self.snapshot(window, cx);
12961        self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
12962            let buffer = self.buffer.read(cx).snapshot(cx);
12963
12964            let mut primary_range = None;
12965            let mut primary_message = None;
12966            let diagnostic_group = buffer
12967                .diagnostic_group(buffer_id, group_id)
12968                .filter_map(|entry| {
12969                    let start = entry.range.start;
12970                    let end = entry.range.end;
12971                    if snapshot.is_line_folded(MultiBufferRow(start.row))
12972                        && (start.row == end.row
12973                            || snapshot.is_line_folded(MultiBufferRow(end.row)))
12974                    {
12975                        return None;
12976                    }
12977                    if entry.diagnostic.is_primary {
12978                        primary_range = Some(entry.range.clone());
12979                        primary_message = Some(entry.diagnostic.message.clone());
12980                    }
12981                    Some(entry)
12982                })
12983                .collect::<Vec<_>>();
12984            let primary_range = primary_range?;
12985            let primary_message = primary_message?;
12986
12987            let blocks = display_map
12988                .insert_blocks(
12989                    diagnostic_group.iter().map(|entry| {
12990                        let diagnostic = entry.diagnostic.clone();
12991                        let message_height = diagnostic.message.matches('\n').count() as u32 + 1;
12992                        BlockProperties {
12993                            style: BlockStyle::Fixed,
12994                            placement: BlockPlacement::Below(
12995                                buffer.anchor_after(entry.range.start),
12996                            ),
12997                            height: message_height,
12998                            render: diagnostic_block_renderer(diagnostic, None, true),
12999                            priority: 0,
13000                        }
13001                    }),
13002                    cx,
13003                )
13004                .into_iter()
13005                .zip(diagnostic_group.into_iter().map(|entry| entry.diagnostic))
13006                .collect();
13007
13008            Some(ActiveDiagnosticGroup {
13009                primary_range: buffer.anchor_before(primary_range.start)
13010                    ..buffer.anchor_after(primary_range.end),
13011                primary_message,
13012                group_id,
13013                blocks,
13014                is_valid: true,
13015            })
13016        });
13017    }
13018
13019    fn dismiss_diagnostics(&mut self, cx: &mut Context<Self>) {
13020        if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
13021            self.display_map.update(cx, |display_map, cx| {
13022                display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx);
13023            });
13024            cx.notify();
13025        }
13026    }
13027
13028    /// Disable inline diagnostics rendering for this editor.
13029    pub fn disable_inline_diagnostics(&mut self) {
13030        self.inline_diagnostics_enabled = false;
13031        self.inline_diagnostics_update = Task::ready(());
13032        self.inline_diagnostics.clear();
13033    }
13034
13035    pub fn inline_diagnostics_enabled(&self) -> bool {
13036        self.inline_diagnostics_enabled
13037    }
13038
13039    pub fn show_inline_diagnostics(&self) -> bool {
13040        self.show_inline_diagnostics
13041    }
13042
13043    pub fn toggle_inline_diagnostics(
13044        &mut self,
13045        _: &ToggleInlineDiagnostics,
13046        window: &mut Window,
13047        cx: &mut Context<'_, Editor>,
13048    ) {
13049        self.show_inline_diagnostics = !self.show_inline_diagnostics;
13050        self.refresh_inline_diagnostics(false, window, cx);
13051    }
13052
13053    fn refresh_inline_diagnostics(
13054        &mut self,
13055        debounce: bool,
13056        window: &mut Window,
13057        cx: &mut Context<Self>,
13058    ) {
13059        if !self.inline_diagnostics_enabled || !self.show_inline_diagnostics {
13060            self.inline_diagnostics_update = Task::ready(());
13061            self.inline_diagnostics.clear();
13062            return;
13063        }
13064
13065        let debounce_ms = ProjectSettings::get_global(cx)
13066            .diagnostics
13067            .inline
13068            .update_debounce_ms;
13069        let debounce = if debounce && debounce_ms > 0 {
13070            Some(Duration::from_millis(debounce_ms))
13071        } else {
13072            None
13073        };
13074        self.inline_diagnostics_update = cx.spawn_in(window, |editor, mut cx| async move {
13075            if let Some(debounce) = debounce {
13076                cx.background_executor().timer(debounce).await;
13077            }
13078            let Some(snapshot) = editor
13079                .update(&mut cx, |editor, cx| editor.buffer().read(cx).snapshot(cx))
13080                .ok()
13081            else {
13082                return;
13083            };
13084
13085            let new_inline_diagnostics = cx
13086                .background_spawn(async move {
13087                    let mut inline_diagnostics = Vec::<(Anchor, InlineDiagnostic)>::new();
13088                    for diagnostic_entry in snapshot.diagnostics_in_range(0..snapshot.len()) {
13089                        let message = diagnostic_entry
13090                            .diagnostic
13091                            .message
13092                            .split_once('\n')
13093                            .map(|(line, _)| line)
13094                            .map(SharedString::new)
13095                            .unwrap_or_else(|| {
13096                                SharedString::from(diagnostic_entry.diagnostic.message)
13097                            });
13098                        let start_anchor = snapshot.anchor_before(diagnostic_entry.range.start);
13099                        let (Ok(i) | Err(i)) = inline_diagnostics
13100                            .binary_search_by(|(probe, _)| probe.cmp(&start_anchor, &snapshot));
13101                        inline_diagnostics.insert(
13102                            i,
13103                            (
13104                                start_anchor,
13105                                InlineDiagnostic {
13106                                    message,
13107                                    group_id: diagnostic_entry.diagnostic.group_id,
13108                                    start: diagnostic_entry.range.start.to_point(&snapshot),
13109                                    is_primary: diagnostic_entry.diagnostic.is_primary,
13110                                    severity: diagnostic_entry.diagnostic.severity,
13111                                },
13112                            ),
13113                        );
13114                    }
13115                    inline_diagnostics
13116                })
13117                .await;
13118
13119            editor
13120                .update(&mut cx, |editor, cx| {
13121                    editor.inline_diagnostics = new_inline_diagnostics;
13122                    cx.notify();
13123                })
13124                .ok();
13125        });
13126    }
13127
13128    pub fn set_selections_from_remote(
13129        &mut self,
13130        selections: Vec<Selection<Anchor>>,
13131        pending_selection: Option<Selection<Anchor>>,
13132        window: &mut Window,
13133        cx: &mut Context<Self>,
13134    ) {
13135        let old_cursor_position = self.selections.newest_anchor().head();
13136        self.selections.change_with(cx, |s| {
13137            s.select_anchors(selections);
13138            if let Some(pending_selection) = pending_selection {
13139                s.set_pending(pending_selection, SelectMode::Character);
13140            } else {
13141                s.clear_pending();
13142            }
13143        });
13144        self.selections_did_change(false, &old_cursor_position, true, window, cx);
13145    }
13146
13147    fn push_to_selection_history(&mut self) {
13148        self.selection_history.push(SelectionHistoryEntry {
13149            selections: self.selections.disjoint_anchors(),
13150            select_next_state: self.select_next_state.clone(),
13151            select_prev_state: self.select_prev_state.clone(),
13152            add_selections_state: self.add_selections_state.clone(),
13153        });
13154    }
13155
13156    pub fn transact(
13157        &mut self,
13158        window: &mut Window,
13159        cx: &mut Context<Self>,
13160        update: impl FnOnce(&mut Self, &mut Window, &mut Context<Self>),
13161    ) -> Option<TransactionId> {
13162        self.start_transaction_at(Instant::now(), window, cx);
13163        update(self, window, cx);
13164        self.end_transaction_at(Instant::now(), cx)
13165    }
13166
13167    pub fn start_transaction_at(
13168        &mut self,
13169        now: Instant,
13170        window: &mut Window,
13171        cx: &mut Context<Self>,
13172    ) {
13173        self.end_selection(window, cx);
13174        if let Some(tx_id) = self
13175            .buffer
13176            .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx))
13177        {
13178            self.selection_history
13179                .insert_transaction(tx_id, self.selections.disjoint_anchors());
13180            cx.emit(EditorEvent::TransactionBegun {
13181                transaction_id: tx_id,
13182            })
13183        }
13184    }
13185
13186    pub fn end_transaction_at(
13187        &mut self,
13188        now: Instant,
13189        cx: &mut Context<Self>,
13190    ) -> Option<TransactionId> {
13191        if let Some(transaction_id) = self
13192            .buffer
13193            .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
13194        {
13195            if let Some((_, end_selections)) =
13196                self.selection_history.transaction_mut(transaction_id)
13197            {
13198                *end_selections = Some(self.selections.disjoint_anchors());
13199            } else {
13200                log::error!("unexpectedly ended a transaction that wasn't started by this editor");
13201            }
13202
13203            cx.emit(EditorEvent::Edited { transaction_id });
13204            Some(transaction_id)
13205        } else {
13206            None
13207        }
13208    }
13209
13210    pub fn set_mark(&mut self, _: &actions::SetMark, window: &mut Window, cx: &mut Context<Self>) {
13211        if self.selection_mark_mode {
13212            self.change_selections(None, window, cx, |s| {
13213                s.move_with(|_, sel| {
13214                    sel.collapse_to(sel.head(), SelectionGoal::None);
13215                });
13216            })
13217        }
13218        self.selection_mark_mode = true;
13219        cx.notify();
13220    }
13221
13222    pub fn swap_selection_ends(
13223        &mut self,
13224        _: &actions::SwapSelectionEnds,
13225        window: &mut Window,
13226        cx: &mut Context<Self>,
13227    ) {
13228        self.change_selections(None, window, cx, |s| {
13229            s.move_with(|_, sel| {
13230                if sel.start != sel.end {
13231                    sel.reversed = !sel.reversed
13232                }
13233            });
13234        });
13235        self.request_autoscroll(Autoscroll::newest(), cx);
13236        cx.notify();
13237    }
13238
13239    pub fn toggle_fold(
13240        &mut self,
13241        _: &actions::ToggleFold,
13242        window: &mut Window,
13243        cx: &mut Context<Self>,
13244    ) {
13245        if self.is_singleton(cx) {
13246            let selection = self.selections.newest::<Point>(cx);
13247
13248            let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
13249            let range = if selection.is_empty() {
13250                let point = selection.head().to_display_point(&display_map);
13251                let start = DisplayPoint::new(point.row(), 0).to_point(&display_map);
13252                let end = DisplayPoint::new(point.row(), display_map.line_len(point.row()))
13253                    .to_point(&display_map);
13254                start..end
13255            } else {
13256                selection.range()
13257            };
13258            if display_map.folds_in_range(range).next().is_some() {
13259                self.unfold_lines(&Default::default(), window, cx)
13260            } else {
13261                self.fold(&Default::default(), window, cx)
13262            }
13263        } else {
13264            let multi_buffer_snapshot = self.buffer.read(cx).snapshot(cx);
13265            let buffer_ids: HashSet<_> = self
13266                .selections
13267                .disjoint_anchor_ranges()
13268                .flat_map(|range| multi_buffer_snapshot.buffer_ids_for_range(range))
13269                .collect();
13270
13271            let should_unfold = buffer_ids
13272                .iter()
13273                .any(|buffer_id| self.is_buffer_folded(*buffer_id, cx));
13274
13275            for buffer_id in buffer_ids {
13276                if should_unfold {
13277                    self.unfold_buffer(buffer_id, cx);
13278                } else {
13279                    self.fold_buffer(buffer_id, cx);
13280                }
13281            }
13282        }
13283    }
13284
13285    pub fn toggle_fold_recursive(
13286        &mut self,
13287        _: &actions::ToggleFoldRecursive,
13288        window: &mut Window,
13289        cx: &mut Context<Self>,
13290    ) {
13291        let selection = self.selections.newest::<Point>(cx);
13292
13293        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
13294        let range = if selection.is_empty() {
13295            let point = selection.head().to_display_point(&display_map);
13296            let start = DisplayPoint::new(point.row(), 0).to_point(&display_map);
13297            let end = DisplayPoint::new(point.row(), display_map.line_len(point.row()))
13298                .to_point(&display_map);
13299            start..end
13300        } else {
13301            selection.range()
13302        };
13303        if display_map.folds_in_range(range).next().is_some() {
13304            self.unfold_recursive(&Default::default(), window, cx)
13305        } else {
13306            self.fold_recursive(&Default::default(), window, cx)
13307        }
13308    }
13309
13310    pub fn fold(&mut self, _: &actions::Fold, window: &mut Window, cx: &mut Context<Self>) {
13311        if self.is_singleton(cx) {
13312            let mut to_fold = Vec::new();
13313            let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
13314            let selections = self.selections.all_adjusted(cx);
13315
13316            for selection in selections {
13317                let range = selection.range().sorted();
13318                let buffer_start_row = range.start.row;
13319
13320                if range.start.row != range.end.row {
13321                    let mut found = false;
13322                    let mut row = range.start.row;
13323                    while row <= range.end.row {
13324                        if let Some(crease) = display_map.crease_for_buffer_row(MultiBufferRow(row))
13325                        {
13326                            found = true;
13327                            row = crease.range().end.row + 1;
13328                            to_fold.push(crease);
13329                        } else {
13330                            row += 1
13331                        }
13332                    }
13333                    if found {
13334                        continue;
13335                    }
13336                }
13337
13338                for row in (0..=range.start.row).rev() {
13339                    if let Some(crease) = display_map.crease_for_buffer_row(MultiBufferRow(row)) {
13340                        if crease.range().end.row >= buffer_start_row {
13341                            to_fold.push(crease);
13342                            if row <= range.start.row {
13343                                break;
13344                            }
13345                        }
13346                    }
13347                }
13348            }
13349
13350            self.fold_creases(to_fold, true, window, cx);
13351        } else {
13352            let multi_buffer_snapshot = self.buffer.read(cx).snapshot(cx);
13353            let buffer_ids = self
13354                .selections
13355                .disjoint_anchor_ranges()
13356                .flat_map(|range| multi_buffer_snapshot.buffer_ids_for_range(range))
13357                .collect::<HashSet<_>>();
13358            for buffer_id in buffer_ids {
13359                self.fold_buffer(buffer_id, cx);
13360            }
13361        }
13362    }
13363
13364    fn fold_at_level(
13365        &mut self,
13366        fold_at: &FoldAtLevel,
13367        window: &mut Window,
13368        cx: &mut Context<Self>,
13369    ) {
13370        if !self.buffer.read(cx).is_singleton() {
13371            return;
13372        }
13373
13374        let fold_at_level = fold_at.0;
13375        let snapshot = self.buffer.read(cx).snapshot(cx);
13376        let mut to_fold = Vec::new();
13377        let mut stack = vec![(0, snapshot.max_row().0, 1)];
13378
13379        while let Some((mut start_row, end_row, current_level)) = stack.pop() {
13380            while start_row < end_row {
13381                match self
13382                    .snapshot(window, cx)
13383                    .crease_for_buffer_row(MultiBufferRow(start_row))
13384                {
13385                    Some(crease) => {
13386                        let nested_start_row = crease.range().start.row + 1;
13387                        let nested_end_row = crease.range().end.row;
13388
13389                        if current_level < fold_at_level {
13390                            stack.push((nested_start_row, nested_end_row, current_level + 1));
13391                        } else if current_level == fold_at_level {
13392                            to_fold.push(crease);
13393                        }
13394
13395                        start_row = nested_end_row + 1;
13396                    }
13397                    None => start_row += 1,
13398                }
13399            }
13400        }
13401
13402        self.fold_creases(to_fold, true, window, cx);
13403    }
13404
13405    pub fn fold_all(&mut self, _: &actions::FoldAll, window: &mut Window, cx: &mut Context<Self>) {
13406        if self.buffer.read(cx).is_singleton() {
13407            let mut fold_ranges = Vec::new();
13408            let snapshot = self.buffer.read(cx).snapshot(cx);
13409
13410            for row in 0..snapshot.max_row().0 {
13411                if let Some(foldable_range) = self
13412                    .snapshot(window, cx)
13413                    .crease_for_buffer_row(MultiBufferRow(row))
13414                {
13415                    fold_ranges.push(foldable_range);
13416                }
13417            }
13418
13419            self.fold_creases(fold_ranges, true, window, cx);
13420        } else {
13421            self.toggle_fold_multiple_buffers = cx.spawn_in(window, |editor, mut cx| async move {
13422                editor
13423                    .update_in(&mut cx, |editor, _, cx| {
13424                        for buffer_id in editor.buffer.read(cx).excerpt_buffer_ids() {
13425                            editor.fold_buffer(buffer_id, cx);
13426                        }
13427                    })
13428                    .ok();
13429            });
13430        }
13431    }
13432
13433    pub fn fold_function_bodies(
13434        &mut self,
13435        _: &actions::FoldFunctionBodies,
13436        window: &mut Window,
13437        cx: &mut Context<Self>,
13438    ) {
13439        let snapshot = self.buffer.read(cx).snapshot(cx);
13440
13441        let ranges = snapshot
13442            .text_object_ranges(0..snapshot.len(), TreeSitterOptions::default())
13443            .filter_map(|(range, obj)| (obj == TextObject::InsideFunction).then_some(range))
13444            .collect::<Vec<_>>();
13445
13446        let creases = ranges
13447            .into_iter()
13448            .map(|range| Crease::simple(range, self.display_map.read(cx).fold_placeholder.clone()))
13449            .collect();
13450
13451        self.fold_creases(creases, true, window, cx);
13452    }
13453
13454    pub fn fold_recursive(
13455        &mut self,
13456        _: &actions::FoldRecursive,
13457        window: &mut Window,
13458        cx: &mut Context<Self>,
13459    ) {
13460        let mut to_fold = Vec::new();
13461        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
13462        let selections = self.selections.all_adjusted(cx);
13463
13464        for selection in selections {
13465            let range = selection.range().sorted();
13466            let buffer_start_row = range.start.row;
13467
13468            if range.start.row != range.end.row {
13469                let mut found = false;
13470                for row in range.start.row..=range.end.row {
13471                    if let Some(crease) = display_map.crease_for_buffer_row(MultiBufferRow(row)) {
13472                        found = true;
13473                        to_fold.push(crease);
13474                    }
13475                }
13476                if found {
13477                    continue;
13478                }
13479            }
13480
13481            for row in (0..=range.start.row).rev() {
13482                if let Some(crease) = display_map.crease_for_buffer_row(MultiBufferRow(row)) {
13483                    if crease.range().end.row >= buffer_start_row {
13484                        to_fold.push(crease);
13485                    } else {
13486                        break;
13487                    }
13488                }
13489            }
13490        }
13491
13492        self.fold_creases(to_fold, true, window, cx);
13493    }
13494
13495    pub fn fold_at(&mut self, fold_at: &FoldAt, window: &mut Window, cx: &mut Context<Self>) {
13496        let buffer_row = fold_at.buffer_row;
13497        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
13498
13499        if let Some(crease) = display_map.crease_for_buffer_row(buffer_row) {
13500            let autoscroll = self
13501                .selections
13502                .all::<Point>(cx)
13503                .iter()
13504                .any(|selection| crease.range().overlaps(&selection.range()));
13505
13506            self.fold_creases(vec![crease], autoscroll, window, cx);
13507        }
13508    }
13509
13510    pub fn unfold_lines(&mut self, _: &UnfoldLines, _window: &mut Window, cx: &mut Context<Self>) {
13511        if self.is_singleton(cx) {
13512            let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
13513            let buffer = &display_map.buffer_snapshot;
13514            let selections = self.selections.all::<Point>(cx);
13515            let ranges = selections
13516                .iter()
13517                .map(|s| {
13518                    let range = s.display_range(&display_map).sorted();
13519                    let mut start = range.start.to_point(&display_map);
13520                    let mut end = range.end.to_point(&display_map);
13521                    start.column = 0;
13522                    end.column = buffer.line_len(MultiBufferRow(end.row));
13523                    start..end
13524                })
13525                .collect::<Vec<_>>();
13526
13527            self.unfold_ranges(&ranges, true, true, cx);
13528        } else {
13529            let multi_buffer_snapshot = self.buffer.read(cx).snapshot(cx);
13530            let buffer_ids = self
13531                .selections
13532                .disjoint_anchor_ranges()
13533                .flat_map(|range| multi_buffer_snapshot.buffer_ids_for_range(range))
13534                .collect::<HashSet<_>>();
13535            for buffer_id in buffer_ids {
13536                self.unfold_buffer(buffer_id, cx);
13537            }
13538        }
13539    }
13540
13541    pub fn unfold_recursive(
13542        &mut self,
13543        _: &UnfoldRecursive,
13544        _window: &mut Window,
13545        cx: &mut Context<Self>,
13546    ) {
13547        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
13548        let selections = self.selections.all::<Point>(cx);
13549        let ranges = selections
13550            .iter()
13551            .map(|s| {
13552                let mut range = s.display_range(&display_map).sorted();
13553                *range.start.column_mut() = 0;
13554                *range.end.column_mut() = display_map.line_len(range.end.row());
13555                let start = range.start.to_point(&display_map);
13556                let end = range.end.to_point(&display_map);
13557                start..end
13558            })
13559            .collect::<Vec<_>>();
13560
13561        self.unfold_ranges(&ranges, true, true, cx);
13562    }
13563
13564    pub fn unfold_at(
13565        &mut self,
13566        unfold_at: &UnfoldAt,
13567        _window: &mut Window,
13568        cx: &mut Context<Self>,
13569    ) {
13570        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
13571
13572        let intersection_range = Point::new(unfold_at.buffer_row.0, 0)
13573            ..Point::new(
13574                unfold_at.buffer_row.0,
13575                display_map.buffer_snapshot.line_len(unfold_at.buffer_row),
13576            );
13577
13578        let autoscroll = self
13579            .selections
13580            .all::<Point>(cx)
13581            .iter()
13582            .any(|selection| RangeExt::overlaps(&selection.range(), &intersection_range));
13583
13584        self.unfold_ranges(&[intersection_range], true, autoscroll, cx);
13585    }
13586
13587    pub fn unfold_all(
13588        &mut self,
13589        _: &actions::UnfoldAll,
13590        _window: &mut Window,
13591        cx: &mut Context<Self>,
13592    ) {
13593        if self.buffer.read(cx).is_singleton() {
13594            let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
13595            self.unfold_ranges(&[0..display_map.buffer_snapshot.len()], true, true, cx);
13596        } else {
13597            self.toggle_fold_multiple_buffers = cx.spawn(|editor, mut cx| async move {
13598                editor
13599                    .update(&mut cx, |editor, cx| {
13600                        for buffer_id in editor.buffer.read(cx).excerpt_buffer_ids() {
13601                            editor.unfold_buffer(buffer_id, cx);
13602                        }
13603                    })
13604                    .ok();
13605            });
13606        }
13607    }
13608
13609    pub fn fold_selected_ranges(
13610        &mut self,
13611        _: &FoldSelectedRanges,
13612        window: &mut Window,
13613        cx: &mut Context<Self>,
13614    ) {
13615        let selections = self.selections.all::<Point>(cx);
13616        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
13617        let line_mode = self.selections.line_mode;
13618        let ranges = selections
13619            .into_iter()
13620            .map(|s| {
13621                if line_mode {
13622                    let start = Point::new(s.start.row, 0);
13623                    let end = Point::new(
13624                        s.end.row,
13625                        display_map
13626                            .buffer_snapshot
13627                            .line_len(MultiBufferRow(s.end.row)),
13628                    );
13629                    Crease::simple(start..end, display_map.fold_placeholder.clone())
13630                } else {
13631                    Crease::simple(s.start..s.end, display_map.fold_placeholder.clone())
13632                }
13633            })
13634            .collect::<Vec<_>>();
13635        self.fold_creases(ranges, true, window, cx);
13636    }
13637
13638    pub fn fold_ranges<T: ToOffset + Clone>(
13639        &mut self,
13640        ranges: Vec<Range<T>>,
13641        auto_scroll: bool,
13642        window: &mut Window,
13643        cx: &mut Context<Self>,
13644    ) {
13645        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
13646        let ranges = ranges
13647            .into_iter()
13648            .map(|r| Crease::simple(r, display_map.fold_placeholder.clone()))
13649            .collect::<Vec<_>>();
13650        self.fold_creases(ranges, auto_scroll, window, cx);
13651    }
13652
13653    pub fn fold_creases<T: ToOffset + Clone>(
13654        &mut self,
13655        creases: Vec<Crease<T>>,
13656        auto_scroll: bool,
13657        window: &mut Window,
13658        cx: &mut Context<Self>,
13659    ) {
13660        if creases.is_empty() {
13661            return;
13662        }
13663
13664        let mut buffers_affected = HashSet::default();
13665        let multi_buffer = self.buffer().read(cx);
13666        for crease in &creases {
13667            if let Some((_, buffer, _)) =
13668                multi_buffer.excerpt_containing(crease.range().start.clone(), cx)
13669            {
13670                buffers_affected.insert(buffer.read(cx).remote_id());
13671            };
13672        }
13673
13674        self.display_map.update(cx, |map, cx| map.fold(creases, cx));
13675
13676        if auto_scroll {
13677            self.request_autoscroll(Autoscroll::fit(), cx);
13678        }
13679
13680        cx.notify();
13681
13682        if let Some(active_diagnostics) = self.active_diagnostics.take() {
13683            // Clear diagnostics block when folding a range that contains it.
13684            let snapshot = self.snapshot(window, cx);
13685            if snapshot.intersects_fold(active_diagnostics.primary_range.start) {
13686                drop(snapshot);
13687                self.active_diagnostics = Some(active_diagnostics);
13688                self.dismiss_diagnostics(cx);
13689            } else {
13690                self.active_diagnostics = Some(active_diagnostics);
13691            }
13692        }
13693
13694        self.scrollbar_marker_state.dirty = true;
13695    }
13696
13697    /// Removes any folds whose ranges intersect any of the given ranges.
13698    pub fn unfold_ranges<T: ToOffset + Clone>(
13699        &mut self,
13700        ranges: &[Range<T>],
13701        inclusive: bool,
13702        auto_scroll: bool,
13703        cx: &mut Context<Self>,
13704    ) {
13705        self.remove_folds_with(ranges, auto_scroll, cx, |map, cx| {
13706            map.unfold_intersecting(ranges.iter().cloned(), inclusive, cx)
13707        });
13708    }
13709
13710    pub fn fold_buffer(&mut self, buffer_id: BufferId, cx: &mut Context<Self>) {
13711        if self.buffer().read(cx).is_singleton() || self.is_buffer_folded(buffer_id, cx) {
13712            return;
13713        }
13714        let folded_excerpts = self.buffer().read(cx).excerpts_for_buffer(buffer_id, cx);
13715        self.display_map.update(cx, |display_map, cx| {
13716            display_map.fold_buffers([buffer_id], cx)
13717        });
13718        cx.emit(EditorEvent::BufferFoldToggled {
13719            ids: folded_excerpts.iter().map(|&(id, _)| id).collect(),
13720            folded: true,
13721        });
13722        cx.notify();
13723    }
13724
13725    pub fn unfold_buffer(&mut self, buffer_id: BufferId, cx: &mut Context<Self>) {
13726        if self.buffer().read(cx).is_singleton() || !self.is_buffer_folded(buffer_id, cx) {
13727            return;
13728        }
13729        let unfolded_excerpts = self.buffer().read(cx).excerpts_for_buffer(buffer_id, cx);
13730        self.display_map.update(cx, |display_map, cx| {
13731            display_map.unfold_buffers([buffer_id], cx);
13732        });
13733        cx.emit(EditorEvent::BufferFoldToggled {
13734            ids: unfolded_excerpts.iter().map(|&(id, _)| id).collect(),
13735            folded: false,
13736        });
13737        cx.notify();
13738    }
13739
13740    pub fn is_buffer_folded(&self, buffer: BufferId, cx: &App) -> bool {
13741        self.display_map.read(cx).is_buffer_folded(buffer)
13742    }
13743
13744    pub fn folded_buffers<'a>(&self, cx: &'a App) -> &'a HashSet<BufferId> {
13745        self.display_map.read(cx).folded_buffers()
13746    }
13747
13748    /// Removes any folds with the given ranges.
13749    pub fn remove_folds_with_type<T: ToOffset + Clone>(
13750        &mut self,
13751        ranges: &[Range<T>],
13752        type_id: TypeId,
13753        auto_scroll: bool,
13754        cx: &mut Context<Self>,
13755    ) {
13756        self.remove_folds_with(ranges, auto_scroll, cx, |map, cx| {
13757            map.remove_folds_with_type(ranges.iter().cloned(), type_id, cx)
13758        });
13759    }
13760
13761    fn remove_folds_with<T: ToOffset + Clone>(
13762        &mut self,
13763        ranges: &[Range<T>],
13764        auto_scroll: bool,
13765        cx: &mut Context<Self>,
13766        update: impl FnOnce(&mut DisplayMap, &mut Context<DisplayMap>),
13767    ) {
13768        if ranges.is_empty() {
13769            return;
13770        }
13771
13772        let mut buffers_affected = HashSet::default();
13773        let multi_buffer = self.buffer().read(cx);
13774        for range in ranges {
13775            if let Some((_, buffer, _)) = multi_buffer.excerpt_containing(range.start.clone(), cx) {
13776                buffers_affected.insert(buffer.read(cx).remote_id());
13777            };
13778        }
13779
13780        self.display_map.update(cx, update);
13781
13782        if auto_scroll {
13783            self.request_autoscroll(Autoscroll::fit(), cx);
13784        }
13785
13786        cx.notify();
13787        self.scrollbar_marker_state.dirty = true;
13788        self.active_indent_guides_state.dirty = true;
13789    }
13790
13791    pub fn default_fold_placeholder(&self, cx: &App) -> FoldPlaceholder {
13792        self.display_map.read(cx).fold_placeholder.clone()
13793    }
13794
13795    pub fn set_expand_all_diff_hunks(&mut self, cx: &mut App) {
13796        self.buffer.update(cx, |buffer, cx| {
13797            buffer.set_all_diff_hunks_expanded(cx);
13798        });
13799    }
13800
13801    pub fn expand_all_diff_hunks(
13802        &mut self,
13803        _: &ExpandAllDiffHunks,
13804        _window: &mut Window,
13805        cx: &mut Context<Self>,
13806    ) {
13807        self.buffer.update(cx, |buffer, cx| {
13808            buffer.expand_diff_hunks(vec![Anchor::min()..Anchor::max()], cx)
13809        });
13810    }
13811
13812    pub fn toggle_selected_diff_hunks(
13813        &mut self,
13814        _: &ToggleSelectedDiffHunks,
13815        _window: &mut Window,
13816        cx: &mut Context<Self>,
13817    ) {
13818        let ranges: Vec<_> = self.selections.disjoint.iter().map(|s| s.range()).collect();
13819        self.toggle_diff_hunks_in_ranges(ranges, cx);
13820    }
13821
13822    pub fn diff_hunks_in_ranges<'a>(
13823        &'a self,
13824        ranges: &'a [Range<Anchor>],
13825        buffer: &'a MultiBufferSnapshot,
13826    ) -> impl 'a + Iterator<Item = MultiBufferDiffHunk> {
13827        ranges.iter().flat_map(move |range| {
13828            let end_excerpt_id = range.end.excerpt_id;
13829            let range = range.to_point(buffer);
13830            let mut peek_end = range.end;
13831            if range.end.row < buffer.max_row().0 {
13832                peek_end = Point::new(range.end.row + 1, 0);
13833            }
13834            buffer
13835                .diff_hunks_in_range(range.start..peek_end)
13836                .filter(move |hunk| hunk.excerpt_id.cmp(&end_excerpt_id, buffer).is_le())
13837        })
13838    }
13839
13840    pub fn has_stageable_diff_hunks_in_ranges(
13841        &self,
13842        ranges: &[Range<Anchor>],
13843        snapshot: &MultiBufferSnapshot,
13844    ) -> bool {
13845        let mut hunks = self.diff_hunks_in_ranges(ranges, &snapshot);
13846        hunks.any(|hunk| hunk.status().has_secondary_hunk())
13847    }
13848
13849    pub fn toggle_staged_selected_diff_hunks(
13850        &mut self,
13851        _: &::git::ToggleStaged,
13852        _: &mut Window,
13853        cx: &mut Context<Self>,
13854    ) {
13855        let snapshot = self.buffer.read(cx).snapshot(cx);
13856        let ranges: Vec<_> = self.selections.disjoint.iter().map(|s| s.range()).collect();
13857        let stage = self.has_stageable_diff_hunks_in_ranges(&ranges, &snapshot);
13858        self.stage_or_unstage_diff_hunks(stage, ranges, cx);
13859    }
13860
13861    pub fn stage_and_next(
13862        &mut self,
13863        _: &::git::StageAndNext,
13864        window: &mut Window,
13865        cx: &mut Context<Self>,
13866    ) {
13867        self.do_stage_or_unstage_and_next(true, window, cx);
13868    }
13869
13870    pub fn unstage_and_next(
13871        &mut self,
13872        _: &::git::UnstageAndNext,
13873        window: &mut Window,
13874        cx: &mut Context<Self>,
13875    ) {
13876        self.do_stage_or_unstage_and_next(false, window, cx);
13877    }
13878
13879    pub fn stage_or_unstage_diff_hunks(
13880        &mut self,
13881        stage: bool,
13882        ranges: Vec<Range<Anchor>>,
13883        cx: &mut Context<Self>,
13884    ) {
13885        let task = self.save_buffers_for_ranges_if_needed(&ranges, cx);
13886        cx.spawn(|this, mut cx| async move {
13887            task.await?;
13888            this.update(&mut cx, |this, cx| {
13889                let snapshot = this.buffer.read(cx).snapshot(cx);
13890                let chunk_by = this
13891                    .diff_hunks_in_ranges(&ranges, &snapshot)
13892                    .chunk_by(|hunk| hunk.buffer_id);
13893                for (buffer_id, hunks) in &chunk_by {
13894                    this.do_stage_or_unstage(stage, buffer_id, hunks, cx);
13895                }
13896            })
13897        })
13898        .detach_and_log_err(cx);
13899    }
13900
13901    fn save_buffers_for_ranges_if_needed(
13902        &mut self,
13903        ranges: &[Range<Anchor>],
13904        cx: &mut Context<'_, Editor>,
13905    ) -> Task<Result<()>> {
13906        let multibuffer = self.buffer.read(cx);
13907        let snapshot = multibuffer.read(cx);
13908        let buffer_ids: HashSet<_> = ranges
13909            .iter()
13910            .flat_map(|range| snapshot.buffer_ids_for_range(range.clone()))
13911            .collect();
13912        drop(snapshot);
13913
13914        let mut buffers = HashSet::default();
13915        for buffer_id in buffer_ids {
13916            if let Some(buffer_entity) = multibuffer.buffer(buffer_id) {
13917                let buffer = buffer_entity.read(cx);
13918                if buffer.file().is_some_and(|file| file.disk_state().exists()) && buffer.is_dirty()
13919                {
13920                    buffers.insert(buffer_entity);
13921                }
13922            }
13923        }
13924
13925        if let Some(project) = &self.project {
13926            project.update(cx, |project, cx| project.save_buffers(buffers, cx))
13927        } else {
13928            Task::ready(Ok(()))
13929        }
13930    }
13931
13932    fn do_stage_or_unstage_and_next(
13933        &mut self,
13934        stage: bool,
13935        window: &mut Window,
13936        cx: &mut Context<Self>,
13937    ) {
13938        let ranges = self.selections.disjoint_anchor_ranges().collect::<Vec<_>>();
13939
13940        if ranges.iter().any(|range| range.start != range.end) {
13941            self.stage_or_unstage_diff_hunks(stage, ranges, cx);
13942            return;
13943        }
13944
13945        self.stage_or_unstage_diff_hunks(stage, ranges, cx);
13946        let snapshot = self.snapshot(window, cx);
13947        let position = self.selections.newest::<Point>(cx).head();
13948        let mut row = snapshot
13949            .buffer_snapshot
13950            .diff_hunks_in_range(position..snapshot.buffer_snapshot.max_point())
13951            .find(|hunk| hunk.row_range.start.0 > position.row)
13952            .map(|hunk| hunk.row_range.start);
13953
13954        let all_diff_hunks_expanded = self.buffer().read(cx).all_diff_hunks_expanded();
13955        // Outside of the project diff editor, wrap around to the beginning.
13956        if !all_diff_hunks_expanded {
13957            row = row.or_else(|| {
13958                snapshot
13959                    .buffer_snapshot
13960                    .diff_hunks_in_range(Point::zero()..position)
13961                    .find(|hunk| hunk.row_range.end.0 < position.row)
13962                    .map(|hunk| hunk.row_range.start)
13963            });
13964        }
13965
13966        if let Some(row) = row {
13967            let destination = Point::new(row.0, 0);
13968            let autoscroll = Autoscroll::center();
13969
13970            self.unfold_ranges(&[destination..destination], false, false, cx);
13971            self.change_selections(Some(autoscroll), window, cx, |s| {
13972                s.select_ranges([destination..destination]);
13973            });
13974        } else if all_diff_hunks_expanded {
13975            window.dispatch_action(::git::ExpandCommitEditor.boxed_clone(), cx);
13976        }
13977    }
13978
13979    fn do_stage_or_unstage(
13980        &self,
13981        stage: bool,
13982        buffer_id: BufferId,
13983        hunks: impl Iterator<Item = MultiBufferDiffHunk>,
13984        cx: &mut App,
13985    ) -> Option<()> {
13986        let project = self.project.as_ref()?;
13987        let buffer = project.read(cx).buffer_for_id(buffer_id, cx)?;
13988        let diff = self.buffer.read(cx).diff_for(buffer_id)?;
13989        let buffer_snapshot = buffer.read(cx).snapshot();
13990        let file_exists = buffer_snapshot
13991            .file()
13992            .is_some_and(|file| file.disk_state().exists());
13993        diff.update(cx, |diff, cx| {
13994            diff.stage_or_unstage_hunks(
13995                stage,
13996                &hunks
13997                    .map(|hunk| buffer_diff::DiffHunk {
13998                        buffer_range: hunk.buffer_range,
13999                        diff_base_byte_range: hunk.diff_base_byte_range,
14000                        secondary_status: hunk.secondary_status,
14001                        range: Point::zero()..Point::zero(), // unused
14002                    })
14003                    .collect::<Vec<_>>(),
14004                &buffer_snapshot,
14005                file_exists,
14006                cx,
14007            )
14008        });
14009        None
14010    }
14011
14012    pub fn expand_selected_diff_hunks(&mut self, cx: &mut Context<Self>) {
14013        let ranges: Vec<_> = self.selections.disjoint.iter().map(|s| s.range()).collect();
14014        self.buffer
14015            .update(cx, |buffer, cx| buffer.expand_diff_hunks(ranges, cx))
14016    }
14017
14018    pub fn clear_expanded_diff_hunks(&mut self, cx: &mut Context<Self>) -> bool {
14019        self.buffer.update(cx, |buffer, cx| {
14020            let ranges = vec![Anchor::min()..Anchor::max()];
14021            if !buffer.all_diff_hunks_expanded()
14022                && buffer.has_expanded_diff_hunks_in_ranges(&ranges, cx)
14023            {
14024                buffer.collapse_diff_hunks(ranges, cx);
14025                true
14026            } else {
14027                false
14028            }
14029        })
14030    }
14031
14032    fn toggle_diff_hunks_in_ranges(
14033        &mut self,
14034        ranges: Vec<Range<Anchor>>,
14035        cx: &mut Context<'_, Editor>,
14036    ) {
14037        self.buffer.update(cx, |buffer, cx| {
14038            let expand = !buffer.has_expanded_diff_hunks_in_ranges(&ranges, cx);
14039            buffer.expand_or_collapse_diff_hunks(ranges, expand, cx);
14040        })
14041    }
14042
14043    fn toggle_single_diff_hunk(&mut self, range: Range<Anchor>, cx: &mut Context<Self>) {
14044        self.buffer.update(cx, |buffer, cx| {
14045            let snapshot = buffer.snapshot(cx);
14046            let excerpt_id = range.end.excerpt_id;
14047            let point_range = range.to_point(&snapshot);
14048            let expand = !buffer.single_hunk_is_expanded(range, cx);
14049            buffer.expand_or_collapse_diff_hunks_inner([(point_range, excerpt_id)], expand, cx);
14050        })
14051    }
14052
14053    pub(crate) fn apply_all_diff_hunks(
14054        &mut self,
14055        _: &ApplyAllDiffHunks,
14056        window: &mut Window,
14057        cx: &mut Context<Self>,
14058    ) {
14059        let buffers = self.buffer.read(cx).all_buffers();
14060        for branch_buffer in buffers {
14061            branch_buffer.update(cx, |branch_buffer, cx| {
14062                branch_buffer.merge_into_base(Vec::new(), cx);
14063            });
14064        }
14065
14066        if let Some(project) = self.project.clone() {
14067            self.save(true, project, window, cx).detach_and_log_err(cx);
14068        }
14069    }
14070
14071    pub(crate) fn apply_selected_diff_hunks(
14072        &mut self,
14073        _: &ApplyDiffHunk,
14074        window: &mut Window,
14075        cx: &mut Context<Self>,
14076    ) {
14077        let snapshot = self.snapshot(window, cx);
14078        let hunks = snapshot.hunks_for_ranges(self.selections.ranges(cx));
14079        let mut ranges_by_buffer = HashMap::default();
14080        self.transact(window, cx, |editor, _window, cx| {
14081            for hunk in hunks {
14082                if let Some(buffer) = editor.buffer.read(cx).buffer(hunk.buffer_id) {
14083                    ranges_by_buffer
14084                        .entry(buffer.clone())
14085                        .or_insert_with(Vec::new)
14086                        .push(hunk.buffer_range.to_offset(buffer.read(cx)));
14087                }
14088            }
14089
14090            for (buffer, ranges) in ranges_by_buffer {
14091                buffer.update(cx, |buffer, cx| {
14092                    buffer.merge_into_base(ranges, cx);
14093                });
14094            }
14095        });
14096
14097        if let Some(project) = self.project.clone() {
14098            self.save(true, project, window, cx).detach_and_log_err(cx);
14099        }
14100    }
14101
14102    pub fn set_gutter_hovered(&mut self, hovered: bool, cx: &mut Context<Self>) {
14103        if hovered != self.gutter_hovered {
14104            self.gutter_hovered = hovered;
14105            cx.notify();
14106        }
14107    }
14108
14109    pub fn insert_blocks(
14110        &mut self,
14111        blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
14112        autoscroll: Option<Autoscroll>,
14113        cx: &mut Context<Self>,
14114    ) -> Vec<CustomBlockId> {
14115        let blocks = self
14116            .display_map
14117            .update(cx, |display_map, cx| display_map.insert_blocks(blocks, cx));
14118        if let Some(autoscroll) = autoscroll {
14119            self.request_autoscroll(autoscroll, cx);
14120        }
14121        cx.notify();
14122        blocks
14123    }
14124
14125    pub fn resize_blocks(
14126        &mut self,
14127        heights: HashMap<CustomBlockId, u32>,
14128        autoscroll: Option<Autoscroll>,
14129        cx: &mut Context<Self>,
14130    ) {
14131        self.display_map
14132            .update(cx, |display_map, cx| display_map.resize_blocks(heights, cx));
14133        if let Some(autoscroll) = autoscroll {
14134            self.request_autoscroll(autoscroll, cx);
14135        }
14136        cx.notify();
14137    }
14138
14139    pub fn replace_blocks(
14140        &mut self,
14141        renderers: HashMap<CustomBlockId, RenderBlock>,
14142        autoscroll: Option<Autoscroll>,
14143        cx: &mut Context<Self>,
14144    ) {
14145        self.display_map
14146            .update(cx, |display_map, _cx| display_map.replace_blocks(renderers));
14147        if let Some(autoscroll) = autoscroll {
14148            self.request_autoscroll(autoscroll, cx);
14149        }
14150        cx.notify();
14151    }
14152
14153    pub fn remove_blocks(
14154        &mut self,
14155        block_ids: HashSet<CustomBlockId>,
14156        autoscroll: Option<Autoscroll>,
14157        cx: &mut Context<Self>,
14158    ) {
14159        self.display_map.update(cx, |display_map, cx| {
14160            display_map.remove_blocks(block_ids, cx)
14161        });
14162        if let Some(autoscroll) = autoscroll {
14163            self.request_autoscroll(autoscroll, cx);
14164        }
14165        cx.notify();
14166    }
14167
14168    pub fn row_for_block(
14169        &self,
14170        block_id: CustomBlockId,
14171        cx: &mut Context<Self>,
14172    ) -> Option<DisplayRow> {
14173        self.display_map
14174            .update(cx, |map, cx| map.row_for_block(block_id, cx))
14175    }
14176
14177    pub(crate) fn set_focused_block(&mut self, focused_block: FocusedBlock) {
14178        self.focused_block = Some(focused_block);
14179    }
14180
14181    pub(crate) fn take_focused_block(&mut self) -> Option<FocusedBlock> {
14182        self.focused_block.take()
14183    }
14184
14185    pub fn insert_creases(
14186        &mut self,
14187        creases: impl IntoIterator<Item = Crease<Anchor>>,
14188        cx: &mut Context<Self>,
14189    ) -> Vec<CreaseId> {
14190        self.display_map
14191            .update(cx, |map, cx| map.insert_creases(creases, cx))
14192    }
14193
14194    pub fn remove_creases(
14195        &mut self,
14196        ids: impl IntoIterator<Item = CreaseId>,
14197        cx: &mut Context<Self>,
14198    ) {
14199        self.display_map
14200            .update(cx, |map, cx| map.remove_creases(ids, cx));
14201    }
14202
14203    pub fn longest_row(&self, cx: &mut App) -> DisplayRow {
14204        self.display_map
14205            .update(cx, |map, cx| map.snapshot(cx))
14206            .longest_row()
14207    }
14208
14209    pub fn max_point(&self, cx: &mut App) -> DisplayPoint {
14210        self.display_map
14211            .update(cx, |map, cx| map.snapshot(cx))
14212            .max_point()
14213    }
14214
14215    pub fn text(&self, cx: &App) -> String {
14216        self.buffer.read(cx).read(cx).text()
14217    }
14218
14219    pub fn is_empty(&self, cx: &App) -> bool {
14220        self.buffer.read(cx).read(cx).is_empty()
14221    }
14222
14223    pub fn text_option(&self, cx: &App) -> Option<String> {
14224        let text = self.text(cx);
14225        let text = text.trim();
14226
14227        if text.is_empty() {
14228            return None;
14229        }
14230
14231        Some(text.to_string())
14232    }
14233
14234    pub fn set_text(
14235        &mut self,
14236        text: impl Into<Arc<str>>,
14237        window: &mut Window,
14238        cx: &mut Context<Self>,
14239    ) {
14240        self.transact(window, cx, |this, _, cx| {
14241            this.buffer
14242                .read(cx)
14243                .as_singleton()
14244                .expect("you can only call set_text on editors for singleton buffers")
14245                .update(cx, |buffer, cx| buffer.set_text(text, cx));
14246        });
14247    }
14248
14249    pub fn display_text(&self, cx: &mut App) -> String {
14250        self.display_map
14251            .update(cx, |map, cx| map.snapshot(cx))
14252            .text()
14253    }
14254
14255    pub fn wrap_guides(&self, cx: &App) -> SmallVec<[(usize, bool); 2]> {
14256        let mut wrap_guides = smallvec::smallvec![];
14257
14258        if self.show_wrap_guides == Some(false) {
14259            return wrap_guides;
14260        }
14261
14262        let settings = self.buffer.read(cx).language_settings(cx);
14263        if settings.show_wrap_guides {
14264            match self.soft_wrap_mode(cx) {
14265                SoftWrap::Column(soft_wrap) => {
14266                    wrap_guides.push((soft_wrap as usize, true));
14267                }
14268                SoftWrap::Bounded(soft_wrap) => {
14269                    wrap_guides.push((soft_wrap as usize, true));
14270                }
14271                SoftWrap::GitDiff | SoftWrap::None | SoftWrap::EditorWidth => {}
14272            }
14273            wrap_guides.extend(settings.wrap_guides.iter().map(|guide| (*guide, false)))
14274        }
14275
14276        wrap_guides
14277    }
14278
14279    pub fn soft_wrap_mode(&self, cx: &App) -> SoftWrap {
14280        let settings = self.buffer.read(cx).language_settings(cx);
14281        let mode = self.soft_wrap_mode_override.unwrap_or(settings.soft_wrap);
14282        match mode {
14283            language_settings::SoftWrap::PreferLine | language_settings::SoftWrap::None => {
14284                SoftWrap::None
14285            }
14286            language_settings::SoftWrap::EditorWidth => SoftWrap::EditorWidth,
14287            language_settings::SoftWrap::PreferredLineLength => {
14288                SoftWrap::Column(settings.preferred_line_length)
14289            }
14290            language_settings::SoftWrap::Bounded => {
14291                SoftWrap::Bounded(settings.preferred_line_length)
14292            }
14293        }
14294    }
14295
14296    pub fn set_soft_wrap_mode(
14297        &mut self,
14298        mode: language_settings::SoftWrap,
14299
14300        cx: &mut Context<Self>,
14301    ) {
14302        self.soft_wrap_mode_override = Some(mode);
14303        cx.notify();
14304    }
14305
14306    pub fn set_hard_wrap(&mut self, hard_wrap: Option<usize>, cx: &mut Context<Self>) {
14307        self.hard_wrap = hard_wrap;
14308        cx.notify();
14309    }
14310
14311    pub fn set_text_style_refinement(&mut self, style: TextStyleRefinement) {
14312        self.text_style_refinement = Some(style);
14313    }
14314
14315    /// called by the Element so we know what style we were most recently rendered with.
14316    pub(crate) fn set_style(
14317        &mut self,
14318        style: EditorStyle,
14319        window: &mut Window,
14320        cx: &mut Context<Self>,
14321    ) {
14322        let rem_size = window.rem_size();
14323        self.display_map.update(cx, |map, cx| {
14324            map.set_font(
14325                style.text.font(),
14326                style.text.font_size.to_pixels(rem_size),
14327                cx,
14328            )
14329        });
14330        self.style = Some(style);
14331    }
14332
14333    pub fn style(&self) -> Option<&EditorStyle> {
14334        self.style.as_ref()
14335    }
14336
14337    // Called by the element. This method is not designed to be called outside of the editor
14338    // element's layout code because it does not notify when rewrapping is computed synchronously.
14339    pub(crate) fn set_wrap_width(&self, width: Option<Pixels>, cx: &mut App) -> bool {
14340        self.display_map
14341            .update(cx, |map, cx| map.set_wrap_width(width, cx))
14342    }
14343
14344    pub fn set_soft_wrap(&mut self) {
14345        self.soft_wrap_mode_override = Some(language_settings::SoftWrap::EditorWidth)
14346    }
14347
14348    pub fn toggle_soft_wrap(&mut self, _: &ToggleSoftWrap, _: &mut Window, cx: &mut Context<Self>) {
14349        if self.soft_wrap_mode_override.is_some() {
14350            self.soft_wrap_mode_override.take();
14351        } else {
14352            let soft_wrap = match self.soft_wrap_mode(cx) {
14353                SoftWrap::GitDiff => return,
14354                SoftWrap::None => language_settings::SoftWrap::EditorWidth,
14355                SoftWrap::EditorWidth | SoftWrap::Column(_) | SoftWrap::Bounded(_) => {
14356                    language_settings::SoftWrap::None
14357                }
14358            };
14359            self.soft_wrap_mode_override = Some(soft_wrap);
14360        }
14361        cx.notify();
14362    }
14363
14364    pub fn toggle_tab_bar(&mut self, _: &ToggleTabBar, _: &mut Window, cx: &mut Context<Self>) {
14365        let Some(workspace) = self.workspace() else {
14366            return;
14367        };
14368        let fs = workspace.read(cx).app_state().fs.clone();
14369        let current_show = TabBarSettings::get_global(cx).show;
14370        update_settings_file::<TabBarSettings>(fs, cx, move |setting, _| {
14371            setting.show = Some(!current_show);
14372        });
14373    }
14374
14375    pub fn toggle_indent_guides(
14376        &mut self,
14377        _: &ToggleIndentGuides,
14378        _: &mut Window,
14379        cx: &mut Context<Self>,
14380    ) {
14381        let currently_enabled = self.should_show_indent_guides().unwrap_or_else(|| {
14382            self.buffer
14383                .read(cx)
14384                .language_settings(cx)
14385                .indent_guides
14386                .enabled
14387        });
14388        self.show_indent_guides = Some(!currently_enabled);
14389        cx.notify();
14390    }
14391
14392    fn should_show_indent_guides(&self) -> Option<bool> {
14393        self.show_indent_guides
14394    }
14395
14396    pub fn toggle_line_numbers(
14397        &mut self,
14398        _: &ToggleLineNumbers,
14399        _: &mut Window,
14400        cx: &mut Context<Self>,
14401    ) {
14402        let mut editor_settings = EditorSettings::get_global(cx).clone();
14403        editor_settings.gutter.line_numbers = !editor_settings.gutter.line_numbers;
14404        EditorSettings::override_global(editor_settings, cx);
14405    }
14406
14407    pub fn line_numbers_enabled(&self, cx: &App) -> bool {
14408        if let Some(show_line_numbers) = self.show_line_numbers {
14409            return show_line_numbers;
14410        }
14411        EditorSettings::get_global(cx).gutter.line_numbers
14412    }
14413
14414    pub fn should_use_relative_line_numbers(&self, cx: &mut App) -> bool {
14415        self.use_relative_line_numbers
14416            .unwrap_or(EditorSettings::get_global(cx).relative_line_numbers)
14417    }
14418
14419    pub fn toggle_relative_line_numbers(
14420        &mut self,
14421        _: &ToggleRelativeLineNumbers,
14422        _: &mut Window,
14423        cx: &mut Context<Self>,
14424    ) {
14425        let is_relative = self.should_use_relative_line_numbers(cx);
14426        self.set_relative_line_number(Some(!is_relative), cx)
14427    }
14428
14429    pub fn set_relative_line_number(&mut self, is_relative: Option<bool>, cx: &mut Context<Self>) {
14430        self.use_relative_line_numbers = is_relative;
14431        cx.notify();
14432    }
14433
14434    pub fn set_show_gutter(&mut self, show_gutter: bool, cx: &mut Context<Self>) {
14435        self.show_gutter = show_gutter;
14436        cx.notify();
14437    }
14438
14439    pub fn set_show_scrollbars(&mut self, show_scrollbars: bool, cx: &mut Context<Self>) {
14440        self.show_scrollbars = show_scrollbars;
14441        cx.notify();
14442    }
14443
14444    pub fn set_show_line_numbers(&mut self, show_line_numbers: bool, cx: &mut Context<Self>) {
14445        self.show_line_numbers = Some(show_line_numbers);
14446        cx.notify();
14447    }
14448
14449    pub fn set_show_git_diff_gutter(&mut self, show_git_diff_gutter: bool, cx: &mut Context<Self>) {
14450        self.show_git_diff_gutter = Some(show_git_diff_gutter);
14451        cx.notify();
14452    }
14453
14454    pub fn set_show_code_actions(&mut self, show_code_actions: bool, cx: &mut Context<Self>) {
14455        self.show_code_actions = Some(show_code_actions);
14456        cx.notify();
14457    }
14458
14459    pub fn set_show_runnables(&mut self, show_runnables: bool, cx: &mut Context<Self>) {
14460        self.show_runnables = Some(show_runnables);
14461        cx.notify();
14462    }
14463
14464    pub fn set_masked(&mut self, masked: bool, cx: &mut Context<Self>) {
14465        if self.display_map.read(cx).masked != masked {
14466            self.display_map.update(cx, |map, _| map.masked = masked);
14467        }
14468        cx.notify()
14469    }
14470
14471    pub fn set_show_wrap_guides(&mut self, show_wrap_guides: bool, cx: &mut Context<Self>) {
14472        self.show_wrap_guides = Some(show_wrap_guides);
14473        cx.notify();
14474    }
14475
14476    pub fn set_show_indent_guides(&mut self, show_indent_guides: bool, cx: &mut Context<Self>) {
14477        self.show_indent_guides = Some(show_indent_guides);
14478        cx.notify();
14479    }
14480
14481    pub fn working_directory(&self, cx: &App) -> Option<PathBuf> {
14482        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
14483            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
14484                if let Some(dir) = file.abs_path(cx).parent() {
14485                    return Some(dir.to_owned());
14486                }
14487            }
14488
14489            if let Some(project_path) = buffer.read(cx).project_path(cx) {
14490                return Some(project_path.path.to_path_buf());
14491            }
14492        }
14493
14494        None
14495    }
14496
14497    fn target_file<'a>(&self, cx: &'a App) -> Option<&'a dyn language::LocalFile> {
14498        self.active_excerpt(cx)?
14499            .1
14500            .read(cx)
14501            .file()
14502            .and_then(|f| f.as_local())
14503    }
14504
14505    pub fn target_file_abs_path(&self, cx: &mut Context<Self>) -> Option<PathBuf> {
14506        self.active_excerpt(cx).and_then(|(_, buffer, _)| {
14507            let buffer = buffer.read(cx);
14508            if let Some(project_path) = buffer.project_path(cx) {
14509                let project = self.project.as_ref()?.read(cx);
14510                project.absolute_path(&project_path, cx)
14511            } else {
14512                buffer
14513                    .file()
14514                    .and_then(|file| file.as_local().map(|file| file.abs_path(cx)))
14515            }
14516        })
14517    }
14518
14519    fn target_file_path(&self, cx: &mut Context<Self>) -> Option<PathBuf> {
14520        self.active_excerpt(cx).and_then(|(_, buffer, _)| {
14521            let project_path = buffer.read(cx).project_path(cx)?;
14522            let project = self.project.as_ref()?.read(cx);
14523            let entry = project.entry_for_path(&project_path, cx)?;
14524            let path = entry.path.to_path_buf();
14525            Some(path)
14526        })
14527    }
14528
14529    pub fn reveal_in_finder(
14530        &mut self,
14531        _: &RevealInFileManager,
14532        _window: &mut Window,
14533        cx: &mut Context<Self>,
14534    ) {
14535        if let Some(target) = self.target_file(cx) {
14536            cx.reveal_path(&target.abs_path(cx));
14537        }
14538    }
14539
14540    pub fn copy_path(
14541        &mut self,
14542        _: &zed_actions::workspace::CopyPath,
14543        _window: &mut Window,
14544        cx: &mut Context<Self>,
14545    ) {
14546        if let Some(path) = self.target_file_abs_path(cx) {
14547            if let Some(path) = path.to_str() {
14548                cx.write_to_clipboard(ClipboardItem::new_string(path.to_string()));
14549            }
14550        }
14551    }
14552
14553    pub fn copy_relative_path(
14554        &mut self,
14555        _: &zed_actions::workspace::CopyRelativePath,
14556        _window: &mut Window,
14557        cx: &mut Context<Self>,
14558    ) {
14559        if let Some(path) = self.target_file_path(cx) {
14560            if let Some(path) = path.to_str() {
14561                cx.write_to_clipboard(ClipboardItem::new_string(path.to_string()));
14562            }
14563        }
14564    }
14565
14566    pub fn copy_file_name_without_extension(
14567        &mut self,
14568        _: &CopyFileNameWithoutExtension,
14569        _: &mut Window,
14570        cx: &mut Context<Self>,
14571    ) {
14572        if let Some(file) = self.target_file(cx) {
14573            if let Some(file_stem) = file.path().file_stem() {
14574                if let Some(name) = file_stem.to_str() {
14575                    cx.write_to_clipboard(ClipboardItem::new_string(name.to_string()));
14576                }
14577            }
14578        }
14579    }
14580
14581    pub fn copy_file_name(&mut self, _: &CopyFileName, _: &mut Window, cx: &mut Context<Self>) {
14582        if let Some(file) = self.target_file(cx) {
14583            if let Some(file_name) = file.path().file_name() {
14584                if let Some(name) = file_name.to_str() {
14585                    cx.write_to_clipboard(ClipboardItem::new_string(name.to_string()));
14586                }
14587            }
14588        }
14589    }
14590
14591    pub fn toggle_git_blame(
14592        &mut self,
14593        _: &::git::Blame,
14594        window: &mut Window,
14595        cx: &mut Context<Self>,
14596    ) {
14597        self.show_git_blame_gutter = !self.show_git_blame_gutter;
14598
14599        if self.show_git_blame_gutter && !self.has_blame_entries(cx) {
14600            self.start_git_blame(true, window, cx);
14601        }
14602
14603        cx.notify();
14604    }
14605
14606    pub fn toggle_git_blame_inline(
14607        &mut self,
14608        _: &ToggleGitBlameInline,
14609        window: &mut Window,
14610        cx: &mut Context<Self>,
14611    ) {
14612        self.toggle_git_blame_inline_internal(true, window, cx);
14613        cx.notify();
14614    }
14615
14616    pub fn git_blame_inline_enabled(&self) -> bool {
14617        self.git_blame_inline_enabled
14618    }
14619
14620    pub fn toggle_selection_menu(
14621        &mut self,
14622        _: &ToggleSelectionMenu,
14623        _: &mut Window,
14624        cx: &mut Context<Self>,
14625    ) {
14626        self.show_selection_menu = self
14627            .show_selection_menu
14628            .map(|show_selections_menu| !show_selections_menu)
14629            .or_else(|| Some(!EditorSettings::get_global(cx).toolbar.selections_menu));
14630
14631        cx.notify();
14632    }
14633
14634    pub fn selection_menu_enabled(&self, cx: &App) -> bool {
14635        self.show_selection_menu
14636            .unwrap_or_else(|| EditorSettings::get_global(cx).toolbar.selections_menu)
14637    }
14638
14639    fn start_git_blame(
14640        &mut self,
14641        user_triggered: bool,
14642        window: &mut Window,
14643        cx: &mut Context<Self>,
14644    ) {
14645        if let Some(project) = self.project.as_ref() {
14646            let Some(buffer) = self.buffer().read(cx).as_singleton() else {
14647                return;
14648            };
14649
14650            if buffer.read(cx).file().is_none() {
14651                return;
14652            }
14653
14654            let focused = self.focus_handle(cx).contains_focused(window, cx);
14655
14656            let project = project.clone();
14657            let blame = cx.new(|cx| GitBlame::new(buffer, project, user_triggered, focused, cx));
14658            self.blame_subscription =
14659                Some(cx.observe_in(&blame, window, |_, _, _, cx| cx.notify()));
14660            self.blame = Some(blame);
14661        }
14662    }
14663
14664    fn toggle_git_blame_inline_internal(
14665        &mut self,
14666        user_triggered: bool,
14667        window: &mut Window,
14668        cx: &mut Context<Self>,
14669    ) {
14670        if self.git_blame_inline_enabled {
14671            self.git_blame_inline_enabled = false;
14672            self.show_git_blame_inline = false;
14673            self.show_git_blame_inline_delay_task.take();
14674        } else {
14675            self.git_blame_inline_enabled = true;
14676            self.start_git_blame_inline(user_triggered, window, cx);
14677        }
14678
14679        cx.notify();
14680    }
14681
14682    fn start_git_blame_inline(
14683        &mut self,
14684        user_triggered: bool,
14685        window: &mut Window,
14686        cx: &mut Context<Self>,
14687    ) {
14688        self.start_git_blame(user_triggered, window, cx);
14689
14690        if ProjectSettings::get_global(cx)
14691            .git
14692            .inline_blame_delay()
14693            .is_some()
14694        {
14695            self.start_inline_blame_timer(window, cx);
14696        } else {
14697            self.show_git_blame_inline = true
14698        }
14699    }
14700
14701    pub fn blame(&self) -> Option<&Entity<GitBlame>> {
14702        self.blame.as_ref()
14703    }
14704
14705    pub fn show_git_blame_gutter(&self) -> bool {
14706        self.show_git_blame_gutter
14707    }
14708
14709    pub fn render_git_blame_gutter(&self, cx: &App) -> bool {
14710        self.show_git_blame_gutter && self.has_blame_entries(cx)
14711    }
14712
14713    pub fn render_git_blame_inline(&self, window: &Window, cx: &App) -> bool {
14714        self.show_git_blame_inline
14715            && (self.focus_handle.is_focused(window)
14716                || self
14717                    .git_blame_inline_tooltip
14718                    .as_ref()
14719                    .and_then(|t| t.upgrade())
14720                    .is_some())
14721            && !self.newest_selection_head_on_empty_line(cx)
14722            && self.has_blame_entries(cx)
14723    }
14724
14725    fn has_blame_entries(&self, cx: &App) -> bool {
14726        self.blame()
14727            .map_or(false, |blame| blame.read(cx).has_generated_entries())
14728    }
14729
14730    fn newest_selection_head_on_empty_line(&self, cx: &App) -> bool {
14731        let cursor_anchor = self.selections.newest_anchor().head();
14732
14733        let snapshot = self.buffer.read(cx).snapshot(cx);
14734        let buffer_row = MultiBufferRow(cursor_anchor.to_point(&snapshot).row);
14735
14736        snapshot.line_len(buffer_row) == 0
14737    }
14738
14739    fn get_permalink_to_line(&self, cx: &mut Context<Self>) -> Task<Result<url::Url>> {
14740        let buffer_and_selection = maybe!({
14741            let selection = self.selections.newest::<Point>(cx);
14742            let selection_range = selection.range();
14743
14744            let multi_buffer = self.buffer().read(cx);
14745            let multi_buffer_snapshot = multi_buffer.snapshot(cx);
14746            let buffer_ranges = multi_buffer_snapshot.range_to_buffer_ranges(selection_range);
14747
14748            let (buffer, range, _) = if selection.reversed {
14749                buffer_ranges.first()
14750            } else {
14751                buffer_ranges.last()
14752            }?;
14753
14754            let selection = text::ToPoint::to_point(&range.start, &buffer).row
14755                ..text::ToPoint::to_point(&range.end, &buffer).row;
14756            Some((
14757                multi_buffer.buffer(buffer.remote_id()).unwrap().clone(),
14758                selection,
14759            ))
14760        });
14761
14762        let Some((buffer, selection)) = buffer_and_selection else {
14763            return Task::ready(Err(anyhow!("failed to determine buffer and selection")));
14764        };
14765
14766        let Some(project) = self.project.as_ref() else {
14767            return Task::ready(Err(anyhow!("editor does not have project")));
14768        };
14769
14770        project.update(cx, |project, cx| {
14771            project.get_permalink_to_line(&buffer, selection, cx)
14772        })
14773    }
14774
14775    pub fn copy_permalink_to_line(
14776        &mut self,
14777        _: &CopyPermalinkToLine,
14778        window: &mut Window,
14779        cx: &mut Context<Self>,
14780    ) {
14781        let permalink_task = self.get_permalink_to_line(cx);
14782        let workspace = self.workspace();
14783
14784        cx.spawn_in(window, |_, mut cx| async move {
14785            match permalink_task.await {
14786                Ok(permalink) => {
14787                    cx.update(|_, cx| {
14788                        cx.write_to_clipboard(ClipboardItem::new_string(permalink.to_string()));
14789                    })
14790                    .ok();
14791                }
14792                Err(err) => {
14793                    let message = format!("Failed to copy permalink: {err}");
14794
14795                    Err::<(), anyhow::Error>(err).log_err();
14796
14797                    if let Some(workspace) = workspace {
14798                        workspace
14799                            .update_in(&mut cx, |workspace, _, cx| {
14800                                struct CopyPermalinkToLine;
14801
14802                                workspace.show_toast(
14803                                    Toast::new(
14804                                        NotificationId::unique::<CopyPermalinkToLine>(),
14805                                        message,
14806                                    ),
14807                                    cx,
14808                                )
14809                            })
14810                            .ok();
14811                    }
14812                }
14813            }
14814        })
14815        .detach();
14816    }
14817
14818    pub fn copy_file_location(
14819        &mut self,
14820        _: &CopyFileLocation,
14821        _: &mut Window,
14822        cx: &mut Context<Self>,
14823    ) {
14824        let selection = self.selections.newest::<Point>(cx).start.row + 1;
14825        if let Some(file) = self.target_file(cx) {
14826            if let Some(path) = file.path().to_str() {
14827                cx.write_to_clipboard(ClipboardItem::new_string(format!("{path}:{selection}")));
14828            }
14829        }
14830    }
14831
14832    pub fn open_permalink_to_line(
14833        &mut self,
14834        _: &OpenPermalinkToLine,
14835        window: &mut Window,
14836        cx: &mut Context<Self>,
14837    ) {
14838        let permalink_task = self.get_permalink_to_line(cx);
14839        let workspace = self.workspace();
14840
14841        cx.spawn_in(window, |_, mut cx| async move {
14842            match permalink_task.await {
14843                Ok(permalink) => {
14844                    cx.update(|_, cx| {
14845                        cx.open_url(permalink.as_ref());
14846                    })
14847                    .ok();
14848                }
14849                Err(err) => {
14850                    let message = format!("Failed to open permalink: {err}");
14851
14852                    Err::<(), anyhow::Error>(err).log_err();
14853
14854                    if let Some(workspace) = workspace {
14855                        workspace
14856                            .update(&mut cx, |workspace, cx| {
14857                                struct OpenPermalinkToLine;
14858
14859                                workspace.show_toast(
14860                                    Toast::new(
14861                                        NotificationId::unique::<OpenPermalinkToLine>(),
14862                                        message,
14863                                    ),
14864                                    cx,
14865                                )
14866                            })
14867                            .ok();
14868                    }
14869                }
14870            }
14871        })
14872        .detach();
14873    }
14874
14875    pub fn insert_uuid_v4(
14876        &mut self,
14877        _: &InsertUuidV4,
14878        window: &mut Window,
14879        cx: &mut Context<Self>,
14880    ) {
14881        self.insert_uuid(UuidVersion::V4, window, cx);
14882    }
14883
14884    pub fn insert_uuid_v7(
14885        &mut self,
14886        _: &InsertUuidV7,
14887        window: &mut Window,
14888        cx: &mut Context<Self>,
14889    ) {
14890        self.insert_uuid(UuidVersion::V7, window, cx);
14891    }
14892
14893    fn insert_uuid(&mut self, version: UuidVersion, window: &mut Window, cx: &mut Context<Self>) {
14894        self.transact(window, cx, |this, window, cx| {
14895            let edits = this
14896                .selections
14897                .all::<Point>(cx)
14898                .into_iter()
14899                .map(|selection| {
14900                    let uuid = match version {
14901                        UuidVersion::V4 => uuid::Uuid::new_v4(),
14902                        UuidVersion::V7 => uuid::Uuid::now_v7(),
14903                    };
14904
14905                    (selection.range(), uuid.to_string())
14906                });
14907            this.edit(edits, cx);
14908            this.refresh_inline_completion(true, false, window, cx);
14909        });
14910    }
14911
14912    pub fn open_selections_in_multibuffer(
14913        &mut self,
14914        _: &OpenSelectionsInMultibuffer,
14915        window: &mut Window,
14916        cx: &mut Context<Self>,
14917    ) {
14918        let multibuffer = self.buffer.read(cx);
14919
14920        let Some(buffer) = multibuffer.as_singleton() else {
14921            return;
14922        };
14923
14924        let Some(workspace) = self.workspace() else {
14925            return;
14926        };
14927
14928        let locations = self
14929            .selections
14930            .disjoint_anchors()
14931            .iter()
14932            .map(|range| Location {
14933                buffer: buffer.clone(),
14934                range: range.start.text_anchor..range.end.text_anchor,
14935            })
14936            .collect::<Vec<_>>();
14937
14938        let title = multibuffer.title(cx).to_string();
14939
14940        cx.spawn_in(window, |_, mut cx| async move {
14941            workspace.update_in(&mut cx, |workspace, window, cx| {
14942                Self::open_locations_in_multibuffer(
14943                    workspace,
14944                    locations,
14945                    format!("Selections for '{title}'"),
14946                    false,
14947                    MultibufferSelectionMode::All,
14948                    window,
14949                    cx,
14950                );
14951            })
14952        })
14953        .detach();
14954    }
14955
14956    /// Adds a row highlight for the given range. If a row has multiple highlights, the
14957    /// last highlight added will be used.
14958    ///
14959    /// If the range ends at the beginning of a line, then that line will not be highlighted.
14960    pub fn highlight_rows<T: 'static>(
14961        &mut self,
14962        range: Range<Anchor>,
14963        color: Hsla,
14964        should_autoscroll: bool,
14965        cx: &mut Context<Self>,
14966    ) {
14967        let snapshot = self.buffer().read(cx).snapshot(cx);
14968        let row_highlights = self.highlighted_rows.entry(TypeId::of::<T>()).or_default();
14969        let ix = row_highlights.binary_search_by(|highlight| {
14970            Ordering::Equal
14971                .then_with(|| highlight.range.start.cmp(&range.start, &snapshot))
14972                .then_with(|| highlight.range.end.cmp(&range.end, &snapshot))
14973        });
14974
14975        if let Err(mut ix) = ix {
14976            let index = post_inc(&mut self.highlight_order);
14977
14978            // If this range intersects with the preceding highlight, then merge it with
14979            // the preceding highlight. Otherwise insert a new highlight.
14980            let mut merged = false;
14981            if ix > 0 {
14982                let prev_highlight = &mut row_highlights[ix - 1];
14983                if prev_highlight
14984                    .range
14985                    .end
14986                    .cmp(&range.start, &snapshot)
14987                    .is_ge()
14988                {
14989                    ix -= 1;
14990                    if prev_highlight.range.end.cmp(&range.end, &snapshot).is_lt() {
14991                        prev_highlight.range.end = range.end;
14992                    }
14993                    merged = true;
14994                    prev_highlight.index = index;
14995                    prev_highlight.color = color;
14996                    prev_highlight.should_autoscroll = should_autoscroll;
14997                }
14998            }
14999
15000            if !merged {
15001                row_highlights.insert(
15002                    ix,
15003                    RowHighlight {
15004                        range: range.clone(),
15005                        index,
15006                        color,
15007                        should_autoscroll,
15008                    },
15009                );
15010            }
15011
15012            // If any of the following highlights intersect with this one, merge them.
15013            while let Some(next_highlight) = row_highlights.get(ix + 1) {
15014                let highlight = &row_highlights[ix];
15015                if next_highlight
15016                    .range
15017                    .start
15018                    .cmp(&highlight.range.end, &snapshot)
15019                    .is_le()
15020                {
15021                    if next_highlight
15022                        .range
15023                        .end
15024                        .cmp(&highlight.range.end, &snapshot)
15025                        .is_gt()
15026                    {
15027                        row_highlights[ix].range.end = next_highlight.range.end;
15028                    }
15029                    row_highlights.remove(ix + 1);
15030                } else {
15031                    break;
15032                }
15033            }
15034        }
15035    }
15036
15037    /// Remove any highlighted row ranges of the given type that intersect the
15038    /// given ranges.
15039    pub fn remove_highlighted_rows<T: 'static>(
15040        &mut self,
15041        ranges_to_remove: Vec<Range<Anchor>>,
15042        cx: &mut Context<Self>,
15043    ) {
15044        let snapshot = self.buffer().read(cx).snapshot(cx);
15045        let row_highlights = self.highlighted_rows.entry(TypeId::of::<T>()).or_default();
15046        let mut ranges_to_remove = ranges_to_remove.iter().peekable();
15047        row_highlights.retain(|highlight| {
15048            while let Some(range_to_remove) = ranges_to_remove.peek() {
15049                match range_to_remove.end.cmp(&highlight.range.start, &snapshot) {
15050                    Ordering::Less | Ordering::Equal => {
15051                        ranges_to_remove.next();
15052                    }
15053                    Ordering::Greater => {
15054                        match range_to_remove.start.cmp(&highlight.range.end, &snapshot) {
15055                            Ordering::Less | Ordering::Equal => {
15056                                return false;
15057                            }
15058                            Ordering::Greater => break,
15059                        }
15060                    }
15061                }
15062            }
15063
15064            true
15065        })
15066    }
15067
15068    /// Clear all anchor ranges for a certain highlight context type, so no corresponding rows will be highlighted.
15069    pub fn clear_row_highlights<T: 'static>(&mut self) {
15070        self.highlighted_rows.remove(&TypeId::of::<T>());
15071    }
15072
15073    /// For a highlight given context type, gets all anchor ranges that will be used for row highlighting.
15074    pub fn highlighted_rows<T: 'static>(&self) -> impl '_ + Iterator<Item = (Range<Anchor>, Hsla)> {
15075        self.highlighted_rows
15076            .get(&TypeId::of::<T>())
15077            .map_or(&[] as &[_], |vec| vec.as_slice())
15078            .iter()
15079            .map(|highlight| (highlight.range.clone(), highlight.color))
15080    }
15081
15082    /// Merges all anchor ranges for all context types ever set, picking the last highlight added in case of a row conflict.
15083    /// Returns a map of display rows that are highlighted and their corresponding highlight color.
15084    /// Allows to ignore certain kinds of highlights.
15085    pub fn highlighted_display_rows(
15086        &self,
15087        window: &mut Window,
15088        cx: &mut App,
15089    ) -> BTreeMap<DisplayRow, LineHighlight> {
15090        let snapshot = self.snapshot(window, cx);
15091        let mut used_highlight_orders = HashMap::default();
15092        self.highlighted_rows
15093            .iter()
15094            .flat_map(|(_, highlighted_rows)| highlighted_rows.iter())
15095            .fold(
15096                BTreeMap::<DisplayRow, LineHighlight>::new(),
15097                |mut unique_rows, highlight| {
15098                    let start = highlight.range.start.to_display_point(&snapshot);
15099                    let end = highlight.range.end.to_display_point(&snapshot);
15100                    let start_row = start.row().0;
15101                    let end_row = if highlight.range.end.text_anchor != text::Anchor::MAX
15102                        && end.column() == 0
15103                    {
15104                        end.row().0.saturating_sub(1)
15105                    } else {
15106                        end.row().0
15107                    };
15108                    for row in start_row..=end_row {
15109                        let used_index =
15110                            used_highlight_orders.entry(row).or_insert(highlight.index);
15111                        if highlight.index >= *used_index {
15112                            *used_index = highlight.index;
15113                            unique_rows.insert(DisplayRow(row), highlight.color.into());
15114                        }
15115                    }
15116                    unique_rows
15117                },
15118            )
15119    }
15120
15121    pub fn highlighted_display_row_for_autoscroll(
15122        &self,
15123        snapshot: &DisplaySnapshot,
15124    ) -> Option<DisplayRow> {
15125        self.highlighted_rows
15126            .values()
15127            .flat_map(|highlighted_rows| highlighted_rows.iter())
15128            .filter_map(|highlight| {
15129                if highlight.should_autoscroll {
15130                    Some(highlight.range.start.to_display_point(snapshot).row())
15131                } else {
15132                    None
15133                }
15134            })
15135            .min()
15136    }
15137
15138    pub fn set_search_within_ranges(&mut self, ranges: &[Range<Anchor>], cx: &mut Context<Self>) {
15139        self.highlight_background::<SearchWithinRange>(
15140            ranges,
15141            |colors| colors.editor_document_highlight_read_background,
15142            cx,
15143        )
15144    }
15145
15146    pub fn set_breadcrumb_header(&mut self, new_header: String) {
15147        self.breadcrumb_header = Some(new_header);
15148    }
15149
15150    pub fn clear_search_within_ranges(&mut self, cx: &mut Context<Self>) {
15151        self.clear_background_highlights::<SearchWithinRange>(cx);
15152    }
15153
15154    pub fn highlight_background<T: 'static>(
15155        &mut self,
15156        ranges: &[Range<Anchor>],
15157        color_fetcher: fn(&ThemeColors) -> Hsla,
15158        cx: &mut Context<Self>,
15159    ) {
15160        self.background_highlights
15161            .insert(TypeId::of::<T>(), (color_fetcher, Arc::from(ranges)));
15162        self.scrollbar_marker_state.dirty = true;
15163        cx.notify();
15164    }
15165
15166    pub fn clear_background_highlights<T: 'static>(
15167        &mut self,
15168        cx: &mut Context<Self>,
15169    ) -> Option<BackgroundHighlight> {
15170        let text_highlights = self.background_highlights.remove(&TypeId::of::<T>())?;
15171        if !text_highlights.1.is_empty() {
15172            self.scrollbar_marker_state.dirty = true;
15173            cx.notify();
15174        }
15175        Some(text_highlights)
15176    }
15177
15178    pub fn highlight_gutter<T: 'static>(
15179        &mut self,
15180        ranges: &[Range<Anchor>],
15181        color_fetcher: fn(&App) -> Hsla,
15182        cx: &mut Context<Self>,
15183    ) {
15184        self.gutter_highlights
15185            .insert(TypeId::of::<T>(), (color_fetcher, Arc::from(ranges)));
15186        cx.notify();
15187    }
15188
15189    pub fn clear_gutter_highlights<T: 'static>(
15190        &mut self,
15191        cx: &mut Context<Self>,
15192    ) -> Option<GutterHighlight> {
15193        cx.notify();
15194        self.gutter_highlights.remove(&TypeId::of::<T>())
15195    }
15196
15197    #[cfg(feature = "test-support")]
15198    pub fn all_text_background_highlights(
15199        &self,
15200        window: &mut Window,
15201        cx: &mut Context<Self>,
15202    ) -> Vec<(Range<DisplayPoint>, Hsla)> {
15203        let snapshot = self.snapshot(window, cx);
15204        let buffer = &snapshot.buffer_snapshot;
15205        let start = buffer.anchor_before(0);
15206        let end = buffer.anchor_after(buffer.len());
15207        let theme = cx.theme().colors();
15208        self.background_highlights_in_range(start..end, &snapshot, theme)
15209    }
15210
15211    #[cfg(feature = "test-support")]
15212    pub fn search_background_highlights(&mut self, cx: &mut Context<Self>) -> Vec<Range<Point>> {
15213        let snapshot = self.buffer().read(cx).snapshot(cx);
15214
15215        let highlights = self
15216            .background_highlights
15217            .get(&TypeId::of::<items::BufferSearchHighlights>());
15218
15219        if let Some((_color, ranges)) = highlights {
15220            ranges
15221                .iter()
15222                .map(|range| range.start.to_point(&snapshot)..range.end.to_point(&snapshot))
15223                .collect_vec()
15224        } else {
15225            vec![]
15226        }
15227    }
15228
15229    fn document_highlights_for_position<'a>(
15230        &'a self,
15231        position: Anchor,
15232        buffer: &'a MultiBufferSnapshot,
15233    ) -> impl 'a + Iterator<Item = &'a Range<Anchor>> {
15234        let read_highlights = self
15235            .background_highlights
15236            .get(&TypeId::of::<DocumentHighlightRead>())
15237            .map(|h| &h.1);
15238        let write_highlights = self
15239            .background_highlights
15240            .get(&TypeId::of::<DocumentHighlightWrite>())
15241            .map(|h| &h.1);
15242        let left_position = position.bias_left(buffer);
15243        let right_position = position.bias_right(buffer);
15244        read_highlights
15245            .into_iter()
15246            .chain(write_highlights)
15247            .flat_map(move |ranges| {
15248                let start_ix = match ranges.binary_search_by(|probe| {
15249                    let cmp = probe.end.cmp(&left_position, buffer);
15250                    if cmp.is_ge() {
15251                        Ordering::Greater
15252                    } else {
15253                        Ordering::Less
15254                    }
15255                }) {
15256                    Ok(i) | Err(i) => i,
15257                };
15258
15259                ranges[start_ix..]
15260                    .iter()
15261                    .take_while(move |range| range.start.cmp(&right_position, buffer).is_le())
15262            })
15263    }
15264
15265    pub fn has_background_highlights<T: 'static>(&self) -> bool {
15266        self.background_highlights
15267            .get(&TypeId::of::<T>())
15268            .map_or(false, |(_, highlights)| !highlights.is_empty())
15269    }
15270
15271    pub fn background_highlights_in_range(
15272        &self,
15273        search_range: Range<Anchor>,
15274        display_snapshot: &DisplaySnapshot,
15275        theme: &ThemeColors,
15276    ) -> Vec<(Range<DisplayPoint>, Hsla)> {
15277        let mut results = Vec::new();
15278        for (color_fetcher, ranges) in self.background_highlights.values() {
15279            let color = color_fetcher(theme);
15280            let start_ix = match ranges.binary_search_by(|probe| {
15281                let cmp = probe
15282                    .end
15283                    .cmp(&search_range.start, &display_snapshot.buffer_snapshot);
15284                if cmp.is_gt() {
15285                    Ordering::Greater
15286                } else {
15287                    Ordering::Less
15288                }
15289            }) {
15290                Ok(i) | Err(i) => i,
15291            };
15292            for range in &ranges[start_ix..] {
15293                if range
15294                    .start
15295                    .cmp(&search_range.end, &display_snapshot.buffer_snapshot)
15296                    .is_ge()
15297                {
15298                    break;
15299                }
15300
15301                let start = range.start.to_display_point(display_snapshot);
15302                let end = range.end.to_display_point(display_snapshot);
15303                results.push((start..end, color))
15304            }
15305        }
15306        results
15307    }
15308
15309    pub fn background_highlight_row_ranges<T: 'static>(
15310        &self,
15311        search_range: Range<Anchor>,
15312        display_snapshot: &DisplaySnapshot,
15313        count: usize,
15314    ) -> Vec<RangeInclusive<DisplayPoint>> {
15315        let mut results = Vec::new();
15316        let Some((_, ranges)) = self.background_highlights.get(&TypeId::of::<T>()) else {
15317            return vec![];
15318        };
15319
15320        let start_ix = match ranges.binary_search_by(|probe| {
15321            let cmp = probe
15322                .end
15323                .cmp(&search_range.start, &display_snapshot.buffer_snapshot);
15324            if cmp.is_gt() {
15325                Ordering::Greater
15326            } else {
15327                Ordering::Less
15328            }
15329        }) {
15330            Ok(i) | Err(i) => i,
15331        };
15332        let mut push_region = |start: Option<Point>, end: Option<Point>| {
15333            if let (Some(start_display), Some(end_display)) = (start, end) {
15334                results.push(
15335                    start_display.to_display_point(display_snapshot)
15336                        ..=end_display.to_display_point(display_snapshot),
15337                );
15338            }
15339        };
15340        let mut start_row: Option<Point> = None;
15341        let mut end_row: Option<Point> = None;
15342        if ranges.len() > count {
15343            return Vec::new();
15344        }
15345        for range in &ranges[start_ix..] {
15346            if range
15347                .start
15348                .cmp(&search_range.end, &display_snapshot.buffer_snapshot)
15349                .is_ge()
15350            {
15351                break;
15352            }
15353            let end = range.end.to_point(&display_snapshot.buffer_snapshot);
15354            if let Some(current_row) = &end_row {
15355                if end.row == current_row.row {
15356                    continue;
15357                }
15358            }
15359            let start = range.start.to_point(&display_snapshot.buffer_snapshot);
15360            if start_row.is_none() {
15361                assert_eq!(end_row, None);
15362                start_row = Some(start);
15363                end_row = Some(end);
15364                continue;
15365            }
15366            if let Some(current_end) = end_row.as_mut() {
15367                if start.row > current_end.row + 1 {
15368                    push_region(start_row, end_row);
15369                    start_row = Some(start);
15370                    end_row = Some(end);
15371                } else {
15372                    // Merge two hunks.
15373                    *current_end = end;
15374                }
15375            } else {
15376                unreachable!();
15377            }
15378        }
15379        // We might still have a hunk that was not rendered (if there was a search hit on the last line)
15380        push_region(start_row, end_row);
15381        results
15382    }
15383
15384    pub fn gutter_highlights_in_range(
15385        &self,
15386        search_range: Range<Anchor>,
15387        display_snapshot: &DisplaySnapshot,
15388        cx: &App,
15389    ) -> Vec<(Range<DisplayPoint>, Hsla)> {
15390        let mut results = Vec::new();
15391        for (color_fetcher, ranges) in self.gutter_highlights.values() {
15392            let color = color_fetcher(cx);
15393            let start_ix = match ranges.binary_search_by(|probe| {
15394                let cmp = probe
15395                    .end
15396                    .cmp(&search_range.start, &display_snapshot.buffer_snapshot);
15397                if cmp.is_gt() {
15398                    Ordering::Greater
15399                } else {
15400                    Ordering::Less
15401                }
15402            }) {
15403                Ok(i) | Err(i) => i,
15404            };
15405            for range in &ranges[start_ix..] {
15406                if range
15407                    .start
15408                    .cmp(&search_range.end, &display_snapshot.buffer_snapshot)
15409                    .is_ge()
15410                {
15411                    break;
15412                }
15413
15414                let start = range.start.to_display_point(display_snapshot);
15415                let end = range.end.to_display_point(display_snapshot);
15416                results.push((start..end, color))
15417            }
15418        }
15419        results
15420    }
15421
15422    /// Get the text ranges corresponding to the redaction query
15423    pub fn redacted_ranges(
15424        &self,
15425        search_range: Range<Anchor>,
15426        display_snapshot: &DisplaySnapshot,
15427        cx: &App,
15428    ) -> Vec<Range<DisplayPoint>> {
15429        display_snapshot
15430            .buffer_snapshot
15431            .redacted_ranges(search_range, |file| {
15432                if let Some(file) = file {
15433                    file.is_private()
15434                        && EditorSettings::get(
15435                            Some(SettingsLocation {
15436                                worktree_id: file.worktree_id(cx),
15437                                path: file.path().as_ref(),
15438                            }),
15439                            cx,
15440                        )
15441                        .redact_private_values
15442                } else {
15443                    false
15444                }
15445            })
15446            .map(|range| {
15447                range.start.to_display_point(display_snapshot)
15448                    ..range.end.to_display_point(display_snapshot)
15449            })
15450            .collect()
15451    }
15452
15453    pub fn highlight_text<T: 'static>(
15454        &mut self,
15455        ranges: Vec<Range<Anchor>>,
15456        style: HighlightStyle,
15457        cx: &mut Context<Self>,
15458    ) {
15459        self.display_map.update(cx, |map, _| {
15460            map.highlight_text(TypeId::of::<T>(), ranges, style)
15461        });
15462        cx.notify();
15463    }
15464
15465    pub(crate) fn highlight_inlays<T: 'static>(
15466        &mut self,
15467        highlights: Vec<InlayHighlight>,
15468        style: HighlightStyle,
15469        cx: &mut Context<Self>,
15470    ) {
15471        self.display_map.update(cx, |map, _| {
15472            map.highlight_inlays(TypeId::of::<T>(), highlights, style)
15473        });
15474        cx.notify();
15475    }
15476
15477    pub fn text_highlights<'a, T: 'static>(
15478        &'a self,
15479        cx: &'a App,
15480    ) -> Option<(HighlightStyle, &'a [Range<Anchor>])> {
15481        self.display_map.read(cx).text_highlights(TypeId::of::<T>())
15482    }
15483
15484    pub fn clear_highlights<T: 'static>(&mut self, cx: &mut Context<Self>) {
15485        let cleared = self
15486            .display_map
15487            .update(cx, |map, _| map.clear_highlights(TypeId::of::<T>()));
15488        if cleared {
15489            cx.notify();
15490        }
15491    }
15492
15493    pub fn show_local_cursors(&self, window: &mut Window, cx: &mut App) -> bool {
15494        (self.read_only(cx) || self.blink_manager.read(cx).visible())
15495            && self.focus_handle.is_focused(window)
15496    }
15497
15498    pub fn set_show_cursor_when_unfocused(&mut self, is_enabled: bool, cx: &mut Context<Self>) {
15499        self.show_cursor_when_unfocused = is_enabled;
15500        cx.notify();
15501    }
15502
15503    fn on_buffer_changed(&mut self, _: Entity<MultiBuffer>, cx: &mut Context<Self>) {
15504        cx.notify();
15505    }
15506
15507    fn on_buffer_event(
15508        &mut self,
15509        multibuffer: &Entity<MultiBuffer>,
15510        event: &multi_buffer::Event,
15511        window: &mut Window,
15512        cx: &mut Context<Self>,
15513    ) {
15514        match event {
15515            multi_buffer::Event::Edited {
15516                singleton_buffer_edited,
15517                edited_buffer: buffer_edited,
15518            } => {
15519                self.scrollbar_marker_state.dirty = true;
15520                self.active_indent_guides_state.dirty = true;
15521                self.refresh_active_diagnostics(cx);
15522                self.refresh_code_actions(window, cx);
15523                if self.has_active_inline_completion() {
15524                    self.update_visible_inline_completion(window, cx);
15525                }
15526                if let Some(buffer) = buffer_edited {
15527                    let buffer_id = buffer.read(cx).remote_id();
15528                    if !self.registered_buffers.contains_key(&buffer_id) {
15529                        if let Some(project) = self.project.as_ref() {
15530                            project.update(cx, |project, cx| {
15531                                self.registered_buffers.insert(
15532                                    buffer_id,
15533                                    project.register_buffer_with_language_servers(&buffer, cx),
15534                                );
15535                            })
15536                        }
15537                    }
15538                }
15539                cx.emit(EditorEvent::BufferEdited);
15540                cx.emit(SearchEvent::MatchesInvalidated);
15541                if *singleton_buffer_edited {
15542                    if let Some(project) = &self.project {
15543                        #[allow(clippy::mutable_key_type)]
15544                        let languages_affected = multibuffer.update(cx, |multibuffer, cx| {
15545                            multibuffer
15546                                .all_buffers()
15547                                .into_iter()
15548                                .filter_map(|buffer| {
15549                                    buffer.update(cx, |buffer, cx| {
15550                                        let language = buffer.language()?;
15551                                        let should_discard = project.update(cx, |project, cx| {
15552                                            project.is_local()
15553                                                && !project.has_language_servers_for(buffer, cx)
15554                                        });
15555                                        should_discard.not().then_some(language.clone())
15556                                    })
15557                                })
15558                                .collect::<HashSet<_>>()
15559                        });
15560                        if !languages_affected.is_empty() {
15561                            self.refresh_inlay_hints(
15562                                InlayHintRefreshReason::BufferEdited(languages_affected),
15563                                cx,
15564                            );
15565                        }
15566                    }
15567                }
15568
15569                let Some(project) = &self.project else { return };
15570                let (telemetry, is_via_ssh) = {
15571                    let project = project.read(cx);
15572                    let telemetry = project.client().telemetry().clone();
15573                    let is_via_ssh = project.is_via_ssh();
15574                    (telemetry, is_via_ssh)
15575                };
15576                refresh_linked_ranges(self, window, cx);
15577                telemetry.log_edit_event("editor", is_via_ssh);
15578            }
15579            multi_buffer::Event::ExcerptsAdded {
15580                buffer,
15581                predecessor,
15582                excerpts,
15583            } => {
15584                self.tasks_update_task = Some(self.refresh_runnables(window, cx));
15585                let buffer_id = buffer.read(cx).remote_id();
15586                if self.buffer.read(cx).diff_for(buffer_id).is_none() {
15587                    if let Some(project) = &self.project {
15588                        get_uncommitted_diff_for_buffer(
15589                            project,
15590                            [buffer.clone()],
15591                            self.buffer.clone(),
15592                            cx,
15593                        )
15594                        .detach();
15595                    }
15596                }
15597                cx.emit(EditorEvent::ExcerptsAdded {
15598                    buffer: buffer.clone(),
15599                    predecessor: *predecessor,
15600                    excerpts: excerpts.clone(),
15601                });
15602                self.refresh_inlay_hints(InlayHintRefreshReason::NewLinesShown, cx);
15603            }
15604            multi_buffer::Event::ExcerptsRemoved { ids } => {
15605                self.refresh_inlay_hints(InlayHintRefreshReason::ExcerptsRemoved(ids.clone()), cx);
15606                let buffer = self.buffer.read(cx);
15607                self.registered_buffers
15608                    .retain(|buffer_id, _| buffer.buffer(*buffer_id).is_some());
15609                jsx_tag_auto_close::refresh_enabled_in_any_buffer(self, multibuffer, cx);
15610                cx.emit(EditorEvent::ExcerptsRemoved { ids: ids.clone() })
15611            }
15612            multi_buffer::Event::ExcerptsEdited {
15613                excerpt_ids,
15614                buffer_ids,
15615            } => {
15616                self.display_map.update(cx, |map, cx| {
15617                    map.unfold_buffers(buffer_ids.iter().copied(), cx)
15618                });
15619                cx.emit(EditorEvent::ExcerptsEdited {
15620                    ids: excerpt_ids.clone(),
15621                })
15622            }
15623            multi_buffer::Event::ExcerptsExpanded { ids } => {
15624                self.refresh_inlay_hints(InlayHintRefreshReason::NewLinesShown, cx);
15625                cx.emit(EditorEvent::ExcerptsExpanded { ids: ids.clone() })
15626            }
15627            multi_buffer::Event::Reparsed(buffer_id) => {
15628                self.tasks_update_task = Some(self.refresh_runnables(window, cx));
15629                jsx_tag_auto_close::refresh_enabled_in_any_buffer(self, multibuffer, cx);
15630
15631                cx.emit(EditorEvent::Reparsed(*buffer_id));
15632            }
15633            multi_buffer::Event::DiffHunksToggled => {
15634                self.tasks_update_task = Some(self.refresh_runnables(window, cx));
15635            }
15636            multi_buffer::Event::LanguageChanged(buffer_id) => {
15637                linked_editing_ranges::refresh_linked_ranges(self, window, cx);
15638                jsx_tag_auto_close::refresh_enabled_in_any_buffer(self, multibuffer, cx);
15639                cx.emit(EditorEvent::Reparsed(*buffer_id));
15640                cx.notify();
15641            }
15642            multi_buffer::Event::DirtyChanged => cx.emit(EditorEvent::DirtyChanged),
15643            multi_buffer::Event::Saved => cx.emit(EditorEvent::Saved),
15644            multi_buffer::Event::FileHandleChanged
15645            | multi_buffer::Event::Reloaded
15646            | multi_buffer::Event::BufferDiffChanged => cx.emit(EditorEvent::TitleChanged),
15647            multi_buffer::Event::Closed => cx.emit(EditorEvent::Closed),
15648            multi_buffer::Event::DiagnosticsUpdated => {
15649                self.refresh_active_diagnostics(cx);
15650                self.refresh_inline_diagnostics(true, window, cx);
15651                self.scrollbar_marker_state.dirty = true;
15652                cx.notify();
15653            }
15654            _ => {}
15655        };
15656    }
15657
15658    fn on_display_map_changed(
15659        &mut self,
15660        _: Entity<DisplayMap>,
15661        _: &mut Window,
15662        cx: &mut Context<Self>,
15663    ) {
15664        cx.notify();
15665    }
15666
15667    fn settings_changed(&mut self, window: &mut Window, cx: &mut Context<Self>) {
15668        self.tasks_update_task = Some(self.refresh_runnables(window, cx));
15669        self.update_edit_prediction_settings(cx);
15670        self.refresh_inline_completion(true, false, window, cx);
15671        self.refresh_inlay_hints(
15672            InlayHintRefreshReason::SettingsChange(inlay_hint_settings(
15673                self.selections.newest_anchor().head(),
15674                &self.buffer.read(cx).snapshot(cx),
15675                cx,
15676            )),
15677            cx,
15678        );
15679
15680        let old_cursor_shape = self.cursor_shape;
15681
15682        {
15683            let editor_settings = EditorSettings::get_global(cx);
15684            self.scroll_manager.vertical_scroll_margin = editor_settings.vertical_scroll_margin;
15685            self.show_breadcrumbs = editor_settings.toolbar.breadcrumbs;
15686            self.cursor_shape = editor_settings.cursor_shape.unwrap_or_default();
15687        }
15688
15689        if old_cursor_shape != self.cursor_shape {
15690            cx.emit(EditorEvent::CursorShapeChanged);
15691        }
15692
15693        let project_settings = ProjectSettings::get_global(cx);
15694        self.serialize_dirty_buffers = project_settings.session.restore_unsaved_buffers;
15695
15696        if self.mode == EditorMode::Full {
15697            let show_inline_diagnostics = project_settings.diagnostics.inline.enabled;
15698            let inline_blame_enabled = project_settings.git.inline_blame_enabled();
15699            if self.show_inline_diagnostics != show_inline_diagnostics {
15700                self.show_inline_diagnostics = show_inline_diagnostics;
15701                self.refresh_inline_diagnostics(false, window, cx);
15702            }
15703
15704            if self.git_blame_inline_enabled != inline_blame_enabled {
15705                self.toggle_git_blame_inline_internal(false, window, cx);
15706            }
15707        }
15708
15709        cx.notify();
15710    }
15711
15712    pub fn set_searchable(&mut self, searchable: bool) {
15713        self.searchable = searchable;
15714    }
15715
15716    pub fn searchable(&self) -> bool {
15717        self.searchable
15718    }
15719
15720    fn open_proposed_changes_editor(
15721        &mut self,
15722        _: &OpenProposedChangesEditor,
15723        window: &mut Window,
15724        cx: &mut Context<Self>,
15725    ) {
15726        let Some(workspace) = self.workspace() else {
15727            cx.propagate();
15728            return;
15729        };
15730
15731        let selections = self.selections.all::<usize>(cx);
15732        let multi_buffer = self.buffer.read(cx);
15733        let multi_buffer_snapshot = multi_buffer.snapshot(cx);
15734        let mut new_selections_by_buffer = HashMap::default();
15735        for selection in selections {
15736            for (buffer, range, _) in
15737                multi_buffer_snapshot.range_to_buffer_ranges(selection.start..selection.end)
15738            {
15739                let mut range = range.to_point(buffer);
15740                range.start.column = 0;
15741                range.end.column = buffer.line_len(range.end.row);
15742                new_selections_by_buffer
15743                    .entry(multi_buffer.buffer(buffer.remote_id()).unwrap())
15744                    .or_insert(Vec::new())
15745                    .push(range)
15746            }
15747        }
15748
15749        let proposed_changes_buffers = new_selections_by_buffer
15750            .into_iter()
15751            .map(|(buffer, ranges)| ProposedChangeLocation { buffer, ranges })
15752            .collect::<Vec<_>>();
15753        let proposed_changes_editor = cx.new(|cx| {
15754            ProposedChangesEditor::new(
15755                "Proposed changes",
15756                proposed_changes_buffers,
15757                self.project.clone(),
15758                window,
15759                cx,
15760            )
15761        });
15762
15763        window.defer(cx, move |window, cx| {
15764            workspace.update(cx, |workspace, cx| {
15765                workspace.active_pane().update(cx, |pane, cx| {
15766                    pane.add_item(
15767                        Box::new(proposed_changes_editor),
15768                        true,
15769                        true,
15770                        None,
15771                        window,
15772                        cx,
15773                    );
15774                });
15775            });
15776        });
15777    }
15778
15779    pub fn open_excerpts_in_split(
15780        &mut self,
15781        _: &OpenExcerptsSplit,
15782        window: &mut Window,
15783        cx: &mut Context<Self>,
15784    ) {
15785        self.open_excerpts_common(None, true, window, cx)
15786    }
15787
15788    pub fn open_excerpts(&mut self, _: &OpenExcerpts, window: &mut Window, cx: &mut Context<Self>) {
15789        self.open_excerpts_common(None, false, window, cx)
15790    }
15791
15792    fn open_excerpts_common(
15793        &mut self,
15794        jump_data: Option<JumpData>,
15795        split: bool,
15796        window: &mut Window,
15797        cx: &mut Context<Self>,
15798    ) {
15799        let Some(workspace) = self.workspace() else {
15800            cx.propagate();
15801            return;
15802        };
15803
15804        if self.buffer.read(cx).is_singleton() {
15805            cx.propagate();
15806            return;
15807        }
15808
15809        let mut new_selections_by_buffer = HashMap::default();
15810        match &jump_data {
15811            Some(JumpData::MultiBufferPoint {
15812                excerpt_id,
15813                position,
15814                anchor,
15815                line_offset_from_top,
15816            }) => {
15817                let multi_buffer_snapshot = self.buffer.read(cx).snapshot(cx);
15818                if let Some(buffer) = multi_buffer_snapshot
15819                    .buffer_id_for_excerpt(*excerpt_id)
15820                    .and_then(|buffer_id| self.buffer.read(cx).buffer(buffer_id))
15821                {
15822                    let buffer_snapshot = buffer.read(cx).snapshot();
15823                    let jump_to_point = if buffer_snapshot.can_resolve(anchor) {
15824                        language::ToPoint::to_point(anchor, &buffer_snapshot)
15825                    } else {
15826                        buffer_snapshot.clip_point(*position, Bias::Left)
15827                    };
15828                    let jump_to_offset = buffer_snapshot.point_to_offset(jump_to_point);
15829                    new_selections_by_buffer.insert(
15830                        buffer,
15831                        (
15832                            vec![jump_to_offset..jump_to_offset],
15833                            Some(*line_offset_from_top),
15834                        ),
15835                    );
15836                }
15837            }
15838            Some(JumpData::MultiBufferRow {
15839                row,
15840                line_offset_from_top,
15841            }) => {
15842                let point = MultiBufferPoint::new(row.0, 0);
15843                if let Some((buffer, buffer_point, _)) =
15844                    self.buffer.read(cx).point_to_buffer_point(point, cx)
15845                {
15846                    let buffer_offset = buffer.read(cx).point_to_offset(buffer_point);
15847                    new_selections_by_buffer
15848                        .entry(buffer)
15849                        .or_insert((Vec::new(), Some(*line_offset_from_top)))
15850                        .0
15851                        .push(buffer_offset..buffer_offset)
15852                }
15853            }
15854            None => {
15855                let selections = self.selections.all::<usize>(cx);
15856                let multi_buffer = self.buffer.read(cx);
15857                for selection in selections {
15858                    for (snapshot, range, _, anchor) in multi_buffer
15859                        .snapshot(cx)
15860                        .range_to_buffer_ranges_with_deleted_hunks(selection.range())
15861                    {
15862                        if let Some(anchor) = anchor {
15863                            // selection is in a deleted hunk
15864                            let Some(buffer_id) = anchor.buffer_id else {
15865                                continue;
15866                            };
15867                            let Some(buffer_handle) = multi_buffer.buffer(buffer_id) else {
15868                                continue;
15869                            };
15870                            let offset = text::ToOffset::to_offset(
15871                                &anchor.text_anchor,
15872                                &buffer_handle.read(cx).snapshot(),
15873                            );
15874                            let range = offset..offset;
15875                            new_selections_by_buffer
15876                                .entry(buffer_handle)
15877                                .or_insert((Vec::new(), None))
15878                                .0
15879                                .push(range)
15880                        } else {
15881                            let Some(buffer_handle) = multi_buffer.buffer(snapshot.remote_id())
15882                            else {
15883                                continue;
15884                            };
15885                            new_selections_by_buffer
15886                                .entry(buffer_handle)
15887                                .or_insert((Vec::new(), None))
15888                                .0
15889                                .push(range)
15890                        }
15891                    }
15892                }
15893            }
15894        }
15895
15896        if new_selections_by_buffer.is_empty() {
15897            return;
15898        }
15899
15900        // We defer the pane interaction because we ourselves are a workspace item
15901        // and activating a new item causes the pane to call a method on us reentrantly,
15902        // which panics if we're on the stack.
15903        window.defer(cx, move |window, cx| {
15904            workspace.update(cx, |workspace, cx| {
15905                let pane = if split {
15906                    workspace.adjacent_pane(window, cx)
15907                } else {
15908                    workspace.active_pane().clone()
15909                };
15910
15911                for (buffer, (ranges, scroll_offset)) in new_selections_by_buffer {
15912                    let editor = buffer
15913                        .read(cx)
15914                        .file()
15915                        .is_none()
15916                        .then(|| {
15917                            // Handle file-less buffers separately: those are not really the project items, so won't have a project path or entity id,
15918                            // so `workspace.open_project_item` will never find them, always opening a new editor.
15919                            // Instead, we try to activate the existing editor in the pane first.
15920                            let (editor, pane_item_index) =
15921                                pane.read(cx).items().enumerate().find_map(|(i, item)| {
15922                                    let editor = item.downcast::<Editor>()?;
15923                                    let singleton_buffer =
15924                                        editor.read(cx).buffer().read(cx).as_singleton()?;
15925                                    if singleton_buffer == buffer {
15926                                        Some((editor, i))
15927                                    } else {
15928                                        None
15929                                    }
15930                                })?;
15931                            pane.update(cx, |pane, cx| {
15932                                pane.activate_item(pane_item_index, true, true, window, cx)
15933                            });
15934                            Some(editor)
15935                        })
15936                        .flatten()
15937                        .unwrap_or_else(|| {
15938                            workspace.open_project_item::<Self>(
15939                                pane.clone(),
15940                                buffer,
15941                                true,
15942                                true,
15943                                window,
15944                                cx,
15945                            )
15946                        });
15947
15948                    editor.update(cx, |editor, cx| {
15949                        let autoscroll = match scroll_offset {
15950                            Some(scroll_offset) => Autoscroll::top_relative(scroll_offset as usize),
15951                            None => Autoscroll::newest(),
15952                        };
15953                        let nav_history = editor.nav_history.take();
15954                        editor.change_selections(Some(autoscroll), window, cx, |s| {
15955                            s.select_ranges(ranges);
15956                        });
15957                        editor.nav_history = nav_history;
15958                    });
15959                }
15960            })
15961        });
15962    }
15963
15964    fn marked_text_ranges(&self, cx: &App) -> Option<Vec<Range<OffsetUtf16>>> {
15965        let snapshot = self.buffer.read(cx).read(cx);
15966        let (_, ranges) = self.text_highlights::<InputComposition>(cx)?;
15967        Some(
15968            ranges
15969                .iter()
15970                .map(move |range| {
15971                    range.start.to_offset_utf16(&snapshot)..range.end.to_offset_utf16(&snapshot)
15972                })
15973                .collect(),
15974        )
15975    }
15976
15977    fn selection_replacement_ranges(
15978        &self,
15979        range: Range<OffsetUtf16>,
15980        cx: &mut App,
15981    ) -> Vec<Range<OffsetUtf16>> {
15982        let selections = self.selections.all::<OffsetUtf16>(cx);
15983        let newest_selection = selections
15984            .iter()
15985            .max_by_key(|selection| selection.id)
15986            .unwrap();
15987        let start_delta = range.start.0 as isize - newest_selection.start.0 as isize;
15988        let end_delta = range.end.0 as isize - newest_selection.end.0 as isize;
15989        let snapshot = self.buffer.read(cx).read(cx);
15990        selections
15991            .into_iter()
15992            .map(|mut selection| {
15993                selection.start.0 =
15994                    (selection.start.0 as isize).saturating_add(start_delta) as usize;
15995                selection.end.0 = (selection.end.0 as isize).saturating_add(end_delta) as usize;
15996                snapshot.clip_offset_utf16(selection.start, Bias::Left)
15997                    ..snapshot.clip_offset_utf16(selection.end, Bias::Right)
15998            })
15999            .collect()
16000    }
16001
16002    fn report_editor_event(
16003        &self,
16004        event_type: &'static str,
16005        file_extension: Option<String>,
16006        cx: &App,
16007    ) {
16008        if cfg!(any(test, feature = "test-support")) {
16009            return;
16010        }
16011
16012        let Some(project) = &self.project else { return };
16013
16014        // If None, we are in a file without an extension
16015        let file = self
16016            .buffer
16017            .read(cx)
16018            .as_singleton()
16019            .and_then(|b| b.read(cx).file());
16020        let file_extension = file_extension.or(file
16021            .as_ref()
16022            .and_then(|file| Path::new(file.file_name(cx)).extension())
16023            .and_then(|e| e.to_str())
16024            .map(|a| a.to_string()));
16025
16026        let vim_mode = cx
16027            .global::<SettingsStore>()
16028            .raw_user_settings()
16029            .get("vim_mode")
16030            == Some(&serde_json::Value::Bool(true));
16031
16032        let edit_predictions_provider = all_language_settings(file, cx).edit_predictions.provider;
16033        let copilot_enabled = edit_predictions_provider
16034            == language::language_settings::EditPredictionProvider::Copilot;
16035        let copilot_enabled_for_language = self
16036            .buffer
16037            .read(cx)
16038            .language_settings(cx)
16039            .show_edit_predictions;
16040
16041        let project = project.read(cx);
16042        telemetry::event!(
16043            event_type,
16044            file_extension,
16045            vim_mode,
16046            copilot_enabled,
16047            copilot_enabled_for_language,
16048            edit_predictions_provider,
16049            is_via_ssh = project.is_via_ssh(),
16050        );
16051    }
16052
16053    /// Copy the highlighted chunks to the clipboard as JSON. The format is an array of lines,
16054    /// with each line being an array of {text, highlight} objects.
16055    fn copy_highlight_json(
16056        &mut self,
16057        _: &CopyHighlightJson,
16058        window: &mut Window,
16059        cx: &mut Context<Self>,
16060    ) {
16061        #[derive(Serialize)]
16062        struct Chunk<'a> {
16063            text: String,
16064            highlight: Option<&'a str>,
16065        }
16066
16067        let snapshot = self.buffer.read(cx).snapshot(cx);
16068        let range = self
16069            .selected_text_range(false, window, cx)
16070            .and_then(|selection| {
16071                if selection.range.is_empty() {
16072                    None
16073                } else {
16074                    Some(selection.range)
16075                }
16076            })
16077            .unwrap_or_else(|| 0..snapshot.len());
16078
16079        let chunks = snapshot.chunks(range, true);
16080        let mut lines = Vec::new();
16081        let mut line: VecDeque<Chunk> = VecDeque::new();
16082
16083        let Some(style) = self.style.as_ref() else {
16084            return;
16085        };
16086
16087        for chunk in chunks {
16088            let highlight = chunk
16089                .syntax_highlight_id
16090                .and_then(|id| id.name(&style.syntax));
16091            let mut chunk_lines = chunk.text.split('\n').peekable();
16092            while let Some(text) = chunk_lines.next() {
16093                let mut merged_with_last_token = false;
16094                if let Some(last_token) = line.back_mut() {
16095                    if last_token.highlight == highlight {
16096                        last_token.text.push_str(text);
16097                        merged_with_last_token = true;
16098                    }
16099                }
16100
16101                if !merged_with_last_token {
16102                    line.push_back(Chunk {
16103                        text: text.into(),
16104                        highlight,
16105                    });
16106                }
16107
16108                if chunk_lines.peek().is_some() {
16109                    if line.len() > 1 && line.front().unwrap().text.is_empty() {
16110                        line.pop_front();
16111                    }
16112                    if line.len() > 1 && line.back().unwrap().text.is_empty() {
16113                        line.pop_back();
16114                    }
16115
16116                    lines.push(mem::take(&mut line));
16117                }
16118            }
16119        }
16120
16121        let Some(lines) = serde_json::to_string_pretty(&lines).log_err() else {
16122            return;
16123        };
16124        cx.write_to_clipboard(ClipboardItem::new_string(lines));
16125    }
16126
16127    pub fn open_context_menu(
16128        &mut self,
16129        _: &OpenContextMenu,
16130        window: &mut Window,
16131        cx: &mut Context<Self>,
16132    ) {
16133        self.request_autoscroll(Autoscroll::newest(), cx);
16134        let position = self.selections.newest_display(cx).start;
16135        mouse_context_menu::deploy_context_menu(self, None, position, window, cx);
16136    }
16137
16138    pub fn inlay_hint_cache(&self) -> &InlayHintCache {
16139        &self.inlay_hint_cache
16140    }
16141
16142    pub fn replay_insert_event(
16143        &mut self,
16144        text: &str,
16145        relative_utf16_range: Option<Range<isize>>,
16146        window: &mut Window,
16147        cx: &mut Context<Self>,
16148    ) {
16149        if !self.input_enabled {
16150            cx.emit(EditorEvent::InputIgnored { text: text.into() });
16151            return;
16152        }
16153        if let Some(relative_utf16_range) = relative_utf16_range {
16154            let selections = self.selections.all::<OffsetUtf16>(cx);
16155            self.change_selections(None, window, cx, |s| {
16156                let new_ranges = selections.into_iter().map(|range| {
16157                    let start = OffsetUtf16(
16158                        range
16159                            .head()
16160                            .0
16161                            .saturating_add_signed(relative_utf16_range.start),
16162                    );
16163                    let end = OffsetUtf16(
16164                        range
16165                            .head()
16166                            .0
16167                            .saturating_add_signed(relative_utf16_range.end),
16168                    );
16169                    start..end
16170                });
16171                s.select_ranges(new_ranges);
16172            });
16173        }
16174
16175        self.handle_input(text, window, cx);
16176    }
16177
16178    pub fn supports_inlay_hints(&self, cx: &mut App) -> bool {
16179        let Some(provider) = self.semantics_provider.as_ref() else {
16180            return false;
16181        };
16182
16183        let mut supports = false;
16184        self.buffer().update(cx, |this, cx| {
16185            this.for_each_buffer(|buffer| {
16186                supports |= provider.supports_inlay_hints(buffer, cx);
16187            });
16188        });
16189
16190        supports
16191    }
16192
16193    pub fn is_focused(&self, window: &Window) -> bool {
16194        self.focus_handle.is_focused(window)
16195    }
16196
16197    fn handle_focus(&mut self, window: &mut Window, cx: &mut Context<Self>) {
16198        cx.emit(EditorEvent::Focused);
16199
16200        if let Some(descendant) = self
16201            .last_focused_descendant
16202            .take()
16203            .and_then(|descendant| descendant.upgrade())
16204        {
16205            window.focus(&descendant);
16206        } else {
16207            if let Some(blame) = self.blame.as_ref() {
16208                blame.update(cx, GitBlame::focus)
16209            }
16210
16211            self.blink_manager.update(cx, BlinkManager::enable);
16212            self.show_cursor_names(window, cx);
16213            self.buffer.update(cx, |buffer, cx| {
16214                buffer.finalize_last_transaction(cx);
16215                if self.leader_peer_id.is_none() {
16216                    buffer.set_active_selections(
16217                        &self.selections.disjoint_anchors(),
16218                        self.selections.line_mode,
16219                        self.cursor_shape,
16220                        cx,
16221                    );
16222                }
16223            });
16224        }
16225    }
16226
16227    fn handle_focus_in(&mut self, _: &mut Window, cx: &mut Context<Self>) {
16228        cx.emit(EditorEvent::FocusedIn)
16229    }
16230
16231    fn handle_focus_out(
16232        &mut self,
16233        event: FocusOutEvent,
16234        _window: &mut Window,
16235        cx: &mut Context<Self>,
16236    ) {
16237        if event.blurred != self.focus_handle {
16238            self.last_focused_descendant = Some(event.blurred);
16239        }
16240        self.refresh_inlay_hints(InlayHintRefreshReason::ModifiersChanged(false), cx);
16241    }
16242
16243    pub fn handle_blur(&mut self, window: &mut Window, cx: &mut Context<Self>) {
16244        self.blink_manager.update(cx, BlinkManager::disable);
16245        self.buffer
16246            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
16247
16248        if let Some(blame) = self.blame.as_ref() {
16249            blame.update(cx, GitBlame::blur)
16250        }
16251        if !self.hover_state.focused(window, cx) {
16252            hide_hover(self, cx);
16253        }
16254        if !self
16255            .context_menu
16256            .borrow()
16257            .as_ref()
16258            .is_some_and(|context_menu| context_menu.focused(window, cx))
16259        {
16260            self.hide_context_menu(window, cx);
16261        }
16262        self.discard_inline_completion(false, cx);
16263        cx.emit(EditorEvent::Blurred);
16264        cx.notify();
16265    }
16266
16267    pub fn register_action<A: Action>(
16268        &mut self,
16269        listener: impl Fn(&A, &mut Window, &mut App) + 'static,
16270    ) -> Subscription {
16271        let id = self.next_editor_action_id.post_inc();
16272        let listener = Arc::new(listener);
16273        self.editor_actions.borrow_mut().insert(
16274            id,
16275            Box::new(move |window, _| {
16276                let listener = listener.clone();
16277                window.on_action(TypeId::of::<A>(), move |action, phase, window, cx| {
16278                    let action = action.downcast_ref().unwrap();
16279                    if phase == DispatchPhase::Bubble {
16280                        listener(action, window, cx)
16281                    }
16282                })
16283            }),
16284        );
16285
16286        let editor_actions = self.editor_actions.clone();
16287        Subscription::new(move || {
16288            editor_actions.borrow_mut().remove(&id);
16289        })
16290    }
16291
16292    pub fn file_header_size(&self) -> u32 {
16293        FILE_HEADER_HEIGHT
16294    }
16295
16296    pub fn restore(
16297        &mut self,
16298        revert_changes: HashMap<BufferId, Vec<(Range<text::Anchor>, Rope)>>,
16299        window: &mut Window,
16300        cx: &mut Context<Self>,
16301    ) {
16302        let workspace = self.workspace();
16303        let project = self.project.as_ref();
16304        let save_tasks = self.buffer().update(cx, |multi_buffer, cx| {
16305            let mut tasks = Vec::new();
16306            for (buffer_id, changes) in revert_changes {
16307                if let Some(buffer) = multi_buffer.buffer(buffer_id) {
16308                    buffer.update(cx, |buffer, cx| {
16309                        buffer.edit(
16310                            changes
16311                                .into_iter()
16312                                .map(|(range, text)| (range, text.to_string())),
16313                            None,
16314                            cx,
16315                        );
16316                    });
16317
16318                    if let Some(project) =
16319                        project.filter(|_| multi_buffer.all_diff_hunks_expanded())
16320                    {
16321                        project.update(cx, |project, cx| {
16322                            tasks.push((buffer.clone(), project.save_buffer(buffer, cx)));
16323                        })
16324                    }
16325                }
16326            }
16327            tasks
16328        });
16329        cx.spawn_in(window, |_, mut cx| async move {
16330            for (buffer, task) in save_tasks {
16331                let result = task.await;
16332                if result.is_err() {
16333                    let Some(path) = buffer
16334                        .read_with(&cx, |buffer, cx| buffer.project_path(cx))
16335                        .ok()
16336                    else {
16337                        continue;
16338                    };
16339                    if let Some((workspace, path)) = workspace.as_ref().zip(path) {
16340                        let Some(task) = cx
16341                            .update_window_entity(&workspace, |workspace, window, cx| {
16342                                workspace
16343                                    .open_path_preview(path, None, false, false, false, window, cx)
16344                            })
16345                            .ok()
16346                        else {
16347                            continue;
16348                        };
16349                        task.await.log_err();
16350                    }
16351                }
16352            }
16353        })
16354        .detach();
16355        self.change_selections(None, window, cx, |selections| selections.refresh());
16356    }
16357
16358    pub fn to_pixel_point(
16359        &self,
16360        source: multi_buffer::Anchor,
16361        editor_snapshot: &EditorSnapshot,
16362        window: &mut Window,
16363    ) -> Option<gpui::Point<Pixels>> {
16364        let source_point = source.to_display_point(editor_snapshot);
16365        self.display_to_pixel_point(source_point, editor_snapshot, window)
16366    }
16367
16368    pub fn display_to_pixel_point(
16369        &self,
16370        source: DisplayPoint,
16371        editor_snapshot: &EditorSnapshot,
16372        window: &mut Window,
16373    ) -> Option<gpui::Point<Pixels>> {
16374        let line_height = self.style()?.text.line_height_in_pixels(window.rem_size());
16375        let text_layout_details = self.text_layout_details(window);
16376        let scroll_top = text_layout_details
16377            .scroll_anchor
16378            .scroll_position(editor_snapshot)
16379            .y;
16380
16381        if source.row().as_f32() < scroll_top.floor() {
16382            return None;
16383        }
16384        let source_x = editor_snapshot.x_for_display_point(source, &text_layout_details);
16385        let source_y = line_height * (source.row().as_f32() - scroll_top);
16386        Some(gpui::Point::new(source_x, source_y))
16387    }
16388
16389    pub fn has_visible_completions_menu(&self) -> bool {
16390        !self.edit_prediction_preview_is_active()
16391            && self.context_menu.borrow().as_ref().map_or(false, |menu| {
16392                menu.visible() && matches!(menu, CodeContextMenu::Completions(_))
16393            })
16394    }
16395
16396    pub fn register_addon<T: Addon>(&mut self, instance: T) {
16397        self.addons
16398            .insert(std::any::TypeId::of::<T>(), Box::new(instance));
16399    }
16400
16401    pub fn unregister_addon<T: Addon>(&mut self) {
16402        self.addons.remove(&std::any::TypeId::of::<T>());
16403    }
16404
16405    pub fn addon<T: Addon>(&self) -> Option<&T> {
16406        let type_id = std::any::TypeId::of::<T>();
16407        self.addons
16408            .get(&type_id)
16409            .and_then(|item| item.to_any().downcast_ref::<T>())
16410    }
16411
16412    fn character_size(&self, window: &mut Window) -> gpui::Size<Pixels> {
16413        let text_layout_details = self.text_layout_details(window);
16414        let style = &text_layout_details.editor_style;
16415        let font_id = window.text_system().resolve_font(&style.text.font());
16416        let font_size = style.text.font_size.to_pixels(window.rem_size());
16417        let line_height = style.text.line_height_in_pixels(window.rem_size());
16418        let em_width = window.text_system().em_width(font_id, font_size).unwrap();
16419
16420        gpui::Size::new(em_width, line_height)
16421    }
16422
16423    pub fn wait_for_diff_to_load(&self) -> Option<Shared<Task<()>>> {
16424        self.load_diff_task.clone()
16425    }
16426
16427    fn read_selections_from_db(
16428        &mut self,
16429        item_id: u64,
16430        workspace_id: WorkspaceId,
16431        window: &mut Window,
16432        cx: &mut Context<Editor>,
16433    ) {
16434        if !self.is_singleton(cx)
16435            || WorkspaceSettings::get(None, cx).restore_on_startup == RestoreOnStartupBehavior::None
16436        {
16437            return;
16438        }
16439        let Some(selections) = DB.get_editor_selections(item_id, workspace_id).log_err() else {
16440            return;
16441        };
16442        if selections.is_empty() {
16443            return;
16444        }
16445
16446        let snapshot = self.buffer.read(cx).snapshot(cx);
16447        self.change_selections(None, window, cx, |s| {
16448            s.select_ranges(selections.into_iter().map(|(start, end)| {
16449                snapshot.clip_offset(start, Bias::Left)..snapshot.clip_offset(end, Bias::Right)
16450            }));
16451        });
16452    }
16453}
16454
16455fn insert_extra_newline_brackets(
16456    buffer: &MultiBufferSnapshot,
16457    range: Range<usize>,
16458    language: &language::LanguageScope,
16459) -> bool {
16460    let leading_whitespace_len = buffer
16461        .reversed_chars_at(range.start)
16462        .take_while(|c| c.is_whitespace() && *c != '\n')
16463        .map(|c| c.len_utf8())
16464        .sum::<usize>();
16465    let trailing_whitespace_len = buffer
16466        .chars_at(range.end)
16467        .take_while(|c| c.is_whitespace() && *c != '\n')
16468        .map(|c| c.len_utf8())
16469        .sum::<usize>();
16470    let range = range.start - leading_whitespace_len..range.end + trailing_whitespace_len;
16471
16472    language.brackets().any(|(pair, enabled)| {
16473        let pair_start = pair.start.trim_end();
16474        let pair_end = pair.end.trim_start();
16475
16476        enabled
16477            && pair.newline
16478            && buffer.contains_str_at(range.end, pair_end)
16479            && buffer.contains_str_at(range.start.saturating_sub(pair_start.len()), pair_start)
16480    })
16481}
16482
16483fn insert_extra_newline_tree_sitter(buffer: &MultiBufferSnapshot, range: Range<usize>) -> bool {
16484    let (buffer, range) = match buffer.range_to_buffer_ranges(range).as_slice() {
16485        [(buffer, range, _)] => (*buffer, range.clone()),
16486        _ => return false,
16487    };
16488    let pair = {
16489        let mut result: Option<BracketMatch> = None;
16490
16491        for pair in buffer
16492            .all_bracket_ranges(range.clone())
16493            .filter(move |pair| {
16494                pair.open_range.start <= range.start && pair.close_range.end >= range.end
16495            })
16496        {
16497            let len = pair.close_range.end - pair.open_range.start;
16498
16499            if let Some(existing) = &result {
16500                let existing_len = existing.close_range.end - existing.open_range.start;
16501                if len > existing_len {
16502                    continue;
16503                }
16504            }
16505
16506            result = Some(pair);
16507        }
16508
16509        result
16510    };
16511    let Some(pair) = pair else {
16512        return false;
16513    };
16514    pair.newline_only
16515        && buffer
16516            .chars_for_range(pair.open_range.end..range.start)
16517            .chain(buffer.chars_for_range(range.end..pair.close_range.start))
16518            .all(|c| c.is_whitespace() && c != '\n')
16519}
16520
16521fn get_uncommitted_diff_for_buffer(
16522    project: &Entity<Project>,
16523    buffers: impl IntoIterator<Item = Entity<Buffer>>,
16524    buffer: Entity<MultiBuffer>,
16525    cx: &mut App,
16526) -> Task<()> {
16527    let mut tasks = Vec::new();
16528    project.update(cx, |project, cx| {
16529        for buffer in buffers {
16530            tasks.push(project.open_uncommitted_diff(buffer.clone(), cx))
16531        }
16532    });
16533    cx.spawn(|mut cx| async move {
16534        let diffs = future::join_all(tasks).await;
16535        buffer
16536            .update(&mut cx, |buffer, cx| {
16537                for diff in diffs.into_iter().flatten() {
16538                    buffer.add_diff(diff, cx);
16539                }
16540            })
16541            .ok();
16542    })
16543}
16544
16545fn char_len_with_expanded_tabs(offset: usize, text: &str, tab_size: NonZeroU32) -> usize {
16546    let tab_size = tab_size.get() as usize;
16547    let mut width = offset;
16548
16549    for ch in text.chars() {
16550        width += if ch == '\t' {
16551            tab_size - (width % tab_size)
16552        } else {
16553            1
16554        };
16555    }
16556
16557    width - offset
16558}
16559
16560#[cfg(test)]
16561mod tests {
16562    use super::*;
16563
16564    #[test]
16565    fn test_string_size_with_expanded_tabs() {
16566        let nz = |val| NonZeroU32::new(val).unwrap();
16567        assert_eq!(char_len_with_expanded_tabs(0, "", nz(4)), 0);
16568        assert_eq!(char_len_with_expanded_tabs(0, "hello", nz(4)), 5);
16569        assert_eq!(char_len_with_expanded_tabs(0, "\thello", nz(4)), 9);
16570        assert_eq!(char_len_with_expanded_tabs(0, "abc\tab", nz(4)), 6);
16571        assert_eq!(char_len_with_expanded_tabs(0, "hello\t", nz(4)), 8);
16572        assert_eq!(char_len_with_expanded_tabs(0, "\t\t", nz(8)), 16);
16573        assert_eq!(char_len_with_expanded_tabs(0, "x\t", nz(8)), 8);
16574        assert_eq!(char_len_with_expanded_tabs(7, "x\t", nz(8)), 9);
16575    }
16576}
16577
16578/// Tokenizes a string into runs of text that should stick together, or that is whitespace.
16579struct WordBreakingTokenizer<'a> {
16580    input: &'a str,
16581}
16582
16583impl<'a> WordBreakingTokenizer<'a> {
16584    fn new(input: &'a str) -> Self {
16585        Self { input }
16586    }
16587}
16588
16589fn is_char_ideographic(ch: char) -> bool {
16590    use unicode_script::Script::*;
16591    use unicode_script::UnicodeScript;
16592    matches!(ch.script(), Han | Tangut | Yi)
16593}
16594
16595fn is_grapheme_ideographic(text: &str) -> bool {
16596    text.chars().any(is_char_ideographic)
16597}
16598
16599fn is_grapheme_whitespace(text: &str) -> bool {
16600    text.chars().any(|x| x.is_whitespace())
16601}
16602
16603fn should_stay_with_preceding_ideograph(text: &str) -> bool {
16604    text.chars().next().map_or(false, |ch| {
16605        matches!(ch, '。' | '、' | ',' | '?' | '!' | ':' | ';' | '…')
16606    })
16607}
16608
16609#[derive(PartialEq, Eq, Debug, Clone, Copy)]
16610struct WordBreakToken<'a> {
16611    token: &'a str,
16612    grapheme_len: usize,
16613    is_whitespace: bool,
16614}
16615
16616impl<'a> Iterator for WordBreakingTokenizer<'a> {
16617    /// Yields a span, the count of graphemes in the token, and whether it was
16618    /// whitespace. Note that it also breaks at word boundaries.
16619    type Item = WordBreakToken<'a>;
16620
16621    fn next(&mut self) -> Option<Self::Item> {
16622        use unicode_segmentation::UnicodeSegmentation;
16623        if self.input.is_empty() {
16624            return None;
16625        }
16626
16627        let mut iter = self.input.graphemes(true).peekable();
16628        let mut offset = 0;
16629        let mut graphemes = 0;
16630        if let Some(first_grapheme) = iter.next() {
16631            let is_whitespace = is_grapheme_whitespace(first_grapheme);
16632            offset += first_grapheme.len();
16633            graphemes += 1;
16634            if is_grapheme_ideographic(first_grapheme) && !is_whitespace {
16635                if let Some(grapheme) = iter.peek().copied() {
16636                    if should_stay_with_preceding_ideograph(grapheme) {
16637                        offset += grapheme.len();
16638                        graphemes += 1;
16639                    }
16640                }
16641            } else {
16642                let mut words = self.input[offset..].split_word_bound_indices().peekable();
16643                let mut next_word_bound = words.peek().copied();
16644                if next_word_bound.map_or(false, |(i, _)| i == 0) {
16645                    next_word_bound = words.next();
16646                }
16647                while let Some(grapheme) = iter.peek().copied() {
16648                    if next_word_bound.map_or(false, |(i, _)| i == offset) {
16649                        break;
16650                    };
16651                    if is_grapheme_whitespace(grapheme) != is_whitespace {
16652                        break;
16653                    };
16654                    offset += grapheme.len();
16655                    graphemes += 1;
16656                    iter.next();
16657                }
16658            }
16659            let token = &self.input[..offset];
16660            self.input = &self.input[offset..];
16661            if is_whitespace {
16662                Some(WordBreakToken {
16663                    token: " ",
16664                    grapheme_len: 1,
16665                    is_whitespace: true,
16666                })
16667            } else {
16668                Some(WordBreakToken {
16669                    token,
16670                    grapheme_len: graphemes,
16671                    is_whitespace: false,
16672                })
16673            }
16674        } else {
16675            None
16676        }
16677    }
16678}
16679
16680#[test]
16681fn test_word_breaking_tokenizer() {
16682    let tests: &[(&str, &[(&str, usize, bool)])] = &[
16683        ("", &[]),
16684        ("  ", &[(" ", 1, true)]),
16685        ("Ʒ", &[("Ʒ", 1, false)]),
16686        ("Ǽ", &[("Ǽ", 1, false)]),
16687        ("", &[("", 1, false)]),
16688        ("⋑⋑", &[("⋑⋑", 2, false)]),
16689        (
16690            "原理,进而",
16691            &[
16692                ("", 1, false),
16693                ("理,", 2, false),
16694                ("", 1, false),
16695                ("", 1, false),
16696            ],
16697        ),
16698        (
16699            "hello world",
16700            &[("hello", 5, false), (" ", 1, true), ("world", 5, false)],
16701        ),
16702        (
16703            "hello, world",
16704            &[("hello,", 6, false), (" ", 1, true), ("world", 5, false)],
16705        ),
16706        (
16707            "  hello world",
16708            &[
16709                (" ", 1, true),
16710                ("hello", 5, false),
16711                (" ", 1, true),
16712                ("world", 5, false),
16713            ],
16714        ),
16715        (
16716            "这是什么 \n 钢笔",
16717            &[
16718                ("", 1, false),
16719                ("", 1, false),
16720                ("", 1, false),
16721                ("", 1, false),
16722                (" ", 1, true),
16723                ("", 1, false),
16724                ("", 1, false),
16725            ],
16726        ),
16727        (" mutton", &[(" ", 1, true), ("mutton", 6, false)]),
16728    ];
16729
16730    for (input, result) in tests {
16731        assert_eq!(
16732            WordBreakingTokenizer::new(input).collect::<Vec<_>>(),
16733            result
16734                .iter()
16735                .copied()
16736                .map(|(token, grapheme_len, is_whitespace)| WordBreakToken {
16737                    token,
16738                    grapheme_len,
16739                    is_whitespace,
16740                })
16741                .collect::<Vec<_>>()
16742        );
16743    }
16744}
16745
16746fn wrap_with_prefix(
16747    line_prefix: String,
16748    unwrapped_text: String,
16749    wrap_column: usize,
16750    tab_size: NonZeroU32,
16751) -> String {
16752    let line_prefix_len = char_len_with_expanded_tabs(0, &line_prefix, tab_size);
16753    let mut wrapped_text = String::new();
16754    let mut current_line = line_prefix.clone();
16755
16756    let tokenizer = WordBreakingTokenizer::new(&unwrapped_text);
16757    let mut current_line_len = line_prefix_len;
16758    for WordBreakToken {
16759        token,
16760        grapheme_len,
16761        is_whitespace,
16762    } in tokenizer
16763    {
16764        if current_line_len + grapheme_len > wrap_column && current_line_len != line_prefix_len {
16765            wrapped_text.push_str(current_line.trim_end());
16766            wrapped_text.push('\n');
16767            current_line.truncate(line_prefix.len());
16768            current_line_len = line_prefix_len;
16769            if !is_whitespace {
16770                current_line.push_str(token);
16771                current_line_len += grapheme_len;
16772            }
16773        } else if !is_whitespace {
16774            current_line.push_str(token);
16775            current_line_len += grapheme_len;
16776        } else if current_line_len != line_prefix_len {
16777            current_line.push(' ');
16778            current_line_len += 1;
16779        }
16780    }
16781
16782    if !current_line.is_empty() {
16783        wrapped_text.push_str(&current_line);
16784    }
16785    wrapped_text
16786}
16787
16788#[test]
16789fn test_wrap_with_prefix() {
16790    assert_eq!(
16791        wrap_with_prefix(
16792            "# ".to_string(),
16793            "abcdefg".to_string(),
16794            4,
16795            NonZeroU32::new(4).unwrap()
16796        ),
16797        "# abcdefg"
16798    );
16799    assert_eq!(
16800        wrap_with_prefix(
16801            "".to_string(),
16802            "\thello world".to_string(),
16803            8,
16804            NonZeroU32::new(4).unwrap()
16805        ),
16806        "hello\nworld"
16807    );
16808    assert_eq!(
16809        wrap_with_prefix(
16810            "// ".to_string(),
16811            "xx \nyy zz aa bb cc".to_string(),
16812            12,
16813            NonZeroU32::new(4).unwrap()
16814        ),
16815        "// xx yy zz\n// aa bb cc"
16816    );
16817    assert_eq!(
16818        wrap_with_prefix(
16819            String::new(),
16820            "这是什么 \n 钢笔".to_string(),
16821            3,
16822            NonZeroU32::new(4).unwrap()
16823        ),
16824        "这是什\n么 钢\n"
16825    );
16826}
16827
16828pub trait CollaborationHub {
16829    fn collaborators<'a>(&self, cx: &'a App) -> &'a HashMap<PeerId, Collaborator>;
16830    fn user_participant_indices<'a>(&self, cx: &'a App) -> &'a HashMap<u64, ParticipantIndex>;
16831    fn user_names(&self, cx: &App) -> HashMap<u64, SharedString>;
16832}
16833
16834impl CollaborationHub for Entity<Project> {
16835    fn collaborators<'a>(&self, cx: &'a App) -> &'a HashMap<PeerId, Collaborator> {
16836        self.read(cx).collaborators()
16837    }
16838
16839    fn user_participant_indices<'a>(&self, cx: &'a App) -> &'a HashMap<u64, ParticipantIndex> {
16840        self.read(cx).user_store().read(cx).participant_indices()
16841    }
16842
16843    fn user_names(&self, cx: &App) -> HashMap<u64, SharedString> {
16844        let this = self.read(cx);
16845        let user_ids = this.collaborators().values().map(|c| c.user_id);
16846        this.user_store().read_with(cx, |user_store, cx| {
16847            user_store.participant_names(user_ids, cx)
16848        })
16849    }
16850}
16851
16852pub trait SemanticsProvider {
16853    fn hover(
16854        &self,
16855        buffer: &Entity<Buffer>,
16856        position: text::Anchor,
16857        cx: &mut App,
16858    ) -> Option<Task<Vec<project::Hover>>>;
16859
16860    fn inlay_hints(
16861        &self,
16862        buffer_handle: Entity<Buffer>,
16863        range: Range<text::Anchor>,
16864        cx: &mut App,
16865    ) -> Option<Task<anyhow::Result<Vec<InlayHint>>>>;
16866
16867    fn resolve_inlay_hint(
16868        &self,
16869        hint: InlayHint,
16870        buffer_handle: Entity<Buffer>,
16871        server_id: LanguageServerId,
16872        cx: &mut App,
16873    ) -> Option<Task<anyhow::Result<InlayHint>>>;
16874
16875    fn supports_inlay_hints(&self, buffer: &Entity<Buffer>, cx: &mut App) -> bool;
16876
16877    fn document_highlights(
16878        &self,
16879        buffer: &Entity<Buffer>,
16880        position: text::Anchor,
16881        cx: &mut App,
16882    ) -> Option<Task<Result<Vec<DocumentHighlight>>>>;
16883
16884    fn definitions(
16885        &self,
16886        buffer: &Entity<Buffer>,
16887        position: text::Anchor,
16888        kind: GotoDefinitionKind,
16889        cx: &mut App,
16890    ) -> Option<Task<Result<Vec<LocationLink>>>>;
16891
16892    fn range_for_rename(
16893        &self,
16894        buffer: &Entity<Buffer>,
16895        position: text::Anchor,
16896        cx: &mut App,
16897    ) -> Option<Task<Result<Option<Range<text::Anchor>>>>>;
16898
16899    fn perform_rename(
16900        &self,
16901        buffer: &Entity<Buffer>,
16902        position: text::Anchor,
16903        new_name: String,
16904        cx: &mut App,
16905    ) -> Option<Task<Result<ProjectTransaction>>>;
16906}
16907
16908pub trait CompletionProvider {
16909    fn completions(
16910        &self,
16911        buffer: &Entity<Buffer>,
16912        buffer_position: text::Anchor,
16913        trigger: CompletionContext,
16914        window: &mut Window,
16915        cx: &mut Context<Editor>,
16916    ) -> Task<Result<Vec<Completion>>>;
16917
16918    fn resolve_completions(
16919        &self,
16920        buffer: Entity<Buffer>,
16921        completion_indices: Vec<usize>,
16922        completions: Rc<RefCell<Box<[Completion]>>>,
16923        cx: &mut Context<Editor>,
16924    ) -> Task<Result<bool>>;
16925
16926    fn apply_additional_edits_for_completion(
16927        &self,
16928        _buffer: Entity<Buffer>,
16929        _completions: Rc<RefCell<Box<[Completion]>>>,
16930        _completion_index: usize,
16931        _push_to_history: bool,
16932        _cx: &mut Context<Editor>,
16933    ) -> Task<Result<Option<language::Transaction>>> {
16934        Task::ready(Ok(None))
16935    }
16936
16937    fn is_completion_trigger(
16938        &self,
16939        buffer: &Entity<Buffer>,
16940        position: language::Anchor,
16941        text: &str,
16942        trigger_in_words: bool,
16943        cx: &mut Context<Editor>,
16944    ) -> bool;
16945
16946    fn sort_completions(&self) -> bool {
16947        true
16948    }
16949}
16950
16951pub trait CodeActionProvider {
16952    fn id(&self) -> Arc<str>;
16953
16954    fn code_actions(
16955        &self,
16956        buffer: &Entity<Buffer>,
16957        range: Range<text::Anchor>,
16958        window: &mut Window,
16959        cx: &mut App,
16960    ) -> Task<Result<Vec<CodeAction>>>;
16961
16962    fn apply_code_action(
16963        &self,
16964        buffer_handle: Entity<Buffer>,
16965        action: CodeAction,
16966        excerpt_id: ExcerptId,
16967        push_to_history: bool,
16968        window: &mut Window,
16969        cx: &mut App,
16970    ) -> Task<Result<ProjectTransaction>>;
16971}
16972
16973impl CodeActionProvider for Entity<Project> {
16974    fn id(&self) -> Arc<str> {
16975        "project".into()
16976    }
16977
16978    fn code_actions(
16979        &self,
16980        buffer: &Entity<Buffer>,
16981        range: Range<text::Anchor>,
16982        _window: &mut Window,
16983        cx: &mut App,
16984    ) -> Task<Result<Vec<CodeAction>>> {
16985        self.update(cx, |project, cx| {
16986            project.code_actions(buffer, range, None, cx)
16987        })
16988    }
16989
16990    fn apply_code_action(
16991        &self,
16992        buffer_handle: Entity<Buffer>,
16993        action: CodeAction,
16994        _excerpt_id: ExcerptId,
16995        push_to_history: bool,
16996        _window: &mut Window,
16997        cx: &mut App,
16998    ) -> Task<Result<ProjectTransaction>> {
16999        self.update(cx, |project, cx| {
17000            project.apply_code_action(buffer_handle, action, push_to_history, cx)
17001        })
17002    }
17003}
17004
17005fn snippet_completions(
17006    project: &Project,
17007    buffer: &Entity<Buffer>,
17008    buffer_position: text::Anchor,
17009    cx: &mut App,
17010) -> Task<Result<Vec<Completion>>> {
17011    let language = buffer.read(cx).language_at(buffer_position);
17012    let language_name = language.as_ref().map(|language| language.lsp_id());
17013    let snippet_store = project.snippets().read(cx);
17014    let snippets = snippet_store.snippets_for(language_name, cx);
17015
17016    if snippets.is_empty() {
17017        return Task::ready(Ok(vec![]));
17018    }
17019    let snapshot = buffer.read(cx).text_snapshot();
17020    let chars: String = snapshot
17021        .reversed_chars_for_range(text::Anchor::MIN..buffer_position)
17022        .collect();
17023
17024    let scope = language.map(|language| language.default_scope());
17025    let executor = cx.background_executor().clone();
17026
17027    cx.background_spawn(async move {
17028        let classifier = CharClassifier::new(scope).for_completion(true);
17029        let mut last_word = chars
17030            .chars()
17031            .take_while(|c| classifier.is_word(*c))
17032            .collect::<String>();
17033        last_word = last_word.chars().rev().collect();
17034
17035        if last_word.is_empty() {
17036            return Ok(vec![]);
17037        }
17038
17039        let as_offset = text::ToOffset::to_offset(&buffer_position, &snapshot);
17040        let to_lsp = |point: &text::Anchor| {
17041            let end = text::ToPointUtf16::to_point_utf16(point, &snapshot);
17042            point_to_lsp(end)
17043        };
17044        let lsp_end = to_lsp(&buffer_position);
17045
17046        let candidates = snippets
17047            .iter()
17048            .enumerate()
17049            .flat_map(|(ix, snippet)| {
17050                snippet
17051                    .prefix
17052                    .iter()
17053                    .map(move |prefix| StringMatchCandidate::new(ix, &prefix))
17054            })
17055            .collect::<Vec<StringMatchCandidate>>();
17056
17057        let mut matches = fuzzy::match_strings(
17058            &candidates,
17059            &last_word,
17060            last_word.chars().any(|c| c.is_uppercase()),
17061            100,
17062            &Default::default(),
17063            executor,
17064        )
17065        .await;
17066
17067        // Remove all candidates where the query's start does not match the start of any word in the candidate
17068        if let Some(query_start) = last_word.chars().next() {
17069            matches.retain(|string_match| {
17070                split_words(&string_match.string).any(|word| {
17071                    // Check that the first codepoint of the word as lowercase matches the first
17072                    // codepoint of the query as lowercase
17073                    word.chars()
17074                        .flat_map(|codepoint| codepoint.to_lowercase())
17075                        .zip(query_start.to_lowercase())
17076                        .all(|(word_cp, query_cp)| word_cp == query_cp)
17077                })
17078            });
17079        }
17080
17081        let matched_strings = matches
17082            .into_iter()
17083            .map(|m| m.string)
17084            .collect::<HashSet<_>>();
17085
17086        let result: Vec<Completion> = snippets
17087            .into_iter()
17088            .filter_map(|snippet| {
17089                let matching_prefix = snippet
17090                    .prefix
17091                    .iter()
17092                    .find(|prefix| matched_strings.contains(*prefix))?;
17093                let start = as_offset - last_word.len();
17094                let start = snapshot.anchor_before(start);
17095                let range = start..buffer_position;
17096                let lsp_start = to_lsp(&start);
17097                let lsp_range = lsp::Range {
17098                    start: lsp_start,
17099                    end: lsp_end,
17100                };
17101                Some(Completion {
17102                    old_range: range,
17103                    new_text: snippet.body.clone(),
17104                    source: CompletionSource::Lsp {
17105                        server_id: LanguageServerId(usize::MAX),
17106                        resolved: true,
17107                        lsp_completion: Box::new(lsp::CompletionItem {
17108                            label: snippet.prefix.first().unwrap().clone(),
17109                            kind: Some(CompletionItemKind::SNIPPET),
17110                            label_details: snippet.description.as_ref().map(|description| {
17111                                lsp::CompletionItemLabelDetails {
17112                                    detail: Some(description.clone()),
17113                                    description: None,
17114                                }
17115                            }),
17116                            insert_text_format: Some(InsertTextFormat::SNIPPET),
17117                            text_edit: Some(lsp::CompletionTextEdit::InsertAndReplace(
17118                                lsp::InsertReplaceEdit {
17119                                    new_text: snippet.body.clone(),
17120                                    insert: lsp_range,
17121                                    replace: lsp_range,
17122                                },
17123                            )),
17124                            filter_text: Some(snippet.body.clone()),
17125                            sort_text: Some(char::MAX.to_string()),
17126                            ..lsp::CompletionItem::default()
17127                        }),
17128                        lsp_defaults: None,
17129                    },
17130                    label: CodeLabel {
17131                        text: matching_prefix.clone(),
17132                        runs: Vec::new(),
17133                        filter_range: 0..matching_prefix.len(),
17134                    },
17135                    documentation: snippet
17136                        .description
17137                        .clone()
17138                        .map(|description| CompletionDocumentation::SingleLine(description.into())),
17139                    confirm: None,
17140                })
17141            })
17142            .collect();
17143
17144        Ok(result)
17145    })
17146}
17147
17148impl CompletionProvider for Entity<Project> {
17149    fn completions(
17150        &self,
17151        buffer: &Entity<Buffer>,
17152        buffer_position: text::Anchor,
17153        options: CompletionContext,
17154        _window: &mut Window,
17155        cx: &mut Context<Editor>,
17156    ) -> Task<Result<Vec<Completion>>> {
17157        self.update(cx, |project, cx| {
17158            let snippets = snippet_completions(project, buffer, buffer_position, cx);
17159            let project_completions = project.completions(buffer, buffer_position, options, cx);
17160            cx.background_spawn(async move {
17161                let mut completions = project_completions.await?;
17162                let snippets_completions = snippets.await?;
17163                completions.extend(snippets_completions);
17164                Ok(completions)
17165            })
17166        })
17167    }
17168
17169    fn resolve_completions(
17170        &self,
17171        buffer: Entity<Buffer>,
17172        completion_indices: Vec<usize>,
17173        completions: Rc<RefCell<Box<[Completion]>>>,
17174        cx: &mut Context<Editor>,
17175    ) -> Task<Result<bool>> {
17176        self.update(cx, |project, cx| {
17177            project.lsp_store().update(cx, |lsp_store, cx| {
17178                lsp_store.resolve_completions(buffer, completion_indices, completions, cx)
17179            })
17180        })
17181    }
17182
17183    fn apply_additional_edits_for_completion(
17184        &self,
17185        buffer: Entity<Buffer>,
17186        completions: Rc<RefCell<Box<[Completion]>>>,
17187        completion_index: usize,
17188        push_to_history: bool,
17189        cx: &mut Context<Editor>,
17190    ) -> Task<Result<Option<language::Transaction>>> {
17191        self.update(cx, |project, cx| {
17192            project.lsp_store().update(cx, |lsp_store, cx| {
17193                lsp_store.apply_additional_edits_for_completion(
17194                    buffer,
17195                    completions,
17196                    completion_index,
17197                    push_to_history,
17198                    cx,
17199                )
17200            })
17201        })
17202    }
17203
17204    fn is_completion_trigger(
17205        &self,
17206        buffer: &Entity<Buffer>,
17207        position: language::Anchor,
17208        text: &str,
17209        trigger_in_words: bool,
17210        cx: &mut Context<Editor>,
17211    ) -> bool {
17212        let mut chars = text.chars();
17213        let char = if let Some(char) = chars.next() {
17214            char
17215        } else {
17216            return false;
17217        };
17218        if chars.next().is_some() {
17219            return false;
17220        }
17221
17222        let buffer = buffer.read(cx);
17223        let snapshot = buffer.snapshot();
17224        if !snapshot.settings_at(position, cx).show_completions_on_input {
17225            return false;
17226        }
17227        let classifier = snapshot.char_classifier_at(position).for_completion(true);
17228        if trigger_in_words && classifier.is_word(char) {
17229            return true;
17230        }
17231
17232        buffer.completion_triggers().contains(text)
17233    }
17234}
17235
17236impl SemanticsProvider for Entity<Project> {
17237    fn hover(
17238        &self,
17239        buffer: &Entity<Buffer>,
17240        position: text::Anchor,
17241        cx: &mut App,
17242    ) -> Option<Task<Vec<project::Hover>>> {
17243        Some(self.update(cx, |project, cx| project.hover(buffer, position, cx)))
17244    }
17245
17246    fn document_highlights(
17247        &self,
17248        buffer: &Entity<Buffer>,
17249        position: text::Anchor,
17250        cx: &mut App,
17251    ) -> Option<Task<Result<Vec<DocumentHighlight>>>> {
17252        Some(self.update(cx, |project, cx| {
17253            project.document_highlights(buffer, position, cx)
17254        }))
17255    }
17256
17257    fn definitions(
17258        &self,
17259        buffer: &Entity<Buffer>,
17260        position: text::Anchor,
17261        kind: GotoDefinitionKind,
17262        cx: &mut App,
17263    ) -> Option<Task<Result<Vec<LocationLink>>>> {
17264        Some(self.update(cx, |project, cx| match kind {
17265            GotoDefinitionKind::Symbol => project.definition(&buffer, position, cx),
17266            GotoDefinitionKind::Declaration => project.declaration(&buffer, position, cx),
17267            GotoDefinitionKind::Type => project.type_definition(&buffer, position, cx),
17268            GotoDefinitionKind::Implementation => project.implementation(&buffer, position, cx),
17269        }))
17270    }
17271
17272    fn supports_inlay_hints(&self, buffer: &Entity<Buffer>, cx: &mut App) -> bool {
17273        // TODO: make this work for remote projects
17274        self.update(cx, |this, cx| {
17275            buffer.update(cx, |buffer, cx| {
17276                this.any_language_server_supports_inlay_hints(buffer, cx)
17277            })
17278        })
17279    }
17280
17281    fn inlay_hints(
17282        &self,
17283        buffer_handle: Entity<Buffer>,
17284        range: Range<text::Anchor>,
17285        cx: &mut App,
17286    ) -> Option<Task<anyhow::Result<Vec<InlayHint>>>> {
17287        Some(self.update(cx, |project, cx| {
17288            project.inlay_hints(buffer_handle, range, cx)
17289        }))
17290    }
17291
17292    fn resolve_inlay_hint(
17293        &self,
17294        hint: InlayHint,
17295        buffer_handle: Entity<Buffer>,
17296        server_id: LanguageServerId,
17297        cx: &mut App,
17298    ) -> Option<Task<anyhow::Result<InlayHint>>> {
17299        Some(self.update(cx, |project, cx| {
17300            project.resolve_inlay_hint(hint, buffer_handle, server_id, cx)
17301        }))
17302    }
17303
17304    fn range_for_rename(
17305        &self,
17306        buffer: &Entity<Buffer>,
17307        position: text::Anchor,
17308        cx: &mut App,
17309    ) -> Option<Task<Result<Option<Range<text::Anchor>>>>> {
17310        Some(self.update(cx, |project, cx| {
17311            let buffer = buffer.clone();
17312            let task = project.prepare_rename(buffer.clone(), position, cx);
17313            cx.spawn(|_, mut cx| async move {
17314                Ok(match task.await? {
17315                    PrepareRenameResponse::Success(range) => Some(range),
17316                    PrepareRenameResponse::InvalidPosition => None,
17317                    PrepareRenameResponse::OnlyUnpreparedRenameSupported => {
17318                        // Fallback on using TreeSitter info to determine identifier range
17319                        buffer.update(&mut cx, |buffer, _| {
17320                            let snapshot = buffer.snapshot();
17321                            let (range, kind) = snapshot.surrounding_word(position);
17322                            if kind != Some(CharKind::Word) {
17323                                return None;
17324                            }
17325                            Some(
17326                                snapshot.anchor_before(range.start)
17327                                    ..snapshot.anchor_after(range.end),
17328                            )
17329                        })?
17330                    }
17331                })
17332            })
17333        }))
17334    }
17335
17336    fn perform_rename(
17337        &self,
17338        buffer: &Entity<Buffer>,
17339        position: text::Anchor,
17340        new_name: String,
17341        cx: &mut App,
17342    ) -> Option<Task<Result<ProjectTransaction>>> {
17343        Some(self.update(cx, |project, cx| {
17344            project.perform_rename(buffer.clone(), position, new_name, cx)
17345        }))
17346    }
17347}
17348
17349fn inlay_hint_settings(
17350    location: Anchor,
17351    snapshot: &MultiBufferSnapshot,
17352    cx: &mut Context<Editor>,
17353) -> InlayHintSettings {
17354    let file = snapshot.file_at(location);
17355    let language = snapshot.language_at(location).map(|l| l.name());
17356    language_settings(language, file, cx).inlay_hints
17357}
17358
17359fn consume_contiguous_rows(
17360    contiguous_row_selections: &mut Vec<Selection<Point>>,
17361    selection: &Selection<Point>,
17362    display_map: &DisplaySnapshot,
17363    selections: &mut Peekable<std::slice::Iter<Selection<Point>>>,
17364) -> (MultiBufferRow, MultiBufferRow) {
17365    contiguous_row_selections.push(selection.clone());
17366    let start_row = MultiBufferRow(selection.start.row);
17367    let mut end_row = ending_row(selection, display_map);
17368
17369    while let Some(next_selection) = selections.peek() {
17370        if next_selection.start.row <= end_row.0 {
17371            end_row = ending_row(next_selection, display_map);
17372            contiguous_row_selections.push(selections.next().unwrap().clone());
17373        } else {
17374            break;
17375        }
17376    }
17377    (start_row, end_row)
17378}
17379
17380fn ending_row(next_selection: &Selection<Point>, display_map: &DisplaySnapshot) -> MultiBufferRow {
17381    if next_selection.end.column > 0 || next_selection.is_empty() {
17382        MultiBufferRow(display_map.next_line_boundary(next_selection.end).0.row + 1)
17383    } else {
17384        MultiBufferRow(next_selection.end.row)
17385    }
17386}
17387
17388impl EditorSnapshot {
17389    pub fn remote_selections_in_range<'a>(
17390        &'a self,
17391        range: &'a Range<Anchor>,
17392        collaboration_hub: &dyn CollaborationHub,
17393        cx: &'a App,
17394    ) -> impl 'a + Iterator<Item = RemoteSelection> {
17395        let participant_names = collaboration_hub.user_names(cx);
17396        let participant_indices = collaboration_hub.user_participant_indices(cx);
17397        let collaborators_by_peer_id = collaboration_hub.collaborators(cx);
17398        let collaborators_by_replica_id = collaborators_by_peer_id
17399            .iter()
17400            .map(|(_, collaborator)| (collaborator.replica_id, collaborator))
17401            .collect::<HashMap<_, _>>();
17402        self.buffer_snapshot
17403            .selections_in_range(range, false)
17404            .filter_map(move |(replica_id, line_mode, cursor_shape, selection)| {
17405                let collaborator = collaborators_by_replica_id.get(&replica_id)?;
17406                let participant_index = participant_indices.get(&collaborator.user_id).copied();
17407                let user_name = participant_names.get(&collaborator.user_id).cloned();
17408                Some(RemoteSelection {
17409                    replica_id,
17410                    selection,
17411                    cursor_shape,
17412                    line_mode,
17413                    participant_index,
17414                    peer_id: collaborator.peer_id,
17415                    user_name,
17416                })
17417            })
17418    }
17419
17420    pub fn hunks_for_ranges(
17421        &self,
17422        ranges: impl IntoIterator<Item = Range<Point>>,
17423    ) -> Vec<MultiBufferDiffHunk> {
17424        let mut hunks = Vec::new();
17425        let mut processed_buffer_rows: HashMap<BufferId, HashSet<Range<text::Anchor>>> =
17426            HashMap::default();
17427        for query_range in ranges {
17428            let query_rows =
17429                MultiBufferRow(query_range.start.row)..MultiBufferRow(query_range.end.row + 1);
17430            for hunk in self.buffer_snapshot.diff_hunks_in_range(
17431                Point::new(query_rows.start.0, 0)..Point::new(query_rows.end.0, 0),
17432            ) {
17433                // Include deleted hunks that are adjacent to the query range, because
17434                // otherwise they would be missed.
17435                let mut intersects_range = hunk.row_range.overlaps(&query_rows);
17436                if hunk.status().is_deleted() {
17437                    intersects_range |= hunk.row_range.start == query_rows.end;
17438                    intersects_range |= hunk.row_range.end == query_rows.start;
17439                }
17440                if intersects_range {
17441                    if !processed_buffer_rows
17442                        .entry(hunk.buffer_id)
17443                        .or_default()
17444                        .insert(hunk.buffer_range.start..hunk.buffer_range.end)
17445                    {
17446                        continue;
17447                    }
17448                    hunks.push(hunk);
17449                }
17450            }
17451        }
17452
17453        hunks
17454    }
17455
17456    fn display_diff_hunks_for_rows<'a>(
17457        &'a self,
17458        display_rows: Range<DisplayRow>,
17459        folded_buffers: &'a HashSet<BufferId>,
17460    ) -> impl 'a + Iterator<Item = DisplayDiffHunk> {
17461        let buffer_start = DisplayPoint::new(display_rows.start, 0).to_point(self);
17462        let buffer_end = DisplayPoint::new(display_rows.end, 0).to_point(self);
17463
17464        self.buffer_snapshot
17465            .diff_hunks_in_range(buffer_start..buffer_end)
17466            .filter_map(|hunk| {
17467                if folded_buffers.contains(&hunk.buffer_id) {
17468                    return None;
17469                }
17470
17471                let hunk_start_point = Point::new(hunk.row_range.start.0, 0);
17472                let hunk_end_point = Point::new(hunk.row_range.end.0, 0);
17473
17474                let hunk_display_start = self.point_to_display_point(hunk_start_point, Bias::Left);
17475                let hunk_display_end = self.point_to_display_point(hunk_end_point, Bias::Right);
17476
17477                let display_hunk = if hunk_display_start.column() != 0 {
17478                    DisplayDiffHunk::Folded {
17479                        display_row: hunk_display_start.row(),
17480                    }
17481                } else {
17482                    let mut end_row = hunk_display_end.row();
17483                    if hunk_display_end.column() > 0 {
17484                        end_row.0 += 1;
17485                    }
17486                    let is_created_file = hunk.is_created_file();
17487                    DisplayDiffHunk::Unfolded {
17488                        status: hunk.status(),
17489                        diff_base_byte_range: hunk.diff_base_byte_range,
17490                        display_row_range: hunk_display_start.row()..end_row,
17491                        multi_buffer_range: Anchor::range_in_buffer(
17492                            hunk.excerpt_id,
17493                            hunk.buffer_id,
17494                            hunk.buffer_range,
17495                        ),
17496                        is_created_file,
17497                    }
17498                };
17499
17500                Some(display_hunk)
17501            })
17502    }
17503
17504    pub fn language_at<T: ToOffset>(&self, position: T) -> Option<&Arc<Language>> {
17505        self.display_snapshot.buffer_snapshot.language_at(position)
17506    }
17507
17508    pub fn is_focused(&self) -> bool {
17509        self.is_focused
17510    }
17511
17512    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
17513        self.placeholder_text.as_ref()
17514    }
17515
17516    pub fn scroll_position(&self) -> gpui::Point<f32> {
17517        self.scroll_anchor.scroll_position(&self.display_snapshot)
17518    }
17519
17520    fn gutter_dimensions(
17521        &self,
17522        font_id: FontId,
17523        font_size: Pixels,
17524        max_line_number_width: Pixels,
17525        cx: &App,
17526    ) -> Option<GutterDimensions> {
17527        if !self.show_gutter {
17528            return None;
17529        }
17530
17531        let descent = cx.text_system().descent(font_id, font_size);
17532        let em_width = cx.text_system().em_width(font_id, font_size).log_err()?;
17533        let em_advance = cx.text_system().em_advance(font_id, font_size).log_err()?;
17534
17535        let show_git_gutter = self.show_git_diff_gutter.unwrap_or_else(|| {
17536            matches!(
17537                ProjectSettings::get_global(cx).git.git_gutter,
17538                Some(GitGutterSetting::TrackedFiles)
17539            )
17540        });
17541        let gutter_settings = EditorSettings::get_global(cx).gutter;
17542        let show_line_numbers = self
17543            .show_line_numbers
17544            .unwrap_or(gutter_settings.line_numbers);
17545        let line_gutter_width = if show_line_numbers {
17546            // Avoid flicker-like gutter resizes when the line number gains another digit and only resize the gutter on files with N*10^5 lines.
17547            let min_width_for_number_on_gutter = em_advance * 4.0;
17548            max_line_number_width.max(min_width_for_number_on_gutter)
17549        } else {
17550            0.0.into()
17551        };
17552
17553        let show_code_actions = self
17554            .show_code_actions
17555            .unwrap_or(gutter_settings.code_actions);
17556
17557        let show_runnables = self.show_runnables.unwrap_or(gutter_settings.runnables);
17558
17559        let git_blame_entries_width =
17560            self.git_blame_gutter_max_author_length
17561                .map(|max_author_length| {
17562                    const MAX_RELATIVE_TIMESTAMP: &str = "60 minutes ago";
17563
17564                    /// The number of characters to dedicate to gaps and margins.
17565                    const SPACING_WIDTH: usize = 4;
17566
17567                    let max_char_count = max_author_length
17568                        .min(GIT_BLAME_MAX_AUTHOR_CHARS_DISPLAYED)
17569                        + ::git::SHORT_SHA_LENGTH
17570                        + MAX_RELATIVE_TIMESTAMP.len()
17571                        + SPACING_WIDTH;
17572
17573                    em_advance * max_char_count
17574                });
17575
17576        let mut left_padding = git_blame_entries_width.unwrap_or(Pixels::ZERO);
17577        left_padding += if show_code_actions || show_runnables {
17578            em_width * 3.0
17579        } else if show_git_gutter && show_line_numbers {
17580            em_width * 2.0
17581        } else if show_git_gutter || show_line_numbers {
17582            em_width
17583        } else {
17584            px(0.)
17585        };
17586
17587        let right_padding = if gutter_settings.folds && show_line_numbers {
17588            em_width * 4.0
17589        } else if gutter_settings.folds {
17590            em_width * 3.0
17591        } else if show_line_numbers {
17592            em_width
17593        } else {
17594            px(0.)
17595        };
17596
17597        Some(GutterDimensions {
17598            left_padding,
17599            right_padding,
17600            width: line_gutter_width + left_padding + right_padding,
17601            margin: -descent,
17602            git_blame_entries_width,
17603        })
17604    }
17605
17606    pub fn render_crease_toggle(
17607        &self,
17608        buffer_row: MultiBufferRow,
17609        row_contains_cursor: bool,
17610        editor: Entity<Editor>,
17611        window: &mut Window,
17612        cx: &mut App,
17613    ) -> Option<AnyElement> {
17614        let folded = self.is_line_folded(buffer_row);
17615        let mut is_foldable = false;
17616
17617        if let Some(crease) = self
17618            .crease_snapshot
17619            .query_row(buffer_row, &self.buffer_snapshot)
17620        {
17621            is_foldable = true;
17622            match crease {
17623                Crease::Inline { render_toggle, .. } | Crease::Block { render_toggle, .. } => {
17624                    if let Some(render_toggle) = render_toggle {
17625                        let toggle_callback =
17626                            Arc::new(move |folded, window: &mut Window, cx: &mut App| {
17627                                if folded {
17628                                    editor.update(cx, |editor, cx| {
17629                                        editor.fold_at(&crate::FoldAt { buffer_row }, window, cx)
17630                                    });
17631                                } else {
17632                                    editor.update(cx, |editor, cx| {
17633                                        editor.unfold_at(
17634                                            &crate::UnfoldAt { buffer_row },
17635                                            window,
17636                                            cx,
17637                                        )
17638                                    });
17639                                }
17640                            });
17641                        return Some((render_toggle)(
17642                            buffer_row,
17643                            folded,
17644                            toggle_callback,
17645                            window,
17646                            cx,
17647                        ));
17648                    }
17649                }
17650            }
17651        }
17652
17653        is_foldable |= self.starts_indent(buffer_row);
17654
17655        if folded || (is_foldable && (row_contains_cursor || self.gutter_hovered)) {
17656            Some(
17657                Disclosure::new(("gutter_crease", buffer_row.0), !folded)
17658                    .toggle_state(folded)
17659                    .on_click(window.listener_for(&editor, move |this, _e, window, cx| {
17660                        if folded {
17661                            this.unfold_at(&UnfoldAt { buffer_row }, window, cx);
17662                        } else {
17663                            this.fold_at(&FoldAt { buffer_row }, window, cx);
17664                        }
17665                    }))
17666                    .into_any_element(),
17667            )
17668        } else {
17669            None
17670        }
17671    }
17672
17673    pub fn render_crease_trailer(
17674        &self,
17675        buffer_row: MultiBufferRow,
17676        window: &mut Window,
17677        cx: &mut App,
17678    ) -> Option<AnyElement> {
17679        let folded = self.is_line_folded(buffer_row);
17680        if let Crease::Inline { render_trailer, .. } = self
17681            .crease_snapshot
17682            .query_row(buffer_row, &self.buffer_snapshot)?
17683        {
17684            let render_trailer = render_trailer.as_ref()?;
17685            Some(render_trailer(buffer_row, folded, window, cx))
17686        } else {
17687            None
17688        }
17689    }
17690}
17691
17692impl Deref for EditorSnapshot {
17693    type Target = DisplaySnapshot;
17694
17695    fn deref(&self) -> &Self::Target {
17696        &self.display_snapshot
17697    }
17698}
17699
17700#[derive(Clone, Debug, PartialEq, Eq)]
17701pub enum EditorEvent {
17702    InputIgnored {
17703        text: Arc<str>,
17704    },
17705    InputHandled {
17706        utf16_range_to_replace: Option<Range<isize>>,
17707        text: Arc<str>,
17708    },
17709    ExcerptsAdded {
17710        buffer: Entity<Buffer>,
17711        predecessor: ExcerptId,
17712        excerpts: Vec<(ExcerptId, ExcerptRange<language::Anchor>)>,
17713    },
17714    ExcerptsRemoved {
17715        ids: Vec<ExcerptId>,
17716    },
17717    BufferFoldToggled {
17718        ids: Vec<ExcerptId>,
17719        folded: bool,
17720    },
17721    ExcerptsEdited {
17722        ids: Vec<ExcerptId>,
17723    },
17724    ExcerptsExpanded {
17725        ids: Vec<ExcerptId>,
17726    },
17727    BufferEdited,
17728    Edited {
17729        transaction_id: clock::Lamport,
17730    },
17731    Reparsed(BufferId),
17732    Focused,
17733    FocusedIn,
17734    Blurred,
17735    DirtyChanged,
17736    Saved,
17737    TitleChanged,
17738    DiffBaseChanged,
17739    SelectionsChanged {
17740        local: bool,
17741    },
17742    ScrollPositionChanged {
17743        local: bool,
17744        autoscroll: bool,
17745    },
17746    Closed,
17747    TransactionUndone {
17748        transaction_id: clock::Lamport,
17749    },
17750    TransactionBegun {
17751        transaction_id: clock::Lamport,
17752    },
17753    Reloaded,
17754    CursorShapeChanged,
17755}
17756
17757impl EventEmitter<EditorEvent> for Editor {}
17758
17759impl Focusable for Editor {
17760    fn focus_handle(&self, _cx: &App) -> FocusHandle {
17761        self.focus_handle.clone()
17762    }
17763}
17764
17765impl Render for Editor {
17766    fn render(&mut self, _: &mut Window, cx: &mut Context<'_, Self>) -> impl IntoElement {
17767        let settings = ThemeSettings::get_global(cx);
17768
17769        let mut text_style = match self.mode {
17770            EditorMode::SingleLine { .. } | EditorMode::AutoHeight { .. } => TextStyle {
17771                color: cx.theme().colors().editor_foreground,
17772                font_family: settings.ui_font.family.clone(),
17773                font_features: settings.ui_font.features.clone(),
17774                font_fallbacks: settings.ui_font.fallbacks.clone(),
17775                font_size: rems(0.875).into(),
17776                font_weight: settings.ui_font.weight,
17777                line_height: relative(settings.buffer_line_height.value()),
17778                ..Default::default()
17779            },
17780            EditorMode::Full => TextStyle {
17781                color: cx.theme().colors().editor_foreground,
17782                font_family: settings.buffer_font.family.clone(),
17783                font_features: settings.buffer_font.features.clone(),
17784                font_fallbacks: settings.buffer_font.fallbacks.clone(),
17785                font_size: settings.buffer_font_size(cx).into(),
17786                font_weight: settings.buffer_font.weight,
17787                line_height: relative(settings.buffer_line_height.value()),
17788                ..Default::default()
17789            },
17790        };
17791        if let Some(text_style_refinement) = &self.text_style_refinement {
17792            text_style.refine(text_style_refinement)
17793        }
17794
17795        let background = match self.mode {
17796            EditorMode::SingleLine { .. } => cx.theme().system().transparent,
17797            EditorMode::AutoHeight { max_lines: _ } => cx.theme().system().transparent,
17798            EditorMode::Full => cx.theme().colors().editor_background,
17799        };
17800
17801        EditorElement::new(
17802            &cx.entity(),
17803            EditorStyle {
17804                background,
17805                local_player: cx.theme().players().local(),
17806                text: text_style,
17807                scrollbar_width: EditorElement::SCROLLBAR_WIDTH,
17808                syntax: cx.theme().syntax().clone(),
17809                status: cx.theme().status().clone(),
17810                inlay_hints_style: make_inlay_hints_style(cx),
17811                inline_completion_styles: make_suggestion_styles(cx),
17812                unnecessary_code_fade: ThemeSettings::get_global(cx).unnecessary_code_fade,
17813            },
17814        )
17815    }
17816}
17817
17818impl EntityInputHandler for Editor {
17819    fn text_for_range(
17820        &mut self,
17821        range_utf16: Range<usize>,
17822        adjusted_range: &mut Option<Range<usize>>,
17823        _: &mut Window,
17824        cx: &mut Context<Self>,
17825    ) -> Option<String> {
17826        let snapshot = self.buffer.read(cx).read(cx);
17827        let start = snapshot.clip_offset_utf16(OffsetUtf16(range_utf16.start), Bias::Left);
17828        let end = snapshot.clip_offset_utf16(OffsetUtf16(range_utf16.end), Bias::Right);
17829        if (start.0..end.0) != range_utf16 {
17830            adjusted_range.replace(start.0..end.0);
17831        }
17832        Some(snapshot.text_for_range(start..end).collect())
17833    }
17834
17835    fn selected_text_range(
17836        &mut self,
17837        ignore_disabled_input: bool,
17838        _: &mut Window,
17839        cx: &mut Context<Self>,
17840    ) -> Option<UTF16Selection> {
17841        // Prevent the IME menu from appearing when holding down an alphabetic key
17842        // while input is disabled.
17843        if !ignore_disabled_input && !self.input_enabled {
17844            return None;
17845        }
17846
17847        let selection = self.selections.newest::<OffsetUtf16>(cx);
17848        let range = selection.range();
17849
17850        Some(UTF16Selection {
17851            range: range.start.0..range.end.0,
17852            reversed: selection.reversed,
17853        })
17854    }
17855
17856    fn marked_text_range(&self, _: &mut Window, cx: &mut Context<Self>) -> Option<Range<usize>> {
17857        let snapshot = self.buffer.read(cx).read(cx);
17858        let range = self.text_highlights::<InputComposition>(cx)?.1.first()?;
17859        Some(range.start.to_offset_utf16(&snapshot).0..range.end.to_offset_utf16(&snapshot).0)
17860    }
17861
17862    fn unmark_text(&mut self, _: &mut Window, cx: &mut Context<Self>) {
17863        self.clear_highlights::<InputComposition>(cx);
17864        self.ime_transaction.take();
17865    }
17866
17867    fn replace_text_in_range(
17868        &mut self,
17869        range_utf16: Option<Range<usize>>,
17870        text: &str,
17871        window: &mut Window,
17872        cx: &mut Context<Self>,
17873    ) {
17874        if !self.input_enabled {
17875            cx.emit(EditorEvent::InputIgnored { text: text.into() });
17876            return;
17877        }
17878
17879        self.transact(window, cx, |this, window, cx| {
17880            let new_selected_ranges = if let Some(range_utf16) = range_utf16 {
17881                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
17882                Some(this.selection_replacement_ranges(range_utf16, cx))
17883            } else {
17884                this.marked_text_ranges(cx)
17885            };
17886
17887            let range_to_replace = new_selected_ranges.as_ref().and_then(|ranges_to_replace| {
17888                let newest_selection_id = this.selections.newest_anchor().id;
17889                this.selections
17890                    .all::<OffsetUtf16>(cx)
17891                    .iter()
17892                    .zip(ranges_to_replace.iter())
17893                    .find_map(|(selection, range)| {
17894                        if selection.id == newest_selection_id {
17895                            Some(
17896                                (range.start.0 as isize - selection.head().0 as isize)
17897                                    ..(range.end.0 as isize - selection.head().0 as isize),
17898                            )
17899                        } else {
17900                            None
17901                        }
17902                    })
17903            });
17904
17905            cx.emit(EditorEvent::InputHandled {
17906                utf16_range_to_replace: range_to_replace,
17907                text: text.into(),
17908            });
17909
17910            if let Some(new_selected_ranges) = new_selected_ranges {
17911                this.change_selections(None, window, cx, |selections| {
17912                    selections.select_ranges(new_selected_ranges)
17913                });
17914                this.backspace(&Default::default(), window, cx);
17915            }
17916
17917            this.handle_input(text, window, cx);
17918        });
17919
17920        if let Some(transaction) = self.ime_transaction {
17921            self.buffer.update(cx, |buffer, cx| {
17922                buffer.group_until_transaction(transaction, cx);
17923            });
17924        }
17925
17926        self.unmark_text(window, cx);
17927    }
17928
17929    fn replace_and_mark_text_in_range(
17930        &mut self,
17931        range_utf16: Option<Range<usize>>,
17932        text: &str,
17933        new_selected_range_utf16: Option<Range<usize>>,
17934        window: &mut Window,
17935        cx: &mut Context<Self>,
17936    ) {
17937        if !self.input_enabled {
17938            return;
17939        }
17940
17941        let transaction = self.transact(window, cx, |this, window, cx| {
17942            let ranges_to_replace = if let Some(mut marked_ranges) = this.marked_text_ranges(cx) {
17943                let snapshot = this.buffer.read(cx).read(cx);
17944                if let Some(relative_range_utf16) = range_utf16.as_ref() {
17945                    for marked_range in &mut marked_ranges {
17946                        marked_range.end.0 = marked_range.start.0 + relative_range_utf16.end;
17947                        marked_range.start.0 += relative_range_utf16.start;
17948                        marked_range.start =
17949                            snapshot.clip_offset_utf16(marked_range.start, Bias::Left);
17950                        marked_range.end =
17951                            snapshot.clip_offset_utf16(marked_range.end, Bias::Right);
17952                    }
17953                }
17954                Some(marked_ranges)
17955            } else if let Some(range_utf16) = range_utf16 {
17956                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
17957                Some(this.selection_replacement_ranges(range_utf16, cx))
17958            } else {
17959                None
17960            };
17961
17962            let range_to_replace = ranges_to_replace.as_ref().and_then(|ranges_to_replace| {
17963                let newest_selection_id = this.selections.newest_anchor().id;
17964                this.selections
17965                    .all::<OffsetUtf16>(cx)
17966                    .iter()
17967                    .zip(ranges_to_replace.iter())
17968                    .find_map(|(selection, range)| {
17969                        if selection.id == newest_selection_id {
17970                            Some(
17971                                (range.start.0 as isize - selection.head().0 as isize)
17972                                    ..(range.end.0 as isize - selection.head().0 as isize),
17973                            )
17974                        } else {
17975                            None
17976                        }
17977                    })
17978            });
17979
17980            cx.emit(EditorEvent::InputHandled {
17981                utf16_range_to_replace: range_to_replace,
17982                text: text.into(),
17983            });
17984
17985            if let Some(ranges) = ranges_to_replace {
17986                this.change_selections(None, window, cx, |s| s.select_ranges(ranges));
17987            }
17988
17989            let marked_ranges = {
17990                let snapshot = this.buffer.read(cx).read(cx);
17991                this.selections
17992                    .disjoint_anchors()
17993                    .iter()
17994                    .map(|selection| {
17995                        selection.start.bias_left(&snapshot)..selection.end.bias_right(&snapshot)
17996                    })
17997                    .collect::<Vec<_>>()
17998            };
17999
18000            if text.is_empty() {
18001                this.unmark_text(window, cx);
18002            } else {
18003                this.highlight_text::<InputComposition>(
18004                    marked_ranges.clone(),
18005                    HighlightStyle {
18006                        underline: Some(UnderlineStyle {
18007                            thickness: px(1.),
18008                            color: None,
18009                            wavy: false,
18010                        }),
18011                        ..Default::default()
18012                    },
18013                    cx,
18014                );
18015            }
18016
18017            // Disable auto-closing when composing text (i.e. typing a `"` on a Brazilian keyboard)
18018            let use_autoclose = this.use_autoclose;
18019            let use_auto_surround = this.use_auto_surround;
18020            this.set_use_autoclose(false);
18021            this.set_use_auto_surround(false);
18022            this.handle_input(text, window, cx);
18023            this.set_use_autoclose(use_autoclose);
18024            this.set_use_auto_surround(use_auto_surround);
18025
18026            if let Some(new_selected_range) = new_selected_range_utf16 {
18027                let snapshot = this.buffer.read(cx).read(cx);
18028                let new_selected_ranges = marked_ranges
18029                    .into_iter()
18030                    .map(|marked_range| {
18031                        let insertion_start = marked_range.start.to_offset_utf16(&snapshot).0;
18032                        let new_start = OffsetUtf16(new_selected_range.start + insertion_start);
18033                        let new_end = OffsetUtf16(new_selected_range.end + insertion_start);
18034                        snapshot.clip_offset_utf16(new_start, Bias::Left)
18035                            ..snapshot.clip_offset_utf16(new_end, Bias::Right)
18036                    })
18037                    .collect::<Vec<_>>();
18038
18039                drop(snapshot);
18040                this.change_selections(None, window, cx, |selections| {
18041                    selections.select_ranges(new_selected_ranges)
18042                });
18043            }
18044        });
18045
18046        self.ime_transaction = self.ime_transaction.or(transaction);
18047        if let Some(transaction) = self.ime_transaction {
18048            self.buffer.update(cx, |buffer, cx| {
18049                buffer.group_until_transaction(transaction, cx);
18050            });
18051        }
18052
18053        if self.text_highlights::<InputComposition>(cx).is_none() {
18054            self.ime_transaction.take();
18055        }
18056    }
18057
18058    fn bounds_for_range(
18059        &mut self,
18060        range_utf16: Range<usize>,
18061        element_bounds: gpui::Bounds<Pixels>,
18062        window: &mut Window,
18063        cx: &mut Context<Self>,
18064    ) -> Option<gpui::Bounds<Pixels>> {
18065        let text_layout_details = self.text_layout_details(window);
18066        let gpui::Size {
18067            width: em_width,
18068            height: line_height,
18069        } = self.character_size(window);
18070
18071        let snapshot = self.snapshot(window, cx);
18072        let scroll_position = snapshot.scroll_position();
18073        let scroll_left = scroll_position.x * em_width;
18074
18075        let start = OffsetUtf16(range_utf16.start).to_display_point(&snapshot);
18076        let x = snapshot.x_for_display_point(start, &text_layout_details) - scroll_left
18077            + self.gutter_dimensions.width
18078            + self.gutter_dimensions.margin;
18079        let y = line_height * (start.row().as_f32() - scroll_position.y);
18080
18081        Some(Bounds {
18082            origin: element_bounds.origin + point(x, y),
18083            size: size(em_width, line_height),
18084        })
18085    }
18086
18087    fn character_index_for_point(
18088        &mut self,
18089        point: gpui::Point<Pixels>,
18090        _window: &mut Window,
18091        _cx: &mut Context<Self>,
18092    ) -> Option<usize> {
18093        let position_map = self.last_position_map.as_ref()?;
18094        if !position_map.text_hitbox.contains(&point) {
18095            return None;
18096        }
18097        let display_point = position_map.point_for_position(point).previous_valid;
18098        let anchor = position_map
18099            .snapshot
18100            .display_point_to_anchor(display_point, Bias::Left);
18101        let utf16_offset = anchor.to_offset_utf16(&position_map.snapshot.buffer_snapshot);
18102        Some(utf16_offset.0)
18103    }
18104}
18105
18106trait SelectionExt {
18107    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
18108    fn spanned_rows(
18109        &self,
18110        include_end_if_at_line_start: bool,
18111        map: &DisplaySnapshot,
18112    ) -> Range<MultiBufferRow>;
18113}
18114
18115impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
18116    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
18117        let start = self
18118            .start
18119            .to_point(&map.buffer_snapshot)
18120            .to_display_point(map);
18121        let end = self
18122            .end
18123            .to_point(&map.buffer_snapshot)
18124            .to_display_point(map);
18125        if self.reversed {
18126            end..start
18127        } else {
18128            start..end
18129        }
18130    }
18131
18132    fn spanned_rows(
18133        &self,
18134        include_end_if_at_line_start: bool,
18135        map: &DisplaySnapshot,
18136    ) -> Range<MultiBufferRow> {
18137        let start = self.start.to_point(&map.buffer_snapshot);
18138        let mut end = self.end.to_point(&map.buffer_snapshot);
18139        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
18140            end.row -= 1;
18141        }
18142
18143        let buffer_start = map.prev_line_boundary(start).0;
18144        let buffer_end = map.next_line_boundary(end).0;
18145        MultiBufferRow(buffer_start.row)..MultiBufferRow(buffer_end.row + 1)
18146    }
18147}
18148
18149impl<T: InvalidationRegion> InvalidationStack<T> {
18150    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
18151    where
18152        S: Clone + ToOffset,
18153    {
18154        while let Some(region) = self.last() {
18155            let all_selections_inside_invalidation_ranges =
18156                if selections.len() == region.ranges().len() {
18157                    selections
18158                        .iter()
18159                        .zip(region.ranges().iter().map(|r| r.to_offset(buffer)))
18160                        .all(|(selection, invalidation_range)| {
18161                            let head = selection.head().to_offset(buffer);
18162                            invalidation_range.start <= head && invalidation_range.end >= head
18163                        })
18164                } else {
18165                    false
18166                };
18167
18168            if all_selections_inside_invalidation_ranges {
18169                break;
18170            } else {
18171                self.pop();
18172            }
18173        }
18174    }
18175}
18176
18177impl<T> Default for InvalidationStack<T> {
18178    fn default() -> Self {
18179        Self(Default::default())
18180    }
18181}
18182
18183impl<T> Deref for InvalidationStack<T> {
18184    type Target = Vec<T>;
18185
18186    fn deref(&self) -> &Self::Target {
18187        &self.0
18188    }
18189}
18190
18191impl<T> DerefMut for InvalidationStack<T> {
18192    fn deref_mut(&mut self) -> &mut Self::Target {
18193        &mut self.0
18194    }
18195}
18196
18197impl InvalidationRegion for SnippetState {
18198    fn ranges(&self) -> &[Range<Anchor>] {
18199        &self.ranges[self.active_index]
18200    }
18201}
18202
18203pub fn diagnostic_block_renderer(
18204    diagnostic: Diagnostic,
18205    max_message_rows: Option<u8>,
18206    allow_closing: bool,
18207) -> RenderBlock {
18208    let (text_without_backticks, code_ranges) =
18209        highlight_diagnostic_message(&diagnostic, max_message_rows);
18210
18211    Arc::new(move |cx: &mut BlockContext| {
18212        let group_id: SharedString = cx.block_id.to_string().into();
18213
18214        let mut text_style = cx.window.text_style().clone();
18215        text_style.color = diagnostic_style(diagnostic.severity, cx.theme().status());
18216        let theme_settings = ThemeSettings::get_global(cx);
18217        text_style.font_family = theme_settings.buffer_font.family.clone();
18218        text_style.font_style = theme_settings.buffer_font.style;
18219        text_style.font_features = theme_settings.buffer_font.features.clone();
18220        text_style.font_weight = theme_settings.buffer_font.weight;
18221
18222        let multi_line_diagnostic = diagnostic.message.contains('\n');
18223
18224        let buttons = |diagnostic: &Diagnostic| {
18225            if multi_line_diagnostic {
18226                v_flex()
18227            } else {
18228                h_flex()
18229            }
18230            .when(allow_closing, |div| {
18231                div.children(diagnostic.is_primary.then(|| {
18232                    IconButton::new("close-block", IconName::XCircle)
18233                        .icon_color(Color::Muted)
18234                        .size(ButtonSize::Compact)
18235                        .style(ButtonStyle::Transparent)
18236                        .visible_on_hover(group_id.clone())
18237                        .on_click(move |_click, window, cx| {
18238                            window.dispatch_action(Box::new(Cancel), cx)
18239                        })
18240                        .tooltip(|window, cx| {
18241                            Tooltip::for_action("Close Diagnostics", &Cancel, window, cx)
18242                        })
18243                }))
18244            })
18245            .child(
18246                IconButton::new("copy-block", IconName::Copy)
18247                    .icon_color(Color::Muted)
18248                    .size(ButtonSize::Compact)
18249                    .style(ButtonStyle::Transparent)
18250                    .visible_on_hover(group_id.clone())
18251                    .on_click({
18252                        let message = diagnostic.message.clone();
18253                        move |_click, _, cx| {
18254                            cx.write_to_clipboard(ClipboardItem::new_string(message.clone()))
18255                        }
18256                    })
18257                    .tooltip(Tooltip::text("Copy diagnostic message")),
18258            )
18259        };
18260
18261        let icon_size = buttons(&diagnostic).into_any_element().layout_as_root(
18262            AvailableSpace::min_size(),
18263            cx.window,
18264            cx.app,
18265        );
18266
18267        h_flex()
18268            .id(cx.block_id)
18269            .group(group_id.clone())
18270            .relative()
18271            .size_full()
18272            .block_mouse_down()
18273            .pl(cx.gutter_dimensions.width)
18274            .w(cx.max_width - cx.gutter_dimensions.full_width())
18275            .child(
18276                div()
18277                    .flex()
18278                    .w(cx.anchor_x - cx.gutter_dimensions.width - icon_size.width)
18279                    .flex_shrink(),
18280            )
18281            .child(buttons(&diagnostic))
18282            .child(div().flex().flex_shrink_0().child(
18283                StyledText::new(text_without_backticks.clone()).with_default_highlights(
18284                    &text_style,
18285                    code_ranges.iter().map(|range| {
18286                        (
18287                            range.clone(),
18288                            HighlightStyle {
18289                                font_weight: Some(FontWeight::BOLD),
18290                                ..Default::default()
18291                            },
18292                        )
18293                    }),
18294                ),
18295            ))
18296            .into_any_element()
18297    })
18298}
18299
18300fn inline_completion_edit_text(
18301    current_snapshot: &BufferSnapshot,
18302    edits: &[(Range<Anchor>, String)],
18303    edit_preview: &EditPreview,
18304    include_deletions: bool,
18305    cx: &App,
18306) -> HighlightedText {
18307    let edits = edits
18308        .iter()
18309        .map(|(anchor, text)| {
18310            (
18311                anchor.start.text_anchor..anchor.end.text_anchor,
18312                text.clone(),
18313            )
18314        })
18315        .collect::<Vec<_>>();
18316
18317    edit_preview.highlight_edits(current_snapshot, &edits, include_deletions, cx)
18318}
18319
18320pub fn highlight_diagnostic_message(
18321    diagnostic: &Diagnostic,
18322    mut max_message_rows: Option<u8>,
18323) -> (SharedString, Vec<Range<usize>>) {
18324    let mut text_without_backticks = String::new();
18325    let mut code_ranges = Vec::new();
18326
18327    if let Some(source) = &diagnostic.source {
18328        text_without_backticks.push_str(source);
18329        code_ranges.push(0..source.len());
18330        text_without_backticks.push_str(": ");
18331    }
18332
18333    let mut prev_offset = 0;
18334    let mut in_code_block = false;
18335    let has_row_limit = max_message_rows.is_some();
18336    let mut newline_indices = diagnostic
18337        .message
18338        .match_indices('\n')
18339        .filter(|_| has_row_limit)
18340        .map(|(ix, _)| ix)
18341        .fuse()
18342        .peekable();
18343
18344    for (quote_ix, _) in diagnostic
18345        .message
18346        .match_indices('`')
18347        .chain([(diagnostic.message.len(), "")])
18348    {
18349        let mut first_newline_ix = None;
18350        let mut last_newline_ix = None;
18351        while let Some(newline_ix) = newline_indices.peek() {
18352            if *newline_ix < quote_ix {
18353                if first_newline_ix.is_none() {
18354                    first_newline_ix = Some(*newline_ix);
18355                }
18356                last_newline_ix = Some(*newline_ix);
18357
18358                if let Some(rows_left) = &mut max_message_rows {
18359                    if *rows_left == 0 {
18360                        break;
18361                    } else {
18362                        *rows_left -= 1;
18363                    }
18364                }
18365                let _ = newline_indices.next();
18366            } else {
18367                break;
18368            }
18369        }
18370        let prev_len = text_without_backticks.len();
18371        let new_text = &diagnostic.message[prev_offset..first_newline_ix.unwrap_or(quote_ix)];
18372        text_without_backticks.push_str(new_text);
18373        if in_code_block {
18374            code_ranges.push(prev_len..text_without_backticks.len());
18375        }
18376        prev_offset = last_newline_ix.unwrap_or(quote_ix) + 1;
18377        in_code_block = !in_code_block;
18378        if first_newline_ix.map_or(false, |newline_ix| newline_ix < quote_ix) {
18379            text_without_backticks.push_str("...");
18380            break;
18381        }
18382    }
18383
18384    (text_without_backticks.into(), code_ranges)
18385}
18386
18387fn diagnostic_style(severity: DiagnosticSeverity, colors: &StatusColors) -> Hsla {
18388    match severity {
18389        DiagnosticSeverity::ERROR => colors.error,
18390        DiagnosticSeverity::WARNING => colors.warning,
18391        DiagnosticSeverity::INFORMATION => colors.info,
18392        DiagnosticSeverity::HINT => colors.info,
18393        _ => colors.ignored,
18394    }
18395}
18396
18397pub fn styled_runs_for_code_label<'a>(
18398    label: &'a CodeLabel,
18399    syntax_theme: &'a theme::SyntaxTheme,
18400) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
18401    let fade_out = HighlightStyle {
18402        fade_out: Some(0.35),
18403        ..Default::default()
18404    };
18405
18406    let mut prev_end = label.filter_range.end;
18407    label
18408        .runs
18409        .iter()
18410        .enumerate()
18411        .flat_map(move |(ix, (range, highlight_id))| {
18412            let style = if let Some(style) = highlight_id.style(syntax_theme) {
18413                style
18414            } else {
18415                return Default::default();
18416            };
18417            let mut muted_style = style;
18418            muted_style.highlight(fade_out);
18419
18420            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
18421            if range.start >= label.filter_range.end {
18422                if range.start > prev_end {
18423                    runs.push((prev_end..range.start, fade_out));
18424                }
18425                runs.push((range.clone(), muted_style));
18426            } else if range.end <= label.filter_range.end {
18427                runs.push((range.clone(), style));
18428            } else {
18429                runs.push((range.start..label.filter_range.end, style));
18430                runs.push((label.filter_range.end..range.end, muted_style));
18431            }
18432            prev_end = cmp::max(prev_end, range.end);
18433
18434            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
18435                runs.push((prev_end..label.text.len(), fade_out));
18436            }
18437
18438            runs
18439        })
18440}
18441
18442pub(crate) fn split_words(text: &str) -> impl std::iter::Iterator<Item = &str> + '_ {
18443    let mut prev_index = 0;
18444    let mut prev_codepoint: Option<char> = None;
18445    text.char_indices()
18446        .chain([(text.len(), '\0')])
18447        .filter_map(move |(index, codepoint)| {
18448            let prev_codepoint = prev_codepoint.replace(codepoint)?;
18449            let is_boundary = index == text.len()
18450                || !prev_codepoint.is_uppercase() && codepoint.is_uppercase()
18451                || !prev_codepoint.is_alphanumeric() && codepoint.is_alphanumeric();
18452            if is_boundary {
18453                let chunk = &text[prev_index..index];
18454                prev_index = index;
18455                Some(chunk)
18456            } else {
18457                None
18458            }
18459        })
18460}
18461
18462pub trait RangeToAnchorExt: Sized {
18463    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor>;
18464
18465    fn to_display_points(self, snapshot: &EditorSnapshot) -> Range<DisplayPoint> {
18466        let anchor_range = self.to_anchors(&snapshot.buffer_snapshot);
18467        anchor_range.start.to_display_point(snapshot)..anchor_range.end.to_display_point(snapshot)
18468    }
18469}
18470
18471impl<T: ToOffset> RangeToAnchorExt for Range<T> {
18472    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor> {
18473        let start_offset = self.start.to_offset(snapshot);
18474        let end_offset = self.end.to_offset(snapshot);
18475        if start_offset == end_offset {
18476            snapshot.anchor_before(start_offset)..snapshot.anchor_before(end_offset)
18477        } else {
18478            snapshot.anchor_after(self.start)..snapshot.anchor_before(self.end)
18479        }
18480    }
18481}
18482
18483pub trait RowExt {
18484    fn as_f32(&self) -> f32;
18485
18486    fn next_row(&self) -> Self;
18487
18488    fn previous_row(&self) -> Self;
18489
18490    fn minus(&self, other: Self) -> u32;
18491}
18492
18493impl RowExt for DisplayRow {
18494    fn as_f32(&self) -> f32 {
18495        self.0 as f32
18496    }
18497
18498    fn next_row(&self) -> Self {
18499        Self(self.0 + 1)
18500    }
18501
18502    fn previous_row(&self) -> Self {
18503        Self(self.0.saturating_sub(1))
18504    }
18505
18506    fn minus(&self, other: Self) -> u32 {
18507        self.0 - other.0
18508    }
18509}
18510
18511impl RowExt for MultiBufferRow {
18512    fn as_f32(&self) -> f32 {
18513        self.0 as f32
18514    }
18515
18516    fn next_row(&self) -> Self {
18517        Self(self.0 + 1)
18518    }
18519
18520    fn previous_row(&self) -> Self {
18521        Self(self.0.saturating_sub(1))
18522    }
18523
18524    fn minus(&self, other: Self) -> u32 {
18525        self.0 - other.0
18526    }
18527}
18528
18529trait RowRangeExt {
18530    type Row;
18531
18532    fn len(&self) -> usize;
18533
18534    fn iter_rows(&self) -> impl DoubleEndedIterator<Item = Self::Row>;
18535}
18536
18537impl RowRangeExt for Range<MultiBufferRow> {
18538    type Row = MultiBufferRow;
18539
18540    fn len(&self) -> usize {
18541        (self.end.0 - self.start.0) as usize
18542    }
18543
18544    fn iter_rows(&self) -> impl DoubleEndedIterator<Item = MultiBufferRow> {
18545        (self.start.0..self.end.0).map(MultiBufferRow)
18546    }
18547}
18548
18549impl RowRangeExt for Range<DisplayRow> {
18550    type Row = DisplayRow;
18551
18552    fn len(&self) -> usize {
18553        (self.end.0 - self.start.0) as usize
18554    }
18555
18556    fn iter_rows(&self) -> impl DoubleEndedIterator<Item = DisplayRow> {
18557        (self.start.0..self.end.0).map(DisplayRow)
18558    }
18559}
18560
18561/// If select range has more than one line, we
18562/// just point the cursor to range.start.
18563fn collapse_multiline_range(range: Range<Point>) -> Range<Point> {
18564    if range.start.row == range.end.row {
18565        range
18566    } else {
18567        range.start..range.start
18568    }
18569}
18570pub struct KillRing(ClipboardItem);
18571impl Global for KillRing {}
18572
18573const UPDATE_DEBOUNCE: Duration = Duration::from_millis(50);
18574
18575fn all_edits_insertions_or_deletions(
18576    edits: &Vec<(Range<Anchor>, String)>,
18577    snapshot: &MultiBufferSnapshot,
18578) -> bool {
18579    let mut all_insertions = true;
18580    let mut all_deletions = true;
18581
18582    for (range, new_text) in edits.iter() {
18583        let range_is_empty = range.to_offset(&snapshot).is_empty();
18584        let text_is_empty = new_text.is_empty();
18585
18586        if range_is_empty != text_is_empty {
18587            if range_is_empty {
18588                all_deletions = false;
18589            } else {
18590                all_insertions = false;
18591            }
18592        } else {
18593            return false;
18594        }
18595
18596        if !all_insertions && !all_deletions {
18597            return false;
18598        }
18599    }
18600    all_insertions || all_deletions
18601}
18602
18603struct MissingEditPredictionKeybindingTooltip;
18604
18605impl Render for MissingEditPredictionKeybindingTooltip {
18606    fn render(&mut self, window: &mut Window, cx: &mut Context<'_, Self>) -> impl IntoElement {
18607        ui::tooltip_container(window, cx, |container, _, cx| {
18608            container
18609                .flex_shrink_0()
18610                .max_w_80()
18611                .min_h(rems_from_px(124.))
18612                .justify_between()
18613                .child(
18614                    v_flex()
18615                        .flex_1()
18616                        .text_ui_sm(cx)
18617                        .child(Label::new("Conflict with Accept Keybinding"))
18618                        .child("Your keymap currently overrides the default accept keybinding. To continue, assign one keybinding for the `editor::AcceptEditPrediction` action.")
18619                )
18620                .child(
18621                    h_flex()
18622                        .pb_1()
18623                        .gap_1()
18624                        .items_end()
18625                        .w_full()
18626                        .child(Button::new("open-keymap", "Assign Keybinding").size(ButtonSize::Compact).on_click(|_ev, window, cx| {
18627                            window.dispatch_action(zed_actions::OpenKeymap.boxed_clone(), cx)
18628                        }))
18629                        .child(Button::new("see-docs", "See Docs").size(ButtonSize::Compact).on_click(|_ev, _window, cx| {
18630                            cx.open_url("https://zed.dev/docs/completions#edit-predictions-missing-keybinding");
18631                        })),
18632                )
18633        })
18634    }
18635}
18636
18637#[derive(Debug, Clone, Copy, PartialEq)]
18638pub struct LineHighlight {
18639    pub background: Background,
18640    pub border: Option<gpui::Hsla>,
18641}
18642
18643impl From<Hsla> for LineHighlight {
18644    fn from(hsla: Hsla) -> Self {
18645        Self {
18646            background: hsla.into(),
18647            border: None,
18648        }
18649    }
18650}
18651
18652impl From<Background> for LineHighlight {
18653    fn from(background: Background) -> Self {
18654        Self {
18655            background,
18656            border: None,
18657        }
18658    }
18659}