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    },
  105    point_from_lsp, text_diff_with_options, AutoindentMode, BracketMatch, BracketPair, Buffer,
  106    Capability, CharKind, CodeLabel, CursorShape, Diagnostic, DiffOptions, EditPredictionsMode,
  107    EditPreview, HighlightedText, IndentKind, IndentSize, Language, OffsetRangeExt, Point,
  108    Selection, SelectionGoal, TextObject, TransactionId, TreeSitterOptions,
  109};
  110use language::{point_to_lsp, BufferRow, CharClassifier, Runnable, RunnableRange};
  111use linked_editing_ranges::refresh_linked_ranges;
  112use mouse_context_menu::MouseContextMenu;
  113use persistence::DB;
  114pub use proposed_changes_editor::{
  115    ProposedChangeLocation, ProposedChangesEditor, ProposedChangesEditorToolbar,
  116};
  117use smallvec::smallvec;
  118use std::iter::Peekable;
  119use task::{ResolvedTask, TaskTemplate, TaskVariables};
  120
  121use hover_links::{find_file, HoverLink, HoveredLinkState, InlayHighlight};
  122pub use lsp::CompletionContext;
  123use lsp::{
  124    CodeActionKind, CompletionItemKind, CompletionTriggerKind, DiagnosticSeverity,
  125    InsertTextFormat, LanguageServerId, LanguageServerName,
  126};
  127
  128use language::BufferSnapshot;
  129use movement::TextLayoutDetails;
  130pub use multi_buffer::{
  131    Anchor, AnchorRangeExt, ExcerptId, ExcerptRange, MultiBuffer, MultiBufferSnapshot, RowInfo,
  132    ToOffset, ToPoint,
  133};
  134use multi_buffer::{
  135    ExcerptInfo, ExpandExcerptDirection, MultiBufferDiffHunk, MultiBufferPoint, MultiBufferRow,
  136    MultiOrSingleBufferOffsetRange, ToOffsetUtf16,
  137};
  138use project::{
  139    lsp_store::{CompletionDocumentation, FormatTrigger, LspFormatTarget, OpenLspBufferHandle},
  140    project_settings::{GitGutterSetting, ProjectSettings},
  141    CodeAction, Completion, CompletionIntent, CompletionSource, DocumentHighlight, InlayHint,
  142    Location, LocationLink, PrepareRenameResponse, Project, ProjectItem, ProjectTransaction,
  143    TaskSourceKind,
  144};
  145use rand::prelude::*;
  146use rpc::{proto::*, ErrorExt};
  147use scroll::{Autoscroll, OngoingScroll, ScrollAnchor, ScrollManager, ScrollbarAutoHide};
  148use selections_collection::{
  149    resolve_selections, MutableSelectionsCollection, SelectionsCollection,
  150};
  151use serde::{Deserialize, Serialize};
  152use settings::{update_settings_file, Settings, SettingsLocation, SettingsStore};
  153use smallvec::SmallVec;
  154use snippet::Snippet;
  155use std::{
  156    any::TypeId,
  157    borrow::Cow,
  158    cell::RefCell,
  159    cmp::{self, Ordering, Reverse},
  160    mem,
  161    num::NonZeroU32,
  162    ops::{ControlFlow, Deref, DerefMut, Not as _, Range, RangeInclusive},
  163    path::{Path, PathBuf},
  164    rc::Rc,
  165    sync::Arc,
  166    time::{Duration, Instant},
  167};
  168pub use sum_tree::Bias;
  169use sum_tree::TreeMap;
  170use text::{BufferId, OffsetUtf16, Rope};
  171use theme::{
  172    observe_buffer_font_size_adjustment, ActiveTheme, PlayerColor, StatusColors, SyntaxTheme,
  173    ThemeColors, ThemeSettings,
  174};
  175use ui::{
  176    h_flex, prelude::*, ButtonSize, ButtonStyle, Disclosure, IconButton, IconName, IconSize, Key,
  177    Tooltip,
  178};
  179use util::{defer, maybe, post_inc, RangeExt, ResultExt, TryFutureExt};
  180use workspace::{
  181    item::{ItemHandle, PreviewTabsSettings},
  182    ItemId, RestoreOnStartupBehavior,
  183};
  184use workspace::{
  185    notifications::{DetachAndPromptErr, NotificationId, NotifyTaskExt},
  186    WorkspaceSettings,
  187};
  188use workspace::{
  189    searchable::SearchEvent, ItemNavHistory, SplitDirection, ViewId, Workspace, WorkspaceId,
  190};
  191use workspace::{Item as WorkspaceItem, OpenInTerminal, OpenTerminal, TabBarSettings, Toast};
  192
  193use crate::hover_links::{find_url, find_url_from_range};
  194use crate::signature_help::{SignatureHelpHiddenBy, SignatureHelpState};
  195
  196pub const FILE_HEADER_HEIGHT: u32 = 2;
  197pub const MULTI_BUFFER_EXCERPT_HEADER_HEIGHT: u32 = 1;
  198pub const MULTI_BUFFER_EXCERPT_FOOTER_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            false,
 1095            window,
 1096            cx,
 1097        )
 1098    }
 1099
 1100    pub fn multi_line(window: &mut Window, cx: &mut Context<Self>) -> Self {
 1101        let buffer = cx.new(|cx| Buffer::local("", cx));
 1102        let buffer = cx.new(|cx| MultiBuffer::singleton(buffer, cx));
 1103        Self::new(EditorMode::Full, buffer, None, false, window, cx)
 1104    }
 1105
 1106    pub fn auto_width(window: &mut Window, cx: &mut Context<Self>) -> Self {
 1107        let buffer = cx.new(|cx| Buffer::local("", cx));
 1108        let buffer = cx.new(|cx| MultiBuffer::singleton(buffer, cx));
 1109        Self::new(
 1110            EditorMode::SingleLine { auto_width: true },
 1111            buffer,
 1112            None,
 1113            false,
 1114            window,
 1115            cx,
 1116        )
 1117    }
 1118
 1119    pub fn auto_height(max_lines: usize, window: &mut Window, cx: &mut Context<Self>) -> Self {
 1120        let buffer = cx.new(|cx| Buffer::local("", cx));
 1121        let buffer = cx.new(|cx| MultiBuffer::singleton(buffer, cx));
 1122        Self::new(
 1123            EditorMode::AutoHeight { max_lines },
 1124            buffer,
 1125            None,
 1126            false,
 1127            window,
 1128            cx,
 1129        )
 1130    }
 1131
 1132    pub fn for_buffer(
 1133        buffer: Entity<Buffer>,
 1134        project: Option<Entity<Project>>,
 1135        window: &mut Window,
 1136        cx: &mut Context<Self>,
 1137    ) -> Self {
 1138        let buffer = cx.new(|cx| MultiBuffer::singleton(buffer, cx));
 1139        Self::new(EditorMode::Full, buffer, project, false, window, cx)
 1140    }
 1141
 1142    pub fn for_multibuffer(
 1143        buffer: Entity<MultiBuffer>,
 1144        project: Option<Entity<Project>>,
 1145        show_excerpt_controls: bool,
 1146        window: &mut Window,
 1147        cx: &mut Context<Self>,
 1148    ) -> Self {
 1149        Self::new(
 1150            EditorMode::Full,
 1151            buffer,
 1152            project,
 1153            show_excerpt_controls,
 1154            window,
 1155            cx,
 1156        )
 1157    }
 1158
 1159    pub fn clone(&self, window: &mut Window, cx: &mut Context<Self>) -> Self {
 1160        let show_excerpt_controls = self.display_map.read(cx).show_excerpt_controls();
 1161        let mut clone = Self::new(
 1162            self.mode,
 1163            self.buffer.clone(),
 1164            self.project.clone(),
 1165            show_excerpt_controls,
 1166            window,
 1167            cx,
 1168        );
 1169        self.display_map.update(cx, |display_map, cx| {
 1170            let snapshot = display_map.snapshot(cx);
 1171            clone.display_map.update(cx, |display_map, cx| {
 1172                display_map.set_state(&snapshot, cx);
 1173            });
 1174        });
 1175        clone.selections.clone_state(&self.selections);
 1176        clone.scroll_manager.clone_state(&self.scroll_manager);
 1177        clone.searchable = self.searchable;
 1178        clone
 1179    }
 1180
 1181    pub fn new(
 1182        mode: EditorMode,
 1183        buffer: Entity<MultiBuffer>,
 1184        project: Option<Entity<Project>>,
 1185        show_excerpt_controls: bool,
 1186        window: &mut Window,
 1187        cx: &mut Context<Self>,
 1188    ) -> Self {
 1189        let style = window.text_style();
 1190        let font_size = style.font_size.to_pixels(window.rem_size());
 1191        let editor = cx.entity().downgrade();
 1192        let fold_placeholder = FoldPlaceholder {
 1193            constrain_width: true,
 1194            render: Arc::new(move |fold_id, fold_range, cx| {
 1195                let editor = editor.clone();
 1196                div()
 1197                    .id(fold_id)
 1198                    .bg(cx.theme().colors().ghost_element_background)
 1199                    .hover(|style| style.bg(cx.theme().colors().ghost_element_hover))
 1200                    .active(|style| style.bg(cx.theme().colors().ghost_element_active))
 1201                    .rounded_xs()
 1202                    .size_full()
 1203                    .cursor_pointer()
 1204                    .child("")
 1205                    .on_mouse_down(MouseButton::Left, |_, _, cx| cx.stop_propagation())
 1206                    .on_click(move |_, _window, cx| {
 1207                        editor
 1208                            .update(cx, |editor, cx| {
 1209                                editor.unfold_ranges(
 1210                                    &[fold_range.start..fold_range.end],
 1211                                    true,
 1212                                    false,
 1213                                    cx,
 1214                                );
 1215                                cx.stop_propagation();
 1216                            })
 1217                            .ok();
 1218                    })
 1219                    .into_any()
 1220            }),
 1221            merge_adjacent: true,
 1222            ..Default::default()
 1223        };
 1224        let display_map = cx.new(|cx| {
 1225            DisplayMap::new(
 1226                buffer.clone(),
 1227                style.font(),
 1228                font_size,
 1229                None,
 1230                show_excerpt_controls,
 1231                FILE_HEADER_HEIGHT,
 1232                MULTI_BUFFER_EXCERPT_HEADER_HEIGHT,
 1233                MULTI_BUFFER_EXCERPT_FOOTER_HEIGHT,
 1234                fold_placeholder,
 1235                cx,
 1236            )
 1237        });
 1238
 1239        let selections = SelectionsCollection::new(display_map.clone(), buffer.clone());
 1240
 1241        let blink_manager = cx.new(|cx| BlinkManager::new(CURSOR_BLINK_INTERVAL, cx));
 1242
 1243        let soft_wrap_mode_override = matches!(mode, EditorMode::SingleLine { .. })
 1244            .then(|| language_settings::SoftWrap::None);
 1245
 1246        let mut project_subscriptions = Vec::new();
 1247        if mode == EditorMode::Full {
 1248            if let Some(project) = project.as_ref() {
 1249                project_subscriptions.push(cx.subscribe_in(
 1250                    project,
 1251                    window,
 1252                    |editor, _, event, window, cx| {
 1253                        if let project::Event::RefreshInlayHints = event {
 1254                            editor
 1255                                .refresh_inlay_hints(InlayHintRefreshReason::RefreshRequested, cx);
 1256                        } else if let project::Event::SnippetEdit(id, snippet_edits) = event {
 1257                            if let Some(buffer) = editor.buffer.read(cx).buffer(*id) {
 1258                                let focus_handle = editor.focus_handle(cx);
 1259                                if focus_handle.is_focused(window) {
 1260                                    let snapshot = buffer.read(cx).snapshot();
 1261                                    for (range, snippet) in snippet_edits {
 1262                                        let editor_range =
 1263                                            language::range_from_lsp(*range).to_offset(&snapshot);
 1264                                        editor
 1265                                            .insert_snippet(
 1266                                                &[editor_range],
 1267                                                snippet.clone(),
 1268                                                window,
 1269                                                cx,
 1270                                            )
 1271                                            .ok();
 1272                                    }
 1273                                }
 1274                            }
 1275                        }
 1276                    },
 1277                ));
 1278                if let Some(task_inventory) = project
 1279                    .read(cx)
 1280                    .task_store()
 1281                    .read(cx)
 1282                    .task_inventory()
 1283                    .cloned()
 1284                {
 1285                    project_subscriptions.push(cx.observe_in(
 1286                        &task_inventory,
 1287                        window,
 1288                        |editor, _, window, cx| {
 1289                            editor.tasks_update_task = Some(editor.refresh_runnables(window, cx));
 1290                        },
 1291                    ));
 1292                }
 1293            }
 1294        }
 1295
 1296        let buffer_snapshot = buffer.read(cx).snapshot(cx);
 1297
 1298        let inlay_hint_settings =
 1299            inlay_hint_settings(selections.newest_anchor().head(), &buffer_snapshot, cx);
 1300        let focus_handle = cx.focus_handle();
 1301        cx.on_focus(&focus_handle, window, Self::handle_focus)
 1302            .detach();
 1303        cx.on_focus_in(&focus_handle, window, Self::handle_focus_in)
 1304            .detach();
 1305        cx.on_focus_out(&focus_handle, window, Self::handle_focus_out)
 1306            .detach();
 1307        cx.on_blur(&focus_handle, window, Self::handle_blur)
 1308            .detach();
 1309
 1310        let show_indent_guides = if matches!(mode, EditorMode::SingleLine { .. }) {
 1311            Some(false)
 1312        } else {
 1313            None
 1314        };
 1315
 1316        let mut code_action_providers = Vec::new();
 1317        let mut load_uncommitted_diff = None;
 1318        if let Some(project) = project.clone() {
 1319            load_uncommitted_diff = Some(
 1320                get_uncommitted_diff_for_buffer(
 1321                    &project,
 1322                    buffer.read(cx).all_buffers(),
 1323                    buffer.clone(),
 1324                    cx,
 1325                )
 1326                .shared(),
 1327            );
 1328            code_action_providers.push(Rc::new(project) as Rc<_>);
 1329        }
 1330
 1331        let mut this = Self {
 1332            focus_handle,
 1333            show_cursor_when_unfocused: false,
 1334            last_focused_descendant: None,
 1335            buffer: buffer.clone(),
 1336            display_map: display_map.clone(),
 1337            selections,
 1338            scroll_manager: ScrollManager::new(cx),
 1339            columnar_selection_tail: None,
 1340            add_selections_state: None,
 1341            select_next_state: None,
 1342            select_prev_state: None,
 1343            selection_history: Default::default(),
 1344            autoclose_regions: Default::default(),
 1345            snippet_stack: Default::default(),
 1346            select_larger_syntax_node_stack: Vec::new(),
 1347            ime_transaction: Default::default(),
 1348            active_diagnostics: None,
 1349            show_inline_diagnostics: ProjectSettings::get_global(cx).diagnostics.inline.enabled,
 1350            inline_diagnostics_update: Task::ready(()),
 1351            inline_diagnostics: Vec::new(),
 1352            soft_wrap_mode_override,
 1353            hard_wrap: None,
 1354            completion_provider: project.clone().map(|project| Box::new(project) as _),
 1355            semantics_provider: project.clone().map(|project| Rc::new(project) as _),
 1356            collaboration_hub: project.clone().map(|project| Box::new(project) as _),
 1357            project,
 1358            blink_manager: blink_manager.clone(),
 1359            show_local_selections: true,
 1360            show_scrollbars: true,
 1361            mode,
 1362            show_breadcrumbs: EditorSettings::get_global(cx).toolbar.breadcrumbs,
 1363            show_gutter: mode == EditorMode::Full,
 1364            show_line_numbers: None,
 1365            use_relative_line_numbers: None,
 1366            show_git_diff_gutter: None,
 1367            show_code_actions: None,
 1368            show_runnables: None,
 1369            show_wrap_guides: None,
 1370            show_indent_guides,
 1371            placeholder_text: None,
 1372            highlight_order: 0,
 1373            highlighted_rows: HashMap::default(),
 1374            background_highlights: Default::default(),
 1375            gutter_highlights: TreeMap::default(),
 1376            scrollbar_marker_state: ScrollbarMarkerState::default(),
 1377            active_indent_guides_state: ActiveIndentGuidesState::default(),
 1378            nav_history: None,
 1379            context_menu: RefCell::new(None),
 1380            mouse_context_menu: None,
 1381            completion_tasks: Default::default(),
 1382            signature_help_state: SignatureHelpState::default(),
 1383            auto_signature_help: None,
 1384            find_all_references_task_sources: Vec::new(),
 1385            next_completion_id: 0,
 1386            next_inlay_id: 0,
 1387            code_action_providers,
 1388            available_code_actions: Default::default(),
 1389            code_actions_task: Default::default(),
 1390            selection_highlight_task: Default::default(),
 1391            document_highlights_task: Default::default(),
 1392            linked_editing_range_task: Default::default(),
 1393            pending_rename: Default::default(),
 1394            searchable: true,
 1395            cursor_shape: EditorSettings::get_global(cx)
 1396                .cursor_shape
 1397                .unwrap_or_default(),
 1398            current_line_highlight: None,
 1399            autoindent_mode: Some(AutoindentMode::EachLine),
 1400            collapse_matches: false,
 1401            workspace: None,
 1402            input_enabled: true,
 1403            use_modal_editing: mode == EditorMode::Full,
 1404            read_only: false,
 1405            use_autoclose: true,
 1406            use_auto_surround: true,
 1407            auto_replace_emoji_shortcode: false,
 1408            jsx_tag_auto_close_enabled_in_any_buffer: false,
 1409            leader_peer_id: None,
 1410            remote_id: None,
 1411            hover_state: Default::default(),
 1412            pending_mouse_down: None,
 1413            hovered_link_state: Default::default(),
 1414            edit_prediction_provider: None,
 1415            active_inline_completion: None,
 1416            stale_inline_completion_in_menu: None,
 1417            edit_prediction_preview: EditPredictionPreview::Inactive {
 1418                released_too_fast: false,
 1419            },
 1420            inline_diagnostics_enabled: mode == EditorMode::Full,
 1421            inlay_hint_cache: InlayHintCache::new(inlay_hint_settings),
 1422
 1423            gutter_hovered: false,
 1424            pixel_position_of_newest_cursor: None,
 1425            last_bounds: None,
 1426            last_position_map: None,
 1427            expect_bounds_change: None,
 1428            gutter_dimensions: GutterDimensions::default(),
 1429            style: None,
 1430            show_cursor_names: false,
 1431            hovered_cursors: Default::default(),
 1432            next_editor_action_id: EditorActionId::default(),
 1433            editor_actions: Rc::default(),
 1434            inline_completions_hidden_for_vim_mode: false,
 1435            show_inline_completions_override: None,
 1436            menu_inline_completions_policy: MenuInlineCompletionsPolicy::ByProvider,
 1437            edit_prediction_settings: EditPredictionSettings::Disabled,
 1438            edit_prediction_indent_conflict: false,
 1439            edit_prediction_requires_modifier_in_indent_conflict: true,
 1440            custom_context_menu: None,
 1441            show_git_blame_gutter: false,
 1442            show_git_blame_inline: false,
 1443            show_selection_menu: None,
 1444            show_git_blame_inline_delay_task: None,
 1445            git_blame_inline_tooltip: None,
 1446            git_blame_inline_enabled: ProjectSettings::get_global(cx).git.inline_blame_enabled(),
 1447            serialize_dirty_buffers: ProjectSettings::get_global(cx)
 1448                .session
 1449                .restore_unsaved_buffers,
 1450            blame: None,
 1451            blame_subscription: None,
 1452            tasks: Default::default(),
 1453            _subscriptions: vec![
 1454                cx.observe(&buffer, Self::on_buffer_changed),
 1455                cx.subscribe_in(&buffer, window, Self::on_buffer_event),
 1456                cx.observe_in(&display_map, window, Self::on_display_map_changed),
 1457                cx.observe(&blink_manager, |_, _, cx| cx.notify()),
 1458                cx.observe_global_in::<SettingsStore>(window, Self::settings_changed),
 1459                observe_buffer_font_size_adjustment(cx, |_, cx| cx.notify()),
 1460                cx.observe_window_activation(window, |editor, window, cx| {
 1461                    let active = window.is_window_active();
 1462                    editor.blink_manager.update(cx, |blink_manager, cx| {
 1463                        if active {
 1464                            blink_manager.enable(cx);
 1465                        } else {
 1466                            blink_manager.disable(cx);
 1467                        }
 1468                    });
 1469                }),
 1470            ],
 1471            tasks_update_task: None,
 1472            linked_edit_ranges: Default::default(),
 1473            in_project_search: false,
 1474            previous_search_ranges: None,
 1475            breadcrumb_header: None,
 1476            focused_block: None,
 1477            next_scroll_position: NextScrollCursorCenterTopBottom::default(),
 1478            addons: HashMap::default(),
 1479            registered_buffers: HashMap::default(),
 1480            _scroll_cursor_center_top_bottom_task: Task::ready(()),
 1481            selection_mark_mode: false,
 1482            toggle_fold_multiple_buffers: Task::ready(()),
 1483            serialize_selections: Task::ready(()),
 1484            text_style_refinement: None,
 1485            load_diff_task: load_uncommitted_diff,
 1486        };
 1487        this.tasks_update_task = Some(this.refresh_runnables(window, cx));
 1488        this._subscriptions.extend(project_subscriptions);
 1489
 1490        this.end_selection(window, cx);
 1491        this.scroll_manager.show_scrollbar(window, cx);
 1492        jsx_tag_auto_close::refresh_enabled_in_any_buffer(&mut this, &buffer, cx);
 1493
 1494        if mode == EditorMode::Full {
 1495            let should_auto_hide_scrollbars = cx.should_auto_hide_scrollbars();
 1496            cx.set_global(ScrollbarAutoHide(should_auto_hide_scrollbars));
 1497
 1498            if this.git_blame_inline_enabled {
 1499                this.git_blame_inline_enabled = true;
 1500                this.start_git_blame_inline(false, window, cx);
 1501            }
 1502
 1503            if let Some(buffer) = buffer.read(cx).as_singleton() {
 1504                if let Some(project) = this.project.as_ref() {
 1505                    let handle = project.update(cx, |project, cx| {
 1506                        project.register_buffer_with_language_servers(&buffer, cx)
 1507                    });
 1508                    this.registered_buffers
 1509                        .insert(buffer.read(cx).remote_id(), handle);
 1510                }
 1511            }
 1512        }
 1513
 1514        this.report_editor_event("Editor Opened", None, cx);
 1515        this
 1516    }
 1517
 1518    pub fn mouse_menu_is_focused(&self, window: &Window, cx: &App) -> bool {
 1519        self.mouse_context_menu
 1520            .as_ref()
 1521            .is_some_and(|menu| menu.context_menu.focus_handle(cx).is_focused(window))
 1522    }
 1523
 1524    fn key_context(&self, window: &Window, cx: &App) -> KeyContext {
 1525        self.key_context_internal(self.has_active_inline_completion(), window, cx)
 1526    }
 1527
 1528    fn key_context_internal(
 1529        &self,
 1530        has_active_edit_prediction: bool,
 1531        window: &Window,
 1532        cx: &App,
 1533    ) -> KeyContext {
 1534        let mut key_context = KeyContext::new_with_defaults();
 1535        key_context.add("Editor");
 1536        let mode = match self.mode {
 1537            EditorMode::SingleLine { .. } => "single_line",
 1538            EditorMode::AutoHeight { .. } => "auto_height",
 1539            EditorMode::Full => "full",
 1540        };
 1541
 1542        if EditorSettings::jupyter_enabled(cx) {
 1543            key_context.add("jupyter");
 1544        }
 1545
 1546        key_context.set("mode", mode);
 1547        if self.pending_rename.is_some() {
 1548            key_context.add("renaming");
 1549        }
 1550
 1551        match self.context_menu.borrow().as_ref() {
 1552            Some(CodeContextMenu::Completions(_)) => {
 1553                key_context.add("menu");
 1554                key_context.add("showing_completions");
 1555            }
 1556            Some(CodeContextMenu::CodeActions(_)) => {
 1557                key_context.add("menu");
 1558                key_context.add("showing_code_actions")
 1559            }
 1560            None => {}
 1561        }
 1562
 1563        // Disable vim contexts when a sub-editor (e.g. rename/inline assistant) is focused.
 1564        if !self.focus_handle(cx).contains_focused(window, cx)
 1565            || (self.is_focused(window) || self.mouse_menu_is_focused(window, cx))
 1566        {
 1567            for addon in self.addons.values() {
 1568                addon.extend_key_context(&mut key_context, cx)
 1569            }
 1570        }
 1571
 1572        if let Some(singleton_buffer) = self.buffer.read(cx).as_singleton() {
 1573            if let Some(extension) = singleton_buffer
 1574                .read(cx)
 1575                .file()
 1576                .and_then(|file| file.path().extension()?.to_str())
 1577            {
 1578                key_context.set("extension", extension.to_string());
 1579            }
 1580        } else {
 1581            key_context.add("multibuffer");
 1582        }
 1583
 1584        if has_active_edit_prediction {
 1585            if self.edit_prediction_in_conflict() {
 1586                key_context.add(EDIT_PREDICTION_CONFLICT_KEY_CONTEXT);
 1587            } else {
 1588                key_context.add(EDIT_PREDICTION_KEY_CONTEXT);
 1589                key_context.add("copilot_suggestion");
 1590            }
 1591        }
 1592
 1593        if self.selection_mark_mode {
 1594            key_context.add("selection_mode");
 1595        }
 1596
 1597        key_context
 1598    }
 1599
 1600    pub fn edit_prediction_in_conflict(&self) -> bool {
 1601        if !self.show_edit_predictions_in_menu() {
 1602            return false;
 1603        }
 1604
 1605        let showing_completions = self
 1606            .context_menu
 1607            .borrow()
 1608            .as_ref()
 1609            .map_or(false, |context| {
 1610                matches!(context, CodeContextMenu::Completions(_))
 1611            });
 1612
 1613        showing_completions
 1614            || self.edit_prediction_requires_modifier()
 1615            // Require modifier key when the cursor is on leading whitespace, to allow `tab`
 1616            // bindings to insert tab characters.
 1617            || (self.edit_prediction_requires_modifier_in_indent_conflict && self.edit_prediction_indent_conflict)
 1618    }
 1619
 1620    pub fn accept_edit_prediction_keybind(
 1621        &self,
 1622        window: &Window,
 1623        cx: &App,
 1624    ) -> AcceptEditPredictionBinding {
 1625        let key_context = self.key_context_internal(true, window, cx);
 1626        let in_conflict = self.edit_prediction_in_conflict();
 1627
 1628        AcceptEditPredictionBinding(
 1629            window
 1630                .bindings_for_action_in_context(&AcceptEditPrediction, key_context)
 1631                .into_iter()
 1632                .filter(|binding| {
 1633                    !in_conflict
 1634                        || binding
 1635                            .keystrokes()
 1636                            .first()
 1637                            .map_or(false, |keystroke| keystroke.modifiers.modified())
 1638                })
 1639                .rev()
 1640                .min_by_key(|binding| {
 1641                    binding
 1642                        .keystrokes()
 1643                        .first()
 1644                        .map_or(u8::MAX, |k| k.modifiers.number_of_modifiers())
 1645                }),
 1646        )
 1647    }
 1648
 1649    pub fn new_file(
 1650        workspace: &mut Workspace,
 1651        _: &workspace::NewFile,
 1652        window: &mut Window,
 1653        cx: &mut Context<Workspace>,
 1654    ) {
 1655        Self::new_in_workspace(workspace, window, cx).detach_and_prompt_err(
 1656            "Failed to create buffer",
 1657            window,
 1658            cx,
 1659            |e, _, _| match e.error_code() {
 1660                ErrorCode::RemoteUpgradeRequired => Some(format!(
 1661                "The remote instance of Zed does not support this yet. It must be upgraded to {}",
 1662                e.error_tag("required").unwrap_or("the latest version")
 1663            )),
 1664                _ => None,
 1665            },
 1666        );
 1667    }
 1668
 1669    pub fn new_in_workspace(
 1670        workspace: &mut Workspace,
 1671        window: &mut Window,
 1672        cx: &mut Context<Workspace>,
 1673    ) -> Task<Result<Entity<Editor>>> {
 1674        let project = workspace.project().clone();
 1675        let create = project.update(cx, |project, cx| project.create_buffer(cx));
 1676
 1677        cx.spawn_in(window, |workspace, mut cx| async move {
 1678            let buffer = create.await?;
 1679            workspace.update_in(&mut cx, |workspace, window, cx| {
 1680                let editor =
 1681                    cx.new(|cx| Editor::for_buffer(buffer, Some(project.clone()), window, cx));
 1682                workspace.add_item_to_active_pane(Box::new(editor.clone()), None, true, window, cx);
 1683                editor
 1684            })
 1685        })
 1686    }
 1687
 1688    fn new_file_vertical(
 1689        workspace: &mut Workspace,
 1690        _: &workspace::NewFileSplitVertical,
 1691        window: &mut Window,
 1692        cx: &mut Context<Workspace>,
 1693    ) {
 1694        Self::new_file_in_direction(workspace, SplitDirection::vertical(cx), window, cx)
 1695    }
 1696
 1697    fn new_file_horizontal(
 1698        workspace: &mut Workspace,
 1699        _: &workspace::NewFileSplitHorizontal,
 1700        window: &mut Window,
 1701        cx: &mut Context<Workspace>,
 1702    ) {
 1703        Self::new_file_in_direction(workspace, SplitDirection::horizontal(cx), window, cx)
 1704    }
 1705
 1706    fn new_file_in_direction(
 1707        workspace: &mut Workspace,
 1708        direction: SplitDirection,
 1709        window: &mut Window,
 1710        cx: &mut Context<Workspace>,
 1711    ) {
 1712        let project = workspace.project().clone();
 1713        let create = project.update(cx, |project, cx| project.create_buffer(cx));
 1714
 1715        cx.spawn_in(window, |workspace, mut cx| async move {
 1716            let buffer = create.await?;
 1717            workspace.update_in(&mut cx, move |workspace, window, cx| {
 1718                workspace.split_item(
 1719                    direction,
 1720                    Box::new(
 1721                        cx.new(|cx| Editor::for_buffer(buffer, Some(project.clone()), window, cx)),
 1722                    ),
 1723                    window,
 1724                    cx,
 1725                )
 1726            })?;
 1727            anyhow::Ok(())
 1728        })
 1729        .detach_and_prompt_err("Failed to create buffer", window, cx, |e, _, _| {
 1730            match e.error_code() {
 1731                ErrorCode::RemoteUpgradeRequired => Some(format!(
 1732                "The remote instance of Zed does not support this yet. It must be upgraded to {}",
 1733                e.error_tag("required").unwrap_or("the latest version")
 1734            )),
 1735                _ => None,
 1736            }
 1737        });
 1738    }
 1739
 1740    pub fn leader_peer_id(&self) -> Option<PeerId> {
 1741        self.leader_peer_id
 1742    }
 1743
 1744    pub fn buffer(&self) -> &Entity<MultiBuffer> {
 1745        &self.buffer
 1746    }
 1747
 1748    pub fn workspace(&self) -> Option<Entity<Workspace>> {
 1749        self.workspace.as_ref()?.0.upgrade()
 1750    }
 1751
 1752    pub fn title<'a>(&self, cx: &'a App) -> Cow<'a, str> {
 1753        self.buffer().read(cx).title(cx)
 1754    }
 1755
 1756    pub fn snapshot(&self, window: &mut Window, cx: &mut App) -> EditorSnapshot {
 1757        let git_blame_gutter_max_author_length = self
 1758            .render_git_blame_gutter(cx)
 1759            .then(|| {
 1760                if let Some(blame) = self.blame.as_ref() {
 1761                    let max_author_length =
 1762                        blame.update(cx, |blame, cx| blame.max_author_length(cx));
 1763                    Some(max_author_length)
 1764                } else {
 1765                    None
 1766                }
 1767            })
 1768            .flatten();
 1769
 1770        EditorSnapshot {
 1771            mode: self.mode,
 1772            show_gutter: self.show_gutter,
 1773            show_line_numbers: self.show_line_numbers,
 1774            show_git_diff_gutter: self.show_git_diff_gutter,
 1775            show_code_actions: self.show_code_actions,
 1776            show_runnables: self.show_runnables,
 1777            git_blame_gutter_max_author_length,
 1778            display_snapshot: self.display_map.update(cx, |map, cx| map.snapshot(cx)),
 1779            scroll_anchor: self.scroll_manager.anchor(),
 1780            ongoing_scroll: self.scroll_manager.ongoing_scroll(),
 1781            placeholder_text: self.placeholder_text.clone(),
 1782            is_focused: self.focus_handle.is_focused(window),
 1783            current_line_highlight: self
 1784                .current_line_highlight
 1785                .unwrap_or_else(|| EditorSettings::get_global(cx).current_line_highlight),
 1786            gutter_hovered: self.gutter_hovered,
 1787        }
 1788    }
 1789
 1790    pub fn language_at<T: ToOffset>(&self, point: T, cx: &App) -> Option<Arc<Language>> {
 1791        self.buffer.read(cx).language_at(point, cx)
 1792    }
 1793
 1794    pub fn file_at<T: ToOffset>(&self, point: T, cx: &App) -> Option<Arc<dyn language::File>> {
 1795        self.buffer.read(cx).read(cx).file_at(point).cloned()
 1796    }
 1797
 1798    pub fn active_excerpt(
 1799        &self,
 1800        cx: &App,
 1801    ) -> Option<(ExcerptId, Entity<Buffer>, Range<text::Anchor>)> {
 1802        self.buffer
 1803            .read(cx)
 1804            .excerpt_containing(self.selections.newest_anchor().head(), cx)
 1805    }
 1806
 1807    pub fn mode(&self) -> EditorMode {
 1808        self.mode
 1809    }
 1810
 1811    pub fn collaboration_hub(&self) -> Option<&dyn CollaborationHub> {
 1812        self.collaboration_hub.as_deref()
 1813    }
 1814
 1815    pub fn set_collaboration_hub(&mut self, hub: Box<dyn CollaborationHub>) {
 1816        self.collaboration_hub = Some(hub);
 1817    }
 1818
 1819    pub fn set_in_project_search(&mut self, in_project_search: bool) {
 1820        self.in_project_search = in_project_search;
 1821    }
 1822
 1823    pub fn set_custom_context_menu(
 1824        &mut self,
 1825        f: impl 'static
 1826            + Fn(
 1827                &mut Self,
 1828                DisplayPoint,
 1829                &mut Window,
 1830                &mut Context<Self>,
 1831            ) -> Option<Entity<ui::ContextMenu>>,
 1832    ) {
 1833        self.custom_context_menu = Some(Box::new(f))
 1834    }
 1835
 1836    pub fn set_completion_provider(&mut self, provider: Option<Box<dyn CompletionProvider>>) {
 1837        self.completion_provider = provider;
 1838    }
 1839
 1840    pub fn semantics_provider(&self) -> Option<Rc<dyn SemanticsProvider>> {
 1841        self.semantics_provider.clone()
 1842    }
 1843
 1844    pub fn set_semantics_provider(&mut self, provider: Option<Rc<dyn SemanticsProvider>>) {
 1845        self.semantics_provider = provider;
 1846    }
 1847
 1848    pub fn set_edit_prediction_provider<T>(
 1849        &mut self,
 1850        provider: Option<Entity<T>>,
 1851        window: &mut Window,
 1852        cx: &mut Context<Self>,
 1853    ) where
 1854        T: EditPredictionProvider,
 1855    {
 1856        self.edit_prediction_provider =
 1857            provider.map(|provider| RegisteredInlineCompletionProvider {
 1858                _subscription: cx.observe_in(&provider, window, |this, _, window, cx| {
 1859                    if this.focus_handle.is_focused(window) {
 1860                        this.update_visible_inline_completion(window, cx);
 1861                    }
 1862                }),
 1863                provider: Arc::new(provider),
 1864            });
 1865        self.update_edit_prediction_settings(cx);
 1866        self.refresh_inline_completion(false, false, window, cx);
 1867    }
 1868
 1869    pub fn placeholder_text(&self) -> Option<&str> {
 1870        self.placeholder_text.as_deref()
 1871    }
 1872
 1873    pub fn set_placeholder_text(
 1874        &mut self,
 1875        placeholder_text: impl Into<Arc<str>>,
 1876        cx: &mut Context<Self>,
 1877    ) {
 1878        let placeholder_text = Some(placeholder_text.into());
 1879        if self.placeholder_text != placeholder_text {
 1880            self.placeholder_text = placeholder_text;
 1881            cx.notify();
 1882        }
 1883    }
 1884
 1885    pub fn set_cursor_shape(&mut self, cursor_shape: CursorShape, cx: &mut Context<Self>) {
 1886        self.cursor_shape = cursor_shape;
 1887
 1888        // Disrupt blink for immediate user feedback that the cursor shape has changed
 1889        self.blink_manager.update(cx, BlinkManager::show_cursor);
 1890
 1891        cx.notify();
 1892    }
 1893
 1894    pub fn set_current_line_highlight(
 1895        &mut self,
 1896        current_line_highlight: Option<CurrentLineHighlight>,
 1897    ) {
 1898        self.current_line_highlight = current_line_highlight;
 1899    }
 1900
 1901    pub fn set_collapse_matches(&mut self, collapse_matches: bool) {
 1902        self.collapse_matches = collapse_matches;
 1903    }
 1904
 1905    fn register_buffers_with_language_servers(&mut self, cx: &mut Context<Self>) {
 1906        let buffers = self.buffer.read(cx).all_buffers();
 1907        let Some(project) = self.project.as_ref() else {
 1908            return;
 1909        };
 1910        project.update(cx, |project, cx| {
 1911            for buffer in buffers {
 1912                self.registered_buffers
 1913                    .entry(buffer.read(cx).remote_id())
 1914                    .or_insert_with(|| project.register_buffer_with_language_servers(&buffer, cx));
 1915            }
 1916        })
 1917    }
 1918
 1919    pub fn range_for_match<T: std::marker::Copy>(&self, range: &Range<T>) -> Range<T> {
 1920        if self.collapse_matches {
 1921            return range.start..range.start;
 1922        }
 1923        range.clone()
 1924    }
 1925
 1926    pub fn set_clip_at_line_ends(&mut self, clip: bool, cx: &mut Context<Self>) {
 1927        if self.display_map.read(cx).clip_at_line_ends != clip {
 1928            self.display_map
 1929                .update(cx, |map, _| map.clip_at_line_ends = clip);
 1930        }
 1931    }
 1932
 1933    pub fn set_input_enabled(&mut self, input_enabled: bool) {
 1934        self.input_enabled = input_enabled;
 1935    }
 1936
 1937    pub fn set_inline_completions_hidden_for_vim_mode(
 1938        &mut self,
 1939        hidden: bool,
 1940        window: &mut Window,
 1941        cx: &mut Context<Self>,
 1942    ) {
 1943        if hidden != self.inline_completions_hidden_for_vim_mode {
 1944            self.inline_completions_hidden_for_vim_mode = hidden;
 1945            if hidden {
 1946                self.update_visible_inline_completion(window, cx);
 1947            } else {
 1948                self.refresh_inline_completion(true, false, window, cx);
 1949            }
 1950        }
 1951    }
 1952
 1953    pub fn set_menu_inline_completions_policy(&mut self, value: MenuInlineCompletionsPolicy) {
 1954        self.menu_inline_completions_policy = value;
 1955    }
 1956
 1957    pub fn set_autoindent(&mut self, autoindent: bool) {
 1958        if autoindent {
 1959            self.autoindent_mode = Some(AutoindentMode::EachLine);
 1960        } else {
 1961            self.autoindent_mode = None;
 1962        }
 1963    }
 1964
 1965    pub fn read_only(&self, cx: &App) -> bool {
 1966        self.read_only || self.buffer.read(cx).read_only()
 1967    }
 1968
 1969    pub fn set_read_only(&mut self, read_only: bool) {
 1970        self.read_only = read_only;
 1971    }
 1972
 1973    pub fn set_use_autoclose(&mut self, autoclose: bool) {
 1974        self.use_autoclose = autoclose;
 1975    }
 1976
 1977    pub fn set_use_auto_surround(&mut self, auto_surround: bool) {
 1978        self.use_auto_surround = auto_surround;
 1979    }
 1980
 1981    pub fn set_auto_replace_emoji_shortcode(&mut self, auto_replace: bool) {
 1982        self.auto_replace_emoji_shortcode = auto_replace;
 1983    }
 1984
 1985    pub fn toggle_edit_predictions(
 1986        &mut self,
 1987        _: &ToggleEditPrediction,
 1988        window: &mut Window,
 1989        cx: &mut Context<Self>,
 1990    ) {
 1991        if self.show_inline_completions_override.is_some() {
 1992            self.set_show_edit_predictions(None, window, cx);
 1993        } else {
 1994            let show_edit_predictions = !self.edit_predictions_enabled();
 1995            self.set_show_edit_predictions(Some(show_edit_predictions), window, cx);
 1996        }
 1997    }
 1998
 1999    pub fn set_show_edit_predictions(
 2000        &mut self,
 2001        show_edit_predictions: Option<bool>,
 2002        window: &mut Window,
 2003        cx: &mut Context<Self>,
 2004    ) {
 2005        self.show_inline_completions_override = show_edit_predictions;
 2006        self.update_edit_prediction_settings(cx);
 2007
 2008        if let Some(false) = show_edit_predictions {
 2009            self.discard_inline_completion(false, cx);
 2010        } else {
 2011            self.refresh_inline_completion(false, true, window, cx);
 2012        }
 2013    }
 2014
 2015    fn inline_completions_disabled_in_scope(
 2016        &self,
 2017        buffer: &Entity<Buffer>,
 2018        buffer_position: language::Anchor,
 2019        cx: &App,
 2020    ) -> bool {
 2021        let snapshot = buffer.read(cx).snapshot();
 2022        let settings = snapshot.settings_at(buffer_position, cx);
 2023
 2024        let Some(scope) = snapshot.language_scope_at(buffer_position) else {
 2025            return false;
 2026        };
 2027
 2028        scope.override_name().map_or(false, |scope_name| {
 2029            settings
 2030                .edit_predictions_disabled_in
 2031                .iter()
 2032                .any(|s| s == scope_name)
 2033        })
 2034    }
 2035
 2036    pub fn set_use_modal_editing(&mut self, to: bool) {
 2037        self.use_modal_editing = to;
 2038    }
 2039
 2040    pub fn use_modal_editing(&self) -> bool {
 2041        self.use_modal_editing
 2042    }
 2043
 2044    fn selections_did_change(
 2045        &mut self,
 2046        local: bool,
 2047        old_cursor_position: &Anchor,
 2048        show_completions: bool,
 2049        window: &mut Window,
 2050        cx: &mut Context<Self>,
 2051    ) {
 2052        window.invalidate_character_coordinates();
 2053
 2054        // Copy selections to primary selection buffer
 2055        #[cfg(any(target_os = "linux", target_os = "freebsd"))]
 2056        if local {
 2057            let selections = self.selections.all::<usize>(cx);
 2058            let buffer_handle = self.buffer.read(cx).read(cx);
 2059
 2060            let mut text = String::new();
 2061            for (index, selection) in selections.iter().enumerate() {
 2062                let text_for_selection = buffer_handle
 2063                    .text_for_range(selection.start..selection.end)
 2064                    .collect::<String>();
 2065
 2066                text.push_str(&text_for_selection);
 2067                if index != selections.len() - 1 {
 2068                    text.push('\n');
 2069                }
 2070            }
 2071
 2072            if !text.is_empty() {
 2073                cx.write_to_primary(ClipboardItem::new_string(text));
 2074            }
 2075        }
 2076
 2077        if self.focus_handle.is_focused(window) && self.leader_peer_id.is_none() {
 2078            self.buffer.update(cx, |buffer, cx| {
 2079                buffer.set_active_selections(
 2080                    &self.selections.disjoint_anchors(),
 2081                    self.selections.line_mode,
 2082                    self.cursor_shape,
 2083                    cx,
 2084                )
 2085            });
 2086        }
 2087        let display_map = self
 2088            .display_map
 2089            .update(cx, |display_map, cx| display_map.snapshot(cx));
 2090        let buffer = &display_map.buffer_snapshot;
 2091        self.add_selections_state = None;
 2092        self.select_next_state = None;
 2093        self.select_prev_state = None;
 2094        self.select_larger_syntax_node_stack.clear();
 2095        self.invalidate_autoclose_regions(&self.selections.disjoint_anchors(), buffer);
 2096        self.snippet_stack
 2097            .invalidate(&self.selections.disjoint_anchors(), buffer);
 2098        self.take_rename(false, window, cx);
 2099
 2100        let new_cursor_position = self.selections.newest_anchor().head();
 2101
 2102        self.push_to_nav_history(
 2103            *old_cursor_position,
 2104            Some(new_cursor_position.to_point(buffer)),
 2105            cx,
 2106        );
 2107
 2108        if local {
 2109            let new_cursor_position = self.selections.newest_anchor().head();
 2110            let mut context_menu = self.context_menu.borrow_mut();
 2111            let completion_menu = match context_menu.as_ref() {
 2112                Some(CodeContextMenu::Completions(menu)) => Some(menu),
 2113                _ => {
 2114                    *context_menu = None;
 2115                    None
 2116                }
 2117            };
 2118            if let Some(buffer_id) = new_cursor_position.buffer_id {
 2119                if !self.registered_buffers.contains_key(&buffer_id) {
 2120                    if let Some(project) = self.project.as_ref() {
 2121                        project.update(cx, |project, cx| {
 2122                            let Some(buffer) = self.buffer.read(cx).buffer(buffer_id) else {
 2123                                return;
 2124                            };
 2125                            self.registered_buffers.insert(
 2126                                buffer_id,
 2127                                project.register_buffer_with_language_servers(&buffer, cx),
 2128                            );
 2129                        })
 2130                    }
 2131                }
 2132            }
 2133
 2134            if let Some(completion_menu) = completion_menu {
 2135                let cursor_position = new_cursor_position.to_offset(buffer);
 2136                let (word_range, kind) =
 2137                    buffer.surrounding_word(completion_menu.initial_position, true);
 2138                if kind == Some(CharKind::Word)
 2139                    && word_range.to_inclusive().contains(&cursor_position)
 2140                {
 2141                    let mut completion_menu = completion_menu.clone();
 2142                    drop(context_menu);
 2143
 2144                    let query = Self::completion_query(buffer, cursor_position);
 2145                    cx.spawn(move |this, mut cx| async move {
 2146                        completion_menu
 2147                            .filter(query.as_deref(), cx.background_executor().clone())
 2148                            .await;
 2149
 2150                        this.update(&mut cx, |this, cx| {
 2151                            let mut context_menu = this.context_menu.borrow_mut();
 2152                            let Some(CodeContextMenu::Completions(menu)) = context_menu.as_ref()
 2153                            else {
 2154                                return;
 2155                            };
 2156
 2157                            if menu.id > completion_menu.id {
 2158                                return;
 2159                            }
 2160
 2161                            *context_menu = Some(CodeContextMenu::Completions(completion_menu));
 2162                            drop(context_menu);
 2163                            cx.notify();
 2164                        })
 2165                    })
 2166                    .detach();
 2167
 2168                    if show_completions {
 2169                        self.show_completions(&ShowCompletions { trigger: None }, window, cx);
 2170                    }
 2171                } else {
 2172                    drop(context_menu);
 2173                    self.hide_context_menu(window, cx);
 2174                }
 2175            } else {
 2176                drop(context_menu);
 2177            }
 2178
 2179            hide_hover(self, cx);
 2180
 2181            if old_cursor_position.to_display_point(&display_map).row()
 2182                != new_cursor_position.to_display_point(&display_map).row()
 2183            {
 2184                self.available_code_actions.take();
 2185            }
 2186            self.refresh_code_actions(window, cx);
 2187            self.refresh_document_highlights(cx);
 2188            self.refresh_selected_text_highlights(window, cx);
 2189            refresh_matching_bracket_highlights(self, window, cx);
 2190            self.update_visible_inline_completion(window, cx);
 2191            self.edit_prediction_requires_modifier_in_indent_conflict = true;
 2192            linked_editing_ranges::refresh_linked_ranges(self, window, cx);
 2193            if self.git_blame_inline_enabled {
 2194                self.start_inline_blame_timer(window, cx);
 2195            }
 2196        }
 2197
 2198        self.blink_manager.update(cx, BlinkManager::pause_blinking);
 2199        cx.emit(EditorEvent::SelectionsChanged { local });
 2200
 2201        let selections = &self.selections.disjoint;
 2202        if selections.len() == 1 {
 2203            cx.emit(SearchEvent::ActiveMatchChanged)
 2204        }
 2205        if local
 2206            && self.is_singleton(cx)
 2207            && WorkspaceSettings::get(None, cx).restore_on_startup != RestoreOnStartupBehavior::None
 2208        {
 2209            if let Some(workspace_id) = self.workspace.as_ref().and_then(|workspace| workspace.1) {
 2210                let background_executor = cx.background_executor().clone();
 2211                let editor_id = cx.entity().entity_id().as_u64() as ItemId;
 2212                let snapshot = self.buffer().read(cx).snapshot(cx);
 2213                let selections = selections.clone();
 2214                self.serialize_selections = cx.background_spawn(async move {
 2215                    background_executor.timer(Duration::from_millis(100)).await;
 2216                    let selections = selections
 2217                        .iter()
 2218                        .map(|selection| {
 2219                            (
 2220                                selection.start.to_offset(&snapshot),
 2221                                selection.end.to_offset(&snapshot),
 2222                            )
 2223                        })
 2224                        .collect();
 2225                    DB.save_editor_selections(editor_id, workspace_id, selections)
 2226                        .await
 2227                        .with_context(|| format!("persisting editor selections for editor {editor_id}, workspace {workspace_id:?}"))
 2228                        .log_err();
 2229                });
 2230            }
 2231        }
 2232
 2233        cx.notify();
 2234    }
 2235
 2236    pub fn sync_selections(
 2237        &mut self,
 2238        other: Entity<Editor>,
 2239        cx: &mut Context<Self>,
 2240    ) -> gpui::Subscription {
 2241        let other_selections = other.read(cx).selections.disjoint.to_vec();
 2242        self.selections.change_with(cx, |selections| {
 2243            selections.select_anchors(other_selections);
 2244        });
 2245
 2246        let other_subscription =
 2247            cx.subscribe(&other, |this, other, other_evt, cx| match other_evt {
 2248                EditorEvent::SelectionsChanged { local: true } => {
 2249                    let other_selections = other.read(cx).selections.disjoint.to_vec();
 2250                    if other_selections.is_empty() {
 2251                        return;
 2252                    }
 2253                    this.selections.change_with(cx, |selections| {
 2254                        selections.select_anchors(other_selections);
 2255                    });
 2256                }
 2257                _ => {}
 2258            });
 2259
 2260        let this_subscription =
 2261            cx.subscribe_self::<EditorEvent>(move |this, this_evt, cx| match this_evt {
 2262                EditorEvent::SelectionsChanged { local: true } => {
 2263                    let these_selections = this.selections.disjoint.to_vec();
 2264                    if these_selections.is_empty() {
 2265                        return;
 2266                    }
 2267                    other.update(cx, |other_editor, cx| {
 2268                        other_editor.selections.change_with(cx, |selections| {
 2269                            selections.select_anchors(these_selections);
 2270                        })
 2271                    });
 2272                }
 2273                _ => {}
 2274            });
 2275
 2276        Subscription::join(other_subscription, this_subscription)
 2277    }
 2278
 2279    pub fn change_selections<R>(
 2280        &mut self,
 2281        autoscroll: Option<Autoscroll>,
 2282        window: &mut Window,
 2283        cx: &mut Context<Self>,
 2284        change: impl FnOnce(&mut MutableSelectionsCollection<'_>) -> R,
 2285    ) -> R {
 2286        self.change_selections_inner(autoscroll, true, window, cx, change)
 2287    }
 2288
 2289    fn change_selections_inner<R>(
 2290        &mut self,
 2291        autoscroll: Option<Autoscroll>,
 2292        request_completions: bool,
 2293        window: &mut Window,
 2294        cx: &mut Context<Self>,
 2295        change: impl FnOnce(&mut MutableSelectionsCollection<'_>) -> R,
 2296    ) -> R {
 2297        let old_cursor_position = self.selections.newest_anchor().head();
 2298        self.push_to_selection_history();
 2299
 2300        let (changed, result) = self.selections.change_with(cx, change);
 2301
 2302        if changed {
 2303            if let Some(autoscroll) = autoscroll {
 2304                self.request_autoscroll(autoscroll, cx);
 2305            }
 2306            self.selections_did_change(true, &old_cursor_position, request_completions, window, cx);
 2307
 2308            if self.should_open_signature_help_automatically(
 2309                &old_cursor_position,
 2310                self.signature_help_state.backspace_pressed(),
 2311                cx,
 2312            ) {
 2313                self.show_signature_help(&ShowSignatureHelp, window, cx);
 2314            }
 2315            self.signature_help_state.set_backspace_pressed(false);
 2316        }
 2317
 2318        result
 2319    }
 2320
 2321    pub fn edit<I, S, T>(&mut self, edits: I, cx: &mut Context<Self>)
 2322    where
 2323        I: IntoIterator<Item = (Range<S>, T)>,
 2324        S: ToOffset,
 2325        T: Into<Arc<str>>,
 2326    {
 2327        if self.read_only(cx) {
 2328            return;
 2329        }
 2330
 2331        self.buffer
 2332            .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
 2333    }
 2334
 2335    pub fn edit_with_autoindent<I, S, T>(&mut self, edits: I, cx: &mut Context<Self>)
 2336    where
 2337        I: IntoIterator<Item = (Range<S>, T)>,
 2338        S: ToOffset,
 2339        T: Into<Arc<str>>,
 2340    {
 2341        if self.read_only(cx) {
 2342            return;
 2343        }
 2344
 2345        self.buffer.update(cx, |buffer, cx| {
 2346            buffer.edit(edits, self.autoindent_mode.clone(), cx)
 2347        });
 2348    }
 2349
 2350    pub fn edit_with_block_indent<I, S, T>(
 2351        &mut self,
 2352        edits: I,
 2353        original_indent_columns: Vec<Option<u32>>,
 2354        cx: &mut Context<Self>,
 2355    ) where
 2356        I: IntoIterator<Item = (Range<S>, T)>,
 2357        S: ToOffset,
 2358        T: Into<Arc<str>>,
 2359    {
 2360        if self.read_only(cx) {
 2361            return;
 2362        }
 2363
 2364        self.buffer.update(cx, |buffer, cx| {
 2365            buffer.edit(
 2366                edits,
 2367                Some(AutoindentMode::Block {
 2368                    original_indent_columns,
 2369                }),
 2370                cx,
 2371            )
 2372        });
 2373    }
 2374
 2375    fn select(&mut self, phase: SelectPhase, window: &mut Window, cx: &mut Context<Self>) {
 2376        self.hide_context_menu(window, cx);
 2377
 2378        match phase {
 2379            SelectPhase::Begin {
 2380                position,
 2381                add,
 2382                click_count,
 2383            } => self.begin_selection(position, add, click_count, window, cx),
 2384            SelectPhase::BeginColumnar {
 2385                position,
 2386                goal_column,
 2387                reset,
 2388            } => self.begin_columnar_selection(position, goal_column, reset, window, cx),
 2389            SelectPhase::Extend {
 2390                position,
 2391                click_count,
 2392            } => self.extend_selection(position, click_count, window, cx),
 2393            SelectPhase::Update {
 2394                position,
 2395                goal_column,
 2396                scroll_delta,
 2397            } => self.update_selection(position, goal_column, scroll_delta, window, cx),
 2398            SelectPhase::End => self.end_selection(window, cx),
 2399        }
 2400    }
 2401
 2402    fn extend_selection(
 2403        &mut self,
 2404        position: DisplayPoint,
 2405        click_count: usize,
 2406        window: &mut Window,
 2407        cx: &mut Context<Self>,
 2408    ) {
 2409        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 2410        let tail = self.selections.newest::<usize>(cx).tail();
 2411        self.begin_selection(position, false, click_count, window, cx);
 2412
 2413        let position = position.to_offset(&display_map, Bias::Left);
 2414        let tail_anchor = display_map.buffer_snapshot.anchor_before(tail);
 2415
 2416        let mut pending_selection = self
 2417            .selections
 2418            .pending_anchor()
 2419            .expect("extend_selection not called with pending selection");
 2420        if position >= tail {
 2421            pending_selection.start = tail_anchor;
 2422        } else {
 2423            pending_selection.end = tail_anchor;
 2424            pending_selection.reversed = true;
 2425        }
 2426
 2427        let mut pending_mode = self.selections.pending_mode().unwrap();
 2428        match &mut pending_mode {
 2429            SelectMode::Word(range) | SelectMode::Line(range) => *range = tail_anchor..tail_anchor,
 2430            _ => {}
 2431        }
 2432
 2433        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 2434            s.set_pending(pending_selection, pending_mode)
 2435        });
 2436    }
 2437
 2438    fn begin_selection(
 2439        &mut self,
 2440        position: DisplayPoint,
 2441        add: bool,
 2442        click_count: usize,
 2443        window: &mut Window,
 2444        cx: &mut Context<Self>,
 2445    ) {
 2446        if !self.focus_handle.is_focused(window) {
 2447            self.last_focused_descendant = None;
 2448            window.focus(&self.focus_handle);
 2449        }
 2450
 2451        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 2452        let buffer = &display_map.buffer_snapshot;
 2453        let newest_selection = self.selections.newest_anchor().clone();
 2454        let position = display_map.clip_point(position, Bias::Left);
 2455
 2456        let start;
 2457        let end;
 2458        let mode;
 2459        let mut auto_scroll;
 2460        match click_count {
 2461            1 => {
 2462                start = buffer.anchor_before(position.to_point(&display_map));
 2463                end = start;
 2464                mode = SelectMode::Character;
 2465                auto_scroll = true;
 2466            }
 2467            2 => {
 2468                let range = movement::surrounding_word(&display_map, position);
 2469                start = buffer.anchor_before(range.start.to_point(&display_map));
 2470                end = buffer.anchor_before(range.end.to_point(&display_map));
 2471                mode = SelectMode::Word(start..end);
 2472                auto_scroll = true;
 2473            }
 2474            3 => {
 2475                let position = display_map
 2476                    .clip_point(position, Bias::Left)
 2477                    .to_point(&display_map);
 2478                let line_start = display_map.prev_line_boundary(position).0;
 2479                let next_line_start = buffer.clip_point(
 2480                    display_map.next_line_boundary(position).0 + Point::new(1, 0),
 2481                    Bias::Left,
 2482                );
 2483                start = buffer.anchor_before(line_start);
 2484                end = buffer.anchor_before(next_line_start);
 2485                mode = SelectMode::Line(start..end);
 2486                auto_scroll = true;
 2487            }
 2488            _ => {
 2489                start = buffer.anchor_before(0);
 2490                end = buffer.anchor_before(buffer.len());
 2491                mode = SelectMode::All;
 2492                auto_scroll = false;
 2493            }
 2494        }
 2495        auto_scroll &= EditorSettings::get_global(cx).autoscroll_on_clicks;
 2496
 2497        let point_to_delete: Option<usize> = {
 2498            let selected_points: Vec<Selection<Point>> =
 2499                self.selections.disjoint_in_range(start..end, cx);
 2500
 2501            if !add || click_count > 1 {
 2502                None
 2503            } else if !selected_points.is_empty() {
 2504                Some(selected_points[0].id)
 2505            } else {
 2506                let clicked_point_already_selected =
 2507                    self.selections.disjoint.iter().find(|selection| {
 2508                        selection.start.to_point(buffer) == start.to_point(buffer)
 2509                            || selection.end.to_point(buffer) == end.to_point(buffer)
 2510                    });
 2511
 2512                clicked_point_already_selected.map(|selection| selection.id)
 2513            }
 2514        };
 2515
 2516        let selections_count = self.selections.count();
 2517
 2518        self.change_selections(auto_scroll.then(Autoscroll::newest), window, cx, |s| {
 2519            if let Some(point_to_delete) = point_to_delete {
 2520                s.delete(point_to_delete);
 2521
 2522                if selections_count == 1 {
 2523                    s.set_pending_anchor_range(start..end, mode);
 2524                }
 2525            } else {
 2526                if !add {
 2527                    s.clear_disjoint();
 2528                } else if click_count > 1 {
 2529                    s.delete(newest_selection.id)
 2530                }
 2531
 2532                s.set_pending_anchor_range(start..end, mode);
 2533            }
 2534        });
 2535    }
 2536
 2537    fn begin_columnar_selection(
 2538        &mut self,
 2539        position: DisplayPoint,
 2540        goal_column: u32,
 2541        reset: bool,
 2542        window: &mut Window,
 2543        cx: &mut Context<Self>,
 2544    ) {
 2545        if !self.focus_handle.is_focused(window) {
 2546            self.last_focused_descendant = None;
 2547            window.focus(&self.focus_handle);
 2548        }
 2549
 2550        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 2551
 2552        if reset {
 2553            let pointer_position = display_map
 2554                .buffer_snapshot
 2555                .anchor_before(position.to_point(&display_map));
 2556
 2557            self.change_selections(Some(Autoscroll::newest()), window, cx, |s| {
 2558                s.clear_disjoint();
 2559                s.set_pending_anchor_range(
 2560                    pointer_position..pointer_position,
 2561                    SelectMode::Character,
 2562                );
 2563            });
 2564        }
 2565
 2566        let tail = self.selections.newest::<Point>(cx).tail();
 2567        self.columnar_selection_tail = Some(display_map.buffer_snapshot.anchor_before(tail));
 2568
 2569        if !reset {
 2570            self.select_columns(
 2571                tail.to_display_point(&display_map),
 2572                position,
 2573                goal_column,
 2574                &display_map,
 2575                window,
 2576                cx,
 2577            );
 2578        }
 2579    }
 2580
 2581    fn update_selection(
 2582        &mut self,
 2583        position: DisplayPoint,
 2584        goal_column: u32,
 2585        scroll_delta: gpui::Point<f32>,
 2586        window: &mut Window,
 2587        cx: &mut Context<Self>,
 2588    ) {
 2589        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 2590
 2591        if let Some(tail) = self.columnar_selection_tail.as_ref() {
 2592            let tail = tail.to_display_point(&display_map);
 2593            self.select_columns(tail, position, goal_column, &display_map, window, cx);
 2594        } else if let Some(mut pending) = self.selections.pending_anchor() {
 2595            let buffer = self.buffer.read(cx).snapshot(cx);
 2596            let head;
 2597            let tail;
 2598            let mode = self.selections.pending_mode().unwrap();
 2599            match &mode {
 2600                SelectMode::Character => {
 2601                    head = position.to_point(&display_map);
 2602                    tail = pending.tail().to_point(&buffer);
 2603                }
 2604                SelectMode::Word(original_range) => {
 2605                    let original_display_range = original_range.start.to_display_point(&display_map)
 2606                        ..original_range.end.to_display_point(&display_map);
 2607                    let original_buffer_range = original_display_range.start.to_point(&display_map)
 2608                        ..original_display_range.end.to_point(&display_map);
 2609                    if movement::is_inside_word(&display_map, position)
 2610                        || original_display_range.contains(&position)
 2611                    {
 2612                        let word_range = movement::surrounding_word(&display_map, position);
 2613                        if word_range.start < original_display_range.start {
 2614                            head = word_range.start.to_point(&display_map);
 2615                        } else {
 2616                            head = word_range.end.to_point(&display_map);
 2617                        }
 2618                    } else {
 2619                        head = position.to_point(&display_map);
 2620                    }
 2621
 2622                    if head <= original_buffer_range.start {
 2623                        tail = original_buffer_range.end;
 2624                    } else {
 2625                        tail = original_buffer_range.start;
 2626                    }
 2627                }
 2628                SelectMode::Line(original_range) => {
 2629                    let original_range = original_range.to_point(&display_map.buffer_snapshot);
 2630
 2631                    let position = display_map
 2632                        .clip_point(position, Bias::Left)
 2633                        .to_point(&display_map);
 2634                    let line_start = display_map.prev_line_boundary(position).0;
 2635                    let next_line_start = buffer.clip_point(
 2636                        display_map.next_line_boundary(position).0 + Point::new(1, 0),
 2637                        Bias::Left,
 2638                    );
 2639
 2640                    if line_start < original_range.start {
 2641                        head = line_start
 2642                    } else {
 2643                        head = next_line_start
 2644                    }
 2645
 2646                    if head <= original_range.start {
 2647                        tail = original_range.end;
 2648                    } else {
 2649                        tail = original_range.start;
 2650                    }
 2651                }
 2652                SelectMode::All => {
 2653                    return;
 2654                }
 2655            };
 2656
 2657            if head < tail {
 2658                pending.start = buffer.anchor_before(head);
 2659                pending.end = buffer.anchor_before(tail);
 2660                pending.reversed = true;
 2661            } else {
 2662                pending.start = buffer.anchor_before(tail);
 2663                pending.end = buffer.anchor_before(head);
 2664                pending.reversed = false;
 2665            }
 2666
 2667            self.change_selections(None, window, cx, |s| {
 2668                s.set_pending(pending, mode);
 2669            });
 2670        } else {
 2671            log::error!("update_selection dispatched with no pending selection");
 2672            return;
 2673        }
 2674
 2675        self.apply_scroll_delta(scroll_delta, window, cx);
 2676        cx.notify();
 2677    }
 2678
 2679    fn end_selection(&mut self, window: &mut Window, cx: &mut Context<Self>) {
 2680        self.columnar_selection_tail.take();
 2681        if self.selections.pending_anchor().is_some() {
 2682            let selections = self.selections.all::<usize>(cx);
 2683            self.change_selections(None, window, cx, |s| {
 2684                s.select(selections);
 2685                s.clear_pending();
 2686            });
 2687        }
 2688    }
 2689
 2690    fn select_columns(
 2691        &mut self,
 2692        tail: DisplayPoint,
 2693        head: DisplayPoint,
 2694        goal_column: u32,
 2695        display_map: &DisplaySnapshot,
 2696        window: &mut Window,
 2697        cx: &mut Context<Self>,
 2698    ) {
 2699        let start_row = cmp::min(tail.row(), head.row());
 2700        let end_row = cmp::max(tail.row(), head.row());
 2701        let start_column = cmp::min(tail.column(), goal_column);
 2702        let end_column = cmp::max(tail.column(), goal_column);
 2703        let reversed = start_column < tail.column();
 2704
 2705        let selection_ranges = (start_row.0..=end_row.0)
 2706            .map(DisplayRow)
 2707            .filter_map(|row| {
 2708                if start_column <= display_map.line_len(row) && !display_map.is_block_line(row) {
 2709                    let start = display_map
 2710                        .clip_point(DisplayPoint::new(row, start_column), Bias::Left)
 2711                        .to_point(display_map);
 2712                    let end = display_map
 2713                        .clip_point(DisplayPoint::new(row, end_column), Bias::Right)
 2714                        .to_point(display_map);
 2715                    if reversed {
 2716                        Some(end..start)
 2717                    } else {
 2718                        Some(start..end)
 2719                    }
 2720                } else {
 2721                    None
 2722                }
 2723            })
 2724            .collect::<Vec<_>>();
 2725
 2726        self.change_selections(None, window, cx, |s| {
 2727            s.select_ranges(selection_ranges);
 2728        });
 2729        cx.notify();
 2730    }
 2731
 2732    pub fn has_pending_nonempty_selection(&self) -> bool {
 2733        let pending_nonempty_selection = match self.selections.pending_anchor() {
 2734            Some(Selection { start, end, .. }) => start != end,
 2735            None => false,
 2736        };
 2737
 2738        pending_nonempty_selection
 2739            || (self.columnar_selection_tail.is_some() && self.selections.disjoint.len() > 1)
 2740    }
 2741
 2742    pub fn has_pending_selection(&self) -> bool {
 2743        self.selections.pending_anchor().is_some() || self.columnar_selection_tail.is_some()
 2744    }
 2745
 2746    pub fn cancel(&mut self, _: &Cancel, window: &mut Window, cx: &mut Context<Self>) {
 2747        self.selection_mark_mode = false;
 2748
 2749        if self.clear_expanded_diff_hunks(cx) {
 2750            cx.notify();
 2751            return;
 2752        }
 2753        if self.dismiss_menus_and_popups(true, window, cx) {
 2754            return;
 2755        }
 2756
 2757        if self.mode == EditorMode::Full
 2758            && self.change_selections(Some(Autoscroll::fit()), window, cx, |s| s.try_cancel())
 2759        {
 2760            return;
 2761        }
 2762
 2763        cx.propagate();
 2764    }
 2765
 2766    pub fn dismiss_menus_and_popups(
 2767        &mut self,
 2768        is_user_requested: bool,
 2769        window: &mut Window,
 2770        cx: &mut Context<Self>,
 2771    ) -> bool {
 2772        if self.take_rename(false, window, cx).is_some() {
 2773            return true;
 2774        }
 2775
 2776        if hide_hover(self, cx) {
 2777            return true;
 2778        }
 2779
 2780        if self.hide_signature_help(cx, SignatureHelpHiddenBy::Escape) {
 2781            return true;
 2782        }
 2783
 2784        if self.hide_context_menu(window, cx).is_some() {
 2785            return true;
 2786        }
 2787
 2788        if self.mouse_context_menu.take().is_some() {
 2789            return true;
 2790        }
 2791
 2792        if is_user_requested && self.discard_inline_completion(true, cx) {
 2793            return true;
 2794        }
 2795
 2796        if self.snippet_stack.pop().is_some() {
 2797            return true;
 2798        }
 2799
 2800        if self.mode == EditorMode::Full && self.active_diagnostics.is_some() {
 2801            self.dismiss_diagnostics(cx);
 2802            return true;
 2803        }
 2804
 2805        false
 2806    }
 2807
 2808    fn linked_editing_ranges_for(
 2809        &self,
 2810        selection: Range<text::Anchor>,
 2811        cx: &App,
 2812    ) -> Option<HashMap<Entity<Buffer>, Vec<Range<text::Anchor>>>> {
 2813        if self.linked_edit_ranges.is_empty() {
 2814            return None;
 2815        }
 2816        let ((base_range, linked_ranges), buffer_snapshot, buffer) =
 2817            selection.end.buffer_id.and_then(|end_buffer_id| {
 2818                if selection.start.buffer_id != Some(end_buffer_id) {
 2819                    return None;
 2820                }
 2821                let buffer = self.buffer.read(cx).buffer(end_buffer_id)?;
 2822                let snapshot = buffer.read(cx).snapshot();
 2823                self.linked_edit_ranges
 2824                    .get(end_buffer_id, selection.start..selection.end, &snapshot)
 2825                    .map(|ranges| (ranges, snapshot, buffer))
 2826            })?;
 2827        use text::ToOffset as TO;
 2828        // find offset from the start of current range to current cursor position
 2829        let start_byte_offset = TO::to_offset(&base_range.start, &buffer_snapshot);
 2830
 2831        let start_offset = TO::to_offset(&selection.start, &buffer_snapshot);
 2832        let start_difference = start_offset - start_byte_offset;
 2833        let end_offset = TO::to_offset(&selection.end, &buffer_snapshot);
 2834        let end_difference = end_offset - start_byte_offset;
 2835        // Current range has associated linked ranges.
 2836        let mut linked_edits = HashMap::<_, Vec<_>>::default();
 2837        for range in linked_ranges.iter() {
 2838            let start_offset = TO::to_offset(&range.start, &buffer_snapshot);
 2839            let end_offset = start_offset + end_difference;
 2840            let start_offset = start_offset + start_difference;
 2841            if start_offset > buffer_snapshot.len() || end_offset > buffer_snapshot.len() {
 2842                continue;
 2843            }
 2844            if self.selections.disjoint_anchor_ranges().any(|s| {
 2845                if s.start.buffer_id != selection.start.buffer_id
 2846                    || s.end.buffer_id != selection.end.buffer_id
 2847                {
 2848                    return false;
 2849                }
 2850                TO::to_offset(&s.start.text_anchor, &buffer_snapshot) <= end_offset
 2851                    && TO::to_offset(&s.end.text_anchor, &buffer_snapshot) >= start_offset
 2852            }) {
 2853                continue;
 2854            }
 2855            let start = buffer_snapshot.anchor_after(start_offset);
 2856            let end = buffer_snapshot.anchor_after(end_offset);
 2857            linked_edits
 2858                .entry(buffer.clone())
 2859                .or_default()
 2860                .push(start..end);
 2861        }
 2862        Some(linked_edits)
 2863    }
 2864
 2865    pub fn handle_input(&mut self, text: &str, window: &mut Window, cx: &mut Context<Self>) {
 2866        let text: Arc<str> = text.into();
 2867
 2868        if self.read_only(cx) {
 2869            return;
 2870        }
 2871
 2872        let selections = self.selections.all_adjusted(cx);
 2873        let mut bracket_inserted = false;
 2874        let mut edits = Vec::new();
 2875        let mut linked_edits = HashMap::<_, Vec<_>>::default();
 2876        let mut new_selections = Vec::with_capacity(selections.len());
 2877        let mut new_autoclose_regions = Vec::new();
 2878        let snapshot = self.buffer.read(cx).read(cx);
 2879
 2880        for (selection, autoclose_region) in
 2881            self.selections_with_autoclose_regions(selections, &snapshot)
 2882        {
 2883            if let Some(scope) = snapshot.language_scope_at(selection.head()) {
 2884                // Determine if the inserted text matches the opening or closing
 2885                // bracket of any of this language's bracket pairs.
 2886                let mut bracket_pair = None;
 2887                let mut is_bracket_pair_start = false;
 2888                let mut is_bracket_pair_end = false;
 2889                if !text.is_empty() {
 2890                    // `text` can be empty when a user is using IME (e.g. Chinese Wubi Simplified)
 2891                    //  and they are removing the character that triggered IME popup.
 2892                    for (pair, enabled) in scope.brackets() {
 2893                        if !pair.close && !pair.surround {
 2894                            continue;
 2895                        }
 2896
 2897                        if enabled && pair.start.ends_with(text.as_ref()) {
 2898                            let prefix_len = pair.start.len() - text.len();
 2899                            let preceding_text_matches_prefix = prefix_len == 0
 2900                                || (selection.start.column >= (prefix_len as u32)
 2901                                    && snapshot.contains_str_at(
 2902                                        Point::new(
 2903                                            selection.start.row,
 2904                                            selection.start.column - (prefix_len as u32),
 2905                                        ),
 2906                                        &pair.start[..prefix_len],
 2907                                    ));
 2908                            if preceding_text_matches_prefix {
 2909                                bracket_pair = Some(pair.clone());
 2910                                is_bracket_pair_start = true;
 2911                                break;
 2912                            }
 2913                        }
 2914                        if pair.end.as_str() == text.as_ref() {
 2915                            bracket_pair = Some(pair.clone());
 2916                            is_bracket_pair_end = true;
 2917                            break;
 2918                        }
 2919                    }
 2920                }
 2921
 2922                if let Some(bracket_pair) = bracket_pair {
 2923                    let snapshot_settings = snapshot.language_settings_at(selection.start, cx);
 2924                    let autoclose = self.use_autoclose && snapshot_settings.use_autoclose;
 2925                    let auto_surround =
 2926                        self.use_auto_surround && snapshot_settings.use_auto_surround;
 2927                    if selection.is_empty() {
 2928                        if is_bracket_pair_start {
 2929                            // If the inserted text is a suffix of an opening bracket and the
 2930                            // selection is preceded by the rest of the opening bracket, then
 2931                            // insert the closing bracket.
 2932                            let following_text_allows_autoclose = snapshot
 2933                                .chars_at(selection.start)
 2934                                .next()
 2935                                .map_or(true, |c| scope.should_autoclose_before(c));
 2936
 2937                            let is_closing_quote = if bracket_pair.end == bracket_pair.start
 2938                                && bracket_pair.start.len() == 1
 2939                            {
 2940                                let target = bracket_pair.start.chars().next().unwrap();
 2941                                let current_line_count = snapshot
 2942                                    .reversed_chars_at(selection.start)
 2943                                    .take_while(|&c| c != '\n')
 2944                                    .filter(|&c| c == target)
 2945                                    .count();
 2946                                current_line_count % 2 == 1
 2947                            } else {
 2948                                false
 2949                            };
 2950
 2951                            if autoclose
 2952                                && bracket_pair.close
 2953                                && following_text_allows_autoclose
 2954                                && !is_closing_quote
 2955                            {
 2956                                let anchor = snapshot.anchor_before(selection.end);
 2957                                new_selections.push((selection.map(|_| anchor), text.len()));
 2958                                new_autoclose_regions.push((
 2959                                    anchor,
 2960                                    text.len(),
 2961                                    selection.id,
 2962                                    bracket_pair.clone(),
 2963                                ));
 2964                                edits.push((
 2965                                    selection.range(),
 2966                                    format!("{}{}", text, bracket_pair.end).into(),
 2967                                ));
 2968                                bracket_inserted = true;
 2969                                continue;
 2970                            }
 2971                        }
 2972
 2973                        if let Some(region) = autoclose_region {
 2974                            // If the selection is followed by an auto-inserted closing bracket,
 2975                            // then don't insert that closing bracket again; just move the selection
 2976                            // past the closing bracket.
 2977                            let should_skip = selection.end == region.range.end.to_point(&snapshot)
 2978                                && text.as_ref() == region.pair.end.as_str();
 2979                            if should_skip {
 2980                                let anchor = snapshot.anchor_after(selection.end);
 2981                                new_selections
 2982                                    .push((selection.map(|_| anchor), region.pair.end.len()));
 2983                                continue;
 2984                            }
 2985                        }
 2986
 2987                        let always_treat_brackets_as_autoclosed = snapshot
 2988                            .language_settings_at(selection.start, cx)
 2989                            .always_treat_brackets_as_autoclosed;
 2990                        if always_treat_brackets_as_autoclosed
 2991                            && is_bracket_pair_end
 2992                            && snapshot.contains_str_at(selection.end, text.as_ref())
 2993                        {
 2994                            // Otherwise, when `always_treat_brackets_as_autoclosed` is set to `true
 2995                            // and the inserted text is a closing bracket and the selection is followed
 2996                            // by the closing bracket then move the selection past the closing bracket.
 2997                            let anchor = snapshot.anchor_after(selection.end);
 2998                            new_selections.push((selection.map(|_| anchor), text.len()));
 2999                            continue;
 3000                        }
 3001                    }
 3002                    // If an opening bracket is 1 character long and is typed while
 3003                    // text is selected, then surround that text with the bracket pair.
 3004                    else if auto_surround
 3005                        && bracket_pair.surround
 3006                        && is_bracket_pair_start
 3007                        && bracket_pair.start.chars().count() == 1
 3008                    {
 3009                        edits.push((selection.start..selection.start, text.clone()));
 3010                        edits.push((
 3011                            selection.end..selection.end,
 3012                            bracket_pair.end.as_str().into(),
 3013                        ));
 3014                        bracket_inserted = true;
 3015                        new_selections.push((
 3016                            Selection {
 3017                                id: selection.id,
 3018                                start: snapshot.anchor_after(selection.start),
 3019                                end: snapshot.anchor_before(selection.end),
 3020                                reversed: selection.reversed,
 3021                                goal: selection.goal,
 3022                            },
 3023                            0,
 3024                        ));
 3025                        continue;
 3026                    }
 3027                }
 3028            }
 3029
 3030            if self.auto_replace_emoji_shortcode
 3031                && selection.is_empty()
 3032                && text.as_ref().ends_with(':')
 3033            {
 3034                if let Some(possible_emoji_short_code) =
 3035                    Self::find_possible_emoji_shortcode_at_position(&snapshot, selection.start)
 3036                {
 3037                    if !possible_emoji_short_code.is_empty() {
 3038                        if let Some(emoji) = emojis::get_by_shortcode(&possible_emoji_short_code) {
 3039                            let emoji_shortcode_start = Point::new(
 3040                                selection.start.row,
 3041                                selection.start.column - possible_emoji_short_code.len() as u32 - 1,
 3042                            );
 3043
 3044                            // Remove shortcode from buffer
 3045                            edits.push((
 3046                                emoji_shortcode_start..selection.start,
 3047                                "".to_string().into(),
 3048                            ));
 3049                            new_selections.push((
 3050                                Selection {
 3051                                    id: selection.id,
 3052                                    start: snapshot.anchor_after(emoji_shortcode_start),
 3053                                    end: snapshot.anchor_before(selection.start),
 3054                                    reversed: selection.reversed,
 3055                                    goal: selection.goal,
 3056                                },
 3057                                0,
 3058                            ));
 3059
 3060                            // Insert emoji
 3061                            let selection_start_anchor = snapshot.anchor_after(selection.start);
 3062                            new_selections.push((selection.map(|_| selection_start_anchor), 0));
 3063                            edits.push((selection.start..selection.end, emoji.to_string().into()));
 3064
 3065                            continue;
 3066                        }
 3067                    }
 3068                }
 3069            }
 3070
 3071            // If not handling any auto-close operation, then just replace the selected
 3072            // text with the given input and move the selection to the end of the
 3073            // newly inserted text.
 3074            let anchor = snapshot.anchor_after(selection.end);
 3075            if !self.linked_edit_ranges.is_empty() {
 3076                let start_anchor = snapshot.anchor_before(selection.start);
 3077
 3078                let is_word_char = text.chars().next().map_or(true, |char| {
 3079                    let classifier = snapshot.char_classifier_at(start_anchor.to_offset(&snapshot));
 3080                    classifier.is_word(char)
 3081                });
 3082
 3083                if is_word_char {
 3084                    if let Some(ranges) = self
 3085                        .linked_editing_ranges_for(start_anchor.text_anchor..anchor.text_anchor, cx)
 3086                    {
 3087                        for (buffer, edits) in ranges {
 3088                            linked_edits
 3089                                .entry(buffer.clone())
 3090                                .or_default()
 3091                                .extend(edits.into_iter().map(|range| (range, text.clone())));
 3092                        }
 3093                    }
 3094                }
 3095            }
 3096
 3097            new_selections.push((selection.map(|_| anchor), 0));
 3098            edits.push((selection.start..selection.end, text.clone()));
 3099        }
 3100
 3101        drop(snapshot);
 3102
 3103        self.transact(window, cx, |this, window, cx| {
 3104            let initial_buffer_versions =
 3105                jsx_tag_auto_close::construct_initial_buffer_versions_map(this, &edits, cx);
 3106
 3107            this.buffer.update(cx, |buffer, cx| {
 3108                buffer.edit(edits, this.autoindent_mode.clone(), cx);
 3109            });
 3110            for (buffer, edits) in linked_edits {
 3111                buffer.update(cx, |buffer, cx| {
 3112                    let snapshot = buffer.snapshot();
 3113                    let edits = edits
 3114                        .into_iter()
 3115                        .map(|(range, text)| {
 3116                            use text::ToPoint as TP;
 3117                            let end_point = TP::to_point(&range.end, &snapshot);
 3118                            let start_point = TP::to_point(&range.start, &snapshot);
 3119                            (start_point..end_point, text)
 3120                        })
 3121                        .sorted_by_key(|(range, _)| range.start)
 3122                        .collect::<Vec<_>>();
 3123                    buffer.edit(edits, None, cx);
 3124                })
 3125            }
 3126            let new_anchor_selections = new_selections.iter().map(|e| &e.0);
 3127            let new_selection_deltas = new_selections.iter().map(|e| e.1);
 3128            let map = this.display_map.update(cx, |map, cx| map.snapshot(cx));
 3129            let new_selections = resolve_selections::<usize, _>(new_anchor_selections, &map)
 3130                .zip(new_selection_deltas)
 3131                .map(|(selection, delta)| Selection {
 3132                    id: selection.id,
 3133                    start: selection.start + delta,
 3134                    end: selection.end + delta,
 3135                    reversed: selection.reversed,
 3136                    goal: SelectionGoal::None,
 3137                })
 3138                .collect::<Vec<_>>();
 3139
 3140            let mut i = 0;
 3141            for (position, delta, selection_id, pair) in new_autoclose_regions {
 3142                let position = position.to_offset(&map.buffer_snapshot) + delta;
 3143                let start = map.buffer_snapshot.anchor_before(position);
 3144                let end = map.buffer_snapshot.anchor_after(position);
 3145                while let Some(existing_state) = this.autoclose_regions.get(i) {
 3146                    match existing_state.range.start.cmp(&start, &map.buffer_snapshot) {
 3147                        Ordering::Less => i += 1,
 3148                        Ordering::Greater => break,
 3149                        Ordering::Equal => {
 3150                            match end.cmp(&existing_state.range.end, &map.buffer_snapshot) {
 3151                                Ordering::Less => i += 1,
 3152                                Ordering::Equal => break,
 3153                                Ordering::Greater => break,
 3154                            }
 3155                        }
 3156                    }
 3157                }
 3158                this.autoclose_regions.insert(
 3159                    i,
 3160                    AutocloseRegion {
 3161                        selection_id,
 3162                        range: start..end,
 3163                        pair,
 3164                    },
 3165                );
 3166            }
 3167
 3168            let had_active_inline_completion = this.has_active_inline_completion();
 3169            this.change_selections_inner(Some(Autoscroll::fit()), false, window, cx, |s| {
 3170                s.select(new_selections)
 3171            });
 3172
 3173            if !bracket_inserted {
 3174                if let Some(on_type_format_task) =
 3175                    this.trigger_on_type_formatting(text.to_string(), window, cx)
 3176                {
 3177                    on_type_format_task.detach_and_log_err(cx);
 3178                }
 3179            }
 3180
 3181            let editor_settings = EditorSettings::get_global(cx);
 3182            if bracket_inserted
 3183                && (editor_settings.auto_signature_help
 3184                    || editor_settings.show_signature_help_after_edits)
 3185            {
 3186                this.show_signature_help(&ShowSignatureHelp, window, cx);
 3187            }
 3188
 3189            let trigger_in_words =
 3190                this.show_edit_predictions_in_menu() || !had_active_inline_completion;
 3191            if this.hard_wrap.is_some() {
 3192                let latest: Range<Point> = this.selections.newest(cx).range();
 3193                if latest.is_empty()
 3194                    && this
 3195                        .buffer()
 3196                        .read(cx)
 3197                        .snapshot(cx)
 3198                        .line_len(MultiBufferRow(latest.start.row))
 3199                        == latest.start.column
 3200                {
 3201                    this.rewrap_impl(true, cx)
 3202                }
 3203            }
 3204            this.trigger_completion_on_input(&text, trigger_in_words, window, cx);
 3205            linked_editing_ranges::refresh_linked_ranges(this, window, cx);
 3206            this.refresh_inline_completion(true, false, window, cx);
 3207            jsx_tag_auto_close::handle_from(this, initial_buffer_versions, window, cx);
 3208        });
 3209    }
 3210
 3211    fn find_possible_emoji_shortcode_at_position(
 3212        snapshot: &MultiBufferSnapshot,
 3213        position: Point,
 3214    ) -> Option<String> {
 3215        let mut chars = Vec::new();
 3216        let mut found_colon = false;
 3217        for char in snapshot.reversed_chars_at(position).take(100) {
 3218            // Found a possible emoji shortcode in the middle of the buffer
 3219            if found_colon {
 3220                if char.is_whitespace() {
 3221                    chars.reverse();
 3222                    return Some(chars.iter().collect());
 3223                }
 3224                // If the previous character is not a whitespace, we are in the middle of a word
 3225                // and we only want to complete the shortcode if the word is made up of other emojis
 3226                let mut containing_word = String::new();
 3227                for ch in snapshot
 3228                    .reversed_chars_at(position)
 3229                    .skip(chars.len() + 1)
 3230                    .take(100)
 3231                {
 3232                    if ch.is_whitespace() {
 3233                        break;
 3234                    }
 3235                    containing_word.push(ch);
 3236                }
 3237                let containing_word = containing_word.chars().rev().collect::<String>();
 3238                if util::word_consists_of_emojis(containing_word.as_str()) {
 3239                    chars.reverse();
 3240                    return Some(chars.iter().collect());
 3241                }
 3242            }
 3243
 3244            if char.is_whitespace() || !char.is_ascii() {
 3245                return None;
 3246            }
 3247            if char == ':' {
 3248                found_colon = true;
 3249            } else {
 3250                chars.push(char);
 3251            }
 3252        }
 3253        // Found a possible emoji shortcode at the beginning of the buffer
 3254        chars.reverse();
 3255        Some(chars.iter().collect())
 3256    }
 3257
 3258    pub fn newline(&mut self, _: &Newline, window: &mut Window, cx: &mut Context<Self>) {
 3259        self.transact(window, cx, |this, window, cx| {
 3260            let (edits, selection_fixup_info): (Vec<_>, Vec<_>) = {
 3261                let selections = this.selections.all::<usize>(cx);
 3262                let multi_buffer = this.buffer.read(cx);
 3263                let buffer = multi_buffer.snapshot(cx);
 3264                selections
 3265                    .iter()
 3266                    .map(|selection| {
 3267                        let start_point = selection.start.to_point(&buffer);
 3268                        let mut indent =
 3269                            buffer.indent_size_for_line(MultiBufferRow(start_point.row));
 3270                        indent.len = cmp::min(indent.len, start_point.column);
 3271                        let start = selection.start;
 3272                        let end = selection.end;
 3273                        let selection_is_empty = start == end;
 3274                        let language_scope = buffer.language_scope_at(start);
 3275                        let (comment_delimiter, insert_extra_newline) = if let Some(language) =
 3276                            &language_scope
 3277                        {
 3278                            let insert_extra_newline =
 3279                                insert_extra_newline_brackets(&buffer, start..end, language)
 3280                                    || insert_extra_newline_tree_sitter(&buffer, start..end);
 3281
 3282                            // Comment extension on newline is allowed only for cursor selections
 3283                            let comment_delimiter = maybe!({
 3284                                if !selection_is_empty {
 3285                                    return None;
 3286                                }
 3287
 3288                                if !multi_buffer.language_settings(cx).extend_comment_on_newline {
 3289                                    return None;
 3290                                }
 3291
 3292                                let delimiters = language.line_comment_prefixes();
 3293                                let max_len_of_delimiter =
 3294                                    delimiters.iter().map(|delimiter| delimiter.len()).max()?;
 3295                                let (snapshot, range) =
 3296                                    buffer.buffer_line_for_row(MultiBufferRow(start_point.row))?;
 3297
 3298                                let mut index_of_first_non_whitespace = 0;
 3299                                let comment_candidate = snapshot
 3300                                    .chars_for_range(range)
 3301                                    .skip_while(|c| {
 3302                                        let should_skip = c.is_whitespace();
 3303                                        if should_skip {
 3304                                            index_of_first_non_whitespace += 1;
 3305                                        }
 3306                                        should_skip
 3307                                    })
 3308                                    .take(max_len_of_delimiter)
 3309                                    .collect::<String>();
 3310                                let comment_prefix = delimiters.iter().find(|comment_prefix| {
 3311                                    comment_candidate.starts_with(comment_prefix.as_ref())
 3312                                })?;
 3313                                let cursor_is_placed_after_comment_marker =
 3314                                    index_of_first_non_whitespace + comment_prefix.len()
 3315                                        <= start_point.column as usize;
 3316                                if cursor_is_placed_after_comment_marker {
 3317                                    Some(comment_prefix.clone())
 3318                                } else {
 3319                                    None
 3320                                }
 3321                            });
 3322                            (comment_delimiter, insert_extra_newline)
 3323                        } else {
 3324                            (None, false)
 3325                        };
 3326
 3327                        let capacity_for_delimiter = comment_delimiter
 3328                            .as_deref()
 3329                            .map(str::len)
 3330                            .unwrap_or_default();
 3331                        let mut new_text =
 3332                            String::with_capacity(1 + capacity_for_delimiter + indent.len as usize);
 3333                        new_text.push('\n');
 3334                        new_text.extend(indent.chars());
 3335                        if let Some(delimiter) = &comment_delimiter {
 3336                            new_text.push_str(delimiter);
 3337                        }
 3338                        if insert_extra_newline {
 3339                            new_text = new_text.repeat(2);
 3340                        }
 3341
 3342                        let anchor = buffer.anchor_after(end);
 3343                        let new_selection = selection.map(|_| anchor);
 3344                        (
 3345                            (start..end, new_text),
 3346                            (insert_extra_newline, new_selection),
 3347                        )
 3348                    })
 3349                    .unzip()
 3350            };
 3351
 3352            this.edit_with_autoindent(edits, cx);
 3353            let buffer = this.buffer.read(cx).snapshot(cx);
 3354            let new_selections = selection_fixup_info
 3355                .into_iter()
 3356                .map(|(extra_newline_inserted, new_selection)| {
 3357                    let mut cursor = new_selection.end.to_point(&buffer);
 3358                    if extra_newline_inserted {
 3359                        cursor.row -= 1;
 3360                        cursor.column = buffer.line_len(MultiBufferRow(cursor.row));
 3361                    }
 3362                    new_selection.map(|_| cursor)
 3363                })
 3364                .collect();
 3365
 3366            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 3367                s.select(new_selections)
 3368            });
 3369            this.refresh_inline_completion(true, false, window, cx);
 3370        });
 3371    }
 3372
 3373    pub fn newline_above(&mut self, _: &NewlineAbove, window: &mut Window, cx: &mut Context<Self>) {
 3374        let buffer = self.buffer.read(cx);
 3375        let snapshot = buffer.snapshot(cx);
 3376
 3377        let mut edits = Vec::new();
 3378        let mut rows = Vec::new();
 3379
 3380        for (rows_inserted, selection) in self.selections.all_adjusted(cx).into_iter().enumerate() {
 3381            let cursor = selection.head();
 3382            let row = cursor.row;
 3383
 3384            let start_of_line = snapshot.clip_point(Point::new(row, 0), Bias::Left);
 3385
 3386            let newline = "\n".to_string();
 3387            edits.push((start_of_line..start_of_line, newline));
 3388
 3389            rows.push(row + rows_inserted as u32);
 3390        }
 3391
 3392        self.transact(window, cx, |editor, window, cx| {
 3393            editor.edit(edits, cx);
 3394
 3395            editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 3396                let mut index = 0;
 3397                s.move_cursors_with(|map, _, _| {
 3398                    let row = rows[index];
 3399                    index += 1;
 3400
 3401                    let point = Point::new(row, 0);
 3402                    let boundary = map.next_line_boundary(point).1;
 3403                    let clipped = map.clip_point(boundary, Bias::Left);
 3404
 3405                    (clipped, SelectionGoal::None)
 3406                });
 3407            });
 3408
 3409            let mut indent_edits = Vec::new();
 3410            let multibuffer_snapshot = editor.buffer.read(cx).snapshot(cx);
 3411            for row in rows {
 3412                let indents = multibuffer_snapshot.suggested_indents(row..row + 1, cx);
 3413                for (row, indent) in indents {
 3414                    if indent.len == 0 {
 3415                        continue;
 3416                    }
 3417
 3418                    let text = match indent.kind {
 3419                        IndentKind::Space => " ".repeat(indent.len as usize),
 3420                        IndentKind::Tab => "\t".repeat(indent.len as usize),
 3421                    };
 3422                    let point = Point::new(row.0, 0);
 3423                    indent_edits.push((point..point, text));
 3424                }
 3425            }
 3426            editor.edit(indent_edits, cx);
 3427        });
 3428    }
 3429
 3430    pub fn newline_below(&mut self, _: &NewlineBelow, window: &mut Window, cx: &mut Context<Self>) {
 3431        let buffer = self.buffer.read(cx);
 3432        let snapshot = buffer.snapshot(cx);
 3433
 3434        let mut edits = Vec::new();
 3435        let mut rows = Vec::new();
 3436        let mut rows_inserted = 0;
 3437
 3438        for selection in self.selections.all_adjusted(cx) {
 3439            let cursor = selection.head();
 3440            let row = cursor.row;
 3441
 3442            let point = Point::new(row + 1, 0);
 3443            let start_of_line = snapshot.clip_point(point, Bias::Left);
 3444
 3445            let newline = "\n".to_string();
 3446            edits.push((start_of_line..start_of_line, newline));
 3447
 3448            rows_inserted += 1;
 3449            rows.push(row + rows_inserted);
 3450        }
 3451
 3452        self.transact(window, cx, |editor, window, cx| {
 3453            editor.edit(edits, cx);
 3454
 3455            editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 3456                let mut index = 0;
 3457                s.move_cursors_with(|map, _, _| {
 3458                    let row = rows[index];
 3459                    index += 1;
 3460
 3461                    let point = Point::new(row, 0);
 3462                    let boundary = map.next_line_boundary(point).1;
 3463                    let clipped = map.clip_point(boundary, Bias::Left);
 3464
 3465                    (clipped, SelectionGoal::None)
 3466                });
 3467            });
 3468
 3469            let mut indent_edits = Vec::new();
 3470            let multibuffer_snapshot = editor.buffer.read(cx).snapshot(cx);
 3471            for row in rows {
 3472                let indents = multibuffer_snapshot.suggested_indents(row..row + 1, cx);
 3473                for (row, indent) in indents {
 3474                    if indent.len == 0 {
 3475                        continue;
 3476                    }
 3477
 3478                    let text = match indent.kind {
 3479                        IndentKind::Space => " ".repeat(indent.len as usize),
 3480                        IndentKind::Tab => "\t".repeat(indent.len as usize),
 3481                    };
 3482                    let point = Point::new(row.0, 0);
 3483                    indent_edits.push((point..point, text));
 3484                }
 3485            }
 3486            editor.edit(indent_edits, cx);
 3487        });
 3488    }
 3489
 3490    pub fn insert(&mut self, text: &str, window: &mut Window, cx: &mut Context<Self>) {
 3491        let autoindent = text.is_empty().not().then(|| AutoindentMode::Block {
 3492            original_indent_columns: Vec::new(),
 3493        });
 3494        self.insert_with_autoindent_mode(text, autoindent, window, cx);
 3495    }
 3496
 3497    fn insert_with_autoindent_mode(
 3498        &mut self,
 3499        text: &str,
 3500        autoindent_mode: Option<AutoindentMode>,
 3501        window: &mut Window,
 3502        cx: &mut Context<Self>,
 3503    ) {
 3504        if self.read_only(cx) {
 3505            return;
 3506        }
 3507
 3508        let text: Arc<str> = text.into();
 3509        self.transact(window, cx, |this, window, cx| {
 3510            let old_selections = this.selections.all_adjusted(cx);
 3511            let selection_anchors = this.buffer.update(cx, |buffer, cx| {
 3512                let anchors = {
 3513                    let snapshot = buffer.read(cx);
 3514                    old_selections
 3515                        .iter()
 3516                        .map(|s| {
 3517                            let anchor = snapshot.anchor_after(s.head());
 3518                            s.map(|_| anchor)
 3519                        })
 3520                        .collect::<Vec<_>>()
 3521                };
 3522                buffer.edit(
 3523                    old_selections
 3524                        .iter()
 3525                        .map(|s| (s.start..s.end, text.clone())),
 3526                    autoindent_mode,
 3527                    cx,
 3528                );
 3529                anchors
 3530            });
 3531
 3532            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 3533                s.select_anchors(selection_anchors);
 3534            });
 3535
 3536            cx.notify();
 3537        });
 3538    }
 3539
 3540    fn trigger_completion_on_input(
 3541        &mut self,
 3542        text: &str,
 3543        trigger_in_words: bool,
 3544        window: &mut Window,
 3545        cx: &mut Context<Self>,
 3546    ) {
 3547        if self.is_completion_trigger(text, trigger_in_words, cx) {
 3548            self.show_completions(
 3549                &ShowCompletions {
 3550                    trigger: Some(text.to_owned()).filter(|x| !x.is_empty()),
 3551                },
 3552                window,
 3553                cx,
 3554            );
 3555        } else {
 3556            self.hide_context_menu(window, cx);
 3557        }
 3558    }
 3559
 3560    fn is_completion_trigger(
 3561        &self,
 3562        text: &str,
 3563        trigger_in_words: bool,
 3564        cx: &mut Context<Self>,
 3565    ) -> bool {
 3566        let position = self.selections.newest_anchor().head();
 3567        let multibuffer = self.buffer.read(cx);
 3568        let Some(buffer) = position
 3569            .buffer_id
 3570            .and_then(|buffer_id| multibuffer.buffer(buffer_id).clone())
 3571        else {
 3572            return false;
 3573        };
 3574
 3575        if let Some(completion_provider) = &self.completion_provider {
 3576            completion_provider.is_completion_trigger(
 3577                &buffer,
 3578                position.text_anchor,
 3579                text,
 3580                trigger_in_words,
 3581                cx,
 3582            )
 3583        } else {
 3584            false
 3585        }
 3586    }
 3587
 3588    /// If any empty selections is touching the start of its innermost containing autoclose
 3589    /// region, expand it to select the brackets.
 3590    fn select_autoclose_pair(&mut self, window: &mut Window, cx: &mut Context<Self>) {
 3591        let selections = self.selections.all::<usize>(cx);
 3592        let buffer = self.buffer.read(cx).read(cx);
 3593        let new_selections = self
 3594            .selections_with_autoclose_regions(selections, &buffer)
 3595            .map(|(mut selection, region)| {
 3596                if !selection.is_empty() {
 3597                    return selection;
 3598                }
 3599
 3600                if let Some(region) = region {
 3601                    let mut range = region.range.to_offset(&buffer);
 3602                    if selection.start == range.start && range.start >= region.pair.start.len() {
 3603                        range.start -= region.pair.start.len();
 3604                        if buffer.contains_str_at(range.start, &region.pair.start)
 3605                            && buffer.contains_str_at(range.end, &region.pair.end)
 3606                        {
 3607                            range.end += region.pair.end.len();
 3608                            selection.start = range.start;
 3609                            selection.end = range.end;
 3610
 3611                            return selection;
 3612                        }
 3613                    }
 3614                }
 3615
 3616                let always_treat_brackets_as_autoclosed = buffer
 3617                    .language_settings_at(selection.start, cx)
 3618                    .always_treat_brackets_as_autoclosed;
 3619
 3620                if !always_treat_brackets_as_autoclosed {
 3621                    return selection;
 3622                }
 3623
 3624                if let Some(scope) = buffer.language_scope_at(selection.start) {
 3625                    for (pair, enabled) in scope.brackets() {
 3626                        if !enabled || !pair.close {
 3627                            continue;
 3628                        }
 3629
 3630                        if buffer.contains_str_at(selection.start, &pair.end) {
 3631                            let pair_start_len = pair.start.len();
 3632                            if buffer.contains_str_at(
 3633                                selection.start.saturating_sub(pair_start_len),
 3634                                &pair.start,
 3635                            ) {
 3636                                selection.start -= pair_start_len;
 3637                                selection.end += pair.end.len();
 3638
 3639                                return selection;
 3640                            }
 3641                        }
 3642                    }
 3643                }
 3644
 3645                selection
 3646            })
 3647            .collect();
 3648
 3649        drop(buffer);
 3650        self.change_selections(None, window, cx, |selections| {
 3651            selections.select(new_selections)
 3652        });
 3653    }
 3654
 3655    /// Iterate the given selections, and for each one, find the smallest surrounding
 3656    /// autoclose region. This uses the ordering of the selections and the autoclose
 3657    /// regions to avoid repeated comparisons.
 3658    fn selections_with_autoclose_regions<'a, D: ToOffset + Clone>(
 3659        &'a self,
 3660        selections: impl IntoIterator<Item = Selection<D>>,
 3661        buffer: &'a MultiBufferSnapshot,
 3662    ) -> impl Iterator<Item = (Selection<D>, Option<&'a AutocloseRegion>)> {
 3663        let mut i = 0;
 3664        let mut regions = self.autoclose_regions.as_slice();
 3665        selections.into_iter().map(move |selection| {
 3666            let range = selection.start.to_offset(buffer)..selection.end.to_offset(buffer);
 3667
 3668            let mut enclosing = None;
 3669            while let Some(pair_state) = regions.get(i) {
 3670                if pair_state.range.end.to_offset(buffer) < range.start {
 3671                    regions = &regions[i + 1..];
 3672                    i = 0;
 3673                } else if pair_state.range.start.to_offset(buffer) > range.end {
 3674                    break;
 3675                } else {
 3676                    if pair_state.selection_id == selection.id {
 3677                        enclosing = Some(pair_state);
 3678                    }
 3679                    i += 1;
 3680                }
 3681            }
 3682
 3683            (selection, enclosing)
 3684        })
 3685    }
 3686
 3687    /// Remove any autoclose regions that no longer contain their selection.
 3688    fn invalidate_autoclose_regions(
 3689        &mut self,
 3690        mut selections: &[Selection<Anchor>],
 3691        buffer: &MultiBufferSnapshot,
 3692    ) {
 3693        self.autoclose_regions.retain(|state| {
 3694            let mut i = 0;
 3695            while let Some(selection) = selections.get(i) {
 3696                if selection.end.cmp(&state.range.start, buffer).is_lt() {
 3697                    selections = &selections[1..];
 3698                    continue;
 3699                }
 3700                if selection.start.cmp(&state.range.end, buffer).is_gt() {
 3701                    break;
 3702                }
 3703                if selection.id == state.selection_id {
 3704                    return true;
 3705                } else {
 3706                    i += 1;
 3707                }
 3708            }
 3709            false
 3710        });
 3711    }
 3712
 3713    fn completion_query(buffer: &MultiBufferSnapshot, position: impl ToOffset) -> Option<String> {
 3714        let offset = position.to_offset(buffer);
 3715        let (word_range, kind) = buffer.surrounding_word(offset, true);
 3716        if offset > word_range.start && kind == Some(CharKind::Word) {
 3717            Some(
 3718                buffer
 3719                    .text_for_range(word_range.start..offset)
 3720                    .collect::<String>(),
 3721            )
 3722        } else {
 3723            None
 3724        }
 3725    }
 3726
 3727    pub fn toggle_inlay_hints(
 3728        &mut self,
 3729        _: &ToggleInlayHints,
 3730        _: &mut Window,
 3731        cx: &mut Context<Self>,
 3732    ) {
 3733        self.refresh_inlay_hints(
 3734            InlayHintRefreshReason::Toggle(!self.inlay_hints_enabled()),
 3735            cx,
 3736        );
 3737    }
 3738
 3739    pub fn inlay_hints_enabled(&self) -> bool {
 3740        self.inlay_hint_cache.enabled
 3741    }
 3742
 3743    fn refresh_inlay_hints(&mut self, reason: InlayHintRefreshReason, cx: &mut Context<Self>) {
 3744        if self.semantics_provider.is_none() || self.mode != EditorMode::Full {
 3745            return;
 3746        }
 3747
 3748        let reason_description = reason.description();
 3749        let ignore_debounce = matches!(
 3750            reason,
 3751            InlayHintRefreshReason::SettingsChange(_)
 3752                | InlayHintRefreshReason::Toggle(_)
 3753                | InlayHintRefreshReason::ExcerptsRemoved(_)
 3754                | InlayHintRefreshReason::ModifiersChanged(_)
 3755        );
 3756        let (invalidate_cache, required_languages) = match reason {
 3757            InlayHintRefreshReason::ModifiersChanged(enabled) => {
 3758                match self.inlay_hint_cache.modifiers_override(enabled) {
 3759                    Some(enabled) => {
 3760                        if enabled {
 3761                            (InvalidationStrategy::RefreshRequested, None)
 3762                        } else {
 3763                            self.splice_inlays(
 3764                                &self
 3765                                    .visible_inlay_hints(cx)
 3766                                    .iter()
 3767                                    .map(|inlay| inlay.id)
 3768                                    .collect::<Vec<InlayId>>(),
 3769                                Vec::new(),
 3770                                cx,
 3771                            );
 3772                            return;
 3773                        }
 3774                    }
 3775                    None => return,
 3776                }
 3777            }
 3778            InlayHintRefreshReason::Toggle(enabled) => {
 3779                if self.inlay_hint_cache.toggle(enabled) {
 3780                    if enabled {
 3781                        (InvalidationStrategy::RefreshRequested, None)
 3782                    } else {
 3783                        self.splice_inlays(
 3784                            &self
 3785                                .visible_inlay_hints(cx)
 3786                                .iter()
 3787                                .map(|inlay| inlay.id)
 3788                                .collect::<Vec<InlayId>>(),
 3789                            Vec::new(),
 3790                            cx,
 3791                        );
 3792                        return;
 3793                    }
 3794                } else {
 3795                    return;
 3796                }
 3797            }
 3798            InlayHintRefreshReason::SettingsChange(new_settings) => {
 3799                match self.inlay_hint_cache.update_settings(
 3800                    &self.buffer,
 3801                    new_settings,
 3802                    self.visible_inlay_hints(cx),
 3803                    cx,
 3804                ) {
 3805                    ControlFlow::Break(Some(InlaySplice {
 3806                        to_remove,
 3807                        to_insert,
 3808                    })) => {
 3809                        self.splice_inlays(&to_remove, to_insert, cx);
 3810                        return;
 3811                    }
 3812                    ControlFlow::Break(None) => return,
 3813                    ControlFlow::Continue(()) => (InvalidationStrategy::RefreshRequested, None),
 3814                }
 3815            }
 3816            InlayHintRefreshReason::ExcerptsRemoved(excerpts_removed) => {
 3817                if let Some(InlaySplice {
 3818                    to_remove,
 3819                    to_insert,
 3820                }) = self.inlay_hint_cache.remove_excerpts(excerpts_removed)
 3821                {
 3822                    self.splice_inlays(&to_remove, to_insert, cx);
 3823                }
 3824                return;
 3825            }
 3826            InlayHintRefreshReason::NewLinesShown => (InvalidationStrategy::None, None),
 3827            InlayHintRefreshReason::BufferEdited(buffer_languages) => {
 3828                (InvalidationStrategy::BufferEdited, Some(buffer_languages))
 3829            }
 3830            InlayHintRefreshReason::RefreshRequested => {
 3831                (InvalidationStrategy::RefreshRequested, None)
 3832            }
 3833        };
 3834
 3835        if let Some(InlaySplice {
 3836            to_remove,
 3837            to_insert,
 3838        }) = self.inlay_hint_cache.spawn_hint_refresh(
 3839            reason_description,
 3840            self.excerpts_for_inlay_hints_query(required_languages.as_ref(), cx),
 3841            invalidate_cache,
 3842            ignore_debounce,
 3843            cx,
 3844        ) {
 3845            self.splice_inlays(&to_remove, to_insert, cx);
 3846        }
 3847    }
 3848
 3849    fn visible_inlay_hints(&self, cx: &Context<Editor>) -> Vec<Inlay> {
 3850        self.display_map
 3851            .read(cx)
 3852            .current_inlays()
 3853            .filter(move |inlay| matches!(inlay.id, InlayId::Hint(_)))
 3854            .cloned()
 3855            .collect()
 3856    }
 3857
 3858    pub fn excerpts_for_inlay_hints_query(
 3859        &self,
 3860        restrict_to_languages: Option<&HashSet<Arc<Language>>>,
 3861        cx: &mut Context<Editor>,
 3862    ) -> HashMap<ExcerptId, (Entity<Buffer>, clock::Global, Range<usize>)> {
 3863        let Some(project) = self.project.as_ref() else {
 3864            return HashMap::default();
 3865        };
 3866        let project = project.read(cx);
 3867        let multi_buffer = self.buffer().read(cx);
 3868        let multi_buffer_snapshot = multi_buffer.snapshot(cx);
 3869        let multi_buffer_visible_start = self
 3870            .scroll_manager
 3871            .anchor()
 3872            .anchor
 3873            .to_point(&multi_buffer_snapshot);
 3874        let multi_buffer_visible_end = multi_buffer_snapshot.clip_point(
 3875            multi_buffer_visible_start
 3876                + Point::new(self.visible_line_count().unwrap_or(0.).ceil() as u32, 0),
 3877            Bias::Left,
 3878        );
 3879        let multi_buffer_visible_range = multi_buffer_visible_start..multi_buffer_visible_end;
 3880        multi_buffer_snapshot
 3881            .range_to_buffer_ranges(multi_buffer_visible_range)
 3882            .into_iter()
 3883            .filter(|(_, excerpt_visible_range, _)| !excerpt_visible_range.is_empty())
 3884            .filter_map(|(buffer, excerpt_visible_range, excerpt_id)| {
 3885                let buffer_file = project::File::from_dyn(buffer.file())?;
 3886                let buffer_worktree = project.worktree_for_id(buffer_file.worktree_id(cx), cx)?;
 3887                let worktree_entry = buffer_worktree
 3888                    .read(cx)
 3889                    .entry_for_id(buffer_file.project_entry_id(cx)?)?;
 3890                if worktree_entry.is_ignored {
 3891                    return None;
 3892                }
 3893
 3894                let language = buffer.language()?;
 3895                if let Some(restrict_to_languages) = restrict_to_languages {
 3896                    if !restrict_to_languages.contains(language) {
 3897                        return None;
 3898                    }
 3899                }
 3900                Some((
 3901                    excerpt_id,
 3902                    (
 3903                        multi_buffer.buffer(buffer.remote_id()).unwrap(),
 3904                        buffer.version().clone(),
 3905                        excerpt_visible_range,
 3906                    ),
 3907                ))
 3908            })
 3909            .collect()
 3910    }
 3911
 3912    pub fn text_layout_details(&self, window: &mut Window) -> TextLayoutDetails {
 3913        TextLayoutDetails {
 3914            text_system: window.text_system().clone(),
 3915            editor_style: self.style.clone().unwrap(),
 3916            rem_size: window.rem_size(),
 3917            scroll_anchor: self.scroll_manager.anchor(),
 3918            visible_rows: self.visible_line_count(),
 3919            vertical_scroll_margin: self.scroll_manager.vertical_scroll_margin,
 3920        }
 3921    }
 3922
 3923    pub fn splice_inlays(
 3924        &self,
 3925        to_remove: &[InlayId],
 3926        to_insert: Vec<Inlay>,
 3927        cx: &mut Context<Self>,
 3928    ) {
 3929        self.display_map.update(cx, |display_map, cx| {
 3930            display_map.splice_inlays(to_remove, to_insert, cx)
 3931        });
 3932        cx.notify();
 3933    }
 3934
 3935    fn trigger_on_type_formatting(
 3936        &self,
 3937        input: String,
 3938        window: &mut Window,
 3939        cx: &mut Context<Self>,
 3940    ) -> Option<Task<Result<()>>> {
 3941        if input.len() != 1 {
 3942            return None;
 3943        }
 3944
 3945        let project = self.project.as_ref()?;
 3946        let position = self.selections.newest_anchor().head();
 3947        let (buffer, buffer_position) = self
 3948            .buffer
 3949            .read(cx)
 3950            .text_anchor_for_position(position, cx)?;
 3951
 3952        let settings = language_settings::language_settings(
 3953            buffer
 3954                .read(cx)
 3955                .language_at(buffer_position)
 3956                .map(|l| l.name()),
 3957            buffer.read(cx).file(),
 3958            cx,
 3959        );
 3960        if !settings.use_on_type_format {
 3961            return None;
 3962        }
 3963
 3964        // OnTypeFormatting returns a list of edits, no need to pass them between Zed instances,
 3965        // hence we do LSP request & edit on host side only — add formats to host's history.
 3966        let push_to_lsp_host_history = true;
 3967        // If this is not the host, append its history with new edits.
 3968        let push_to_client_history = project.read(cx).is_via_collab();
 3969
 3970        let on_type_formatting = project.update(cx, |project, cx| {
 3971            project.on_type_format(
 3972                buffer.clone(),
 3973                buffer_position,
 3974                input,
 3975                push_to_lsp_host_history,
 3976                cx,
 3977            )
 3978        });
 3979        Some(cx.spawn_in(window, |editor, mut cx| async move {
 3980            if let Some(transaction) = on_type_formatting.await? {
 3981                if push_to_client_history {
 3982                    buffer
 3983                        .update(&mut cx, |buffer, _| {
 3984                            buffer.push_transaction(transaction, Instant::now());
 3985                        })
 3986                        .ok();
 3987                }
 3988                editor.update(&mut cx, |editor, cx| {
 3989                    editor.refresh_document_highlights(cx);
 3990                })?;
 3991            }
 3992            Ok(())
 3993        }))
 3994    }
 3995
 3996    pub fn show_completions(
 3997        &mut self,
 3998        options: &ShowCompletions,
 3999        window: &mut Window,
 4000        cx: &mut Context<Self>,
 4001    ) {
 4002        if self.pending_rename.is_some() {
 4003            return;
 4004        }
 4005
 4006        let Some(provider) = self.completion_provider.as_ref() else {
 4007            return;
 4008        };
 4009
 4010        if !self.snippet_stack.is_empty() && self.context_menu.borrow().as_ref().is_some() {
 4011            return;
 4012        }
 4013
 4014        let position = self.selections.newest_anchor().head();
 4015        if position.diff_base_anchor.is_some() {
 4016            return;
 4017        }
 4018        let (buffer, buffer_position) =
 4019            if let Some(output) = self.buffer.read(cx).text_anchor_for_position(position, cx) {
 4020                output
 4021            } else {
 4022                return;
 4023            };
 4024        let show_completion_documentation = buffer
 4025            .read(cx)
 4026            .snapshot()
 4027            .settings_at(buffer_position, cx)
 4028            .show_completion_documentation;
 4029
 4030        let query = Self::completion_query(&self.buffer.read(cx).read(cx), position);
 4031
 4032        let trigger_kind = match &options.trigger {
 4033            Some(trigger) if buffer.read(cx).completion_triggers().contains(trigger) => {
 4034                CompletionTriggerKind::TRIGGER_CHARACTER
 4035            }
 4036            _ => CompletionTriggerKind::INVOKED,
 4037        };
 4038        let completion_context = CompletionContext {
 4039            trigger_character: options.trigger.as_ref().and_then(|trigger| {
 4040                if trigger_kind == CompletionTriggerKind::TRIGGER_CHARACTER {
 4041                    Some(String::from(trigger))
 4042                } else {
 4043                    None
 4044                }
 4045            }),
 4046            trigger_kind,
 4047        };
 4048        let completions =
 4049            provider.completions(&buffer, buffer_position, completion_context, window, cx);
 4050        let sort_completions = provider.sort_completions();
 4051
 4052        let id = post_inc(&mut self.next_completion_id);
 4053        let task = cx.spawn_in(window, |editor, mut cx| {
 4054            async move {
 4055                editor.update(&mut cx, |this, _| {
 4056                    this.completion_tasks.retain(|(task_id, _)| *task_id >= id);
 4057                })?;
 4058                let completions = completions.await.log_err();
 4059                let menu = if let Some(completions) = completions {
 4060                    let mut menu = CompletionsMenu::new(
 4061                        id,
 4062                        sort_completions,
 4063                        show_completion_documentation,
 4064                        position,
 4065                        buffer.clone(),
 4066                        completions.into(),
 4067                    );
 4068
 4069                    menu.filter(query.as_deref(), cx.background_executor().clone())
 4070                        .await;
 4071
 4072                    menu.visible().then_some(menu)
 4073                } else {
 4074                    None
 4075                };
 4076
 4077                editor.update_in(&mut cx, |editor, window, cx| {
 4078                    match editor.context_menu.borrow().as_ref() {
 4079                        None => {}
 4080                        Some(CodeContextMenu::Completions(prev_menu)) => {
 4081                            if prev_menu.id > id {
 4082                                return;
 4083                            }
 4084                        }
 4085                        _ => return,
 4086                    }
 4087
 4088                    if editor.focus_handle.is_focused(window) && menu.is_some() {
 4089                        let mut menu = menu.unwrap();
 4090                        menu.resolve_visible_completions(editor.completion_provider.as_deref(), cx);
 4091
 4092                        *editor.context_menu.borrow_mut() =
 4093                            Some(CodeContextMenu::Completions(menu));
 4094
 4095                        if editor.show_edit_predictions_in_menu() {
 4096                            editor.update_visible_inline_completion(window, cx);
 4097                        } else {
 4098                            editor.discard_inline_completion(false, cx);
 4099                        }
 4100
 4101                        cx.notify();
 4102                    } else if editor.completion_tasks.len() <= 1 {
 4103                        // If there are no more completion tasks and the last menu was
 4104                        // empty, we should hide it.
 4105                        let was_hidden = editor.hide_context_menu(window, cx).is_none();
 4106                        // If it was already hidden and we don't show inline
 4107                        // completions in the menu, we should also show the
 4108                        // inline-completion when available.
 4109                        if was_hidden && editor.show_edit_predictions_in_menu() {
 4110                            editor.update_visible_inline_completion(window, cx);
 4111                        }
 4112                    }
 4113                })?;
 4114
 4115                Ok::<_, anyhow::Error>(())
 4116            }
 4117            .log_err()
 4118        });
 4119
 4120        self.completion_tasks.push((id, task));
 4121    }
 4122
 4123    pub fn confirm_completion(
 4124        &mut self,
 4125        action: &ConfirmCompletion,
 4126        window: &mut Window,
 4127        cx: &mut Context<Self>,
 4128    ) -> Option<Task<Result<()>>> {
 4129        self.do_completion(action.item_ix, CompletionIntent::Complete, window, cx)
 4130    }
 4131
 4132    pub fn compose_completion(
 4133        &mut self,
 4134        action: &ComposeCompletion,
 4135        window: &mut Window,
 4136        cx: &mut Context<Self>,
 4137    ) -> Option<Task<Result<()>>> {
 4138        self.do_completion(action.item_ix, CompletionIntent::Compose, window, cx)
 4139    }
 4140
 4141    fn do_completion(
 4142        &mut self,
 4143        item_ix: Option<usize>,
 4144        intent: CompletionIntent,
 4145        window: &mut Window,
 4146        cx: &mut Context<Editor>,
 4147    ) -> Option<Task<std::result::Result<(), anyhow::Error>>> {
 4148        use language::ToOffset as _;
 4149
 4150        let completions_menu =
 4151            if let CodeContextMenu::Completions(menu) = self.hide_context_menu(window, cx)? {
 4152                menu
 4153            } else {
 4154                return None;
 4155            };
 4156
 4157        let entries = completions_menu.entries.borrow();
 4158        let mat = entries.get(item_ix.unwrap_or(completions_menu.selected_item))?;
 4159        if self.show_edit_predictions_in_menu() {
 4160            self.discard_inline_completion(true, cx);
 4161        }
 4162        let candidate_id = mat.candidate_id;
 4163        drop(entries);
 4164
 4165        let buffer_handle = completions_menu.buffer;
 4166        let completion = completions_menu
 4167            .completions
 4168            .borrow()
 4169            .get(candidate_id)?
 4170            .clone();
 4171        cx.stop_propagation();
 4172
 4173        let snippet;
 4174        let text;
 4175
 4176        if completion.is_snippet() {
 4177            snippet = Some(Snippet::parse(&completion.new_text).log_err()?);
 4178            text = snippet.as_ref().unwrap().text.clone();
 4179        } else {
 4180            snippet = None;
 4181            text = completion.new_text.clone();
 4182        };
 4183        let selections = self.selections.all::<usize>(cx);
 4184        let buffer = buffer_handle.read(cx);
 4185        let old_range = completion.old_range.to_offset(buffer);
 4186        let old_text = buffer.text_for_range(old_range.clone()).collect::<String>();
 4187
 4188        let newest_selection = self.selections.newest_anchor();
 4189        if newest_selection.start.buffer_id != Some(buffer_handle.read(cx).remote_id()) {
 4190            return None;
 4191        }
 4192
 4193        let lookbehind = newest_selection
 4194            .start
 4195            .text_anchor
 4196            .to_offset(buffer)
 4197            .saturating_sub(old_range.start);
 4198        let lookahead = old_range
 4199            .end
 4200            .saturating_sub(newest_selection.end.text_anchor.to_offset(buffer));
 4201        let mut common_prefix_len = old_text
 4202            .bytes()
 4203            .zip(text.bytes())
 4204            .take_while(|(a, b)| a == b)
 4205            .count();
 4206
 4207        let snapshot = self.buffer.read(cx).snapshot(cx);
 4208        let mut range_to_replace: Option<Range<isize>> = None;
 4209        let mut ranges = Vec::new();
 4210        let mut linked_edits = HashMap::<_, Vec<_>>::default();
 4211        for selection in &selections {
 4212            if snapshot.contains_str_at(selection.start.saturating_sub(lookbehind), &old_text) {
 4213                let start = selection.start.saturating_sub(lookbehind);
 4214                let end = selection.end + lookahead;
 4215                if selection.id == newest_selection.id {
 4216                    range_to_replace = Some(
 4217                        ((start + common_prefix_len) as isize - selection.start as isize)
 4218                            ..(end as isize - selection.start as isize),
 4219                    );
 4220                }
 4221                ranges.push(start + common_prefix_len..end);
 4222            } else {
 4223                common_prefix_len = 0;
 4224                ranges.clear();
 4225                ranges.extend(selections.iter().map(|s| {
 4226                    if s.id == newest_selection.id {
 4227                        range_to_replace = Some(
 4228                            old_range.start.to_offset_utf16(&snapshot).0 as isize
 4229                                - selection.start as isize
 4230                                ..old_range.end.to_offset_utf16(&snapshot).0 as isize
 4231                                    - selection.start as isize,
 4232                        );
 4233                        old_range.clone()
 4234                    } else {
 4235                        s.start..s.end
 4236                    }
 4237                }));
 4238                break;
 4239            }
 4240            if !self.linked_edit_ranges.is_empty() {
 4241                let start_anchor = snapshot.anchor_before(selection.head());
 4242                let end_anchor = snapshot.anchor_after(selection.tail());
 4243                if let Some(ranges) = self
 4244                    .linked_editing_ranges_for(start_anchor.text_anchor..end_anchor.text_anchor, cx)
 4245                {
 4246                    for (buffer, edits) in ranges {
 4247                        linked_edits.entry(buffer.clone()).or_default().extend(
 4248                            edits
 4249                                .into_iter()
 4250                                .map(|range| (range, text[common_prefix_len..].to_owned())),
 4251                        );
 4252                    }
 4253                }
 4254            }
 4255        }
 4256        let text = &text[common_prefix_len..];
 4257
 4258        cx.emit(EditorEvent::InputHandled {
 4259            utf16_range_to_replace: range_to_replace,
 4260            text: text.into(),
 4261        });
 4262
 4263        self.transact(window, cx, |this, window, cx| {
 4264            if let Some(mut snippet) = snippet {
 4265                snippet.text = text.to_string();
 4266                for tabstop in snippet
 4267                    .tabstops
 4268                    .iter_mut()
 4269                    .flat_map(|tabstop| tabstop.ranges.iter_mut())
 4270                {
 4271                    tabstop.start -= common_prefix_len as isize;
 4272                    tabstop.end -= common_prefix_len as isize;
 4273                }
 4274
 4275                this.insert_snippet(&ranges, snippet, window, cx).log_err();
 4276            } else {
 4277                this.buffer.update(cx, |buffer, cx| {
 4278                    buffer.edit(
 4279                        ranges.iter().map(|range| (range.clone(), text)),
 4280                        this.autoindent_mode.clone(),
 4281                        cx,
 4282                    );
 4283                });
 4284            }
 4285            for (buffer, edits) in linked_edits {
 4286                buffer.update(cx, |buffer, cx| {
 4287                    let snapshot = buffer.snapshot();
 4288                    let edits = edits
 4289                        .into_iter()
 4290                        .map(|(range, text)| {
 4291                            use text::ToPoint as TP;
 4292                            let end_point = TP::to_point(&range.end, &snapshot);
 4293                            let start_point = TP::to_point(&range.start, &snapshot);
 4294                            (start_point..end_point, text)
 4295                        })
 4296                        .sorted_by_key(|(range, _)| range.start)
 4297                        .collect::<Vec<_>>();
 4298                    buffer.edit(edits, None, cx);
 4299                })
 4300            }
 4301
 4302            this.refresh_inline_completion(true, false, window, cx);
 4303        });
 4304
 4305        let show_new_completions_on_confirm = completion
 4306            .confirm
 4307            .as_ref()
 4308            .map_or(false, |confirm| confirm(intent, window, cx));
 4309        if show_new_completions_on_confirm {
 4310            self.show_completions(&ShowCompletions { trigger: None }, window, cx);
 4311        }
 4312
 4313        let provider = self.completion_provider.as_ref()?;
 4314        drop(completion);
 4315        let apply_edits = provider.apply_additional_edits_for_completion(
 4316            buffer_handle,
 4317            completions_menu.completions.clone(),
 4318            candidate_id,
 4319            true,
 4320            cx,
 4321        );
 4322
 4323        let editor_settings = EditorSettings::get_global(cx);
 4324        if editor_settings.show_signature_help_after_edits || editor_settings.auto_signature_help {
 4325            // After the code completion is finished, users often want to know what signatures are needed.
 4326            // so we should automatically call signature_help
 4327            self.show_signature_help(&ShowSignatureHelp, window, cx);
 4328        }
 4329
 4330        Some(cx.foreground_executor().spawn(async move {
 4331            apply_edits.await?;
 4332            Ok(())
 4333        }))
 4334    }
 4335
 4336    pub fn toggle_code_actions(
 4337        &mut self,
 4338        action: &ToggleCodeActions,
 4339        window: &mut Window,
 4340        cx: &mut Context<Self>,
 4341    ) {
 4342        let mut context_menu = self.context_menu.borrow_mut();
 4343        if let Some(CodeContextMenu::CodeActions(code_actions)) = context_menu.as_ref() {
 4344            if code_actions.deployed_from_indicator == action.deployed_from_indicator {
 4345                // Toggle if we're selecting the same one
 4346                *context_menu = None;
 4347                cx.notify();
 4348                return;
 4349            } else {
 4350                // Otherwise, clear it and start a new one
 4351                *context_menu = None;
 4352                cx.notify();
 4353            }
 4354        }
 4355        drop(context_menu);
 4356        let snapshot = self.snapshot(window, cx);
 4357        let deployed_from_indicator = action.deployed_from_indicator;
 4358        let mut task = self.code_actions_task.take();
 4359        let action = action.clone();
 4360        cx.spawn_in(window, |editor, mut cx| async move {
 4361            while let Some(prev_task) = task {
 4362                prev_task.await.log_err();
 4363                task = editor.update(&mut cx, |this, _| this.code_actions_task.take())?;
 4364            }
 4365
 4366            let spawned_test_task = editor.update_in(&mut cx, |editor, window, cx| {
 4367                if editor.focus_handle.is_focused(window) {
 4368                    let multibuffer_point = action
 4369                        .deployed_from_indicator
 4370                        .map(|row| DisplayPoint::new(row, 0).to_point(&snapshot))
 4371                        .unwrap_or_else(|| editor.selections.newest::<Point>(cx).head());
 4372                    let (buffer, buffer_row) = snapshot
 4373                        .buffer_snapshot
 4374                        .buffer_line_for_row(MultiBufferRow(multibuffer_point.row))
 4375                        .and_then(|(buffer_snapshot, range)| {
 4376                            editor
 4377                                .buffer
 4378                                .read(cx)
 4379                                .buffer(buffer_snapshot.remote_id())
 4380                                .map(|buffer| (buffer, range.start.row))
 4381                        })?;
 4382                    let (_, code_actions) = editor
 4383                        .available_code_actions
 4384                        .clone()
 4385                        .and_then(|(location, code_actions)| {
 4386                            let snapshot = location.buffer.read(cx).snapshot();
 4387                            let point_range = location.range.to_point(&snapshot);
 4388                            let point_range = point_range.start.row..=point_range.end.row;
 4389                            if point_range.contains(&buffer_row) {
 4390                                Some((location, code_actions))
 4391                            } else {
 4392                                None
 4393                            }
 4394                        })
 4395                        .unzip();
 4396                    let buffer_id = buffer.read(cx).remote_id();
 4397                    let tasks = editor
 4398                        .tasks
 4399                        .get(&(buffer_id, buffer_row))
 4400                        .map(|t| Arc::new(t.to_owned()));
 4401                    if tasks.is_none() && code_actions.is_none() {
 4402                        return None;
 4403                    }
 4404
 4405                    editor.completion_tasks.clear();
 4406                    editor.discard_inline_completion(false, cx);
 4407                    let task_context =
 4408                        tasks
 4409                            .as_ref()
 4410                            .zip(editor.project.clone())
 4411                            .map(|(tasks, project)| {
 4412                                Self::build_tasks_context(&project, &buffer, buffer_row, tasks, cx)
 4413                            });
 4414
 4415                    Some(cx.spawn_in(window, |editor, mut cx| async move {
 4416                        let task_context = match task_context {
 4417                            Some(task_context) => task_context.await,
 4418                            None => None,
 4419                        };
 4420                        let resolved_tasks =
 4421                            tasks.zip(task_context).map(|(tasks, task_context)| {
 4422                                Rc::new(ResolvedTasks {
 4423                                    templates: tasks.resolve(&task_context).collect(),
 4424                                    position: snapshot.buffer_snapshot.anchor_before(Point::new(
 4425                                        multibuffer_point.row,
 4426                                        tasks.column,
 4427                                    )),
 4428                                })
 4429                            });
 4430                        let spawn_straight_away = resolved_tasks
 4431                            .as_ref()
 4432                            .map_or(false, |tasks| tasks.templates.len() == 1)
 4433                            && code_actions
 4434                                .as_ref()
 4435                                .map_or(true, |actions| actions.is_empty());
 4436                        if let Ok(task) = editor.update_in(&mut cx, |editor, window, cx| {
 4437                            *editor.context_menu.borrow_mut() =
 4438                                Some(CodeContextMenu::CodeActions(CodeActionsMenu {
 4439                                    buffer,
 4440                                    actions: CodeActionContents {
 4441                                        tasks: resolved_tasks,
 4442                                        actions: code_actions,
 4443                                    },
 4444                                    selected_item: Default::default(),
 4445                                    scroll_handle: UniformListScrollHandle::default(),
 4446                                    deployed_from_indicator,
 4447                                }));
 4448                            if spawn_straight_away {
 4449                                if let Some(task) = editor.confirm_code_action(
 4450                                    &ConfirmCodeAction { item_ix: Some(0) },
 4451                                    window,
 4452                                    cx,
 4453                                ) {
 4454                                    cx.notify();
 4455                                    return task;
 4456                                }
 4457                            }
 4458                            cx.notify();
 4459                            Task::ready(Ok(()))
 4460                        }) {
 4461                            task.await
 4462                        } else {
 4463                            Ok(())
 4464                        }
 4465                    }))
 4466                } else {
 4467                    Some(Task::ready(Ok(())))
 4468                }
 4469            })?;
 4470            if let Some(task) = spawned_test_task {
 4471                task.await?;
 4472            }
 4473
 4474            Ok::<_, anyhow::Error>(())
 4475        })
 4476        .detach_and_log_err(cx);
 4477    }
 4478
 4479    pub fn confirm_code_action(
 4480        &mut self,
 4481        action: &ConfirmCodeAction,
 4482        window: &mut Window,
 4483        cx: &mut Context<Self>,
 4484    ) -> Option<Task<Result<()>>> {
 4485        let actions_menu =
 4486            if let CodeContextMenu::CodeActions(menu) = self.hide_context_menu(window, cx)? {
 4487                menu
 4488            } else {
 4489                return None;
 4490            };
 4491        let action_ix = action.item_ix.unwrap_or(actions_menu.selected_item);
 4492        let action = actions_menu.actions.get(action_ix)?;
 4493        let title = action.label();
 4494        let buffer = actions_menu.buffer;
 4495        let workspace = self.workspace()?;
 4496
 4497        match action {
 4498            CodeActionsItem::Task(task_source_kind, resolved_task) => {
 4499                workspace.update(cx, |workspace, cx| {
 4500                    workspace::tasks::schedule_resolved_task(
 4501                        workspace,
 4502                        task_source_kind,
 4503                        resolved_task,
 4504                        false,
 4505                        cx,
 4506                    );
 4507
 4508                    Some(Task::ready(Ok(())))
 4509                })
 4510            }
 4511            CodeActionsItem::CodeAction {
 4512                excerpt_id,
 4513                action,
 4514                provider,
 4515            } => {
 4516                let apply_code_action =
 4517                    provider.apply_code_action(buffer, action, excerpt_id, true, window, cx);
 4518                let workspace = workspace.downgrade();
 4519                Some(cx.spawn_in(window, |editor, cx| async move {
 4520                    let project_transaction = apply_code_action.await?;
 4521                    Self::open_project_transaction(
 4522                        &editor,
 4523                        workspace,
 4524                        project_transaction,
 4525                        title,
 4526                        cx,
 4527                    )
 4528                    .await
 4529                }))
 4530            }
 4531        }
 4532    }
 4533
 4534    pub async fn open_project_transaction(
 4535        this: &WeakEntity<Editor>,
 4536        workspace: WeakEntity<Workspace>,
 4537        transaction: ProjectTransaction,
 4538        title: String,
 4539        mut cx: AsyncWindowContext,
 4540    ) -> Result<()> {
 4541        let mut entries = transaction.0.into_iter().collect::<Vec<_>>();
 4542        cx.update(|_, cx| {
 4543            entries.sort_unstable_by_key(|(buffer, _)| {
 4544                buffer.read(cx).file().map(|f| f.path().clone())
 4545            });
 4546        })?;
 4547
 4548        // If the project transaction's edits are all contained within this editor, then
 4549        // avoid opening a new editor to display them.
 4550
 4551        if let Some((buffer, transaction)) = entries.first() {
 4552            if entries.len() == 1 {
 4553                let excerpt = this.update(&mut cx, |editor, cx| {
 4554                    editor
 4555                        .buffer()
 4556                        .read(cx)
 4557                        .excerpt_containing(editor.selections.newest_anchor().head(), cx)
 4558                })?;
 4559                if let Some((_, excerpted_buffer, excerpt_range)) = excerpt {
 4560                    if excerpted_buffer == *buffer {
 4561                        let all_edits_within_excerpt = buffer.read_with(&cx, |buffer, _| {
 4562                            let excerpt_range = excerpt_range.to_offset(buffer);
 4563                            buffer
 4564                                .edited_ranges_for_transaction::<usize>(transaction)
 4565                                .all(|range| {
 4566                                    excerpt_range.start <= range.start
 4567                                        && excerpt_range.end >= range.end
 4568                                })
 4569                        })?;
 4570
 4571                        if all_edits_within_excerpt {
 4572                            return Ok(());
 4573                        }
 4574                    }
 4575                }
 4576            }
 4577        } else {
 4578            return Ok(());
 4579        }
 4580
 4581        let mut ranges_to_highlight = Vec::new();
 4582        let excerpt_buffer = cx.new(|cx| {
 4583            let mut multibuffer = MultiBuffer::new(Capability::ReadWrite).with_title(title);
 4584            for (buffer_handle, transaction) in &entries {
 4585                let buffer = buffer_handle.read(cx);
 4586                ranges_to_highlight.extend(
 4587                    multibuffer.push_excerpts_with_context_lines(
 4588                        buffer_handle.clone(),
 4589                        buffer
 4590                            .edited_ranges_for_transaction::<usize>(transaction)
 4591                            .collect(),
 4592                        DEFAULT_MULTIBUFFER_CONTEXT,
 4593                        cx,
 4594                    ),
 4595                );
 4596            }
 4597            multibuffer.push_transaction(entries.iter().map(|(b, t)| (b, t)), cx);
 4598            multibuffer
 4599        })?;
 4600
 4601        workspace.update_in(&mut cx, |workspace, window, cx| {
 4602            let project = workspace.project().clone();
 4603            let editor = cx
 4604                .new(|cx| Editor::for_multibuffer(excerpt_buffer, Some(project), true, window, cx));
 4605            workspace.add_item_to_active_pane(Box::new(editor.clone()), None, true, window, cx);
 4606            editor.update(cx, |editor, cx| {
 4607                editor.highlight_background::<Self>(
 4608                    &ranges_to_highlight,
 4609                    |theme| theme.editor_highlighted_line_background,
 4610                    cx,
 4611                );
 4612            });
 4613        })?;
 4614
 4615        Ok(())
 4616    }
 4617
 4618    pub fn clear_code_action_providers(&mut self) {
 4619        self.code_action_providers.clear();
 4620        self.available_code_actions.take();
 4621    }
 4622
 4623    pub fn add_code_action_provider(
 4624        &mut self,
 4625        provider: Rc<dyn CodeActionProvider>,
 4626        window: &mut Window,
 4627        cx: &mut Context<Self>,
 4628    ) {
 4629        if self
 4630            .code_action_providers
 4631            .iter()
 4632            .any(|existing_provider| existing_provider.id() == provider.id())
 4633        {
 4634            return;
 4635        }
 4636
 4637        self.code_action_providers.push(provider);
 4638        self.refresh_code_actions(window, cx);
 4639    }
 4640
 4641    pub fn remove_code_action_provider(
 4642        &mut self,
 4643        id: Arc<str>,
 4644        window: &mut Window,
 4645        cx: &mut Context<Self>,
 4646    ) {
 4647        self.code_action_providers
 4648            .retain(|provider| provider.id() != id);
 4649        self.refresh_code_actions(window, cx);
 4650    }
 4651
 4652    fn refresh_code_actions(&mut self, window: &mut Window, cx: &mut Context<Self>) -> Option<()> {
 4653        let buffer = self.buffer.read(cx);
 4654        let newest_selection = self.selections.newest_anchor().clone();
 4655        if newest_selection.head().diff_base_anchor.is_some() {
 4656            return None;
 4657        }
 4658        let (start_buffer, start) = buffer.text_anchor_for_position(newest_selection.start, cx)?;
 4659        let (end_buffer, end) = buffer.text_anchor_for_position(newest_selection.end, cx)?;
 4660        if start_buffer != end_buffer {
 4661            return None;
 4662        }
 4663
 4664        self.code_actions_task = Some(cx.spawn_in(window, |this, mut cx| async move {
 4665            cx.background_executor()
 4666                .timer(CODE_ACTIONS_DEBOUNCE_TIMEOUT)
 4667                .await;
 4668
 4669            let (providers, tasks) = this.update_in(&mut cx, |this, window, cx| {
 4670                let providers = this.code_action_providers.clone();
 4671                let tasks = this
 4672                    .code_action_providers
 4673                    .iter()
 4674                    .map(|provider| provider.code_actions(&start_buffer, start..end, window, cx))
 4675                    .collect::<Vec<_>>();
 4676                (providers, tasks)
 4677            })?;
 4678
 4679            let mut actions = Vec::new();
 4680            for (provider, provider_actions) in
 4681                providers.into_iter().zip(future::join_all(tasks).await)
 4682            {
 4683                if let Some(provider_actions) = provider_actions.log_err() {
 4684                    actions.extend(provider_actions.into_iter().map(|action| {
 4685                        AvailableCodeAction {
 4686                            excerpt_id: newest_selection.start.excerpt_id,
 4687                            action,
 4688                            provider: provider.clone(),
 4689                        }
 4690                    }));
 4691                }
 4692            }
 4693
 4694            this.update(&mut cx, |this, cx| {
 4695                this.available_code_actions = if actions.is_empty() {
 4696                    None
 4697                } else {
 4698                    Some((
 4699                        Location {
 4700                            buffer: start_buffer,
 4701                            range: start..end,
 4702                        },
 4703                        actions.into(),
 4704                    ))
 4705                };
 4706                cx.notify();
 4707            })
 4708        }));
 4709        None
 4710    }
 4711
 4712    fn start_inline_blame_timer(&mut self, window: &mut Window, cx: &mut Context<Self>) {
 4713        if let Some(delay) = ProjectSettings::get_global(cx).git.inline_blame_delay() {
 4714            self.show_git_blame_inline = false;
 4715
 4716            self.show_git_blame_inline_delay_task =
 4717                Some(cx.spawn_in(window, |this, mut cx| async move {
 4718                    cx.background_executor().timer(delay).await;
 4719
 4720                    this.update(&mut cx, |this, cx| {
 4721                        this.show_git_blame_inline = true;
 4722                        cx.notify();
 4723                    })
 4724                    .log_err();
 4725                }));
 4726        }
 4727    }
 4728
 4729    fn refresh_document_highlights(&mut self, cx: &mut Context<Self>) -> Option<()> {
 4730        if self.pending_rename.is_some() {
 4731            return None;
 4732        }
 4733
 4734        let provider = self.semantics_provider.clone()?;
 4735        let buffer = self.buffer.read(cx);
 4736        let newest_selection = self.selections.newest_anchor().clone();
 4737        let cursor_position = newest_selection.head();
 4738        let (cursor_buffer, cursor_buffer_position) =
 4739            buffer.text_anchor_for_position(cursor_position, cx)?;
 4740        let (tail_buffer, _) = buffer.text_anchor_for_position(newest_selection.tail(), cx)?;
 4741        if cursor_buffer != tail_buffer {
 4742            return None;
 4743        }
 4744        let debounce = EditorSettings::get_global(cx).lsp_highlight_debounce;
 4745        self.document_highlights_task = Some(cx.spawn(|this, mut cx| async move {
 4746            cx.background_executor()
 4747                .timer(Duration::from_millis(debounce))
 4748                .await;
 4749
 4750            let highlights = if let Some(highlights) = cx
 4751                .update(|cx| {
 4752                    provider.document_highlights(&cursor_buffer, cursor_buffer_position, cx)
 4753                })
 4754                .ok()
 4755                .flatten()
 4756            {
 4757                highlights.await.log_err()
 4758            } else {
 4759                None
 4760            };
 4761
 4762            if let Some(highlights) = highlights {
 4763                this.update(&mut cx, |this, cx| {
 4764                    if this.pending_rename.is_some() {
 4765                        return;
 4766                    }
 4767
 4768                    let buffer_id = cursor_position.buffer_id;
 4769                    let buffer = this.buffer.read(cx);
 4770                    if !buffer
 4771                        .text_anchor_for_position(cursor_position, cx)
 4772                        .map_or(false, |(buffer, _)| buffer == cursor_buffer)
 4773                    {
 4774                        return;
 4775                    }
 4776
 4777                    let cursor_buffer_snapshot = cursor_buffer.read(cx);
 4778                    let mut write_ranges = Vec::new();
 4779                    let mut read_ranges = Vec::new();
 4780                    for highlight in highlights {
 4781                        for (excerpt_id, excerpt_range) in
 4782                            buffer.excerpts_for_buffer(cursor_buffer.read(cx).remote_id(), cx)
 4783                        {
 4784                            let start = highlight
 4785                                .range
 4786                                .start
 4787                                .max(&excerpt_range.context.start, cursor_buffer_snapshot);
 4788                            let end = highlight
 4789                                .range
 4790                                .end
 4791                                .min(&excerpt_range.context.end, cursor_buffer_snapshot);
 4792                            if start.cmp(&end, cursor_buffer_snapshot).is_ge() {
 4793                                continue;
 4794                            }
 4795
 4796                            let range = Anchor {
 4797                                buffer_id,
 4798                                excerpt_id,
 4799                                text_anchor: start,
 4800                                diff_base_anchor: None,
 4801                            }..Anchor {
 4802                                buffer_id,
 4803                                excerpt_id,
 4804                                text_anchor: end,
 4805                                diff_base_anchor: None,
 4806                            };
 4807                            if highlight.kind == lsp::DocumentHighlightKind::WRITE {
 4808                                write_ranges.push(range);
 4809                            } else {
 4810                                read_ranges.push(range);
 4811                            }
 4812                        }
 4813                    }
 4814
 4815                    this.highlight_background::<DocumentHighlightRead>(
 4816                        &read_ranges,
 4817                        |theme| theme.editor_document_highlight_read_background,
 4818                        cx,
 4819                    );
 4820                    this.highlight_background::<DocumentHighlightWrite>(
 4821                        &write_ranges,
 4822                        |theme| theme.editor_document_highlight_write_background,
 4823                        cx,
 4824                    );
 4825                    cx.notify();
 4826                })
 4827                .log_err();
 4828            }
 4829        }));
 4830        None
 4831    }
 4832
 4833    pub fn refresh_selected_text_highlights(
 4834        &mut self,
 4835        window: &mut Window,
 4836        cx: &mut Context<Editor>,
 4837    ) {
 4838        self.selection_highlight_task.take();
 4839        if !EditorSettings::get_global(cx).selection_highlight {
 4840            self.clear_background_highlights::<SelectedTextHighlight>(cx);
 4841            return;
 4842        }
 4843        if self.selections.count() != 1 || self.selections.line_mode {
 4844            self.clear_background_highlights::<SelectedTextHighlight>(cx);
 4845            return;
 4846        }
 4847        let selection = self.selections.newest::<Point>(cx);
 4848        if selection.is_empty() || selection.start.row != selection.end.row {
 4849            self.clear_background_highlights::<SelectedTextHighlight>(cx);
 4850            return;
 4851        }
 4852        let debounce = EditorSettings::get_global(cx).selection_highlight_debounce;
 4853        self.selection_highlight_task = Some(cx.spawn_in(window, |editor, mut cx| async move {
 4854            cx.background_executor()
 4855                .timer(Duration::from_millis(debounce))
 4856                .await;
 4857            let Some(Some(matches_task)) = editor
 4858                .update_in(&mut cx, |editor, _, cx| {
 4859                    if editor.selections.count() != 1 || editor.selections.line_mode {
 4860                        editor.clear_background_highlights::<SelectedTextHighlight>(cx);
 4861                        return None;
 4862                    }
 4863                    let selection = editor.selections.newest::<Point>(cx);
 4864                    if selection.is_empty() || selection.start.row != selection.end.row {
 4865                        editor.clear_background_highlights::<SelectedTextHighlight>(cx);
 4866                        return None;
 4867                    }
 4868                    let buffer = editor.buffer().read(cx).snapshot(cx);
 4869                    let query = buffer.text_for_range(selection.range()).collect::<String>();
 4870                    if query.trim().is_empty() {
 4871                        editor.clear_background_highlights::<SelectedTextHighlight>(cx);
 4872                        return None;
 4873                    }
 4874                    Some(cx.background_spawn(async move {
 4875                        let mut ranges = Vec::new();
 4876                        let selection_anchors = selection.range().to_anchors(&buffer);
 4877                        for range in [buffer.anchor_before(0)..buffer.anchor_after(buffer.len())] {
 4878                            for (search_buffer, search_range, excerpt_id) in
 4879                                buffer.range_to_buffer_ranges(range)
 4880                            {
 4881                                ranges.extend(
 4882                                    project::search::SearchQuery::text(
 4883                                        query.clone(),
 4884                                        false,
 4885                                        false,
 4886                                        false,
 4887                                        Default::default(),
 4888                                        Default::default(),
 4889                                        None,
 4890                                    )
 4891                                    .unwrap()
 4892                                    .search(search_buffer, Some(search_range.clone()))
 4893                                    .await
 4894                                    .into_iter()
 4895                                    .filter_map(
 4896                                        |match_range| {
 4897                                            let start = search_buffer.anchor_after(
 4898                                                search_range.start + match_range.start,
 4899                                            );
 4900                                            let end = search_buffer.anchor_before(
 4901                                                search_range.start + match_range.end,
 4902                                            );
 4903                                            let range = Anchor::range_in_buffer(
 4904                                                excerpt_id,
 4905                                                search_buffer.remote_id(),
 4906                                                start..end,
 4907                                            );
 4908                                            (range != selection_anchors).then_some(range)
 4909                                        },
 4910                                    ),
 4911                                );
 4912                            }
 4913                        }
 4914                        ranges
 4915                    }))
 4916                })
 4917                .log_err()
 4918            else {
 4919                return;
 4920            };
 4921            let matches = matches_task.await;
 4922            editor
 4923                .update_in(&mut cx, |editor, _, cx| {
 4924                    editor.clear_background_highlights::<SelectedTextHighlight>(cx);
 4925                    if !matches.is_empty() {
 4926                        editor.highlight_background::<SelectedTextHighlight>(
 4927                            &matches,
 4928                            |theme| theme.editor_document_highlight_bracket_background,
 4929                            cx,
 4930                        )
 4931                    }
 4932                })
 4933                .log_err();
 4934        }));
 4935    }
 4936
 4937    pub fn refresh_inline_completion(
 4938        &mut self,
 4939        debounce: bool,
 4940        user_requested: bool,
 4941        window: &mut Window,
 4942        cx: &mut Context<Self>,
 4943    ) -> Option<()> {
 4944        let provider = self.edit_prediction_provider()?;
 4945        let cursor = self.selections.newest_anchor().head();
 4946        let (buffer, cursor_buffer_position) =
 4947            self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
 4948
 4949        if !self.edit_predictions_enabled_in_buffer(&buffer, cursor_buffer_position, cx) {
 4950            self.discard_inline_completion(false, cx);
 4951            return None;
 4952        }
 4953
 4954        if !user_requested
 4955            && (!self.should_show_edit_predictions()
 4956                || !self.is_focused(window)
 4957                || buffer.read(cx).is_empty())
 4958        {
 4959            self.discard_inline_completion(false, cx);
 4960            return None;
 4961        }
 4962
 4963        self.update_visible_inline_completion(window, cx);
 4964        provider.refresh(
 4965            self.project.clone(),
 4966            buffer,
 4967            cursor_buffer_position,
 4968            debounce,
 4969            cx,
 4970        );
 4971        Some(())
 4972    }
 4973
 4974    fn show_edit_predictions_in_menu(&self) -> bool {
 4975        match self.edit_prediction_settings {
 4976            EditPredictionSettings::Disabled => false,
 4977            EditPredictionSettings::Enabled { show_in_menu, .. } => show_in_menu,
 4978        }
 4979    }
 4980
 4981    pub fn edit_predictions_enabled(&self) -> bool {
 4982        match self.edit_prediction_settings {
 4983            EditPredictionSettings::Disabled => false,
 4984            EditPredictionSettings::Enabled { .. } => true,
 4985        }
 4986    }
 4987
 4988    fn edit_prediction_requires_modifier(&self) -> bool {
 4989        match self.edit_prediction_settings {
 4990            EditPredictionSettings::Disabled => false,
 4991            EditPredictionSettings::Enabled {
 4992                preview_requires_modifier,
 4993                ..
 4994            } => preview_requires_modifier,
 4995        }
 4996    }
 4997
 4998    pub fn update_edit_prediction_settings(&mut self, cx: &mut Context<Self>) {
 4999        if self.edit_prediction_provider.is_none() {
 5000            self.edit_prediction_settings = EditPredictionSettings::Disabled;
 5001        } else {
 5002            let selection = self.selections.newest_anchor();
 5003            let cursor = selection.head();
 5004
 5005            if let Some((buffer, cursor_buffer_position)) =
 5006                self.buffer.read(cx).text_anchor_for_position(cursor, cx)
 5007            {
 5008                self.edit_prediction_settings =
 5009                    self.edit_prediction_settings_at_position(&buffer, cursor_buffer_position, cx);
 5010            }
 5011        }
 5012    }
 5013
 5014    fn edit_prediction_settings_at_position(
 5015        &self,
 5016        buffer: &Entity<Buffer>,
 5017        buffer_position: language::Anchor,
 5018        cx: &App,
 5019    ) -> EditPredictionSettings {
 5020        if self.mode != EditorMode::Full
 5021            || !self.show_inline_completions_override.unwrap_or(true)
 5022            || self.inline_completions_disabled_in_scope(buffer, buffer_position, cx)
 5023        {
 5024            return EditPredictionSettings::Disabled;
 5025        }
 5026
 5027        let buffer = buffer.read(cx);
 5028
 5029        let file = buffer.file();
 5030
 5031        if !language_settings(buffer.language().map(|l| l.name()), file, cx).show_edit_predictions {
 5032            return EditPredictionSettings::Disabled;
 5033        };
 5034
 5035        let by_provider = matches!(
 5036            self.menu_inline_completions_policy,
 5037            MenuInlineCompletionsPolicy::ByProvider
 5038        );
 5039
 5040        let show_in_menu = by_provider
 5041            && self
 5042                .edit_prediction_provider
 5043                .as_ref()
 5044                .map_or(false, |provider| {
 5045                    provider.provider.show_completions_in_menu()
 5046                });
 5047
 5048        let preview_requires_modifier =
 5049            all_language_settings(file, cx).edit_predictions_mode() == EditPredictionsMode::Subtle;
 5050
 5051        EditPredictionSettings::Enabled {
 5052            show_in_menu,
 5053            preview_requires_modifier,
 5054        }
 5055    }
 5056
 5057    fn should_show_edit_predictions(&self) -> bool {
 5058        self.snippet_stack.is_empty() && self.edit_predictions_enabled()
 5059    }
 5060
 5061    pub fn edit_prediction_preview_is_active(&self) -> bool {
 5062        matches!(
 5063            self.edit_prediction_preview,
 5064            EditPredictionPreview::Active { .. }
 5065        )
 5066    }
 5067
 5068    pub fn edit_predictions_enabled_at_cursor(&self, cx: &App) -> bool {
 5069        let cursor = self.selections.newest_anchor().head();
 5070        if let Some((buffer, cursor_position)) =
 5071            self.buffer.read(cx).text_anchor_for_position(cursor, cx)
 5072        {
 5073            self.edit_predictions_enabled_in_buffer(&buffer, cursor_position, cx)
 5074        } else {
 5075            false
 5076        }
 5077    }
 5078
 5079    fn edit_predictions_enabled_in_buffer(
 5080        &self,
 5081        buffer: &Entity<Buffer>,
 5082        buffer_position: language::Anchor,
 5083        cx: &App,
 5084    ) -> bool {
 5085        maybe!({
 5086            let provider = self.edit_prediction_provider()?;
 5087            if !provider.is_enabled(&buffer, buffer_position, cx) {
 5088                return Some(false);
 5089            }
 5090            let buffer = buffer.read(cx);
 5091            let Some(file) = buffer.file() else {
 5092                return Some(true);
 5093            };
 5094            let settings = all_language_settings(Some(file), cx);
 5095            Some(settings.edit_predictions_enabled_for_file(file, cx))
 5096        })
 5097        .unwrap_or(false)
 5098    }
 5099
 5100    fn cycle_inline_completion(
 5101        &mut self,
 5102        direction: Direction,
 5103        window: &mut Window,
 5104        cx: &mut Context<Self>,
 5105    ) -> Option<()> {
 5106        let provider = self.edit_prediction_provider()?;
 5107        let cursor = self.selections.newest_anchor().head();
 5108        let (buffer, cursor_buffer_position) =
 5109            self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
 5110        if self.inline_completions_hidden_for_vim_mode || !self.should_show_edit_predictions() {
 5111            return None;
 5112        }
 5113
 5114        provider.cycle(buffer, cursor_buffer_position, direction, cx);
 5115        self.update_visible_inline_completion(window, cx);
 5116
 5117        Some(())
 5118    }
 5119
 5120    pub fn show_inline_completion(
 5121        &mut self,
 5122        _: &ShowEditPrediction,
 5123        window: &mut Window,
 5124        cx: &mut Context<Self>,
 5125    ) {
 5126        if !self.has_active_inline_completion() {
 5127            self.refresh_inline_completion(false, true, window, cx);
 5128            return;
 5129        }
 5130
 5131        self.update_visible_inline_completion(window, cx);
 5132    }
 5133
 5134    pub fn display_cursor_names(
 5135        &mut self,
 5136        _: &DisplayCursorNames,
 5137        window: &mut Window,
 5138        cx: &mut Context<Self>,
 5139    ) {
 5140        self.show_cursor_names(window, cx);
 5141    }
 5142
 5143    fn show_cursor_names(&mut self, window: &mut Window, cx: &mut Context<Self>) {
 5144        self.show_cursor_names = true;
 5145        cx.notify();
 5146        cx.spawn_in(window, |this, mut cx| async move {
 5147            cx.background_executor().timer(CURSORS_VISIBLE_FOR).await;
 5148            this.update(&mut cx, |this, cx| {
 5149                this.show_cursor_names = false;
 5150                cx.notify()
 5151            })
 5152            .ok()
 5153        })
 5154        .detach();
 5155    }
 5156
 5157    pub fn next_edit_prediction(
 5158        &mut self,
 5159        _: &NextEditPrediction,
 5160        window: &mut Window,
 5161        cx: &mut Context<Self>,
 5162    ) {
 5163        if self.has_active_inline_completion() {
 5164            self.cycle_inline_completion(Direction::Next, window, cx);
 5165        } else {
 5166            let is_copilot_disabled = self
 5167                .refresh_inline_completion(false, true, window, cx)
 5168                .is_none();
 5169            if is_copilot_disabled {
 5170                cx.propagate();
 5171            }
 5172        }
 5173    }
 5174
 5175    pub fn previous_edit_prediction(
 5176        &mut self,
 5177        _: &PreviousEditPrediction,
 5178        window: &mut Window,
 5179        cx: &mut Context<Self>,
 5180    ) {
 5181        if self.has_active_inline_completion() {
 5182            self.cycle_inline_completion(Direction::Prev, window, cx);
 5183        } else {
 5184            let is_copilot_disabled = self
 5185                .refresh_inline_completion(false, true, window, cx)
 5186                .is_none();
 5187            if is_copilot_disabled {
 5188                cx.propagate();
 5189            }
 5190        }
 5191    }
 5192
 5193    pub fn accept_edit_prediction(
 5194        &mut self,
 5195        _: &AcceptEditPrediction,
 5196        window: &mut Window,
 5197        cx: &mut Context<Self>,
 5198    ) {
 5199        if self.show_edit_predictions_in_menu() {
 5200            self.hide_context_menu(window, cx);
 5201        }
 5202
 5203        let Some(active_inline_completion) = self.active_inline_completion.as_ref() else {
 5204            return;
 5205        };
 5206
 5207        self.report_inline_completion_event(
 5208            active_inline_completion.completion_id.clone(),
 5209            true,
 5210            cx,
 5211        );
 5212
 5213        match &active_inline_completion.completion {
 5214            InlineCompletion::Move { target, .. } => {
 5215                let target = *target;
 5216
 5217                if let Some(position_map) = &self.last_position_map {
 5218                    if position_map
 5219                        .visible_row_range
 5220                        .contains(&target.to_display_point(&position_map.snapshot).row())
 5221                        || !self.edit_prediction_requires_modifier()
 5222                    {
 5223                        self.unfold_ranges(&[target..target], true, false, cx);
 5224                        // Note that this is also done in vim's handler of the Tab action.
 5225                        self.change_selections(
 5226                            Some(Autoscroll::newest()),
 5227                            window,
 5228                            cx,
 5229                            |selections| {
 5230                                selections.select_anchor_ranges([target..target]);
 5231                            },
 5232                        );
 5233                        self.clear_row_highlights::<EditPredictionPreview>();
 5234
 5235                        self.edit_prediction_preview
 5236                            .set_previous_scroll_position(None);
 5237                    } else {
 5238                        self.edit_prediction_preview
 5239                            .set_previous_scroll_position(Some(
 5240                                position_map.snapshot.scroll_anchor,
 5241                            ));
 5242
 5243                        self.highlight_rows::<EditPredictionPreview>(
 5244                            target..target,
 5245                            cx.theme().colors().editor_highlighted_line_background,
 5246                            true,
 5247                            cx,
 5248                        );
 5249                        self.request_autoscroll(Autoscroll::fit(), cx);
 5250                    }
 5251                }
 5252            }
 5253            InlineCompletion::Edit { edits, .. } => {
 5254                if let Some(provider) = self.edit_prediction_provider() {
 5255                    provider.accept(cx);
 5256                }
 5257
 5258                let snapshot = self.buffer.read(cx).snapshot(cx);
 5259                let last_edit_end = edits.last().unwrap().0.end.bias_right(&snapshot);
 5260
 5261                self.buffer.update(cx, |buffer, cx| {
 5262                    buffer.edit(edits.iter().cloned(), None, cx)
 5263                });
 5264
 5265                self.change_selections(None, window, cx, |s| {
 5266                    s.select_anchor_ranges([last_edit_end..last_edit_end])
 5267                });
 5268
 5269                self.update_visible_inline_completion(window, cx);
 5270                if self.active_inline_completion.is_none() {
 5271                    self.refresh_inline_completion(true, true, window, cx);
 5272                }
 5273
 5274                cx.notify();
 5275            }
 5276        }
 5277
 5278        self.edit_prediction_requires_modifier_in_indent_conflict = false;
 5279    }
 5280
 5281    pub fn accept_partial_inline_completion(
 5282        &mut self,
 5283        _: &AcceptPartialEditPrediction,
 5284        window: &mut Window,
 5285        cx: &mut Context<Self>,
 5286    ) {
 5287        let Some(active_inline_completion) = self.active_inline_completion.as_ref() else {
 5288            return;
 5289        };
 5290        if self.selections.count() != 1 {
 5291            return;
 5292        }
 5293
 5294        self.report_inline_completion_event(
 5295            active_inline_completion.completion_id.clone(),
 5296            true,
 5297            cx,
 5298        );
 5299
 5300        match &active_inline_completion.completion {
 5301            InlineCompletion::Move { target, .. } => {
 5302                let target = *target;
 5303                self.change_selections(Some(Autoscroll::newest()), window, cx, |selections| {
 5304                    selections.select_anchor_ranges([target..target]);
 5305                });
 5306            }
 5307            InlineCompletion::Edit { edits, .. } => {
 5308                // Find an insertion that starts at the cursor position.
 5309                let snapshot = self.buffer.read(cx).snapshot(cx);
 5310                let cursor_offset = self.selections.newest::<usize>(cx).head();
 5311                let insertion = edits.iter().find_map(|(range, text)| {
 5312                    let range = range.to_offset(&snapshot);
 5313                    if range.is_empty() && range.start == cursor_offset {
 5314                        Some(text)
 5315                    } else {
 5316                        None
 5317                    }
 5318                });
 5319
 5320                if let Some(text) = insertion {
 5321                    let mut partial_completion = text
 5322                        .chars()
 5323                        .by_ref()
 5324                        .take_while(|c| c.is_alphabetic())
 5325                        .collect::<String>();
 5326                    if partial_completion.is_empty() {
 5327                        partial_completion = text
 5328                            .chars()
 5329                            .by_ref()
 5330                            .take_while(|c| c.is_whitespace() || !c.is_alphabetic())
 5331                            .collect::<String>();
 5332                    }
 5333
 5334                    cx.emit(EditorEvent::InputHandled {
 5335                        utf16_range_to_replace: None,
 5336                        text: partial_completion.clone().into(),
 5337                    });
 5338
 5339                    self.insert_with_autoindent_mode(&partial_completion, None, window, cx);
 5340
 5341                    self.refresh_inline_completion(true, true, window, cx);
 5342                    cx.notify();
 5343                } else {
 5344                    self.accept_edit_prediction(&Default::default(), window, cx);
 5345                }
 5346            }
 5347        }
 5348    }
 5349
 5350    fn discard_inline_completion(
 5351        &mut self,
 5352        should_report_inline_completion_event: bool,
 5353        cx: &mut Context<Self>,
 5354    ) -> bool {
 5355        if should_report_inline_completion_event {
 5356            let completion_id = self
 5357                .active_inline_completion
 5358                .as_ref()
 5359                .and_then(|active_completion| active_completion.completion_id.clone());
 5360
 5361            self.report_inline_completion_event(completion_id, false, cx);
 5362        }
 5363
 5364        if let Some(provider) = self.edit_prediction_provider() {
 5365            provider.discard(cx);
 5366        }
 5367
 5368        self.take_active_inline_completion(cx)
 5369    }
 5370
 5371    fn report_inline_completion_event(&self, id: Option<SharedString>, accepted: bool, cx: &App) {
 5372        let Some(provider) = self.edit_prediction_provider() else {
 5373            return;
 5374        };
 5375
 5376        let Some((_, buffer, _)) = self
 5377            .buffer
 5378            .read(cx)
 5379            .excerpt_containing(self.selections.newest_anchor().head(), cx)
 5380        else {
 5381            return;
 5382        };
 5383
 5384        let extension = buffer
 5385            .read(cx)
 5386            .file()
 5387            .and_then(|file| Some(file.path().extension()?.to_string_lossy().to_string()));
 5388
 5389        let event_type = match accepted {
 5390            true => "Edit Prediction Accepted",
 5391            false => "Edit Prediction Discarded",
 5392        };
 5393        telemetry::event!(
 5394            event_type,
 5395            provider = provider.name(),
 5396            prediction_id = id,
 5397            suggestion_accepted = accepted,
 5398            file_extension = extension,
 5399        );
 5400    }
 5401
 5402    pub fn has_active_inline_completion(&self) -> bool {
 5403        self.active_inline_completion.is_some()
 5404    }
 5405
 5406    fn take_active_inline_completion(&mut self, cx: &mut Context<Self>) -> bool {
 5407        let Some(active_inline_completion) = self.active_inline_completion.take() else {
 5408            return false;
 5409        };
 5410
 5411        self.splice_inlays(&active_inline_completion.inlay_ids, Default::default(), cx);
 5412        self.clear_highlights::<InlineCompletionHighlight>(cx);
 5413        self.stale_inline_completion_in_menu = Some(active_inline_completion);
 5414        true
 5415    }
 5416
 5417    /// Returns true when we're displaying the edit prediction popover below the cursor
 5418    /// like we are not previewing and the LSP autocomplete menu is visible
 5419    /// or we are in `when_holding_modifier` mode.
 5420    pub fn edit_prediction_visible_in_cursor_popover(&self, has_completion: bool) -> bool {
 5421        if self.edit_prediction_preview_is_active()
 5422            || !self.show_edit_predictions_in_menu()
 5423            || !self.edit_predictions_enabled()
 5424        {
 5425            return false;
 5426        }
 5427
 5428        if self.has_visible_completions_menu() {
 5429            return true;
 5430        }
 5431
 5432        has_completion && self.edit_prediction_requires_modifier()
 5433    }
 5434
 5435    fn handle_modifiers_changed(
 5436        &mut self,
 5437        modifiers: Modifiers,
 5438        position_map: &PositionMap,
 5439        window: &mut Window,
 5440        cx: &mut Context<Self>,
 5441    ) {
 5442        if self.show_edit_predictions_in_menu() {
 5443            self.update_edit_prediction_preview(&modifiers, window, cx);
 5444        }
 5445
 5446        self.update_selection_mode(&modifiers, position_map, window, cx);
 5447
 5448        let mouse_position = window.mouse_position();
 5449        if !position_map.text_hitbox.is_hovered(window) {
 5450            return;
 5451        }
 5452
 5453        self.update_hovered_link(
 5454            position_map.point_for_position(mouse_position),
 5455            &position_map.snapshot,
 5456            modifiers,
 5457            window,
 5458            cx,
 5459        )
 5460    }
 5461
 5462    fn update_selection_mode(
 5463        &mut self,
 5464        modifiers: &Modifiers,
 5465        position_map: &PositionMap,
 5466        window: &mut Window,
 5467        cx: &mut Context<Self>,
 5468    ) {
 5469        if modifiers != &COLUMNAR_SELECTION_MODIFIERS || self.selections.pending.is_none() {
 5470            return;
 5471        }
 5472
 5473        let mouse_position = window.mouse_position();
 5474        let point_for_position = position_map.point_for_position(mouse_position);
 5475        let position = point_for_position.previous_valid;
 5476
 5477        self.select(
 5478            SelectPhase::BeginColumnar {
 5479                position,
 5480                reset: false,
 5481                goal_column: point_for_position.exact_unclipped.column(),
 5482            },
 5483            window,
 5484            cx,
 5485        );
 5486    }
 5487
 5488    fn update_edit_prediction_preview(
 5489        &mut self,
 5490        modifiers: &Modifiers,
 5491        window: &mut Window,
 5492        cx: &mut Context<Self>,
 5493    ) {
 5494        let accept_keybind = self.accept_edit_prediction_keybind(window, cx);
 5495        let Some(accept_keystroke) = accept_keybind.keystroke() else {
 5496            return;
 5497        };
 5498
 5499        if &accept_keystroke.modifiers == modifiers && accept_keystroke.modifiers.modified() {
 5500            if matches!(
 5501                self.edit_prediction_preview,
 5502                EditPredictionPreview::Inactive { .. }
 5503            ) {
 5504                self.edit_prediction_preview = EditPredictionPreview::Active {
 5505                    previous_scroll_position: None,
 5506                    since: Instant::now(),
 5507                };
 5508
 5509                self.update_visible_inline_completion(window, cx);
 5510                cx.notify();
 5511            }
 5512        } else if let EditPredictionPreview::Active {
 5513            previous_scroll_position,
 5514            since,
 5515        } = self.edit_prediction_preview
 5516        {
 5517            if let (Some(previous_scroll_position), Some(position_map)) =
 5518                (previous_scroll_position, self.last_position_map.as_ref())
 5519            {
 5520                self.set_scroll_position(
 5521                    previous_scroll_position
 5522                        .scroll_position(&position_map.snapshot.display_snapshot),
 5523                    window,
 5524                    cx,
 5525                );
 5526            }
 5527
 5528            self.edit_prediction_preview = EditPredictionPreview::Inactive {
 5529                released_too_fast: since.elapsed() < Duration::from_millis(200),
 5530            };
 5531            self.clear_row_highlights::<EditPredictionPreview>();
 5532            self.update_visible_inline_completion(window, cx);
 5533            cx.notify();
 5534        }
 5535    }
 5536
 5537    fn update_visible_inline_completion(
 5538        &mut self,
 5539        _window: &mut Window,
 5540        cx: &mut Context<Self>,
 5541    ) -> Option<()> {
 5542        let selection = self.selections.newest_anchor();
 5543        let cursor = selection.head();
 5544        let multibuffer = self.buffer.read(cx).snapshot(cx);
 5545        let offset_selection = selection.map(|endpoint| endpoint.to_offset(&multibuffer));
 5546        let excerpt_id = cursor.excerpt_id;
 5547
 5548        let show_in_menu = self.show_edit_predictions_in_menu();
 5549        let completions_menu_has_precedence = !show_in_menu
 5550            && (self.context_menu.borrow().is_some()
 5551                || (!self.completion_tasks.is_empty() && !self.has_active_inline_completion()));
 5552
 5553        if completions_menu_has_precedence
 5554            || !offset_selection.is_empty()
 5555            || self
 5556                .active_inline_completion
 5557                .as_ref()
 5558                .map_or(false, |completion| {
 5559                    let invalidation_range = completion.invalidation_range.to_offset(&multibuffer);
 5560                    let invalidation_range = invalidation_range.start..=invalidation_range.end;
 5561                    !invalidation_range.contains(&offset_selection.head())
 5562                })
 5563        {
 5564            self.discard_inline_completion(false, cx);
 5565            return None;
 5566        }
 5567
 5568        self.take_active_inline_completion(cx);
 5569        let Some(provider) = self.edit_prediction_provider() else {
 5570            self.edit_prediction_settings = EditPredictionSettings::Disabled;
 5571            return None;
 5572        };
 5573
 5574        let (buffer, cursor_buffer_position) =
 5575            self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
 5576
 5577        self.edit_prediction_settings =
 5578            self.edit_prediction_settings_at_position(&buffer, cursor_buffer_position, cx);
 5579
 5580        self.edit_prediction_indent_conflict = multibuffer.is_line_whitespace_upto(cursor);
 5581
 5582        if self.edit_prediction_indent_conflict {
 5583            let cursor_point = cursor.to_point(&multibuffer);
 5584
 5585            let indents = multibuffer.suggested_indents(cursor_point.row..cursor_point.row + 1, cx);
 5586
 5587            if let Some((_, indent)) = indents.iter().next() {
 5588                if indent.len == cursor_point.column {
 5589                    self.edit_prediction_indent_conflict = false;
 5590                }
 5591            }
 5592        }
 5593
 5594        let inline_completion = provider.suggest(&buffer, cursor_buffer_position, cx)?;
 5595        let edits = inline_completion
 5596            .edits
 5597            .into_iter()
 5598            .flat_map(|(range, new_text)| {
 5599                let start = multibuffer.anchor_in_excerpt(excerpt_id, range.start)?;
 5600                let end = multibuffer.anchor_in_excerpt(excerpt_id, range.end)?;
 5601                Some((start..end, new_text))
 5602            })
 5603            .collect::<Vec<_>>();
 5604        if edits.is_empty() {
 5605            return None;
 5606        }
 5607
 5608        let first_edit_start = edits.first().unwrap().0.start;
 5609        let first_edit_start_point = first_edit_start.to_point(&multibuffer);
 5610        let edit_start_row = first_edit_start_point.row.saturating_sub(2);
 5611
 5612        let last_edit_end = edits.last().unwrap().0.end;
 5613        let last_edit_end_point = last_edit_end.to_point(&multibuffer);
 5614        let edit_end_row = cmp::min(multibuffer.max_point().row, last_edit_end_point.row + 2);
 5615
 5616        let cursor_row = cursor.to_point(&multibuffer).row;
 5617
 5618        let snapshot = multibuffer.buffer_for_excerpt(excerpt_id).cloned()?;
 5619
 5620        let mut inlay_ids = Vec::new();
 5621        let invalidation_row_range;
 5622        let move_invalidation_row_range = if cursor_row < edit_start_row {
 5623            Some(cursor_row..edit_end_row)
 5624        } else if cursor_row > edit_end_row {
 5625            Some(edit_start_row..cursor_row)
 5626        } else {
 5627            None
 5628        };
 5629        let is_move =
 5630            move_invalidation_row_range.is_some() || self.inline_completions_hidden_for_vim_mode;
 5631        let completion = if is_move {
 5632            invalidation_row_range =
 5633                move_invalidation_row_range.unwrap_or(edit_start_row..edit_end_row);
 5634            let target = first_edit_start;
 5635            InlineCompletion::Move { target, snapshot }
 5636        } else {
 5637            let show_completions_in_buffer = !self.edit_prediction_visible_in_cursor_popover(true)
 5638                && !self.inline_completions_hidden_for_vim_mode;
 5639
 5640            if show_completions_in_buffer {
 5641                if edits
 5642                    .iter()
 5643                    .all(|(range, _)| range.to_offset(&multibuffer).is_empty())
 5644                {
 5645                    let mut inlays = Vec::new();
 5646                    for (range, new_text) in &edits {
 5647                        let inlay = Inlay::inline_completion(
 5648                            post_inc(&mut self.next_inlay_id),
 5649                            range.start,
 5650                            new_text.as_str(),
 5651                        );
 5652                        inlay_ids.push(inlay.id);
 5653                        inlays.push(inlay);
 5654                    }
 5655
 5656                    self.splice_inlays(&[], inlays, cx);
 5657                } else {
 5658                    let background_color = cx.theme().status().deleted_background;
 5659                    self.highlight_text::<InlineCompletionHighlight>(
 5660                        edits.iter().map(|(range, _)| range.clone()).collect(),
 5661                        HighlightStyle {
 5662                            background_color: Some(background_color),
 5663                            ..Default::default()
 5664                        },
 5665                        cx,
 5666                    );
 5667                }
 5668            }
 5669
 5670            invalidation_row_range = edit_start_row..edit_end_row;
 5671
 5672            let display_mode = if all_edits_insertions_or_deletions(&edits, &multibuffer) {
 5673                if provider.show_tab_accept_marker() {
 5674                    EditDisplayMode::TabAccept
 5675                } else {
 5676                    EditDisplayMode::Inline
 5677                }
 5678            } else {
 5679                EditDisplayMode::DiffPopover
 5680            };
 5681
 5682            InlineCompletion::Edit {
 5683                edits,
 5684                edit_preview: inline_completion.edit_preview,
 5685                display_mode,
 5686                snapshot,
 5687            }
 5688        };
 5689
 5690        let invalidation_range = multibuffer
 5691            .anchor_before(Point::new(invalidation_row_range.start, 0))
 5692            ..multibuffer.anchor_after(Point::new(
 5693                invalidation_row_range.end,
 5694                multibuffer.line_len(MultiBufferRow(invalidation_row_range.end)),
 5695            ));
 5696
 5697        self.stale_inline_completion_in_menu = None;
 5698        self.active_inline_completion = Some(InlineCompletionState {
 5699            inlay_ids,
 5700            completion,
 5701            completion_id: inline_completion.id,
 5702            invalidation_range,
 5703        });
 5704
 5705        cx.notify();
 5706
 5707        Some(())
 5708    }
 5709
 5710    pub fn edit_prediction_provider(&self) -> Option<Arc<dyn InlineCompletionProviderHandle>> {
 5711        Some(self.edit_prediction_provider.as_ref()?.provider.clone())
 5712    }
 5713
 5714    fn render_code_actions_indicator(
 5715        &self,
 5716        _style: &EditorStyle,
 5717        row: DisplayRow,
 5718        is_active: bool,
 5719        cx: &mut Context<Self>,
 5720    ) -> Option<IconButton> {
 5721        if self.available_code_actions.is_some() {
 5722            Some(
 5723                IconButton::new("code_actions_indicator", ui::IconName::Bolt)
 5724                    .shape(ui::IconButtonShape::Square)
 5725                    .icon_size(IconSize::XSmall)
 5726                    .icon_color(Color::Muted)
 5727                    .toggle_state(is_active)
 5728                    .tooltip({
 5729                        let focus_handle = self.focus_handle.clone();
 5730                        move |window, cx| {
 5731                            Tooltip::for_action_in(
 5732                                "Toggle Code Actions",
 5733                                &ToggleCodeActions {
 5734                                    deployed_from_indicator: None,
 5735                                },
 5736                                &focus_handle,
 5737                                window,
 5738                                cx,
 5739                            )
 5740                        }
 5741                    })
 5742                    .on_click(cx.listener(move |editor, _e, window, cx| {
 5743                        window.focus(&editor.focus_handle(cx));
 5744                        editor.toggle_code_actions(
 5745                            &ToggleCodeActions {
 5746                                deployed_from_indicator: Some(row),
 5747                            },
 5748                            window,
 5749                            cx,
 5750                        );
 5751                    })),
 5752            )
 5753        } else {
 5754            None
 5755        }
 5756    }
 5757
 5758    fn clear_tasks(&mut self) {
 5759        self.tasks.clear()
 5760    }
 5761
 5762    fn insert_tasks(&mut self, key: (BufferId, BufferRow), value: RunnableTasks) {
 5763        if self.tasks.insert(key, value).is_some() {
 5764            // This case should hopefully be rare, but just in case...
 5765            log::error!("multiple different run targets found on a single line, only the last target will be rendered")
 5766        }
 5767    }
 5768
 5769    fn build_tasks_context(
 5770        project: &Entity<Project>,
 5771        buffer: &Entity<Buffer>,
 5772        buffer_row: u32,
 5773        tasks: &Arc<RunnableTasks>,
 5774        cx: &mut Context<Self>,
 5775    ) -> Task<Option<task::TaskContext>> {
 5776        let position = Point::new(buffer_row, tasks.column);
 5777        let range_start = buffer.read(cx).anchor_at(position, Bias::Right);
 5778        let location = Location {
 5779            buffer: buffer.clone(),
 5780            range: range_start..range_start,
 5781        };
 5782        // Fill in the environmental variables from the tree-sitter captures
 5783        let mut captured_task_variables = TaskVariables::default();
 5784        for (capture_name, value) in tasks.extra_variables.clone() {
 5785            captured_task_variables.insert(
 5786                task::VariableName::Custom(capture_name.into()),
 5787                value.clone(),
 5788            );
 5789        }
 5790        project.update(cx, |project, cx| {
 5791            project.task_store().update(cx, |task_store, cx| {
 5792                task_store.task_context_for_location(captured_task_variables, location, cx)
 5793            })
 5794        })
 5795    }
 5796
 5797    pub fn spawn_nearest_task(
 5798        &mut self,
 5799        action: &SpawnNearestTask,
 5800        window: &mut Window,
 5801        cx: &mut Context<Self>,
 5802    ) {
 5803        let Some((workspace, _)) = self.workspace.clone() else {
 5804            return;
 5805        };
 5806        let Some(project) = self.project.clone() else {
 5807            return;
 5808        };
 5809
 5810        // Try to find a closest, enclosing node using tree-sitter that has a
 5811        // task
 5812        let Some((buffer, buffer_row, tasks)) = self
 5813            .find_enclosing_node_task(cx)
 5814            // Or find the task that's closest in row-distance.
 5815            .or_else(|| self.find_closest_task(cx))
 5816        else {
 5817            return;
 5818        };
 5819
 5820        let reveal_strategy = action.reveal;
 5821        let task_context = Self::build_tasks_context(&project, &buffer, buffer_row, &tasks, cx);
 5822        cx.spawn_in(window, |_, mut cx| async move {
 5823            let context = task_context.await?;
 5824            let (task_source_kind, mut resolved_task) = tasks.resolve(&context).next()?;
 5825
 5826            let resolved = resolved_task.resolved.as_mut()?;
 5827            resolved.reveal = reveal_strategy;
 5828
 5829            workspace
 5830                .update(&mut cx, |workspace, cx| {
 5831                    workspace::tasks::schedule_resolved_task(
 5832                        workspace,
 5833                        task_source_kind,
 5834                        resolved_task,
 5835                        false,
 5836                        cx,
 5837                    );
 5838                })
 5839                .ok()
 5840        })
 5841        .detach();
 5842    }
 5843
 5844    fn find_closest_task(
 5845        &mut self,
 5846        cx: &mut Context<Self>,
 5847    ) -> Option<(Entity<Buffer>, u32, Arc<RunnableTasks>)> {
 5848        let cursor_row = self.selections.newest_adjusted(cx).head().row;
 5849
 5850        let ((buffer_id, row), tasks) = self
 5851            .tasks
 5852            .iter()
 5853            .min_by_key(|((_, row), _)| cursor_row.abs_diff(*row))?;
 5854
 5855        let buffer = self.buffer.read(cx).buffer(*buffer_id)?;
 5856        let tasks = Arc::new(tasks.to_owned());
 5857        Some((buffer, *row, tasks))
 5858    }
 5859
 5860    fn find_enclosing_node_task(
 5861        &mut self,
 5862        cx: &mut Context<Self>,
 5863    ) -> Option<(Entity<Buffer>, u32, Arc<RunnableTasks>)> {
 5864        let snapshot = self.buffer.read(cx).snapshot(cx);
 5865        let offset = self.selections.newest::<usize>(cx).head();
 5866        let excerpt = snapshot.excerpt_containing(offset..offset)?;
 5867        let buffer_id = excerpt.buffer().remote_id();
 5868
 5869        let layer = excerpt.buffer().syntax_layer_at(offset)?;
 5870        let mut cursor = layer.node().walk();
 5871
 5872        while cursor.goto_first_child_for_byte(offset).is_some() {
 5873            if cursor.node().end_byte() == offset {
 5874                cursor.goto_next_sibling();
 5875            }
 5876        }
 5877
 5878        // Ascend to the smallest ancestor that contains the range and has a task.
 5879        loop {
 5880            let node = cursor.node();
 5881            let node_range = node.byte_range();
 5882            let symbol_start_row = excerpt.buffer().offset_to_point(node.start_byte()).row;
 5883
 5884            // Check if this node contains our offset
 5885            if node_range.start <= offset && node_range.end >= offset {
 5886                // If it contains offset, check for task
 5887                if let Some(tasks) = self.tasks.get(&(buffer_id, symbol_start_row)) {
 5888                    let buffer = self.buffer.read(cx).buffer(buffer_id)?;
 5889                    return Some((buffer, symbol_start_row, Arc::new(tasks.to_owned())));
 5890                }
 5891            }
 5892
 5893            if !cursor.goto_parent() {
 5894                break;
 5895            }
 5896        }
 5897        None
 5898    }
 5899
 5900    fn render_run_indicator(
 5901        &self,
 5902        _style: &EditorStyle,
 5903        is_active: bool,
 5904        row: DisplayRow,
 5905        cx: &mut Context<Self>,
 5906    ) -> IconButton {
 5907        IconButton::new(("run_indicator", row.0 as usize), ui::IconName::Play)
 5908            .shape(ui::IconButtonShape::Square)
 5909            .icon_size(IconSize::XSmall)
 5910            .icon_color(Color::Muted)
 5911            .toggle_state(is_active)
 5912            .on_click(cx.listener(move |editor, _e, window, cx| {
 5913                window.focus(&editor.focus_handle(cx));
 5914                editor.toggle_code_actions(
 5915                    &ToggleCodeActions {
 5916                        deployed_from_indicator: Some(row),
 5917                    },
 5918                    window,
 5919                    cx,
 5920                );
 5921            }))
 5922    }
 5923
 5924    pub fn context_menu_visible(&self) -> bool {
 5925        !self.edit_prediction_preview_is_active()
 5926            && self
 5927                .context_menu
 5928                .borrow()
 5929                .as_ref()
 5930                .map_or(false, |menu| menu.visible())
 5931    }
 5932
 5933    fn context_menu_origin(&self) -> Option<ContextMenuOrigin> {
 5934        self.context_menu
 5935            .borrow()
 5936            .as_ref()
 5937            .map(|menu| menu.origin())
 5938    }
 5939
 5940    const EDIT_PREDICTION_POPOVER_PADDING_X: Pixels = Pixels(24.);
 5941    const EDIT_PREDICTION_POPOVER_PADDING_Y: Pixels = Pixels(2.);
 5942
 5943    fn render_edit_prediction_popover(
 5944        &mut self,
 5945        text_bounds: &Bounds<Pixels>,
 5946        content_origin: gpui::Point<Pixels>,
 5947        editor_snapshot: &EditorSnapshot,
 5948        visible_row_range: Range<DisplayRow>,
 5949        scroll_top: f32,
 5950        scroll_bottom: f32,
 5951        line_layouts: &[LineWithInvisibles],
 5952        line_height: Pixels,
 5953        scroll_pixel_position: gpui::Point<Pixels>,
 5954        newest_selection_head: Option<DisplayPoint>,
 5955        editor_width: Pixels,
 5956        style: &EditorStyle,
 5957        window: &mut Window,
 5958        cx: &mut App,
 5959    ) -> Option<(AnyElement, gpui::Point<Pixels>)> {
 5960        let active_inline_completion = self.active_inline_completion.as_ref()?;
 5961
 5962        if self.edit_prediction_visible_in_cursor_popover(true) {
 5963            return None;
 5964        }
 5965
 5966        match &active_inline_completion.completion {
 5967            InlineCompletion::Move { target, .. } => {
 5968                let target_display_point = target.to_display_point(editor_snapshot);
 5969
 5970                if self.edit_prediction_requires_modifier() {
 5971                    if !self.edit_prediction_preview_is_active() {
 5972                        return None;
 5973                    }
 5974
 5975                    self.render_edit_prediction_modifier_jump_popover(
 5976                        text_bounds,
 5977                        content_origin,
 5978                        visible_row_range,
 5979                        line_layouts,
 5980                        line_height,
 5981                        scroll_pixel_position,
 5982                        newest_selection_head,
 5983                        target_display_point,
 5984                        window,
 5985                        cx,
 5986                    )
 5987                } else {
 5988                    self.render_edit_prediction_eager_jump_popover(
 5989                        text_bounds,
 5990                        content_origin,
 5991                        editor_snapshot,
 5992                        visible_row_range,
 5993                        scroll_top,
 5994                        scroll_bottom,
 5995                        line_height,
 5996                        scroll_pixel_position,
 5997                        target_display_point,
 5998                        editor_width,
 5999                        window,
 6000                        cx,
 6001                    )
 6002                }
 6003            }
 6004            InlineCompletion::Edit {
 6005                display_mode: EditDisplayMode::Inline,
 6006                ..
 6007            } => None,
 6008            InlineCompletion::Edit {
 6009                display_mode: EditDisplayMode::TabAccept,
 6010                edits,
 6011                ..
 6012            } => {
 6013                let range = &edits.first()?.0;
 6014                let target_display_point = range.end.to_display_point(editor_snapshot);
 6015
 6016                self.render_edit_prediction_end_of_line_popover(
 6017                    "Accept",
 6018                    editor_snapshot,
 6019                    visible_row_range,
 6020                    target_display_point,
 6021                    line_height,
 6022                    scroll_pixel_position,
 6023                    content_origin,
 6024                    editor_width,
 6025                    window,
 6026                    cx,
 6027                )
 6028            }
 6029            InlineCompletion::Edit {
 6030                edits,
 6031                edit_preview,
 6032                display_mode: EditDisplayMode::DiffPopover,
 6033                snapshot,
 6034            } => self.render_edit_prediction_diff_popover(
 6035                text_bounds,
 6036                content_origin,
 6037                editor_snapshot,
 6038                visible_row_range,
 6039                line_layouts,
 6040                line_height,
 6041                scroll_pixel_position,
 6042                newest_selection_head,
 6043                editor_width,
 6044                style,
 6045                edits,
 6046                edit_preview,
 6047                snapshot,
 6048                window,
 6049                cx,
 6050            ),
 6051        }
 6052    }
 6053
 6054    fn render_edit_prediction_modifier_jump_popover(
 6055        &mut self,
 6056        text_bounds: &Bounds<Pixels>,
 6057        content_origin: gpui::Point<Pixels>,
 6058        visible_row_range: Range<DisplayRow>,
 6059        line_layouts: &[LineWithInvisibles],
 6060        line_height: Pixels,
 6061        scroll_pixel_position: gpui::Point<Pixels>,
 6062        newest_selection_head: Option<DisplayPoint>,
 6063        target_display_point: DisplayPoint,
 6064        window: &mut Window,
 6065        cx: &mut App,
 6066    ) -> Option<(AnyElement, gpui::Point<Pixels>)> {
 6067        let scrolled_content_origin =
 6068            content_origin - gpui::Point::new(scroll_pixel_position.x, Pixels(0.0));
 6069
 6070        const SCROLL_PADDING_Y: Pixels = px(12.);
 6071
 6072        if target_display_point.row() < visible_row_range.start {
 6073            return self.render_edit_prediction_scroll_popover(
 6074                |_| SCROLL_PADDING_Y,
 6075                IconName::ArrowUp,
 6076                visible_row_range,
 6077                line_layouts,
 6078                newest_selection_head,
 6079                scrolled_content_origin,
 6080                window,
 6081                cx,
 6082            );
 6083        } else if target_display_point.row() >= visible_row_range.end {
 6084            return self.render_edit_prediction_scroll_popover(
 6085                |size| text_bounds.size.height - size.height - SCROLL_PADDING_Y,
 6086                IconName::ArrowDown,
 6087                visible_row_range,
 6088                line_layouts,
 6089                newest_selection_head,
 6090                scrolled_content_origin,
 6091                window,
 6092                cx,
 6093            );
 6094        }
 6095
 6096        const POLE_WIDTH: Pixels = px(2.);
 6097
 6098        let line_layout =
 6099            line_layouts.get(target_display_point.row().minus(visible_row_range.start) as usize)?;
 6100        let target_column = target_display_point.column() as usize;
 6101
 6102        let target_x = line_layout.x_for_index(target_column);
 6103        let target_y =
 6104            (target_display_point.row().as_f32() * line_height) - scroll_pixel_position.y;
 6105
 6106        let flag_on_right = target_x < text_bounds.size.width / 2.;
 6107
 6108        let mut border_color = Self::edit_prediction_callout_popover_border_color(cx);
 6109        border_color.l += 0.001;
 6110
 6111        let mut element = v_flex()
 6112            .items_end()
 6113            .when(flag_on_right, |el| el.items_start())
 6114            .child(if flag_on_right {
 6115                self.render_edit_prediction_line_popover("Jump", None, window, cx)?
 6116                    .rounded_bl(px(0.))
 6117                    .rounded_tl(px(0.))
 6118                    .border_l_2()
 6119                    .border_color(border_color)
 6120            } else {
 6121                self.render_edit_prediction_line_popover("Jump", None, window, cx)?
 6122                    .rounded_br(px(0.))
 6123                    .rounded_tr(px(0.))
 6124                    .border_r_2()
 6125                    .border_color(border_color)
 6126            })
 6127            .child(div().w(POLE_WIDTH).bg(border_color).h(line_height))
 6128            .into_any();
 6129
 6130        let size = element.layout_as_root(AvailableSpace::min_size(), window, cx);
 6131
 6132        let mut origin = scrolled_content_origin + point(target_x, target_y)
 6133            - point(
 6134                if flag_on_right {
 6135                    POLE_WIDTH
 6136                } else {
 6137                    size.width - POLE_WIDTH
 6138                },
 6139                size.height - line_height,
 6140            );
 6141
 6142        origin.x = origin.x.max(content_origin.x);
 6143
 6144        element.prepaint_at(origin, window, cx);
 6145
 6146        Some((element, origin))
 6147    }
 6148
 6149    fn render_edit_prediction_scroll_popover(
 6150        &mut self,
 6151        to_y: impl Fn(Size<Pixels>) -> Pixels,
 6152        scroll_icon: IconName,
 6153        visible_row_range: Range<DisplayRow>,
 6154        line_layouts: &[LineWithInvisibles],
 6155        newest_selection_head: Option<DisplayPoint>,
 6156        scrolled_content_origin: gpui::Point<Pixels>,
 6157        window: &mut Window,
 6158        cx: &mut App,
 6159    ) -> Option<(AnyElement, gpui::Point<Pixels>)> {
 6160        let mut element = self
 6161            .render_edit_prediction_line_popover("Scroll", Some(scroll_icon), window, cx)?
 6162            .into_any();
 6163
 6164        let size = element.layout_as_root(AvailableSpace::min_size(), window, cx);
 6165
 6166        let cursor = newest_selection_head?;
 6167        let cursor_row_layout =
 6168            line_layouts.get(cursor.row().minus(visible_row_range.start) as usize)?;
 6169        let cursor_column = cursor.column() as usize;
 6170
 6171        let cursor_character_x = cursor_row_layout.x_for_index(cursor_column);
 6172
 6173        let origin = scrolled_content_origin + point(cursor_character_x, to_y(size));
 6174
 6175        element.prepaint_at(origin, window, cx);
 6176        Some((element, origin))
 6177    }
 6178
 6179    fn render_edit_prediction_eager_jump_popover(
 6180        &mut self,
 6181        text_bounds: &Bounds<Pixels>,
 6182        content_origin: gpui::Point<Pixels>,
 6183        editor_snapshot: &EditorSnapshot,
 6184        visible_row_range: Range<DisplayRow>,
 6185        scroll_top: f32,
 6186        scroll_bottom: f32,
 6187        line_height: Pixels,
 6188        scroll_pixel_position: gpui::Point<Pixels>,
 6189        target_display_point: DisplayPoint,
 6190        editor_width: Pixels,
 6191        window: &mut Window,
 6192        cx: &mut App,
 6193    ) -> Option<(AnyElement, gpui::Point<Pixels>)> {
 6194        if target_display_point.row().as_f32() < scroll_top {
 6195            let mut element = self
 6196                .render_edit_prediction_line_popover(
 6197                    "Jump to Edit",
 6198                    Some(IconName::ArrowUp),
 6199                    window,
 6200                    cx,
 6201                )?
 6202                .into_any();
 6203
 6204            let size = element.layout_as_root(AvailableSpace::min_size(), window, cx);
 6205            let offset = point(
 6206                (text_bounds.size.width - size.width) / 2.,
 6207                Self::EDIT_PREDICTION_POPOVER_PADDING_Y,
 6208            );
 6209
 6210            let origin = text_bounds.origin + offset;
 6211            element.prepaint_at(origin, window, cx);
 6212            Some((element, origin))
 6213        } else if (target_display_point.row().as_f32() + 1.) > scroll_bottom {
 6214            let mut element = self
 6215                .render_edit_prediction_line_popover(
 6216                    "Jump to Edit",
 6217                    Some(IconName::ArrowDown),
 6218                    window,
 6219                    cx,
 6220                )?
 6221                .into_any();
 6222
 6223            let size = element.layout_as_root(AvailableSpace::min_size(), window, cx);
 6224            let offset = point(
 6225                (text_bounds.size.width - size.width) / 2.,
 6226                text_bounds.size.height - size.height - Self::EDIT_PREDICTION_POPOVER_PADDING_Y,
 6227            );
 6228
 6229            let origin = text_bounds.origin + offset;
 6230            element.prepaint_at(origin, window, cx);
 6231            Some((element, origin))
 6232        } else {
 6233            self.render_edit_prediction_end_of_line_popover(
 6234                "Jump to Edit",
 6235                editor_snapshot,
 6236                visible_row_range,
 6237                target_display_point,
 6238                line_height,
 6239                scroll_pixel_position,
 6240                content_origin,
 6241                editor_width,
 6242                window,
 6243                cx,
 6244            )
 6245        }
 6246    }
 6247
 6248    fn render_edit_prediction_end_of_line_popover(
 6249        self: &mut Editor,
 6250        label: &'static str,
 6251        editor_snapshot: &EditorSnapshot,
 6252        visible_row_range: Range<DisplayRow>,
 6253        target_display_point: DisplayPoint,
 6254        line_height: Pixels,
 6255        scroll_pixel_position: gpui::Point<Pixels>,
 6256        content_origin: gpui::Point<Pixels>,
 6257        editor_width: Pixels,
 6258        window: &mut Window,
 6259        cx: &mut App,
 6260    ) -> Option<(AnyElement, gpui::Point<Pixels>)> {
 6261        let target_line_end = DisplayPoint::new(
 6262            target_display_point.row(),
 6263            editor_snapshot.line_len(target_display_point.row()),
 6264        );
 6265
 6266        let mut element = self
 6267            .render_edit_prediction_line_popover(label, None, window, cx)?
 6268            .into_any();
 6269
 6270        let size = element.layout_as_root(AvailableSpace::min_size(), window, cx);
 6271
 6272        let line_origin = self.display_to_pixel_point(target_line_end, editor_snapshot, window)?;
 6273
 6274        let start_point = content_origin - point(scroll_pixel_position.x, Pixels::ZERO);
 6275        let mut origin = start_point
 6276            + line_origin
 6277            + point(Self::EDIT_PREDICTION_POPOVER_PADDING_X, Pixels::ZERO);
 6278        origin.x = origin.x.max(content_origin.x);
 6279
 6280        let max_x = content_origin.x + editor_width - size.width;
 6281
 6282        if origin.x > max_x {
 6283            let offset = line_height + Self::EDIT_PREDICTION_POPOVER_PADDING_Y;
 6284
 6285            let icon = if visible_row_range.contains(&(target_display_point.row() + 2)) {
 6286                origin.y += offset;
 6287                IconName::ArrowUp
 6288            } else {
 6289                origin.y -= offset;
 6290                IconName::ArrowDown
 6291            };
 6292
 6293            element = self
 6294                .render_edit_prediction_line_popover(label, Some(icon), window, cx)?
 6295                .into_any();
 6296
 6297            let size = element.layout_as_root(AvailableSpace::min_size(), window, cx);
 6298
 6299            origin.x = content_origin.x + editor_width - size.width - px(2.);
 6300        }
 6301
 6302        element.prepaint_at(origin, window, cx);
 6303        Some((element, origin))
 6304    }
 6305
 6306    fn render_edit_prediction_diff_popover(
 6307        self: &Editor,
 6308        text_bounds: &Bounds<Pixels>,
 6309        content_origin: gpui::Point<Pixels>,
 6310        editor_snapshot: &EditorSnapshot,
 6311        visible_row_range: Range<DisplayRow>,
 6312        line_layouts: &[LineWithInvisibles],
 6313        line_height: Pixels,
 6314        scroll_pixel_position: gpui::Point<Pixels>,
 6315        newest_selection_head: Option<DisplayPoint>,
 6316        editor_width: Pixels,
 6317        style: &EditorStyle,
 6318        edits: &Vec<(Range<Anchor>, String)>,
 6319        edit_preview: &Option<language::EditPreview>,
 6320        snapshot: &language::BufferSnapshot,
 6321        window: &mut Window,
 6322        cx: &mut App,
 6323    ) -> Option<(AnyElement, gpui::Point<Pixels>)> {
 6324        let edit_start = edits
 6325            .first()
 6326            .unwrap()
 6327            .0
 6328            .start
 6329            .to_display_point(editor_snapshot);
 6330        let edit_end = edits
 6331            .last()
 6332            .unwrap()
 6333            .0
 6334            .end
 6335            .to_display_point(editor_snapshot);
 6336
 6337        let is_visible = visible_row_range.contains(&edit_start.row())
 6338            || visible_row_range.contains(&edit_end.row());
 6339        if !is_visible {
 6340            return None;
 6341        }
 6342
 6343        let highlighted_edits =
 6344            crate::inline_completion_edit_text(&snapshot, edits, edit_preview.as_ref()?, false, cx);
 6345
 6346        let styled_text = highlighted_edits.to_styled_text(&style.text);
 6347        let line_count = highlighted_edits.text.lines().count();
 6348
 6349        const BORDER_WIDTH: Pixels = px(1.);
 6350
 6351        let keybind = self.render_edit_prediction_accept_keybind(window, cx);
 6352        let has_keybind = keybind.is_some();
 6353
 6354        let mut element = h_flex()
 6355            .items_start()
 6356            .child(
 6357                h_flex()
 6358                    .bg(cx.theme().colors().editor_background)
 6359                    .border(BORDER_WIDTH)
 6360                    .shadow_sm()
 6361                    .border_color(cx.theme().colors().border)
 6362                    .rounded_l_lg()
 6363                    .when(line_count > 1, |el| el.rounded_br_lg())
 6364                    .pr_1()
 6365                    .child(styled_text),
 6366            )
 6367            .child(
 6368                h_flex()
 6369                    .h(line_height + BORDER_WIDTH * px(2.))
 6370                    .px_1p5()
 6371                    .gap_1()
 6372                    // Workaround: For some reason, there's a gap if we don't do this
 6373                    .ml(-BORDER_WIDTH)
 6374                    .shadow(smallvec![gpui::BoxShadow {
 6375                        color: gpui::black().opacity(0.05),
 6376                        offset: point(px(1.), px(1.)),
 6377                        blur_radius: px(2.),
 6378                        spread_radius: px(0.),
 6379                    }])
 6380                    .bg(Editor::edit_prediction_line_popover_bg_color(cx))
 6381                    .border(BORDER_WIDTH)
 6382                    .border_color(cx.theme().colors().border)
 6383                    .rounded_r_lg()
 6384                    .id("edit_prediction_diff_popover_keybind")
 6385                    .when(!has_keybind, |el| {
 6386                        let status_colors = cx.theme().status();
 6387
 6388                        el.bg(status_colors.error_background)
 6389                            .border_color(status_colors.error.opacity(0.6))
 6390                            .child(Icon::new(IconName::Info).color(Color::Error))
 6391                            .cursor_default()
 6392                            .hoverable_tooltip(move |_window, cx| {
 6393                                cx.new(|_| MissingEditPredictionKeybindingTooltip).into()
 6394                            })
 6395                    })
 6396                    .children(keybind),
 6397            )
 6398            .into_any();
 6399
 6400        let longest_row =
 6401            editor_snapshot.longest_row_in_range(edit_start.row()..edit_end.row() + 1);
 6402        let longest_line_width = if visible_row_range.contains(&longest_row) {
 6403            line_layouts[(longest_row.0 - visible_row_range.start.0) as usize].width
 6404        } else {
 6405            layout_line(
 6406                longest_row,
 6407                editor_snapshot,
 6408                style,
 6409                editor_width,
 6410                |_| false,
 6411                window,
 6412                cx,
 6413            )
 6414            .width
 6415        };
 6416
 6417        let viewport_bounds =
 6418            Bounds::new(Default::default(), window.viewport_size()).extend(Edges {
 6419                right: -EditorElement::SCROLLBAR_WIDTH,
 6420                ..Default::default()
 6421            });
 6422
 6423        let x_after_longest =
 6424            text_bounds.origin.x + longest_line_width + Self::EDIT_PREDICTION_POPOVER_PADDING_X
 6425                - scroll_pixel_position.x;
 6426
 6427        let element_bounds = element.layout_as_root(AvailableSpace::min_size(), window, cx);
 6428
 6429        // Fully visible if it can be displayed within the window (allow overlapping other
 6430        // panes). However, this is only allowed if the popover starts within text_bounds.
 6431        let can_position_to_the_right = x_after_longest < text_bounds.right()
 6432            && x_after_longest + element_bounds.width < viewport_bounds.right();
 6433
 6434        let mut origin = if can_position_to_the_right {
 6435            point(
 6436                x_after_longest,
 6437                text_bounds.origin.y + edit_start.row().as_f32() * line_height
 6438                    - scroll_pixel_position.y,
 6439            )
 6440        } else {
 6441            let cursor_row = newest_selection_head.map(|head| head.row());
 6442            let above_edit = edit_start
 6443                .row()
 6444                .0
 6445                .checked_sub(line_count as u32)
 6446                .map(DisplayRow);
 6447            let below_edit = Some(edit_end.row() + 1);
 6448            let above_cursor =
 6449                cursor_row.and_then(|row| row.0.checked_sub(line_count as u32).map(DisplayRow));
 6450            let below_cursor = cursor_row.map(|cursor_row| cursor_row + 1);
 6451
 6452            // Place the edit popover adjacent to the edit if there is a location
 6453            // available that is onscreen and does not obscure the cursor. Otherwise,
 6454            // place it adjacent to the cursor.
 6455            let row_target = [above_edit, below_edit, above_cursor, below_cursor]
 6456                .into_iter()
 6457                .flatten()
 6458                .find(|&start_row| {
 6459                    let end_row = start_row + line_count as u32;
 6460                    visible_row_range.contains(&start_row)
 6461                        && visible_row_range.contains(&end_row)
 6462                        && cursor_row.map_or(true, |cursor_row| {
 6463                            !((start_row..end_row).contains(&cursor_row))
 6464                        })
 6465                })?;
 6466
 6467            content_origin
 6468                + point(
 6469                    -scroll_pixel_position.x,
 6470                    row_target.as_f32() * line_height - scroll_pixel_position.y,
 6471                )
 6472        };
 6473
 6474        origin.x -= BORDER_WIDTH;
 6475
 6476        window.defer_draw(element, origin, 1);
 6477
 6478        // Do not return an element, since it will already be drawn due to defer_draw.
 6479        None
 6480    }
 6481
 6482    fn edit_prediction_cursor_popover_height(&self) -> Pixels {
 6483        px(30.)
 6484    }
 6485
 6486    fn current_user_player_color(&self, cx: &mut App) -> PlayerColor {
 6487        if self.read_only(cx) {
 6488            cx.theme().players().read_only()
 6489        } else {
 6490            self.style.as_ref().unwrap().local_player
 6491        }
 6492    }
 6493
 6494    fn render_edit_prediction_accept_keybind(
 6495        &self,
 6496        window: &mut Window,
 6497        cx: &App,
 6498    ) -> Option<AnyElement> {
 6499        let accept_binding = self.accept_edit_prediction_keybind(window, cx);
 6500        let accept_keystroke = accept_binding.keystroke()?;
 6501
 6502        let is_platform_style_mac = PlatformStyle::platform() == PlatformStyle::Mac;
 6503
 6504        let modifiers_color = if accept_keystroke.modifiers == window.modifiers() {
 6505            Color::Accent
 6506        } else {
 6507            Color::Muted
 6508        };
 6509
 6510        h_flex()
 6511            .px_0p5()
 6512            .when(is_platform_style_mac, |parent| parent.gap_0p5())
 6513            .font(theme::ThemeSettings::get_global(cx).buffer_font.clone())
 6514            .text_size(TextSize::XSmall.rems(cx))
 6515            .child(h_flex().children(ui::render_modifiers(
 6516                &accept_keystroke.modifiers,
 6517                PlatformStyle::platform(),
 6518                Some(modifiers_color),
 6519                Some(IconSize::XSmall.rems().into()),
 6520                true,
 6521            )))
 6522            .when(is_platform_style_mac, |parent| {
 6523                parent.child(accept_keystroke.key.clone())
 6524            })
 6525            .when(!is_platform_style_mac, |parent| {
 6526                parent.child(
 6527                    Key::new(
 6528                        util::capitalize(&accept_keystroke.key),
 6529                        Some(Color::Default),
 6530                    )
 6531                    .size(Some(IconSize::XSmall.rems().into())),
 6532                )
 6533            })
 6534            .into_any()
 6535            .into()
 6536    }
 6537
 6538    fn render_edit_prediction_line_popover(
 6539        &self,
 6540        label: impl Into<SharedString>,
 6541        icon: Option<IconName>,
 6542        window: &mut Window,
 6543        cx: &App,
 6544    ) -> Option<Stateful<Div>> {
 6545        let padding_right = if icon.is_some() { px(4.) } else { px(8.) };
 6546
 6547        let keybind = self.render_edit_prediction_accept_keybind(window, cx);
 6548        let has_keybind = keybind.is_some();
 6549
 6550        let result = h_flex()
 6551            .id("ep-line-popover")
 6552            .py_0p5()
 6553            .pl_1()
 6554            .pr(padding_right)
 6555            .gap_1()
 6556            .rounded_md()
 6557            .border_1()
 6558            .bg(Self::edit_prediction_line_popover_bg_color(cx))
 6559            .border_color(Self::edit_prediction_callout_popover_border_color(cx))
 6560            .shadow_sm()
 6561            .when(!has_keybind, |el| {
 6562                let status_colors = cx.theme().status();
 6563
 6564                el.bg(status_colors.error_background)
 6565                    .border_color(status_colors.error.opacity(0.6))
 6566                    .pl_2()
 6567                    .child(Icon::new(IconName::ZedPredictError).color(Color::Error))
 6568                    .cursor_default()
 6569                    .hoverable_tooltip(move |_window, cx| {
 6570                        cx.new(|_| MissingEditPredictionKeybindingTooltip).into()
 6571                    })
 6572            })
 6573            .children(keybind)
 6574            .child(
 6575                Label::new(label)
 6576                    .size(LabelSize::Small)
 6577                    .when(!has_keybind, |el| {
 6578                        el.color(cx.theme().status().error.into()).strikethrough()
 6579                    }),
 6580            )
 6581            .when(!has_keybind, |el| {
 6582                el.child(
 6583                    h_flex().ml_1().child(
 6584                        Icon::new(IconName::Info)
 6585                            .size(IconSize::Small)
 6586                            .color(cx.theme().status().error.into()),
 6587                    ),
 6588                )
 6589            })
 6590            .when_some(icon, |element, icon| {
 6591                element.child(
 6592                    div()
 6593                        .mt(px(1.5))
 6594                        .child(Icon::new(icon).size(IconSize::Small)),
 6595                )
 6596            });
 6597
 6598        Some(result)
 6599    }
 6600
 6601    fn edit_prediction_line_popover_bg_color(cx: &App) -> Hsla {
 6602        let accent_color = cx.theme().colors().text_accent;
 6603        let editor_bg_color = cx.theme().colors().editor_background;
 6604        editor_bg_color.blend(accent_color.opacity(0.1))
 6605    }
 6606
 6607    fn edit_prediction_callout_popover_border_color(cx: &App) -> Hsla {
 6608        let accent_color = cx.theme().colors().text_accent;
 6609        let editor_bg_color = cx.theme().colors().editor_background;
 6610        editor_bg_color.blend(accent_color.opacity(0.6))
 6611    }
 6612
 6613    fn render_edit_prediction_cursor_popover(
 6614        &self,
 6615        min_width: Pixels,
 6616        max_width: Pixels,
 6617        cursor_point: Point,
 6618        style: &EditorStyle,
 6619        accept_keystroke: Option<&gpui::Keystroke>,
 6620        _window: &Window,
 6621        cx: &mut Context<Editor>,
 6622    ) -> Option<AnyElement> {
 6623        let provider = self.edit_prediction_provider.as_ref()?;
 6624
 6625        if provider.provider.needs_terms_acceptance(cx) {
 6626            return Some(
 6627                h_flex()
 6628                    .min_w(min_width)
 6629                    .flex_1()
 6630                    .px_2()
 6631                    .py_1()
 6632                    .gap_3()
 6633                    .elevation_2(cx)
 6634                    .hover(|style| style.bg(cx.theme().colors().element_hover))
 6635                    .id("accept-terms")
 6636                    .cursor_pointer()
 6637                    .on_mouse_down(MouseButton::Left, |_, window, _| window.prevent_default())
 6638                    .on_click(cx.listener(|this, _event, window, cx| {
 6639                        cx.stop_propagation();
 6640                        this.report_editor_event("Edit Prediction Provider ToS Clicked", None, cx);
 6641                        window.dispatch_action(
 6642                            zed_actions::OpenZedPredictOnboarding.boxed_clone(),
 6643                            cx,
 6644                        );
 6645                    }))
 6646                    .child(
 6647                        h_flex()
 6648                            .flex_1()
 6649                            .gap_2()
 6650                            .child(Icon::new(IconName::ZedPredict))
 6651                            .child(Label::new("Accept Terms of Service"))
 6652                            .child(div().w_full())
 6653                            .child(
 6654                                Icon::new(IconName::ArrowUpRight)
 6655                                    .color(Color::Muted)
 6656                                    .size(IconSize::Small),
 6657                            )
 6658                            .into_any_element(),
 6659                    )
 6660                    .into_any(),
 6661            );
 6662        }
 6663
 6664        let is_refreshing = provider.provider.is_refreshing(cx);
 6665
 6666        fn pending_completion_container() -> Div {
 6667            h_flex()
 6668                .h_full()
 6669                .flex_1()
 6670                .gap_2()
 6671                .child(Icon::new(IconName::ZedPredict))
 6672        }
 6673
 6674        let completion = match &self.active_inline_completion {
 6675            Some(prediction) => {
 6676                if !self.has_visible_completions_menu() {
 6677                    const RADIUS: Pixels = px(6.);
 6678                    const BORDER_WIDTH: Pixels = px(1.);
 6679
 6680                    return Some(
 6681                        h_flex()
 6682                            .elevation_2(cx)
 6683                            .border(BORDER_WIDTH)
 6684                            .border_color(cx.theme().colors().border)
 6685                            .when(accept_keystroke.is_none(), |el| {
 6686                                el.border_color(cx.theme().status().error)
 6687                            })
 6688                            .rounded(RADIUS)
 6689                            .rounded_tl(px(0.))
 6690                            .overflow_hidden()
 6691                            .child(div().px_1p5().child(match &prediction.completion {
 6692                                InlineCompletion::Move { target, snapshot } => {
 6693                                    use text::ToPoint as _;
 6694                                    if target.text_anchor.to_point(&snapshot).row > cursor_point.row
 6695                                    {
 6696                                        Icon::new(IconName::ZedPredictDown)
 6697                                    } else {
 6698                                        Icon::new(IconName::ZedPredictUp)
 6699                                    }
 6700                                }
 6701                                InlineCompletion::Edit { .. } => Icon::new(IconName::ZedPredict),
 6702                            }))
 6703                            .child(
 6704                                h_flex()
 6705                                    .gap_1()
 6706                                    .py_1()
 6707                                    .px_2()
 6708                                    .rounded_r(RADIUS - BORDER_WIDTH)
 6709                                    .border_l_1()
 6710                                    .border_color(cx.theme().colors().border)
 6711                                    .bg(Self::edit_prediction_line_popover_bg_color(cx))
 6712                                    .when(self.edit_prediction_preview.released_too_fast(), |el| {
 6713                                        el.child(
 6714                                            Label::new("Hold")
 6715                                                .size(LabelSize::Small)
 6716                                                .when(accept_keystroke.is_none(), |el| {
 6717                                                    el.strikethrough()
 6718                                                })
 6719                                                .line_height_style(LineHeightStyle::UiLabel),
 6720                                        )
 6721                                    })
 6722                                    .id("edit_prediction_cursor_popover_keybind")
 6723                                    .when(accept_keystroke.is_none(), |el| {
 6724                                        let status_colors = cx.theme().status();
 6725
 6726                                        el.bg(status_colors.error_background)
 6727                                            .border_color(status_colors.error.opacity(0.6))
 6728                                            .child(Icon::new(IconName::Info).color(Color::Error))
 6729                                            .cursor_default()
 6730                                            .hoverable_tooltip(move |_window, cx| {
 6731                                                cx.new(|_| MissingEditPredictionKeybindingTooltip)
 6732                                                    .into()
 6733                                            })
 6734                                    })
 6735                                    .when_some(
 6736                                        accept_keystroke.as_ref(),
 6737                                        |el, accept_keystroke| {
 6738                                            el.child(h_flex().children(ui::render_modifiers(
 6739                                                &accept_keystroke.modifiers,
 6740                                                PlatformStyle::platform(),
 6741                                                Some(Color::Default),
 6742                                                Some(IconSize::XSmall.rems().into()),
 6743                                                false,
 6744                                            )))
 6745                                        },
 6746                                    ),
 6747                            )
 6748                            .into_any(),
 6749                    );
 6750                }
 6751
 6752                self.render_edit_prediction_cursor_popover_preview(
 6753                    prediction,
 6754                    cursor_point,
 6755                    style,
 6756                    cx,
 6757                )?
 6758            }
 6759
 6760            None if is_refreshing => match &self.stale_inline_completion_in_menu {
 6761                Some(stale_completion) => self.render_edit_prediction_cursor_popover_preview(
 6762                    stale_completion,
 6763                    cursor_point,
 6764                    style,
 6765                    cx,
 6766                )?,
 6767
 6768                None => {
 6769                    pending_completion_container().child(Label::new("...").size(LabelSize::Small))
 6770                }
 6771            },
 6772
 6773            None => pending_completion_container().child(Label::new("No Prediction")),
 6774        };
 6775
 6776        let completion = if is_refreshing {
 6777            completion
 6778                .with_animation(
 6779                    "loading-completion",
 6780                    Animation::new(Duration::from_secs(2))
 6781                        .repeat()
 6782                        .with_easing(pulsating_between(0.4, 0.8)),
 6783                    |label, delta| label.opacity(delta),
 6784                )
 6785                .into_any_element()
 6786        } else {
 6787            completion.into_any_element()
 6788        };
 6789
 6790        let has_completion = self.active_inline_completion.is_some();
 6791
 6792        let is_platform_style_mac = PlatformStyle::platform() == PlatformStyle::Mac;
 6793        Some(
 6794            h_flex()
 6795                .min_w(min_width)
 6796                .max_w(max_width)
 6797                .flex_1()
 6798                .elevation_2(cx)
 6799                .border_color(cx.theme().colors().border)
 6800                .child(
 6801                    div()
 6802                        .flex_1()
 6803                        .py_1()
 6804                        .px_2()
 6805                        .overflow_hidden()
 6806                        .child(completion),
 6807                )
 6808                .when_some(accept_keystroke, |el, accept_keystroke| {
 6809                    if !accept_keystroke.modifiers.modified() {
 6810                        return el;
 6811                    }
 6812
 6813                    el.child(
 6814                        h_flex()
 6815                            .h_full()
 6816                            .border_l_1()
 6817                            .rounded_r_lg()
 6818                            .border_color(cx.theme().colors().border)
 6819                            .bg(Self::edit_prediction_line_popover_bg_color(cx))
 6820                            .gap_1()
 6821                            .py_1()
 6822                            .px_2()
 6823                            .child(
 6824                                h_flex()
 6825                                    .font(theme::ThemeSettings::get_global(cx).buffer_font.clone())
 6826                                    .when(is_platform_style_mac, |parent| parent.gap_1())
 6827                                    .child(h_flex().children(ui::render_modifiers(
 6828                                        &accept_keystroke.modifiers,
 6829                                        PlatformStyle::platform(),
 6830                                        Some(if !has_completion {
 6831                                            Color::Muted
 6832                                        } else {
 6833                                            Color::Default
 6834                                        }),
 6835                                        None,
 6836                                        false,
 6837                                    ))),
 6838                            )
 6839                            .child(Label::new("Preview").into_any_element())
 6840                            .opacity(if has_completion { 1.0 } else { 0.4 }),
 6841                    )
 6842                })
 6843                .into_any(),
 6844        )
 6845    }
 6846
 6847    fn render_edit_prediction_cursor_popover_preview(
 6848        &self,
 6849        completion: &InlineCompletionState,
 6850        cursor_point: Point,
 6851        style: &EditorStyle,
 6852        cx: &mut Context<Editor>,
 6853    ) -> Option<Div> {
 6854        use text::ToPoint as _;
 6855
 6856        fn render_relative_row_jump(
 6857            prefix: impl Into<String>,
 6858            current_row: u32,
 6859            target_row: u32,
 6860        ) -> Div {
 6861            let (row_diff, arrow) = if target_row < current_row {
 6862                (current_row - target_row, IconName::ArrowUp)
 6863            } else {
 6864                (target_row - current_row, IconName::ArrowDown)
 6865            };
 6866
 6867            h_flex()
 6868                .child(
 6869                    Label::new(format!("{}{}", prefix.into(), row_diff))
 6870                        .color(Color::Muted)
 6871                        .size(LabelSize::Small),
 6872                )
 6873                .child(Icon::new(arrow).color(Color::Muted).size(IconSize::Small))
 6874        }
 6875
 6876        match &completion.completion {
 6877            InlineCompletion::Move {
 6878                target, snapshot, ..
 6879            } => Some(
 6880                h_flex()
 6881                    .px_2()
 6882                    .gap_2()
 6883                    .flex_1()
 6884                    .child(
 6885                        if target.text_anchor.to_point(&snapshot).row > cursor_point.row {
 6886                            Icon::new(IconName::ZedPredictDown)
 6887                        } else {
 6888                            Icon::new(IconName::ZedPredictUp)
 6889                        },
 6890                    )
 6891                    .child(Label::new("Jump to Edit")),
 6892            ),
 6893
 6894            InlineCompletion::Edit {
 6895                edits,
 6896                edit_preview,
 6897                snapshot,
 6898                display_mode: _,
 6899            } => {
 6900                let first_edit_row = edits.first()?.0.start.text_anchor.to_point(&snapshot).row;
 6901
 6902                let (highlighted_edits, has_more_lines) = crate::inline_completion_edit_text(
 6903                    &snapshot,
 6904                    &edits,
 6905                    edit_preview.as_ref()?,
 6906                    true,
 6907                    cx,
 6908                )
 6909                .first_line_preview();
 6910
 6911                let styled_text = gpui::StyledText::new(highlighted_edits.text)
 6912                    .with_default_highlights(&style.text, highlighted_edits.highlights);
 6913
 6914                let preview = h_flex()
 6915                    .gap_1()
 6916                    .min_w_16()
 6917                    .child(styled_text)
 6918                    .when(has_more_lines, |parent| parent.child(""));
 6919
 6920                let left = if first_edit_row != cursor_point.row {
 6921                    render_relative_row_jump("", cursor_point.row, first_edit_row)
 6922                        .into_any_element()
 6923                } else {
 6924                    Icon::new(IconName::ZedPredict).into_any_element()
 6925                };
 6926
 6927                Some(
 6928                    h_flex()
 6929                        .h_full()
 6930                        .flex_1()
 6931                        .gap_2()
 6932                        .pr_1()
 6933                        .overflow_x_hidden()
 6934                        .font(theme::ThemeSettings::get_global(cx).buffer_font.clone())
 6935                        .child(left)
 6936                        .child(preview),
 6937                )
 6938            }
 6939        }
 6940    }
 6941
 6942    fn render_context_menu(
 6943        &self,
 6944        style: &EditorStyle,
 6945        max_height_in_lines: u32,
 6946        y_flipped: bool,
 6947        window: &mut Window,
 6948        cx: &mut Context<Editor>,
 6949    ) -> Option<AnyElement> {
 6950        let menu = self.context_menu.borrow();
 6951        let menu = menu.as_ref()?;
 6952        if !menu.visible() {
 6953            return None;
 6954        };
 6955        Some(menu.render(style, max_height_in_lines, y_flipped, window, cx))
 6956    }
 6957
 6958    fn render_context_menu_aside(
 6959        &mut self,
 6960        max_size: Size<Pixels>,
 6961        window: &mut Window,
 6962        cx: &mut Context<Editor>,
 6963    ) -> Option<AnyElement> {
 6964        self.context_menu.borrow_mut().as_mut().and_then(|menu| {
 6965            if menu.visible() {
 6966                menu.render_aside(self, max_size, window, cx)
 6967            } else {
 6968                None
 6969            }
 6970        })
 6971    }
 6972
 6973    fn hide_context_menu(
 6974        &mut self,
 6975        window: &mut Window,
 6976        cx: &mut Context<Self>,
 6977    ) -> Option<CodeContextMenu> {
 6978        cx.notify();
 6979        self.completion_tasks.clear();
 6980        let context_menu = self.context_menu.borrow_mut().take();
 6981        self.stale_inline_completion_in_menu.take();
 6982        self.update_visible_inline_completion(window, cx);
 6983        context_menu
 6984    }
 6985
 6986    fn show_snippet_choices(
 6987        &mut self,
 6988        choices: &Vec<String>,
 6989        selection: Range<Anchor>,
 6990        cx: &mut Context<Self>,
 6991    ) {
 6992        if selection.start.buffer_id.is_none() {
 6993            return;
 6994        }
 6995        let buffer_id = selection.start.buffer_id.unwrap();
 6996        let buffer = self.buffer().read(cx).buffer(buffer_id);
 6997        let id = post_inc(&mut self.next_completion_id);
 6998
 6999        if let Some(buffer) = buffer {
 7000            *self.context_menu.borrow_mut() = Some(CodeContextMenu::Completions(
 7001                CompletionsMenu::new_snippet_choices(id, true, choices, selection, buffer),
 7002            ));
 7003        }
 7004    }
 7005
 7006    pub fn insert_snippet(
 7007        &mut self,
 7008        insertion_ranges: &[Range<usize>],
 7009        snippet: Snippet,
 7010        window: &mut Window,
 7011        cx: &mut Context<Self>,
 7012    ) -> Result<()> {
 7013        struct Tabstop<T> {
 7014            is_end_tabstop: bool,
 7015            ranges: Vec<Range<T>>,
 7016            choices: Option<Vec<String>>,
 7017        }
 7018
 7019        let tabstops = self.buffer.update(cx, |buffer, cx| {
 7020            let snippet_text: Arc<str> = snippet.text.clone().into();
 7021            buffer.edit(
 7022                insertion_ranges
 7023                    .iter()
 7024                    .cloned()
 7025                    .map(|range| (range, snippet_text.clone())),
 7026                Some(AutoindentMode::EachLine),
 7027                cx,
 7028            );
 7029
 7030            let snapshot = &*buffer.read(cx);
 7031            let snippet = &snippet;
 7032            snippet
 7033                .tabstops
 7034                .iter()
 7035                .map(|tabstop| {
 7036                    let is_end_tabstop = tabstop.ranges.first().map_or(false, |tabstop| {
 7037                        tabstop.is_empty() && tabstop.start == snippet.text.len() as isize
 7038                    });
 7039                    let mut tabstop_ranges = tabstop
 7040                        .ranges
 7041                        .iter()
 7042                        .flat_map(|tabstop_range| {
 7043                            let mut delta = 0_isize;
 7044                            insertion_ranges.iter().map(move |insertion_range| {
 7045                                let insertion_start = insertion_range.start as isize + delta;
 7046                                delta +=
 7047                                    snippet.text.len() as isize - insertion_range.len() as isize;
 7048
 7049                                let start = ((insertion_start + tabstop_range.start) as usize)
 7050                                    .min(snapshot.len());
 7051                                let end = ((insertion_start + tabstop_range.end) as usize)
 7052                                    .min(snapshot.len());
 7053                                snapshot.anchor_before(start)..snapshot.anchor_after(end)
 7054                            })
 7055                        })
 7056                        .collect::<Vec<_>>();
 7057                    tabstop_ranges.sort_unstable_by(|a, b| a.start.cmp(&b.start, snapshot));
 7058
 7059                    Tabstop {
 7060                        is_end_tabstop,
 7061                        ranges: tabstop_ranges,
 7062                        choices: tabstop.choices.clone(),
 7063                    }
 7064                })
 7065                .collect::<Vec<_>>()
 7066        });
 7067        if let Some(tabstop) = tabstops.first() {
 7068            self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 7069                s.select_ranges(tabstop.ranges.iter().cloned());
 7070            });
 7071
 7072            if let Some(choices) = &tabstop.choices {
 7073                if let Some(selection) = tabstop.ranges.first() {
 7074                    self.show_snippet_choices(choices, selection.clone(), cx)
 7075                }
 7076            }
 7077
 7078            // If we're already at the last tabstop and it's at the end of the snippet,
 7079            // we're done, we don't need to keep the state around.
 7080            if !tabstop.is_end_tabstop {
 7081                let choices = tabstops
 7082                    .iter()
 7083                    .map(|tabstop| tabstop.choices.clone())
 7084                    .collect();
 7085
 7086                let ranges = tabstops
 7087                    .into_iter()
 7088                    .map(|tabstop| tabstop.ranges)
 7089                    .collect::<Vec<_>>();
 7090
 7091                self.snippet_stack.push(SnippetState {
 7092                    active_index: 0,
 7093                    ranges,
 7094                    choices,
 7095                });
 7096            }
 7097
 7098            // Check whether the just-entered snippet ends with an auto-closable bracket.
 7099            if self.autoclose_regions.is_empty() {
 7100                let snapshot = self.buffer.read(cx).snapshot(cx);
 7101                for selection in &mut self.selections.all::<Point>(cx) {
 7102                    let selection_head = selection.head();
 7103                    let Some(scope) = snapshot.language_scope_at(selection_head) else {
 7104                        continue;
 7105                    };
 7106
 7107                    let mut bracket_pair = None;
 7108                    let next_chars = snapshot.chars_at(selection_head).collect::<String>();
 7109                    let prev_chars = snapshot
 7110                        .reversed_chars_at(selection_head)
 7111                        .collect::<String>();
 7112                    for (pair, enabled) in scope.brackets() {
 7113                        if enabled
 7114                            && pair.close
 7115                            && prev_chars.starts_with(pair.start.as_str())
 7116                            && next_chars.starts_with(pair.end.as_str())
 7117                        {
 7118                            bracket_pair = Some(pair.clone());
 7119                            break;
 7120                        }
 7121                    }
 7122                    if let Some(pair) = bracket_pair {
 7123                        let start = snapshot.anchor_after(selection_head);
 7124                        let end = snapshot.anchor_after(selection_head);
 7125                        self.autoclose_regions.push(AutocloseRegion {
 7126                            selection_id: selection.id,
 7127                            range: start..end,
 7128                            pair,
 7129                        });
 7130                    }
 7131                }
 7132            }
 7133        }
 7134        Ok(())
 7135    }
 7136
 7137    pub fn move_to_next_snippet_tabstop(
 7138        &mut self,
 7139        window: &mut Window,
 7140        cx: &mut Context<Self>,
 7141    ) -> bool {
 7142        self.move_to_snippet_tabstop(Bias::Right, window, cx)
 7143    }
 7144
 7145    pub fn move_to_prev_snippet_tabstop(
 7146        &mut self,
 7147        window: &mut Window,
 7148        cx: &mut Context<Self>,
 7149    ) -> bool {
 7150        self.move_to_snippet_tabstop(Bias::Left, window, cx)
 7151    }
 7152
 7153    pub fn move_to_snippet_tabstop(
 7154        &mut self,
 7155        bias: Bias,
 7156        window: &mut Window,
 7157        cx: &mut Context<Self>,
 7158    ) -> bool {
 7159        if let Some(mut snippet) = self.snippet_stack.pop() {
 7160            match bias {
 7161                Bias::Left => {
 7162                    if snippet.active_index > 0 {
 7163                        snippet.active_index -= 1;
 7164                    } else {
 7165                        self.snippet_stack.push(snippet);
 7166                        return false;
 7167                    }
 7168                }
 7169                Bias::Right => {
 7170                    if snippet.active_index + 1 < snippet.ranges.len() {
 7171                        snippet.active_index += 1;
 7172                    } else {
 7173                        self.snippet_stack.push(snippet);
 7174                        return false;
 7175                    }
 7176                }
 7177            }
 7178            if let Some(current_ranges) = snippet.ranges.get(snippet.active_index) {
 7179                self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 7180                    s.select_anchor_ranges(current_ranges.iter().cloned())
 7181                });
 7182
 7183                if let Some(choices) = &snippet.choices[snippet.active_index] {
 7184                    if let Some(selection) = current_ranges.first() {
 7185                        self.show_snippet_choices(&choices, selection.clone(), cx);
 7186                    }
 7187                }
 7188
 7189                // If snippet state is not at the last tabstop, push it back on the stack
 7190                if snippet.active_index + 1 < snippet.ranges.len() {
 7191                    self.snippet_stack.push(snippet);
 7192                }
 7193                return true;
 7194            }
 7195        }
 7196
 7197        false
 7198    }
 7199
 7200    pub fn clear(&mut self, window: &mut Window, cx: &mut Context<Self>) {
 7201        self.transact(window, cx, |this, window, cx| {
 7202            this.select_all(&SelectAll, window, cx);
 7203            this.insert("", window, cx);
 7204        });
 7205    }
 7206
 7207    pub fn backspace(&mut self, _: &Backspace, window: &mut Window, cx: &mut Context<Self>) {
 7208        self.transact(window, cx, |this, window, cx| {
 7209            this.select_autoclose_pair(window, cx);
 7210            let mut linked_ranges = HashMap::<_, Vec<_>>::default();
 7211            if !this.linked_edit_ranges.is_empty() {
 7212                let selections = this.selections.all::<MultiBufferPoint>(cx);
 7213                let snapshot = this.buffer.read(cx).snapshot(cx);
 7214
 7215                for selection in selections.iter() {
 7216                    let selection_start = snapshot.anchor_before(selection.start).text_anchor;
 7217                    let selection_end = snapshot.anchor_after(selection.end).text_anchor;
 7218                    if selection_start.buffer_id != selection_end.buffer_id {
 7219                        continue;
 7220                    }
 7221                    if let Some(ranges) =
 7222                        this.linked_editing_ranges_for(selection_start..selection_end, cx)
 7223                    {
 7224                        for (buffer, entries) in ranges {
 7225                            linked_ranges.entry(buffer).or_default().extend(entries);
 7226                        }
 7227                    }
 7228                }
 7229            }
 7230
 7231            let mut selections = this.selections.all::<MultiBufferPoint>(cx);
 7232            if !this.selections.line_mode {
 7233                let display_map = this.display_map.update(cx, |map, cx| map.snapshot(cx));
 7234                for selection in &mut selections {
 7235                    if selection.is_empty() {
 7236                        let old_head = selection.head();
 7237                        let mut new_head =
 7238                            movement::left(&display_map, old_head.to_display_point(&display_map))
 7239                                .to_point(&display_map);
 7240                        if let Some((buffer, line_buffer_range)) = display_map
 7241                            .buffer_snapshot
 7242                            .buffer_line_for_row(MultiBufferRow(old_head.row))
 7243                        {
 7244                            let indent_size =
 7245                                buffer.indent_size_for_line(line_buffer_range.start.row);
 7246                            let indent_len = match indent_size.kind {
 7247                                IndentKind::Space => {
 7248                                    buffer.settings_at(line_buffer_range.start, cx).tab_size
 7249                                }
 7250                                IndentKind::Tab => NonZeroU32::new(1).unwrap(),
 7251                            };
 7252                            if old_head.column <= indent_size.len && old_head.column > 0 {
 7253                                let indent_len = indent_len.get();
 7254                                new_head = cmp::min(
 7255                                    new_head,
 7256                                    MultiBufferPoint::new(
 7257                                        old_head.row,
 7258                                        ((old_head.column - 1) / indent_len) * indent_len,
 7259                                    ),
 7260                                );
 7261                            }
 7262                        }
 7263
 7264                        selection.set_head(new_head, SelectionGoal::None);
 7265                    }
 7266                }
 7267            }
 7268
 7269            this.signature_help_state.set_backspace_pressed(true);
 7270            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 7271                s.select(selections)
 7272            });
 7273            this.insert("", window, cx);
 7274            let empty_str: Arc<str> = Arc::from("");
 7275            for (buffer, edits) in linked_ranges {
 7276                let snapshot = buffer.read(cx).snapshot();
 7277                use text::ToPoint as TP;
 7278
 7279                let edits = edits
 7280                    .into_iter()
 7281                    .map(|range| {
 7282                        let end_point = TP::to_point(&range.end, &snapshot);
 7283                        let mut start_point = TP::to_point(&range.start, &snapshot);
 7284
 7285                        if end_point == start_point {
 7286                            let offset = text::ToOffset::to_offset(&range.start, &snapshot)
 7287                                .saturating_sub(1);
 7288                            start_point =
 7289                                snapshot.clip_point(TP::to_point(&offset, &snapshot), Bias::Left);
 7290                        };
 7291
 7292                        (start_point..end_point, empty_str.clone())
 7293                    })
 7294                    .sorted_by_key(|(range, _)| range.start)
 7295                    .collect::<Vec<_>>();
 7296                buffer.update(cx, |this, cx| {
 7297                    this.edit(edits, None, cx);
 7298                })
 7299            }
 7300            this.refresh_inline_completion(true, false, window, cx);
 7301            linked_editing_ranges::refresh_linked_ranges(this, window, cx);
 7302        });
 7303    }
 7304
 7305    pub fn delete(&mut self, _: &Delete, window: &mut Window, cx: &mut Context<Self>) {
 7306        self.transact(window, cx, |this, window, cx| {
 7307            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 7308                let line_mode = s.line_mode;
 7309                s.move_with(|map, selection| {
 7310                    if selection.is_empty() && !line_mode {
 7311                        let cursor = movement::right(map, selection.head());
 7312                        selection.end = cursor;
 7313                        selection.reversed = true;
 7314                        selection.goal = SelectionGoal::None;
 7315                    }
 7316                })
 7317            });
 7318            this.insert("", window, cx);
 7319            this.refresh_inline_completion(true, false, window, cx);
 7320        });
 7321    }
 7322
 7323    pub fn backtab(&mut self, _: &Backtab, window: &mut Window, cx: &mut Context<Self>) {
 7324        if self.move_to_prev_snippet_tabstop(window, cx) {
 7325            return;
 7326        }
 7327
 7328        self.outdent(&Outdent, window, cx);
 7329    }
 7330
 7331    pub fn tab(&mut self, _: &Tab, window: &mut Window, cx: &mut Context<Self>) {
 7332        if self.move_to_next_snippet_tabstop(window, cx) || self.read_only(cx) {
 7333            return;
 7334        }
 7335
 7336        let mut selections = self.selections.all_adjusted(cx);
 7337        let buffer = self.buffer.read(cx);
 7338        let snapshot = buffer.snapshot(cx);
 7339        let rows_iter = selections.iter().map(|s| s.head().row);
 7340        let suggested_indents = snapshot.suggested_indents(rows_iter, cx);
 7341
 7342        let mut edits = Vec::new();
 7343        let mut prev_edited_row = 0;
 7344        let mut row_delta = 0;
 7345        for selection in &mut selections {
 7346            if selection.start.row != prev_edited_row {
 7347                row_delta = 0;
 7348            }
 7349            prev_edited_row = selection.end.row;
 7350
 7351            // If the selection is non-empty, then increase the indentation of the selected lines.
 7352            if !selection.is_empty() {
 7353                row_delta =
 7354                    Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
 7355                continue;
 7356            }
 7357
 7358            // If the selection is empty and the cursor is in the leading whitespace before the
 7359            // suggested indentation, then auto-indent the line.
 7360            let cursor = selection.head();
 7361            let current_indent = snapshot.indent_size_for_line(MultiBufferRow(cursor.row));
 7362            if let Some(suggested_indent) =
 7363                suggested_indents.get(&MultiBufferRow(cursor.row)).copied()
 7364            {
 7365                if cursor.column < suggested_indent.len
 7366                    && cursor.column <= current_indent.len
 7367                    && current_indent.len <= suggested_indent.len
 7368                {
 7369                    selection.start = Point::new(cursor.row, suggested_indent.len);
 7370                    selection.end = selection.start;
 7371                    if row_delta == 0 {
 7372                        edits.extend(Buffer::edit_for_indent_size_adjustment(
 7373                            cursor.row,
 7374                            current_indent,
 7375                            suggested_indent,
 7376                        ));
 7377                        row_delta = suggested_indent.len - current_indent.len;
 7378                    }
 7379                    continue;
 7380                }
 7381            }
 7382
 7383            // Otherwise, insert a hard or soft tab.
 7384            let settings = buffer.language_settings_at(cursor, cx);
 7385            let tab_size = if settings.hard_tabs {
 7386                IndentSize::tab()
 7387            } else {
 7388                let tab_size = settings.tab_size.get();
 7389                let char_column = snapshot
 7390                    .text_for_range(Point::new(cursor.row, 0)..cursor)
 7391                    .flat_map(str::chars)
 7392                    .count()
 7393                    + row_delta as usize;
 7394                let chars_to_next_tab_stop = tab_size - (char_column as u32 % tab_size);
 7395                IndentSize::spaces(chars_to_next_tab_stop)
 7396            };
 7397            selection.start = Point::new(cursor.row, cursor.column + row_delta + tab_size.len);
 7398            selection.end = selection.start;
 7399            edits.push((cursor..cursor, tab_size.chars().collect::<String>()));
 7400            row_delta += tab_size.len;
 7401        }
 7402
 7403        self.transact(window, cx, |this, window, cx| {
 7404            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
 7405            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 7406                s.select(selections)
 7407            });
 7408            this.refresh_inline_completion(true, false, window, cx);
 7409        });
 7410    }
 7411
 7412    pub fn indent(&mut self, _: &Indent, window: &mut Window, cx: &mut Context<Self>) {
 7413        if self.read_only(cx) {
 7414            return;
 7415        }
 7416        let mut selections = self.selections.all::<Point>(cx);
 7417        let mut prev_edited_row = 0;
 7418        let mut row_delta = 0;
 7419        let mut edits = Vec::new();
 7420        let buffer = self.buffer.read(cx);
 7421        let snapshot = buffer.snapshot(cx);
 7422        for selection in &mut selections {
 7423            if selection.start.row != prev_edited_row {
 7424                row_delta = 0;
 7425            }
 7426            prev_edited_row = selection.end.row;
 7427
 7428            row_delta =
 7429                Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
 7430        }
 7431
 7432        self.transact(window, cx, |this, window, cx| {
 7433            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
 7434            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 7435                s.select(selections)
 7436            });
 7437        });
 7438    }
 7439
 7440    fn indent_selection(
 7441        buffer: &MultiBuffer,
 7442        snapshot: &MultiBufferSnapshot,
 7443        selection: &mut Selection<Point>,
 7444        edits: &mut Vec<(Range<Point>, String)>,
 7445        delta_for_start_row: u32,
 7446        cx: &App,
 7447    ) -> u32 {
 7448        let settings = buffer.language_settings_at(selection.start, cx);
 7449        let tab_size = settings.tab_size.get();
 7450        let indent_kind = if settings.hard_tabs {
 7451            IndentKind::Tab
 7452        } else {
 7453            IndentKind::Space
 7454        };
 7455        let mut start_row = selection.start.row;
 7456        let mut end_row = selection.end.row + 1;
 7457
 7458        // If a selection ends at the beginning of a line, don't indent
 7459        // that last line.
 7460        if selection.end.column == 0 && selection.end.row > selection.start.row {
 7461            end_row -= 1;
 7462        }
 7463
 7464        // Avoid re-indenting a row that has already been indented by a
 7465        // previous selection, but still update this selection's column
 7466        // to reflect that indentation.
 7467        if delta_for_start_row > 0 {
 7468            start_row += 1;
 7469            selection.start.column += delta_for_start_row;
 7470            if selection.end.row == selection.start.row {
 7471                selection.end.column += delta_for_start_row;
 7472            }
 7473        }
 7474
 7475        let mut delta_for_end_row = 0;
 7476        let has_multiple_rows = start_row + 1 != end_row;
 7477        for row in start_row..end_row {
 7478            let current_indent = snapshot.indent_size_for_line(MultiBufferRow(row));
 7479            let indent_delta = match (current_indent.kind, indent_kind) {
 7480                (IndentKind::Space, IndentKind::Space) => {
 7481                    let columns_to_next_tab_stop = tab_size - (current_indent.len % tab_size);
 7482                    IndentSize::spaces(columns_to_next_tab_stop)
 7483                }
 7484                (IndentKind::Tab, IndentKind::Space) => IndentSize::spaces(tab_size),
 7485                (_, IndentKind::Tab) => IndentSize::tab(),
 7486            };
 7487
 7488            let start = if has_multiple_rows || current_indent.len < selection.start.column {
 7489                0
 7490            } else {
 7491                selection.start.column
 7492            };
 7493            let row_start = Point::new(row, start);
 7494            edits.push((
 7495                row_start..row_start,
 7496                indent_delta.chars().collect::<String>(),
 7497            ));
 7498
 7499            // Update this selection's endpoints to reflect the indentation.
 7500            if row == selection.start.row {
 7501                selection.start.column += indent_delta.len;
 7502            }
 7503            if row == selection.end.row {
 7504                selection.end.column += indent_delta.len;
 7505                delta_for_end_row = indent_delta.len;
 7506            }
 7507        }
 7508
 7509        if selection.start.row == selection.end.row {
 7510            delta_for_start_row + delta_for_end_row
 7511        } else {
 7512            delta_for_end_row
 7513        }
 7514    }
 7515
 7516    pub fn outdent(&mut self, _: &Outdent, window: &mut Window, cx: &mut Context<Self>) {
 7517        if self.read_only(cx) {
 7518            return;
 7519        }
 7520        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 7521        let selections = self.selections.all::<Point>(cx);
 7522        let mut deletion_ranges = Vec::new();
 7523        let mut last_outdent = None;
 7524        {
 7525            let buffer = self.buffer.read(cx);
 7526            let snapshot = buffer.snapshot(cx);
 7527            for selection in &selections {
 7528                let settings = buffer.language_settings_at(selection.start, cx);
 7529                let tab_size = settings.tab_size.get();
 7530                let mut rows = selection.spanned_rows(false, &display_map);
 7531
 7532                // Avoid re-outdenting a row that has already been outdented by a
 7533                // previous selection.
 7534                if let Some(last_row) = last_outdent {
 7535                    if last_row == rows.start {
 7536                        rows.start = rows.start.next_row();
 7537                    }
 7538                }
 7539                let has_multiple_rows = rows.len() > 1;
 7540                for row in rows.iter_rows() {
 7541                    let indent_size = snapshot.indent_size_for_line(row);
 7542                    if indent_size.len > 0 {
 7543                        let deletion_len = match indent_size.kind {
 7544                            IndentKind::Space => {
 7545                                let columns_to_prev_tab_stop = indent_size.len % tab_size;
 7546                                if columns_to_prev_tab_stop == 0 {
 7547                                    tab_size
 7548                                } else {
 7549                                    columns_to_prev_tab_stop
 7550                                }
 7551                            }
 7552                            IndentKind::Tab => 1,
 7553                        };
 7554                        let start = if has_multiple_rows
 7555                            || deletion_len > selection.start.column
 7556                            || indent_size.len < selection.start.column
 7557                        {
 7558                            0
 7559                        } else {
 7560                            selection.start.column - deletion_len
 7561                        };
 7562                        deletion_ranges.push(
 7563                            Point::new(row.0, start)..Point::new(row.0, start + deletion_len),
 7564                        );
 7565                        last_outdent = Some(row);
 7566                    }
 7567                }
 7568            }
 7569        }
 7570
 7571        self.transact(window, cx, |this, window, cx| {
 7572            this.buffer.update(cx, |buffer, cx| {
 7573                let empty_str: Arc<str> = Arc::default();
 7574                buffer.edit(
 7575                    deletion_ranges
 7576                        .into_iter()
 7577                        .map(|range| (range, empty_str.clone())),
 7578                    None,
 7579                    cx,
 7580                );
 7581            });
 7582            let selections = this.selections.all::<usize>(cx);
 7583            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 7584                s.select(selections)
 7585            });
 7586        });
 7587    }
 7588
 7589    pub fn autoindent(&mut self, _: &AutoIndent, window: &mut Window, cx: &mut Context<Self>) {
 7590        if self.read_only(cx) {
 7591            return;
 7592        }
 7593        let selections = self
 7594            .selections
 7595            .all::<usize>(cx)
 7596            .into_iter()
 7597            .map(|s| s.range());
 7598
 7599        self.transact(window, cx, |this, window, cx| {
 7600            this.buffer.update(cx, |buffer, cx| {
 7601                buffer.autoindent_ranges(selections, cx);
 7602            });
 7603            let selections = this.selections.all::<usize>(cx);
 7604            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 7605                s.select(selections)
 7606            });
 7607        });
 7608    }
 7609
 7610    pub fn delete_line(&mut self, _: &DeleteLine, window: &mut Window, cx: &mut Context<Self>) {
 7611        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 7612        let selections = self.selections.all::<Point>(cx);
 7613
 7614        let mut new_cursors = Vec::new();
 7615        let mut edit_ranges = Vec::new();
 7616        let mut selections = selections.iter().peekable();
 7617        while let Some(selection) = selections.next() {
 7618            let mut rows = selection.spanned_rows(false, &display_map);
 7619            let goal_display_column = selection.head().to_display_point(&display_map).column();
 7620
 7621            // Accumulate contiguous regions of rows that we want to delete.
 7622            while let Some(next_selection) = selections.peek() {
 7623                let next_rows = next_selection.spanned_rows(false, &display_map);
 7624                if next_rows.start <= rows.end {
 7625                    rows.end = next_rows.end;
 7626                    selections.next().unwrap();
 7627                } else {
 7628                    break;
 7629                }
 7630            }
 7631
 7632            let buffer = &display_map.buffer_snapshot;
 7633            let mut edit_start = Point::new(rows.start.0, 0).to_offset(buffer);
 7634            let edit_end;
 7635            let cursor_buffer_row;
 7636            if buffer.max_point().row >= rows.end.0 {
 7637                // If there's a line after the range, delete the \n from the end of the row range
 7638                // and position the cursor on the next line.
 7639                edit_end = Point::new(rows.end.0, 0).to_offset(buffer);
 7640                cursor_buffer_row = rows.end;
 7641            } else {
 7642                // If there isn't a line after the range, delete the \n from the line before the
 7643                // start of the row range and position the cursor there.
 7644                edit_start = edit_start.saturating_sub(1);
 7645                edit_end = buffer.len();
 7646                cursor_buffer_row = rows.start.previous_row();
 7647            }
 7648
 7649            let mut cursor = Point::new(cursor_buffer_row.0, 0).to_display_point(&display_map);
 7650            *cursor.column_mut() =
 7651                cmp::min(goal_display_column, display_map.line_len(cursor.row()));
 7652
 7653            new_cursors.push((
 7654                selection.id,
 7655                buffer.anchor_after(cursor.to_point(&display_map)),
 7656            ));
 7657            edit_ranges.push(edit_start..edit_end);
 7658        }
 7659
 7660        self.transact(window, cx, |this, window, cx| {
 7661            let buffer = this.buffer.update(cx, |buffer, cx| {
 7662                let empty_str: Arc<str> = Arc::default();
 7663                buffer.edit(
 7664                    edit_ranges
 7665                        .into_iter()
 7666                        .map(|range| (range, empty_str.clone())),
 7667                    None,
 7668                    cx,
 7669                );
 7670                buffer.snapshot(cx)
 7671            });
 7672            let new_selections = new_cursors
 7673                .into_iter()
 7674                .map(|(id, cursor)| {
 7675                    let cursor = cursor.to_point(&buffer);
 7676                    Selection {
 7677                        id,
 7678                        start: cursor,
 7679                        end: cursor,
 7680                        reversed: false,
 7681                        goal: SelectionGoal::None,
 7682                    }
 7683                })
 7684                .collect();
 7685
 7686            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 7687                s.select(new_selections);
 7688            });
 7689        });
 7690    }
 7691
 7692    pub fn join_lines_impl(
 7693        &mut self,
 7694        insert_whitespace: bool,
 7695        window: &mut Window,
 7696        cx: &mut Context<Self>,
 7697    ) {
 7698        if self.read_only(cx) {
 7699            return;
 7700        }
 7701        let mut row_ranges = Vec::<Range<MultiBufferRow>>::new();
 7702        for selection in self.selections.all::<Point>(cx) {
 7703            let start = MultiBufferRow(selection.start.row);
 7704            // Treat single line selections as if they include the next line. Otherwise this action
 7705            // would do nothing for single line selections individual cursors.
 7706            let end = if selection.start.row == selection.end.row {
 7707                MultiBufferRow(selection.start.row + 1)
 7708            } else {
 7709                MultiBufferRow(selection.end.row)
 7710            };
 7711
 7712            if let Some(last_row_range) = row_ranges.last_mut() {
 7713                if start <= last_row_range.end {
 7714                    last_row_range.end = end;
 7715                    continue;
 7716                }
 7717            }
 7718            row_ranges.push(start..end);
 7719        }
 7720
 7721        let snapshot = self.buffer.read(cx).snapshot(cx);
 7722        let mut cursor_positions = Vec::new();
 7723        for row_range in &row_ranges {
 7724            let anchor = snapshot.anchor_before(Point::new(
 7725                row_range.end.previous_row().0,
 7726                snapshot.line_len(row_range.end.previous_row()),
 7727            ));
 7728            cursor_positions.push(anchor..anchor);
 7729        }
 7730
 7731        self.transact(window, cx, |this, window, cx| {
 7732            for row_range in row_ranges.into_iter().rev() {
 7733                for row in row_range.iter_rows().rev() {
 7734                    let end_of_line = Point::new(row.0, snapshot.line_len(row));
 7735                    let next_line_row = row.next_row();
 7736                    let indent = snapshot.indent_size_for_line(next_line_row);
 7737                    let start_of_next_line = Point::new(next_line_row.0, indent.len);
 7738
 7739                    let replace =
 7740                        if snapshot.line_len(next_line_row) > indent.len && insert_whitespace {
 7741                            " "
 7742                        } else {
 7743                            ""
 7744                        };
 7745
 7746                    this.buffer.update(cx, |buffer, cx| {
 7747                        buffer.edit([(end_of_line..start_of_next_line, replace)], None, cx)
 7748                    });
 7749                }
 7750            }
 7751
 7752            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 7753                s.select_anchor_ranges(cursor_positions)
 7754            });
 7755        });
 7756    }
 7757
 7758    pub fn join_lines(&mut self, _: &JoinLines, window: &mut Window, cx: &mut Context<Self>) {
 7759        self.join_lines_impl(true, window, cx);
 7760    }
 7761
 7762    pub fn sort_lines_case_sensitive(
 7763        &mut self,
 7764        _: &SortLinesCaseSensitive,
 7765        window: &mut Window,
 7766        cx: &mut Context<Self>,
 7767    ) {
 7768        self.manipulate_lines(window, cx, |lines| lines.sort())
 7769    }
 7770
 7771    pub fn sort_lines_case_insensitive(
 7772        &mut self,
 7773        _: &SortLinesCaseInsensitive,
 7774        window: &mut Window,
 7775        cx: &mut Context<Self>,
 7776    ) {
 7777        self.manipulate_lines(window, cx, |lines| {
 7778            lines.sort_by_key(|line| line.to_lowercase())
 7779        })
 7780    }
 7781
 7782    pub fn unique_lines_case_insensitive(
 7783        &mut self,
 7784        _: &UniqueLinesCaseInsensitive,
 7785        window: &mut Window,
 7786        cx: &mut Context<Self>,
 7787    ) {
 7788        self.manipulate_lines(window, cx, |lines| {
 7789            let mut seen = HashSet::default();
 7790            lines.retain(|line| seen.insert(line.to_lowercase()));
 7791        })
 7792    }
 7793
 7794    pub fn unique_lines_case_sensitive(
 7795        &mut self,
 7796        _: &UniqueLinesCaseSensitive,
 7797        window: &mut Window,
 7798        cx: &mut Context<Self>,
 7799    ) {
 7800        self.manipulate_lines(window, cx, |lines| {
 7801            let mut seen = HashSet::default();
 7802            lines.retain(|line| seen.insert(*line));
 7803        })
 7804    }
 7805
 7806    pub fn reload_file(&mut self, _: &ReloadFile, window: &mut Window, cx: &mut Context<Self>) {
 7807        let Some(project) = self.project.clone() else {
 7808            return;
 7809        };
 7810        self.reload(project, window, cx)
 7811            .detach_and_notify_err(window, cx);
 7812    }
 7813
 7814    pub fn restore_file(
 7815        &mut self,
 7816        _: &::git::RestoreFile,
 7817        window: &mut Window,
 7818        cx: &mut Context<Self>,
 7819    ) {
 7820        let mut buffer_ids = HashSet::default();
 7821        let snapshot = self.buffer().read(cx).snapshot(cx);
 7822        for selection in self.selections.all::<usize>(cx) {
 7823            buffer_ids.extend(snapshot.buffer_ids_for_range(selection.range()))
 7824        }
 7825
 7826        let buffer = self.buffer().read(cx);
 7827        let ranges = buffer_ids
 7828            .into_iter()
 7829            .flat_map(|buffer_id| buffer.excerpt_ranges_for_buffer(buffer_id, cx))
 7830            .collect::<Vec<_>>();
 7831
 7832        self.restore_hunks_in_ranges(ranges, window, cx);
 7833    }
 7834
 7835    pub fn git_restore(&mut self, _: &Restore, window: &mut Window, cx: &mut Context<Self>) {
 7836        let selections = self
 7837            .selections
 7838            .all(cx)
 7839            .into_iter()
 7840            .map(|s| s.range())
 7841            .collect();
 7842        self.restore_hunks_in_ranges(selections, window, cx);
 7843    }
 7844
 7845    fn restore_hunks_in_ranges(
 7846        &mut self,
 7847        ranges: Vec<Range<Point>>,
 7848        window: &mut Window,
 7849        cx: &mut Context<Editor>,
 7850    ) {
 7851        let mut revert_changes = HashMap::default();
 7852        let chunk_by = self
 7853            .snapshot(window, cx)
 7854            .hunks_for_ranges(ranges)
 7855            .into_iter()
 7856            .chunk_by(|hunk| hunk.buffer_id);
 7857        for (buffer_id, hunks) in &chunk_by {
 7858            let hunks = hunks.collect::<Vec<_>>();
 7859            for hunk in &hunks {
 7860                self.prepare_restore_change(&mut revert_changes, hunk, cx);
 7861            }
 7862            self.do_stage_or_unstage(false, buffer_id, hunks.into_iter(), cx);
 7863        }
 7864        drop(chunk_by);
 7865        if !revert_changes.is_empty() {
 7866            self.transact(window, cx, |editor, window, cx| {
 7867                editor.restore(revert_changes, window, cx);
 7868            });
 7869        }
 7870    }
 7871
 7872    pub fn open_active_item_in_terminal(
 7873        &mut self,
 7874        _: &OpenInTerminal,
 7875        window: &mut Window,
 7876        cx: &mut Context<Self>,
 7877    ) {
 7878        if let Some(working_directory) = self.active_excerpt(cx).and_then(|(_, buffer, _)| {
 7879            let project_path = buffer.read(cx).project_path(cx)?;
 7880            let project = self.project.as_ref()?.read(cx);
 7881            let entry = project.entry_for_path(&project_path, cx)?;
 7882            let parent = match &entry.canonical_path {
 7883                Some(canonical_path) => canonical_path.to_path_buf(),
 7884                None => project.absolute_path(&project_path, cx)?,
 7885            }
 7886            .parent()?
 7887            .to_path_buf();
 7888            Some(parent)
 7889        }) {
 7890            window.dispatch_action(OpenTerminal { working_directory }.boxed_clone(), cx);
 7891        }
 7892    }
 7893
 7894    pub fn prepare_restore_change(
 7895        &self,
 7896        revert_changes: &mut HashMap<BufferId, Vec<(Range<text::Anchor>, Rope)>>,
 7897        hunk: &MultiBufferDiffHunk,
 7898        cx: &mut App,
 7899    ) -> Option<()> {
 7900        if hunk.is_created_file() {
 7901            return None;
 7902        }
 7903        let buffer = self.buffer.read(cx);
 7904        let diff = buffer.diff_for(hunk.buffer_id)?;
 7905        let buffer = buffer.buffer(hunk.buffer_id)?;
 7906        let buffer = buffer.read(cx);
 7907        let original_text = diff
 7908            .read(cx)
 7909            .base_text()
 7910            .as_rope()
 7911            .slice(hunk.diff_base_byte_range.clone());
 7912        let buffer_snapshot = buffer.snapshot();
 7913        let buffer_revert_changes = revert_changes.entry(buffer.remote_id()).or_default();
 7914        if let Err(i) = buffer_revert_changes.binary_search_by(|probe| {
 7915            probe
 7916                .0
 7917                .start
 7918                .cmp(&hunk.buffer_range.start, &buffer_snapshot)
 7919                .then(probe.0.end.cmp(&hunk.buffer_range.end, &buffer_snapshot))
 7920        }) {
 7921            buffer_revert_changes.insert(i, (hunk.buffer_range.clone(), original_text));
 7922            Some(())
 7923        } else {
 7924            None
 7925        }
 7926    }
 7927
 7928    pub fn reverse_lines(&mut self, _: &ReverseLines, window: &mut Window, cx: &mut Context<Self>) {
 7929        self.manipulate_lines(window, cx, |lines| lines.reverse())
 7930    }
 7931
 7932    pub fn shuffle_lines(&mut self, _: &ShuffleLines, window: &mut Window, cx: &mut Context<Self>) {
 7933        self.manipulate_lines(window, cx, |lines| lines.shuffle(&mut thread_rng()))
 7934    }
 7935
 7936    fn manipulate_lines<Fn>(
 7937        &mut self,
 7938        window: &mut Window,
 7939        cx: &mut Context<Self>,
 7940        mut callback: Fn,
 7941    ) where
 7942        Fn: FnMut(&mut Vec<&str>),
 7943    {
 7944        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 7945        let buffer = self.buffer.read(cx).snapshot(cx);
 7946
 7947        let mut edits = Vec::new();
 7948
 7949        let selections = self.selections.all::<Point>(cx);
 7950        let mut selections = selections.iter().peekable();
 7951        let mut contiguous_row_selections = Vec::new();
 7952        let mut new_selections = Vec::new();
 7953        let mut added_lines = 0;
 7954        let mut removed_lines = 0;
 7955
 7956        while let Some(selection) = selections.next() {
 7957            let (start_row, end_row) = consume_contiguous_rows(
 7958                &mut contiguous_row_selections,
 7959                selection,
 7960                &display_map,
 7961                &mut selections,
 7962            );
 7963
 7964            let start_point = Point::new(start_row.0, 0);
 7965            let end_point = Point::new(
 7966                end_row.previous_row().0,
 7967                buffer.line_len(end_row.previous_row()),
 7968            );
 7969            let text = buffer
 7970                .text_for_range(start_point..end_point)
 7971                .collect::<String>();
 7972
 7973            let mut lines = text.split('\n').collect_vec();
 7974
 7975            let lines_before = lines.len();
 7976            callback(&mut lines);
 7977            let lines_after = lines.len();
 7978
 7979            edits.push((start_point..end_point, lines.join("\n")));
 7980
 7981            // Selections must change based on added and removed line count
 7982            let start_row =
 7983                MultiBufferRow(start_point.row + added_lines as u32 - removed_lines as u32);
 7984            let end_row = MultiBufferRow(start_row.0 + lines_after.saturating_sub(1) as u32);
 7985            new_selections.push(Selection {
 7986                id: selection.id,
 7987                start: start_row,
 7988                end: end_row,
 7989                goal: SelectionGoal::None,
 7990                reversed: selection.reversed,
 7991            });
 7992
 7993            if lines_after > lines_before {
 7994                added_lines += lines_after - lines_before;
 7995            } else if lines_before > lines_after {
 7996                removed_lines += lines_before - lines_after;
 7997            }
 7998        }
 7999
 8000        self.transact(window, cx, |this, window, cx| {
 8001            let buffer = this.buffer.update(cx, |buffer, cx| {
 8002                buffer.edit(edits, None, cx);
 8003                buffer.snapshot(cx)
 8004            });
 8005
 8006            // Recalculate offsets on newly edited buffer
 8007            let new_selections = new_selections
 8008                .iter()
 8009                .map(|s| {
 8010                    let start_point = Point::new(s.start.0, 0);
 8011                    let end_point = Point::new(s.end.0, buffer.line_len(s.end));
 8012                    Selection {
 8013                        id: s.id,
 8014                        start: buffer.point_to_offset(start_point),
 8015                        end: buffer.point_to_offset(end_point),
 8016                        goal: s.goal,
 8017                        reversed: s.reversed,
 8018                    }
 8019                })
 8020                .collect();
 8021
 8022            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8023                s.select(new_selections);
 8024            });
 8025
 8026            this.request_autoscroll(Autoscroll::fit(), cx);
 8027        });
 8028    }
 8029
 8030    pub fn convert_to_upper_case(
 8031        &mut self,
 8032        _: &ConvertToUpperCase,
 8033        window: &mut Window,
 8034        cx: &mut Context<Self>,
 8035    ) {
 8036        self.manipulate_text(window, cx, |text| text.to_uppercase())
 8037    }
 8038
 8039    pub fn convert_to_lower_case(
 8040        &mut self,
 8041        _: &ConvertToLowerCase,
 8042        window: &mut Window,
 8043        cx: &mut Context<Self>,
 8044    ) {
 8045        self.manipulate_text(window, cx, |text| text.to_lowercase())
 8046    }
 8047
 8048    pub fn convert_to_title_case(
 8049        &mut self,
 8050        _: &ConvertToTitleCase,
 8051        window: &mut Window,
 8052        cx: &mut Context<Self>,
 8053    ) {
 8054        self.manipulate_text(window, cx, |text| {
 8055            text.split('\n')
 8056                .map(|line| line.to_case(Case::Title))
 8057                .join("\n")
 8058        })
 8059    }
 8060
 8061    pub fn convert_to_snake_case(
 8062        &mut self,
 8063        _: &ConvertToSnakeCase,
 8064        window: &mut Window,
 8065        cx: &mut Context<Self>,
 8066    ) {
 8067        self.manipulate_text(window, cx, |text| text.to_case(Case::Snake))
 8068    }
 8069
 8070    pub fn convert_to_kebab_case(
 8071        &mut self,
 8072        _: &ConvertToKebabCase,
 8073        window: &mut Window,
 8074        cx: &mut Context<Self>,
 8075    ) {
 8076        self.manipulate_text(window, cx, |text| text.to_case(Case::Kebab))
 8077    }
 8078
 8079    pub fn convert_to_upper_camel_case(
 8080        &mut self,
 8081        _: &ConvertToUpperCamelCase,
 8082        window: &mut Window,
 8083        cx: &mut Context<Self>,
 8084    ) {
 8085        self.manipulate_text(window, cx, |text| {
 8086            text.split('\n')
 8087                .map(|line| line.to_case(Case::UpperCamel))
 8088                .join("\n")
 8089        })
 8090    }
 8091
 8092    pub fn convert_to_lower_camel_case(
 8093        &mut self,
 8094        _: &ConvertToLowerCamelCase,
 8095        window: &mut Window,
 8096        cx: &mut Context<Self>,
 8097    ) {
 8098        self.manipulate_text(window, cx, |text| text.to_case(Case::Camel))
 8099    }
 8100
 8101    pub fn convert_to_opposite_case(
 8102        &mut self,
 8103        _: &ConvertToOppositeCase,
 8104        window: &mut Window,
 8105        cx: &mut Context<Self>,
 8106    ) {
 8107        self.manipulate_text(window, cx, |text| {
 8108            text.chars()
 8109                .fold(String::with_capacity(text.len()), |mut t, c| {
 8110                    if c.is_uppercase() {
 8111                        t.extend(c.to_lowercase());
 8112                    } else {
 8113                        t.extend(c.to_uppercase());
 8114                    }
 8115                    t
 8116                })
 8117        })
 8118    }
 8119
 8120    fn manipulate_text<Fn>(&mut self, window: &mut Window, cx: &mut Context<Self>, mut callback: Fn)
 8121    where
 8122        Fn: FnMut(&str) -> String,
 8123    {
 8124        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8125        let buffer = self.buffer.read(cx).snapshot(cx);
 8126
 8127        let mut new_selections = Vec::new();
 8128        let mut edits = Vec::new();
 8129        let mut selection_adjustment = 0i32;
 8130
 8131        for selection in self.selections.all::<usize>(cx) {
 8132            let selection_is_empty = selection.is_empty();
 8133
 8134            let (start, end) = if selection_is_empty {
 8135                let word_range = movement::surrounding_word(
 8136                    &display_map,
 8137                    selection.start.to_display_point(&display_map),
 8138                );
 8139                let start = word_range.start.to_offset(&display_map, Bias::Left);
 8140                let end = word_range.end.to_offset(&display_map, Bias::Left);
 8141                (start, end)
 8142            } else {
 8143                (selection.start, selection.end)
 8144            };
 8145
 8146            let text = buffer.text_for_range(start..end).collect::<String>();
 8147            let old_length = text.len() as i32;
 8148            let text = callback(&text);
 8149
 8150            new_selections.push(Selection {
 8151                start: (start as i32 - selection_adjustment) as usize,
 8152                end: ((start + text.len()) as i32 - selection_adjustment) as usize,
 8153                goal: SelectionGoal::None,
 8154                ..selection
 8155            });
 8156
 8157            selection_adjustment += old_length - text.len() as i32;
 8158
 8159            edits.push((start..end, text));
 8160        }
 8161
 8162        self.transact(window, cx, |this, window, cx| {
 8163            this.buffer.update(cx, |buffer, cx| {
 8164                buffer.edit(edits, None, cx);
 8165            });
 8166
 8167            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8168                s.select(new_selections);
 8169            });
 8170
 8171            this.request_autoscroll(Autoscroll::fit(), cx);
 8172        });
 8173    }
 8174
 8175    pub fn duplicate(
 8176        &mut self,
 8177        upwards: bool,
 8178        whole_lines: bool,
 8179        window: &mut Window,
 8180        cx: &mut Context<Self>,
 8181    ) {
 8182        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8183        let buffer = &display_map.buffer_snapshot;
 8184        let selections = self.selections.all::<Point>(cx);
 8185
 8186        let mut edits = Vec::new();
 8187        let mut selections_iter = selections.iter().peekable();
 8188        while let Some(selection) = selections_iter.next() {
 8189            let mut rows = selection.spanned_rows(false, &display_map);
 8190            // duplicate line-wise
 8191            if whole_lines || selection.start == selection.end {
 8192                // Avoid duplicating the same lines twice.
 8193                while let Some(next_selection) = selections_iter.peek() {
 8194                    let next_rows = next_selection.spanned_rows(false, &display_map);
 8195                    if next_rows.start < rows.end {
 8196                        rows.end = next_rows.end;
 8197                        selections_iter.next().unwrap();
 8198                    } else {
 8199                        break;
 8200                    }
 8201                }
 8202
 8203                // Copy the text from the selected row region and splice it either at the start
 8204                // or end of the region.
 8205                let start = Point::new(rows.start.0, 0);
 8206                let end = Point::new(
 8207                    rows.end.previous_row().0,
 8208                    buffer.line_len(rows.end.previous_row()),
 8209                );
 8210                let text = buffer
 8211                    .text_for_range(start..end)
 8212                    .chain(Some("\n"))
 8213                    .collect::<String>();
 8214                let insert_location = if upwards {
 8215                    Point::new(rows.end.0, 0)
 8216                } else {
 8217                    start
 8218                };
 8219                edits.push((insert_location..insert_location, text));
 8220            } else {
 8221                // duplicate character-wise
 8222                let start = selection.start;
 8223                let end = selection.end;
 8224                let text = buffer.text_for_range(start..end).collect::<String>();
 8225                edits.push((selection.end..selection.end, text));
 8226            }
 8227        }
 8228
 8229        self.transact(window, cx, |this, _, cx| {
 8230            this.buffer.update(cx, |buffer, cx| {
 8231                buffer.edit(edits, None, cx);
 8232            });
 8233
 8234            this.request_autoscroll(Autoscroll::fit(), cx);
 8235        });
 8236    }
 8237
 8238    pub fn duplicate_line_up(
 8239        &mut self,
 8240        _: &DuplicateLineUp,
 8241        window: &mut Window,
 8242        cx: &mut Context<Self>,
 8243    ) {
 8244        self.duplicate(true, true, window, cx);
 8245    }
 8246
 8247    pub fn duplicate_line_down(
 8248        &mut self,
 8249        _: &DuplicateLineDown,
 8250        window: &mut Window,
 8251        cx: &mut Context<Self>,
 8252    ) {
 8253        self.duplicate(false, true, window, cx);
 8254    }
 8255
 8256    pub fn duplicate_selection(
 8257        &mut self,
 8258        _: &DuplicateSelection,
 8259        window: &mut Window,
 8260        cx: &mut Context<Self>,
 8261    ) {
 8262        self.duplicate(false, false, window, cx);
 8263    }
 8264
 8265    pub fn move_line_up(&mut self, _: &MoveLineUp, window: &mut Window, cx: &mut Context<Self>) {
 8266        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8267        let buffer = self.buffer.read(cx).snapshot(cx);
 8268
 8269        let mut edits = Vec::new();
 8270        let mut unfold_ranges = Vec::new();
 8271        let mut refold_creases = Vec::new();
 8272
 8273        let selections = self.selections.all::<Point>(cx);
 8274        let mut selections = selections.iter().peekable();
 8275        let mut contiguous_row_selections = Vec::new();
 8276        let mut new_selections = Vec::new();
 8277
 8278        while let Some(selection) = selections.next() {
 8279            // Find all the selections that span a contiguous row range
 8280            let (start_row, end_row) = consume_contiguous_rows(
 8281                &mut contiguous_row_selections,
 8282                selection,
 8283                &display_map,
 8284                &mut selections,
 8285            );
 8286
 8287            // Move the text spanned by the row range to be before the line preceding the row range
 8288            if start_row.0 > 0 {
 8289                let range_to_move = Point::new(
 8290                    start_row.previous_row().0,
 8291                    buffer.line_len(start_row.previous_row()),
 8292                )
 8293                    ..Point::new(
 8294                        end_row.previous_row().0,
 8295                        buffer.line_len(end_row.previous_row()),
 8296                    );
 8297                let insertion_point = display_map
 8298                    .prev_line_boundary(Point::new(start_row.previous_row().0, 0))
 8299                    .0;
 8300
 8301                // Don't move lines across excerpts
 8302                if buffer
 8303                    .excerpt_containing(insertion_point..range_to_move.end)
 8304                    .is_some()
 8305                {
 8306                    let text = buffer
 8307                        .text_for_range(range_to_move.clone())
 8308                        .flat_map(|s| s.chars())
 8309                        .skip(1)
 8310                        .chain(['\n'])
 8311                        .collect::<String>();
 8312
 8313                    edits.push((
 8314                        buffer.anchor_after(range_to_move.start)
 8315                            ..buffer.anchor_before(range_to_move.end),
 8316                        String::new(),
 8317                    ));
 8318                    let insertion_anchor = buffer.anchor_after(insertion_point);
 8319                    edits.push((insertion_anchor..insertion_anchor, text));
 8320
 8321                    let row_delta = range_to_move.start.row - insertion_point.row + 1;
 8322
 8323                    // Move selections up
 8324                    new_selections.extend(contiguous_row_selections.drain(..).map(
 8325                        |mut selection| {
 8326                            selection.start.row -= row_delta;
 8327                            selection.end.row -= row_delta;
 8328                            selection
 8329                        },
 8330                    ));
 8331
 8332                    // Move folds up
 8333                    unfold_ranges.push(range_to_move.clone());
 8334                    for fold in display_map.folds_in_range(
 8335                        buffer.anchor_before(range_to_move.start)
 8336                            ..buffer.anchor_after(range_to_move.end),
 8337                    ) {
 8338                        let mut start = fold.range.start.to_point(&buffer);
 8339                        let mut end = fold.range.end.to_point(&buffer);
 8340                        start.row -= row_delta;
 8341                        end.row -= row_delta;
 8342                        refold_creases.push(Crease::simple(start..end, fold.placeholder.clone()));
 8343                    }
 8344                }
 8345            }
 8346
 8347            // If we didn't move line(s), preserve the existing selections
 8348            new_selections.append(&mut contiguous_row_selections);
 8349        }
 8350
 8351        self.transact(window, cx, |this, window, cx| {
 8352            this.unfold_ranges(&unfold_ranges, true, true, cx);
 8353            this.buffer.update(cx, |buffer, cx| {
 8354                for (range, text) in edits {
 8355                    buffer.edit([(range, text)], None, cx);
 8356                }
 8357            });
 8358            this.fold_creases(refold_creases, true, window, cx);
 8359            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8360                s.select(new_selections);
 8361            })
 8362        });
 8363    }
 8364
 8365    pub fn move_line_down(
 8366        &mut self,
 8367        _: &MoveLineDown,
 8368        window: &mut Window,
 8369        cx: &mut Context<Self>,
 8370    ) {
 8371        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8372        let buffer = self.buffer.read(cx).snapshot(cx);
 8373
 8374        let mut edits = Vec::new();
 8375        let mut unfold_ranges = Vec::new();
 8376        let mut refold_creases = Vec::new();
 8377
 8378        let selections = self.selections.all::<Point>(cx);
 8379        let mut selections = selections.iter().peekable();
 8380        let mut contiguous_row_selections = Vec::new();
 8381        let mut new_selections = Vec::new();
 8382
 8383        while let Some(selection) = selections.next() {
 8384            // Find all the selections that span a contiguous row range
 8385            let (start_row, end_row) = consume_contiguous_rows(
 8386                &mut contiguous_row_selections,
 8387                selection,
 8388                &display_map,
 8389                &mut selections,
 8390            );
 8391
 8392            // Move the text spanned by the row range to be after the last line of the row range
 8393            if end_row.0 <= buffer.max_point().row {
 8394                let range_to_move =
 8395                    MultiBufferPoint::new(start_row.0, 0)..MultiBufferPoint::new(end_row.0, 0);
 8396                let insertion_point = display_map
 8397                    .next_line_boundary(MultiBufferPoint::new(end_row.0, 0))
 8398                    .0;
 8399
 8400                // Don't move lines across excerpt boundaries
 8401                if buffer
 8402                    .excerpt_containing(range_to_move.start..insertion_point)
 8403                    .is_some()
 8404                {
 8405                    let mut text = String::from("\n");
 8406                    text.extend(buffer.text_for_range(range_to_move.clone()));
 8407                    text.pop(); // Drop trailing newline
 8408                    edits.push((
 8409                        buffer.anchor_after(range_to_move.start)
 8410                            ..buffer.anchor_before(range_to_move.end),
 8411                        String::new(),
 8412                    ));
 8413                    let insertion_anchor = buffer.anchor_after(insertion_point);
 8414                    edits.push((insertion_anchor..insertion_anchor, text));
 8415
 8416                    let row_delta = insertion_point.row - range_to_move.end.row + 1;
 8417
 8418                    // Move selections down
 8419                    new_selections.extend(contiguous_row_selections.drain(..).map(
 8420                        |mut selection| {
 8421                            selection.start.row += row_delta;
 8422                            selection.end.row += row_delta;
 8423                            selection
 8424                        },
 8425                    ));
 8426
 8427                    // Move folds down
 8428                    unfold_ranges.push(range_to_move.clone());
 8429                    for fold in display_map.folds_in_range(
 8430                        buffer.anchor_before(range_to_move.start)
 8431                            ..buffer.anchor_after(range_to_move.end),
 8432                    ) {
 8433                        let mut start = fold.range.start.to_point(&buffer);
 8434                        let mut end = fold.range.end.to_point(&buffer);
 8435                        start.row += row_delta;
 8436                        end.row += row_delta;
 8437                        refold_creases.push(Crease::simple(start..end, fold.placeholder.clone()));
 8438                    }
 8439                }
 8440            }
 8441
 8442            // If we didn't move line(s), preserve the existing selections
 8443            new_selections.append(&mut contiguous_row_selections);
 8444        }
 8445
 8446        self.transact(window, cx, |this, window, cx| {
 8447            this.unfold_ranges(&unfold_ranges, true, true, cx);
 8448            this.buffer.update(cx, |buffer, cx| {
 8449                for (range, text) in edits {
 8450                    buffer.edit([(range, text)], None, cx);
 8451                }
 8452            });
 8453            this.fold_creases(refold_creases, true, window, cx);
 8454            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8455                s.select(new_selections)
 8456            });
 8457        });
 8458    }
 8459
 8460    pub fn transpose(&mut self, _: &Transpose, window: &mut Window, cx: &mut Context<Self>) {
 8461        let text_layout_details = &self.text_layout_details(window);
 8462        self.transact(window, cx, |this, window, cx| {
 8463            let edits = this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8464                let mut edits: Vec<(Range<usize>, String)> = Default::default();
 8465                let line_mode = s.line_mode;
 8466                s.move_with(|display_map, selection| {
 8467                    if !selection.is_empty() || line_mode {
 8468                        return;
 8469                    }
 8470
 8471                    let mut head = selection.head();
 8472                    let mut transpose_offset = head.to_offset(display_map, Bias::Right);
 8473                    if head.column() == display_map.line_len(head.row()) {
 8474                        transpose_offset = display_map
 8475                            .buffer_snapshot
 8476                            .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
 8477                    }
 8478
 8479                    if transpose_offset == 0 {
 8480                        return;
 8481                    }
 8482
 8483                    *head.column_mut() += 1;
 8484                    head = display_map.clip_point(head, Bias::Right);
 8485                    let goal = SelectionGoal::HorizontalPosition(
 8486                        display_map
 8487                            .x_for_display_point(head, text_layout_details)
 8488                            .into(),
 8489                    );
 8490                    selection.collapse_to(head, goal);
 8491
 8492                    let transpose_start = display_map
 8493                        .buffer_snapshot
 8494                        .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
 8495                    if edits.last().map_or(true, |e| e.0.end <= transpose_start) {
 8496                        let transpose_end = display_map
 8497                            .buffer_snapshot
 8498                            .clip_offset(transpose_offset + 1, Bias::Right);
 8499                        if let Some(ch) =
 8500                            display_map.buffer_snapshot.chars_at(transpose_start).next()
 8501                        {
 8502                            edits.push((transpose_start..transpose_offset, String::new()));
 8503                            edits.push((transpose_end..transpose_end, ch.to_string()));
 8504                        }
 8505                    }
 8506                });
 8507                edits
 8508            });
 8509            this.buffer
 8510                .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
 8511            let selections = this.selections.all::<usize>(cx);
 8512            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8513                s.select(selections);
 8514            });
 8515        });
 8516    }
 8517
 8518    pub fn rewrap(&mut self, _: &Rewrap, _: &mut Window, cx: &mut Context<Self>) {
 8519        self.rewrap_impl(false, cx)
 8520    }
 8521
 8522    pub fn rewrap_impl(&mut self, override_language_settings: bool, cx: &mut Context<Self>) {
 8523        let buffer = self.buffer.read(cx).snapshot(cx);
 8524        let selections = self.selections.all::<Point>(cx);
 8525        let mut selections = selections.iter().peekable();
 8526
 8527        let mut edits = Vec::new();
 8528        let mut rewrapped_row_ranges = Vec::<RangeInclusive<u32>>::new();
 8529
 8530        while let Some(selection) = selections.next() {
 8531            let mut start_row = selection.start.row;
 8532            let mut end_row = selection.end.row;
 8533
 8534            // Skip selections that overlap with a range that has already been rewrapped.
 8535            let selection_range = start_row..end_row;
 8536            if rewrapped_row_ranges
 8537                .iter()
 8538                .any(|range| range.overlaps(&selection_range))
 8539            {
 8540                continue;
 8541            }
 8542
 8543            let tab_size = buffer.language_settings_at(selection.head(), cx).tab_size;
 8544
 8545            // Since not all lines in the selection may be at the same indent
 8546            // level, choose the indent size that is the most common between all
 8547            // of the lines.
 8548            //
 8549            // If there is a tie, we use the deepest indent.
 8550            let (indent_size, indent_end) = {
 8551                let mut indent_size_occurrences = HashMap::default();
 8552                let mut rows_by_indent_size = HashMap::<IndentSize, Vec<u32>>::default();
 8553
 8554                for row in start_row..=end_row {
 8555                    let indent = buffer.indent_size_for_line(MultiBufferRow(row));
 8556                    rows_by_indent_size.entry(indent).or_default().push(row);
 8557                    *indent_size_occurrences.entry(indent).or_insert(0) += 1;
 8558                }
 8559
 8560                let indent_size = indent_size_occurrences
 8561                    .into_iter()
 8562                    .max_by_key(|(indent, count)| (*count, indent.len_with_expanded_tabs(tab_size)))
 8563                    .map(|(indent, _)| indent)
 8564                    .unwrap_or_default();
 8565                let row = rows_by_indent_size[&indent_size][0];
 8566                let indent_end = Point::new(row, indent_size.len);
 8567
 8568                (indent_size, indent_end)
 8569            };
 8570
 8571            let mut line_prefix = indent_size.chars().collect::<String>();
 8572
 8573            let mut inside_comment = false;
 8574            if let Some(comment_prefix) =
 8575                buffer
 8576                    .language_scope_at(selection.head())
 8577                    .and_then(|language| {
 8578                        language
 8579                            .line_comment_prefixes()
 8580                            .iter()
 8581                            .find(|prefix| buffer.contains_str_at(indent_end, prefix))
 8582                            .cloned()
 8583                    })
 8584            {
 8585                line_prefix.push_str(&comment_prefix);
 8586                inside_comment = true;
 8587            }
 8588
 8589            let language_settings = buffer.language_settings_at(selection.head(), cx);
 8590            let allow_rewrap_based_on_language = match language_settings.allow_rewrap {
 8591                RewrapBehavior::InComments => inside_comment,
 8592                RewrapBehavior::InSelections => !selection.is_empty(),
 8593                RewrapBehavior::Anywhere => true,
 8594            };
 8595
 8596            let should_rewrap = override_language_settings
 8597                || allow_rewrap_based_on_language
 8598                || self.hard_wrap.is_some();
 8599            if !should_rewrap {
 8600                continue;
 8601            }
 8602
 8603            if selection.is_empty() {
 8604                'expand_upwards: while start_row > 0 {
 8605                    let prev_row = start_row - 1;
 8606                    if buffer.contains_str_at(Point::new(prev_row, 0), &line_prefix)
 8607                        && buffer.line_len(MultiBufferRow(prev_row)) as usize > line_prefix.len()
 8608                    {
 8609                        start_row = prev_row;
 8610                    } else {
 8611                        break 'expand_upwards;
 8612                    }
 8613                }
 8614
 8615                'expand_downwards: while end_row < buffer.max_point().row {
 8616                    let next_row = end_row + 1;
 8617                    if buffer.contains_str_at(Point::new(next_row, 0), &line_prefix)
 8618                        && buffer.line_len(MultiBufferRow(next_row)) as usize > line_prefix.len()
 8619                    {
 8620                        end_row = next_row;
 8621                    } else {
 8622                        break 'expand_downwards;
 8623                    }
 8624                }
 8625            }
 8626
 8627            let start = Point::new(start_row, 0);
 8628            let start_offset = start.to_offset(&buffer);
 8629            let end = Point::new(end_row, buffer.line_len(MultiBufferRow(end_row)));
 8630            let selection_text = buffer.text_for_range(start..end).collect::<String>();
 8631            let Some(lines_without_prefixes) = selection_text
 8632                .lines()
 8633                .map(|line| {
 8634                    line.strip_prefix(&line_prefix)
 8635                        .or_else(|| line.trim_start().strip_prefix(&line_prefix.trim_start()))
 8636                        .ok_or_else(|| {
 8637                            anyhow!("line did not start with prefix {line_prefix:?}: {line:?}")
 8638                        })
 8639                })
 8640                .collect::<Result<Vec<_>, _>>()
 8641                .log_err()
 8642            else {
 8643                continue;
 8644            };
 8645
 8646            let wrap_column = self.hard_wrap.unwrap_or_else(|| {
 8647                buffer
 8648                    .language_settings_at(Point::new(start_row, 0), cx)
 8649                    .preferred_line_length as usize
 8650            });
 8651            let wrapped_text = wrap_with_prefix(
 8652                line_prefix,
 8653                lines_without_prefixes.join(" "),
 8654                wrap_column,
 8655                tab_size,
 8656            );
 8657
 8658            // TODO: should always use char-based diff while still supporting cursor behavior that
 8659            // matches vim.
 8660            let mut diff_options = DiffOptions::default();
 8661            if override_language_settings {
 8662                diff_options.max_word_diff_len = 0;
 8663                diff_options.max_word_diff_line_count = 0;
 8664            } else {
 8665                diff_options.max_word_diff_len = usize::MAX;
 8666                diff_options.max_word_diff_line_count = usize::MAX;
 8667            }
 8668
 8669            for (old_range, new_text) in
 8670                text_diff_with_options(&selection_text, &wrapped_text, diff_options)
 8671            {
 8672                let edit_start = buffer.anchor_after(start_offset + old_range.start);
 8673                let edit_end = buffer.anchor_after(start_offset + old_range.end);
 8674                edits.push((edit_start..edit_end, new_text));
 8675            }
 8676
 8677            rewrapped_row_ranges.push(start_row..=end_row);
 8678        }
 8679
 8680        self.buffer
 8681            .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
 8682    }
 8683
 8684    pub fn cut_common(&mut self, window: &mut Window, cx: &mut Context<Self>) -> ClipboardItem {
 8685        let mut text = String::new();
 8686        let buffer = self.buffer.read(cx).snapshot(cx);
 8687        let mut selections = self.selections.all::<Point>(cx);
 8688        let mut clipboard_selections = Vec::with_capacity(selections.len());
 8689        {
 8690            let max_point = buffer.max_point();
 8691            let mut is_first = true;
 8692            for selection in &mut selections {
 8693                let is_entire_line = selection.is_empty() || self.selections.line_mode;
 8694                if is_entire_line {
 8695                    selection.start = Point::new(selection.start.row, 0);
 8696                    if !selection.is_empty() && selection.end.column == 0 {
 8697                        selection.end = cmp::min(max_point, selection.end);
 8698                    } else {
 8699                        selection.end = cmp::min(max_point, Point::new(selection.end.row + 1, 0));
 8700                    }
 8701                    selection.goal = SelectionGoal::None;
 8702                }
 8703                if is_first {
 8704                    is_first = false;
 8705                } else {
 8706                    text += "\n";
 8707                }
 8708                let mut len = 0;
 8709                for chunk in buffer.text_for_range(selection.start..selection.end) {
 8710                    text.push_str(chunk);
 8711                    len += chunk.len();
 8712                }
 8713                clipboard_selections.push(ClipboardSelection {
 8714                    len,
 8715                    is_entire_line,
 8716                    first_line_indent: buffer
 8717                        .indent_size_for_line(MultiBufferRow(selection.start.row))
 8718                        .len,
 8719                });
 8720            }
 8721        }
 8722
 8723        self.transact(window, cx, |this, window, cx| {
 8724            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8725                s.select(selections);
 8726            });
 8727            this.insert("", window, cx);
 8728        });
 8729        ClipboardItem::new_string_with_json_metadata(text, clipboard_selections)
 8730    }
 8731
 8732    pub fn cut(&mut self, _: &Cut, window: &mut Window, cx: &mut Context<Self>) {
 8733        let item = self.cut_common(window, cx);
 8734        cx.write_to_clipboard(item);
 8735    }
 8736
 8737    pub fn kill_ring_cut(&mut self, _: &KillRingCut, window: &mut Window, cx: &mut Context<Self>) {
 8738        self.change_selections(None, window, cx, |s| {
 8739            s.move_with(|snapshot, sel| {
 8740                if sel.is_empty() {
 8741                    sel.end = DisplayPoint::new(sel.end.row(), snapshot.line_len(sel.end.row()))
 8742                }
 8743            });
 8744        });
 8745        let item = self.cut_common(window, cx);
 8746        cx.set_global(KillRing(item))
 8747    }
 8748
 8749    pub fn kill_ring_yank(
 8750        &mut self,
 8751        _: &KillRingYank,
 8752        window: &mut Window,
 8753        cx: &mut Context<Self>,
 8754    ) {
 8755        let (text, metadata) = if let Some(KillRing(item)) = cx.try_global() {
 8756            if let Some(ClipboardEntry::String(kill_ring)) = item.entries().first() {
 8757                (kill_ring.text().to_string(), kill_ring.metadata_json())
 8758            } else {
 8759                return;
 8760            }
 8761        } else {
 8762            return;
 8763        };
 8764        self.do_paste(&text, metadata, false, window, cx);
 8765    }
 8766
 8767    pub fn copy(&mut self, _: &Copy, _: &mut Window, cx: &mut Context<Self>) {
 8768        let selections = self.selections.all::<Point>(cx);
 8769        let buffer = self.buffer.read(cx).read(cx);
 8770        let mut text = String::new();
 8771
 8772        let mut clipboard_selections = Vec::with_capacity(selections.len());
 8773        {
 8774            let max_point = buffer.max_point();
 8775            let mut is_first = true;
 8776            for selection in selections.iter() {
 8777                let mut start = selection.start;
 8778                let mut end = selection.end;
 8779                let is_entire_line = selection.is_empty() || self.selections.line_mode;
 8780                if is_entire_line {
 8781                    start = Point::new(start.row, 0);
 8782                    end = cmp::min(max_point, Point::new(end.row + 1, 0));
 8783                }
 8784                if is_first {
 8785                    is_first = false;
 8786                } else {
 8787                    text += "\n";
 8788                }
 8789                let mut len = 0;
 8790                for chunk in buffer.text_for_range(start..end) {
 8791                    text.push_str(chunk);
 8792                    len += chunk.len();
 8793                }
 8794                clipboard_selections.push(ClipboardSelection {
 8795                    len,
 8796                    is_entire_line,
 8797                    first_line_indent: buffer.indent_size_for_line(MultiBufferRow(start.row)).len,
 8798                });
 8799            }
 8800        }
 8801
 8802        cx.write_to_clipboard(ClipboardItem::new_string_with_json_metadata(
 8803            text,
 8804            clipboard_selections,
 8805        ));
 8806    }
 8807
 8808    pub fn do_paste(
 8809        &mut self,
 8810        text: &String,
 8811        clipboard_selections: Option<Vec<ClipboardSelection>>,
 8812        handle_entire_lines: bool,
 8813        window: &mut Window,
 8814        cx: &mut Context<Self>,
 8815    ) {
 8816        if self.read_only(cx) {
 8817            return;
 8818        }
 8819
 8820        let clipboard_text = Cow::Borrowed(text);
 8821
 8822        self.transact(window, cx, |this, window, cx| {
 8823            if let Some(mut clipboard_selections) = clipboard_selections {
 8824                let old_selections = this.selections.all::<usize>(cx);
 8825                let all_selections_were_entire_line =
 8826                    clipboard_selections.iter().all(|s| s.is_entire_line);
 8827                let first_selection_indent_column =
 8828                    clipboard_selections.first().map(|s| s.first_line_indent);
 8829                if clipboard_selections.len() != old_selections.len() {
 8830                    clipboard_selections.drain(..);
 8831                }
 8832                let cursor_offset = this.selections.last::<usize>(cx).head();
 8833                let mut auto_indent_on_paste = true;
 8834
 8835                this.buffer.update(cx, |buffer, cx| {
 8836                    let snapshot = buffer.read(cx);
 8837                    auto_indent_on_paste = snapshot
 8838                        .language_settings_at(cursor_offset, cx)
 8839                        .auto_indent_on_paste;
 8840
 8841                    let mut start_offset = 0;
 8842                    let mut edits = Vec::new();
 8843                    let mut original_indent_columns = Vec::new();
 8844                    for (ix, selection) in old_selections.iter().enumerate() {
 8845                        let to_insert;
 8846                        let entire_line;
 8847                        let original_indent_column;
 8848                        if let Some(clipboard_selection) = clipboard_selections.get(ix) {
 8849                            let end_offset = start_offset + clipboard_selection.len;
 8850                            to_insert = &clipboard_text[start_offset..end_offset];
 8851                            entire_line = clipboard_selection.is_entire_line;
 8852                            start_offset = end_offset + 1;
 8853                            original_indent_column = Some(clipboard_selection.first_line_indent);
 8854                        } else {
 8855                            to_insert = clipboard_text.as_str();
 8856                            entire_line = all_selections_were_entire_line;
 8857                            original_indent_column = first_selection_indent_column
 8858                        }
 8859
 8860                        // If the corresponding selection was empty when this slice of the
 8861                        // clipboard text was written, then the entire line containing the
 8862                        // selection was copied. If this selection is also currently empty,
 8863                        // then paste the line before the current line of the buffer.
 8864                        let range = if selection.is_empty() && handle_entire_lines && entire_line {
 8865                            let column = selection.start.to_point(&snapshot).column as usize;
 8866                            let line_start = selection.start - column;
 8867                            line_start..line_start
 8868                        } else {
 8869                            selection.range()
 8870                        };
 8871
 8872                        edits.push((range, to_insert));
 8873                        original_indent_columns.push(original_indent_column);
 8874                    }
 8875                    drop(snapshot);
 8876
 8877                    buffer.edit(
 8878                        edits,
 8879                        if auto_indent_on_paste {
 8880                            Some(AutoindentMode::Block {
 8881                                original_indent_columns,
 8882                            })
 8883                        } else {
 8884                            None
 8885                        },
 8886                        cx,
 8887                    );
 8888                });
 8889
 8890                let selections = this.selections.all::<usize>(cx);
 8891                this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8892                    s.select(selections)
 8893                });
 8894            } else {
 8895                this.insert(&clipboard_text, window, cx);
 8896            }
 8897        });
 8898    }
 8899
 8900    pub fn paste(&mut self, _: &Paste, window: &mut Window, cx: &mut Context<Self>) {
 8901        if let Some(item) = cx.read_from_clipboard() {
 8902            let entries = item.entries();
 8903
 8904            match entries.first() {
 8905                // For now, we only support applying metadata if there's one string. In the future, we can incorporate all the selections
 8906                // of all the pasted entries.
 8907                Some(ClipboardEntry::String(clipboard_string)) if entries.len() == 1 => self
 8908                    .do_paste(
 8909                        clipboard_string.text(),
 8910                        clipboard_string.metadata_json::<Vec<ClipboardSelection>>(),
 8911                        true,
 8912                        window,
 8913                        cx,
 8914                    ),
 8915                _ => self.do_paste(&item.text().unwrap_or_default(), None, true, window, cx),
 8916            }
 8917        }
 8918    }
 8919
 8920    pub fn undo(&mut self, _: &Undo, window: &mut Window, cx: &mut Context<Self>) {
 8921        if self.read_only(cx) {
 8922            return;
 8923        }
 8924
 8925        if let Some(transaction_id) = self.buffer.update(cx, |buffer, cx| buffer.undo(cx)) {
 8926            if let Some((selections, _)) =
 8927                self.selection_history.transaction(transaction_id).cloned()
 8928            {
 8929                self.change_selections(None, window, cx, |s| {
 8930                    s.select_anchors(selections.to_vec());
 8931                });
 8932            } else {
 8933                log::error!(
 8934                    "No entry in selection_history found for undo. \
 8935                     This may correspond to a bug where undo does not update the selection. \
 8936                     If this is occurring, please add details to \
 8937                     https://github.com/zed-industries/zed/issues/22692"
 8938                );
 8939            }
 8940            self.request_autoscroll(Autoscroll::fit(), cx);
 8941            self.unmark_text(window, cx);
 8942            self.refresh_inline_completion(true, false, window, cx);
 8943            cx.emit(EditorEvent::Edited { transaction_id });
 8944            cx.emit(EditorEvent::TransactionUndone { transaction_id });
 8945        }
 8946    }
 8947
 8948    pub fn redo(&mut self, _: &Redo, window: &mut Window, cx: &mut Context<Self>) {
 8949        if self.read_only(cx) {
 8950            return;
 8951        }
 8952
 8953        if let Some(transaction_id) = self.buffer.update(cx, |buffer, cx| buffer.redo(cx)) {
 8954            if let Some((_, Some(selections))) =
 8955                self.selection_history.transaction(transaction_id).cloned()
 8956            {
 8957                self.change_selections(None, window, cx, |s| {
 8958                    s.select_anchors(selections.to_vec());
 8959                });
 8960            } else {
 8961                log::error!(
 8962                    "No entry in selection_history found for redo. \
 8963                     This may correspond to a bug where undo does not update the selection. \
 8964                     If this is occurring, please add details to \
 8965                     https://github.com/zed-industries/zed/issues/22692"
 8966                );
 8967            }
 8968            self.request_autoscroll(Autoscroll::fit(), cx);
 8969            self.unmark_text(window, cx);
 8970            self.refresh_inline_completion(true, false, window, cx);
 8971            cx.emit(EditorEvent::Edited { transaction_id });
 8972        }
 8973    }
 8974
 8975    pub fn finalize_last_transaction(&mut self, cx: &mut Context<Self>) {
 8976        self.buffer
 8977            .update(cx, |buffer, cx| buffer.finalize_last_transaction(cx));
 8978    }
 8979
 8980    pub fn group_until_transaction(&mut self, tx_id: TransactionId, cx: &mut Context<Self>) {
 8981        self.buffer
 8982            .update(cx, |buffer, cx| buffer.group_until_transaction(tx_id, cx));
 8983    }
 8984
 8985    pub fn move_left(&mut self, _: &MoveLeft, window: &mut Window, cx: &mut Context<Self>) {
 8986        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8987            let line_mode = s.line_mode;
 8988            s.move_with(|map, selection| {
 8989                let cursor = if selection.is_empty() && !line_mode {
 8990                    movement::left(map, selection.start)
 8991                } else {
 8992                    selection.start
 8993                };
 8994                selection.collapse_to(cursor, SelectionGoal::None);
 8995            });
 8996        })
 8997    }
 8998
 8999    pub fn select_left(&mut self, _: &SelectLeft, window: &mut Window, cx: &mut Context<Self>) {
 9000        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9001            s.move_heads_with(|map, head, _| (movement::left(map, head), SelectionGoal::None));
 9002        })
 9003    }
 9004
 9005    pub fn move_right(&mut self, _: &MoveRight, window: &mut Window, cx: &mut Context<Self>) {
 9006        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9007            let line_mode = s.line_mode;
 9008            s.move_with(|map, selection| {
 9009                let cursor = if selection.is_empty() && !line_mode {
 9010                    movement::right(map, selection.end)
 9011                } else {
 9012                    selection.end
 9013                };
 9014                selection.collapse_to(cursor, SelectionGoal::None)
 9015            });
 9016        })
 9017    }
 9018
 9019    pub fn select_right(&mut self, _: &SelectRight, window: &mut Window, cx: &mut Context<Self>) {
 9020        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9021            s.move_heads_with(|map, head, _| (movement::right(map, head), SelectionGoal::None));
 9022        })
 9023    }
 9024
 9025    pub fn move_up(&mut self, _: &MoveUp, window: &mut Window, cx: &mut Context<Self>) {
 9026        if self.take_rename(true, window, cx).is_some() {
 9027            return;
 9028        }
 9029
 9030        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 9031            cx.propagate();
 9032            return;
 9033        }
 9034
 9035        let text_layout_details = &self.text_layout_details(window);
 9036        let selection_count = self.selections.count();
 9037        let first_selection = self.selections.first_anchor();
 9038
 9039        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9040            let line_mode = s.line_mode;
 9041            s.move_with(|map, selection| {
 9042                if !selection.is_empty() && !line_mode {
 9043                    selection.goal = SelectionGoal::None;
 9044                }
 9045                let (cursor, goal) = movement::up(
 9046                    map,
 9047                    selection.start,
 9048                    selection.goal,
 9049                    false,
 9050                    text_layout_details,
 9051                );
 9052                selection.collapse_to(cursor, goal);
 9053            });
 9054        });
 9055
 9056        if selection_count == 1 && first_selection.range() == self.selections.first_anchor().range()
 9057        {
 9058            cx.propagate();
 9059        }
 9060    }
 9061
 9062    pub fn move_up_by_lines(
 9063        &mut self,
 9064        action: &MoveUpByLines,
 9065        window: &mut Window,
 9066        cx: &mut Context<Self>,
 9067    ) {
 9068        if self.take_rename(true, window, cx).is_some() {
 9069            return;
 9070        }
 9071
 9072        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 9073            cx.propagate();
 9074            return;
 9075        }
 9076
 9077        let text_layout_details = &self.text_layout_details(window);
 9078
 9079        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9080            let line_mode = s.line_mode;
 9081            s.move_with(|map, selection| {
 9082                if !selection.is_empty() && !line_mode {
 9083                    selection.goal = SelectionGoal::None;
 9084                }
 9085                let (cursor, goal) = movement::up_by_rows(
 9086                    map,
 9087                    selection.start,
 9088                    action.lines,
 9089                    selection.goal,
 9090                    false,
 9091                    text_layout_details,
 9092                );
 9093                selection.collapse_to(cursor, goal);
 9094            });
 9095        })
 9096    }
 9097
 9098    pub fn move_down_by_lines(
 9099        &mut self,
 9100        action: &MoveDownByLines,
 9101        window: &mut Window,
 9102        cx: &mut Context<Self>,
 9103    ) {
 9104        if self.take_rename(true, window, cx).is_some() {
 9105            return;
 9106        }
 9107
 9108        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 9109            cx.propagate();
 9110            return;
 9111        }
 9112
 9113        let text_layout_details = &self.text_layout_details(window);
 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::down_by_rows(
 9122                    map,
 9123                    selection.start,
 9124                    action.lines,
 9125                    selection.goal,
 9126                    false,
 9127                    text_layout_details,
 9128                );
 9129                selection.collapse_to(cursor, goal);
 9130            });
 9131        })
 9132    }
 9133
 9134    pub fn select_down_by_lines(
 9135        &mut self,
 9136        action: &SelectDownByLines,
 9137        window: &mut Window,
 9138        cx: &mut Context<Self>,
 9139    ) {
 9140        let text_layout_details = &self.text_layout_details(window);
 9141        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9142            s.move_heads_with(|map, head, goal| {
 9143                movement::down_by_rows(map, head, action.lines, goal, false, text_layout_details)
 9144            })
 9145        })
 9146    }
 9147
 9148    pub fn select_up_by_lines(
 9149        &mut self,
 9150        action: &SelectUpByLines,
 9151        window: &mut Window,
 9152        cx: &mut Context<Self>,
 9153    ) {
 9154        let text_layout_details = &self.text_layout_details(window);
 9155        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9156            s.move_heads_with(|map, head, goal| {
 9157                movement::up_by_rows(map, head, action.lines, goal, false, text_layout_details)
 9158            })
 9159        })
 9160    }
 9161
 9162    pub fn select_page_up(
 9163        &mut self,
 9164        _: &SelectPageUp,
 9165        window: &mut Window,
 9166        cx: &mut Context<Self>,
 9167    ) {
 9168        let Some(row_count) = self.visible_row_count() else {
 9169            return;
 9170        };
 9171
 9172        let text_layout_details = &self.text_layout_details(window);
 9173
 9174        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9175            s.move_heads_with(|map, head, goal| {
 9176                movement::up_by_rows(map, head, row_count, goal, false, text_layout_details)
 9177            })
 9178        })
 9179    }
 9180
 9181    pub fn move_page_up(
 9182        &mut self,
 9183        action: &MovePageUp,
 9184        window: &mut Window,
 9185        cx: &mut Context<Self>,
 9186    ) {
 9187        if self.take_rename(true, window, cx).is_some() {
 9188            return;
 9189        }
 9190
 9191        if self
 9192            .context_menu
 9193            .borrow_mut()
 9194            .as_mut()
 9195            .map(|menu| menu.select_first(self.completion_provider.as_deref(), cx))
 9196            .unwrap_or(false)
 9197        {
 9198            return;
 9199        }
 9200
 9201        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 9202            cx.propagate();
 9203            return;
 9204        }
 9205
 9206        let Some(row_count) = self.visible_row_count() else {
 9207            return;
 9208        };
 9209
 9210        let autoscroll = if action.center_cursor {
 9211            Autoscroll::center()
 9212        } else {
 9213            Autoscroll::fit()
 9214        };
 9215
 9216        let text_layout_details = &self.text_layout_details(window);
 9217
 9218        self.change_selections(Some(autoscroll), window, cx, |s| {
 9219            let line_mode = s.line_mode;
 9220            s.move_with(|map, selection| {
 9221                if !selection.is_empty() && !line_mode {
 9222                    selection.goal = SelectionGoal::None;
 9223                }
 9224                let (cursor, goal) = movement::up_by_rows(
 9225                    map,
 9226                    selection.end,
 9227                    row_count,
 9228                    selection.goal,
 9229                    false,
 9230                    text_layout_details,
 9231                );
 9232                selection.collapse_to(cursor, goal);
 9233            });
 9234        });
 9235    }
 9236
 9237    pub fn select_up(&mut self, _: &SelectUp, window: &mut Window, cx: &mut Context<Self>) {
 9238        let text_layout_details = &self.text_layout_details(window);
 9239        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9240            s.move_heads_with(|map, head, goal| {
 9241                movement::up(map, head, goal, false, text_layout_details)
 9242            })
 9243        })
 9244    }
 9245
 9246    pub fn move_down(&mut self, _: &MoveDown, window: &mut Window, cx: &mut Context<Self>) {
 9247        self.take_rename(true, window, cx);
 9248
 9249        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 9250            cx.propagate();
 9251            return;
 9252        }
 9253
 9254        let text_layout_details = &self.text_layout_details(window);
 9255        let selection_count = self.selections.count();
 9256        let first_selection = self.selections.first_anchor();
 9257
 9258        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9259            let line_mode = s.line_mode;
 9260            s.move_with(|map, selection| {
 9261                if !selection.is_empty() && !line_mode {
 9262                    selection.goal = SelectionGoal::None;
 9263                }
 9264                let (cursor, goal) = movement::down(
 9265                    map,
 9266                    selection.end,
 9267                    selection.goal,
 9268                    false,
 9269                    text_layout_details,
 9270                );
 9271                selection.collapse_to(cursor, goal);
 9272            });
 9273        });
 9274
 9275        if selection_count == 1 && first_selection.range() == self.selections.first_anchor().range()
 9276        {
 9277            cx.propagate();
 9278        }
 9279    }
 9280
 9281    pub fn select_page_down(
 9282        &mut self,
 9283        _: &SelectPageDown,
 9284        window: &mut Window,
 9285        cx: &mut Context<Self>,
 9286    ) {
 9287        let Some(row_count) = self.visible_row_count() else {
 9288            return;
 9289        };
 9290
 9291        let text_layout_details = &self.text_layout_details(window);
 9292
 9293        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9294            s.move_heads_with(|map, head, goal| {
 9295                movement::down_by_rows(map, head, row_count, goal, false, text_layout_details)
 9296            })
 9297        })
 9298    }
 9299
 9300    pub fn move_page_down(
 9301        &mut self,
 9302        action: &MovePageDown,
 9303        window: &mut Window,
 9304        cx: &mut Context<Self>,
 9305    ) {
 9306        if self.take_rename(true, window, cx).is_some() {
 9307            return;
 9308        }
 9309
 9310        if self
 9311            .context_menu
 9312            .borrow_mut()
 9313            .as_mut()
 9314            .map(|menu| menu.select_last(self.completion_provider.as_deref(), cx))
 9315            .unwrap_or(false)
 9316        {
 9317            return;
 9318        }
 9319
 9320        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 9321            cx.propagate();
 9322            return;
 9323        }
 9324
 9325        let Some(row_count) = self.visible_row_count() else {
 9326            return;
 9327        };
 9328
 9329        let autoscroll = if action.center_cursor {
 9330            Autoscroll::center()
 9331        } else {
 9332            Autoscroll::fit()
 9333        };
 9334
 9335        let text_layout_details = &self.text_layout_details(window);
 9336        self.change_selections(Some(autoscroll), window, cx, |s| {
 9337            let line_mode = s.line_mode;
 9338            s.move_with(|map, selection| {
 9339                if !selection.is_empty() && !line_mode {
 9340                    selection.goal = SelectionGoal::None;
 9341                }
 9342                let (cursor, goal) = movement::down_by_rows(
 9343                    map,
 9344                    selection.end,
 9345                    row_count,
 9346                    selection.goal,
 9347                    false,
 9348                    text_layout_details,
 9349                );
 9350                selection.collapse_to(cursor, goal);
 9351            });
 9352        });
 9353    }
 9354
 9355    pub fn select_down(&mut self, _: &SelectDown, window: &mut Window, cx: &mut Context<Self>) {
 9356        let text_layout_details = &self.text_layout_details(window);
 9357        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9358            s.move_heads_with(|map, head, goal| {
 9359                movement::down(map, head, goal, false, text_layout_details)
 9360            })
 9361        });
 9362    }
 9363
 9364    pub fn context_menu_first(
 9365        &mut self,
 9366        _: &ContextMenuFirst,
 9367        _window: &mut Window,
 9368        cx: &mut Context<Self>,
 9369    ) {
 9370        if let Some(context_menu) = self.context_menu.borrow_mut().as_mut() {
 9371            context_menu.select_first(self.completion_provider.as_deref(), cx);
 9372        }
 9373    }
 9374
 9375    pub fn context_menu_prev(
 9376        &mut self,
 9377        _: &ContextMenuPrevious,
 9378        _window: &mut Window,
 9379        cx: &mut Context<Self>,
 9380    ) {
 9381        if let Some(context_menu) = self.context_menu.borrow_mut().as_mut() {
 9382            context_menu.select_prev(self.completion_provider.as_deref(), cx);
 9383        }
 9384    }
 9385
 9386    pub fn context_menu_next(
 9387        &mut self,
 9388        _: &ContextMenuNext,
 9389        _window: &mut Window,
 9390        cx: &mut Context<Self>,
 9391    ) {
 9392        if let Some(context_menu) = self.context_menu.borrow_mut().as_mut() {
 9393            context_menu.select_next(self.completion_provider.as_deref(), cx);
 9394        }
 9395    }
 9396
 9397    pub fn context_menu_last(
 9398        &mut self,
 9399        _: &ContextMenuLast,
 9400        _window: &mut Window,
 9401        cx: &mut Context<Self>,
 9402    ) {
 9403        if let Some(context_menu) = self.context_menu.borrow_mut().as_mut() {
 9404            context_menu.select_last(self.completion_provider.as_deref(), cx);
 9405        }
 9406    }
 9407
 9408    pub fn move_to_previous_word_start(
 9409        &mut self,
 9410        _: &MoveToPreviousWordStart,
 9411        window: &mut Window,
 9412        cx: &mut Context<Self>,
 9413    ) {
 9414        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9415            s.move_cursors_with(|map, head, _| {
 9416                (
 9417                    movement::previous_word_start(map, head),
 9418                    SelectionGoal::None,
 9419                )
 9420            });
 9421        })
 9422    }
 9423
 9424    pub fn move_to_previous_subword_start(
 9425        &mut self,
 9426        _: &MoveToPreviousSubwordStart,
 9427        window: &mut Window,
 9428        cx: &mut Context<Self>,
 9429    ) {
 9430        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9431            s.move_cursors_with(|map, head, _| {
 9432                (
 9433                    movement::previous_subword_start(map, head),
 9434                    SelectionGoal::None,
 9435                )
 9436            });
 9437        })
 9438    }
 9439
 9440    pub fn select_to_previous_word_start(
 9441        &mut self,
 9442        _: &SelectToPreviousWordStart,
 9443        window: &mut Window,
 9444        cx: &mut Context<Self>,
 9445    ) {
 9446        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9447            s.move_heads_with(|map, head, _| {
 9448                (
 9449                    movement::previous_word_start(map, head),
 9450                    SelectionGoal::None,
 9451                )
 9452            });
 9453        })
 9454    }
 9455
 9456    pub fn select_to_previous_subword_start(
 9457        &mut self,
 9458        _: &SelectToPreviousSubwordStart,
 9459        window: &mut Window,
 9460        cx: &mut Context<Self>,
 9461    ) {
 9462        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9463            s.move_heads_with(|map, head, _| {
 9464                (
 9465                    movement::previous_subword_start(map, head),
 9466                    SelectionGoal::None,
 9467                )
 9468            });
 9469        })
 9470    }
 9471
 9472    pub fn delete_to_previous_word_start(
 9473        &mut self,
 9474        action: &DeleteToPreviousWordStart,
 9475        window: &mut Window,
 9476        cx: &mut Context<Self>,
 9477    ) {
 9478        self.transact(window, cx, |this, window, cx| {
 9479            this.select_autoclose_pair(window, cx);
 9480            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9481                let line_mode = s.line_mode;
 9482                s.move_with(|map, selection| {
 9483                    if selection.is_empty() && !line_mode {
 9484                        let cursor = if action.ignore_newlines {
 9485                            movement::previous_word_start(map, selection.head())
 9486                        } else {
 9487                            movement::previous_word_start_or_newline(map, selection.head())
 9488                        };
 9489                        selection.set_head(cursor, SelectionGoal::None);
 9490                    }
 9491                });
 9492            });
 9493            this.insert("", window, cx);
 9494        });
 9495    }
 9496
 9497    pub fn delete_to_previous_subword_start(
 9498        &mut self,
 9499        _: &DeleteToPreviousSubwordStart,
 9500        window: &mut Window,
 9501        cx: &mut Context<Self>,
 9502    ) {
 9503        self.transact(window, cx, |this, window, cx| {
 9504            this.select_autoclose_pair(window, cx);
 9505            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9506                let line_mode = s.line_mode;
 9507                s.move_with(|map, selection| {
 9508                    if selection.is_empty() && !line_mode {
 9509                        let cursor = movement::previous_subword_start(map, selection.head());
 9510                        selection.set_head(cursor, SelectionGoal::None);
 9511                    }
 9512                });
 9513            });
 9514            this.insert("", window, cx);
 9515        });
 9516    }
 9517
 9518    pub fn move_to_next_word_end(
 9519        &mut self,
 9520        _: &MoveToNextWordEnd,
 9521        window: &mut Window,
 9522        cx: &mut Context<Self>,
 9523    ) {
 9524        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9525            s.move_cursors_with(|map, head, _| {
 9526                (movement::next_word_end(map, head), SelectionGoal::None)
 9527            });
 9528        })
 9529    }
 9530
 9531    pub fn move_to_next_subword_end(
 9532        &mut self,
 9533        _: &MoveToNextSubwordEnd,
 9534        window: &mut Window,
 9535        cx: &mut Context<Self>,
 9536    ) {
 9537        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9538            s.move_cursors_with(|map, head, _| {
 9539                (movement::next_subword_end(map, head), SelectionGoal::None)
 9540            });
 9541        })
 9542    }
 9543
 9544    pub fn select_to_next_word_end(
 9545        &mut self,
 9546        _: &SelectToNextWordEnd,
 9547        window: &mut Window,
 9548        cx: &mut Context<Self>,
 9549    ) {
 9550        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9551            s.move_heads_with(|map, head, _| {
 9552                (movement::next_word_end(map, head), SelectionGoal::None)
 9553            });
 9554        })
 9555    }
 9556
 9557    pub fn select_to_next_subword_end(
 9558        &mut self,
 9559        _: &SelectToNextSubwordEnd,
 9560        window: &mut Window,
 9561        cx: &mut Context<Self>,
 9562    ) {
 9563        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9564            s.move_heads_with(|map, head, _| {
 9565                (movement::next_subword_end(map, head), SelectionGoal::None)
 9566            });
 9567        })
 9568    }
 9569
 9570    pub fn delete_to_next_word_end(
 9571        &mut self,
 9572        action: &DeleteToNextWordEnd,
 9573        window: &mut Window,
 9574        cx: &mut Context<Self>,
 9575    ) {
 9576        self.transact(window, cx, |this, window, cx| {
 9577            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9578                let line_mode = s.line_mode;
 9579                s.move_with(|map, selection| {
 9580                    if selection.is_empty() && !line_mode {
 9581                        let cursor = if action.ignore_newlines {
 9582                            movement::next_word_end(map, selection.head())
 9583                        } else {
 9584                            movement::next_word_end_or_newline(map, selection.head())
 9585                        };
 9586                        selection.set_head(cursor, SelectionGoal::None);
 9587                    }
 9588                });
 9589            });
 9590            this.insert("", window, cx);
 9591        });
 9592    }
 9593
 9594    pub fn delete_to_next_subword_end(
 9595        &mut self,
 9596        _: &DeleteToNextSubwordEnd,
 9597        window: &mut Window,
 9598        cx: &mut Context<Self>,
 9599    ) {
 9600        self.transact(window, cx, |this, window, cx| {
 9601            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9602                s.move_with(|map, selection| {
 9603                    if selection.is_empty() {
 9604                        let cursor = movement::next_subword_end(map, selection.head());
 9605                        selection.set_head(cursor, SelectionGoal::None);
 9606                    }
 9607                });
 9608            });
 9609            this.insert("", window, cx);
 9610        });
 9611    }
 9612
 9613    pub fn move_to_beginning_of_line(
 9614        &mut self,
 9615        action: &MoveToBeginningOfLine,
 9616        window: &mut Window,
 9617        cx: &mut Context<Self>,
 9618    ) {
 9619        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9620            s.move_cursors_with(|map, head, _| {
 9621                (
 9622                    movement::indented_line_beginning(
 9623                        map,
 9624                        head,
 9625                        action.stop_at_soft_wraps,
 9626                        action.stop_at_indent,
 9627                    ),
 9628                    SelectionGoal::None,
 9629                )
 9630            });
 9631        })
 9632    }
 9633
 9634    pub fn select_to_beginning_of_line(
 9635        &mut self,
 9636        action: &SelectToBeginningOfLine,
 9637        window: &mut Window,
 9638        cx: &mut Context<Self>,
 9639    ) {
 9640        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9641            s.move_heads_with(|map, head, _| {
 9642                (
 9643                    movement::indented_line_beginning(
 9644                        map,
 9645                        head,
 9646                        action.stop_at_soft_wraps,
 9647                        action.stop_at_indent,
 9648                    ),
 9649                    SelectionGoal::None,
 9650                )
 9651            });
 9652        });
 9653    }
 9654
 9655    pub fn delete_to_beginning_of_line(
 9656        &mut self,
 9657        action: &DeleteToBeginningOfLine,
 9658        window: &mut Window,
 9659        cx: &mut Context<Self>,
 9660    ) {
 9661        self.transact(window, cx, |this, window, cx| {
 9662            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9663                s.move_with(|_, selection| {
 9664                    selection.reversed = true;
 9665                });
 9666            });
 9667
 9668            this.select_to_beginning_of_line(
 9669                &SelectToBeginningOfLine {
 9670                    stop_at_soft_wraps: false,
 9671                    stop_at_indent: action.stop_at_indent,
 9672                },
 9673                window,
 9674                cx,
 9675            );
 9676            this.backspace(&Backspace, window, cx);
 9677        });
 9678    }
 9679
 9680    pub fn move_to_end_of_line(
 9681        &mut self,
 9682        action: &MoveToEndOfLine,
 9683        window: &mut Window,
 9684        cx: &mut Context<Self>,
 9685    ) {
 9686        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9687            s.move_cursors_with(|map, head, _| {
 9688                (
 9689                    movement::line_end(map, head, action.stop_at_soft_wraps),
 9690                    SelectionGoal::None,
 9691                )
 9692            });
 9693        })
 9694    }
 9695
 9696    pub fn select_to_end_of_line(
 9697        &mut self,
 9698        action: &SelectToEndOfLine,
 9699        window: &mut Window,
 9700        cx: &mut Context<Self>,
 9701    ) {
 9702        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9703            s.move_heads_with(|map, head, _| {
 9704                (
 9705                    movement::line_end(map, head, action.stop_at_soft_wraps),
 9706                    SelectionGoal::None,
 9707                )
 9708            });
 9709        })
 9710    }
 9711
 9712    pub fn delete_to_end_of_line(
 9713        &mut self,
 9714        _: &DeleteToEndOfLine,
 9715        window: &mut Window,
 9716        cx: &mut Context<Self>,
 9717    ) {
 9718        self.transact(window, cx, |this, window, cx| {
 9719            this.select_to_end_of_line(
 9720                &SelectToEndOfLine {
 9721                    stop_at_soft_wraps: false,
 9722                },
 9723                window,
 9724                cx,
 9725            );
 9726            this.delete(&Delete, window, cx);
 9727        });
 9728    }
 9729
 9730    pub fn cut_to_end_of_line(
 9731        &mut self,
 9732        _: &CutToEndOfLine,
 9733        window: &mut Window,
 9734        cx: &mut Context<Self>,
 9735    ) {
 9736        self.transact(window, cx, |this, window, cx| {
 9737            this.select_to_end_of_line(
 9738                &SelectToEndOfLine {
 9739                    stop_at_soft_wraps: false,
 9740                },
 9741                window,
 9742                cx,
 9743            );
 9744            this.cut(&Cut, window, cx);
 9745        });
 9746    }
 9747
 9748    pub fn move_to_start_of_paragraph(
 9749        &mut self,
 9750        _: &MoveToStartOfParagraph,
 9751        window: &mut Window,
 9752        cx: &mut Context<Self>,
 9753    ) {
 9754        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 9755            cx.propagate();
 9756            return;
 9757        }
 9758
 9759        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9760            s.move_with(|map, selection| {
 9761                selection.collapse_to(
 9762                    movement::start_of_paragraph(map, selection.head(), 1),
 9763                    SelectionGoal::None,
 9764                )
 9765            });
 9766        })
 9767    }
 9768
 9769    pub fn move_to_end_of_paragraph(
 9770        &mut self,
 9771        _: &MoveToEndOfParagraph,
 9772        window: &mut Window,
 9773        cx: &mut Context<Self>,
 9774    ) {
 9775        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 9776            cx.propagate();
 9777            return;
 9778        }
 9779
 9780        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9781            s.move_with(|map, selection| {
 9782                selection.collapse_to(
 9783                    movement::end_of_paragraph(map, selection.head(), 1),
 9784                    SelectionGoal::None,
 9785                )
 9786            });
 9787        })
 9788    }
 9789
 9790    pub fn select_to_start_of_paragraph(
 9791        &mut self,
 9792        _: &SelectToStartOfParagraph,
 9793        window: &mut Window,
 9794        cx: &mut Context<Self>,
 9795    ) {
 9796        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 9797            cx.propagate();
 9798            return;
 9799        }
 9800
 9801        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9802            s.move_heads_with(|map, head, _| {
 9803                (
 9804                    movement::start_of_paragraph(map, head, 1),
 9805                    SelectionGoal::None,
 9806                )
 9807            });
 9808        })
 9809    }
 9810
 9811    pub fn select_to_end_of_paragraph(
 9812        &mut self,
 9813        _: &SelectToEndOfParagraph,
 9814        window: &mut Window,
 9815        cx: &mut Context<Self>,
 9816    ) {
 9817        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 9818            cx.propagate();
 9819            return;
 9820        }
 9821
 9822        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9823            s.move_heads_with(|map, head, _| {
 9824                (
 9825                    movement::end_of_paragraph(map, head, 1),
 9826                    SelectionGoal::None,
 9827                )
 9828            });
 9829        })
 9830    }
 9831
 9832    pub fn move_to_start_of_excerpt(
 9833        &mut self,
 9834        _: &MoveToStartOfExcerpt,
 9835        window: &mut Window,
 9836        cx: &mut Context<Self>,
 9837    ) {
 9838        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 9839            cx.propagate();
 9840            return;
 9841        }
 9842
 9843        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9844            s.move_with(|map, selection| {
 9845                selection.collapse_to(
 9846                    movement::start_of_excerpt(
 9847                        map,
 9848                        selection.head(),
 9849                        workspace::searchable::Direction::Prev,
 9850                    ),
 9851                    SelectionGoal::None,
 9852                )
 9853            });
 9854        })
 9855    }
 9856
 9857    pub fn move_to_start_of_next_excerpt(
 9858        &mut self,
 9859        _: &MoveToStartOfNextExcerpt,
 9860        window: &mut Window,
 9861        cx: &mut Context<Self>,
 9862    ) {
 9863        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 9864            cx.propagate();
 9865            return;
 9866        }
 9867
 9868        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9869            s.move_with(|map, selection| {
 9870                selection.collapse_to(
 9871                    movement::start_of_excerpt(
 9872                        map,
 9873                        selection.head(),
 9874                        workspace::searchable::Direction::Next,
 9875                    ),
 9876                    SelectionGoal::None,
 9877                )
 9878            });
 9879        })
 9880    }
 9881
 9882    pub fn move_to_end_of_excerpt(
 9883        &mut self,
 9884        _: &MoveToEndOfExcerpt,
 9885        window: &mut Window,
 9886        cx: &mut Context<Self>,
 9887    ) {
 9888        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 9889            cx.propagate();
 9890            return;
 9891        }
 9892
 9893        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9894            s.move_with(|map, selection| {
 9895                selection.collapse_to(
 9896                    movement::end_of_excerpt(
 9897                        map,
 9898                        selection.head(),
 9899                        workspace::searchable::Direction::Next,
 9900                    ),
 9901                    SelectionGoal::None,
 9902                )
 9903            });
 9904        })
 9905    }
 9906
 9907    pub fn move_to_end_of_previous_excerpt(
 9908        &mut self,
 9909        _: &MoveToEndOfPreviousExcerpt,
 9910        window: &mut Window,
 9911        cx: &mut Context<Self>,
 9912    ) {
 9913        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 9914            cx.propagate();
 9915            return;
 9916        }
 9917
 9918        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9919            s.move_with(|map, selection| {
 9920                selection.collapse_to(
 9921                    movement::end_of_excerpt(
 9922                        map,
 9923                        selection.head(),
 9924                        workspace::searchable::Direction::Prev,
 9925                    ),
 9926                    SelectionGoal::None,
 9927                )
 9928            });
 9929        })
 9930    }
 9931
 9932    pub fn select_to_start_of_excerpt(
 9933        &mut self,
 9934        _: &SelectToStartOfExcerpt,
 9935        window: &mut Window,
 9936        cx: &mut Context<Self>,
 9937    ) {
 9938        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 9939            cx.propagate();
 9940            return;
 9941        }
 9942
 9943        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9944            s.move_heads_with(|map, head, _| {
 9945                (
 9946                    movement::start_of_excerpt(map, head, workspace::searchable::Direction::Prev),
 9947                    SelectionGoal::None,
 9948                )
 9949            });
 9950        })
 9951    }
 9952
 9953    pub fn select_to_start_of_next_excerpt(
 9954        &mut self,
 9955        _: &SelectToStartOfNextExcerpt,
 9956        window: &mut Window,
 9957        cx: &mut Context<Self>,
 9958    ) {
 9959        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 9960            cx.propagate();
 9961            return;
 9962        }
 9963
 9964        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9965            s.move_heads_with(|map, head, _| {
 9966                (
 9967                    movement::start_of_excerpt(map, head, workspace::searchable::Direction::Next),
 9968                    SelectionGoal::None,
 9969                )
 9970            });
 9971        })
 9972    }
 9973
 9974    pub fn select_to_end_of_excerpt(
 9975        &mut self,
 9976        _: &SelectToEndOfExcerpt,
 9977        window: &mut Window,
 9978        cx: &mut Context<Self>,
 9979    ) {
 9980        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 9981            cx.propagate();
 9982            return;
 9983        }
 9984
 9985        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9986            s.move_heads_with(|map, head, _| {
 9987                (
 9988                    movement::end_of_excerpt(map, head, workspace::searchable::Direction::Next),
 9989                    SelectionGoal::None,
 9990                )
 9991            });
 9992        })
 9993    }
 9994
 9995    pub fn select_to_end_of_previous_excerpt(
 9996        &mut self,
 9997        _: &SelectToEndOfPreviousExcerpt,
 9998        window: &mut Window,
 9999        cx: &mut Context<Self>,
10000    ) {
10001        if matches!(self.mode, EditorMode::SingleLine { .. }) {
10002            cx.propagate();
10003            return;
10004        }
10005
10006        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10007            s.move_heads_with(|map, head, _| {
10008                (
10009                    movement::end_of_excerpt(map, head, workspace::searchable::Direction::Prev),
10010                    SelectionGoal::None,
10011                )
10012            });
10013        })
10014    }
10015
10016    pub fn move_to_beginning(
10017        &mut self,
10018        _: &MoveToBeginning,
10019        window: &mut Window,
10020        cx: &mut Context<Self>,
10021    ) {
10022        if matches!(self.mode, EditorMode::SingleLine { .. }) {
10023            cx.propagate();
10024            return;
10025        }
10026
10027        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10028            s.select_ranges(vec![0..0]);
10029        });
10030    }
10031
10032    pub fn select_to_beginning(
10033        &mut self,
10034        _: &SelectToBeginning,
10035        window: &mut Window,
10036        cx: &mut Context<Self>,
10037    ) {
10038        let mut selection = self.selections.last::<Point>(cx);
10039        selection.set_head(Point::zero(), SelectionGoal::None);
10040
10041        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10042            s.select(vec![selection]);
10043        });
10044    }
10045
10046    pub fn move_to_end(&mut self, _: &MoveToEnd, window: &mut Window, cx: &mut Context<Self>) {
10047        if matches!(self.mode, EditorMode::SingleLine { .. }) {
10048            cx.propagate();
10049            return;
10050        }
10051
10052        let cursor = self.buffer.read(cx).read(cx).len();
10053        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10054            s.select_ranges(vec![cursor..cursor])
10055        });
10056    }
10057
10058    pub fn set_nav_history(&mut self, nav_history: Option<ItemNavHistory>) {
10059        self.nav_history = nav_history;
10060    }
10061
10062    pub fn nav_history(&self) -> Option<&ItemNavHistory> {
10063        self.nav_history.as_ref()
10064    }
10065
10066    fn push_to_nav_history(
10067        &mut self,
10068        cursor_anchor: Anchor,
10069        new_position: Option<Point>,
10070        cx: &mut Context<Self>,
10071    ) {
10072        if let Some(nav_history) = self.nav_history.as_mut() {
10073            let buffer = self.buffer.read(cx).read(cx);
10074            let cursor_position = cursor_anchor.to_point(&buffer);
10075            let scroll_state = self.scroll_manager.anchor();
10076            let scroll_top_row = scroll_state.top_row(&buffer);
10077            drop(buffer);
10078
10079            if let Some(new_position) = new_position {
10080                let row_delta = (new_position.row as i64 - cursor_position.row as i64).abs();
10081                if row_delta < MIN_NAVIGATION_HISTORY_ROW_DELTA {
10082                    return;
10083                }
10084            }
10085
10086            nav_history.push(
10087                Some(NavigationData {
10088                    cursor_anchor,
10089                    cursor_position,
10090                    scroll_anchor: scroll_state,
10091                    scroll_top_row,
10092                }),
10093                cx,
10094            );
10095        }
10096    }
10097
10098    pub fn select_to_end(&mut self, _: &SelectToEnd, window: &mut Window, cx: &mut Context<Self>) {
10099        let buffer = self.buffer.read(cx).snapshot(cx);
10100        let mut selection = self.selections.first::<usize>(cx);
10101        selection.set_head(buffer.len(), SelectionGoal::None);
10102        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10103            s.select(vec![selection]);
10104        });
10105    }
10106
10107    pub fn select_all(&mut self, _: &SelectAll, window: &mut Window, cx: &mut Context<Self>) {
10108        let end = self.buffer.read(cx).read(cx).len();
10109        self.change_selections(None, window, cx, |s| {
10110            s.select_ranges(vec![0..end]);
10111        });
10112    }
10113
10114    pub fn select_line(&mut self, _: &SelectLine, window: &mut Window, cx: &mut Context<Self>) {
10115        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
10116        let mut selections = self.selections.all::<Point>(cx);
10117        let max_point = display_map.buffer_snapshot.max_point();
10118        for selection in &mut selections {
10119            let rows = selection.spanned_rows(true, &display_map);
10120            selection.start = Point::new(rows.start.0, 0);
10121            selection.end = cmp::min(max_point, Point::new(rows.end.0, 0));
10122            selection.reversed = false;
10123        }
10124        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10125            s.select(selections);
10126        });
10127    }
10128
10129    pub fn split_selection_into_lines(
10130        &mut self,
10131        _: &SplitSelectionIntoLines,
10132        window: &mut Window,
10133        cx: &mut Context<Self>,
10134    ) {
10135        let selections = self
10136            .selections
10137            .all::<Point>(cx)
10138            .into_iter()
10139            .map(|selection| selection.start..selection.end)
10140            .collect::<Vec<_>>();
10141        self.unfold_ranges(&selections, true, true, cx);
10142
10143        let mut new_selection_ranges = Vec::new();
10144        {
10145            let buffer = self.buffer.read(cx).read(cx);
10146            for selection in selections {
10147                for row in selection.start.row..selection.end.row {
10148                    let cursor = Point::new(row, buffer.line_len(MultiBufferRow(row)));
10149                    new_selection_ranges.push(cursor..cursor);
10150                }
10151
10152                let is_multiline_selection = selection.start.row != selection.end.row;
10153                // Don't insert last one if it's a multi-line selection ending at the start of a line,
10154                // so this action feels more ergonomic when paired with other selection operations
10155                let should_skip_last = is_multiline_selection && selection.end.column == 0;
10156                if !should_skip_last {
10157                    new_selection_ranges.push(selection.end..selection.end);
10158                }
10159            }
10160        }
10161        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10162            s.select_ranges(new_selection_ranges);
10163        });
10164    }
10165
10166    pub fn add_selection_above(
10167        &mut self,
10168        _: &AddSelectionAbove,
10169        window: &mut Window,
10170        cx: &mut Context<Self>,
10171    ) {
10172        self.add_selection(true, window, cx);
10173    }
10174
10175    pub fn add_selection_below(
10176        &mut self,
10177        _: &AddSelectionBelow,
10178        window: &mut Window,
10179        cx: &mut Context<Self>,
10180    ) {
10181        self.add_selection(false, window, cx);
10182    }
10183
10184    fn add_selection(&mut self, above: bool, window: &mut Window, cx: &mut Context<Self>) {
10185        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
10186        let mut selections = self.selections.all::<Point>(cx);
10187        let text_layout_details = self.text_layout_details(window);
10188        let mut state = self.add_selections_state.take().unwrap_or_else(|| {
10189            let oldest_selection = selections.iter().min_by_key(|s| s.id).unwrap().clone();
10190            let range = oldest_selection.display_range(&display_map).sorted();
10191
10192            let start_x = display_map.x_for_display_point(range.start, &text_layout_details);
10193            let end_x = display_map.x_for_display_point(range.end, &text_layout_details);
10194            let positions = start_x.min(end_x)..start_x.max(end_x);
10195
10196            selections.clear();
10197            let mut stack = Vec::new();
10198            for row in range.start.row().0..=range.end.row().0 {
10199                if let Some(selection) = self.selections.build_columnar_selection(
10200                    &display_map,
10201                    DisplayRow(row),
10202                    &positions,
10203                    oldest_selection.reversed,
10204                    &text_layout_details,
10205                ) {
10206                    stack.push(selection.id);
10207                    selections.push(selection);
10208                }
10209            }
10210
10211            if above {
10212                stack.reverse();
10213            }
10214
10215            AddSelectionsState { above, stack }
10216        });
10217
10218        let last_added_selection = *state.stack.last().unwrap();
10219        let mut new_selections = Vec::new();
10220        if above == state.above {
10221            let end_row = if above {
10222                DisplayRow(0)
10223            } else {
10224                display_map.max_point().row()
10225            };
10226
10227            'outer: for selection in selections {
10228                if selection.id == last_added_selection {
10229                    let range = selection.display_range(&display_map).sorted();
10230                    debug_assert_eq!(range.start.row(), range.end.row());
10231                    let mut row = range.start.row();
10232                    let positions =
10233                        if let SelectionGoal::HorizontalRange { start, end } = selection.goal {
10234                            px(start)..px(end)
10235                        } else {
10236                            let start_x =
10237                                display_map.x_for_display_point(range.start, &text_layout_details);
10238                            let end_x =
10239                                display_map.x_for_display_point(range.end, &text_layout_details);
10240                            start_x.min(end_x)..start_x.max(end_x)
10241                        };
10242
10243                    while row != end_row {
10244                        if above {
10245                            row.0 -= 1;
10246                        } else {
10247                            row.0 += 1;
10248                        }
10249
10250                        if let Some(new_selection) = self.selections.build_columnar_selection(
10251                            &display_map,
10252                            row,
10253                            &positions,
10254                            selection.reversed,
10255                            &text_layout_details,
10256                        ) {
10257                            state.stack.push(new_selection.id);
10258                            if above {
10259                                new_selections.push(new_selection);
10260                                new_selections.push(selection);
10261                            } else {
10262                                new_selections.push(selection);
10263                                new_selections.push(new_selection);
10264                            }
10265
10266                            continue 'outer;
10267                        }
10268                    }
10269                }
10270
10271                new_selections.push(selection);
10272            }
10273        } else {
10274            new_selections = selections;
10275            new_selections.retain(|s| s.id != last_added_selection);
10276            state.stack.pop();
10277        }
10278
10279        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10280            s.select(new_selections);
10281        });
10282        if state.stack.len() > 1 {
10283            self.add_selections_state = Some(state);
10284        }
10285    }
10286
10287    pub fn select_next_match_internal(
10288        &mut self,
10289        display_map: &DisplaySnapshot,
10290        replace_newest: bool,
10291        autoscroll: Option<Autoscroll>,
10292        window: &mut Window,
10293        cx: &mut Context<Self>,
10294    ) -> Result<()> {
10295        fn select_next_match_ranges(
10296            this: &mut Editor,
10297            range: Range<usize>,
10298            replace_newest: bool,
10299            auto_scroll: Option<Autoscroll>,
10300            window: &mut Window,
10301            cx: &mut Context<Editor>,
10302        ) {
10303            this.unfold_ranges(&[range.clone()], false, true, cx);
10304            this.change_selections(auto_scroll, window, cx, |s| {
10305                if replace_newest {
10306                    s.delete(s.newest_anchor().id);
10307                }
10308                s.insert_range(range.clone());
10309            });
10310        }
10311
10312        let buffer = &display_map.buffer_snapshot;
10313        let mut selections = self.selections.all::<usize>(cx);
10314        if let Some(mut select_next_state) = self.select_next_state.take() {
10315            let query = &select_next_state.query;
10316            if !select_next_state.done {
10317                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
10318                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
10319                let mut next_selected_range = None;
10320
10321                let bytes_after_last_selection =
10322                    buffer.bytes_in_range(last_selection.end..buffer.len());
10323                let bytes_before_first_selection = buffer.bytes_in_range(0..first_selection.start);
10324                let query_matches = query
10325                    .stream_find_iter(bytes_after_last_selection)
10326                    .map(|result| (last_selection.end, result))
10327                    .chain(
10328                        query
10329                            .stream_find_iter(bytes_before_first_selection)
10330                            .map(|result| (0, result)),
10331                    );
10332
10333                for (start_offset, query_match) in query_matches {
10334                    let query_match = query_match.unwrap(); // can only fail due to I/O
10335                    let offset_range =
10336                        start_offset + query_match.start()..start_offset + query_match.end();
10337                    let display_range = offset_range.start.to_display_point(display_map)
10338                        ..offset_range.end.to_display_point(display_map);
10339
10340                    if !select_next_state.wordwise
10341                        || (!movement::is_inside_word(display_map, display_range.start)
10342                            && !movement::is_inside_word(display_map, display_range.end))
10343                    {
10344                        // TODO: This is n^2, because we might check all the selections
10345                        if !selections
10346                            .iter()
10347                            .any(|selection| selection.range().overlaps(&offset_range))
10348                        {
10349                            next_selected_range = Some(offset_range);
10350                            break;
10351                        }
10352                    }
10353                }
10354
10355                if let Some(next_selected_range) = next_selected_range {
10356                    select_next_match_ranges(
10357                        self,
10358                        next_selected_range,
10359                        replace_newest,
10360                        autoscroll,
10361                        window,
10362                        cx,
10363                    );
10364                } else {
10365                    select_next_state.done = true;
10366                }
10367            }
10368
10369            self.select_next_state = Some(select_next_state);
10370        } else {
10371            let mut only_carets = true;
10372            let mut same_text_selected = true;
10373            let mut selected_text = None;
10374
10375            let mut selections_iter = selections.iter().peekable();
10376            while let Some(selection) = selections_iter.next() {
10377                if selection.start != selection.end {
10378                    only_carets = false;
10379                }
10380
10381                if same_text_selected {
10382                    if selected_text.is_none() {
10383                        selected_text =
10384                            Some(buffer.text_for_range(selection.range()).collect::<String>());
10385                    }
10386
10387                    if let Some(next_selection) = selections_iter.peek() {
10388                        if next_selection.range().len() == selection.range().len() {
10389                            let next_selected_text = buffer
10390                                .text_for_range(next_selection.range())
10391                                .collect::<String>();
10392                            if Some(next_selected_text) != selected_text {
10393                                same_text_selected = false;
10394                                selected_text = None;
10395                            }
10396                        } else {
10397                            same_text_selected = false;
10398                            selected_text = None;
10399                        }
10400                    }
10401                }
10402            }
10403
10404            if only_carets {
10405                for selection in &mut selections {
10406                    let word_range = movement::surrounding_word(
10407                        display_map,
10408                        selection.start.to_display_point(display_map),
10409                    );
10410                    selection.start = word_range.start.to_offset(display_map, Bias::Left);
10411                    selection.end = word_range.end.to_offset(display_map, Bias::Left);
10412                    selection.goal = SelectionGoal::None;
10413                    selection.reversed = false;
10414                    select_next_match_ranges(
10415                        self,
10416                        selection.start..selection.end,
10417                        replace_newest,
10418                        autoscroll,
10419                        window,
10420                        cx,
10421                    );
10422                }
10423
10424                if selections.len() == 1 {
10425                    let selection = selections
10426                        .last()
10427                        .expect("ensured that there's only one selection");
10428                    let query = buffer
10429                        .text_for_range(selection.start..selection.end)
10430                        .collect::<String>();
10431                    let is_empty = query.is_empty();
10432                    let select_state = SelectNextState {
10433                        query: AhoCorasick::new(&[query])?,
10434                        wordwise: true,
10435                        done: is_empty,
10436                    };
10437                    self.select_next_state = Some(select_state);
10438                } else {
10439                    self.select_next_state = None;
10440                }
10441            } else if let Some(selected_text) = selected_text {
10442                self.select_next_state = Some(SelectNextState {
10443                    query: AhoCorasick::new(&[selected_text])?,
10444                    wordwise: false,
10445                    done: false,
10446                });
10447                self.select_next_match_internal(
10448                    display_map,
10449                    replace_newest,
10450                    autoscroll,
10451                    window,
10452                    cx,
10453                )?;
10454            }
10455        }
10456        Ok(())
10457    }
10458
10459    pub fn select_all_matches(
10460        &mut self,
10461        _action: &SelectAllMatches,
10462        window: &mut Window,
10463        cx: &mut Context<Self>,
10464    ) -> Result<()> {
10465        self.push_to_selection_history();
10466        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
10467
10468        self.select_next_match_internal(&display_map, false, None, window, cx)?;
10469        let Some(select_next_state) = self.select_next_state.as_mut() else {
10470            return Ok(());
10471        };
10472        if select_next_state.done {
10473            return Ok(());
10474        }
10475
10476        let mut new_selections = self.selections.all::<usize>(cx);
10477
10478        let buffer = &display_map.buffer_snapshot;
10479        let query_matches = select_next_state
10480            .query
10481            .stream_find_iter(buffer.bytes_in_range(0..buffer.len()));
10482
10483        for query_match in query_matches {
10484            let query_match = query_match.unwrap(); // can only fail due to I/O
10485            let offset_range = query_match.start()..query_match.end();
10486            let display_range = offset_range.start.to_display_point(&display_map)
10487                ..offset_range.end.to_display_point(&display_map);
10488
10489            if !select_next_state.wordwise
10490                || (!movement::is_inside_word(&display_map, display_range.start)
10491                    && !movement::is_inside_word(&display_map, display_range.end))
10492            {
10493                self.selections.change_with(cx, |selections| {
10494                    new_selections.push(Selection {
10495                        id: selections.new_selection_id(),
10496                        start: offset_range.start,
10497                        end: offset_range.end,
10498                        reversed: false,
10499                        goal: SelectionGoal::None,
10500                    });
10501                });
10502            }
10503        }
10504
10505        new_selections.sort_by_key(|selection| selection.start);
10506        let mut ix = 0;
10507        while ix + 1 < new_selections.len() {
10508            let current_selection = &new_selections[ix];
10509            let next_selection = &new_selections[ix + 1];
10510            if current_selection.range().overlaps(&next_selection.range()) {
10511                if current_selection.id < next_selection.id {
10512                    new_selections.remove(ix + 1);
10513                } else {
10514                    new_selections.remove(ix);
10515                }
10516            } else {
10517                ix += 1;
10518            }
10519        }
10520
10521        let reversed = self.selections.oldest::<usize>(cx).reversed;
10522
10523        for selection in new_selections.iter_mut() {
10524            selection.reversed = reversed;
10525        }
10526
10527        select_next_state.done = true;
10528        self.unfold_ranges(
10529            &new_selections
10530                .iter()
10531                .map(|selection| selection.range())
10532                .collect::<Vec<_>>(),
10533            false,
10534            false,
10535            cx,
10536        );
10537        self.change_selections(Some(Autoscroll::fit()), window, cx, |selections| {
10538            selections.select(new_selections)
10539        });
10540
10541        Ok(())
10542    }
10543
10544    pub fn select_next(
10545        &mut self,
10546        action: &SelectNext,
10547        window: &mut Window,
10548        cx: &mut Context<Self>,
10549    ) -> Result<()> {
10550        self.push_to_selection_history();
10551        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
10552        self.select_next_match_internal(
10553            &display_map,
10554            action.replace_newest,
10555            Some(Autoscroll::newest()),
10556            window,
10557            cx,
10558        )?;
10559        Ok(())
10560    }
10561
10562    pub fn select_previous(
10563        &mut self,
10564        action: &SelectPrevious,
10565        window: &mut Window,
10566        cx: &mut Context<Self>,
10567    ) -> Result<()> {
10568        self.push_to_selection_history();
10569        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
10570        let buffer = &display_map.buffer_snapshot;
10571        let mut selections = self.selections.all::<usize>(cx);
10572        if let Some(mut select_prev_state) = self.select_prev_state.take() {
10573            let query = &select_prev_state.query;
10574            if !select_prev_state.done {
10575                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
10576                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
10577                let mut next_selected_range = None;
10578                // When we're iterating matches backwards, the oldest match will actually be the furthest one in the buffer.
10579                let bytes_before_last_selection =
10580                    buffer.reversed_bytes_in_range(0..last_selection.start);
10581                let bytes_after_first_selection =
10582                    buffer.reversed_bytes_in_range(first_selection.end..buffer.len());
10583                let query_matches = query
10584                    .stream_find_iter(bytes_before_last_selection)
10585                    .map(|result| (last_selection.start, result))
10586                    .chain(
10587                        query
10588                            .stream_find_iter(bytes_after_first_selection)
10589                            .map(|result| (buffer.len(), result)),
10590                    );
10591                for (end_offset, query_match) in query_matches {
10592                    let query_match = query_match.unwrap(); // can only fail due to I/O
10593                    let offset_range =
10594                        end_offset - query_match.end()..end_offset - query_match.start();
10595                    let display_range = offset_range.start.to_display_point(&display_map)
10596                        ..offset_range.end.to_display_point(&display_map);
10597
10598                    if !select_prev_state.wordwise
10599                        || (!movement::is_inside_word(&display_map, display_range.start)
10600                            && !movement::is_inside_word(&display_map, display_range.end))
10601                    {
10602                        next_selected_range = Some(offset_range);
10603                        break;
10604                    }
10605                }
10606
10607                if let Some(next_selected_range) = next_selected_range {
10608                    self.unfold_ranges(&[next_selected_range.clone()], false, true, cx);
10609                    self.change_selections(Some(Autoscroll::newest()), window, cx, |s| {
10610                        if action.replace_newest {
10611                            s.delete(s.newest_anchor().id);
10612                        }
10613                        s.insert_range(next_selected_range);
10614                    });
10615                } else {
10616                    select_prev_state.done = true;
10617                }
10618            }
10619
10620            self.select_prev_state = Some(select_prev_state);
10621        } else {
10622            let mut only_carets = true;
10623            let mut same_text_selected = true;
10624            let mut selected_text = None;
10625
10626            let mut selections_iter = selections.iter().peekable();
10627            while let Some(selection) = selections_iter.next() {
10628                if selection.start != selection.end {
10629                    only_carets = false;
10630                }
10631
10632                if same_text_selected {
10633                    if selected_text.is_none() {
10634                        selected_text =
10635                            Some(buffer.text_for_range(selection.range()).collect::<String>());
10636                    }
10637
10638                    if let Some(next_selection) = selections_iter.peek() {
10639                        if next_selection.range().len() == selection.range().len() {
10640                            let next_selected_text = buffer
10641                                .text_for_range(next_selection.range())
10642                                .collect::<String>();
10643                            if Some(next_selected_text) != selected_text {
10644                                same_text_selected = false;
10645                                selected_text = None;
10646                            }
10647                        } else {
10648                            same_text_selected = false;
10649                            selected_text = None;
10650                        }
10651                    }
10652                }
10653            }
10654
10655            if only_carets {
10656                for selection in &mut selections {
10657                    let word_range = movement::surrounding_word(
10658                        &display_map,
10659                        selection.start.to_display_point(&display_map),
10660                    );
10661                    selection.start = word_range.start.to_offset(&display_map, Bias::Left);
10662                    selection.end = word_range.end.to_offset(&display_map, Bias::Left);
10663                    selection.goal = SelectionGoal::None;
10664                    selection.reversed = false;
10665                }
10666                if selections.len() == 1 {
10667                    let selection = selections
10668                        .last()
10669                        .expect("ensured that there's only one selection");
10670                    let query = buffer
10671                        .text_for_range(selection.start..selection.end)
10672                        .collect::<String>();
10673                    let is_empty = query.is_empty();
10674                    let select_state = SelectNextState {
10675                        query: AhoCorasick::new(&[query.chars().rev().collect::<String>()])?,
10676                        wordwise: true,
10677                        done: is_empty,
10678                    };
10679                    self.select_prev_state = Some(select_state);
10680                } else {
10681                    self.select_prev_state = None;
10682                }
10683
10684                self.unfold_ranges(
10685                    &selections.iter().map(|s| s.range()).collect::<Vec<_>>(),
10686                    false,
10687                    true,
10688                    cx,
10689                );
10690                self.change_selections(Some(Autoscroll::newest()), window, cx, |s| {
10691                    s.select(selections);
10692                });
10693            } else if let Some(selected_text) = selected_text {
10694                self.select_prev_state = Some(SelectNextState {
10695                    query: AhoCorasick::new(&[selected_text.chars().rev().collect::<String>()])?,
10696                    wordwise: false,
10697                    done: false,
10698                });
10699                self.select_previous(action, window, cx)?;
10700            }
10701        }
10702        Ok(())
10703    }
10704
10705    pub fn toggle_comments(
10706        &mut self,
10707        action: &ToggleComments,
10708        window: &mut Window,
10709        cx: &mut Context<Self>,
10710    ) {
10711        if self.read_only(cx) {
10712            return;
10713        }
10714        let text_layout_details = &self.text_layout_details(window);
10715        self.transact(window, cx, |this, window, cx| {
10716            let mut selections = this.selections.all::<MultiBufferPoint>(cx);
10717            let mut edits = Vec::new();
10718            let mut selection_edit_ranges = Vec::new();
10719            let mut last_toggled_row = None;
10720            let snapshot = this.buffer.read(cx).read(cx);
10721            let empty_str: Arc<str> = Arc::default();
10722            let mut suffixes_inserted = Vec::new();
10723            let ignore_indent = action.ignore_indent;
10724
10725            fn comment_prefix_range(
10726                snapshot: &MultiBufferSnapshot,
10727                row: MultiBufferRow,
10728                comment_prefix: &str,
10729                comment_prefix_whitespace: &str,
10730                ignore_indent: bool,
10731            ) -> Range<Point> {
10732                let indent_size = if ignore_indent {
10733                    0
10734                } else {
10735                    snapshot.indent_size_for_line(row).len
10736                };
10737
10738                let start = Point::new(row.0, indent_size);
10739
10740                let mut line_bytes = snapshot
10741                    .bytes_in_range(start..snapshot.max_point())
10742                    .flatten()
10743                    .copied();
10744
10745                // If this line currently begins with the line comment prefix, then record
10746                // the range containing the prefix.
10747                if line_bytes
10748                    .by_ref()
10749                    .take(comment_prefix.len())
10750                    .eq(comment_prefix.bytes())
10751                {
10752                    // Include any whitespace that matches the comment prefix.
10753                    let matching_whitespace_len = line_bytes
10754                        .zip(comment_prefix_whitespace.bytes())
10755                        .take_while(|(a, b)| a == b)
10756                        .count() as u32;
10757                    let end = Point::new(
10758                        start.row,
10759                        start.column + comment_prefix.len() as u32 + matching_whitespace_len,
10760                    );
10761                    start..end
10762                } else {
10763                    start..start
10764                }
10765            }
10766
10767            fn comment_suffix_range(
10768                snapshot: &MultiBufferSnapshot,
10769                row: MultiBufferRow,
10770                comment_suffix: &str,
10771                comment_suffix_has_leading_space: bool,
10772            ) -> Range<Point> {
10773                let end = Point::new(row.0, snapshot.line_len(row));
10774                let suffix_start_column = end.column.saturating_sub(comment_suffix.len() as u32);
10775
10776                let mut line_end_bytes = snapshot
10777                    .bytes_in_range(Point::new(end.row, suffix_start_column.saturating_sub(1))..end)
10778                    .flatten()
10779                    .copied();
10780
10781                let leading_space_len = if suffix_start_column > 0
10782                    && line_end_bytes.next() == Some(b' ')
10783                    && comment_suffix_has_leading_space
10784                {
10785                    1
10786                } else {
10787                    0
10788                };
10789
10790                // If this line currently begins with the line comment prefix, then record
10791                // the range containing the prefix.
10792                if line_end_bytes.by_ref().eq(comment_suffix.bytes()) {
10793                    let start = Point::new(end.row, suffix_start_column - leading_space_len);
10794                    start..end
10795                } else {
10796                    end..end
10797                }
10798            }
10799
10800            // TODO: Handle selections that cross excerpts
10801            for selection in &mut selections {
10802                let start_column = snapshot
10803                    .indent_size_for_line(MultiBufferRow(selection.start.row))
10804                    .len;
10805                let language = if let Some(language) =
10806                    snapshot.language_scope_at(Point::new(selection.start.row, start_column))
10807                {
10808                    language
10809                } else {
10810                    continue;
10811                };
10812
10813                selection_edit_ranges.clear();
10814
10815                // If multiple selections contain a given row, avoid processing that
10816                // row more than once.
10817                let mut start_row = MultiBufferRow(selection.start.row);
10818                if last_toggled_row == Some(start_row) {
10819                    start_row = start_row.next_row();
10820                }
10821                let end_row =
10822                    if selection.end.row > selection.start.row && selection.end.column == 0 {
10823                        MultiBufferRow(selection.end.row - 1)
10824                    } else {
10825                        MultiBufferRow(selection.end.row)
10826                    };
10827                last_toggled_row = Some(end_row);
10828
10829                if start_row > end_row {
10830                    continue;
10831                }
10832
10833                // If the language has line comments, toggle those.
10834                let mut full_comment_prefixes = language.line_comment_prefixes().to_vec();
10835
10836                // If ignore_indent is set, trim spaces from the right side of all full_comment_prefixes
10837                if ignore_indent {
10838                    full_comment_prefixes = full_comment_prefixes
10839                        .into_iter()
10840                        .map(|s| Arc::from(s.trim_end()))
10841                        .collect();
10842                }
10843
10844                if !full_comment_prefixes.is_empty() {
10845                    let first_prefix = full_comment_prefixes
10846                        .first()
10847                        .expect("prefixes is non-empty");
10848                    let prefix_trimmed_lengths = full_comment_prefixes
10849                        .iter()
10850                        .map(|p| p.trim_end_matches(' ').len())
10851                        .collect::<SmallVec<[usize; 4]>>();
10852
10853                    let mut all_selection_lines_are_comments = true;
10854
10855                    for row in start_row.0..=end_row.0 {
10856                        let row = MultiBufferRow(row);
10857                        if start_row < end_row && snapshot.is_line_blank(row) {
10858                            continue;
10859                        }
10860
10861                        let prefix_range = full_comment_prefixes
10862                            .iter()
10863                            .zip(prefix_trimmed_lengths.iter().copied())
10864                            .map(|(prefix, trimmed_prefix_len)| {
10865                                comment_prefix_range(
10866                                    snapshot.deref(),
10867                                    row,
10868                                    &prefix[..trimmed_prefix_len],
10869                                    &prefix[trimmed_prefix_len..],
10870                                    ignore_indent,
10871                                )
10872                            })
10873                            .max_by_key(|range| range.end.column - range.start.column)
10874                            .expect("prefixes is non-empty");
10875
10876                        if prefix_range.is_empty() {
10877                            all_selection_lines_are_comments = false;
10878                        }
10879
10880                        selection_edit_ranges.push(prefix_range);
10881                    }
10882
10883                    if all_selection_lines_are_comments {
10884                        edits.extend(
10885                            selection_edit_ranges
10886                                .iter()
10887                                .cloned()
10888                                .map(|range| (range, empty_str.clone())),
10889                        );
10890                    } else {
10891                        let min_column = selection_edit_ranges
10892                            .iter()
10893                            .map(|range| range.start.column)
10894                            .min()
10895                            .unwrap_or(0);
10896                        edits.extend(selection_edit_ranges.iter().map(|range| {
10897                            let position = Point::new(range.start.row, min_column);
10898                            (position..position, first_prefix.clone())
10899                        }));
10900                    }
10901                } else if let Some((full_comment_prefix, comment_suffix)) =
10902                    language.block_comment_delimiters()
10903                {
10904                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
10905                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
10906                    let prefix_range = comment_prefix_range(
10907                        snapshot.deref(),
10908                        start_row,
10909                        comment_prefix,
10910                        comment_prefix_whitespace,
10911                        ignore_indent,
10912                    );
10913                    let suffix_range = comment_suffix_range(
10914                        snapshot.deref(),
10915                        end_row,
10916                        comment_suffix.trim_start_matches(' '),
10917                        comment_suffix.starts_with(' '),
10918                    );
10919
10920                    if prefix_range.is_empty() || suffix_range.is_empty() {
10921                        edits.push((
10922                            prefix_range.start..prefix_range.start,
10923                            full_comment_prefix.clone(),
10924                        ));
10925                        edits.push((suffix_range.end..suffix_range.end, comment_suffix.clone()));
10926                        suffixes_inserted.push((end_row, comment_suffix.len()));
10927                    } else {
10928                        edits.push((prefix_range, empty_str.clone()));
10929                        edits.push((suffix_range, empty_str.clone()));
10930                    }
10931                } else {
10932                    continue;
10933                }
10934            }
10935
10936            drop(snapshot);
10937            this.buffer.update(cx, |buffer, cx| {
10938                buffer.edit(edits, None, cx);
10939            });
10940
10941            // Adjust selections so that they end before any comment suffixes that
10942            // were inserted.
10943            let mut suffixes_inserted = suffixes_inserted.into_iter().peekable();
10944            let mut selections = this.selections.all::<Point>(cx);
10945            let snapshot = this.buffer.read(cx).read(cx);
10946            for selection in &mut selections {
10947                while let Some((row, suffix_len)) = suffixes_inserted.peek().copied() {
10948                    match row.cmp(&MultiBufferRow(selection.end.row)) {
10949                        Ordering::Less => {
10950                            suffixes_inserted.next();
10951                            continue;
10952                        }
10953                        Ordering::Greater => break,
10954                        Ordering::Equal => {
10955                            if selection.end.column == snapshot.line_len(row) {
10956                                if selection.is_empty() {
10957                                    selection.start.column -= suffix_len as u32;
10958                                }
10959                                selection.end.column -= suffix_len as u32;
10960                            }
10961                            break;
10962                        }
10963                    }
10964                }
10965            }
10966
10967            drop(snapshot);
10968            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10969                s.select(selections)
10970            });
10971
10972            let selections = this.selections.all::<Point>(cx);
10973            let selections_on_single_row = selections.windows(2).all(|selections| {
10974                selections[0].start.row == selections[1].start.row
10975                    && selections[0].end.row == selections[1].end.row
10976                    && selections[0].start.row == selections[0].end.row
10977            });
10978            let selections_selecting = selections
10979                .iter()
10980                .any(|selection| selection.start != selection.end);
10981            let advance_downwards = action.advance_downwards
10982                && selections_on_single_row
10983                && !selections_selecting
10984                && !matches!(this.mode, EditorMode::SingleLine { .. });
10985
10986            if advance_downwards {
10987                let snapshot = this.buffer.read(cx).snapshot(cx);
10988
10989                this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10990                    s.move_cursors_with(|display_snapshot, display_point, _| {
10991                        let mut point = display_point.to_point(display_snapshot);
10992                        point.row += 1;
10993                        point = snapshot.clip_point(point, Bias::Left);
10994                        let display_point = point.to_display_point(display_snapshot);
10995                        let goal = SelectionGoal::HorizontalPosition(
10996                            display_snapshot
10997                                .x_for_display_point(display_point, text_layout_details)
10998                                .into(),
10999                        );
11000                        (display_point, goal)
11001                    })
11002                });
11003            }
11004        });
11005    }
11006
11007    pub fn select_enclosing_symbol(
11008        &mut self,
11009        _: &SelectEnclosingSymbol,
11010        window: &mut Window,
11011        cx: &mut Context<Self>,
11012    ) {
11013        let buffer = self.buffer.read(cx).snapshot(cx);
11014        let old_selections = self.selections.all::<usize>(cx).into_boxed_slice();
11015
11016        fn update_selection(
11017            selection: &Selection<usize>,
11018            buffer_snap: &MultiBufferSnapshot,
11019        ) -> Option<Selection<usize>> {
11020            let cursor = selection.head();
11021            let (_buffer_id, symbols) = buffer_snap.symbols_containing(cursor, None)?;
11022            for symbol in symbols.iter().rev() {
11023                let start = symbol.range.start.to_offset(buffer_snap);
11024                let end = symbol.range.end.to_offset(buffer_snap);
11025                let new_range = start..end;
11026                if start < selection.start || end > selection.end {
11027                    return Some(Selection {
11028                        id: selection.id,
11029                        start: new_range.start,
11030                        end: new_range.end,
11031                        goal: SelectionGoal::None,
11032                        reversed: selection.reversed,
11033                    });
11034                }
11035            }
11036            None
11037        }
11038
11039        let mut selected_larger_symbol = false;
11040        let new_selections = old_selections
11041            .iter()
11042            .map(|selection| match update_selection(selection, &buffer) {
11043                Some(new_selection) => {
11044                    if new_selection.range() != selection.range() {
11045                        selected_larger_symbol = true;
11046                    }
11047                    new_selection
11048                }
11049                None => selection.clone(),
11050            })
11051            .collect::<Vec<_>>();
11052
11053        if selected_larger_symbol {
11054            self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
11055                s.select(new_selections);
11056            });
11057        }
11058    }
11059
11060    pub fn select_larger_syntax_node(
11061        &mut self,
11062        _: &SelectLargerSyntaxNode,
11063        window: &mut Window,
11064        cx: &mut Context<Self>,
11065    ) {
11066        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
11067        let buffer = self.buffer.read(cx).snapshot(cx);
11068        let old_selections = self.selections.all::<usize>(cx).into_boxed_slice();
11069
11070        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
11071        let mut selected_larger_node = false;
11072        let new_selections = old_selections
11073            .iter()
11074            .map(|selection| {
11075                let old_range = selection.start..selection.end;
11076                let mut new_range = old_range.clone();
11077                let mut new_node = None;
11078                while let Some((node, containing_range)) = buffer.syntax_ancestor(new_range.clone())
11079                {
11080                    new_node = Some(node);
11081                    new_range = match containing_range {
11082                        MultiOrSingleBufferOffsetRange::Single(_) => break,
11083                        MultiOrSingleBufferOffsetRange::Multi(range) => range,
11084                    };
11085                    if !display_map.intersects_fold(new_range.start)
11086                        && !display_map.intersects_fold(new_range.end)
11087                    {
11088                        break;
11089                    }
11090                }
11091
11092                if let Some(node) = new_node {
11093                    // Log the ancestor, to support using this action as a way to explore TreeSitter
11094                    // nodes. Parent and grandparent are also logged because this operation will not
11095                    // visit nodes that have the same range as their parent.
11096                    log::info!("Node: {node:?}");
11097                    let parent = node.parent();
11098                    log::info!("Parent: {parent:?}");
11099                    let grandparent = parent.and_then(|x| x.parent());
11100                    log::info!("Grandparent: {grandparent:?}");
11101                }
11102
11103                selected_larger_node |= new_range != old_range;
11104                Selection {
11105                    id: selection.id,
11106                    start: new_range.start,
11107                    end: new_range.end,
11108                    goal: SelectionGoal::None,
11109                    reversed: selection.reversed,
11110                }
11111            })
11112            .collect::<Vec<_>>();
11113
11114        if selected_larger_node {
11115            stack.push(old_selections);
11116            self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
11117                s.select(new_selections);
11118            });
11119        }
11120        self.select_larger_syntax_node_stack = stack;
11121    }
11122
11123    pub fn select_smaller_syntax_node(
11124        &mut self,
11125        _: &SelectSmallerSyntaxNode,
11126        window: &mut Window,
11127        cx: &mut Context<Self>,
11128    ) {
11129        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
11130        if let Some(selections) = stack.pop() {
11131            self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
11132                s.select(selections.to_vec());
11133            });
11134        }
11135        self.select_larger_syntax_node_stack = stack;
11136    }
11137
11138    fn refresh_runnables(&mut self, window: &mut Window, cx: &mut Context<Self>) -> Task<()> {
11139        if !EditorSettings::get_global(cx).gutter.runnables {
11140            self.clear_tasks();
11141            return Task::ready(());
11142        }
11143        let project = self.project.as_ref().map(Entity::downgrade);
11144        cx.spawn_in(window, |this, mut cx| async move {
11145            cx.background_executor().timer(UPDATE_DEBOUNCE).await;
11146            let Some(project) = project.and_then(|p| p.upgrade()) else {
11147                return;
11148            };
11149            let Ok(display_snapshot) = this.update(&mut cx, |this, cx| {
11150                this.display_map.update(cx, |map, cx| map.snapshot(cx))
11151            }) else {
11152                return;
11153            };
11154
11155            let hide_runnables = project
11156                .update(&mut cx, |project, cx| {
11157                    // Do not display any test indicators in non-dev server remote projects.
11158                    project.is_via_collab() && project.ssh_connection_string(cx).is_none()
11159                })
11160                .unwrap_or(true);
11161            if hide_runnables {
11162                return;
11163            }
11164            let new_rows =
11165                cx.background_spawn({
11166                    let snapshot = display_snapshot.clone();
11167                    async move {
11168                        Self::fetch_runnable_ranges(&snapshot, Anchor::min()..Anchor::max())
11169                    }
11170                })
11171                    .await;
11172
11173            let rows = Self::runnable_rows(project, display_snapshot, new_rows, cx.clone());
11174            this.update(&mut cx, |this, _| {
11175                this.clear_tasks();
11176                for (key, value) in rows {
11177                    this.insert_tasks(key, value);
11178                }
11179            })
11180            .ok();
11181        })
11182    }
11183    fn fetch_runnable_ranges(
11184        snapshot: &DisplaySnapshot,
11185        range: Range<Anchor>,
11186    ) -> Vec<language::RunnableRange> {
11187        snapshot.buffer_snapshot.runnable_ranges(range).collect()
11188    }
11189
11190    fn runnable_rows(
11191        project: Entity<Project>,
11192        snapshot: DisplaySnapshot,
11193        runnable_ranges: Vec<RunnableRange>,
11194        mut cx: AsyncWindowContext,
11195    ) -> Vec<((BufferId, u32), RunnableTasks)> {
11196        runnable_ranges
11197            .into_iter()
11198            .filter_map(|mut runnable| {
11199                let tasks = cx
11200                    .update(|_, cx| Self::templates_with_tags(&project, &mut runnable.runnable, cx))
11201                    .ok()?;
11202                if tasks.is_empty() {
11203                    return None;
11204                }
11205
11206                let point = runnable.run_range.start.to_point(&snapshot.buffer_snapshot);
11207
11208                let row = snapshot
11209                    .buffer_snapshot
11210                    .buffer_line_for_row(MultiBufferRow(point.row))?
11211                    .1
11212                    .start
11213                    .row;
11214
11215                let context_range =
11216                    BufferOffset(runnable.full_range.start)..BufferOffset(runnable.full_range.end);
11217                Some((
11218                    (runnable.buffer_id, row),
11219                    RunnableTasks {
11220                        templates: tasks,
11221                        offset: snapshot
11222                            .buffer_snapshot
11223                            .anchor_before(runnable.run_range.start),
11224                        context_range,
11225                        column: point.column,
11226                        extra_variables: runnable.extra_captures,
11227                    },
11228                ))
11229            })
11230            .collect()
11231    }
11232
11233    fn templates_with_tags(
11234        project: &Entity<Project>,
11235        runnable: &mut Runnable,
11236        cx: &mut App,
11237    ) -> Vec<(TaskSourceKind, TaskTemplate)> {
11238        let (inventory, worktree_id, file) = project.read_with(cx, |project, cx| {
11239            let (worktree_id, file) = project
11240                .buffer_for_id(runnable.buffer, cx)
11241                .and_then(|buffer| buffer.read(cx).file())
11242                .map(|file| (file.worktree_id(cx), file.clone()))
11243                .unzip();
11244
11245            (
11246                project.task_store().read(cx).task_inventory().cloned(),
11247                worktree_id,
11248                file,
11249            )
11250        });
11251
11252        let tags = mem::take(&mut runnable.tags);
11253        let mut tags: Vec<_> = tags
11254            .into_iter()
11255            .flat_map(|tag| {
11256                let tag = tag.0.clone();
11257                inventory
11258                    .as_ref()
11259                    .into_iter()
11260                    .flat_map(|inventory| {
11261                        inventory.read(cx).list_tasks(
11262                            file.clone(),
11263                            Some(runnable.language.clone()),
11264                            worktree_id,
11265                            cx,
11266                        )
11267                    })
11268                    .filter(move |(_, template)| {
11269                        template.tags.iter().any(|source_tag| source_tag == &tag)
11270                    })
11271            })
11272            .sorted_by_key(|(kind, _)| kind.to_owned())
11273            .collect();
11274        if let Some((leading_tag_source, _)) = tags.first() {
11275            // Strongest source wins; if we have worktree tag binding, prefer that to
11276            // global and language bindings;
11277            // if we have a global binding, prefer that to language binding.
11278            let first_mismatch = tags
11279                .iter()
11280                .position(|(tag_source, _)| tag_source != leading_tag_source);
11281            if let Some(index) = first_mismatch {
11282                tags.truncate(index);
11283            }
11284        }
11285
11286        tags
11287    }
11288
11289    pub fn move_to_enclosing_bracket(
11290        &mut self,
11291        _: &MoveToEnclosingBracket,
11292        window: &mut Window,
11293        cx: &mut Context<Self>,
11294    ) {
11295        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
11296            s.move_offsets_with(|snapshot, selection| {
11297                let Some(enclosing_bracket_ranges) =
11298                    snapshot.enclosing_bracket_ranges(selection.start..selection.end)
11299                else {
11300                    return;
11301                };
11302
11303                let mut best_length = usize::MAX;
11304                let mut best_inside = false;
11305                let mut best_in_bracket_range = false;
11306                let mut best_destination = None;
11307                for (open, close) in enclosing_bracket_ranges {
11308                    let close = close.to_inclusive();
11309                    let length = close.end() - open.start;
11310                    let inside = selection.start >= open.end && selection.end <= *close.start();
11311                    let in_bracket_range = open.to_inclusive().contains(&selection.head())
11312                        || close.contains(&selection.head());
11313
11314                    // If best is next to a bracket and current isn't, skip
11315                    if !in_bracket_range && best_in_bracket_range {
11316                        continue;
11317                    }
11318
11319                    // Prefer smaller lengths unless best is inside and current isn't
11320                    if length > best_length && (best_inside || !inside) {
11321                        continue;
11322                    }
11323
11324                    best_length = length;
11325                    best_inside = inside;
11326                    best_in_bracket_range = in_bracket_range;
11327                    best_destination = Some(
11328                        if close.contains(&selection.start) && close.contains(&selection.end) {
11329                            if inside {
11330                                open.end
11331                            } else {
11332                                open.start
11333                            }
11334                        } else if inside {
11335                            *close.start()
11336                        } else {
11337                            *close.end()
11338                        },
11339                    );
11340                }
11341
11342                if let Some(destination) = best_destination {
11343                    selection.collapse_to(destination, SelectionGoal::None);
11344                }
11345            })
11346        });
11347    }
11348
11349    pub fn undo_selection(
11350        &mut self,
11351        _: &UndoSelection,
11352        window: &mut Window,
11353        cx: &mut Context<Self>,
11354    ) {
11355        self.end_selection(window, cx);
11356        self.selection_history.mode = SelectionHistoryMode::Undoing;
11357        if let Some(entry) = self.selection_history.undo_stack.pop_back() {
11358            self.change_selections(None, window, cx, |s| {
11359                s.select_anchors(entry.selections.to_vec())
11360            });
11361            self.select_next_state = entry.select_next_state;
11362            self.select_prev_state = entry.select_prev_state;
11363            self.add_selections_state = entry.add_selections_state;
11364            self.request_autoscroll(Autoscroll::newest(), cx);
11365        }
11366        self.selection_history.mode = SelectionHistoryMode::Normal;
11367    }
11368
11369    pub fn redo_selection(
11370        &mut self,
11371        _: &RedoSelection,
11372        window: &mut Window,
11373        cx: &mut Context<Self>,
11374    ) {
11375        self.end_selection(window, cx);
11376        self.selection_history.mode = SelectionHistoryMode::Redoing;
11377        if let Some(entry) = self.selection_history.redo_stack.pop_back() {
11378            self.change_selections(None, window, cx, |s| {
11379                s.select_anchors(entry.selections.to_vec())
11380            });
11381            self.select_next_state = entry.select_next_state;
11382            self.select_prev_state = entry.select_prev_state;
11383            self.add_selections_state = entry.add_selections_state;
11384            self.request_autoscroll(Autoscroll::newest(), cx);
11385        }
11386        self.selection_history.mode = SelectionHistoryMode::Normal;
11387    }
11388
11389    pub fn expand_excerpts(
11390        &mut self,
11391        action: &ExpandExcerpts,
11392        _: &mut Window,
11393        cx: &mut Context<Self>,
11394    ) {
11395        self.expand_excerpts_for_direction(action.lines, ExpandExcerptDirection::UpAndDown, cx)
11396    }
11397
11398    pub fn expand_excerpts_down(
11399        &mut self,
11400        action: &ExpandExcerptsDown,
11401        _: &mut Window,
11402        cx: &mut Context<Self>,
11403    ) {
11404        self.expand_excerpts_for_direction(action.lines, ExpandExcerptDirection::Down, cx)
11405    }
11406
11407    pub fn expand_excerpts_up(
11408        &mut self,
11409        action: &ExpandExcerptsUp,
11410        _: &mut Window,
11411        cx: &mut Context<Self>,
11412    ) {
11413        self.expand_excerpts_for_direction(action.lines, ExpandExcerptDirection::Up, cx)
11414    }
11415
11416    pub fn expand_excerpts_for_direction(
11417        &mut self,
11418        lines: u32,
11419        direction: ExpandExcerptDirection,
11420
11421        cx: &mut Context<Self>,
11422    ) {
11423        let selections = self.selections.disjoint_anchors();
11424
11425        let lines = if lines == 0 {
11426            EditorSettings::get_global(cx).expand_excerpt_lines
11427        } else {
11428            lines
11429        };
11430
11431        self.buffer.update(cx, |buffer, cx| {
11432            let snapshot = buffer.snapshot(cx);
11433            let mut excerpt_ids = selections
11434                .iter()
11435                .flat_map(|selection| snapshot.excerpt_ids_for_range(selection.range()))
11436                .collect::<Vec<_>>();
11437            excerpt_ids.sort();
11438            excerpt_ids.dedup();
11439            buffer.expand_excerpts(excerpt_ids, lines, direction, cx)
11440        })
11441    }
11442
11443    pub fn expand_excerpt(
11444        &mut self,
11445        excerpt: ExcerptId,
11446        direction: ExpandExcerptDirection,
11447        cx: &mut Context<Self>,
11448    ) {
11449        let lines = EditorSettings::get_global(cx).expand_excerpt_lines;
11450        self.buffer.update(cx, |buffer, cx| {
11451            buffer.expand_excerpts([excerpt], lines, direction, cx)
11452        })
11453    }
11454
11455    pub fn go_to_singleton_buffer_point(
11456        &mut self,
11457        point: Point,
11458        window: &mut Window,
11459        cx: &mut Context<Self>,
11460    ) {
11461        self.go_to_singleton_buffer_range(point..point, window, cx);
11462    }
11463
11464    pub fn go_to_singleton_buffer_range(
11465        &mut self,
11466        range: Range<Point>,
11467        window: &mut Window,
11468        cx: &mut Context<Self>,
11469    ) {
11470        let multibuffer = self.buffer().read(cx);
11471        let Some(buffer) = multibuffer.as_singleton() else {
11472            return;
11473        };
11474        let Some(start) = multibuffer.buffer_point_to_anchor(&buffer, range.start, cx) else {
11475            return;
11476        };
11477        let Some(end) = multibuffer.buffer_point_to_anchor(&buffer, range.end, cx) else {
11478            return;
11479        };
11480        self.change_selections(Some(Autoscroll::center()), window, cx, |s| {
11481            s.select_anchor_ranges([start..end])
11482        });
11483    }
11484
11485    fn go_to_diagnostic(
11486        &mut self,
11487        _: &GoToDiagnostic,
11488        window: &mut Window,
11489        cx: &mut Context<Self>,
11490    ) {
11491        self.go_to_diagnostic_impl(Direction::Next, window, cx)
11492    }
11493
11494    fn go_to_prev_diagnostic(
11495        &mut self,
11496        _: &GoToPreviousDiagnostic,
11497        window: &mut Window,
11498        cx: &mut Context<Self>,
11499    ) {
11500        self.go_to_diagnostic_impl(Direction::Prev, window, cx)
11501    }
11502
11503    pub fn go_to_diagnostic_impl(
11504        &mut self,
11505        direction: Direction,
11506        window: &mut Window,
11507        cx: &mut Context<Self>,
11508    ) {
11509        let buffer = self.buffer.read(cx).snapshot(cx);
11510        let selection = self.selections.newest::<usize>(cx);
11511
11512        // If there is an active Diagnostic Popover jump to its diagnostic instead.
11513        if direction == Direction::Next {
11514            if let Some(popover) = self.hover_state.diagnostic_popover.as_ref() {
11515                let Some(buffer_id) = popover.local_diagnostic.range.start.buffer_id else {
11516                    return;
11517                };
11518                self.activate_diagnostics(
11519                    buffer_id,
11520                    popover.local_diagnostic.diagnostic.group_id,
11521                    window,
11522                    cx,
11523                );
11524                if let Some(active_diagnostics) = self.active_diagnostics.as_ref() {
11525                    let primary_range_start = active_diagnostics.primary_range.start;
11526                    self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
11527                        let mut new_selection = s.newest_anchor().clone();
11528                        new_selection.collapse_to(primary_range_start, SelectionGoal::None);
11529                        s.select_anchors(vec![new_selection.clone()]);
11530                    });
11531                    self.refresh_inline_completion(false, true, window, cx);
11532                }
11533                return;
11534            }
11535        }
11536
11537        let active_group_id = self
11538            .active_diagnostics
11539            .as_ref()
11540            .map(|active_group| active_group.group_id);
11541        let active_primary_range = self.active_diagnostics.as_ref().map(|active_diagnostics| {
11542            active_diagnostics
11543                .primary_range
11544                .to_offset(&buffer)
11545                .to_inclusive()
11546        });
11547        let search_start = if let Some(active_primary_range) = active_primary_range.as_ref() {
11548            if active_primary_range.contains(&selection.head()) {
11549                *active_primary_range.start()
11550            } else {
11551                selection.head()
11552            }
11553        } else {
11554            selection.head()
11555        };
11556
11557        let snapshot = self.snapshot(window, cx);
11558        let primary_diagnostics_before = buffer
11559            .diagnostics_in_range::<usize>(0..search_start)
11560            .filter(|entry| entry.diagnostic.is_primary)
11561            .filter(|entry| entry.range.start != entry.range.end)
11562            .filter(|entry| entry.diagnostic.severity <= DiagnosticSeverity::WARNING)
11563            .filter(|entry| !snapshot.intersects_fold(entry.range.start))
11564            .collect::<Vec<_>>();
11565        let last_same_group_diagnostic_before = active_group_id.and_then(|active_group_id| {
11566            primary_diagnostics_before
11567                .iter()
11568                .position(|entry| entry.diagnostic.group_id == active_group_id)
11569        });
11570
11571        let primary_diagnostics_after = buffer
11572            .diagnostics_in_range::<usize>(search_start..buffer.len())
11573            .filter(|entry| entry.diagnostic.is_primary)
11574            .filter(|entry| entry.range.start != entry.range.end)
11575            .filter(|entry| entry.diagnostic.severity <= DiagnosticSeverity::WARNING)
11576            .filter(|diagnostic| !snapshot.intersects_fold(diagnostic.range.start))
11577            .collect::<Vec<_>>();
11578        let last_same_group_diagnostic_after = active_group_id.and_then(|active_group_id| {
11579            primary_diagnostics_after
11580                .iter()
11581                .enumerate()
11582                .rev()
11583                .find_map(|(i, entry)| {
11584                    if entry.diagnostic.group_id == active_group_id {
11585                        Some(i)
11586                    } else {
11587                        None
11588                    }
11589                })
11590        });
11591
11592        let next_primary_diagnostic = match direction {
11593            Direction::Prev => primary_diagnostics_before
11594                .iter()
11595                .take(last_same_group_diagnostic_before.unwrap_or(usize::MAX))
11596                .rev()
11597                .next(),
11598            Direction::Next => primary_diagnostics_after
11599                .iter()
11600                .skip(
11601                    last_same_group_diagnostic_after
11602                        .map(|index| index + 1)
11603                        .unwrap_or(0),
11604                )
11605                .next(),
11606        };
11607
11608        // Cycle around to the start of the buffer, potentially moving back to the start of
11609        // the currently active diagnostic.
11610        let cycle_around = || match direction {
11611            Direction::Prev => primary_diagnostics_after
11612                .iter()
11613                .rev()
11614                .chain(primary_diagnostics_before.iter().rev())
11615                .next(),
11616            Direction::Next => primary_diagnostics_before
11617                .iter()
11618                .chain(primary_diagnostics_after.iter())
11619                .next(),
11620        };
11621
11622        if let Some((primary_range, group_id)) = next_primary_diagnostic
11623            .or_else(cycle_around)
11624            .map(|entry| (&entry.range, entry.diagnostic.group_id))
11625        {
11626            let Some(buffer_id) = buffer.anchor_after(primary_range.start).buffer_id else {
11627                return;
11628            };
11629            self.activate_diagnostics(buffer_id, group_id, window, cx);
11630            if self.active_diagnostics.is_some() {
11631                self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
11632                    s.select(vec![Selection {
11633                        id: selection.id,
11634                        start: primary_range.start,
11635                        end: primary_range.start,
11636                        reversed: false,
11637                        goal: SelectionGoal::None,
11638                    }]);
11639                });
11640                self.refresh_inline_completion(false, true, window, cx);
11641            }
11642        }
11643    }
11644
11645    fn go_to_next_hunk(&mut self, _: &GoToHunk, window: &mut Window, cx: &mut Context<Self>) {
11646        let snapshot = self.snapshot(window, cx);
11647        let selection = self.selections.newest::<Point>(cx);
11648        self.go_to_hunk_before_or_after_position(
11649            &snapshot,
11650            selection.head(),
11651            Direction::Next,
11652            window,
11653            cx,
11654        );
11655    }
11656
11657    fn go_to_hunk_before_or_after_position(
11658        &mut self,
11659        snapshot: &EditorSnapshot,
11660        position: Point,
11661        direction: Direction,
11662        window: &mut Window,
11663        cx: &mut Context<Editor>,
11664    ) {
11665        let row = if direction == Direction::Next {
11666            self.hunk_after_position(snapshot, position)
11667                .map(|hunk| hunk.row_range.start)
11668        } else {
11669            self.hunk_before_position(snapshot, position)
11670        };
11671
11672        if let Some(row) = row {
11673            let destination = Point::new(row.0, 0);
11674            let autoscroll = Autoscroll::center();
11675
11676            self.unfold_ranges(&[destination..destination], false, false, cx);
11677            self.change_selections(Some(autoscroll), window, cx, |s| {
11678                s.select_ranges([destination..destination]);
11679            });
11680        }
11681    }
11682
11683    fn hunk_after_position(
11684        &mut self,
11685        snapshot: &EditorSnapshot,
11686        position: Point,
11687    ) -> Option<MultiBufferDiffHunk> {
11688        snapshot
11689            .buffer_snapshot
11690            .diff_hunks_in_range(position..snapshot.buffer_snapshot.max_point())
11691            .find(|hunk| hunk.row_range.start.0 > position.row)
11692            .or_else(|| {
11693                snapshot
11694                    .buffer_snapshot
11695                    .diff_hunks_in_range(Point::zero()..position)
11696                    .find(|hunk| hunk.row_range.end.0 < position.row)
11697            })
11698    }
11699
11700    fn go_to_prev_hunk(
11701        &mut self,
11702        _: &GoToPreviousHunk,
11703        window: &mut Window,
11704        cx: &mut Context<Self>,
11705    ) {
11706        let snapshot = self.snapshot(window, cx);
11707        let selection = self.selections.newest::<Point>(cx);
11708        self.go_to_hunk_before_or_after_position(
11709            &snapshot,
11710            selection.head(),
11711            Direction::Prev,
11712            window,
11713            cx,
11714        );
11715    }
11716
11717    fn hunk_before_position(
11718        &mut self,
11719        snapshot: &EditorSnapshot,
11720        position: Point,
11721    ) -> Option<MultiBufferRow> {
11722        snapshot
11723            .buffer_snapshot
11724            .diff_hunk_before(position)
11725            .or_else(|| snapshot.buffer_snapshot.diff_hunk_before(Point::MAX))
11726    }
11727
11728    pub fn go_to_definition(
11729        &mut self,
11730        _: &GoToDefinition,
11731        window: &mut Window,
11732        cx: &mut Context<Self>,
11733    ) -> Task<Result<Navigated>> {
11734        let definition =
11735            self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, false, window, cx);
11736        cx.spawn_in(window, |editor, mut cx| async move {
11737            if definition.await? == Navigated::Yes {
11738                return Ok(Navigated::Yes);
11739            }
11740            match editor.update_in(&mut cx, |editor, window, cx| {
11741                editor.find_all_references(&FindAllReferences, window, cx)
11742            })? {
11743                Some(references) => references.await,
11744                None => Ok(Navigated::No),
11745            }
11746        })
11747    }
11748
11749    pub fn go_to_declaration(
11750        &mut self,
11751        _: &GoToDeclaration,
11752        window: &mut Window,
11753        cx: &mut Context<Self>,
11754    ) -> Task<Result<Navigated>> {
11755        self.go_to_definition_of_kind(GotoDefinitionKind::Declaration, false, window, cx)
11756    }
11757
11758    pub fn go_to_declaration_split(
11759        &mut self,
11760        _: &GoToDeclaration,
11761        window: &mut Window,
11762        cx: &mut Context<Self>,
11763    ) -> Task<Result<Navigated>> {
11764        self.go_to_definition_of_kind(GotoDefinitionKind::Declaration, true, window, cx)
11765    }
11766
11767    pub fn go_to_implementation(
11768        &mut self,
11769        _: &GoToImplementation,
11770        window: &mut Window,
11771        cx: &mut Context<Self>,
11772    ) -> Task<Result<Navigated>> {
11773        self.go_to_definition_of_kind(GotoDefinitionKind::Implementation, false, window, cx)
11774    }
11775
11776    pub fn go_to_implementation_split(
11777        &mut self,
11778        _: &GoToImplementationSplit,
11779        window: &mut Window,
11780        cx: &mut Context<Self>,
11781    ) -> Task<Result<Navigated>> {
11782        self.go_to_definition_of_kind(GotoDefinitionKind::Implementation, true, window, cx)
11783    }
11784
11785    pub fn go_to_type_definition(
11786        &mut self,
11787        _: &GoToTypeDefinition,
11788        window: &mut Window,
11789        cx: &mut Context<Self>,
11790    ) -> Task<Result<Navigated>> {
11791        self.go_to_definition_of_kind(GotoDefinitionKind::Type, false, window, cx)
11792    }
11793
11794    pub fn go_to_definition_split(
11795        &mut self,
11796        _: &GoToDefinitionSplit,
11797        window: &mut Window,
11798        cx: &mut Context<Self>,
11799    ) -> Task<Result<Navigated>> {
11800        self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, true, window, cx)
11801    }
11802
11803    pub fn go_to_type_definition_split(
11804        &mut self,
11805        _: &GoToTypeDefinitionSplit,
11806        window: &mut Window,
11807        cx: &mut Context<Self>,
11808    ) -> Task<Result<Navigated>> {
11809        self.go_to_definition_of_kind(GotoDefinitionKind::Type, true, window, cx)
11810    }
11811
11812    fn go_to_definition_of_kind(
11813        &mut self,
11814        kind: GotoDefinitionKind,
11815        split: bool,
11816        window: &mut Window,
11817        cx: &mut Context<Self>,
11818    ) -> Task<Result<Navigated>> {
11819        let Some(provider) = self.semantics_provider.clone() else {
11820            return Task::ready(Ok(Navigated::No));
11821        };
11822        let head = self.selections.newest::<usize>(cx).head();
11823        let buffer = self.buffer.read(cx);
11824        let (buffer, head) = if let Some(text_anchor) = buffer.text_anchor_for_position(head, cx) {
11825            text_anchor
11826        } else {
11827            return Task::ready(Ok(Navigated::No));
11828        };
11829
11830        let Some(definitions) = provider.definitions(&buffer, head, kind, cx) else {
11831            return Task::ready(Ok(Navigated::No));
11832        };
11833
11834        cx.spawn_in(window, |editor, mut cx| async move {
11835            let definitions = definitions.await?;
11836            let navigated = editor
11837                .update_in(&mut cx, |editor, window, cx| {
11838                    editor.navigate_to_hover_links(
11839                        Some(kind),
11840                        definitions
11841                            .into_iter()
11842                            .filter(|location| {
11843                                hover_links::exclude_link_to_position(&buffer, &head, location, cx)
11844                            })
11845                            .map(HoverLink::Text)
11846                            .collect::<Vec<_>>(),
11847                        split,
11848                        window,
11849                        cx,
11850                    )
11851                })?
11852                .await?;
11853            anyhow::Ok(navigated)
11854        })
11855    }
11856
11857    pub fn open_url(&mut self, _: &OpenUrl, window: &mut Window, cx: &mut Context<Self>) {
11858        let selection = self.selections.newest_anchor();
11859        let head = selection.head();
11860        let tail = selection.tail();
11861
11862        let Some((buffer, start_position)) =
11863            self.buffer.read(cx).text_anchor_for_position(head, cx)
11864        else {
11865            return;
11866        };
11867
11868        let end_position = if head != tail {
11869            let Some((_, pos)) = self.buffer.read(cx).text_anchor_for_position(tail, cx) else {
11870                return;
11871            };
11872            Some(pos)
11873        } else {
11874            None
11875        };
11876
11877        let url_finder = cx.spawn_in(window, |editor, mut cx| async move {
11878            let url = if let Some(end_pos) = end_position {
11879                find_url_from_range(&buffer, start_position..end_pos, cx.clone())
11880            } else {
11881                find_url(&buffer, start_position, cx.clone()).map(|(_, url)| url)
11882            };
11883
11884            if let Some(url) = url {
11885                editor.update(&mut cx, |_, cx| {
11886                    cx.open_url(&url);
11887                })
11888            } else {
11889                Ok(())
11890            }
11891        });
11892
11893        url_finder.detach();
11894    }
11895
11896    pub fn open_selected_filename(
11897        &mut self,
11898        _: &OpenSelectedFilename,
11899        window: &mut Window,
11900        cx: &mut Context<Self>,
11901    ) {
11902        let Some(workspace) = self.workspace() else {
11903            return;
11904        };
11905
11906        let position = self.selections.newest_anchor().head();
11907
11908        let Some((buffer, buffer_position)) =
11909            self.buffer.read(cx).text_anchor_for_position(position, cx)
11910        else {
11911            return;
11912        };
11913
11914        let project = self.project.clone();
11915
11916        cx.spawn_in(window, |_, mut cx| async move {
11917            let result = find_file(&buffer, project, buffer_position, &mut cx).await;
11918
11919            if let Some((_, path)) = result {
11920                workspace
11921                    .update_in(&mut cx, |workspace, window, cx| {
11922                        workspace.open_resolved_path(path, window, cx)
11923                    })?
11924                    .await?;
11925            }
11926            anyhow::Ok(())
11927        })
11928        .detach();
11929    }
11930
11931    pub(crate) fn navigate_to_hover_links(
11932        &mut self,
11933        kind: Option<GotoDefinitionKind>,
11934        mut definitions: Vec<HoverLink>,
11935        split: bool,
11936        window: &mut Window,
11937        cx: &mut Context<Editor>,
11938    ) -> Task<Result<Navigated>> {
11939        // If there is one definition, just open it directly
11940        if definitions.len() == 1 {
11941            let definition = definitions.pop().unwrap();
11942
11943            enum TargetTaskResult {
11944                Location(Option<Location>),
11945                AlreadyNavigated,
11946            }
11947
11948            let target_task = match definition {
11949                HoverLink::Text(link) => {
11950                    Task::ready(anyhow::Ok(TargetTaskResult::Location(Some(link.target))))
11951                }
11952                HoverLink::InlayHint(lsp_location, server_id) => {
11953                    let computation =
11954                        self.compute_target_location(lsp_location, server_id, window, cx);
11955                    cx.background_spawn(async move {
11956                        let location = computation.await?;
11957                        Ok(TargetTaskResult::Location(location))
11958                    })
11959                }
11960                HoverLink::Url(url) => {
11961                    cx.open_url(&url);
11962                    Task::ready(Ok(TargetTaskResult::AlreadyNavigated))
11963                }
11964                HoverLink::File(path) => {
11965                    if let Some(workspace) = self.workspace() {
11966                        cx.spawn_in(window, |_, mut cx| async move {
11967                            workspace
11968                                .update_in(&mut cx, |workspace, window, cx| {
11969                                    workspace.open_resolved_path(path, window, cx)
11970                                })?
11971                                .await
11972                                .map(|_| TargetTaskResult::AlreadyNavigated)
11973                        })
11974                    } else {
11975                        Task::ready(Ok(TargetTaskResult::Location(None)))
11976                    }
11977                }
11978            };
11979            cx.spawn_in(window, |editor, mut cx| async move {
11980                let target = match target_task.await.context("target resolution task")? {
11981                    TargetTaskResult::AlreadyNavigated => return Ok(Navigated::Yes),
11982                    TargetTaskResult::Location(None) => return Ok(Navigated::No),
11983                    TargetTaskResult::Location(Some(target)) => target,
11984                };
11985
11986                editor.update_in(&mut cx, |editor, window, cx| {
11987                    let Some(workspace) = editor.workspace() else {
11988                        return Navigated::No;
11989                    };
11990                    let pane = workspace.read(cx).active_pane().clone();
11991
11992                    let range = target.range.to_point(target.buffer.read(cx));
11993                    let range = editor.range_for_match(&range);
11994                    let range = collapse_multiline_range(range);
11995
11996                    if !split
11997                        && Some(&target.buffer) == editor.buffer.read(cx).as_singleton().as_ref()
11998                    {
11999                        editor.go_to_singleton_buffer_range(range.clone(), window, cx);
12000                    } else {
12001                        window.defer(cx, move |window, cx| {
12002                            let target_editor: Entity<Self> =
12003                                workspace.update(cx, |workspace, cx| {
12004                                    let pane = if split {
12005                                        workspace.adjacent_pane(window, cx)
12006                                    } else {
12007                                        workspace.active_pane().clone()
12008                                    };
12009
12010                                    workspace.open_project_item(
12011                                        pane,
12012                                        target.buffer.clone(),
12013                                        true,
12014                                        true,
12015                                        window,
12016                                        cx,
12017                                    )
12018                                });
12019                            target_editor.update(cx, |target_editor, cx| {
12020                                // When selecting a definition in a different buffer, disable the nav history
12021                                // to avoid creating a history entry at the previous cursor location.
12022                                pane.update(cx, |pane, _| pane.disable_history());
12023                                target_editor.go_to_singleton_buffer_range(range, window, cx);
12024                                pane.update(cx, |pane, _| pane.enable_history());
12025                            });
12026                        });
12027                    }
12028                    Navigated::Yes
12029                })
12030            })
12031        } else if !definitions.is_empty() {
12032            cx.spawn_in(window, |editor, mut cx| async move {
12033                let (title, location_tasks, workspace) = editor
12034                    .update_in(&mut cx, |editor, window, cx| {
12035                        let tab_kind = match kind {
12036                            Some(GotoDefinitionKind::Implementation) => "Implementations",
12037                            _ => "Definitions",
12038                        };
12039                        let title = definitions
12040                            .iter()
12041                            .find_map(|definition| match definition {
12042                                HoverLink::Text(link) => link.origin.as_ref().map(|origin| {
12043                                    let buffer = origin.buffer.read(cx);
12044                                    format!(
12045                                        "{} for {}",
12046                                        tab_kind,
12047                                        buffer
12048                                            .text_for_range(origin.range.clone())
12049                                            .collect::<String>()
12050                                    )
12051                                }),
12052                                HoverLink::InlayHint(_, _) => None,
12053                                HoverLink::Url(_) => None,
12054                                HoverLink::File(_) => None,
12055                            })
12056                            .unwrap_or(tab_kind.to_string());
12057                        let location_tasks = definitions
12058                            .into_iter()
12059                            .map(|definition| match definition {
12060                                HoverLink::Text(link) => Task::ready(Ok(Some(link.target))),
12061                                HoverLink::InlayHint(lsp_location, server_id) => editor
12062                                    .compute_target_location(lsp_location, server_id, window, cx),
12063                                HoverLink::Url(_) => Task::ready(Ok(None)),
12064                                HoverLink::File(_) => Task::ready(Ok(None)),
12065                            })
12066                            .collect::<Vec<_>>();
12067                        (title, location_tasks, editor.workspace().clone())
12068                    })
12069                    .context("location tasks preparation")?;
12070
12071                let locations = future::join_all(location_tasks)
12072                    .await
12073                    .into_iter()
12074                    .filter_map(|location| location.transpose())
12075                    .collect::<Result<_>>()
12076                    .context("location tasks")?;
12077
12078                let Some(workspace) = workspace else {
12079                    return Ok(Navigated::No);
12080                };
12081                let opened = workspace
12082                    .update_in(&mut cx, |workspace, window, cx| {
12083                        Self::open_locations_in_multibuffer(
12084                            workspace,
12085                            locations,
12086                            title,
12087                            split,
12088                            MultibufferSelectionMode::First,
12089                            window,
12090                            cx,
12091                        )
12092                    })
12093                    .ok();
12094
12095                anyhow::Ok(Navigated::from_bool(opened.is_some()))
12096            })
12097        } else {
12098            Task::ready(Ok(Navigated::No))
12099        }
12100    }
12101
12102    fn compute_target_location(
12103        &self,
12104        lsp_location: lsp::Location,
12105        server_id: LanguageServerId,
12106        window: &mut Window,
12107        cx: &mut Context<Self>,
12108    ) -> Task<anyhow::Result<Option<Location>>> {
12109        let Some(project) = self.project.clone() else {
12110            return Task::ready(Ok(None));
12111        };
12112
12113        cx.spawn_in(window, move |editor, mut cx| async move {
12114            let location_task = editor.update(&mut cx, |_, cx| {
12115                project.update(cx, |project, cx| {
12116                    let language_server_name = project
12117                        .language_server_statuses(cx)
12118                        .find(|(id, _)| server_id == *id)
12119                        .map(|(_, status)| LanguageServerName::from(status.name.as_str()));
12120                    language_server_name.map(|language_server_name| {
12121                        project.open_local_buffer_via_lsp(
12122                            lsp_location.uri.clone(),
12123                            server_id,
12124                            language_server_name,
12125                            cx,
12126                        )
12127                    })
12128                })
12129            })?;
12130            let location = match location_task {
12131                Some(task) => Some({
12132                    let target_buffer_handle = task.await.context("open local buffer")?;
12133                    let range = target_buffer_handle.update(&mut cx, |target_buffer, _| {
12134                        let target_start = target_buffer
12135                            .clip_point_utf16(point_from_lsp(lsp_location.range.start), Bias::Left);
12136                        let target_end = target_buffer
12137                            .clip_point_utf16(point_from_lsp(lsp_location.range.end), Bias::Left);
12138                        target_buffer.anchor_after(target_start)
12139                            ..target_buffer.anchor_before(target_end)
12140                    })?;
12141                    Location {
12142                        buffer: target_buffer_handle,
12143                        range,
12144                    }
12145                }),
12146                None => None,
12147            };
12148            Ok(location)
12149        })
12150    }
12151
12152    pub fn find_all_references(
12153        &mut self,
12154        _: &FindAllReferences,
12155        window: &mut Window,
12156        cx: &mut Context<Self>,
12157    ) -> Option<Task<Result<Navigated>>> {
12158        let selection = self.selections.newest::<usize>(cx);
12159        let multi_buffer = self.buffer.read(cx);
12160        let head = selection.head();
12161
12162        let multi_buffer_snapshot = multi_buffer.snapshot(cx);
12163        let head_anchor = multi_buffer_snapshot.anchor_at(
12164            head,
12165            if head < selection.tail() {
12166                Bias::Right
12167            } else {
12168                Bias::Left
12169            },
12170        );
12171
12172        match self
12173            .find_all_references_task_sources
12174            .binary_search_by(|anchor| anchor.cmp(&head_anchor, &multi_buffer_snapshot))
12175        {
12176            Ok(_) => {
12177                log::info!(
12178                    "Ignoring repeated FindAllReferences invocation with the position of already running task"
12179                );
12180                return None;
12181            }
12182            Err(i) => {
12183                self.find_all_references_task_sources.insert(i, head_anchor);
12184            }
12185        }
12186
12187        let (buffer, head) = multi_buffer.text_anchor_for_position(head, cx)?;
12188        let workspace = self.workspace()?;
12189        let project = workspace.read(cx).project().clone();
12190        let references = project.update(cx, |project, cx| project.references(&buffer, head, cx));
12191        Some(cx.spawn_in(window, |editor, mut cx| async move {
12192            let _cleanup = defer({
12193                let mut cx = cx.clone();
12194                move || {
12195                    let _ = editor.update(&mut cx, |editor, _| {
12196                        if let Ok(i) =
12197                            editor
12198                                .find_all_references_task_sources
12199                                .binary_search_by(|anchor| {
12200                                    anchor.cmp(&head_anchor, &multi_buffer_snapshot)
12201                                })
12202                        {
12203                            editor.find_all_references_task_sources.remove(i);
12204                        }
12205                    });
12206                }
12207            });
12208
12209            let locations = references.await?;
12210            if locations.is_empty() {
12211                return anyhow::Ok(Navigated::No);
12212            }
12213
12214            workspace.update_in(&mut cx, |workspace, window, cx| {
12215                let title = locations
12216                    .first()
12217                    .as_ref()
12218                    .map(|location| {
12219                        let buffer = location.buffer.read(cx);
12220                        format!(
12221                            "References to `{}`",
12222                            buffer
12223                                .text_for_range(location.range.clone())
12224                                .collect::<String>()
12225                        )
12226                    })
12227                    .unwrap();
12228                Self::open_locations_in_multibuffer(
12229                    workspace,
12230                    locations,
12231                    title,
12232                    false,
12233                    MultibufferSelectionMode::First,
12234                    window,
12235                    cx,
12236                );
12237                Navigated::Yes
12238            })
12239        }))
12240    }
12241
12242    /// Opens a multibuffer with the given project locations in it
12243    pub fn open_locations_in_multibuffer(
12244        workspace: &mut Workspace,
12245        mut locations: Vec<Location>,
12246        title: String,
12247        split: bool,
12248        multibuffer_selection_mode: MultibufferSelectionMode,
12249        window: &mut Window,
12250        cx: &mut Context<Workspace>,
12251    ) {
12252        // If there are multiple definitions, open them in a multibuffer
12253        locations.sort_by_key(|location| location.buffer.read(cx).remote_id());
12254        let mut locations = locations.into_iter().peekable();
12255        let mut ranges = Vec::new();
12256        let capability = workspace.project().read(cx).capability();
12257
12258        let excerpt_buffer = cx.new(|cx| {
12259            let mut multibuffer = MultiBuffer::new(capability);
12260            while let Some(location) = locations.next() {
12261                let buffer = location.buffer.read(cx);
12262                let mut ranges_for_buffer = Vec::new();
12263                let range = location.range.to_offset(buffer);
12264                ranges_for_buffer.push(range.clone());
12265
12266                while let Some(next_location) = locations.peek() {
12267                    if next_location.buffer == location.buffer {
12268                        ranges_for_buffer.push(next_location.range.to_offset(buffer));
12269                        locations.next();
12270                    } else {
12271                        break;
12272                    }
12273                }
12274
12275                ranges_for_buffer.sort_by_key(|range| (range.start, Reverse(range.end)));
12276                ranges.extend(multibuffer.push_excerpts_with_context_lines(
12277                    location.buffer.clone(),
12278                    ranges_for_buffer,
12279                    DEFAULT_MULTIBUFFER_CONTEXT,
12280                    cx,
12281                ))
12282            }
12283
12284            multibuffer.with_title(title)
12285        });
12286
12287        let editor = cx.new(|cx| {
12288            Editor::for_multibuffer(
12289                excerpt_buffer,
12290                Some(workspace.project().clone()),
12291                true,
12292                window,
12293                cx,
12294            )
12295        });
12296        editor.update(cx, |editor, cx| {
12297            match multibuffer_selection_mode {
12298                MultibufferSelectionMode::First => {
12299                    if let Some(first_range) = ranges.first() {
12300                        editor.change_selections(None, window, cx, |selections| {
12301                            selections.clear_disjoint();
12302                            selections.select_anchor_ranges(std::iter::once(first_range.clone()));
12303                        });
12304                    }
12305                    editor.highlight_background::<Self>(
12306                        &ranges,
12307                        |theme| theme.editor_highlighted_line_background,
12308                        cx,
12309                    );
12310                }
12311                MultibufferSelectionMode::All => {
12312                    editor.change_selections(None, window, cx, |selections| {
12313                        selections.clear_disjoint();
12314                        selections.select_anchor_ranges(ranges);
12315                    });
12316                }
12317            }
12318            editor.register_buffers_with_language_servers(cx);
12319        });
12320
12321        let item = Box::new(editor);
12322        let item_id = item.item_id();
12323
12324        if split {
12325            workspace.split_item(SplitDirection::Right, item.clone(), window, cx);
12326        } else {
12327            let destination_index = workspace.active_pane().update(cx, |pane, cx| {
12328                if PreviewTabsSettings::get_global(cx).enable_preview_from_code_navigation {
12329                    pane.close_current_preview_item(window, cx)
12330                } else {
12331                    None
12332                }
12333            });
12334            workspace.add_item_to_active_pane(item.clone(), destination_index, true, window, cx);
12335        }
12336        workspace.active_pane().update(cx, |pane, cx| {
12337            pane.set_preview_item_id(Some(item_id), cx);
12338        });
12339    }
12340
12341    pub fn rename(
12342        &mut self,
12343        _: &Rename,
12344        window: &mut Window,
12345        cx: &mut Context<Self>,
12346    ) -> Option<Task<Result<()>>> {
12347        use language::ToOffset as _;
12348
12349        let provider = self.semantics_provider.clone()?;
12350        let selection = self.selections.newest_anchor().clone();
12351        let (cursor_buffer, cursor_buffer_position) = self
12352            .buffer
12353            .read(cx)
12354            .text_anchor_for_position(selection.head(), cx)?;
12355        let (tail_buffer, cursor_buffer_position_end) = self
12356            .buffer
12357            .read(cx)
12358            .text_anchor_for_position(selection.tail(), cx)?;
12359        if tail_buffer != cursor_buffer {
12360            return None;
12361        }
12362
12363        let snapshot = cursor_buffer.read(cx).snapshot();
12364        let cursor_buffer_offset = cursor_buffer_position.to_offset(&snapshot);
12365        let cursor_buffer_offset_end = cursor_buffer_position_end.to_offset(&snapshot);
12366        let prepare_rename = provider
12367            .range_for_rename(&cursor_buffer, cursor_buffer_position, cx)
12368            .unwrap_or_else(|| Task::ready(Ok(None)));
12369        drop(snapshot);
12370
12371        Some(cx.spawn_in(window, |this, mut cx| async move {
12372            let rename_range = if let Some(range) = prepare_rename.await? {
12373                Some(range)
12374            } else {
12375                this.update(&mut cx, |this, cx| {
12376                    let buffer = this.buffer.read(cx).snapshot(cx);
12377                    let mut buffer_highlights = this
12378                        .document_highlights_for_position(selection.head(), &buffer)
12379                        .filter(|highlight| {
12380                            highlight.start.excerpt_id == selection.head().excerpt_id
12381                                && highlight.end.excerpt_id == selection.head().excerpt_id
12382                        });
12383                    buffer_highlights
12384                        .next()
12385                        .map(|highlight| highlight.start.text_anchor..highlight.end.text_anchor)
12386                })?
12387            };
12388            if let Some(rename_range) = rename_range {
12389                this.update_in(&mut cx, |this, window, cx| {
12390                    let snapshot = cursor_buffer.read(cx).snapshot();
12391                    let rename_buffer_range = rename_range.to_offset(&snapshot);
12392                    let cursor_offset_in_rename_range =
12393                        cursor_buffer_offset.saturating_sub(rename_buffer_range.start);
12394                    let cursor_offset_in_rename_range_end =
12395                        cursor_buffer_offset_end.saturating_sub(rename_buffer_range.start);
12396
12397                    this.take_rename(false, window, cx);
12398                    let buffer = this.buffer.read(cx).read(cx);
12399                    let cursor_offset = selection.head().to_offset(&buffer);
12400                    let rename_start = cursor_offset.saturating_sub(cursor_offset_in_rename_range);
12401                    let rename_end = rename_start + rename_buffer_range.len();
12402                    let range = buffer.anchor_before(rename_start)..buffer.anchor_after(rename_end);
12403                    let mut old_highlight_id = None;
12404                    let old_name: Arc<str> = buffer
12405                        .chunks(rename_start..rename_end, true)
12406                        .map(|chunk| {
12407                            if old_highlight_id.is_none() {
12408                                old_highlight_id = chunk.syntax_highlight_id;
12409                            }
12410                            chunk.text
12411                        })
12412                        .collect::<String>()
12413                        .into();
12414
12415                    drop(buffer);
12416
12417                    // Position the selection in the rename editor so that it matches the current selection.
12418                    this.show_local_selections = false;
12419                    let rename_editor = cx.new(|cx| {
12420                        let mut editor = Editor::single_line(window, cx);
12421                        editor.buffer.update(cx, |buffer, cx| {
12422                            buffer.edit([(0..0, old_name.clone())], None, cx)
12423                        });
12424                        let rename_selection_range = match cursor_offset_in_rename_range
12425                            .cmp(&cursor_offset_in_rename_range_end)
12426                        {
12427                            Ordering::Equal => {
12428                                editor.select_all(&SelectAll, window, cx);
12429                                return editor;
12430                            }
12431                            Ordering::Less => {
12432                                cursor_offset_in_rename_range..cursor_offset_in_rename_range_end
12433                            }
12434                            Ordering::Greater => {
12435                                cursor_offset_in_rename_range_end..cursor_offset_in_rename_range
12436                            }
12437                        };
12438                        if rename_selection_range.end > old_name.len() {
12439                            editor.select_all(&SelectAll, window, cx);
12440                        } else {
12441                            editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
12442                                s.select_ranges([rename_selection_range]);
12443                            });
12444                        }
12445                        editor
12446                    });
12447                    cx.subscribe(&rename_editor, |_, _, e: &EditorEvent, cx| {
12448                        if e == &EditorEvent::Focused {
12449                            cx.emit(EditorEvent::FocusedIn)
12450                        }
12451                    })
12452                    .detach();
12453
12454                    let write_highlights =
12455                        this.clear_background_highlights::<DocumentHighlightWrite>(cx);
12456                    let read_highlights =
12457                        this.clear_background_highlights::<DocumentHighlightRead>(cx);
12458                    let ranges = write_highlights
12459                        .iter()
12460                        .flat_map(|(_, ranges)| ranges.iter())
12461                        .chain(read_highlights.iter().flat_map(|(_, ranges)| ranges.iter()))
12462                        .cloned()
12463                        .collect();
12464
12465                    this.highlight_text::<Rename>(
12466                        ranges,
12467                        HighlightStyle {
12468                            fade_out: Some(0.6),
12469                            ..Default::default()
12470                        },
12471                        cx,
12472                    );
12473                    let rename_focus_handle = rename_editor.focus_handle(cx);
12474                    window.focus(&rename_focus_handle);
12475                    let block_id = this.insert_blocks(
12476                        [BlockProperties {
12477                            style: BlockStyle::Flex,
12478                            placement: BlockPlacement::Below(range.start),
12479                            height: 1,
12480                            render: Arc::new({
12481                                let rename_editor = rename_editor.clone();
12482                                move |cx: &mut BlockContext| {
12483                                    let mut text_style = cx.editor_style.text.clone();
12484                                    if let Some(highlight_style) = old_highlight_id
12485                                        .and_then(|h| h.style(&cx.editor_style.syntax))
12486                                    {
12487                                        text_style = text_style.highlight(highlight_style);
12488                                    }
12489                                    div()
12490                                        .block_mouse_down()
12491                                        .pl(cx.anchor_x)
12492                                        .child(EditorElement::new(
12493                                            &rename_editor,
12494                                            EditorStyle {
12495                                                background: cx.theme().system().transparent,
12496                                                local_player: cx.editor_style.local_player,
12497                                                text: text_style,
12498                                                scrollbar_width: cx.editor_style.scrollbar_width,
12499                                                syntax: cx.editor_style.syntax.clone(),
12500                                                status: cx.editor_style.status.clone(),
12501                                                inlay_hints_style: HighlightStyle {
12502                                                    font_weight: Some(FontWeight::BOLD),
12503                                                    ..make_inlay_hints_style(cx.app)
12504                                                },
12505                                                inline_completion_styles: make_suggestion_styles(
12506                                                    cx.app,
12507                                                ),
12508                                                ..EditorStyle::default()
12509                                            },
12510                                        ))
12511                                        .into_any_element()
12512                                }
12513                            }),
12514                            priority: 0,
12515                        }],
12516                        Some(Autoscroll::fit()),
12517                        cx,
12518                    )[0];
12519                    this.pending_rename = Some(RenameState {
12520                        range,
12521                        old_name,
12522                        editor: rename_editor,
12523                        block_id,
12524                    });
12525                })?;
12526            }
12527
12528            Ok(())
12529        }))
12530    }
12531
12532    pub fn confirm_rename(
12533        &mut self,
12534        _: &ConfirmRename,
12535        window: &mut Window,
12536        cx: &mut Context<Self>,
12537    ) -> Option<Task<Result<()>>> {
12538        let rename = self.take_rename(false, window, cx)?;
12539        let workspace = self.workspace()?.downgrade();
12540        let (buffer, start) = self
12541            .buffer
12542            .read(cx)
12543            .text_anchor_for_position(rename.range.start, cx)?;
12544        let (end_buffer, _) = self
12545            .buffer
12546            .read(cx)
12547            .text_anchor_for_position(rename.range.end, cx)?;
12548        if buffer != end_buffer {
12549            return None;
12550        }
12551
12552        let old_name = rename.old_name;
12553        let new_name = rename.editor.read(cx).text(cx);
12554
12555        let rename = self.semantics_provider.as_ref()?.perform_rename(
12556            &buffer,
12557            start,
12558            new_name.clone(),
12559            cx,
12560        )?;
12561
12562        Some(cx.spawn_in(window, |editor, mut cx| async move {
12563            let project_transaction = rename.await?;
12564            Self::open_project_transaction(
12565                &editor,
12566                workspace,
12567                project_transaction,
12568                format!("Rename: {}{}", old_name, new_name),
12569                cx.clone(),
12570            )
12571            .await?;
12572
12573            editor.update(&mut cx, |editor, cx| {
12574                editor.refresh_document_highlights(cx);
12575            })?;
12576            Ok(())
12577        }))
12578    }
12579
12580    fn take_rename(
12581        &mut self,
12582        moving_cursor: bool,
12583        window: &mut Window,
12584        cx: &mut Context<Self>,
12585    ) -> Option<RenameState> {
12586        let rename = self.pending_rename.take()?;
12587        if rename.editor.focus_handle(cx).is_focused(window) {
12588            window.focus(&self.focus_handle);
12589        }
12590
12591        self.remove_blocks(
12592            [rename.block_id].into_iter().collect(),
12593            Some(Autoscroll::fit()),
12594            cx,
12595        );
12596        self.clear_highlights::<Rename>(cx);
12597        self.show_local_selections = true;
12598
12599        if moving_cursor {
12600            let cursor_in_rename_editor = rename.editor.update(cx, |editor, cx| {
12601                editor.selections.newest::<usize>(cx).head()
12602            });
12603
12604            // Update the selection to match the position of the selection inside
12605            // the rename editor.
12606            let snapshot = self.buffer.read(cx).read(cx);
12607            let rename_range = rename.range.to_offset(&snapshot);
12608            let cursor_in_editor = snapshot
12609                .clip_offset(rename_range.start + cursor_in_rename_editor, Bias::Left)
12610                .min(rename_range.end);
12611            drop(snapshot);
12612
12613            self.change_selections(None, window, cx, |s| {
12614                s.select_ranges(vec![cursor_in_editor..cursor_in_editor])
12615            });
12616        } else {
12617            self.refresh_document_highlights(cx);
12618        }
12619
12620        Some(rename)
12621    }
12622
12623    pub fn pending_rename(&self) -> Option<&RenameState> {
12624        self.pending_rename.as_ref()
12625    }
12626
12627    fn format(
12628        &mut self,
12629        _: &Format,
12630        window: &mut Window,
12631        cx: &mut Context<Self>,
12632    ) -> Option<Task<Result<()>>> {
12633        let project = match &self.project {
12634            Some(project) => project.clone(),
12635            None => return None,
12636        };
12637
12638        Some(self.perform_format(
12639            project,
12640            FormatTrigger::Manual,
12641            FormatTarget::Buffers,
12642            window,
12643            cx,
12644        ))
12645    }
12646
12647    fn format_selections(
12648        &mut self,
12649        _: &FormatSelections,
12650        window: &mut Window,
12651        cx: &mut Context<Self>,
12652    ) -> Option<Task<Result<()>>> {
12653        let project = match &self.project {
12654            Some(project) => project.clone(),
12655            None => return None,
12656        };
12657
12658        let ranges = self
12659            .selections
12660            .all_adjusted(cx)
12661            .into_iter()
12662            .map(|selection| selection.range())
12663            .collect_vec();
12664
12665        Some(self.perform_format(
12666            project,
12667            FormatTrigger::Manual,
12668            FormatTarget::Ranges(ranges),
12669            window,
12670            cx,
12671        ))
12672    }
12673
12674    fn perform_format(
12675        &mut self,
12676        project: Entity<Project>,
12677        trigger: FormatTrigger,
12678        target: FormatTarget,
12679        window: &mut Window,
12680        cx: &mut Context<Self>,
12681    ) -> Task<Result<()>> {
12682        let buffer = self.buffer.clone();
12683        let (buffers, target) = match target {
12684            FormatTarget::Buffers => {
12685                let mut buffers = buffer.read(cx).all_buffers();
12686                if trigger == FormatTrigger::Save {
12687                    buffers.retain(|buffer| buffer.read(cx).is_dirty());
12688                }
12689                (buffers, LspFormatTarget::Buffers)
12690            }
12691            FormatTarget::Ranges(selection_ranges) => {
12692                let multi_buffer = buffer.read(cx);
12693                let snapshot = multi_buffer.read(cx);
12694                let mut buffers = HashSet::default();
12695                let mut buffer_id_to_ranges: BTreeMap<BufferId, Vec<Range<text::Anchor>>> =
12696                    BTreeMap::new();
12697                for selection_range in selection_ranges {
12698                    for (buffer, buffer_range, _) in
12699                        snapshot.range_to_buffer_ranges(selection_range)
12700                    {
12701                        let buffer_id = buffer.remote_id();
12702                        let start = buffer.anchor_before(buffer_range.start);
12703                        let end = buffer.anchor_after(buffer_range.end);
12704                        buffers.insert(multi_buffer.buffer(buffer_id).unwrap());
12705                        buffer_id_to_ranges
12706                            .entry(buffer_id)
12707                            .and_modify(|buffer_ranges| buffer_ranges.push(start..end))
12708                            .or_insert_with(|| vec![start..end]);
12709                    }
12710                }
12711                (buffers, LspFormatTarget::Ranges(buffer_id_to_ranges))
12712            }
12713        };
12714
12715        let mut timeout = cx.background_executor().timer(FORMAT_TIMEOUT).fuse();
12716        let format = project.update(cx, |project, cx| {
12717            project.format(buffers, target, true, trigger, cx)
12718        });
12719
12720        cx.spawn_in(window, |_, mut cx| async move {
12721            let transaction = futures::select_biased! {
12722                () = timeout => {
12723                    log::warn!("timed out waiting for formatting");
12724                    None
12725                }
12726                transaction = format.log_err().fuse() => transaction,
12727            };
12728
12729            buffer
12730                .update(&mut cx, |buffer, cx| {
12731                    if let Some(transaction) = transaction {
12732                        if !buffer.is_singleton() {
12733                            buffer.push_transaction(&transaction.0, cx);
12734                        }
12735                    }
12736                    cx.notify();
12737                })
12738                .ok();
12739
12740            Ok(())
12741        })
12742    }
12743
12744    fn organize_imports(
12745        &mut self,
12746        _: &OrganizeImports,
12747        window: &mut Window,
12748        cx: &mut Context<Self>,
12749    ) -> Option<Task<Result<()>>> {
12750        let project = match &self.project {
12751            Some(project) => project.clone(),
12752            None => return None,
12753        };
12754        Some(self.perform_code_action_kind(
12755            project,
12756            CodeActionKind::SOURCE_ORGANIZE_IMPORTS,
12757            window,
12758            cx,
12759        ))
12760    }
12761
12762    fn perform_code_action_kind(
12763        &mut self,
12764        project: Entity<Project>,
12765        kind: CodeActionKind,
12766        window: &mut Window,
12767        cx: &mut Context<Self>,
12768    ) -> Task<Result<()>> {
12769        let buffer = self.buffer.clone();
12770        let buffers = buffer.read(cx).all_buffers();
12771        let mut timeout = cx.background_executor().timer(CODE_ACTION_TIMEOUT).fuse();
12772        let apply_action = project.update(cx, |project, cx| {
12773            project.apply_code_action_kind(buffers, kind, true, cx)
12774        });
12775        cx.spawn_in(window, |_, mut cx| async move {
12776            let transaction = futures::select_biased! {
12777                () = timeout => {
12778                    log::warn!("timed out waiting for executing code action");
12779                    None
12780                }
12781                transaction = apply_action.log_err().fuse() => transaction,
12782            };
12783            buffer
12784                .update(&mut cx, |buffer, cx| {
12785                    // check if we need this
12786                    if let Some(transaction) = transaction {
12787                        if !buffer.is_singleton() {
12788                            buffer.push_transaction(&transaction.0, cx);
12789                        }
12790                    }
12791                    cx.notify();
12792                })
12793                .ok();
12794            Ok(())
12795        })
12796    }
12797
12798    fn restart_language_server(
12799        &mut self,
12800        _: &RestartLanguageServer,
12801        _: &mut Window,
12802        cx: &mut Context<Self>,
12803    ) {
12804        if let Some(project) = self.project.clone() {
12805            self.buffer.update(cx, |multi_buffer, cx| {
12806                project.update(cx, |project, cx| {
12807                    project.restart_language_servers_for_buffers(
12808                        multi_buffer.all_buffers().into_iter().collect(),
12809                        cx,
12810                    );
12811                });
12812            })
12813        }
12814    }
12815
12816    fn cancel_language_server_work(
12817        workspace: &mut Workspace,
12818        _: &actions::CancelLanguageServerWork,
12819        _: &mut Window,
12820        cx: &mut Context<Workspace>,
12821    ) {
12822        let project = workspace.project();
12823        let buffers = workspace
12824            .active_item(cx)
12825            .and_then(|item| item.act_as::<Editor>(cx))
12826            .map_or(HashSet::default(), |editor| {
12827                editor.read(cx).buffer.read(cx).all_buffers()
12828            });
12829        project.update(cx, |project, cx| {
12830            project.cancel_language_server_work_for_buffers(buffers, cx);
12831        });
12832    }
12833
12834    fn show_character_palette(
12835        &mut self,
12836        _: &ShowCharacterPalette,
12837        window: &mut Window,
12838        _: &mut Context<Self>,
12839    ) {
12840        window.show_character_palette();
12841    }
12842
12843    fn refresh_active_diagnostics(&mut self, cx: &mut Context<Editor>) {
12844        if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
12845            let buffer = self.buffer.read(cx).snapshot(cx);
12846            let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
12847            let primary_range_end = active_diagnostics.primary_range.end.to_offset(&buffer);
12848            let is_valid = buffer
12849                .diagnostics_in_range::<usize>(primary_range_start..primary_range_end)
12850                .any(|entry| {
12851                    entry.diagnostic.is_primary
12852                        && !entry.range.is_empty()
12853                        && entry.range.start == primary_range_start
12854                        && entry.diagnostic.message == active_diagnostics.primary_message
12855                });
12856
12857            if is_valid != active_diagnostics.is_valid {
12858                active_diagnostics.is_valid = is_valid;
12859                if is_valid {
12860                    let mut new_styles = HashMap::default();
12861                    for (block_id, diagnostic) in &active_diagnostics.blocks {
12862                        new_styles.insert(
12863                            *block_id,
12864                            diagnostic_block_renderer(diagnostic.clone(), None, true),
12865                        );
12866                    }
12867                    self.display_map.update(cx, |display_map, _cx| {
12868                        display_map.replace_blocks(new_styles);
12869                    });
12870                } else {
12871                    self.dismiss_diagnostics(cx);
12872                }
12873            }
12874        }
12875    }
12876
12877    fn activate_diagnostics(
12878        &mut self,
12879        buffer_id: BufferId,
12880        group_id: usize,
12881        window: &mut Window,
12882        cx: &mut Context<Self>,
12883    ) {
12884        self.dismiss_diagnostics(cx);
12885        let snapshot = self.snapshot(window, cx);
12886        self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
12887            let buffer = self.buffer.read(cx).snapshot(cx);
12888
12889            let mut primary_range = None;
12890            let mut primary_message = None;
12891            let diagnostic_group = buffer
12892                .diagnostic_group(buffer_id, group_id)
12893                .filter_map(|entry| {
12894                    let start = entry.range.start;
12895                    let end = entry.range.end;
12896                    if snapshot.is_line_folded(MultiBufferRow(start.row))
12897                        && (start.row == end.row
12898                            || snapshot.is_line_folded(MultiBufferRow(end.row)))
12899                    {
12900                        return None;
12901                    }
12902                    if entry.diagnostic.is_primary {
12903                        primary_range = Some(entry.range.clone());
12904                        primary_message = Some(entry.diagnostic.message.clone());
12905                    }
12906                    Some(entry)
12907                })
12908                .collect::<Vec<_>>();
12909            let primary_range = primary_range?;
12910            let primary_message = primary_message?;
12911
12912            let blocks = display_map
12913                .insert_blocks(
12914                    diagnostic_group.iter().map(|entry| {
12915                        let diagnostic = entry.diagnostic.clone();
12916                        let message_height = diagnostic.message.matches('\n').count() as u32 + 1;
12917                        BlockProperties {
12918                            style: BlockStyle::Fixed,
12919                            placement: BlockPlacement::Below(
12920                                buffer.anchor_after(entry.range.start),
12921                            ),
12922                            height: message_height,
12923                            render: diagnostic_block_renderer(diagnostic, None, true),
12924                            priority: 0,
12925                        }
12926                    }),
12927                    cx,
12928                )
12929                .into_iter()
12930                .zip(diagnostic_group.into_iter().map(|entry| entry.diagnostic))
12931                .collect();
12932
12933            Some(ActiveDiagnosticGroup {
12934                primary_range: buffer.anchor_before(primary_range.start)
12935                    ..buffer.anchor_after(primary_range.end),
12936                primary_message,
12937                group_id,
12938                blocks,
12939                is_valid: true,
12940            })
12941        });
12942    }
12943
12944    fn dismiss_diagnostics(&mut self, cx: &mut Context<Self>) {
12945        if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
12946            self.display_map.update(cx, |display_map, cx| {
12947                display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx);
12948            });
12949            cx.notify();
12950        }
12951    }
12952
12953    /// Disable inline diagnostics rendering for this editor.
12954    pub fn disable_inline_diagnostics(&mut self) {
12955        self.inline_diagnostics_enabled = false;
12956        self.inline_diagnostics_update = Task::ready(());
12957        self.inline_diagnostics.clear();
12958    }
12959
12960    pub fn inline_diagnostics_enabled(&self) -> bool {
12961        self.inline_diagnostics_enabled
12962    }
12963
12964    pub fn show_inline_diagnostics(&self) -> bool {
12965        self.show_inline_diagnostics
12966    }
12967
12968    pub fn toggle_inline_diagnostics(
12969        &mut self,
12970        _: &ToggleInlineDiagnostics,
12971        window: &mut Window,
12972        cx: &mut Context<'_, Editor>,
12973    ) {
12974        self.show_inline_diagnostics = !self.show_inline_diagnostics;
12975        self.refresh_inline_diagnostics(false, window, cx);
12976    }
12977
12978    fn refresh_inline_diagnostics(
12979        &mut self,
12980        debounce: bool,
12981        window: &mut Window,
12982        cx: &mut Context<Self>,
12983    ) {
12984        if !self.inline_diagnostics_enabled || !self.show_inline_diagnostics {
12985            self.inline_diagnostics_update = Task::ready(());
12986            self.inline_diagnostics.clear();
12987            return;
12988        }
12989
12990        let debounce_ms = ProjectSettings::get_global(cx)
12991            .diagnostics
12992            .inline
12993            .update_debounce_ms;
12994        let debounce = if debounce && debounce_ms > 0 {
12995            Some(Duration::from_millis(debounce_ms))
12996        } else {
12997            None
12998        };
12999        self.inline_diagnostics_update = cx.spawn_in(window, |editor, mut cx| async move {
13000            if let Some(debounce) = debounce {
13001                cx.background_executor().timer(debounce).await;
13002            }
13003            let Some(snapshot) = editor
13004                .update(&mut cx, |editor, cx| editor.buffer().read(cx).snapshot(cx))
13005                .ok()
13006            else {
13007                return;
13008            };
13009
13010            let new_inline_diagnostics = cx
13011                .background_spawn(async move {
13012                    let mut inline_diagnostics = Vec::<(Anchor, InlineDiagnostic)>::new();
13013                    for diagnostic_entry in snapshot.diagnostics_in_range(0..snapshot.len()) {
13014                        let message = diagnostic_entry
13015                            .diagnostic
13016                            .message
13017                            .split_once('\n')
13018                            .map(|(line, _)| line)
13019                            .map(SharedString::new)
13020                            .unwrap_or_else(|| {
13021                                SharedString::from(diagnostic_entry.diagnostic.message)
13022                            });
13023                        let start_anchor = snapshot.anchor_before(diagnostic_entry.range.start);
13024                        let (Ok(i) | Err(i)) = inline_diagnostics
13025                            .binary_search_by(|(probe, _)| probe.cmp(&start_anchor, &snapshot));
13026                        inline_diagnostics.insert(
13027                            i,
13028                            (
13029                                start_anchor,
13030                                InlineDiagnostic {
13031                                    message,
13032                                    group_id: diagnostic_entry.diagnostic.group_id,
13033                                    start: diagnostic_entry.range.start.to_point(&snapshot),
13034                                    is_primary: diagnostic_entry.diagnostic.is_primary,
13035                                    severity: diagnostic_entry.diagnostic.severity,
13036                                },
13037                            ),
13038                        );
13039                    }
13040                    inline_diagnostics
13041                })
13042                .await;
13043
13044            editor
13045                .update(&mut cx, |editor, cx| {
13046                    editor.inline_diagnostics = new_inline_diagnostics;
13047                    cx.notify();
13048                })
13049                .ok();
13050        });
13051    }
13052
13053    pub fn set_selections_from_remote(
13054        &mut self,
13055        selections: Vec<Selection<Anchor>>,
13056        pending_selection: Option<Selection<Anchor>>,
13057        window: &mut Window,
13058        cx: &mut Context<Self>,
13059    ) {
13060        let old_cursor_position = self.selections.newest_anchor().head();
13061        self.selections.change_with(cx, |s| {
13062            s.select_anchors(selections);
13063            if let Some(pending_selection) = pending_selection {
13064                s.set_pending(pending_selection, SelectMode::Character);
13065            } else {
13066                s.clear_pending();
13067            }
13068        });
13069        self.selections_did_change(false, &old_cursor_position, true, window, cx);
13070    }
13071
13072    fn push_to_selection_history(&mut self) {
13073        self.selection_history.push(SelectionHistoryEntry {
13074            selections: self.selections.disjoint_anchors(),
13075            select_next_state: self.select_next_state.clone(),
13076            select_prev_state: self.select_prev_state.clone(),
13077            add_selections_state: self.add_selections_state.clone(),
13078        });
13079    }
13080
13081    pub fn transact(
13082        &mut self,
13083        window: &mut Window,
13084        cx: &mut Context<Self>,
13085        update: impl FnOnce(&mut Self, &mut Window, &mut Context<Self>),
13086    ) -> Option<TransactionId> {
13087        self.start_transaction_at(Instant::now(), window, cx);
13088        update(self, window, cx);
13089        self.end_transaction_at(Instant::now(), cx)
13090    }
13091
13092    pub fn start_transaction_at(
13093        &mut self,
13094        now: Instant,
13095        window: &mut Window,
13096        cx: &mut Context<Self>,
13097    ) {
13098        self.end_selection(window, cx);
13099        if let Some(tx_id) = self
13100            .buffer
13101            .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx))
13102        {
13103            self.selection_history
13104                .insert_transaction(tx_id, self.selections.disjoint_anchors());
13105            cx.emit(EditorEvent::TransactionBegun {
13106                transaction_id: tx_id,
13107            })
13108        }
13109    }
13110
13111    pub fn end_transaction_at(
13112        &mut self,
13113        now: Instant,
13114        cx: &mut Context<Self>,
13115    ) -> Option<TransactionId> {
13116        if let Some(transaction_id) = self
13117            .buffer
13118            .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
13119        {
13120            if let Some((_, end_selections)) =
13121                self.selection_history.transaction_mut(transaction_id)
13122            {
13123                *end_selections = Some(self.selections.disjoint_anchors());
13124            } else {
13125                log::error!("unexpectedly ended a transaction that wasn't started by this editor");
13126            }
13127
13128            cx.emit(EditorEvent::Edited { transaction_id });
13129            Some(transaction_id)
13130        } else {
13131            None
13132        }
13133    }
13134
13135    pub fn set_mark(&mut self, _: &actions::SetMark, window: &mut Window, cx: &mut Context<Self>) {
13136        if self.selection_mark_mode {
13137            self.change_selections(None, window, cx, |s| {
13138                s.move_with(|_, sel| {
13139                    sel.collapse_to(sel.head(), SelectionGoal::None);
13140                });
13141            })
13142        }
13143        self.selection_mark_mode = true;
13144        cx.notify();
13145    }
13146
13147    pub fn swap_selection_ends(
13148        &mut self,
13149        _: &actions::SwapSelectionEnds,
13150        window: &mut Window,
13151        cx: &mut Context<Self>,
13152    ) {
13153        self.change_selections(None, window, cx, |s| {
13154            s.move_with(|_, sel| {
13155                if sel.start != sel.end {
13156                    sel.reversed = !sel.reversed
13157                }
13158            });
13159        });
13160        self.request_autoscroll(Autoscroll::newest(), cx);
13161        cx.notify();
13162    }
13163
13164    pub fn toggle_fold(
13165        &mut self,
13166        _: &actions::ToggleFold,
13167        window: &mut Window,
13168        cx: &mut Context<Self>,
13169    ) {
13170        if self.is_singleton(cx) {
13171            let selection = self.selections.newest::<Point>(cx);
13172
13173            let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
13174            let range = if selection.is_empty() {
13175                let point = selection.head().to_display_point(&display_map);
13176                let start = DisplayPoint::new(point.row(), 0).to_point(&display_map);
13177                let end = DisplayPoint::new(point.row(), display_map.line_len(point.row()))
13178                    .to_point(&display_map);
13179                start..end
13180            } else {
13181                selection.range()
13182            };
13183            if display_map.folds_in_range(range).next().is_some() {
13184                self.unfold_lines(&Default::default(), window, cx)
13185            } else {
13186                self.fold(&Default::default(), window, cx)
13187            }
13188        } else {
13189            let multi_buffer_snapshot = self.buffer.read(cx).snapshot(cx);
13190            let buffer_ids: HashSet<_> = self
13191                .selections
13192                .disjoint_anchor_ranges()
13193                .flat_map(|range| multi_buffer_snapshot.buffer_ids_for_range(range))
13194                .collect();
13195
13196            let should_unfold = buffer_ids
13197                .iter()
13198                .any(|buffer_id| self.is_buffer_folded(*buffer_id, cx));
13199
13200            for buffer_id in buffer_ids {
13201                if should_unfold {
13202                    self.unfold_buffer(buffer_id, cx);
13203                } else {
13204                    self.fold_buffer(buffer_id, cx);
13205                }
13206            }
13207        }
13208    }
13209
13210    pub fn toggle_fold_recursive(
13211        &mut self,
13212        _: &actions::ToggleFoldRecursive,
13213        window: &mut Window,
13214        cx: &mut Context<Self>,
13215    ) {
13216        let selection = self.selections.newest::<Point>(cx);
13217
13218        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
13219        let range = if selection.is_empty() {
13220            let point = selection.head().to_display_point(&display_map);
13221            let start = DisplayPoint::new(point.row(), 0).to_point(&display_map);
13222            let end = DisplayPoint::new(point.row(), display_map.line_len(point.row()))
13223                .to_point(&display_map);
13224            start..end
13225        } else {
13226            selection.range()
13227        };
13228        if display_map.folds_in_range(range).next().is_some() {
13229            self.unfold_recursive(&Default::default(), window, cx)
13230        } else {
13231            self.fold_recursive(&Default::default(), window, cx)
13232        }
13233    }
13234
13235    pub fn fold(&mut self, _: &actions::Fold, window: &mut Window, cx: &mut Context<Self>) {
13236        if self.is_singleton(cx) {
13237            let mut to_fold = Vec::new();
13238            let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
13239            let selections = self.selections.all_adjusted(cx);
13240
13241            for selection in selections {
13242                let range = selection.range().sorted();
13243                let buffer_start_row = range.start.row;
13244
13245                if range.start.row != range.end.row {
13246                    let mut found = false;
13247                    let mut row = range.start.row;
13248                    while row <= range.end.row {
13249                        if let Some(crease) = display_map.crease_for_buffer_row(MultiBufferRow(row))
13250                        {
13251                            found = true;
13252                            row = crease.range().end.row + 1;
13253                            to_fold.push(crease);
13254                        } else {
13255                            row += 1
13256                        }
13257                    }
13258                    if found {
13259                        continue;
13260                    }
13261                }
13262
13263                for row in (0..=range.start.row).rev() {
13264                    if let Some(crease) = display_map.crease_for_buffer_row(MultiBufferRow(row)) {
13265                        if crease.range().end.row >= buffer_start_row {
13266                            to_fold.push(crease);
13267                            if row <= range.start.row {
13268                                break;
13269                            }
13270                        }
13271                    }
13272                }
13273            }
13274
13275            self.fold_creases(to_fold, true, window, cx);
13276        } else {
13277            let multi_buffer_snapshot = self.buffer.read(cx).snapshot(cx);
13278            let buffer_ids = self
13279                .selections
13280                .disjoint_anchor_ranges()
13281                .flat_map(|range| multi_buffer_snapshot.buffer_ids_for_range(range))
13282                .collect::<HashSet<_>>();
13283            for buffer_id in buffer_ids {
13284                self.fold_buffer(buffer_id, cx);
13285            }
13286        }
13287    }
13288
13289    fn fold_at_level(
13290        &mut self,
13291        fold_at: &FoldAtLevel,
13292        window: &mut Window,
13293        cx: &mut Context<Self>,
13294    ) {
13295        if !self.buffer.read(cx).is_singleton() {
13296            return;
13297        }
13298
13299        let fold_at_level = fold_at.0;
13300        let snapshot = self.buffer.read(cx).snapshot(cx);
13301        let mut to_fold = Vec::new();
13302        let mut stack = vec![(0, snapshot.max_row().0, 1)];
13303
13304        while let Some((mut start_row, end_row, current_level)) = stack.pop() {
13305            while start_row < end_row {
13306                match self
13307                    .snapshot(window, cx)
13308                    .crease_for_buffer_row(MultiBufferRow(start_row))
13309                {
13310                    Some(crease) => {
13311                        let nested_start_row = crease.range().start.row + 1;
13312                        let nested_end_row = crease.range().end.row;
13313
13314                        if current_level < fold_at_level {
13315                            stack.push((nested_start_row, nested_end_row, current_level + 1));
13316                        } else if current_level == fold_at_level {
13317                            to_fold.push(crease);
13318                        }
13319
13320                        start_row = nested_end_row + 1;
13321                    }
13322                    None => start_row += 1,
13323                }
13324            }
13325        }
13326
13327        self.fold_creases(to_fold, true, window, cx);
13328    }
13329
13330    pub fn fold_all(&mut self, _: &actions::FoldAll, window: &mut Window, cx: &mut Context<Self>) {
13331        if self.buffer.read(cx).is_singleton() {
13332            let mut fold_ranges = Vec::new();
13333            let snapshot = self.buffer.read(cx).snapshot(cx);
13334
13335            for row in 0..snapshot.max_row().0 {
13336                if let Some(foldable_range) = self
13337                    .snapshot(window, cx)
13338                    .crease_for_buffer_row(MultiBufferRow(row))
13339                {
13340                    fold_ranges.push(foldable_range);
13341                }
13342            }
13343
13344            self.fold_creases(fold_ranges, true, window, cx);
13345        } else {
13346            self.toggle_fold_multiple_buffers = cx.spawn_in(window, |editor, mut cx| async move {
13347                editor
13348                    .update_in(&mut cx, |editor, _, cx| {
13349                        for buffer_id in editor.buffer.read(cx).excerpt_buffer_ids() {
13350                            editor.fold_buffer(buffer_id, cx);
13351                        }
13352                    })
13353                    .ok();
13354            });
13355        }
13356    }
13357
13358    pub fn fold_function_bodies(
13359        &mut self,
13360        _: &actions::FoldFunctionBodies,
13361        window: &mut Window,
13362        cx: &mut Context<Self>,
13363    ) {
13364        let snapshot = self.buffer.read(cx).snapshot(cx);
13365
13366        let ranges = snapshot
13367            .text_object_ranges(0..snapshot.len(), TreeSitterOptions::default())
13368            .filter_map(|(range, obj)| (obj == TextObject::InsideFunction).then_some(range))
13369            .collect::<Vec<_>>();
13370
13371        let creases = ranges
13372            .into_iter()
13373            .map(|range| Crease::simple(range, self.display_map.read(cx).fold_placeholder.clone()))
13374            .collect();
13375
13376        self.fold_creases(creases, true, window, cx);
13377    }
13378
13379    pub fn fold_recursive(
13380        &mut self,
13381        _: &actions::FoldRecursive,
13382        window: &mut Window,
13383        cx: &mut Context<Self>,
13384    ) {
13385        let mut to_fold = Vec::new();
13386        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
13387        let selections = self.selections.all_adjusted(cx);
13388
13389        for selection in selections {
13390            let range = selection.range().sorted();
13391            let buffer_start_row = range.start.row;
13392
13393            if range.start.row != range.end.row {
13394                let mut found = false;
13395                for row in range.start.row..=range.end.row {
13396                    if let Some(crease) = display_map.crease_for_buffer_row(MultiBufferRow(row)) {
13397                        found = true;
13398                        to_fold.push(crease);
13399                    }
13400                }
13401                if found {
13402                    continue;
13403                }
13404            }
13405
13406            for row in (0..=range.start.row).rev() {
13407                if let Some(crease) = display_map.crease_for_buffer_row(MultiBufferRow(row)) {
13408                    if crease.range().end.row >= buffer_start_row {
13409                        to_fold.push(crease);
13410                    } else {
13411                        break;
13412                    }
13413                }
13414            }
13415        }
13416
13417        self.fold_creases(to_fold, true, window, cx);
13418    }
13419
13420    pub fn fold_at(&mut self, fold_at: &FoldAt, window: &mut Window, cx: &mut Context<Self>) {
13421        let buffer_row = fold_at.buffer_row;
13422        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
13423
13424        if let Some(crease) = display_map.crease_for_buffer_row(buffer_row) {
13425            let autoscroll = self
13426                .selections
13427                .all::<Point>(cx)
13428                .iter()
13429                .any(|selection| crease.range().overlaps(&selection.range()));
13430
13431            self.fold_creases(vec![crease], autoscroll, window, cx);
13432        }
13433    }
13434
13435    pub fn unfold_lines(&mut self, _: &UnfoldLines, _window: &mut Window, cx: &mut Context<Self>) {
13436        if self.is_singleton(cx) {
13437            let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
13438            let buffer = &display_map.buffer_snapshot;
13439            let selections = self.selections.all::<Point>(cx);
13440            let ranges = selections
13441                .iter()
13442                .map(|s| {
13443                    let range = s.display_range(&display_map).sorted();
13444                    let mut start = range.start.to_point(&display_map);
13445                    let mut end = range.end.to_point(&display_map);
13446                    start.column = 0;
13447                    end.column = buffer.line_len(MultiBufferRow(end.row));
13448                    start..end
13449                })
13450                .collect::<Vec<_>>();
13451
13452            self.unfold_ranges(&ranges, true, true, cx);
13453        } else {
13454            let multi_buffer_snapshot = self.buffer.read(cx).snapshot(cx);
13455            let buffer_ids = self
13456                .selections
13457                .disjoint_anchor_ranges()
13458                .flat_map(|range| multi_buffer_snapshot.buffer_ids_for_range(range))
13459                .collect::<HashSet<_>>();
13460            for buffer_id in buffer_ids {
13461                self.unfold_buffer(buffer_id, cx);
13462            }
13463        }
13464    }
13465
13466    pub fn unfold_recursive(
13467        &mut self,
13468        _: &UnfoldRecursive,
13469        _window: &mut Window,
13470        cx: &mut Context<Self>,
13471    ) {
13472        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
13473        let selections = self.selections.all::<Point>(cx);
13474        let ranges = selections
13475            .iter()
13476            .map(|s| {
13477                let mut range = s.display_range(&display_map).sorted();
13478                *range.start.column_mut() = 0;
13479                *range.end.column_mut() = display_map.line_len(range.end.row());
13480                let start = range.start.to_point(&display_map);
13481                let end = range.end.to_point(&display_map);
13482                start..end
13483            })
13484            .collect::<Vec<_>>();
13485
13486        self.unfold_ranges(&ranges, true, true, cx);
13487    }
13488
13489    pub fn unfold_at(
13490        &mut self,
13491        unfold_at: &UnfoldAt,
13492        _window: &mut Window,
13493        cx: &mut Context<Self>,
13494    ) {
13495        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
13496
13497        let intersection_range = Point::new(unfold_at.buffer_row.0, 0)
13498            ..Point::new(
13499                unfold_at.buffer_row.0,
13500                display_map.buffer_snapshot.line_len(unfold_at.buffer_row),
13501            );
13502
13503        let autoscroll = self
13504            .selections
13505            .all::<Point>(cx)
13506            .iter()
13507            .any(|selection| RangeExt::overlaps(&selection.range(), &intersection_range));
13508
13509        self.unfold_ranges(&[intersection_range], true, autoscroll, cx);
13510    }
13511
13512    pub fn unfold_all(
13513        &mut self,
13514        _: &actions::UnfoldAll,
13515        _window: &mut Window,
13516        cx: &mut Context<Self>,
13517    ) {
13518        if self.buffer.read(cx).is_singleton() {
13519            let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
13520            self.unfold_ranges(&[0..display_map.buffer_snapshot.len()], true, true, cx);
13521        } else {
13522            self.toggle_fold_multiple_buffers = cx.spawn(|editor, mut cx| async move {
13523                editor
13524                    .update(&mut cx, |editor, cx| {
13525                        for buffer_id in editor.buffer.read(cx).excerpt_buffer_ids() {
13526                            editor.unfold_buffer(buffer_id, cx);
13527                        }
13528                    })
13529                    .ok();
13530            });
13531        }
13532    }
13533
13534    pub fn fold_selected_ranges(
13535        &mut self,
13536        _: &FoldSelectedRanges,
13537        window: &mut Window,
13538        cx: &mut Context<Self>,
13539    ) {
13540        let selections = self.selections.all::<Point>(cx);
13541        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
13542        let line_mode = self.selections.line_mode;
13543        let ranges = selections
13544            .into_iter()
13545            .map(|s| {
13546                if line_mode {
13547                    let start = Point::new(s.start.row, 0);
13548                    let end = Point::new(
13549                        s.end.row,
13550                        display_map
13551                            .buffer_snapshot
13552                            .line_len(MultiBufferRow(s.end.row)),
13553                    );
13554                    Crease::simple(start..end, display_map.fold_placeholder.clone())
13555                } else {
13556                    Crease::simple(s.start..s.end, display_map.fold_placeholder.clone())
13557                }
13558            })
13559            .collect::<Vec<_>>();
13560        self.fold_creases(ranges, true, window, cx);
13561    }
13562
13563    pub fn fold_ranges<T: ToOffset + Clone>(
13564        &mut self,
13565        ranges: Vec<Range<T>>,
13566        auto_scroll: bool,
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        let ranges = ranges
13572            .into_iter()
13573            .map(|r| Crease::simple(r, display_map.fold_placeholder.clone()))
13574            .collect::<Vec<_>>();
13575        self.fold_creases(ranges, auto_scroll, window, cx);
13576    }
13577
13578    pub fn fold_creases<T: ToOffset + Clone>(
13579        &mut self,
13580        creases: Vec<Crease<T>>,
13581        auto_scroll: bool,
13582        window: &mut Window,
13583        cx: &mut Context<Self>,
13584    ) {
13585        if creases.is_empty() {
13586            return;
13587        }
13588
13589        let mut buffers_affected = HashSet::default();
13590        let multi_buffer = self.buffer().read(cx);
13591        for crease in &creases {
13592            if let Some((_, buffer, _)) =
13593                multi_buffer.excerpt_containing(crease.range().start.clone(), cx)
13594            {
13595                buffers_affected.insert(buffer.read(cx).remote_id());
13596            };
13597        }
13598
13599        self.display_map.update(cx, |map, cx| map.fold(creases, cx));
13600
13601        if auto_scroll {
13602            self.request_autoscroll(Autoscroll::fit(), cx);
13603        }
13604
13605        cx.notify();
13606
13607        if let Some(active_diagnostics) = self.active_diagnostics.take() {
13608            // Clear diagnostics block when folding a range that contains it.
13609            let snapshot = self.snapshot(window, cx);
13610            if snapshot.intersects_fold(active_diagnostics.primary_range.start) {
13611                drop(snapshot);
13612                self.active_diagnostics = Some(active_diagnostics);
13613                self.dismiss_diagnostics(cx);
13614            } else {
13615                self.active_diagnostics = Some(active_diagnostics);
13616            }
13617        }
13618
13619        self.scrollbar_marker_state.dirty = true;
13620    }
13621
13622    /// Removes any folds whose ranges intersect any of the given ranges.
13623    pub fn unfold_ranges<T: ToOffset + Clone>(
13624        &mut self,
13625        ranges: &[Range<T>],
13626        inclusive: bool,
13627        auto_scroll: bool,
13628        cx: &mut Context<Self>,
13629    ) {
13630        self.remove_folds_with(ranges, auto_scroll, cx, |map, cx| {
13631            map.unfold_intersecting(ranges.iter().cloned(), inclusive, cx)
13632        });
13633    }
13634
13635    pub fn fold_buffer(&mut self, buffer_id: BufferId, cx: &mut Context<Self>) {
13636        if self.buffer().read(cx).is_singleton() || self.is_buffer_folded(buffer_id, cx) {
13637            return;
13638        }
13639        let folded_excerpts = self.buffer().read(cx).excerpts_for_buffer(buffer_id, cx);
13640        self.display_map.update(cx, |display_map, cx| {
13641            display_map.fold_buffers([buffer_id], cx)
13642        });
13643        cx.emit(EditorEvent::BufferFoldToggled {
13644            ids: folded_excerpts.iter().map(|&(id, _)| id).collect(),
13645            folded: true,
13646        });
13647        cx.notify();
13648    }
13649
13650    pub fn unfold_buffer(&mut self, buffer_id: BufferId, cx: &mut Context<Self>) {
13651        if self.buffer().read(cx).is_singleton() || !self.is_buffer_folded(buffer_id, cx) {
13652            return;
13653        }
13654        let unfolded_excerpts = self.buffer().read(cx).excerpts_for_buffer(buffer_id, cx);
13655        self.display_map.update(cx, |display_map, cx| {
13656            display_map.unfold_buffers([buffer_id], cx);
13657        });
13658        cx.emit(EditorEvent::BufferFoldToggled {
13659            ids: unfolded_excerpts.iter().map(|&(id, _)| id).collect(),
13660            folded: false,
13661        });
13662        cx.notify();
13663    }
13664
13665    pub fn is_buffer_folded(&self, buffer: BufferId, cx: &App) -> bool {
13666        self.display_map.read(cx).is_buffer_folded(buffer)
13667    }
13668
13669    pub fn folded_buffers<'a>(&self, cx: &'a App) -> &'a HashSet<BufferId> {
13670        self.display_map.read(cx).folded_buffers()
13671    }
13672
13673    /// Removes any folds with the given ranges.
13674    pub fn remove_folds_with_type<T: ToOffset + Clone>(
13675        &mut self,
13676        ranges: &[Range<T>],
13677        type_id: TypeId,
13678        auto_scroll: bool,
13679        cx: &mut Context<Self>,
13680    ) {
13681        self.remove_folds_with(ranges, auto_scroll, cx, |map, cx| {
13682            map.remove_folds_with_type(ranges.iter().cloned(), type_id, cx)
13683        });
13684    }
13685
13686    fn remove_folds_with<T: ToOffset + Clone>(
13687        &mut self,
13688        ranges: &[Range<T>],
13689        auto_scroll: bool,
13690        cx: &mut Context<Self>,
13691        update: impl FnOnce(&mut DisplayMap, &mut Context<DisplayMap>),
13692    ) {
13693        if ranges.is_empty() {
13694            return;
13695        }
13696
13697        let mut buffers_affected = HashSet::default();
13698        let multi_buffer = self.buffer().read(cx);
13699        for range in ranges {
13700            if let Some((_, buffer, _)) = multi_buffer.excerpt_containing(range.start.clone(), cx) {
13701                buffers_affected.insert(buffer.read(cx).remote_id());
13702            };
13703        }
13704
13705        self.display_map.update(cx, update);
13706
13707        if auto_scroll {
13708            self.request_autoscroll(Autoscroll::fit(), cx);
13709        }
13710
13711        cx.notify();
13712        self.scrollbar_marker_state.dirty = true;
13713        self.active_indent_guides_state.dirty = true;
13714    }
13715
13716    pub fn default_fold_placeholder(&self, cx: &App) -> FoldPlaceholder {
13717        self.display_map.read(cx).fold_placeholder.clone()
13718    }
13719
13720    pub fn set_expand_all_diff_hunks(&mut self, cx: &mut App) {
13721        self.buffer.update(cx, |buffer, cx| {
13722            buffer.set_all_diff_hunks_expanded(cx);
13723        });
13724    }
13725
13726    pub fn expand_all_diff_hunks(
13727        &mut self,
13728        _: &ExpandAllDiffHunks,
13729        _window: &mut Window,
13730        cx: &mut Context<Self>,
13731    ) {
13732        self.buffer.update(cx, |buffer, cx| {
13733            buffer.expand_diff_hunks(vec![Anchor::min()..Anchor::max()], cx)
13734        });
13735    }
13736
13737    pub fn toggle_selected_diff_hunks(
13738        &mut self,
13739        _: &ToggleSelectedDiffHunks,
13740        _window: &mut Window,
13741        cx: &mut Context<Self>,
13742    ) {
13743        let ranges: Vec<_> = self.selections.disjoint.iter().map(|s| s.range()).collect();
13744        self.toggle_diff_hunks_in_ranges(ranges, cx);
13745    }
13746
13747    pub fn diff_hunks_in_ranges<'a>(
13748        &'a self,
13749        ranges: &'a [Range<Anchor>],
13750        buffer: &'a MultiBufferSnapshot,
13751    ) -> impl 'a + Iterator<Item = MultiBufferDiffHunk> {
13752        ranges.iter().flat_map(move |range| {
13753            let end_excerpt_id = range.end.excerpt_id;
13754            let range = range.to_point(buffer);
13755            let mut peek_end = range.end;
13756            if range.end.row < buffer.max_row().0 {
13757                peek_end = Point::new(range.end.row + 1, 0);
13758            }
13759            buffer
13760                .diff_hunks_in_range(range.start..peek_end)
13761                .filter(move |hunk| hunk.excerpt_id.cmp(&end_excerpt_id, buffer).is_le())
13762        })
13763    }
13764
13765    pub fn has_stageable_diff_hunks_in_ranges(
13766        &self,
13767        ranges: &[Range<Anchor>],
13768        snapshot: &MultiBufferSnapshot,
13769    ) -> bool {
13770        let mut hunks = self.diff_hunks_in_ranges(ranges, &snapshot);
13771        hunks.any(|hunk| hunk.status().has_secondary_hunk())
13772    }
13773
13774    pub fn toggle_staged_selected_diff_hunks(
13775        &mut self,
13776        _: &::git::ToggleStaged,
13777        _: &mut Window,
13778        cx: &mut Context<Self>,
13779    ) {
13780        let snapshot = self.buffer.read(cx).snapshot(cx);
13781        let ranges: Vec<_> = self.selections.disjoint.iter().map(|s| s.range()).collect();
13782        let stage = self.has_stageable_diff_hunks_in_ranges(&ranges, &snapshot);
13783        self.stage_or_unstage_diff_hunks(stage, ranges, cx);
13784    }
13785
13786    pub fn stage_and_next(
13787        &mut self,
13788        _: &::git::StageAndNext,
13789        window: &mut Window,
13790        cx: &mut Context<Self>,
13791    ) {
13792        self.do_stage_or_unstage_and_next(true, window, cx);
13793    }
13794
13795    pub fn unstage_and_next(
13796        &mut self,
13797        _: &::git::UnstageAndNext,
13798        window: &mut Window,
13799        cx: &mut Context<Self>,
13800    ) {
13801        self.do_stage_or_unstage_and_next(false, window, cx);
13802    }
13803
13804    pub fn stage_or_unstage_diff_hunks(
13805        &mut self,
13806        stage: bool,
13807        ranges: Vec<Range<Anchor>>,
13808        cx: &mut Context<Self>,
13809    ) {
13810        let task = self.save_buffers_for_ranges_if_needed(&ranges, cx);
13811        cx.spawn(|this, mut cx| async move {
13812            task.await?;
13813            this.update(&mut cx, |this, cx| {
13814                let snapshot = this.buffer.read(cx).snapshot(cx);
13815                let chunk_by = this
13816                    .diff_hunks_in_ranges(&ranges, &snapshot)
13817                    .chunk_by(|hunk| hunk.buffer_id);
13818                for (buffer_id, hunks) in &chunk_by {
13819                    this.do_stage_or_unstage(stage, buffer_id, hunks, cx);
13820                }
13821            })
13822        })
13823        .detach_and_log_err(cx);
13824    }
13825
13826    fn save_buffers_for_ranges_if_needed(
13827        &mut self,
13828        ranges: &[Range<Anchor>],
13829        cx: &mut Context<'_, Editor>,
13830    ) -> Task<Result<()>> {
13831        let multibuffer = self.buffer.read(cx);
13832        let snapshot = multibuffer.read(cx);
13833        let buffer_ids: HashSet<_> = ranges
13834            .iter()
13835            .flat_map(|range| snapshot.buffer_ids_for_range(range.clone()))
13836            .collect();
13837        drop(snapshot);
13838
13839        let mut buffers = HashSet::default();
13840        for buffer_id in buffer_ids {
13841            if let Some(buffer_entity) = multibuffer.buffer(buffer_id) {
13842                let buffer = buffer_entity.read(cx);
13843                if buffer.file().is_some_and(|file| file.disk_state().exists()) && buffer.is_dirty()
13844                {
13845                    buffers.insert(buffer_entity);
13846                }
13847            }
13848        }
13849
13850        if let Some(project) = &self.project {
13851            project.update(cx, |project, cx| project.save_buffers(buffers, cx))
13852        } else {
13853            Task::ready(Ok(()))
13854        }
13855    }
13856
13857    fn do_stage_or_unstage_and_next(
13858        &mut self,
13859        stage: bool,
13860        window: &mut Window,
13861        cx: &mut Context<Self>,
13862    ) {
13863        let ranges = self.selections.disjoint_anchor_ranges().collect::<Vec<_>>();
13864
13865        if ranges.iter().any(|range| range.start != range.end) {
13866            self.stage_or_unstage_diff_hunks(stage, ranges, cx);
13867            return;
13868        }
13869
13870        self.stage_or_unstage_diff_hunks(stage, ranges, cx);
13871        let snapshot = self.snapshot(window, cx);
13872        let position = self.selections.newest::<Point>(cx).head();
13873        let mut row = snapshot
13874            .buffer_snapshot
13875            .diff_hunks_in_range(position..snapshot.buffer_snapshot.max_point())
13876            .find(|hunk| hunk.row_range.start.0 > position.row)
13877            .map(|hunk| hunk.row_range.start);
13878
13879        let all_diff_hunks_expanded = self.buffer().read(cx).all_diff_hunks_expanded();
13880        // Outside of the project diff editor, wrap around to the beginning.
13881        if !all_diff_hunks_expanded {
13882            row = row.or_else(|| {
13883                snapshot
13884                    .buffer_snapshot
13885                    .diff_hunks_in_range(Point::zero()..position)
13886                    .find(|hunk| hunk.row_range.end.0 < position.row)
13887                    .map(|hunk| hunk.row_range.start)
13888            });
13889        }
13890
13891        if let Some(row) = row {
13892            let destination = Point::new(row.0, 0);
13893            let autoscroll = Autoscroll::center();
13894
13895            self.unfold_ranges(&[destination..destination], false, false, cx);
13896            self.change_selections(Some(autoscroll), window, cx, |s| {
13897                s.select_ranges([destination..destination]);
13898            });
13899        } else if all_diff_hunks_expanded {
13900            window.dispatch_action(::git::ExpandCommitEditor.boxed_clone(), cx);
13901        }
13902    }
13903
13904    fn do_stage_or_unstage(
13905        &self,
13906        stage: bool,
13907        buffer_id: BufferId,
13908        hunks: impl Iterator<Item = MultiBufferDiffHunk>,
13909        cx: &mut App,
13910    ) -> Option<()> {
13911        let project = self.project.as_ref()?;
13912        let buffer = project.read(cx).buffer_for_id(buffer_id, cx)?;
13913        let diff = self.buffer.read(cx).diff_for(buffer_id)?;
13914        let buffer_snapshot = buffer.read(cx).snapshot();
13915        let file_exists = buffer_snapshot
13916            .file()
13917            .is_some_and(|file| file.disk_state().exists());
13918        diff.update(cx, |diff, cx| {
13919            diff.stage_or_unstage_hunks(
13920                stage,
13921                &hunks
13922                    .map(|hunk| buffer_diff::DiffHunk {
13923                        buffer_range: hunk.buffer_range,
13924                        diff_base_byte_range: hunk.diff_base_byte_range,
13925                        secondary_status: hunk.secondary_status,
13926                        range: Point::zero()..Point::zero(), // unused
13927                    })
13928                    .collect::<Vec<_>>(),
13929                &buffer_snapshot,
13930                file_exists,
13931                cx,
13932            )
13933        });
13934        None
13935    }
13936
13937    pub fn expand_selected_diff_hunks(&mut self, cx: &mut Context<Self>) {
13938        let ranges: Vec<_> = self.selections.disjoint.iter().map(|s| s.range()).collect();
13939        self.buffer
13940            .update(cx, |buffer, cx| buffer.expand_diff_hunks(ranges, cx))
13941    }
13942
13943    pub fn clear_expanded_diff_hunks(&mut self, cx: &mut Context<Self>) -> bool {
13944        self.buffer.update(cx, |buffer, cx| {
13945            let ranges = vec![Anchor::min()..Anchor::max()];
13946            if !buffer.all_diff_hunks_expanded()
13947                && buffer.has_expanded_diff_hunks_in_ranges(&ranges, cx)
13948            {
13949                buffer.collapse_diff_hunks(ranges, cx);
13950                true
13951            } else {
13952                false
13953            }
13954        })
13955    }
13956
13957    fn toggle_diff_hunks_in_ranges(
13958        &mut self,
13959        ranges: Vec<Range<Anchor>>,
13960        cx: &mut Context<'_, Editor>,
13961    ) {
13962        self.buffer.update(cx, |buffer, cx| {
13963            let expand = !buffer.has_expanded_diff_hunks_in_ranges(&ranges, cx);
13964            buffer.expand_or_collapse_diff_hunks(ranges, expand, cx);
13965        })
13966    }
13967
13968    fn toggle_single_diff_hunk(&mut self, range: Range<Anchor>, cx: &mut Context<Self>) {
13969        self.buffer.update(cx, |buffer, cx| {
13970            let snapshot = buffer.snapshot(cx);
13971            let excerpt_id = range.end.excerpt_id;
13972            let point_range = range.to_point(&snapshot);
13973            let expand = !buffer.single_hunk_is_expanded(range, cx);
13974            buffer.expand_or_collapse_diff_hunks_inner([(point_range, excerpt_id)], expand, cx);
13975        })
13976    }
13977
13978    pub(crate) fn apply_all_diff_hunks(
13979        &mut self,
13980        _: &ApplyAllDiffHunks,
13981        window: &mut Window,
13982        cx: &mut Context<Self>,
13983    ) {
13984        let buffers = self.buffer.read(cx).all_buffers();
13985        for branch_buffer in buffers {
13986            branch_buffer.update(cx, |branch_buffer, cx| {
13987                branch_buffer.merge_into_base(Vec::new(), cx);
13988            });
13989        }
13990
13991        if let Some(project) = self.project.clone() {
13992            self.save(true, project, window, cx).detach_and_log_err(cx);
13993        }
13994    }
13995
13996    pub(crate) fn apply_selected_diff_hunks(
13997        &mut self,
13998        _: &ApplyDiffHunk,
13999        window: &mut Window,
14000        cx: &mut Context<Self>,
14001    ) {
14002        let snapshot = self.snapshot(window, cx);
14003        let hunks = snapshot.hunks_for_ranges(self.selections.ranges(cx));
14004        let mut ranges_by_buffer = HashMap::default();
14005        self.transact(window, cx, |editor, _window, cx| {
14006            for hunk in hunks {
14007                if let Some(buffer) = editor.buffer.read(cx).buffer(hunk.buffer_id) {
14008                    ranges_by_buffer
14009                        .entry(buffer.clone())
14010                        .or_insert_with(Vec::new)
14011                        .push(hunk.buffer_range.to_offset(buffer.read(cx)));
14012                }
14013            }
14014
14015            for (buffer, ranges) in ranges_by_buffer {
14016                buffer.update(cx, |buffer, cx| {
14017                    buffer.merge_into_base(ranges, cx);
14018                });
14019            }
14020        });
14021
14022        if let Some(project) = self.project.clone() {
14023            self.save(true, project, window, cx).detach_and_log_err(cx);
14024        }
14025    }
14026
14027    pub fn set_gutter_hovered(&mut self, hovered: bool, cx: &mut Context<Self>) {
14028        if hovered != self.gutter_hovered {
14029            self.gutter_hovered = hovered;
14030            cx.notify();
14031        }
14032    }
14033
14034    pub fn insert_blocks(
14035        &mut self,
14036        blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
14037        autoscroll: Option<Autoscroll>,
14038        cx: &mut Context<Self>,
14039    ) -> Vec<CustomBlockId> {
14040        let blocks = self
14041            .display_map
14042            .update(cx, |display_map, cx| display_map.insert_blocks(blocks, cx));
14043        if let Some(autoscroll) = autoscroll {
14044            self.request_autoscroll(autoscroll, cx);
14045        }
14046        cx.notify();
14047        blocks
14048    }
14049
14050    pub fn resize_blocks(
14051        &mut self,
14052        heights: HashMap<CustomBlockId, u32>,
14053        autoscroll: Option<Autoscroll>,
14054        cx: &mut Context<Self>,
14055    ) {
14056        self.display_map
14057            .update(cx, |display_map, cx| display_map.resize_blocks(heights, cx));
14058        if let Some(autoscroll) = autoscroll {
14059            self.request_autoscroll(autoscroll, cx);
14060        }
14061        cx.notify();
14062    }
14063
14064    pub fn replace_blocks(
14065        &mut self,
14066        renderers: HashMap<CustomBlockId, RenderBlock>,
14067        autoscroll: Option<Autoscroll>,
14068        cx: &mut Context<Self>,
14069    ) {
14070        self.display_map
14071            .update(cx, |display_map, _cx| display_map.replace_blocks(renderers));
14072        if let Some(autoscroll) = autoscroll {
14073            self.request_autoscroll(autoscroll, cx);
14074        }
14075        cx.notify();
14076    }
14077
14078    pub fn remove_blocks(
14079        &mut self,
14080        block_ids: HashSet<CustomBlockId>,
14081        autoscroll: Option<Autoscroll>,
14082        cx: &mut Context<Self>,
14083    ) {
14084        self.display_map.update(cx, |display_map, cx| {
14085            display_map.remove_blocks(block_ids, cx)
14086        });
14087        if let Some(autoscroll) = autoscroll {
14088            self.request_autoscroll(autoscroll, cx);
14089        }
14090        cx.notify();
14091    }
14092
14093    pub fn row_for_block(
14094        &self,
14095        block_id: CustomBlockId,
14096        cx: &mut Context<Self>,
14097    ) -> Option<DisplayRow> {
14098        self.display_map
14099            .update(cx, |map, cx| map.row_for_block(block_id, cx))
14100    }
14101
14102    pub(crate) fn set_focused_block(&mut self, focused_block: FocusedBlock) {
14103        self.focused_block = Some(focused_block);
14104    }
14105
14106    pub(crate) fn take_focused_block(&mut self) -> Option<FocusedBlock> {
14107        self.focused_block.take()
14108    }
14109
14110    pub fn insert_creases(
14111        &mut self,
14112        creases: impl IntoIterator<Item = Crease<Anchor>>,
14113        cx: &mut Context<Self>,
14114    ) -> Vec<CreaseId> {
14115        self.display_map
14116            .update(cx, |map, cx| map.insert_creases(creases, cx))
14117    }
14118
14119    pub fn remove_creases(
14120        &mut self,
14121        ids: impl IntoIterator<Item = CreaseId>,
14122        cx: &mut Context<Self>,
14123    ) {
14124        self.display_map
14125            .update(cx, |map, cx| map.remove_creases(ids, cx));
14126    }
14127
14128    pub fn longest_row(&self, cx: &mut App) -> DisplayRow {
14129        self.display_map
14130            .update(cx, |map, cx| map.snapshot(cx))
14131            .longest_row()
14132    }
14133
14134    pub fn max_point(&self, cx: &mut App) -> DisplayPoint {
14135        self.display_map
14136            .update(cx, |map, cx| map.snapshot(cx))
14137            .max_point()
14138    }
14139
14140    pub fn text(&self, cx: &App) -> String {
14141        self.buffer.read(cx).read(cx).text()
14142    }
14143
14144    pub fn is_empty(&self, cx: &App) -> bool {
14145        self.buffer.read(cx).read(cx).is_empty()
14146    }
14147
14148    pub fn text_option(&self, cx: &App) -> Option<String> {
14149        let text = self.text(cx);
14150        let text = text.trim();
14151
14152        if text.is_empty() {
14153            return None;
14154        }
14155
14156        Some(text.to_string())
14157    }
14158
14159    pub fn set_text(
14160        &mut self,
14161        text: impl Into<Arc<str>>,
14162        window: &mut Window,
14163        cx: &mut Context<Self>,
14164    ) {
14165        self.transact(window, cx, |this, _, cx| {
14166            this.buffer
14167                .read(cx)
14168                .as_singleton()
14169                .expect("you can only call set_text on editors for singleton buffers")
14170                .update(cx, |buffer, cx| buffer.set_text(text, cx));
14171        });
14172    }
14173
14174    pub fn display_text(&self, cx: &mut App) -> String {
14175        self.display_map
14176            .update(cx, |map, cx| map.snapshot(cx))
14177            .text()
14178    }
14179
14180    pub fn wrap_guides(&self, cx: &App) -> SmallVec<[(usize, bool); 2]> {
14181        let mut wrap_guides = smallvec::smallvec![];
14182
14183        if self.show_wrap_guides == Some(false) {
14184            return wrap_guides;
14185        }
14186
14187        let settings = self.buffer.read(cx).language_settings(cx);
14188        if settings.show_wrap_guides {
14189            match self.soft_wrap_mode(cx) {
14190                SoftWrap::Column(soft_wrap) => {
14191                    wrap_guides.push((soft_wrap as usize, true));
14192                }
14193                SoftWrap::Bounded(soft_wrap) => {
14194                    wrap_guides.push((soft_wrap as usize, true));
14195                }
14196                SoftWrap::GitDiff | SoftWrap::None | SoftWrap::EditorWidth => {}
14197            }
14198            wrap_guides.extend(settings.wrap_guides.iter().map(|guide| (*guide, false)))
14199        }
14200
14201        wrap_guides
14202    }
14203
14204    pub fn soft_wrap_mode(&self, cx: &App) -> SoftWrap {
14205        let settings = self.buffer.read(cx).language_settings(cx);
14206        let mode = self.soft_wrap_mode_override.unwrap_or(settings.soft_wrap);
14207        match mode {
14208            language_settings::SoftWrap::PreferLine | language_settings::SoftWrap::None => {
14209                SoftWrap::None
14210            }
14211            language_settings::SoftWrap::EditorWidth => SoftWrap::EditorWidth,
14212            language_settings::SoftWrap::PreferredLineLength => {
14213                SoftWrap::Column(settings.preferred_line_length)
14214            }
14215            language_settings::SoftWrap::Bounded => {
14216                SoftWrap::Bounded(settings.preferred_line_length)
14217            }
14218        }
14219    }
14220
14221    pub fn set_soft_wrap_mode(
14222        &mut self,
14223        mode: language_settings::SoftWrap,
14224
14225        cx: &mut Context<Self>,
14226    ) {
14227        self.soft_wrap_mode_override = Some(mode);
14228        cx.notify();
14229    }
14230
14231    pub fn set_hard_wrap(&mut self, hard_wrap: Option<usize>, cx: &mut Context<Self>) {
14232        self.hard_wrap = hard_wrap;
14233        cx.notify();
14234    }
14235
14236    pub fn set_text_style_refinement(&mut self, style: TextStyleRefinement) {
14237        self.text_style_refinement = Some(style);
14238    }
14239
14240    /// called by the Element so we know what style we were most recently rendered with.
14241    pub(crate) fn set_style(
14242        &mut self,
14243        style: EditorStyle,
14244        window: &mut Window,
14245        cx: &mut Context<Self>,
14246    ) {
14247        let rem_size = window.rem_size();
14248        self.display_map.update(cx, |map, cx| {
14249            map.set_font(
14250                style.text.font(),
14251                style.text.font_size.to_pixels(rem_size),
14252                cx,
14253            )
14254        });
14255        self.style = Some(style);
14256    }
14257
14258    pub fn style(&self) -> Option<&EditorStyle> {
14259        self.style.as_ref()
14260    }
14261
14262    // Called by the element. This method is not designed to be called outside of the editor
14263    // element's layout code because it does not notify when rewrapping is computed synchronously.
14264    pub(crate) fn set_wrap_width(&self, width: Option<Pixels>, cx: &mut App) -> bool {
14265        self.display_map
14266            .update(cx, |map, cx| map.set_wrap_width(width, cx))
14267    }
14268
14269    pub fn set_soft_wrap(&mut self) {
14270        self.soft_wrap_mode_override = Some(language_settings::SoftWrap::EditorWidth)
14271    }
14272
14273    pub fn toggle_soft_wrap(&mut self, _: &ToggleSoftWrap, _: &mut Window, cx: &mut Context<Self>) {
14274        if self.soft_wrap_mode_override.is_some() {
14275            self.soft_wrap_mode_override.take();
14276        } else {
14277            let soft_wrap = match self.soft_wrap_mode(cx) {
14278                SoftWrap::GitDiff => return,
14279                SoftWrap::None => language_settings::SoftWrap::EditorWidth,
14280                SoftWrap::EditorWidth | SoftWrap::Column(_) | SoftWrap::Bounded(_) => {
14281                    language_settings::SoftWrap::None
14282                }
14283            };
14284            self.soft_wrap_mode_override = Some(soft_wrap);
14285        }
14286        cx.notify();
14287    }
14288
14289    pub fn toggle_tab_bar(&mut self, _: &ToggleTabBar, _: &mut Window, cx: &mut Context<Self>) {
14290        let Some(workspace) = self.workspace() else {
14291            return;
14292        };
14293        let fs = workspace.read(cx).app_state().fs.clone();
14294        let current_show = TabBarSettings::get_global(cx).show;
14295        update_settings_file::<TabBarSettings>(fs, cx, move |setting, _| {
14296            setting.show = Some(!current_show);
14297        });
14298    }
14299
14300    pub fn toggle_indent_guides(
14301        &mut self,
14302        _: &ToggleIndentGuides,
14303        _: &mut Window,
14304        cx: &mut Context<Self>,
14305    ) {
14306        let currently_enabled = self.should_show_indent_guides().unwrap_or_else(|| {
14307            self.buffer
14308                .read(cx)
14309                .language_settings(cx)
14310                .indent_guides
14311                .enabled
14312        });
14313        self.show_indent_guides = Some(!currently_enabled);
14314        cx.notify();
14315    }
14316
14317    fn should_show_indent_guides(&self) -> Option<bool> {
14318        self.show_indent_guides
14319    }
14320
14321    pub fn toggle_line_numbers(
14322        &mut self,
14323        _: &ToggleLineNumbers,
14324        _: &mut Window,
14325        cx: &mut Context<Self>,
14326    ) {
14327        let mut editor_settings = EditorSettings::get_global(cx).clone();
14328        editor_settings.gutter.line_numbers = !editor_settings.gutter.line_numbers;
14329        EditorSettings::override_global(editor_settings, cx);
14330    }
14331
14332    pub fn line_numbers_enabled(&self, cx: &App) -> bool {
14333        if let Some(show_line_numbers) = self.show_line_numbers {
14334            return show_line_numbers;
14335        }
14336        EditorSettings::get_global(cx).gutter.line_numbers
14337    }
14338
14339    pub fn should_use_relative_line_numbers(&self, cx: &mut App) -> bool {
14340        self.use_relative_line_numbers
14341            .unwrap_or(EditorSettings::get_global(cx).relative_line_numbers)
14342    }
14343
14344    pub fn toggle_relative_line_numbers(
14345        &mut self,
14346        _: &ToggleRelativeLineNumbers,
14347        _: &mut Window,
14348        cx: &mut Context<Self>,
14349    ) {
14350        let is_relative = self.should_use_relative_line_numbers(cx);
14351        self.set_relative_line_number(Some(!is_relative), cx)
14352    }
14353
14354    pub fn set_relative_line_number(&mut self, is_relative: Option<bool>, cx: &mut Context<Self>) {
14355        self.use_relative_line_numbers = is_relative;
14356        cx.notify();
14357    }
14358
14359    pub fn set_show_gutter(&mut self, show_gutter: bool, cx: &mut Context<Self>) {
14360        self.show_gutter = show_gutter;
14361        cx.notify();
14362    }
14363
14364    pub fn set_show_scrollbars(&mut self, show_scrollbars: bool, cx: &mut Context<Self>) {
14365        self.show_scrollbars = show_scrollbars;
14366        cx.notify();
14367    }
14368
14369    pub fn set_show_line_numbers(&mut self, show_line_numbers: bool, cx: &mut Context<Self>) {
14370        self.show_line_numbers = Some(show_line_numbers);
14371        cx.notify();
14372    }
14373
14374    pub fn set_show_git_diff_gutter(&mut self, show_git_diff_gutter: bool, cx: &mut Context<Self>) {
14375        self.show_git_diff_gutter = Some(show_git_diff_gutter);
14376        cx.notify();
14377    }
14378
14379    pub fn set_show_code_actions(&mut self, show_code_actions: bool, cx: &mut Context<Self>) {
14380        self.show_code_actions = Some(show_code_actions);
14381        cx.notify();
14382    }
14383
14384    pub fn set_show_runnables(&mut self, show_runnables: bool, cx: &mut Context<Self>) {
14385        self.show_runnables = Some(show_runnables);
14386        cx.notify();
14387    }
14388
14389    pub fn set_masked(&mut self, masked: bool, cx: &mut Context<Self>) {
14390        if self.display_map.read(cx).masked != masked {
14391            self.display_map.update(cx, |map, _| map.masked = masked);
14392        }
14393        cx.notify()
14394    }
14395
14396    pub fn set_show_wrap_guides(&mut self, show_wrap_guides: bool, cx: &mut Context<Self>) {
14397        self.show_wrap_guides = Some(show_wrap_guides);
14398        cx.notify();
14399    }
14400
14401    pub fn set_show_indent_guides(&mut self, show_indent_guides: bool, cx: &mut Context<Self>) {
14402        self.show_indent_guides = Some(show_indent_guides);
14403        cx.notify();
14404    }
14405
14406    pub fn working_directory(&self, cx: &App) -> Option<PathBuf> {
14407        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
14408            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
14409                if let Some(dir) = file.abs_path(cx).parent() {
14410                    return Some(dir.to_owned());
14411                }
14412            }
14413
14414            if let Some(project_path) = buffer.read(cx).project_path(cx) {
14415                return Some(project_path.path.to_path_buf());
14416            }
14417        }
14418
14419        None
14420    }
14421
14422    fn target_file<'a>(&self, cx: &'a App) -> Option<&'a dyn language::LocalFile> {
14423        self.active_excerpt(cx)?
14424            .1
14425            .read(cx)
14426            .file()
14427            .and_then(|f| f.as_local())
14428    }
14429
14430    pub fn target_file_abs_path(&self, cx: &mut Context<Self>) -> Option<PathBuf> {
14431        self.active_excerpt(cx).and_then(|(_, buffer, _)| {
14432            let buffer = buffer.read(cx);
14433            if let Some(project_path) = buffer.project_path(cx) {
14434                let project = self.project.as_ref()?.read(cx);
14435                project.absolute_path(&project_path, cx)
14436            } else {
14437                buffer
14438                    .file()
14439                    .and_then(|file| file.as_local().map(|file| file.abs_path(cx)))
14440            }
14441        })
14442    }
14443
14444    fn target_file_path(&self, cx: &mut Context<Self>) -> Option<PathBuf> {
14445        self.active_excerpt(cx).and_then(|(_, buffer, _)| {
14446            let project_path = buffer.read(cx).project_path(cx)?;
14447            let project = self.project.as_ref()?.read(cx);
14448            let entry = project.entry_for_path(&project_path, cx)?;
14449            let path = entry.path.to_path_buf();
14450            Some(path)
14451        })
14452    }
14453
14454    pub fn reveal_in_finder(
14455        &mut self,
14456        _: &RevealInFileManager,
14457        _window: &mut Window,
14458        cx: &mut Context<Self>,
14459    ) {
14460        if let Some(target) = self.target_file(cx) {
14461            cx.reveal_path(&target.abs_path(cx));
14462        }
14463    }
14464
14465    pub fn copy_path(
14466        &mut self,
14467        _: &zed_actions::workspace::CopyPath,
14468        _window: &mut Window,
14469        cx: &mut Context<Self>,
14470    ) {
14471        if let Some(path) = self.target_file_abs_path(cx) {
14472            if let Some(path) = path.to_str() {
14473                cx.write_to_clipboard(ClipboardItem::new_string(path.to_string()));
14474            }
14475        }
14476    }
14477
14478    pub fn copy_relative_path(
14479        &mut self,
14480        _: &zed_actions::workspace::CopyRelativePath,
14481        _window: &mut Window,
14482        cx: &mut Context<Self>,
14483    ) {
14484        if let Some(path) = self.target_file_path(cx) {
14485            if let Some(path) = path.to_str() {
14486                cx.write_to_clipboard(ClipboardItem::new_string(path.to_string()));
14487            }
14488        }
14489    }
14490
14491    pub fn copy_file_name_without_extension(
14492        &mut self,
14493        _: &CopyFileNameWithoutExtension,
14494        _: &mut Window,
14495        cx: &mut Context<Self>,
14496    ) {
14497        if let Some(file) = self.target_file(cx) {
14498            if let Some(file_stem) = file.path().file_stem() {
14499                if let Some(name) = file_stem.to_str() {
14500                    cx.write_to_clipboard(ClipboardItem::new_string(name.to_string()));
14501                }
14502            }
14503        }
14504    }
14505
14506    pub fn copy_file_name(&mut self, _: &CopyFileName, _: &mut Window, cx: &mut Context<Self>) {
14507        if let Some(file) = self.target_file(cx) {
14508            if let Some(file_name) = file.path().file_name() {
14509                if let Some(name) = file_name.to_str() {
14510                    cx.write_to_clipboard(ClipboardItem::new_string(name.to_string()));
14511                }
14512            }
14513        }
14514    }
14515
14516    pub fn toggle_git_blame(
14517        &mut self,
14518        _: &::git::Blame,
14519        window: &mut Window,
14520        cx: &mut Context<Self>,
14521    ) {
14522        self.show_git_blame_gutter = !self.show_git_blame_gutter;
14523
14524        if self.show_git_blame_gutter && !self.has_blame_entries(cx) {
14525            self.start_git_blame(true, window, cx);
14526        }
14527
14528        cx.notify();
14529    }
14530
14531    pub fn toggle_git_blame_inline(
14532        &mut self,
14533        _: &ToggleGitBlameInline,
14534        window: &mut Window,
14535        cx: &mut Context<Self>,
14536    ) {
14537        self.toggle_git_blame_inline_internal(true, window, cx);
14538        cx.notify();
14539    }
14540
14541    pub fn git_blame_inline_enabled(&self) -> bool {
14542        self.git_blame_inline_enabled
14543    }
14544
14545    pub fn toggle_selection_menu(
14546        &mut self,
14547        _: &ToggleSelectionMenu,
14548        _: &mut Window,
14549        cx: &mut Context<Self>,
14550    ) {
14551        self.show_selection_menu = self
14552            .show_selection_menu
14553            .map(|show_selections_menu| !show_selections_menu)
14554            .or_else(|| Some(!EditorSettings::get_global(cx).toolbar.selections_menu));
14555
14556        cx.notify();
14557    }
14558
14559    pub fn selection_menu_enabled(&self, cx: &App) -> bool {
14560        self.show_selection_menu
14561            .unwrap_or_else(|| EditorSettings::get_global(cx).toolbar.selections_menu)
14562    }
14563
14564    fn start_git_blame(
14565        &mut self,
14566        user_triggered: bool,
14567        window: &mut Window,
14568        cx: &mut Context<Self>,
14569    ) {
14570        if let Some(project) = self.project.as_ref() {
14571            let Some(buffer) = self.buffer().read(cx).as_singleton() else {
14572                return;
14573            };
14574
14575            if buffer.read(cx).file().is_none() {
14576                return;
14577            }
14578
14579            let focused = self.focus_handle(cx).contains_focused(window, cx);
14580
14581            let project = project.clone();
14582            let blame = cx.new(|cx| GitBlame::new(buffer, project, user_triggered, focused, cx));
14583            self.blame_subscription =
14584                Some(cx.observe_in(&blame, window, |_, _, _, cx| cx.notify()));
14585            self.blame = Some(blame);
14586        }
14587    }
14588
14589    fn toggle_git_blame_inline_internal(
14590        &mut self,
14591        user_triggered: bool,
14592        window: &mut Window,
14593        cx: &mut Context<Self>,
14594    ) {
14595        if self.git_blame_inline_enabled {
14596            self.git_blame_inline_enabled = false;
14597            self.show_git_blame_inline = false;
14598            self.show_git_blame_inline_delay_task.take();
14599        } else {
14600            self.git_blame_inline_enabled = true;
14601            self.start_git_blame_inline(user_triggered, window, cx);
14602        }
14603
14604        cx.notify();
14605    }
14606
14607    fn start_git_blame_inline(
14608        &mut self,
14609        user_triggered: bool,
14610        window: &mut Window,
14611        cx: &mut Context<Self>,
14612    ) {
14613        self.start_git_blame(user_triggered, window, cx);
14614
14615        if ProjectSettings::get_global(cx)
14616            .git
14617            .inline_blame_delay()
14618            .is_some()
14619        {
14620            self.start_inline_blame_timer(window, cx);
14621        } else {
14622            self.show_git_blame_inline = true
14623        }
14624    }
14625
14626    pub fn blame(&self) -> Option<&Entity<GitBlame>> {
14627        self.blame.as_ref()
14628    }
14629
14630    pub fn show_git_blame_gutter(&self) -> bool {
14631        self.show_git_blame_gutter
14632    }
14633
14634    pub fn render_git_blame_gutter(&self, cx: &App) -> bool {
14635        self.show_git_blame_gutter && self.has_blame_entries(cx)
14636    }
14637
14638    pub fn render_git_blame_inline(&self, window: &Window, cx: &App) -> bool {
14639        self.show_git_blame_inline
14640            && (self.focus_handle.is_focused(window)
14641                || self
14642                    .git_blame_inline_tooltip
14643                    .as_ref()
14644                    .and_then(|t| t.upgrade())
14645                    .is_some())
14646            && !self.newest_selection_head_on_empty_line(cx)
14647            && self.has_blame_entries(cx)
14648    }
14649
14650    fn has_blame_entries(&self, cx: &App) -> bool {
14651        self.blame()
14652            .map_or(false, |blame| blame.read(cx).has_generated_entries())
14653    }
14654
14655    fn newest_selection_head_on_empty_line(&self, cx: &App) -> bool {
14656        let cursor_anchor = self.selections.newest_anchor().head();
14657
14658        let snapshot = self.buffer.read(cx).snapshot(cx);
14659        let buffer_row = MultiBufferRow(cursor_anchor.to_point(&snapshot).row);
14660
14661        snapshot.line_len(buffer_row) == 0
14662    }
14663
14664    fn get_permalink_to_line(&self, cx: &mut Context<Self>) -> Task<Result<url::Url>> {
14665        let buffer_and_selection = maybe!({
14666            let selection = self.selections.newest::<Point>(cx);
14667            let selection_range = selection.range();
14668
14669            let multi_buffer = self.buffer().read(cx);
14670            let multi_buffer_snapshot = multi_buffer.snapshot(cx);
14671            let buffer_ranges = multi_buffer_snapshot.range_to_buffer_ranges(selection_range);
14672
14673            let (buffer, range, _) = if selection.reversed {
14674                buffer_ranges.first()
14675            } else {
14676                buffer_ranges.last()
14677            }?;
14678
14679            let selection = text::ToPoint::to_point(&range.start, &buffer).row
14680                ..text::ToPoint::to_point(&range.end, &buffer).row;
14681            Some((
14682                multi_buffer.buffer(buffer.remote_id()).unwrap().clone(),
14683                selection,
14684            ))
14685        });
14686
14687        let Some((buffer, selection)) = buffer_and_selection else {
14688            return Task::ready(Err(anyhow!("failed to determine buffer and selection")));
14689        };
14690
14691        let Some(project) = self.project.as_ref() else {
14692            return Task::ready(Err(anyhow!("editor does not have project")));
14693        };
14694
14695        project.update(cx, |project, cx| {
14696            project.get_permalink_to_line(&buffer, selection, cx)
14697        })
14698    }
14699
14700    pub fn copy_permalink_to_line(
14701        &mut self,
14702        _: &CopyPermalinkToLine,
14703        window: &mut Window,
14704        cx: &mut Context<Self>,
14705    ) {
14706        let permalink_task = self.get_permalink_to_line(cx);
14707        let workspace = self.workspace();
14708
14709        cx.spawn_in(window, |_, mut cx| async move {
14710            match permalink_task.await {
14711                Ok(permalink) => {
14712                    cx.update(|_, cx| {
14713                        cx.write_to_clipboard(ClipboardItem::new_string(permalink.to_string()));
14714                    })
14715                    .ok();
14716                }
14717                Err(err) => {
14718                    let message = format!("Failed to copy permalink: {err}");
14719
14720                    Err::<(), anyhow::Error>(err).log_err();
14721
14722                    if let Some(workspace) = workspace {
14723                        workspace
14724                            .update_in(&mut cx, |workspace, _, cx| {
14725                                struct CopyPermalinkToLine;
14726
14727                                workspace.show_toast(
14728                                    Toast::new(
14729                                        NotificationId::unique::<CopyPermalinkToLine>(),
14730                                        message,
14731                                    ),
14732                                    cx,
14733                                )
14734                            })
14735                            .ok();
14736                    }
14737                }
14738            }
14739        })
14740        .detach();
14741    }
14742
14743    pub fn copy_file_location(
14744        &mut self,
14745        _: &CopyFileLocation,
14746        _: &mut Window,
14747        cx: &mut Context<Self>,
14748    ) {
14749        let selection = self.selections.newest::<Point>(cx).start.row + 1;
14750        if let Some(file) = self.target_file(cx) {
14751            if let Some(path) = file.path().to_str() {
14752                cx.write_to_clipboard(ClipboardItem::new_string(format!("{path}:{selection}")));
14753            }
14754        }
14755    }
14756
14757    pub fn open_permalink_to_line(
14758        &mut self,
14759        _: &OpenPermalinkToLine,
14760        window: &mut Window,
14761        cx: &mut Context<Self>,
14762    ) {
14763        let permalink_task = self.get_permalink_to_line(cx);
14764        let workspace = self.workspace();
14765
14766        cx.spawn_in(window, |_, mut cx| async move {
14767            match permalink_task.await {
14768                Ok(permalink) => {
14769                    cx.update(|_, cx| {
14770                        cx.open_url(permalink.as_ref());
14771                    })
14772                    .ok();
14773                }
14774                Err(err) => {
14775                    let message = format!("Failed to open permalink: {err}");
14776
14777                    Err::<(), anyhow::Error>(err).log_err();
14778
14779                    if let Some(workspace) = workspace {
14780                        workspace
14781                            .update(&mut cx, |workspace, cx| {
14782                                struct OpenPermalinkToLine;
14783
14784                                workspace.show_toast(
14785                                    Toast::new(
14786                                        NotificationId::unique::<OpenPermalinkToLine>(),
14787                                        message,
14788                                    ),
14789                                    cx,
14790                                )
14791                            })
14792                            .ok();
14793                    }
14794                }
14795            }
14796        })
14797        .detach();
14798    }
14799
14800    pub fn insert_uuid_v4(
14801        &mut self,
14802        _: &InsertUuidV4,
14803        window: &mut Window,
14804        cx: &mut Context<Self>,
14805    ) {
14806        self.insert_uuid(UuidVersion::V4, window, cx);
14807    }
14808
14809    pub fn insert_uuid_v7(
14810        &mut self,
14811        _: &InsertUuidV7,
14812        window: &mut Window,
14813        cx: &mut Context<Self>,
14814    ) {
14815        self.insert_uuid(UuidVersion::V7, window, cx);
14816    }
14817
14818    fn insert_uuid(&mut self, version: UuidVersion, window: &mut Window, cx: &mut Context<Self>) {
14819        self.transact(window, cx, |this, window, cx| {
14820            let edits = this
14821                .selections
14822                .all::<Point>(cx)
14823                .into_iter()
14824                .map(|selection| {
14825                    let uuid = match version {
14826                        UuidVersion::V4 => uuid::Uuid::new_v4(),
14827                        UuidVersion::V7 => uuid::Uuid::now_v7(),
14828                    };
14829
14830                    (selection.range(), uuid.to_string())
14831                });
14832            this.edit(edits, cx);
14833            this.refresh_inline_completion(true, false, window, cx);
14834        });
14835    }
14836
14837    pub fn open_selections_in_multibuffer(
14838        &mut self,
14839        _: &OpenSelectionsInMultibuffer,
14840        window: &mut Window,
14841        cx: &mut Context<Self>,
14842    ) {
14843        let multibuffer = self.buffer.read(cx);
14844
14845        let Some(buffer) = multibuffer.as_singleton() else {
14846            return;
14847        };
14848
14849        let Some(workspace) = self.workspace() else {
14850            return;
14851        };
14852
14853        let locations = self
14854            .selections
14855            .disjoint_anchors()
14856            .iter()
14857            .map(|range| Location {
14858                buffer: buffer.clone(),
14859                range: range.start.text_anchor..range.end.text_anchor,
14860            })
14861            .collect::<Vec<_>>();
14862
14863        let title = multibuffer.title(cx).to_string();
14864
14865        cx.spawn_in(window, |_, mut cx| async move {
14866            workspace.update_in(&mut cx, |workspace, window, cx| {
14867                Self::open_locations_in_multibuffer(
14868                    workspace,
14869                    locations,
14870                    format!("Selections for '{title}'"),
14871                    false,
14872                    MultibufferSelectionMode::All,
14873                    window,
14874                    cx,
14875                );
14876            })
14877        })
14878        .detach();
14879    }
14880
14881    /// Adds a row highlight for the given range. If a row has multiple highlights, the
14882    /// last highlight added will be used.
14883    ///
14884    /// If the range ends at the beginning of a line, then that line will not be highlighted.
14885    pub fn highlight_rows<T: 'static>(
14886        &mut self,
14887        range: Range<Anchor>,
14888        color: Hsla,
14889        should_autoscroll: bool,
14890        cx: &mut Context<Self>,
14891    ) {
14892        let snapshot = self.buffer().read(cx).snapshot(cx);
14893        let row_highlights = self.highlighted_rows.entry(TypeId::of::<T>()).or_default();
14894        let ix = row_highlights.binary_search_by(|highlight| {
14895            Ordering::Equal
14896                .then_with(|| highlight.range.start.cmp(&range.start, &snapshot))
14897                .then_with(|| highlight.range.end.cmp(&range.end, &snapshot))
14898        });
14899
14900        if let Err(mut ix) = ix {
14901            let index = post_inc(&mut self.highlight_order);
14902
14903            // If this range intersects with the preceding highlight, then merge it with
14904            // the preceding highlight. Otherwise insert a new highlight.
14905            let mut merged = false;
14906            if ix > 0 {
14907                let prev_highlight = &mut row_highlights[ix - 1];
14908                if prev_highlight
14909                    .range
14910                    .end
14911                    .cmp(&range.start, &snapshot)
14912                    .is_ge()
14913                {
14914                    ix -= 1;
14915                    if prev_highlight.range.end.cmp(&range.end, &snapshot).is_lt() {
14916                        prev_highlight.range.end = range.end;
14917                    }
14918                    merged = true;
14919                    prev_highlight.index = index;
14920                    prev_highlight.color = color;
14921                    prev_highlight.should_autoscroll = should_autoscroll;
14922                }
14923            }
14924
14925            if !merged {
14926                row_highlights.insert(
14927                    ix,
14928                    RowHighlight {
14929                        range: range.clone(),
14930                        index,
14931                        color,
14932                        should_autoscroll,
14933                    },
14934                );
14935            }
14936
14937            // If any of the following highlights intersect with this one, merge them.
14938            while let Some(next_highlight) = row_highlights.get(ix + 1) {
14939                let highlight = &row_highlights[ix];
14940                if next_highlight
14941                    .range
14942                    .start
14943                    .cmp(&highlight.range.end, &snapshot)
14944                    .is_le()
14945                {
14946                    if next_highlight
14947                        .range
14948                        .end
14949                        .cmp(&highlight.range.end, &snapshot)
14950                        .is_gt()
14951                    {
14952                        row_highlights[ix].range.end = next_highlight.range.end;
14953                    }
14954                    row_highlights.remove(ix + 1);
14955                } else {
14956                    break;
14957                }
14958            }
14959        }
14960    }
14961
14962    /// Remove any highlighted row ranges of the given type that intersect the
14963    /// given ranges.
14964    pub fn remove_highlighted_rows<T: 'static>(
14965        &mut self,
14966        ranges_to_remove: Vec<Range<Anchor>>,
14967        cx: &mut Context<Self>,
14968    ) {
14969        let snapshot = self.buffer().read(cx).snapshot(cx);
14970        let row_highlights = self.highlighted_rows.entry(TypeId::of::<T>()).or_default();
14971        let mut ranges_to_remove = ranges_to_remove.iter().peekable();
14972        row_highlights.retain(|highlight| {
14973            while let Some(range_to_remove) = ranges_to_remove.peek() {
14974                match range_to_remove.end.cmp(&highlight.range.start, &snapshot) {
14975                    Ordering::Less | Ordering::Equal => {
14976                        ranges_to_remove.next();
14977                    }
14978                    Ordering::Greater => {
14979                        match range_to_remove.start.cmp(&highlight.range.end, &snapshot) {
14980                            Ordering::Less | Ordering::Equal => {
14981                                return false;
14982                            }
14983                            Ordering::Greater => break,
14984                        }
14985                    }
14986                }
14987            }
14988
14989            true
14990        })
14991    }
14992
14993    /// Clear all anchor ranges for a certain highlight context type, so no corresponding rows will be highlighted.
14994    pub fn clear_row_highlights<T: 'static>(&mut self) {
14995        self.highlighted_rows.remove(&TypeId::of::<T>());
14996    }
14997
14998    /// For a highlight given context type, gets all anchor ranges that will be used for row highlighting.
14999    pub fn highlighted_rows<T: 'static>(&self) -> impl '_ + Iterator<Item = (Range<Anchor>, Hsla)> {
15000        self.highlighted_rows
15001            .get(&TypeId::of::<T>())
15002            .map_or(&[] as &[_], |vec| vec.as_slice())
15003            .iter()
15004            .map(|highlight| (highlight.range.clone(), highlight.color))
15005    }
15006
15007    /// Merges all anchor ranges for all context types ever set, picking the last highlight added in case of a row conflict.
15008    /// Returns a map of display rows that are highlighted and their corresponding highlight color.
15009    /// Allows to ignore certain kinds of highlights.
15010    pub fn highlighted_display_rows(
15011        &self,
15012        window: &mut Window,
15013        cx: &mut App,
15014    ) -> BTreeMap<DisplayRow, LineHighlight> {
15015        let snapshot = self.snapshot(window, cx);
15016        let mut used_highlight_orders = HashMap::default();
15017        self.highlighted_rows
15018            .iter()
15019            .flat_map(|(_, highlighted_rows)| highlighted_rows.iter())
15020            .fold(
15021                BTreeMap::<DisplayRow, LineHighlight>::new(),
15022                |mut unique_rows, highlight| {
15023                    let start = highlight.range.start.to_display_point(&snapshot);
15024                    let end = highlight.range.end.to_display_point(&snapshot);
15025                    let start_row = start.row().0;
15026                    let end_row = if highlight.range.end.text_anchor != text::Anchor::MAX
15027                        && end.column() == 0
15028                    {
15029                        end.row().0.saturating_sub(1)
15030                    } else {
15031                        end.row().0
15032                    };
15033                    for row in start_row..=end_row {
15034                        let used_index =
15035                            used_highlight_orders.entry(row).or_insert(highlight.index);
15036                        if highlight.index >= *used_index {
15037                            *used_index = highlight.index;
15038                            unique_rows.insert(DisplayRow(row), highlight.color.into());
15039                        }
15040                    }
15041                    unique_rows
15042                },
15043            )
15044    }
15045
15046    pub fn highlighted_display_row_for_autoscroll(
15047        &self,
15048        snapshot: &DisplaySnapshot,
15049    ) -> Option<DisplayRow> {
15050        self.highlighted_rows
15051            .values()
15052            .flat_map(|highlighted_rows| highlighted_rows.iter())
15053            .filter_map(|highlight| {
15054                if highlight.should_autoscroll {
15055                    Some(highlight.range.start.to_display_point(snapshot).row())
15056                } else {
15057                    None
15058                }
15059            })
15060            .min()
15061    }
15062
15063    pub fn set_search_within_ranges(&mut self, ranges: &[Range<Anchor>], cx: &mut Context<Self>) {
15064        self.highlight_background::<SearchWithinRange>(
15065            ranges,
15066            |colors| colors.editor_document_highlight_read_background,
15067            cx,
15068        )
15069    }
15070
15071    pub fn set_breadcrumb_header(&mut self, new_header: String) {
15072        self.breadcrumb_header = Some(new_header);
15073    }
15074
15075    pub fn clear_search_within_ranges(&mut self, cx: &mut Context<Self>) {
15076        self.clear_background_highlights::<SearchWithinRange>(cx);
15077    }
15078
15079    pub fn highlight_background<T: 'static>(
15080        &mut self,
15081        ranges: &[Range<Anchor>],
15082        color_fetcher: fn(&ThemeColors) -> Hsla,
15083        cx: &mut Context<Self>,
15084    ) {
15085        self.background_highlights
15086            .insert(TypeId::of::<T>(), (color_fetcher, Arc::from(ranges)));
15087        self.scrollbar_marker_state.dirty = true;
15088        cx.notify();
15089    }
15090
15091    pub fn clear_background_highlights<T: 'static>(
15092        &mut self,
15093        cx: &mut Context<Self>,
15094    ) -> Option<BackgroundHighlight> {
15095        let text_highlights = self.background_highlights.remove(&TypeId::of::<T>())?;
15096        if !text_highlights.1.is_empty() {
15097            self.scrollbar_marker_state.dirty = true;
15098            cx.notify();
15099        }
15100        Some(text_highlights)
15101    }
15102
15103    pub fn highlight_gutter<T: 'static>(
15104        &mut self,
15105        ranges: &[Range<Anchor>],
15106        color_fetcher: fn(&App) -> Hsla,
15107        cx: &mut Context<Self>,
15108    ) {
15109        self.gutter_highlights
15110            .insert(TypeId::of::<T>(), (color_fetcher, Arc::from(ranges)));
15111        cx.notify();
15112    }
15113
15114    pub fn clear_gutter_highlights<T: 'static>(
15115        &mut self,
15116        cx: &mut Context<Self>,
15117    ) -> Option<GutterHighlight> {
15118        cx.notify();
15119        self.gutter_highlights.remove(&TypeId::of::<T>())
15120    }
15121
15122    #[cfg(feature = "test-support")]
15123    pub fn all_text_background_highlights(
15124        &self,
15125        window: &mut Window,
15126        cx: &mut Context<Self>,
15127    ) -> Vec<(Range<DisplayPoint>, Hsla)> {
15128        let snapshot = self.snapshot(window, cx);
15129        let buffer = &snapshot.buffer_snapshot;
15130        let start = buffer.anchor_before(0);
15131        let end = buffer.anchor_after(buffer.len());
15132        let theme = cx.theme().colors();
15133        self.background_highlights_in_range(start..end, &snapshot, theme)
15134    }
15135
15136    #[cfg(feature = "test-support")]
15137    pub fn search_background_highlights(&mut self, cx: &mut Context<Self>) -> Vec<Range<Point>> {
15138        let snapshot = self.buffer().read(cx).snapshot(cx);
15139
15140        let highlights = self
15141            .background_highlights
15142            .get(&TypeId::of::<items::BufferSearchHighlights>());
15143
15144        if let Some((_color, ranges)) = highlights {
15145            ranges
15146                .iter()
15147                .map(|range| range.start.to_point(&snapshot)..range.end.to_point(&snapshot))
15148                .collect_vec()
15149        } else {
15150            vec![]
15151        }
15152    }
15153
15154    fn document_highlights_for_position<'a>(
15155        &'a self,
15156        position: Anchor,
15157        buffer: &'a MultiBufferSnapshot,
15158    ) -> impl 'a + Iterator<Item = &'a Range<Anchor>> {
15159        let read_highlights = self
15160            .background_highlights
15161            .get(&TypeId::of::<DocumentHighlightRead>())
15162            .map(|h| &h.1);
15163        let write_highlights = self
15164            .background_highlights
15165            .get(&TypeId::of::<DocumentHighlightWrite>())
15166            .map(|h| &h.1);
15167        let left_position = position.bias_left(buffer);
15168        let right_position = position.bias_right(buffer);
15169        read_highlights
15170            .into_iter()
15171            .chain(write_highlights)
15172            .flat_map(move |ranges| {
15173                let start_ix = match ranges.binary_search_by(|probe| {
15174                    let cmp = probe.end.cmp(&left_position, buffer);
15175                    if cmp.is_ge() {
15176                        Ordering::Greater
15177                    } else {
15178                        Ordering::Less
15179                    }
15180                }) {
15181                    Ok(i) | Err(i) => i,
15182                };
15183
15184                ranges[start_ix..]
15185                    .iter()
15186                    .take_while(move |range| range.start.cmp(&right_position, buffer).is_le())
15187            })
15188    }
15189
15190    pub fn has_background_highlights<T: 'static>(&self) -> bool {
15191        self.background_highlights
15192            .get(&TypeId::of::<T>())
15193            .map_or(false, |(_, highlights)| !highlights.is_empty())
15194    }
15195
15196    pub fn background_highlights_in_range(
15197        &self,
15198        search_range: Range<Anchor>,
15199        display_snapshot: &DisplaySnapshot,
15200        theme: &ThemeColors,
15201    ) -> Vec<(Range<DisplayPoint>, Hsla)> {
15202        let mut results = Vec::new();
15203        for (color_fetcher, ranges) in self.background_highlights.values() {
15204            let color = color_fetcher(theme);
15205            let start_ix = match ranges.binary_search_by(|probe| {
15206                let cmp = probe
15207                    .end
15208                    .cmp(&search_range.start, &display_snapshot.buffer_snapshot);
15209                if cmp.is_gt() {
15210                    Ordering::Greater
15211                } else {
15212                    Ordering::Less
15213                }
15214            }) {
15215                Ok(i) | Err(i) => i,
15216            };
15217            for range in &ranges[start_ix..] {
15218                if range
15219                    .start
15220                    .cmp(&search_range.end, &display_snapshot.buffer_snapshot)
15221                    .is_ge()
15222                {
15223                    break;
15224                }
15225
15226                let start = range.start.to_display_point(display_snapshot);
15227                let end = range.end.to_display_point(display_snapshot);
15228                results.push((start..end, color))
15229            }
15230        }
15231        results
15232    }
15233
15234    pub fn background_highlight_row_ranges<T: 'static>(
15235        &self,
15236        search_range: Range<Anchor>,
15237        display_snapshot: &DisplaySnapshot,
15238        count: usize,
15239    ) -> Vec<RangeInclusive<DisplayPoint>> {
15240        let mut results = Vec::new();
15241        let Some((_, ranges)) = self.background_highlights.get(&TypeId::of::<T>()) else {
15242            return vec![];
15243        };
15244
15245        let start_ix = match ranges.binary_search_by(|probe| {
15246            let cmp = probe
15247                .end
15248                .cmp(&search_range.start, &display_snapshot.buffer_snapshot);
15249            if cmp.is_gt() {
15250                Ordering::Greater
15251            } else {
15252                Ordering::Less
15253            }
15254        }) {
15255            Ok(i) | Err(i) => i,
15256        };
15257        let mut push_region = |start: Option<Point>, end: Option<Point>| {
15258            if let (Some(start_display), Some(end_display)) = (start, end) {
15259                results.push(
15260                    start_display.to_display_point(display_snapshot)
15261                        ..=end_display.to_display_point(display_snapshot),
15262                );
15263            }
15264        };
15265        let mut start_row: Option<Point> = None;
15266        let mut end_row: Option<Point> = None;
15267        if ranges.len() > count {
15268            return Vec::new();
15269        }
15270        for range in &ranges[start_ix..] {
15271            if range
15272                .start
15273                .cmp(&search_range.end, &display_snapshot.buffer_snapshot)
15274                .is_ge()
15275            {
15276                break;
15277            }
15278            let end = range.end.to_point(&display_snapshot.buffer_snapshot);
15279            if let Some(current_row) = &end_row {
15280                if end.row == current_row.row {
15281                    continue;
15282                }
15283            }
15284            let start = range.start.to_point(&display_snapshot.buffer_snapshot);
15285            if start_row.is_none() {
15286                assert_eq!(end_row, None);
15287                start_row = Some(start);
15288                end_row = Some(end);
15289                continue;
15290            }
15291            if let Some(current_end) = end_row.as_mut() {
15292                if start.row > current_end.row + 1 {
15293                    push_region(start_row, end_row);
15294                    start_row = Some(start);
15295                    end_row = Some(end);
15296                } else {
15297                    // Merge two hunks.
15298                    *current_end = end;
15299                }
15300            } else {
15301                unreachable!();
15302            }
15303        }
15304        // We might still have a hunk that was not rendered (if there was a search hit on the last line)
15305        push_region(start_row, end_row);
15306        results
15307    }
15308
15309    pub fn gutter_highlights_in_range(
15310        &self,
15311        search_range: Range<Anchor>,
15312        display_snapshot: &DisplaySnapshot,
15313        cx: &App,
15314    ) -> Vec<(Range<DisplayPoint>, Hsla)> {
15315        let mut results = Vec::new();
15316        for (color_fetcher, ranges) in self.gutter_highlights.values() {
15317            let color = color_fetcher(cx);
15318            let start_ix = match ranges.binary_search_by(|probe| {
15319                let cmp = probe
15320                    .end
15321                    .cmp(&search_range.start, &display_snapshot.buffer_snapshot);
15322                if cmp.is_gt() {
15323                    Ordering::Greater
15324                } else {
15325                    Ordering::Less
15326                }
15327            }) {
15328                Ok(i) | Err(i) => i,
15329            };
15330            for range in &ranges[start_ix..] {
15331                if range
15332                    .start
15333                    .cmp(&search_range.end, &display_snapshot.buffer_snapshot)
15334                    .is_ge()
15335                {
15336                    break;
15337                }
15338
15339                let start = range.start.to_display_point(display_snapshot);
15340                let end = range.end.to_display_point(display_snapshot);
15341                results.push((start..end, color))
15342            }
15343        }
15344        results
15345    }
15346
15347    /// Get the text ranges corresponding to the redaction query
15348    pub fn redacted_ranges(
15349        &self,
15350        search_range: Range<Anchor>,
15351        display_snapshot: &DisplaySnapshot,
15352        cx: &App,
15353    ) -> Vec<Range<DisplayPoint>> {
15354        display_snapshot
15355            .buffer_snapshot
15356            .redacted_ranges(search_range, |file| {
15357                if let Some(file) = file {
15358                    file.is_private()
15359                        && EditorSettings::get(
15360                            Some(SettingsLocation {
15361                                worktree_id: file.worktree_id(cx),
15362                                path: file.path().as_ref(),
15363                            }),
15364                            cx,
15365                        )
15366                        .redact_private_values
15367                } else {
15368                    false
15369                }
15370            })
15371            .map(|range| {
15372                range.start.to_display_point(display_snapshot)
15373                    ..range.end.to_display_point(display_snapshot)
15374            })
15375            .collect()
15376    }
15377
15378    pub fn highlight_text<T: 'static>(
15379        &mut self,
15380        ranges: Vec<Range<Anchor>>,
15381        style: HighlightStyle,
15382        cx: &mut Context<Self>,
15383    ) {
15384        self.display_map.update(cx, |map, _| {
15385            map.highlight_text(TypeId::of::<T>(), ranges, style)
15386        });
15387        cx.notify();
15388    }
15389
15390    pub(crate) fn highlight_inlays<T: 'static>(
15391        &mut self,
15392        highlights: Vec<InlayHighlight>,
15393        style: HighlightStyle,
15394        cx: &mut Context<Self>,
15395    ) {
15396        self.display_map.update(cx, |map, _| {
15397            map.highlight_inlays(TypeId::of::<T>(), highlights, style)
15398        });
15399        cx.notify();
15400    }
15401
15402    pub fn text_highlights<'a, T: 'static>(
15403        &'a self,
15404        cx: &'a App,
15405    ) -> Option<(HighlightStyle, &'a [Range<Anchor>])> {
15406        self.display_map.read(cx).text_highlights(TypeId::of::<T>())
15407    }
15408
15409    pub fn clear_highlights<T: 'static>(&mut self, cx: &mut Context<Self>) {
15410        let cleared = self
15411            .display_map
15412            .update(cx, |map, _| map.clear_highlights(TypeId::of::<T>()));
15413        if cleared {
15414            cx.notify();
15415        }
15416    }
15417
15418    pub fn show_local_cursors(&self, window: &mut Window, cx: &mut App) -> bool {
15419        (self.read_only(cx) || self.blink_manager.read(cx).visible())
15420            && self.focus_handle.is_focused(window)
15421    }
15422
15423    pub fn set_show_cursor_when_unfocused(&mut self, is_enabled: bool, cx: &mut Context<Self>) {
15424        self.show_cursor_when_unfocused = is_enabled;
15425        cx.notify();
15426    }
15427
15428    fn on_buffer_changed(&mut self, _: Entity<MultiBuffer>, cx: &mut Context<Self>) {
15429        cx.notify();
15430    }
15431
15432    fn on_buffer_event(
15433        &mut self,
15434        multibuffer: &Entity<MultiBuffer>,
15435        event: &multi_buffer::Event,
15436        window: &mut Window,
15437        cx: &mut Context<Self>,
15438    ) {
15439        match event {
15440            multi_buffer::Event::Edited {
15441                singleton_buffer_edited,
15442                edited_buffer: buffer_edited,
15443            } => {
15444                self.scrollbar_marker_state.dirty = true;
15445                self.active_indent_guides_state.dirty = true;
15446                self.refresh_active_diagnostics(cx);
15447                self.refresh_code_actions(window, cx);
15448                if self.has_active_inline_completion() {
15449                    self.update_visible_inline_completion(window, cx);
15450                }
15451                if let Some(buffer) = buffer_edited {
15452                    let buffer_id = buffer.read(cx).remote_id();
15453                    if !self.registered_buffers.contains_key(&buffer_id) {
15454                        if let Some(project) = self.project.as_ref() {
15455                            project.update(cx, |project, cx| {
15456                                self.registered_buffers.insert(
15457                                    buffer_id,
15458                                    project.register_buffer_with_language_servers(&buffer, cx),
15459                                );
15460                            })
15461                        }
15462                    }
15463                }
15464                cx.emit(EditorEvent::BufferEdited);
15465                cx.emit(SearchEvent::MatchesInvalidated);
15466                if *singleton_buffer_edited {
15467                    if let Some(project) = &self.project {
15468                        #[allow(clippy::mutable_key_type)]
15469                        let languages_affected = multibuffer.update(cx, |multibuffer, cx| {
15470                            multibuffer
15471                                .all_buffers()
15472                                .into_iter()
15473                                .filter_map(|buffer| {
15474                                    buffer.update(cx, |buffer, cx| {
15475                                        let language = buffer.language()?;
15476                                        let should_discard = project.update(cx, |project, cx| {
15477                                            project.is_local()
15478                                                && !project.has_language_servers_for(buffer, cx)
15479                                        });
15480                                        should_discard.not().then_some(language.clone())
15481                                    })
15482                                })
15483                                .collect::<HashSet<_>>()
15484                        });
15485                        if !languages_affected.is_empty() {
15486                            self.refresh_inlay_hints(
15487                                InlayHintRefreshReason::BufferEdited(languages_affected),
15488                                cx,
15489                            );
15490                        }
15491                    }
15492                }
15493
15494                let Some(project) = &self.project else { return };
15495                let (telemetry, is_via_ssh) = {
15496                    let project = project.read(cx);
15497                    let telemetry = project.client().telemetry().clone();
15498                    let is_via_ssh = project.is_via_ssh();
15499                    (telemetry, is_via_ssh)
15500                };
15501                refresh_linked_ranges(self, window, cx);
15502                telemetry.log_edit_event("editor", is_via_ssh);
15503            }
15504            multi_buffer::Event::ExcerptsAdded {
15505                buffer,
15506                predecessor,
15507                excerpts,
15508            } => {
15509                self.tasks_update_task = Some(self.refresh_runnables(window, cx));
15510                let buffer_id = buffer.read(cx).remote_id();
15511                if self.buffer.read(cx).diff_for(buffer_id).is_none() {
15512                    if let Some(project) = &self.project {
15513                        get_uncommitted_diff_for_buffer(
15514                            project,
15515                            [buffer.clone()],
15516                            self.buffer.clone(),
15517                            cx,
15518                        )
15519                        .detach();
15520                    }
15521                }
15522                cx.emit(EditorEvent::ExcerptsAdded {
15523                    buffer: buffer.clone(),
15524                    predecessor: *predecessor,
15525                    excerpts: excerpts.clone(),
15526                });
15527                self.refresh_inlay_hints(InlayHintRefreshReason::NewLinesShown, cx);
15528            }
15529            multi_buffer::Event::ExcerptsRemoved { ids } => {
15530                self.refresh_inlay_hints(InlayHintRefreshReason::ExcerptsRemoved(ids.clone()), cx);
15531                let buffer = self.buffer.read(cx);
15532                self.registered_buffers
15533                    .retain(|buffer_id, _| buffer.buffer(*buffer_id).is_some());
15534                jsx_tag_auto_close::refresh_enabled_in_any_buffer(self, multibuffer, cx);
15535                cx.emit(EditorEvent::ExcerptsRemoved { ids: ids.clone() })
15536            }
15537            multi_buffer::Event::ExcerptsEdited {
15538                excerpt_ids,
15539                buffer_ids,
15540            } => {
15541                self.display_map.update(cx, |map, cx| {
15542                    map.unfold_buffers(buffer_ids.iter().copied(), cx)
15543                });
15544                cx.emit(EditorEvent::ExcerptsEdited {
15545                    ids: excerpt_ids.clone(),
15546                })
15547            }
15548            multi_buffer::Event::ExcerptsExpanded { ids } => {
15549                self.refresh_inlay_hints(InlayHintRefreshReason::NewLinesShown, cx);
15550                cx.emit(EditorEvent::ExcerptsExpanded { ids: ids.clone() })
15551            }
15552            multi_buffer::Event::Reparsed(buffer_id) => {
15553                self.tasks_update_task = Some(self.refresh_runnables(window, cx));
15554                jsx_tag_auto_close::refresh_enabled_in_any_buffer(self, multibuffer, cx);
15555
15556                cx.emit(EditorEvent::Reparsed(*buffer_id));
15557            }
15558            multi_buffer::Event::DiffHunksToggled => {
15559                self.tasks_update_task = Some(self.refresh_runnables(window, cx));
15560            }
15561            multi_buffer::Event::LanguageChanged(buffer_id) => {
15562                linked_editing_ranges::refresh_linked_ranges(self, window, cx);
15563                jsx_tag_auto_close::refresh_enabled_in_any_buffer(self, multibuffer, cx);
15564                cx.emit(EditorEvent::Reparsed(*buffer_id));
15565                cx.notify();
15566            }
15567            multi_buffer::Event::DirtyChanged => cx.emit(EditorEvent::DirtyChanged),
15568            multi_buffer::Event::Saved => cx.emit(EditorEvent::Saved),
15569            multi_buffer::Event::FileHandleChanged
15570            | multi_buffer::Event::Reloaded
15571            | multi_buffer::Event::BufferDiffChanged => cx.emit(EditorEvent::TitleChanged),
15572            multi_buffer::Event::Closed => cx.emit(EditorEvent::Closed),
15573            multi_buffer::Event::DiagnosticsUpdated => {
15574                self.refresh_active_diagnostics(cx);
15575                self.refresh_inline_diagnostics(true, window, cx);
15576                self.scrollbar_marker_state.dirty = true;
15577                cx.notify();
15578            }
15579            _ => {}
15580        };
15581    }
15582
15583    fn on_display_map_changed(
15584        &mut self,
15585        _: Entity<DisplayMap>,
15586        _: &mut Window,
15587        cx: &mut Context<Self>,
15588    ) {
15589        cx.notify();
15590    }
15591
15592    fn settings_changed(&mut self, window: &mut Window, cx: &mut Context<Self>) {
15593        self.tasks_update_task = Some(self.refresh_runnables(window, cx));
15594        self.update_edit_prediction_settings(cx);
15595        self.refresh_inline_completion(true, false, window, cx);
15596        self.refresh_inlay_hints(
15597            InlayHintRefreshReason::SettingsChange(inlay_hint_settings(
15598                self.selections.newest_anchor().head(),
15599                &self.buffer.read(cx).snapshot(cx),
15600                cx,
15601            )),
15602            cx,
15603        );
15604
15605        let old_cursor_shape = self.cursor_shape;
15606
15607        {
15608            let editor_settings = EditorSettings::get_global(cx);
15609            self.scroll_manager.vertical_scroll_margin = editor_settings.vertical_scroll_margin;
15610            self.show_breadcrumbs = editor_settings.toolbar.breadcrumbs;
15611            self.cursor_shape = editor_settings.cursor_shape.unwrap_or_default();
15612        }
15613
15614        if old_cursor_shape != self.cursor_shape {
15615            cx.emit(EditorEvent::CursorShapeChanged);
15616        }
15617
15618        let project_settings = ProjectSettings::get_global(cx);
15619        self.serialize_dirty_buffers = project_settings.session.restore_unsaved_buffers;
15620
15621        if self.mode == EditorMode::Full {
15622            let show_inline_diagnostics = project_settings.diagnostics.inline.enabled;
15623            let inline_blame_enabled = project_settings.git.inline_blame_enabled();
15624            if self.show_inline_diagnostics != show_inline_diagnostics {
15625                self.show_inline_diagnostics = show_inline_diagnostics;
15626                self.refresh_inline_diagnostics(false, window, cx);
15627            }
15628
15629            if self.git_blame_inline_enabled != inline_blame_enabled {
15630                self.toggle_git_blame_inline_internal(false, window, cx);
15631            }
15632        }
15633
15634        cx.notify();
15635    }
15636
15637    pub fn set_searchable(&mut self, searchable: bool) {
15638        self.searchable = searchable;
15639    }
15640
15641    pub fn searchable(&self) -> bool {
15642        self.searchable
15643    }
15644
15645    fn open_proposed_changes_editor(
15646        &mut self,
15647        _: &OpenProposedChangesEditor,
15648        window: &mut Window,
15649        cx: &mut Context<Self>,
15650    ) {
15651        let Some(workspace) = self.workspace() else {
15652            cx.propagate();
15653            return;
15654        };
15655
15656        let selections = self.selections.all::<usize>(cx);
15657        let multi_buffer = self.buffer.read(cx);
15658        let multi_buffer_snapshot = multi_buffer.snapshot(cx);
15659        let mut new_selections_by_buffer = HashMap::default();
15660        for selection in selections {
15661            for (buffer, range, _) in
15662                multi_buffer_snapshot.range_to_buffer_ranges(selection.start..selection.end)
15663            {
15664                let mut range = range.to_point(buffer);
15665                range.start.column = 0;
15666                range.end.column = buffer.line_len(range.end.row);
15667                new_selections_by_buffer
15668                    .entry(multi_buffer.buffer(buffer.remote_id()).unwrap())
15669                    .or_insert(Vec::new())
15670                    .push(range)
15671            }
15672        }
15673
15674        let proposed_changes_buffers = new_selections_by_buffer
15675            .into_iter()
15676            .map(|(buffer, ranges)| ProposedChangeLocation { buffer, ranges })
15677            .collect::<Vec<_>>();
15678        let proposed_changes_editor = cx.new(|cx| {
15679            ProposedChangesEditor::new(
15680                "Proposed changes",
15681                proposed_changes_buffers,
15682                self.project.clone(),
15683                window,
15684                cx,
15685            )
15686        });
15687
15688        window.defer(cx, move |window, cx| {
15689            workspace.update(cx, |workspace, cx| {
15690                workspace.active_pane().update(cx, |pane, cx| {
15691                    pane.add_item(
15692                        Box::new(proposed_changes_editor),
15693                        true,
15694                        true,
15695                        None,
15696                        window,
15697                        cx,
15698                    );
15699                });
15700            });
15701        });
15702    }
15703
15704    pub fn open_excerpts_in_split(
15705        &mut self,
15706        _: &OpenExcerptsSplit,
15707        window: &mut Window,
15708        cx: &mut Context<Self>,
15709    ) {
15710        self.open_excerpts_common(None, true, window, cx)
15711    }
15712
15713    pub fn open_excerpts(&mut self, _: &OpenExcerpts, window: &mut Window, cx: &mut Context<Self>) {
15714        self.open_excerpts_common(None, false, window, cx)
15715    }
15716
15717    fn open_excerpts_common(
15718        &mut self,
15719        jump_data: Option<JumpData>,
15720        split: bool,
15721        window: &mut Window,
15722        cx: &mut Context<Self>,
15723    ) {
15724        let Some(workspace) = self.workspace() else {
15725            cx.propagate();
15726            return;
15727        };
15728
15729        if self.buffer.read(cx).is_singleton() {
15730            cx.propagate();
15731            return;
15732        }
15733
15734        let mut new_selections_by_buffer = HashMap::default();
15735        match &jump_data {
15736            Some(JumpData::MultiBufferPoint {
15737                excerpt_id,
15738                position,
15739                anchor,
15740                line_offset_from_top,
15741            }) => {
15742                let multi_buffer_snapshot = self.buffer.read(cx).snapshot(cx);
15743                if let Some(buffer) = multi_buffer_snapshot
15744                    .buffer_id_for_excerpt(*excerpt_id)
15745                    .and_then(|buffer_id| self.buffer.read(cx).buffer(buffer_id))
15746                {
15747                    let buffer_snapshot = buffer.read(cx).snapshot();
15748                    let jump_to_point = if buffer_snapshot.can_resolve(anchor) {
15749                        language::ToPoint::to_point(anchor, &buffer_snapshot)
15750                    } else {
15751                        buffer_snapshot.clip_point(*position, Bias::Left)
15752                    };
15753                    let jump_to_offset = buffer_snapshot.point_to_offset(jump_to_point);
15754                    new_selections_by_buffer.insert(
15755                        buffer,
15756                        (
15757                            vec![jump_to_offset..jump_to_offset],
15758                            Some(*line_offset_from_top),
15759                        ),
15760                    );
15761                }
15762            }
15763            Some(JumpData::MultiBufferRow {
15764                row,
15765                line_offset_from_top,
15766            }) => {
15767                let point = MultiBufferPoint::new(row.0, 0);
15768                if let Some((buffer, buffer_point, _)) =
15769                    self.buffer.read(cx).point_to_buffer_point(point, cx)
15770                {
15771                    let buffer_offset = buffer.read(cx).point_to_offset(buffer_point);
15772                    new_selections_by_buffer
15773                        .entry(buffer)
15774                        .or_insert((Vec::new(), Some(*line_offset_from_top)))
15775                        .0
15776                        .push(buffer_offset..buffer_offset)
15777                }
15778            }
15779            None => {
15780                let selections = self.selections.all::<usize>(cx);
15781                let multi_buffer = self.buffer.read(cx);
15782                for selection in selections {
15783                    for (snapshot, range, _, anchor) in multi_buffer
15784                        .snapshot(cx)
15785                        .range_to_buffer_ranges_with_deleted_hunks(selection.range())
15786                    {
15787                        if let Some(anchor) = anchor {
15788                            // selection is in a deleted hunk
15789                            let Some(buffer_id) = anchor.buffer_id else {
15790                                continue;
15791                            };
15792                            let Some(buffer_handle) = multi_buffer.buffer(buffer_id) else {
15793                                continue;
15794                            };
15795                            let offset = text::ToOffset::to_offset(
15796                                &anchor.text_anchor,
15797                                &buffer_handle.read(cx).snapshot(),
15798                            );
15799                            let range = offset..offset;
15800                            new_selections_by_buffer
15801                                .entry(buffer_handle)
15802                                .or_insert((Vec::new(), None))
15803                                .0
15804                                .push(range)
15805                        } else {
15806                            let Some(buffer_handle) = multi_buffer.buffer(snapshot.remote_id())
15807                            else {
15808                                continue;
15809                            };
15810                            new_selections_by_buffer
15811                                .entry(buffer_handle)
15812                                .or_insert((Vec::new(), None))
15813                                .0
15814                                .push(range)
15815                        }
15816                    }
15817                }
15818            }
15819        }
15820
15821        if new_selections_by_buffer.is_empty() {
15822            return;
15823        }
15824
15825        // We defer the pane interaction because we ourselves are a workspace item
15826        // and activating a new item causes the pane to call a method on us reentrantly,
15827        // which panics if we're on the stack.
15828        window.defer(cx, move |window, cx| {
15829            workspace.update(cx, |workspace, cx| {
15830                let pane = if split {
15831                    workspace.adjacent_pane(window, cx)
15832                } else {
15833                    workspace.active_pane().clone()
15834                };
15835
15836                for (buffer, (ranges, scroll_offset)) in new_selections_by_buffer {
15837                    let editor = buffer
15838                        .read(cx)
15839                        .file()
15840                        .is_none()
15841                        .then(|| {
15842                            // Handle file-less buffers separately: those are not really the project items, so won't have a project path or entity id,
15843                            // so `workspace.open_project_item` will never find them, always opening a new editor.
15844                            // Instead, we try to activate the existing editor in the pane first.
15845                            let (editor, pane_item_index) =
15846                                pane.read(cx).items().enumerate().find_map(|(i, item)| {
15847                                    let editor = item.downcast::<Editor>()?;
15848                                    let singleton_buffer =
15849                                        editor.read(cx).buffer().read(cx).as_singleton()?;
15850                                    if singleton_buffer == buffer {
15851                                        Some((editor, i))
15852                                    } else {
15853                                        None
15854                                    }
15855                                })?;
15856                            pane.update(cx, |pane, cx| {
15857                                pane.activate_item(pane_item_index, true, true, window, cx)
15858                            });
15859                            Some(editor)
15860                        })
15861                        .flatten()
15862                        .unwrap_or_else(|| {
15863                            workspace.open_project_item::<Self>(
15864                                pane.clone(),
15865                                buffer,
15866                                true,
15867                                true,
15868                                window,
15869                                cx,
15870                            )
15871                        });
15872
15873                    editor.update(cx, |editor, cx| {
15874                        let autoscroll = match scroll_offset {
15875                            Some(scroll_offset) => Autoscroll::top_relative(scroll_offset as usize),
15876                            None => Autoscroll::newest(),
15877                        };
15878                        let nav_history = editor.nav_history.take();
15879                        editor.change_selections(Some(autoscroll), window, cx, |s| {
15880                            s.select_ranges(ranges);
15881                        });
15882                        editor.nav_history = nav_history;
15883                    });
15884                }
15885            })
15886        });
15887    }
15888
15889    fn marked_text_ranges(&self, cx: &App) -> Option<Vec<Range<OffsetUtf16>>> {
15890        let snapshot = self.buffer.read(cx).read(cx);
15891        let (_, ranges) = self.text_highlights::<InputComposition>(cx)?;
15892        Some(
15893            ranges
15894                .iter()
15895                .map(move |range| {
15896                    range.start.to_offset_utf16(&snapshot)..range.end.to_offset_utf16(&snapshot)
15897                })
15898                .collect(),
15899        )
15900    }
15901
15902    fn selection_replacement_ranges(
15903        &self,
15904        range: Range<OffsetUtf16>,
15905        cx: &mut App,
15906    ) -> Vec<Range<OffsetUtf16>> {
15907        let selections = self.selections.all::<OffsetUtf16>(cx);
15908        let newest_selection = selections
15909            .iter()
15910            .max_by_key(|selection| selection.id)
15911            .unwrap();
15912        let start_delta = range.start.0 as isize - newest_selection.start.0 as isize;
15913        let end_delta = range.end.0 as isize - newest_selection.end.0 as isize;
15914        let snapshot = self.buffer.read(cx).read(cx);
15915        selections
15916            .into_iter()
15917            .map(|mut selection| {
15918                selection.start.0 =
15919                    (selection.start.0 as isize).saturating_add(start_delta) as usize;
15920                selection.end.0 = (selection.end.0 as isize).saturating_add(end_delta) as usize;
15921                snapshot.clip_offset_utf16(selection.start, Bias::Left)
15922                    ..snapshot.clip_offset_utf16(selection.end, Bias::Right)
15923            })
15924            .collect()
15925    }
15926
15927    fn report_editor_event(
15928        &self,
15929        event_type: &'static str,
15930        file_extension: Option<String>,
15931        cx: &App,
15932    ) {
15933        if cfg!(any(test, feature = "test-support")) {
15934            return;
15935        }
15936
15937        let Some(project) = &self.project else { return };
15938
15939        // If None, we are in a file without an extension
15940        let file = self
15941            .buffer
15942            .read(cx)
15943            .as_singleton()
15944            .and_then(|b| b.read(cx).file());
15945        let file_extension = file_extension.or(file
15946            .as_ref()
15947            .and_then(|file| Path::new(file.file_name(cx)).extension())
15948            .and_then(|e| e.to_str())
15949            .map(|a| a.to_string()));
15950
15951        let vim_mode = cx
15952            .global::<SettingsStore>()
15953            .raw_user_settings()
15954            .get("vim_mode")
15955            == Some(&serde_json::Value::Bool(true));
15956
15957        let edit_predictions_provider = all_language_settings(file, cx).edit_predictions.provider;
15958        let copilot_enabled = edit_predictions_provider
15959            == language::language_settings::EditPredictionProvider::Copilot;
15960        let copilot_enabled_for_language = self
15961            .buffer
15962            .read(cx)
15963            .language_settings(cx)
15964            .show_edit_predictions;
15965
15966        let project = project.read(cx);
15967        telemetry::event!(
15968            event_type,
15969            file_extension,
15970            vim_mode,
15971            copilot_enabled,
15972            copilot_enabled_for_language,
15973            edit_predictions_provider,
15974            is_via_ssh = project.is_via_ssh(),
15975        );
15976    }
15977
15978    /// Copy the highlighted chunks to the clipboard as JSON. The format is an array of lines,
15979    /// with each line being an array of {text, highlight} objects.
15980    fn copy_highlight_json(
15981        &mut self,
15982        _: &CopyHighlightJson,
15983        window: &mut Window,
15984        cx: &mut Context<Self>,
15985    ) {
15986        #[derive(Serialize)]
15987        struct Chunk<'a> {
15988            text: String,
15989            highlight: Option<&'a str>,
15990        }
15991
15992        let snapshot = self.buffer.read(cx).snapshot(cx);
15993        let range = self
15994            .selected_text_range(false, window, cx)
15995            .and_then(|selection| {
15996                if selection.range.is_empty() {
15997                    None
15998                } else {
15999                    Some(selection.range)
16000                }
16001            })
16002            .unwrap_or_else(|| 0..snapshot.len());
16003
16004        let chunks = snapshot.chunks(range, true);
16005        let mut lines = Vec::new();
16006        let mut line: VecDeque<Chunk> = VecDeque::new();
16007
16008        let Some(style) = self.style.as_ref() else {
16009            return;
16010        };
16011
16012        for chunk in chunks {
16013            let highlight = chunk
16014                .syntax_highlight_id
16015                .and_then(|id| id.name(&style.syntax));
16016            let mut chunk_lines = chunk.text.split('\n').peekable();
16017            while let Some(text) = chunk_lines.next() {
16018                let mut merged_with_last_token = false;
16019                if let Some(last_token) = line.back_mut() {
16020                    if last_token.highlight == highlight {
16021                        last_token.text.push_str(text);
16022                        merged_with_last_token = true;
16023                    }
16024                }
16025
16026                if !merged_with_last_token {
16027                    line.push_back(Chunk {
16028                        text: text.into(),
16029                        highlight,
16030                    });
16031                }
16032
16033                if chunk_lines.peek().is_some() {
16034                    if line.len() > 1 && line.front().unwrap().text.is_empty() {
16035                        line.pop_front();
16036                    }
16037                    if line.len() > 1 && line.back().unwrap().text.is_empty() {
16038                        line.pop_back();
16039                    }
16040
16041                    lines.push(mem::take(&mut line));
16042                }
16043            }
16044        }
16045
16046        let Some(lines) = serde_json::to_string_pretty(&lines).log_err() else {
16047            return;
16048        };
16049        cx.write_to_clipboard(ClipboardItem::new_string(lines));
16050    }
16051
16052    pub fn open_context_menu(
16053        &mut self,
16054        _: &OpenContextMenu,
16055        window: &mut Window,
16056        cx: &mut Context<Self>,
16057    ) {
16058        self.request_autoscroll(Autoscroll::newest(), cx);
16059        let position = self.selections.newest_display(cx).start;
16060        mouse_context_menu::deploy_context_menu(self, None, position, window, cx);
16061    }
16062
16063    pub fn inlay_hint_cache(&self) -> &InlayHintCache {
16064        &self.inlay_hint_cache
16065    }
16066
16067    pub fn replay_insert_event(
16068        &mut self,
16069        text: &str,
16070        relative_utf16_range: Option<Range<isize>>,
16071        window: &mut Window,
16072        cx: &mut Context<Self>,
16073    ) {
16074        if !self.input_enabled {
16075            cx.emit(EditorEvent::InputIgnored { text: text.into() });
16076            return;
16077        }
16078        if let Some(relative_utf16_range) = relative_utf16_range {
16079            let selections = self.selections.all::<OffsetUtf16>(cx);
16080            self.change_selections(None, window, cx, |s| {
16081                let new_ranges = selections.into_iter().map(|range| {
16082                    let start = OffsetUtf16(
16083                        range
16084                            .head()
16085                            .0
16086                            .saturating_add_signed(relative_utf16_range.start),
16087                    );
16088                    let end = OffsetUtf16(
16089                        range
16090                            .head()
16091                            .0
16092                            .saturating_add_signed(relative_utf16_range.end),
16093                    );
16094                    start..end
16095                });
16096                s.select_ranges(new_ranges);
16097            });
16098        }
16099
16100        self.handle_input(text, window, cx);
16101    }
16102
16103    pub fn supports_inlay_hints(&self, cx: &mut App) -> bool {
16104        let Some(provider) = self.semantics_provider.as_ref() else {
16105            return false;
16106        };
16107
16108        let mut supports = false;
16109        self.buffer().update(cx, |this, cx| {
16110            this.for_each_buffer(|buffer| {
16111                supports |= provider.supports_inlay_hints(buffer, cx);
16112            });
16113        });
16114
16115        supports
16116    }
16117
16118    pub fn is_focused(&self, window: &Window) -> bool {
16119        self.focus_handle.is_focused(window)
16120    }
16121
16122    fn handle_focus(&mut self, window: &mut Window, cx: &mut Context<Self>) {
16123        cx.emit(EditorEvent::Focused);
16124
16125        if let Some(descendant) = self
16126            .last_focused_descendant
16127            .take()
16128            .and_then(|descendant| descendant.upgrade())
16129        {
16130            window.focus(&descendant);
16131        } else {
16132            if let Some(blame) = self.blame.as_ref() {
16133                blame.update(cx, GitBlame::focus)
16134            }
16135
16136            self.blink_manager.update(cx, BlinkManager::enable);
16137            self.show_cursor_names(window, cx);
16138            self.buffer.update(cx, |buffer, cx| {
16139                buffer.finalize_last_transaction(cx);
16140                if self.leader_peer_id.is_none() {
16141                    buffer.set_active_selections(
16142                        &self.selections.disjoint_anchors(),
16143                        self.selections.line_mode,
16144                        self.cursor_shape,
16145                        cx,
16146                    );
16147                }
16148            });
16149        }
16150    }
16151
16152    fn handle_focus_in(&mut self, _: &mut Window, cx: &mut Context<Self>) {
16153        cx.emit(EditorEvent::FocusedIn)
16154    }
16155
16156    fn handle_focus_out(
16157        &mut self,
16158        event: FocusOutEvent,
16159        _window: &mut Window,
16160        cx: &mut Context<Self>,
16161    ) {
16162        if event.blurred != self.focus_handle {
16163            self.last_focused_descendant = Some(event.blurred);
16164        }
16165        self.refresh_inlay_hints(InlayHintRefreshReason::ModifiersChanged(false), cx);
16166    }
16167
16168    pub fn handle_blur(&mut self, window: &mut Window, cx: &mut Context<Self>) {
16169        self.blink_manager.update(cx, BlinkManager::disable);
16170        self.buffer
16171            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
16172
16173        if let Some(blame) = self.blame.as_ref() {
16174            blame.update(cx, GitBlame::blur)
16175        }
16176        if !self.hover_state.focused(window, cx) {
16177            hide_hover(self, cx);
16178        }
16179        if !self
16180            .context_menu
16181            .borrow()
16182            .as_ref()
16183            .is_some_and(|context_menu| context_menu.focused(window, cx))
16184        {
16185            self.hide_context_menu(window, cx);
16186        }
16187        self.discard_inline_completion(false, cx);
16188        cx.emit(EditorEvent::Blurred);
16189        cx.notify();
16190    }
16191
16192    pub fn register_action<A: Action>(
16193        &mut self,
16194        listener: impl Fn(&A, &mut Window, &mut App) + 'static,
16195    ) -> Subscription {
16196        let id = self.next_editor_action_id.post_inc();
16197        let listener = Arc::new(listener);
16198        self.editor_actions.borrow_mut().insert(
16199            id,
16200            Box::new(move |window, _| {
16201                let listener = listener.clone();
16202                window.on_action(TypeId::of::<A>(), move |action, phase, window, cx| {
16203                    let action = action.downcast_ref().unwrap();
16204                    if phase == DispatchPhase::Bubble {
16205                        listener(action, window, cx)
16206                    }
16207                })
16208            }),
16209        );
16210
16211        let editor_actions = self.editor_actions.clone();
16212        Subscription::new(move || {
16213            editor_actions.borrow_mut().remove(&id);
16214        })
16215    }
16216
16217    pub fn file_header_size(&self) -> u32 {
16218        FILE_HEADER_HEIGHT
16219    }
16220
16221    pub fn restore(
16222        &mut self,
16223        revert_changes: HashMap<BufferId, Vec<(Range<text::Anchor>, Rope)>>,
16224        window: &mut Window,
16225        cx: &mut Context<Self>,
16226    ) {
16227        let workspace = self.workspace();
16228        let project = self.project.as_ref();
16229        let save_tasks = self.buffer().update(cx, |multi_buffer, cx| {
16230            let mut tasks = Vec::new();
16231            for (buffer_id, changes) in revert_changes {
16232                if let Some(buffer) = multi_buffer.buffer(buffer_id) {
16233                    buffer.update(cx, |buffer, cx| {
16234                        buffer.edit(
16235                            changes
16236                                .into_iter()
16237                                .map(|(range, text)| (range, text.to_string())),
16238                            None,
16239                            cx,
16240                        );
16241                    });
16242
16243                    if let Some(project) =
16244                        project.filter(|_| multi_buffer.all_diff_hunks_expanded())
16245                    {
16246                        project.update(cx, |project, cx| {
16247                            tasks.push((buffer.clone(), project.save_buffer(buffer, cx)));
16248                        })
16249                    }
16250                }
16251            }
16252            tasks
16253        });
16254        cx.spawn_in(window, |_, mut cx| async move {
16255            for (buffer, task) in save_tasks {
16256                let result = task.await;
16257                if result.is_err() {
16258                    let Some(path) = buffer
16259                        .read_with(&cx, |buffer, cx| buffer.project_path(cx))
16260                        .ok()
16261                    else {
16262                        continue;
16263                    };
16264                    if let Some((workspace, path)) = workspace.as_ref().zip(path) {
16265                        let Some(task) = cx
16266                            .update_window_entity(&workspace, |workspace, window, cx| {
16267                                workspace
16268                                    .open_path_preview(path, None, false, false, false, window, cx)
16269                            })
16270                            .ok()
16271                        else {
16272                            continue;
16273                        };
16274                        task.await.log_err();
16275                    }
16276                }
16277            }
16278        })
16279        .detach();
16280        self.change_selections(None, window, cx, |selections| selections.refresh());
16281    }
16282
16283    pub fn to_pixel_point(
16284        &self,
16285        source: multi_buffer::Anchor,
16286        editor_snapshot: &EditorSnapshot,
16287        window: &mut Window,
16288    ) -> Option<gpui::Point<Pixels>> {
16289        let source_point = source.to_display_point(editor_snapshot);
16290        self.display_to_pixel_point(source_point, editor_snapshot, window)
16291    }
16292
16293    pub fn display_to_pixel_point(
16294        &self,
16295        source: DisplayPoint,
16296        editor_snapshot: &EditorSnapshot,
16297        window: &mut Window,
16298    ) -> Option<gpui::Point<Pixels>> {
16299        let line_height = self.style()?.text.line_height_in_pixels(window.rem_size());
16300        let text_layout_details = self.text_layout_details(window);
16301        let scroll_top = text_layout_details
16302            .scroll_anchor
16303            .scroll_position(editor_snapshot)
16304            .y;
16305
16306        if source.row().as_f32() < scroll_top.floor() {
16307            return None;
16308        }
16309        let source_x = editor_snapshot.x_for_display_point(source, &text_layout_details);
16310        let source_y = line_height * (source.row().as_f32() - scroll_top);
16311        Some(gpui::Point::new(source_x, source_y))
16312    }
16313
16314    pub fn has_visible_completions_menu(&self) -> bool {
16315        !self.edit_prediction_preview_is_active()
16316            && self.context_menu.borrow().as_ref().map_or(false, |menu| {
16317                menu.visible() && matches!(menu, CodeContextMenu::Completions(_))
16318            })
16319    }
16320
16321    pub fn register_addon<T: Addon>(&mut self, instance: T) {
16322        self.addons
16323            .insert(std::any::TypeId::of::<T>(), Box::new(instance));
16324    }
16325
16326    pub fn unregister_addon<T: Addon>(&mut self) {
16327        self.addons.remove(&std::any::TypeId::of::<T>());
16328    }
16329
16330    pub fn addon<T: Addon>(&self) -> Option<&T> {
16331        let type_id = std::any::TypeId::of::<T>();
16332        self.addons
16333            .get(&type_id)
16334            .and_then(|item| item.to_any().downcast_ref::<T>())
16335    }
16336
16337    fn character_size(&self, window: &mut Window) -> gpui::Size<Pixels> {
16338        let text_layout_details = self.text_layout_details(window);
16339        let style = &text_layout_details.editor_style;
16340        let font_id = window.text_system().resolve_font(&style.text.font());
16341        let font_size = style.text.font_size.to_pixels(window.rem_size());
16342        let line_height = style.text.line_height_in_pixels(window.rem_size());
16343        let em_width = window.text_system().em_width(font_id, font_size).unwrap();
16344
16345        gpui::Size::new(em_width, line_height)
16346    }
16347
16348    pub fn wait_for_diff_to_load(&self) -> Option<Shared<Task<()>>> {
16349        self.load_diff_task.clone()
16350    }
16351
16352    fn read_selections_from_db(
16353        &mut self,
16354        item_id: u64,
16355        workspace_id: WorkspaceId,
16356        window: &mut Window,
16357        cx: &mut Context<Editor>,
16358    ) {
16359        if !self.is_singleton(cx)
16360            || WorkspaceSettings::get(None, cx).restore_on_startup == RestoreOnStartupBehavior::None
16361        {
16362            return;
16363        }
16364        let Some(selections) = DB.get_editor_selections(item_id, workspace_id).log_err() else {
16365            return;
16366        };
16367        if selections.is_empty() {
16368            return;
16369        }
16370
16371        let snapshot = self.buffer.read(cx).snapshot(cx);
16372        self.change_selections(None, window, cx, |s| {
16373            s.select_ranges(selections.into_iter().map(|(start, end)| {
16374                snapshot.clip_offset(start, Bias::Left)..snapshot.clip_offset(end, Bias::Right)
16375            }));
16376        });
16377    }
16378}
16379
16380fn insert_extra_newline_brackets(
16381    buffer: &MultiBufferSnapshot,
16382    range: Range<usize>,
16383    language: &language::LanguageScope,
16384) -> bool {
16385    let leading_whitespace_len = buffer
16386        .reversed_chars_at(range.start)
16387        .take_while(|c| c.is_whitespace() && *c != '\n')
16388        .map(|c| c.len_utf8())
16389        .sum::<usize>();
16390    let trailing_whitespace_len = buffer
16391        .chars_at(range.end)
16392        .take_while(|c| c.is_whitespace() && *c != '\n')
16393        .map(|c| c.len_utf8())
16394        .sum::<usize>();
16395    let range = range.start - leading_whitespace_len..range.end + trailing_whitespace_len;
16396
16397    language.brackets().any(|(pair, enabled)| {
16398        let pair_start = pair.start.trim_end();
16399        let pair_end = pair.end.trim_start();
16400
16401        enabled
16402            && pair.newline
16403            && buffer.contains_str_at(range.end, pair_end)
16404            && buffer.contains_str_at(range.start.saturating_sub(pair_start.len()), pair_start)
16405    })
16406}
16407
16408fn insert_extra_newline_tree_sitter(buffer: &MultiBufferSnapshot, range: Range<usize>) -> bool {
16409    let (buffer, range) = match buffer.range_to_buffer_ranges(range).as_slice() {
16410        [(buffer, range, _)] => (*buffer, range.clone()),
16411        _ => return false,
16412    };
16413    let pair = {
16414        let mut result: Option<BracketMatch> = None;
16415
16416        for pair in buffer
16417            .all_bracket_ranges(range.clone())
16418            .filter(move |pair| {
16419                pair.open_range.start <= range.start && pair.close_range.end >= range.end
16420            })
16421        {
16422            let len = pair.close_range.end - pair.open_range.start;
16423
16424            if let Some(existing) = &result {
16425                let existing_len = existing.close_range.end - existing.open_range.start;
16426                if len > existing_len {
16427                    continue;
16428                }
16429            }
16430
16431            result = Some(pair);
16432        }
16433
16434        result
16435    };
16436    let Some(pair) = pair else {
16437        return false;
16438    };
16439    pair.newline_only
16440        && buffer
16441            .chars_for_range(pair.open_range.end..range.start)
16442            .chain(buffer.chars_for_range(range.end..pair.close_range.start))
16443            .all(|c| c.is_whitespace() && c != '\n')
16444}
16445
16446fn get_uncommitted_diff_for_buffer(
16447    project: &Entity<Project>,
16448    buffers: impl IntoIterator<Item = Entity<Buffer>>,
16449    buffer: Entity<MultiBuffer>,
16450    cx: &mut App,
16451) -> Task<()> {
16452    let mut tasks = Vec::new();
16453    project.update(cx, |project, cx| {
16454        for buffer in buffers {
16455            tasks.push(project.open_uncommitted_diff(buffer.clone(), cx))
16456        }
16457    });
16458    cx.spawn(|mut cx| async move {
16459        let diffs = future::join_all(tasks).await;
16460        buffer
16461            .update(&mut cx, |buffer, cx| {
16462                for diff in diffs.into_iter().flatten() {
16463                    buffer.add_diff(diff, cx);
16464                }
16465            })
16466            .ok();
16467    })
16468}
16469
16470fn char_len_with_expanded_tabs(offset: usize, text: &str, tab_size: NonZeroU32) -> usize {
16471    let tab_size = tab_size.get() as usize;
16472    let mut width = offset;
16473
16474    for ch in text.chars() {
16475        width += if ch == '\t' {
16476            tab_size - (width % tab_size)
16477        } else {
16478            1
16479        };
16480    }
16481
16482    width - offset
16483}
16484
16485#[cfg(test)]
16486mod tests {
16487    use super::*;
16488
16489    #[test]
16490    fn test_string_size_with_expanded_tabs() {
16491        let nz = |val| NonZeroU32::new(val).unwrap();
16492        assert_eq!(char_len_with_expanded_tabs(0, "", nz(4)), 0);
16493        assert_eq!(char_len_with_expanded_tabs(0, "hello", nz(4)), 5);
16494        assert_eq!(char_len_with_expanded_tabs(0, "\thello", nz(4)), 9);
16495        assert_eq!(char_len_with_expanded_tabs(0, "abc\tab", nz(4)), 6);
16496        assert_eq!(char_len_with_expanded_tabs(0, "hello\t", nz(4)), 8);
16497        assert_eq!(char_len_with_expanded_tabs(0, "\t\t", nz(8)), 16);
16498        assert_eq!(char_len_with_expanded_tabs(0, "x\t", nz(8)), 8);
16499        assert_eq!(char_len_with_expanded_tabs(7, "x\t", nz(8)), 9);
16500    }
16501}
16502
16503/// Tokenizes a string into runs of text that should stick together, or that is whitespace.
16504struct WordBreakingTokenizer<'a> {
16505    input: &'a str,
16506}
16507
16508impl<'a> WordBreakingTokenizer<'a> {
16509    fn new(input: &'a str) -> Self {
16510        Self { input }
16511    }
16512}
16513
16514fn is_char_ideographic(ch: char) -> bool {
16515    use unicode_script::Script::*;
16516    use unicode_script::UnicodeScript;
16517    matches!(ch.script(), Han | Tangut | Yi)
16518}
16519
16520fn is_grapheme_ideographic(text: &str) -> bool {
16521    text.chars().any(is_char_ideographic)
16522}
16523
16524fn is_grapheme_whitespace(text: &str) -> bool {
16525    text.chars().any(|x| x.is_whitespace())
16526}
16527
16528fn should_stay_with_preceding_ideograph(text: &str) -> bool {
16529    text.chars().next().map_or(false, |ch| {
16530        matches!(ch, '。' | '、' | ',' | '?' | '!' | ':' | ';' | '…')
16531    })
16532}
16533
16534#[derive(PartialEq, Eq, Debug, Clone, Copy)]
16535struct WordBreakToken<'a> {
16536    token: &'a str,
16537    grapheme_len: usize,
16538    is_whitespace: bool,
16539}
16540
16541impl<'a> Iterator for WordBreakingTokenizer<'a> {
16542    /// Yields a span, the count of graphemes in the token, and whether it was
16543    /// whitespace. Note that it also breaks at word boundaries.
16544    type Item = WordBreakToken<'a>;
16545
16546    fn next(&mut self) -> Option<Self::Item> {
16547        use unicode_segmentation::UnicodeSegmentation;
16548        if self.input.is_empty() {
16549            return None;
16550        }
16551
16552        let mut iter = self.input.graphemes(true).peekable();
16553        let mut offset = 0;
16554        let mut graphemes = 0;
16555        if let Some(first_grapheme) = iter.next() {
16556            let is_whitespace = is_grapheme_whitespace(first_grapheme);
16557            offset += first_grapheme.len();
16558            graphemes += 1;
16559            if is_grapheme_ideographic(first_grapheme) && !is_whitespace {
16560                if let Some(grapheme) = iter.peek().copied() {
16561                    if should_stay_with_preceding_ideograph(grapheme) {
16562                        offset += grapheme.len();
16563                        graphemes += 1;
16564                    }
16565                }
16566            } else {
16567                let mut words = self.input[offset..].split_word_bound_indices().peekable();
16568                let mut next_word_bound = words.peek().copied();
16569                if next_word_bound.map_or(false, |(i, _)| i == 0) {
16570                    next_word_bound = words.next();
16571                }
16572                while let Some(grapheme) = iter.peek().copied() {
16573                    if next_word_bound.map_or(false, |(i, _)| i == offset) {
16574                        break;
16575                    };
16576                    if is_grapheme_whitespace(grapheme) != is_whitespace {
16577                        break;
16578                    };
16579                    offset += grapheme.len();
16580                    graphemes += 1;
16581                    iter.next();
16582                }
16583            }
16584            let token = &self.input[..offset];
16585            self.input = &self.input[offset..];
16586            if is_whitespace {
16587                Some(WordBreakToken {
16588                    token: " ",
16589                    grapheme_len: 1,
16590                    is_whitespace: true,
16591                })
16592            } else {
16593                Some(WordBreakToken {
16594                    token,
16595                    grapheme_len: graphemes,
16596                    is_whitespace: false,
16597                })
16598            }
16599        } else {
16600            None
16601        }
16602    }
16603}
16604
16605#[test]
16606fn test_word_breaking_tokenizer() {
16607    let tests: &[(&str, &[(&str, usize, bool)])] = &[
16608        ("", &[]),
16609        ("  ", &[(" ", 1, true)]),
16610        ("Ʒ", &[("Ʒ", 1, false)]),
16611        ("Ǽ", &[("Ǽ", 1, false)]),
16612        ("", &[("", 1, false)]),
16613        ("⋑⋑", &[("⋑⋑", 2, false)]),
16614        (
16615            "原理,进而",
16616            &[
16617                ("", 1, false),
16618                ("理,", 2, false),
16619                ("", 1, false),
16620                ("", 1, false),
16621            ],
16622        ),
16623        (
16624            "hello world",
16625            &[("hello", 5, false), (" ", 1, true), ("world", 5, false)],
16626        ),
16627        (
16628            "hello, world",
16629            &[("hello,", 6, false), (" ", 1, true), ("world", 5, false)],
16630        ),
16631        (
16632            "  hello world",
16633            &[
16634                (" ", 1, true),
16635                ("hello", 5, false),
16636                (" ", 1, true),
16637                ("world", 5, false),
16638            ],
16639        ),
16640        (
16641            "这是什么 \n 钢笔",
16642            &[
16643                ("", 1, false),
16644                ("", 1, false),
16645                ("", 1, false),
16646                ("", 1, false),
16647                (" ", 1, true),
16648                ("", 1, false),
16649                ("", 1, false),
16650            ],
16651        ),
16652        (" mutton", &[(" ", 1, true), ("mutton", 6, false)]),
16653    ];
16654
16655    for (input, result) in tests {
16656        assert_eq!(
16657            WordBreakingTokenizer::new(input).collect::<Vec<_>>(),
16658            result
16659                .iter()
16660                .copied()
16661                .map(|(token, grapheme_len, is_whitespace)| WordBreakToken {
16662                    token,
16663                    grapheme_len,
16664                    is_whitespace,
16665                })
16666                .collect::<Vec<_>>()
16667        );
16668    }
16669}
16670
16671fn wrap_with_prefix(
16672    line_prefix: String,
16673    unwrapped_text: String,
16674    wrap_column: usize,
16675    tab_size: NonZeroU32,
16676) -> String {
16677    let line_prefix_len = char_len_with_expanded_tabs(0, &line_prefix, tab_size);
16678    let mut wrapped_text = String::new();
16679    let mut current_line = line_prefix.clone();
16680
16681    let tokenizer = WordBreakingTokenizer::new(&unwrapped_text);
16682    let mut current_line_len = line_prefix_len;
16683    for WordBreakToken {
16684        token,
16685        grapheme_len,
16686        is_whitespace,
16687    } in tokenizer
16688    {
16689        if current_line_len + grapheme_len > wrap_column && current_line_len != line_prefix_len {
16690            wrapped_text.push_str(current_line.trim_end());
16691            wrapped_text.push('\n');
16692            current_line.truncate(line_prefix.len());
16693            current_line_len = line_prefix_len;
16694            if !is_whitespace {
16695                current_line.push_str(token);
16696                current_line_len += grapheme_len;
16697            }
16698        } else if !is_whitespace {
16699            current_line.push_str(token);
16700            current_line_len += grapheme_len;
16701        } else if current_line_len != line_prefix_len {
16702            current_line.push(' ');
16703            current_line_len += 1;
16704        }
16705    }
16706
16707    if !current_line.is_empty() {
16708        wrapped_text.push_str(&current_line);
16709    }
16710    wrapped_text
16711}
16712
16713#[test]
16714fn test_wrap_with_prefix() {
16715    assert_eq!(
16716        wrap_with_prefix(
16717            "# ".to_string(),
16718            "abcdefg".to_string(),
16719            4,
16720            NonZeroU32::new(4).unwrap()
16721        ),
16722        "# abcdefg"
16723    );
16724    assert_eq!(
16725        wrap_with_prefix(
16726            "".to_string(),
16727            "\thello world".to_string(),
16728            8,
16729            NonZeroU32::new(4).unwrap()
16730        ),
16731        "hello\nworld"
16732    );
16733    assert_eq!(
16734        wrap_with_prefix(
16735            "// ".to_string(),
16736            "xx \nyy zz aa bb cc".to_string(),
16737            12,
16738            NonZeroU32::new(4).unwrap()
16739        ),
16740        "// xx yy zz\n// aa bb cc"
16741    );
16742    assert_eq!(
16743        wrap_with_prefix(
16744            String::new(),
16745            "这是什么 \n 钢笔".to_string(),
16746            3,
16747            NonZeroU32::new(4).unwrap()
16748        ),
16749        "这是什\n么 钢\n"
16750    );
16751}
16752
16753pub trait CollaborationHub {
16754    fn collaborators<'a>(&self, cx: &'a App) -> &'a HashMap<PeerId, Collaborator>;
16755    fn user_participant_indices<'a>(&self, cx: &'a App) -> &'a HashMap<u64, ParticipantIndex>;
16756    fn user_names(&self, cx: &App) -> HashMap<u64, SharedString>;
16757}
16758
16759impl CollaborationHub for Entity<Project> {
16760    fn collaborators<'a>(&self, cx: &'a App) -> &'a HashMap<PeerId, Collaborator> {
16761        self.read(cx).collaborators()
16762    }
16763
16764    fn user_participant_indices<'a>(&self, cx: &'a App) -> &'a HashMap<u64, ParticipantIndex> {
16765        self.read(cx).user_store().read(cx).participant_indices()
16766    }
16767
16768    fn user_names(&self, cx: &App) -> HashMap<u64, SharedString> {
16769        let this = self.read(cx);
16770        let user_ids = this.collaborators().values().map(|c| c.user_id);
16771        this.user_store().read_with(cx, |user_store, cx| {
16772            user_store.participant_names(user_ids, cx)
16773        })
16774    }
16775}
16776
16777pub trait SemanticsProvider {
16778    fn hover(
16779        &self,
16780        buffer: &Entity<Buffer>,
16781        position: text::Anchor,
16782        cx: &mut App,
16783    ) -> Option<Task<Vec<project::Hover>>>;
16784
16785    fn inlay_hints(
16786        &self,
16787        buffer_handle: Entity<Buffer>,
16788        range: Range<text::Anchor>,
16789        cx: &mut App,
16790    ) -> Option<Task<anyhow::Result<Vec<InlayHint>>>>;
16791
16792    fn resolve_inlay_hint(
16793        &self,
16794        hint: InlayHint,
16795        buffer_handle: Entity<Buffer>,
16796        server_id: LanguageServerId,
16797        cx: &mut App,
16798    ) -> Option<Task<anyhow::Result<InlayHint>>>;
16799
16800    fn supports_inlay_hints(&self, buffer: &Entity<Buffer>, cx: &mut App) -> bool;
16801
16802    fn document_highlights(
16803        &self,
16804        buffer: &Entity<Buffer>,
16805        position: text::Anchor,
16806        cx: &mut App,
16807    ) -> Option<Task<Result<Vec<DocumentHighlight>>>>;
16808
16809    fn definitions(
16810        &self,
16811        buffer: &Entity<Buffer>,
16812        position: text::Anchor,
16813        kind: GotoDefinitionKind,
16814        cx: &mut App,
16815    ) -> Option<Task<Result<Vec<LocationLink>>>>;
16816
16817    fn range_for_rename(
16818        &self,
16819        buffer: &Entity<Buffer>,
16820        position: text::Anchor,
16821        cx: &mut App,
16822    ) -> Option<Task<Result<Option<Range<text::Anchor>>>>>;
16823
16824    fn perform_rename(
16825        &self,
16826        buffer: &Entity<Buffer>,
16827        position: text::Anchor,
16828        new_name: String,
16829        cx: &mut App,
16830    ) -> Option<Task<Result<ProjectTransaction>>>;
16831}
16832
16833pub trait CompletionProvider {
16834    fn completions(
16835        &self,
16836        buffer: &Entity<Buffer>,
16837        buffer_position: text::Anchor,
16838        trigger: CompletionContext,
16839        window: &mut Window,
16840        cx: &mut Context<Editor>,
16841    ) -> Task<Result<Vec<Completion>>>;
16842
16843    fn resolve_completions(
16844        &self,
16845        buffer: Entity<Buffer>,
16846        completion_indices: Vec<usize>,
16847        completions: Rc<RefCell<Box<[Completion]>>>,
16848        cx: &mut Context<Editor>,
16849    ) -> Task<Result<bool>>;
16850
16851    fn apply_additional_edits_for_completion(
16852        &self,
16853        _buffer: Entity<Buffer>,
16854        _completions: Rc<RefCell<Box<[Completion]>>>,
16855        _completion_index: usize,
16856        _push_to_history: bool,
16857        _cx: &mut Context<Editor>,
16858    ) -> Task<Result<Option<language::Transaction>>> {
16859        Task::ready(Ok(None))
16860    }
16861
16862    fn is_completion_trigger(
16863        &self,
16864        buffer: &Entity<Buffer>,
16865        position: language::Anchor,
16866        text: &str,
16867        trigger_in_words: bool,
16868        cx: &mut Context<Editor>,
16869    ) -> bool;
16870
16871    fn sort_completions(&self) -> bool {
16872        true
16873    }
16874}
16875
16876pub trait CodeActionProvider {
16877    fn id(&self) -> Arc<str>;
16878
16879    fn code_actions(
16880        &self,
16881        buffer: &Entity<Buffer>,
16882        range: Range<text::Anchor>,
16883        window: &mut Window,
16884        cx: &mut App,
16885    ) -> Task<Result<Vec<CodeAction>>>;
16886
16887    fn apply_code_action(
16888        &self,
16889        buffer_handle: Entity<Buffer>,
16890        action: CodeAction,
16891        excerpt_id: ExcerptId,
16892        push_to_history: bool,
16893        window: &mut Window,
16894        cx: &mut App,
16895    ) -> Task<Result<ProjectTransaction>>;
16896}
16897
16898impl CodeActionProvider for Entity<Project> {
16899    fn id(&self) -> Arc<str> {
16900        "project".into()
16901    }
16902
16903    fn code_actions(
16904        &self,
16905        buffer: &Entity<Buffer>,
16906        range: Range<text::Anchor>,
16907        _window: &mut Window,
16908        cx: &mut App,
16909    ) -> Task<Result<Vec<CodeAction>>> {
16910        self.update(cx, |project, cx| {
16911            project.code_actions(buffer, range, None, cx)
16912        })
16913    }
16914
16915    fn apply_code_action(
16916        &self,
16917        buffer_handle: Entity<Buffer>,
16918        action: CodeAction,
16919        _excerpt_id: ExcerptId,
16920        push_to_history: bool,
16921        _window: &mut Window,
16922        cx: &mut App,
16923    ) -> Task<Result<ProjectTransaction>> {
16924        self.update(cx, |project, cx| {
16925            project.apply_code_action(buffer_handle, action, push_to_history, cx)
16926        })
16927    }
16928}
16929
16930fn snippet_completions(
16931    project: &Project,
16932    buffer: &Entity<Buffer>,
16933    buffer_position: text::Anchor,
16934    cx: &mut App,
16935) -> Task<Result<Vec<Completion>>> {
16936    let language = buffer.read(cx).language_at(buffer_position);
16937    let language_name = language.as_ref().map(|language| language.lsp_id());
16938    let snippet_store = project.snippets().read(cx);
16939    let snippets = snippet_store.snippets_for(language_name, cx);
16940
16941    if snippets.is_empty() {
16942        return Task::ready(Ok(vec![]));
16943    }
16944    let snapshot = buffer.read(cx).text_snapshot();
16945    let chars: String = snapshot
16946        .reversed_chars_for_range(text::Anchor::MIN..buffer_position)
16947        .collect();
16948
16949    let scope = language.map(|language| language.default_scope());
16950    let executor = cx.background_executor().clone();
16951
16952    cx.background_spawn(async move {
16953        let classifier = CharClassifier::new(scope).for_completion(true);
16954        let mut last_word = chars
16955            .chars()
16956            .take_while(|c| classifier.is_word(*c))
16957            .collect::<String>();
16958        last_word = last_word.chars().rev().collect();
16959
16960        if last_word.is_empty() {
16961            return Ok(vec![]);
16962        }
16963
16964        let as_offset = text::ToOffset::to_offset(&buffer_position, &snapshot);
16965        let to_lsp = |point: &text::Anchor| {
16966            let end = text::ToPointUtf16::to_point_utf16(point, &snapshot);
16967            point_to_lsp(end)
16968        };
16969        let lsp_end = to_lsp(&buffer_position);
16970
16971        let candidates = snippets
16972            .iter()
16973            .enumerate()
16974            .flat_map(|(ix, snippet)| {
16975                snippet
16976                    .prefix
16977                    .iter()
16978                    .map(move |prefix| StringMatchCandidate::new(ix, &prefix))
16979            })
16980            .collect::<Vec<StringMatchCandidate>>();
16981
16982        let mut matches = fuzzy::match_strings(
16983            &candidates,
16984            &last_word,
16985            last_word.chars().any(|c| c.is_uppercase()),
16986            100,
16987            &Default::default(),
16988            executor,
16989        )
16990        .await;
16991
16992        // Remove all candidates where the query's start does not match the start of any word in the candidate
16993        if let Some(query_start) = last_word.chars().next() {
16994            matches.retain(|string_match| {
16995                split_words(&string_match.string).any(|word| {
16996                    // Check that the first codepoint of the word as lowercase matches the first
16997                    // codepoint of the query as lowercase
16998                    word.chars()
16999                        .flat_map(|codepoint| codepoint.to_lowercase())
17000                        .zip(query_start.to_lowercase())
17001                        .all(|(word_cp, query_cp)| word_cp == query_cp)
17002                })
17003            });
17004        }
17005
17006        let matched_strings = matches
17007            .into_iter()
17008            .map(|m| m.string)
17009            .collect::<HashSet<_>>();
17010
17011        let result: Vec<Completion> = snippets
17012            .into_iter()
17013            .filter_map(|snippet| {
17014                let matching_prefix = snippet
17015                    .prefix
17016                    .iter()
17017                    .find(|prefix| matched_strings.contains(*prefix))?;
17018                let start = as_offset - last_word.len();
17019                let start = snapshot.anchor_before(start);
17020                let range = start..buffer_position;
17021                let lsp_start = to_lsp(&start);
17022                let lsp_range = lsp::Range {
17023                    start: lsp_start,
17024                    end: lsp_end,
17025                };
17026                Some(Completion {
17027                    old_range: range,
17028                    new_text: snippet.body.clone(),
17029                    source: CompletionSource::Lsp {
17030                        server_id: LanguageServerId(usize::MAX),
17031                        resolved: true,
17032                        lsp_completion: Box::new(lsp::CompletionItem {
17033                            label: snippet.prefix.first().unwrap().clone(),
17034                            kind: Some(CompletionItemKind::SNIPPET),
17035                            label_details: snippet.description.as_ref().map(|description| {
17036                                lsp::CompletionItemLabelDetails {
17037                                    detail: Some(description.clone()),
17038                                    description: None,
17039                                }
17040                            }),
17041                            insert_text_format: Some(InsertTextFormat::SNIPPET),
17042                            text_edit: Some(lsp::CompletionTextEdit::InsertAndReplace(
17043                                lsp::InsertReplaceEdit {
17044                                    new_text: snippet.body.clone(),
17045                                    insert: lsp_range,
17046                                    replace: lsp_range,
17047                                },
17048                            )),
17049                            filter_text: Some(snippet.body.clone()),
17050                            sort_text: Some(char::MAX.to_string()),
17051                            ..lsp::CompletionItem::default()
17052                        }),
17053                        lsp_defaults: None,
17054                    },
17055                    label: CodeLabel {
17056                        text: matching_prefix.clone(),
17057                        runs: Vec::new(),
17058                        filter_range: 0..matching_prefix.len(),
17059                    },
17060                    documentation: snippet
17061                        .description
17062                        .clone()
17063                        .map(|description| CompletionDocumentation::SingleLine(description.into())),
17064                    confirm: None,
17065                })
17066            })
17067            .collect();
17068
17069        Ok(result)
17070    })
17071}
17072
17073impl CompletionProvider for Entity<Project> {
17074    fn completions(
17075        &self,
17076        buffer: &Entity<Buffer>,
17077        buffer_position: text::Anchor,
17078        options: CompletionContext,
17079        _window: &mut Window,
17080        cx: &mut Context<Editor>,
17081    ) -> Task<Result<Vec<Completion>>> {
17082        self.update(cx, |project, cx| {
17083            let snippets = snippet_completions(project, buffer, buffer_position, cx);
17084            let project_completions = project.completions(buffer, buffer_position, options, cx);
17085            cx.background_spawn(async move {
17086                let mut completions = project_completions.await?;
17087                let snippets_completions = snippets.await?;
17088                completions.extend(snippets_completions);
17089                Ok(completions)
17090            })
17091        })
17092    }
17093
17094    fn resolve_completions(
17095        &self,
17096        buffer: Entity<Buffer>,
17097        completion_indices: Vec<usize>,
17098        completions: Rc<RefCell<Box<[Completion]>>>,
17099        cx: &mut Context<Editor>,
17100    ) -> Task<Result<bool>> {
17101        self.update(cx, |project, cx| {
17102            project.lsp_store().update(cx, |lsp_store, cx| {
17103                lsp_store.resolve_completions(buffer, completion_indices, completions, cx)
17104            })
17105        })
17106    }
17107
17108    fn apply_additional_edits_for_completion(
17109        &self,
17110        buffer: Entity<Buffer>,
17111        completions: Rc<RefCell<Box<[Completion]>>>,
17112        completion_index: usize,
17113        push_to_history: bool,
17114        cx: &mut Context<Editor>,
17115    ) -> Task<Result<Option<language::Transaction>>> {
17116        self.update(cx, |project, cx| {
17117            project.lsp_store().update(cx, |lsp_store, cx| {
17118                lsp_store.apply_additional_edits_for_completion(
17119                    buffer,
17120                    completions,
17121                    completion_index,
17122                    push_to_history,
17123                    cx,
17124                )
17125            })
17126        })
17127    }
17128
17129    fn is_completion_trigger(
17130        &self,
17131        buffer: &Entity<Buffer>,
17132        position: language::Anchor,
17133        text: &str,
17134        trigger_in_words: bool,
17135        cx: &mut Context<Editor>,
17136    ) -> bool {
17137        let mut chars = text.chars();
17138        let char = if let Some(char) = chars.next() {
17139            char
17140        } else {
17141            return false;
17142        };
17143        if chars.next().is_some() {
17144            return false;
17145        }
17146
17147        let buffer = buffer.read(cx);
17148        let snapshot = buffer.snapshot();
17149        if !snapshot.settings_at(position, cx).show_completions_on_input {
17150            return false;
17151        }
17152        let classifier = snapshot.char_classifier_at(position).for_completion(true);
17153        if trigger_in_words && classifier.is_word(char) {
17154            return true;
17155        }
17156
17157        buffer.completion_triggers().contains(text)
17158    }
17159}
17160
17161impl SemanticsProvider for Entity<Project> {
17162    fn hover(
17163        &self,
17164        buffer: &Entity<Buffer>,
17165        position: text::Anchor,
17166        cx: &mut App,
17167    ) -> Option<Task<Vec<project::Hover>>> {
17168        Some(self.update(cx, |project, cx| project.hover(buffer, position, cx)))
17169    }
17170
17171    fn document_highlights(
17172        &self,
17173        buffer: &Entity<Buffer>,
17174        position: text::Anchor,
17175        cx: &mut App,
17176    ) -> Option<Task<Result<Vec<DocumentHighlight>>>> {
17177        Some(self.update(cx, |project, cx| {
17178            project.document_highlights(buffer, position, cx)
17179        }))
17180    }
17181
17182    fn definitions(
17183        &self,
17184        buffer: &Entity<Buffer>,
17185        position: text::Anchor,
17186        kind: GotoDefinitionKind,
17187        cx: &mut App,
17188    ) -> Option<Task<Result<Vec<LocationLink>>>> {
17189        Some(self.update(cx, |project, cx| match kind {
17190            GotoDefinitionKind::Symbol => project.definition(&buffer, position, cx),
17191            GotoDefinitionKind::Declaration => project.declaration(&buffer, position, cx),
17192            GotoDefinitionKind::Type => project.type_definition(&buffer, position, cx),
17193            GotoDefinitionKind::Implementation => project.implementation(&buffer, position, cx),
17194        }))
17195    }
17196
17197    fn supports_inlay_hints(&self, buffer: &Entity<Buffer>, cx: &mut App) -> bool {
17198        // TODO: make this work for remote projects
17199        self.update(cx, |this, cx| {
17200            buffer.update(cx, |buffer, cx| {
17201                this.any_language_server_supports_inlay_hints(buffer, cx)
17202            })
17203        })
17204    }
17205
17206    fn inlay_hints(
17207        &self,
17208        buffer_handle: Entity<Buffer>,
17209        range: Range<text::Anchor>,
17210        cx: &mut App,
17211    ) -> Option<Task<anyhow::Result<Vec<InlayHint>>>> {
17212        Some(self.update(cx, |project, cx| {
17213            project.inlay_hints(buffer_handle, range, cx)
17214        }))
17215    }
17216
17217    fn resolve_inlay_hint(
17218        &self,
17219        hint: InlayHint,
17220        buffer_handle: Entity<Buffer>,
17221        server_id: LanguageServerId,
17222        cx: &mut App,
17223    ) -> Option<Task<anyhow::Result<InlayHint>>> {
17224        Some(self.update(cx, |project, cx| {
17225            project.resolve_inlay_hint(hint, buffer_handle, server_id, cx)
17226        }))
17227    }
17228
17229    fn range_for_rename(
17230        &self,
17231        buffer: &Entity<Buffer>,
17232        position: text::Anchor,
17233        cx: &mut App,
17234    ) -> Option<Task<Result<Option<Range<text::Anchor>>>>> {
17235        Some(self.update(cx, |project, cx| {
17236            let buffer = buffer.clone();
17237            let task = project.prepare_rename(buffer.clone(), position, cx);
17238            cx.spawn(|_, mut cx| async move {
17239                Ok(match task.await? {
17240                    PrepareRenameResponse::Success(range) => Some(range),
17241                    PrepareRenameResponse::InvalidPosition => None,
17242                    PrepareRenameResponse::OnlyUnpreparedRenameSupported => {
17243                        // Fallback on using TreeSitter info to determine identifier range
17244                        buffer.update(&mut cx, |buffer, _| {
17245                            let snapshot = buffer.snapshot();
17246                            let (range, kind) = snapshot.surrounding_word(position);
17247                            if kind != Some(CharKind::Word) {
17248                                return None;
17249                            }
17250                            Some(
17251                                snapshot.anchor_before(range.start)
17252                                    ..snapshot.anchor_after(range.end),
17253                            )
17254                        })?
17255                    }
17256                })
17257            })
17258        }))
17259    }
17260
17261    fn perform_rename(
17262        &self,
17263        buffer: &Entity<Buffer>,
17264        position: text::Anchor,
17265        new_name: String,
17266        cx: &mut App,
17267    ) -> Option<Task<Result<ProjectTransaction>>> {
17268        Some(self.update(cx, |project, cx| {
17269            project.perform_rename(buffer.clone(), position, new_name, cx)
17270        }))
17271    }
17272}
17273
17274fn inlay_hint_settings(
17275    location: Anchor,
17276    snapshot: &MultiBufferSnapshot,
17277    cx: &mut Context<Editor>,
17278) -> InlayHintSettings {
17279    let file = snapshot.file_at(location);
17280    let language = snapshot.language_at(location).map(|l| l.name());
17281    language_settings(language, file, cx).inlay_hints
17282}
17283
17284fn consume_contiguous_rows(
17285    contiguous_row_selections: &mut Vec<Selection<Point>>,
17286    selection: &Selection<Point>,
17287    display_map: &DisplaySnapshot,
17288    selections: &mut Peekable<std::slice::Iter<Selection<Point>>>,
17289) -> (MultiBufferRow, MultiBufferRow) {
17290    contiguous_row_selections.push(selection.clone());
17291    let start_row = MultiBufferRow(selection.start.row);
17292    let mut end_row = ending_row(selection, display_map);
17293
17294    while let Some(next_selection) = selections.peek() {
17295        if next_selection.start.row <= end_row.0 {
17296            end_row = ending_row(next_selection, display_map);
17297            contiguous_row_selections.push(selections.next().unwrap().clone());
17298        } else {
17299            break;
17300        }
17301    }
17302    (start_row, end_row)
17303}
17304
17305fn ending_row(next_selection: &Selection<Point>, display_map: &DisplaySnapshot) -> MultiBufferRow {
17306    if next_selection.end.column > 0 || next_selection.is_empty() {
17307        MultiBufferRow(display_map.next_line_boundary(next_selection.end).0.row + 1)
17308    } else {
17309        MultiBufferRow(next_selection.end.row)
17310    }
17311}
17312
17313impl EditorSnapshot {
17314    pub fn remote_selections_in_range<'a>(
17315        &'a self,
17316        range: &'a Range<Anchor>,
17317        collaboration_hub: &dyn CollaborationHub,
17318        cx: &'a App,
17319    ) -> impl 'a + Iterator<Item = RemoteSelection> {
17320        let participant_names = collaboration_hub.user_names(cx);
17321        let participant_indices = collaboration_hub.user_participant_indices(cx);
17322        let collaborators_by_peer_id = collaboration_hub.collaborators(cx);
17323        let collaborators_by_replica_id = collaborators_by_peer_id
17324            .iter()
17325            .map(|(_, collaborator)| (collaborator.replica_id, collaborator))
17326            .collect::<HashMap<_, _>>();
17327        self.buffer_snapshot
17328            .selections_in_range(range, false)
17329            .filter_map(move |(replica_id, line_mode, cursor_shape, selection)| {
17330                let collaborator = collaborators_by_replica_id.get(&replica_id)?;
17331                let participant_index = participant_indices.get(&collaborator.user_id).copied();
17332                let user_name = participant_names.get(&collaborator.user_id).cloned();
17333                Some(RemoteSelection {
17334                    replica_id,
17335                    selection,
17336                    cursor_shape,
17337                    line_mode,
17338                    participant_index,
17339                    peer_id: collaborator.peer_id,
17340                    user_name,
17341                })
17342            })
17343    }
17344
17345    pub fn hunks_for_ranges(
17346        &self,
17347        ranges: impl IntoIterator<Item = Range<Point>>,
17348    ) -> Vec<MultiBufferDiffHunk> {
17349        let mut hunks = Vec::new();
17350        let mut processed_buffer_rows: HashMap<BufferId, HashSet<Range<text::Anchor>>> =
17351            HashMap::default();
17352        for query_range in ranges {
17353            let query_rows =
17354                MultiBufferRow(query_range.start.row)..MultiBufferRow(query_range.end.row + 1);
17355            for hunk in self.buffer_snapshot.diff_hunks_in_range(
17356                Point::new(query_rows.start.0, 0)..Point::new(query_rows.end.0, 0),
17357            ) {
17358                // Include deleted hunks that are adjacent to the query range, because
17359                // otherwise they would be missed.
17360                let mut intersects_range = hunk.row_range.overlaps(&query_rows);
17361                if hunk.status().is_deleted() {
17362                    intersects_range |= hunk.row_range.start == query_rows.end;
17363                    intersects_range |= hunk.row_range.end == query_rows.start;
17364                }
17365                if intersects_range {
17366                    if !processed_buffer_rows
17367                        .entry(hunk.buffer_id)
17368                        .or_default()
17369                        .insert(hunk.buffer_range.start..hunk.buffer_range.end)
17370                    {
17371                        continue;
17372                    }
17373                    hunks.push(hunk);
17374                }
17375            }
17376        }
17377
17378        hunks
17379    }
17380
17381    fn display_diff_hunks_for_rows<'a>(
17382        &'a self,
17383        display_rows: Range<DisplayRow>,
17384        folded_buffers: &'a HashSet<BufferId>,
17385    ) -> impl 'a + Iterator<Item = DisplayDiffHunk> {
17386        let buffer_start = DisplayPoint::new(display_rows.start, 0).to_point(self);
17387        let buffer_end = DisplayPoint::new(display_rows.end, 0).to_point(self);
17388
17389        self.buffer_snapshot
17390            .diff_hunks_in_range(buffer_start..buffer_end)
17391            .filter_map(|hunk| {
17392                if folded_buffers.contains(&hunk.buffer_id) {
17393                    return None;
17394                }
17395
17396                let hunk_start_point = Point::new(hunk.row_range.start.0, 0);
17397                let hunk_end_point = Point::new(hunk.row_range.end.0, 0);
17398
17399                let hunk_display_start = self.point_to_display_point(hunk_start_point, Bias::Left);
17400                let hunk_display_end = self.point_to_display_point(hunk_end_point, Bias::Right);
17401
17402                let display_hunk = if hunk_display_start.column() != 0 {
17403                    DisplayDiffHunk::Folded {
17404                        display_row: hunk_display_start.row(),
17405                    }
17406                } else {
17407                    let mut end_row = hunk_display_end.row();
17408                    if hunk_display_end.column() > 0 {
17409                        end_row.0 += 1;
17410                    }
17411                    let is_created_file = hunk.is_created_file();
17412                    DisplayDiffHunk::Unfolded {
17413                        status: hunk.status(),
17414                        diff_base_byte_range: hunk.diff_base_byte_range,
17415                        display_row_range: hunk_display_start.row()..end_row,
17416                        multi_buffer_range: Anchor::range_in_buffer(
17417                            hunk.excerpt_id,
17418                            hunk.buffer_id,
17419                            hunk.buffer_range,
17420                        ),
17421                        is_created_file,
17422                    }
17423                };
17424
17425                Some(display_hunk)
17426            })
17427    }
17428
17429    pub fn language_at<T: ToOffset>(&self, position: T) -> Option<&Arc<Language>> {
17430        self.display_snapshot.buffer_snapshot.language_at(position)
17431    }
17432
17433    pub fn is_focused(&self) -> bool {
17434        self.is_focused
17435    }
17436
17437    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
17438        self.placeholder_text.as_ref()
17439    }
17440
17441    pub fn scroll_position(&self) -> gpui::Point<f32> {
17442        self.scroll_anchor.scroll_position(&self.display_snapshot)
17443    }
17444
17445    fn gutter_dimensions(
17446        &self,
17447        font_id: FontId,
17448        font_size: Pixels,
17449        max_line_number_width: Pixels,
17450        cx: &App,
17451    ) -> Option<GutterDimensions> {
17452        if !self.show_gutter {
17453            return None;
17454        }
17455
17456        let descent = cx.text_system().descent(font_id, font_size);
17457        let em_width = cx.text_system().em_width(font_id, font_size).log_err()?;
17458        let em_advance = cx.text_system().em_advance(font_id, font_size).log_err()?;
17459
17460        let show_git_gutter = self.show_git_diff_gutter.unwrap_or_else(|| {
17461            matches!(
17462                ProjectSettings::get_global(cx).git.git_gutter,
17463                Some(GitGutterSetting::TrackedFiles)
17464            )
17465        });
17466        let gutter_settings = EditorSettings::get_global(cx).gutter;
17467        let show_line_numbers = self
17468            .show_line_numbers
17469            .unwrap_or(gutter_settings.line_numbers);
17470        let line_gutter_width = if show_line_numbers {
17471            // Avoid flicker-like gutter resizes when the line number gains another digit and only resize the gutter on files with N*10^5 lines.
17472            let min_width_for_number_on_gutter = em_advance * 4.0;
17473            max_line_number_width.max(min_width_for_number_on_gutter)
17474        } else {
17475            0.0.into()
17476        };
17477
17478        let show_code_actions = self
17479            .show_code_actions
17480            .unwrap_or(gutter_settings.code_actions);
17481
17482        let show_runnables = self.show_runnables.unwrap_or(gutter_settings.runnables);
17483
17484        let git_blame_entries_width =
17485            self.git_blame_gutter_max_author_length
17486                .map(|max_author_length| {
17487                    const MAX_RELATIVE_TIMESTAMP: &str = "60 minutes ago";
17488
17489                    /// The number of characters to dedicate to gaps and margins.
17490                    const SPACING_WIDTH: usize = 4;
17491
17492                    let max_char_count = max_author_length
17493                        .min(GIT_BLAME_MAX_AUTHOR_CHARS_DISPLAYED)
17494                        + ::git::SHORT_SHA_LENGTH
17495                        + MAX_RELATIVE_TIMESTAMP.len()
17496                        + SPACING_WIDTH;
17497
17498                    em_advance * max_char_count
17499                });
17500
17501        let mut left_padding = git_blame_entries_width.unwrap_or(Pixels::ZERO);
17502        left_padding += if show_code_actions || show_runnables {
17503            em_width * 3.0
17504        } else if show_git_gutter && show_line_numbers {
17505            em_width * 2.0
17506        } else if show_git_gutter || show_line_numbers {
17507            em_width
17508        } else {
17509            px(0.)
17510        };
17511
17512        let right_padding = if gutter_settings.folds && show_line_numbers {
17513            em_width * 4.0
17514        } else if gutter_settings.folds {
17515            em_width * 3.0
17516        } else if show_line_numbers {
17517            em_width
17518        } else {
17519            px(0.)
17520        };
17521
17522        Some(GutterDimensions {
17523            left_padding,
17524            right_padding,
17525            width: line_gutter_width + left_padding + right_padding,
17526            margin: -descent,
17527            git_blame_entries_width,
17528        })
17529    }
17530
17531    pub fn render_crease_toggle(
17532        &self,
17533        buffer_row: MultiBufferRow,
17534        row_contains_cursor: bool,
17535        editor: Entity<Editor>,
17536        window: &mut Window,
17537        cx: &mut App,
17538    ) -> Option<AnyElement> {
17539        let folded = self.is_line_folded(buffer_row);
17540        let mut is_foldable = false;
17541
17542        if let Some(crease) = self
17543            .crease_snapshot
17544            .query_row(buffer_row, &self.buffer_snapshot)
17545        {
17546            is_foldable = true;
17547            match crease {
17548                Crease::Inline { render_toggle, .. } | Crease::Block { render_toggle, .. } => {
17549                    if let Some(render_toggle) = render_toggle {
17550                        let toggle_callback =
17551                            Arc::new(move |folded, window: &mut Window, cx: &mut App| {
17552                                if folded {
17553                                    editor.update(cx, |editor, cx| {
17554                                        editor.fold_at(&crate::FoldAt { buffer_row }, window, cx)
17555                                    });
17556                                } else {
17557                                    editor.update(cx, |editor, cx| {
17558                                        editor.unfold_at(
17559                                            &crate::UnfoldAt { buffer_row },
17560                                            window,
17561                                            cx,
17562                                        )
17563                                    });
17564                                }
17565                            });
17566                        return Some((render_toggle)(
17567                            buffer_row,
17568                            folded,
17569                            toggle_callback,
17570                            window,
17571                            cx,
17572                        ));
17573                    }
17574                }
17575            }
17576        }
17577
17578        is_foldable |= self.starts_indent(buffer_row);
17579
17580        if folded || (is_foldable && (row_contains_cursor || self.gutter_hovered)) {
17581            Some(
17582                Disclosure::new(("gutter_crease", buffer_row.0), !folded)
17583                    .toggle_state(folded)
17584                    .on_click(window.listener_for(&editor, move |this, _e, window, cx| {
17585                        if folded {
17586                            this.unfold_at(&UnfoldAt { buffer_row }, window, cx);
17587                        } else {
17588                            this.fold_at(&FoldAt { buffer_row }, window, cx);
17589                        }
17590                    }))
17591                    .into_any_element(),
17592            )
17593        } else {
17594            None
17595        }
17596    }
17597
17598    pub fn render_crease_trailer(
17599        &self,
17600        buffer_row: MultiBufferRow,
17601        window: &mut Window,
17602        cx: &mut App,
17603    ) -> Option<AnyElement> {
17604        let folded = self.is_line_folded(buffer_row);
17605        if let Crease::Inline { render_trailer, .. } = self
17606            .crease_snapshot
17607            .query_row(buffer_row, &self.buffer_snapshot)?
17608        {
17609            let render_trailer = render_trailer.as_ref()?;
17610            Some(render_trailer(buffer_row, folded, window, cx))
17611        } else {
17612            None
17613        }
17614    }
17615}
17616
17617impl Deref for EditorSnapshot {
17618    type Target = DisplaySnapshot;
17619
17620    fn deref(&self) -> &Self::Target {
17621        &self.display_snapshot
17622    }
17623}
17624
17625#[derive(Clone, Debug, PartialEq, Eq)]
17626pub enum EditorEvent {
17627    InputIgnored {
17628        text: Arc<str>,
17629    },
17630    InputHandled {
17631        utf16_range_to_replace: Option<Range<isize>>,
17632        text: Arc<str>,
17633    },
17634    ExcerptsAdded {
17635        buffer: Entity<Buffer>,
17636        predecessor: ExcerptId,
17637        excerpts: Vec<(ExcerptId, ExcerptRange<language::Anchor>)>,
17638    },
17639    ExcerptsRemoved {
17640        ids: Vec<ExcerptId>,
17641    },
17642    BufferFoldToggled {
17643        ids: Vec<ExcerptId>,
17644        folded: bool,
17645    },
17646    ExcerptsEdited {
17647        ids: Vec<ExcerptId>,
17648    },
17649    ExcerptsExpanded {
17650        ids: Vec<ExcerptId>,
17651    },
17652    BufferEdited,
17653    Edited {
17654        transaction_id: clock::Lamport,
17655    },
17656    Reparsed(BufferId),
17657    Focused,
17658    FocusedIn,
17659    Blurred,
17660    DirtyChanged,
17661    Saved,
17662    TitleChanged,
17663    DiffBaseChanged,
17664    SelectionsChanged {
17665        local: bool,
17666    },
17667    ScrollPositionChanged {
17668        local: bool,
17669        autoscroll: bool,
17670    },
17671    Closed,
17672    TransactionUndone {
17673        transaction_id: clock::Lamport,
17674    },
17675    TransactionBegun {
17676        transaction_id: clock::Lamport,
17677    },
17678    Reloaded,
17679    CursorShapeChanged,
17680}
17681
17682impl EventEmitter<EditorEvent> for Editor {}
17683
17684impl Focusable for Editor {
17685    fn focus_handle(&self, _cx: &App) -> FocusHandle {
17686        self.focus_handle.clone()
17687    }
17688}
17689
17690impl Render for Editor {
17691    fn render(&mut self, _: &mut Window, cx: &mut Context<'_, Self>) -> impl IntoElement {
17692        let settings = ThemeSettings::get_global(cx);
17693
17694        let mut text_style = match self.mode {
17695            EditorMode::SingleLine { .. } | EditorMode::AutoHeight { .. } => TextStyle {
17696                color: cx.theme().colors().editor_foreground,
17697                font_family: settings.ui_font.family.clone(),
17698                font_features: settings.ui_font.features.clone(),
17699                font_fallbacks: settings.ui_font.fallbacks.clone(),
17700                font_size: rems(0.875).into(),
17701                font_weight: settings.ui_font.weight,
17702                line_height: relative(settings.buffer_line_height.value()),
17703                ..Default::default()
17704            },
17705            EditorMode::Full => TextStyle {
17706                color: cx.theme().colors().editor_foreground,
17707                font_family: settings.buffer_font.family.clone(),
17708                font_features: settings.buffer_font.features.clone(),
17709                font_fallbacks: settings.buffer_font.fallbacks.clone(),
17710                font_size: settings.buffer_font_size(cx).into(),
17711                font_weight: settings.buffer_font.weight,
17712                line_height: relative(settings.buffer_line_height.value()),
17713                ..Default::default()
17714            },
17715        };
17716        if let Some(text_style_refinement) = &self.text_style_refinement {
17717            text_style.refine(text_style_refinement)
17718        }
17719
17720        let background = match self.mode {
17721            EditorMode::SingleLine { .. } => cx.theme().system().transparent,
17722            EditorMode::AutoHeight { max_lines: _ } => cx.theme().system().transparent,
17723            EditorMode::Full => cx.theme().colors().editor_background,
17724        };
17725
17726        EditorElement::new(
17727            &cx.entity(),
17728            EditorStyle {
17729                background,
17730                local_player: cx.theme().players().local(),
17731                text: text_style,
17732                scrollbar_width: EditorElement::SCROLLBAR_WIDTH,
17733                syntax: cx.theme().syntax().clone(),
17734                status: cx.theme().status().clone(),
17735                inlay_hints_style: make_inlay_hints_style(cx),
17736                inline_completion_styles: make_suggestion_styles(cx),
17737                unnecessary_code_fade: ThemeSettings::get_global(cx).unnecessary_code_fade,
17738            },
17739        )
17740    }
17741}
17742
17743impl EntityInputHandler for Editor {
17744    fn text_for_range(
17745        &mut self,
17746        range_utf16: Range<usize>,
17747        adjusted_range: &mut Option<Range<usize>>,
17748        _: &mut Window,
17749        cx: &mut Context<Self>,
17750    ) -> Option<String> {
17751        let snapshot = self.buffer.read(cx).read(cx);
17752        let start = snapshot.clip_offset_utf16(OffsetUtf16(range_utf16.start), Bias::Left);
17753        let end = snapshot.clip_offset_utf16(OffsetUtf16(range_utf16.end), Bias::Right);
17754        if (start.0..end.0) != range_utf16 {
17755            adjusted_range.replace(start.0..end.0);
17756        }
17757        Some(snapshot.text_for_range(start..end).collect())
17758    }
17759
17760    fn selected_text_range(
17761        &mut self,
17762        ignore_disabled_input: bool,
17763        _: &mut Window,
17764        cx: &mut Context<Self>,
17765    ) -> Option<UTF16Selection> {
17766        // Prevent the IME menu from appearing when holding down an alphabetic key
17767        // while input is disabled.
17768        if !ignore_disabled_input && !self.input_enabled {
17769            return None;
17770        }
17771
17772        let selection = self.selections.newest::<OffsetUtf16>(cx);
17773        let range = selection.range();
17774
17775        Some(UTF16Selection {
17776            range: range.start.0..range.end.0,
17777            reversed: selection.reversed,
17778        })
17779    }
17780
17781    fn marked_text_range(&self, _: &mut Window, cx: &mut Context<Self>) -> Option<Range<usize>> {
17782        let snapshot = self.buffer.read(cx).read(cx);
17783        let range = self.text_highlights::<InputComposition>(cx)?.1.first()?;
17784        Some(range.start.to_offset_utf16(&snapshot).0..range.end.to_offset_utf16(&snapshot).0)
17785    }
17786
17787    fn unmark_text(&mut self, _: &mut Window, cx: &mut Context<Self>) {
17788        self.clear_highlights::<InputComposition>(cx);
17789        self.ime_transaction.take();
17790    }
17791
17792    fn replace_text_in_range(
17793        &mut self,
17794        range_utf16: Option<Range<usize>>,
17795        text: &str,
17796        window: &mut Window,
17797        cx: &mut Context<Self>,
17798    ) {
17799        if !self.input_enabled {
17800            cx.emit(EditorEvent::InputIgnored { text: text.into() });
17801            return;
17802        }
17803
17804        self.transact(window, cx, |this, window, cx| {
17805            let new_selected_ranges = if let Some(range_utf16) = range_utf16 {
17806                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
17807                Some(this.selection_replacement_ranges(range_utf16, cx))
17808            } else {
17809                this.marked_text_ranges(cx)
17810            };
17811
17812            let range_to_replace = new_selected_ranges.as_ref().and_then(|ranges_to_replace| {
17813                let newest_selection_id = this.selections.newest_anchor().id;
17814                this.selections
17815                    .all::<OffsetUtf16>(cx)
17816                    .iter()
17817                    .zip(ranges_to_replace.iter())
17818                    .find_map(|(selection, range)| {
17819                        if selection.id == newest_selection_id {
17820                            Some(
17821                                (range.start.0 as isize - selection.head().0 as isize)
17822                                    ..(range.end.0 as isize - selection.head().0 as isize),
17823                            )
17824                        } else {
17825                            None
17826                        }
17827                    })
17828            });
17829
17830            cx.emit(EditorEvent::InputHandled {
17831                utf16_range_to_replace: range_to_replace,
17832                text: text.into(),
17833            });
17834
17835            if let Some(new_selected_ranges) = new_selected_ranges {
17836                this.change_selections(None, window, cx, |selections| {
17837                    selections.select_ranges(new_selected_ranges)
17838                });
17839                this.backspace(&Default::default(), window, cx);
17840            }
17841
17842            this.handle_input(text, window, cx);
17843        });
17844
17845        if let Some(transaction) = self.ime_transaction {
17846            self.buffer.update(cx, |buffer, cx| {
17847                buffer.group_until_transaction(transaction, cx);
17848            });
17849        }
17850
17851        self.unmark_text(window, cx);
17852    }
17853
17854    fn replace_and_mark_text_in_range(
17855        &mut self,
17856        range_utf16: Option<Range<usize>>,
17857        text: &str,
17858        new_selected_range_utf16: Option<Range<usize>>,
17859        window: &mut Window,
17860        cx: &mut Context<Self>,
17861    ) {
17862        if !self.input_enabled {
17863            return;
17864        }
17865
17866        let transaction = self.transact(window, cx, |this, window, cx| {
17867            let ranges_to_replace = if let Some(mut marked_ranges) = this.marked_text_ranges(cx) {
17868                let snapshot = this.buffer.read(cx).read(cx);
17869                if let Some(relative_range_utf16) = range_utf16.as_ref() {
17870                    for marked_range in &mut marked_ranges {
17871                        marked_range.end.0 = marked_range.start.0 + relative_range_utf16.end;
17872                        marked_range.start.0 += relative_range_utf16.start;
17873                        marked_range.start =
17874                            snapshot.clip_offset_utf16(marked_range.start, Bias::Left);
17875                        marked_range.end =
17876                            snapshot.clip_offset_utf16(marked_range.end, Bias::Right);
17877                    }
17878                }
17879                Some(marked_ranges)
17880            } else 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                None
17885            };
17886
17887            let range_to_replace = ranges_to_replace.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(ranges) = ranges_to_replace {
17911                this.change_selections(None, window, cx, |s| s.select_ranges(ranges));
17912            }
17913
17914            let marked_ranges = {
17915                let snapshot = this.buffer.read(cx).read(cx);
17916                this.selections
17917                    .disjoint_anchors()
17918                    .iter()
17919                    .map(|selection| {
17920                        selection.start.bias_left(&snapshot)..selection.end.bias_right(&snapshot)
17921                    })
17922                    .collect::<Vec<_>>()
17923            };
17924
17925            if text.is_empty() {
17926                this.unmark_text(window, cx);
17927            } else {
17928                this.highlight_text::<InputComposition>(
17929                    marked_ranges.clone(),
17930                    HighlightStyle {
17931                        underline: Some(UnderlineStyle {
17932                            thickness: px(1.),
17933                            color: None,
17934                            wavy: false,
17935                        }),
17936                        ..Default::default()
17937                    },
17938                    cx,
17939                );
17940            }
17941
17942            // Disable auto-closing when composing text (i.e. typing a `"` on a Brazilian keyboard)
17943            let use_autoclose = this.use_autoclose;
17944            let use_auto_surround = this.use_auto_surround;
17945            this.set_use_autoclose(false);
17946            this.set_use_auto_surround(false);
17947            this.handle_input(text, window, cx);
17948            this.set_use_autoclose(use_autoclose);
17949            this.set_use_auto_surround(use_auto_surround);
17950
17951            if let Some(new_selected_range) = new_selected_range_utf16 {
17952                let snapshot = this.buffer.read(cx).read(cx);
17953                let new_selected_ranges = marked_ranges
17954                    .into_iter()
17955                    .map(|marked_range| {
17956                        let insertion_start = marked_range.start.to_offset_utf16(&snapshot).0;
17957                        let new_start = OffsetUtf16(new_selected_range.start + insertion_start);
17958                        let new_end = OffsetUtf16(new_selected_range.end + insertion_start);
17959                        snapshot.clip_offset_utf16(new_start, Bias::Left)
17960                            ..snapshot.clip_offset_utf16(new_end, Bias::Right)
17961                    })
17962                    .collect::<Vec<_>>();
17963
17964                drop(snapshot);
17965                this.change_selections(None, window, cx, |selections| {
17966                    selections.select_ranges(new_selected_ranges)
17967                });
17968            }
17969        });
17970
17971        self.ime_transaction = self.ime_transaction.or(transaction);
17972        if let Some(transaction) = self.ime_transaction {
17973            self.buffer.update(cx, |buffer, cx| {
17974                buffer.group_until_transaction(transaction, cx);
17975            });
17976        }
17977
17978        if self.text_highlights::<InputComposition>(cx).is_none() {
17979            self.ime_transaction.take();
17980        }
17981    }
17982
17983    fn bounds_for_range(
17984        &mut self,
17985        range_utf16: Range<usize>,
17986        element_bounds: gpui::Bounds<Pixels>,
17987        window: &mut Window,
17988        cx: &mut Context<Self>,
17989    ) -> Option<gpui::Bounds<Pixels>> {
17990        let text_layout_details = self.text_layout_details(window);
17991        let gpui::Size {
17992            width: em_width,
17993            height: line_height,
17994        } = self.character_size(window);
17995
17996        let snapshot = self.snapshot(window, cx);
17997        let scroll_position = snapshot.scroll_position();
17998        let scroll_left = scroll_position.x * em_width;
17999
18000        let start = OffsetUtf16(range_utf16.start).to_display_point(&snapshot);
18001        let x = snapshot.x_for_display_point(start, &text_layout_details) - scroll_left
18002            + self.gutter_dimensions.width
18003            + self.gutter_dimensions.margin;
18004        let y = line_height * (start.row().as_f32() - scroll_position.y);
18005
18006        Some(Bounds {
18007            origin: element_bounds.origin + point(x, y),
18008            size: size(em_width, line_height),
18009        })
18010    }
18011
18012    fn character_index_for_point(
18013        &mut self,
18014        point: gpui::Point<Pixels>,
18015        _window: &mut Window,
18016        _cx: &mut Context<Self>,
18017    ) -> Option<usize> {
18018        let position_map = self.last_position_map.as_ref()?;
18019        if !position_map.text_hitbox.contains(&point) {
18020            return None;
18021        }
18022        let display_point = position_map.point_for_position(point).previous_valid;
18023        let anchor = position_map
18024            .snapshot
18025            .display_point_to_anchor(display_point, Bias::Left);
18026        let utf16_offset = anchor.to_offset_utf16(&position_map.snapshot.buffer_snapshot);
18027        Some(utf16_offset.0)
18028    }
18029}
18030
18031trait SelectionExt {
18032    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
18033    fn spanned_rows(
18034        &self,
18035        include_end_if_at_line_start: bool,
18036        map: &DisplaySnapshot,
18037    ) -> Range<MultiBufferRow>;
18038}
18039
18040impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
18041    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
18042        let start = self
18043            .start
18044            .to_point(&map.buffer_snapshot)
18045            .to_display_point(map);
18046        let end = self
18047            .end
18048            .to_point(&map.buffer_snapshot)
18049            .to_display_point(map);
18050        if self.reversed {
18051            end..start
18052        } else {
18053            start..end
18054        }
18055    }
18056
18057    fn spanned_rows(
18058        &self,
18059        include_end_if_at_line_start: bool,
18060        map: &DisplaySnapshot,
18061    ) -> Range<MultiBufferRow> {
18062        let start = self.start.to_point(&map.buffer_snapshot);
18063        let mut end = self.end.to_point(&map.buffer_snapshot);
18064        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
18065            end.row -= 1;
18066        }
18067
18068        let buffer_start = map.prev_line_boundary(start).0;
18069        let buffer_end = map.next_line_boundary(end).0;
18070        MultiBufferRow(buffer_start.row)..MultiBufferRow(buffer_end.row + 1)
18071    }
18072}
18073
18074impl<T: InvalidationRegion> InvalidationStack<T> {
18075    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
18076    where
18077        S: Clone + ToOffset,
18078    {
18079        while let Some(region) = self.last() {
18080            let all_selections_inside_invalidation_ranges =
18081                if selections.len() == region.ranges().len() {
18082                    selections
18083                        .iter()
18084                        .zip(region.ranges().iter().map(|r| r.to_offset(buffer)))
18085                        .all(|(selection, invalidation_range)| {
18086                            let head = selection.head().to_offset(buffer);
18087                            invalidation_range.start <= head && invalidation_range.end >= head
18088                        })
18089                } else {
18090                    false
18091                };
18092
18093            if all_selections_inside_invalidation_ranges {
18094                break;
18095            } else {
18096                self.pop();
18097            }
18098        }
18099    }
18100}
18101
18102impl<T> Default for InvalidationStack<T> {
18103    fn default() -> Self {
18104        Self(Default::default())
18105    }
18106}
18107
18108impl<T> Deref for InvalidationStack<T> {
18109    type Target = Vec<T>;
18110
18111    fn deref(&self) -> &Self::Target {
18112        &self.0
18113    }
18114}
18115
18116impl<T> DerefMut for InvalidationStack<T> {
18117    fn deref_mut(&mut self) -> &mut Self::Target {
18118        &mut self.0
18119    }
18120}
18121
18122impl InvalidationRegion for SnippetState {
18123    fn ranges(&self) -> &[Range<Anchor>] {
18124        &self.ranges[self.active_index]
18125    }
18126}
18127
18128pub fn diagnostic_block_renderer(
18129    diagnostic: Diagnostic,
18130    max_message_rows: Option<u8>,
18131    allow_closing: bool,
18132) -> RenderBlock {
18133    let (text_without_backticks, code_ranges) =
18134        highlight_diagnostic_message(&diagnostic, max_message_rows);
18135
18136    Arc::new(move |cx: &mut BlockContext| {
18137        let group_id: SharedString = cx.block_id.to_string().into();
18138
18139        let mut text_style = cx.window.text_style().clone();
18140        text_style.color = diagnostic_style(diagnostic.severity, cx.theme().status());
18141        let theme_settings = ThemeSettings::get_global(cx);
18142        text_style.font_family = theme_settings.buffer_font.family.clone();
18143        text_style.font_style = theme_settings.buffer_font.style;
18144        text_style.font_features = theme_settings.buffer_font.features.clone();
18145        text_style.font_weight = theme_settings.buffer_font.weight;
18146
18147        let multi_line_diagnostic = diagnostic.message.contains('\n');
18148
18149        let buttons = |diagnostic: &Diagnostic| {
18150            if multi_line_diagnostic {
18151                v_flex()
18152            } else {
18153                h_flex()
18154            }
18155            .when(allow_closing, |div| {
18156                div.children(diagnostic.is_primary.then(|| {
18157                    IconButton::new("close-block", IconName::XCircle)
18158                        .icon_color(Color::Muted)
18159                        .size(ButtonSize::Compact)
18160                        .style(ButtonStyle::Transparent)
18161                        .visible_on_hover(group_id.clone())
18162                        .on_click(move |_click, window, cx| {
18163                            window.dispatch_action(Box::new(Cancel), cx)
18164                        })
18165                        .tooltip(|window, cx| {
18166                            Tooltip::for_action("Close Diagnostics", &Cancel, window, cx)
18167                        })
18168                }))
18169            })
18170            .child(
18171                IconButton::new("copy-block", IconName::Copy)
18172                    .icon_color(Color::Muted)
18173                    .size(ButtonSize::Compact)
18174                    .style(ButtonStyle::Transparent)
18175                    .visible_on_hover(group_id.clone())
18176                    .on_click({
18177                        let message = diagnostic.message.clone();
18178                        move |_click, _, cx| {
18179                            cx.write_to_clipboard(ClipboardItem::new_string(message.clone()))
18180                        }
18181                    })
18182                    .tooltip(Tooltip::text("Copy diagnostic message")),
18183            )
18184        };
18185
18186        let icon_size = buttons(&diagnostic).into_any_element().layout_as_root(
18187            AvailableSpace::min_size(),
18188            cx.window,
18189            cx.app,
18190        );
18191
18192        h_flex()
18193            .id(cx.block_id)
18194            .group(group_id.clone())
18195            .relative()
18196            .size_full()
18197            .block_mouse_down()
18198            .pl(cx.gutter_dimensions.width)
18199            .w(cx.max_width - cx.gutter_dimensions.full_width())
18200            .child(
18201                div()
18202                    .flex()
18203                    .w(cx.anchor_x - cx.gutter_dimensions.width - icon_size.width)
18204                    .flex_shrink(),
18205            )
18206            .child(buttons(&diagnostic))
18207            .child(div().flex().flex_shrink_0().child(
18208                StyledText::new(text_without_backticks.clone()).with_default_highlights(
18209                    &text_style,
18210                    code_ranges.iter().map(|range| {
18211                        (
18212                            range.clone(),
18213                            HighlightStyle {
18214                                font_weight: Some(FontWeight::BOLD),
18215                                ..Default::default()
18216                            },
18217                        )
18218                    }),
18219                ),
18220            ))
18221            .into_any_element()
18222    })
18223}
18224
18225fn inline_completion_edit_text(
18226    current_snapshot: &BufferSnapshot,
18227    edits: &[(Range<Anchor>, String)],
18228    edit_preview: &EditPreview,
18229    include_deletions: bool,
18230    cx: &App,
18231) -> HighlightedText {
18232    let edits = edits
18233        .iter()
18234        .map(|(anchor, text)| {
18235            (
18236                anchor.start.text_anchor..anchor.end.text_anchor,
18237                text.clone(),
18238            )
18239        })
18240        .collect::<Vec<_>>();
18241
18242    edit_preview.highlight_edits(current_snapshot, &edits, include_deletions, cx)
18243}
18244
18245pub fn highlight_diagnostic_message(
18246    diagnostic: &Diagnostic,
18247    mut max_message_rows: Option<u8>,
18248) -> (SharedString, Vec<Range<usize>>) {
18249    let mut text_without_backticks = String::new();
18250    let mut code_ranges = Vec::new();
18251
18252    if let Some(source) = &diagnostic.source {
18253        text_without_backticks.push_str(source);
18254        code_ranges.push(0..source.len());
18255        text_without_backticks.push_str(": ");
18256    }
18257
18258    let mut prev_offset = 0;
18259    let mut in_code_block = false;
18260    let has_row_limit = max_message_rows.is_some();
18261    let mut newline_indices = diagnostic
18262        .message
18263        .match_indices('\n')
18264        .filter(|_| has_row_limit)
18265        .map(|(ix, _)| ix)
18266        .fuse()
18267        .peekable();
18268
18269    for (quote_ix, _) in diagnostic
18270        .message
18271        .match_indices('`')
18272        .chain([(diagnostic.message.len(), "")])
18273    {
18274        let mut first_newline_ix = None;
18275        let mut last_newline_ix = None;
18276        while let Some(newline_ix) = newline_indices.peek() {
18277            if *newline_ix < quote_ix {
18278                if first_newline_ix.is_none() {
18279                    first_newline_ix = Some(*newline_ix);
18280                }
18281                last_newline_ix = Some(*newline_ix);
18282
18283                if let Some(rows_left) = &mut max_message_rows {
18284                    if *rows_left == 0 {
18285                        break;
18286                    } else {
18287                        *rows_left -= 1;
18288                    }
18289                }
18290                let _ = newline_indices.next();
18291            } else {
18292                break;
18293            }
18294        }
18295        let prev_len = text_without_backticks.len();
18296        let new_text = &diagnostic.message[prev_offset..first_newline_ix.unwrap_or(quote_ix)];
18297        text_without_backticks.push_str(new_text);
18298        if in_code_block {
18299            code_ranges.push(prev_len..text_without_backticks.len());
18300        }
18301        prev_offset = last_newline_ix.unwrap_or(quote_ix) + 1;
18302        in_code_block = !in_code_block;
18303        if first_newline_ix.map_or(false, |newline_ix| newline_ix < quote_ix) {
18304            text_without_backticks.push_str("...");
18305            break;
18306        }
18307    }
18308
18309    (text_without_backticks.into(), code_ranges)
18310}
18311
18312fn diagnostic_style(severity: DiagnosticSeverity, colors: &StatusColors) -> Hsla {
18313    match severity {
18314        DiagnosticSeverity::ERROR => colors.error,
18315        DiagnosticSeverity::WARNING => colors.warning,
18316        DiagnosticSeverity::INFORMATION => colors.info,
18317        DiagnosticSeverity::HINT => colors.info,
18318        _ => colors.ignored,
18319    }
18320}
18321
18322pub fn styled_runs_for_code_label<'a>(
18323    label: &'a CodeLabel,
18324    syntax_theme: &'a theme::SyntaxTheme,
18325) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
18326    let fade_out = HighlightStyle {
18327        fade_out: Some(0.35),
18328        ..Default::default()
18329    };
18330
18331    let mut prev_end = label.filter_range.end;
18332    label
18333        .runs
18334        .iter()
18335        .enumerate()
18336        .flat_map(move |(ix, (range, highlight_id))| {
18337            let style = if let Some(style) = highlight_id.style(syntax_theme) {
18338                style
18339            } else {
18340                return Default::default();
18341            };
18342            let mut muted_style = style;
18343            muted_style.highlight(fade_out);
18344
18345            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
18346            if range.start >= label.filter_range.end {
18347                if range.start > prev_end {
18348                    runs.push((prev_end..range.start, fade_out));
18349                }
18350                runs.push((range.clone(), muted_style));
18351            } else if range.end <= label.filter_range.end {
18352                runs.push((range.clone(), style));
18353            } else {
18354                runs.push((range.start..label.filter_range.end, style));
18355                runs.push((label.filter_range.end..range.end, muted_style));
18356            }
18357            prev_end = cmp::max(prev_end, range.end);
18358
18359            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
18360                runs.push((prev_end..label.text.len(), fade_out));
18361            }
18362
18363            runs
18364        })
18365}
18366
18367pub(crate) fn split_words(text: &str) -> impl std::iter::Iterator<Item = &str> + '_ {
18368    let mut prev_index = 0;
18369    let mut prev_codepoint: Option<char> = None;
18370    text.char_indices()
18371        .chain([(text.len(), '\0')])
18372        .filter_map(move |(index, codepoint)| {
18373            let prev_codepoint = prev_codepoint.replace(codepoint)?;
18374            let is_boundary = index == text.len()
18375                || !prev_codepoint.is_uppercase() && codepoint.is_uppercase()
18376                || !prev_codepoint.is_alphanumeric() && codepoint.is_alphanumeric();
18377            if is_boundary {
18378                let chunk = &text[prev_index..index];
18379                prev_index = index;
18380                Some(chunk)
18381            } else {
18382                None
18383            }
18384        })
18385}
18386
18387pub trait RangeToAnchorExt: Sized {
18388    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor>;
18389
18390    fn to_display_points(self, snapshot: &EditorSnapshot) -> Range<DisplayPoint> {
18391        let anchor_range = self.to_anchors(&snapshot.buffer_snapshot);
18392        anchor_range.start.to_display_point(snapshot)..anchor_range.end.to_display_point(snapshot)
18393    }
18394}
18395
18396impl<T: ToOffset> RangeToAnchorExt for Range<T> {
18397    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor> {
18398        let start_offset = self.start.to_offset(snapshot);
18399        let end_offset = self.end.to_offset(snapshot);
18400        if start_offset == end_offset {
18401            snapshot.anchor_before(start_offset)..snapshot.anchor_before(end_offset)
18402        } else {
18403            snapshot.anchor_after(self.start)..snapshot.anchor_before(self.end)
18404        }
18405    }
18406}
18407
18408pub trait RowExt {
18409    fn as_f32(&self) -> f32;
18410
18411    fn next_row(&self) -> Self;
18412
18413    fn previous_row(&self) -> Self;
18414
18415    fn minus(&self, other: Self) -> u32;
18416}
18417
18418impl RowExt for DisplayRow {
18419    fn as_f32(&self) -> f32 {
18420        self.0 as f32
18421    }
18422
18423    fn next_row(&self) -> Self {
18424        Self(self.0 + 1)
18425    }
18426
18427    fn previous_row(&self) -> Self {
18428        Self(self.0.saturating_sub(1))
18429    }
18430
18431    fn minus(&self, other: Self) -> u32 {
18432        self.0 - other.0
18433    }
18434}
18435
18436impl RowExt for MultiBufferRow {
18437    fn as_f32(&self) -> f32 {
18438        self.0 as f32
18439    }
18440
18441    fn next_row(&self) -> Self {
18442        Self(self.0 + 1)
18443    }
18444
18445    fn previous_row(&self) -> Self {
18446        Self(self.0.saturating_sub(1))
18447    }
18448
18449    fn minus(&self, other: Self) -> u32 {
18450        self.0 - other.0
18451    }
18452}
18453
18454trait RowRangeExt {
18455    type Row;
18456
18457    fn len(&self) -> usize;
18458
18459    fn iter_rows(&self) -> impl DoubleEndedIterator<Item = Self::Row>;
18460}
18461
18462impl RowRangeExt for Range<MultiBufferRow> {
18463    type Row = MultiBufferRow;
18464
18465    fn len(&self) -> usize {
18466        (self.end.0 - self.start.0) as usize
18467    }
18468
18469    fn iter_rows(&self) -> impl DoubleEndedIterator<Item = MultiBufferRow> {
18470        (self.start.0..self.end.0).map(MultiBufferRow)
18471    }
18472}
18473
18474impl RowRangeExt for Range<DisplayRow> {
18475    type Row = DisplayRow;
18476
18477    fn len(&self) -> usize {
18478        (self.end.0 - self.start.0) as usize
18479    }
18480
18481    fn iter_rows(&self) -> impl DoubleEndedIterator<Item = DisplayRow> {
18482        (self.start.0..self.end.0).map(DisplayRow)
18483    }
18484}
18485
18486/// If select range has more than one line, we
18487/// just point the cursor to range.start.
18488fn collapse_multiline_range(range: Range<Point>) -> Range<Point> {
18489    if range.start.row == range.end.row {
18490        range
18491    } else {
18492        range.start..range.start
18493    }
18494}
18495pub struct KillRing(ClipboardItem);
18496impl Global for KillRing {}
18497
18498const UPDATE_DEBOUNCE: Duration = Duration::from_millis(50);
18499
18500fn all_edits_insertions_or_deletions(
18501    edits: &Vec<(Range<Anchor>, String)>,
18502    snapshot: &MultiBufferSnapshot,
18503) -> bool {
18504    let mut all_insertions = true;
18505    let mut all_deletions = true;
18506
18507    for (range, new_text) in edits.iter() {
18508        let range_is_empty = range.to_offset(&snapshot).is_empty();
18509        let text_is_empty = new_text.is_empty();
18510
18511        if range_is_empty != text_is_empty {
18512            if range_is_empty {
18513                all_deletions = false;
18514            } else {
18515                all_insertions = false;
18516            }
18517        } else {
18518            return false;
18519        }
18520
18521        if !all_insertions && !all_deletions {
18522            return false;
18523        }
18524    }
18525    all_insertions || all_deletions
18526}
18527
18528struct MissingEditPredictionKeybindingTooltip;
18529
18530impl Render for MissingEditPredictionKeybindingTooltip {
18531    fn render(&mut self, window: &mut Window, cx: &mut Context<'_, Self>) -> impl IntoElement {
18532        ui::tooltip_container(window, cx, |container, _, cx| {
18533            container
18534                .flex_shrink_0()
18535                .max_w_80()
18536                .min_h(rems_from_px(124.))
18537                .justify_between()
18538                .child(
18539                    v_flex()
18540                        .flex_1()
18541                        .text_ui_sm(cx)
18542                        .child(Label::new("Conflict with Accept Keybinding"))
18543                        .child("Your keymap currently overrides the default accept keybinding. To continue, assign one keybinding for the `editor::AcceptEditPrediction` action.")
18544                )
18545                .child(
18546                    h_flex()
18547                        .pb_1()
18548                        .gap_1()
18549                        .items_end()
18550                        .w_full()
18551                        .child(Button::new("open-keymap", "Assign Keybinding").size(ButtonSize::Compact).on_click(|_ev, window, cx| {
18552                            window.dispatch_action(zed_actions::OpenKeymap.boxed_clone(), cx)
18553                        }))
18554                        .child(Button::new("see-docs", "See Docs").size(ButtonSize::Compact).on_click(|_ev, _window, cx| {
18555                            cx.open_url("https://zed.dev/docs/completions#edit-predictions-missing-keybinding");
18556                        })),
18557                )
18558        })
18559    }
18560}
18561
18562#[derive(Debug, Clone, Copy, PartialEq)]
18563pub struct LineHighlight {
18564    pub background: Background,
18565    pub border: Option<gpui::Hsla>,
18566}
18567
18568impl From<Hsla> for LineHighlight {
18569    fn from(hsla: Hsla) -> Self {
18570        Self {
18571            background: hsla.into(),
18572            border: None,
18573        }
18574    }
18575}
18576
18577impl From<Background> for LineHighlight {
18578    fn from(background: Background) -> Self {
18579        Self {
18580            background,
18581            border: None,
18582        }
18583    }
18584}