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 feature_flags::{Debugger, FeatureFlagAppExt};
   72use futures::{
   73    future::{self, join, Shared},
   74    FutureExt,
   75};
   76use fuzzy::StringMatchCandidate;
   77
   78use ::git::Restore;
   79use code_context_menus::{
   80    AvailableCodeAction, CodeActionContents, CodeActionsItem, CodeActionsMenu, CodeContextMenu,
   81    CompletionsMenu, ContextMenuOrigin,
   82};
   83use git::blame::GitBlame;
   84use gpui::{
   85    div, impl_actions, point, prelude::*, pulsating_between, px, relative, size, Action, Animation,
   86    AnimationExt, AnyElement, App, AppContext, AsyncWindowContext, AvailableSpace, Background,
   87    Bounds, ClickEvent, ClipboardEntry, ClipboardItem, Context, DispatchPhase, Edges, Entity,
   88    EntityInputHandler, EventEmitter, FocusHandle, FocusOutEvent, Focusable, FontId, FontWeight,
   89    Global, HighlightStyle, Hsla, KeyContext, Modifiers, MouseButton, MouseDownEvent, PaintQuad,
   90    ParentElement, Pixels, Render, SharedString, Size, Stateful, Styled, StyledText, Subscription,
   91    Task, TextStyle, TextStyleRefinement, UTF16Selection, UnderlineStyle, UniformListScrollHandle,
   92    WeakEntity, WeakFocusHandle, Window,
   93};
   94use highlight_matching_bracket::refresh_matching_bracket_highlights;
   95use hover_links::{find_file, HoverLink, HoveredLinkState, InlayHighlight};
   96use hover_popover::{hide_hover, HoverState};
   97use indent_guides::ActiveIndentGuidesState;
   98use inlay_hint_cache::{InlayHintCache, InlaySplice, InvalidationStrategy};
   99pub use inline_completion::Direction;
  100use inline_completion::{EditPredictionProvider, InlineCompletionProviderHandle};
  101pub use items::MAX_TAB_TITLE_LEN;
  102use itertools::Itertools;
  103use language::{
  104    language_settings::{
  105        self, all_language_settings, language_settings, InlayHintSettings, RewrapBehavior,
  106        WordsCompletionMode,
  107    },
  108    point_from_lsp, text_diff_with_options, AutoindentMode, BracketMatch, BracketPair, Buffer,
  109    Capability, CharKind, CodeLabel, CursorShape, Diagnostic, DiffOptions, EditPredictionsMode,
  110    EditPreview, HighlightedText, IndentKind, IndentSize, Language, OffsetRangeExt, Point,
  111    Selection, SelectionGoal, TextObject, TransactionId, TreeSitterOptions, WordsQuery,
  112};
  113use language::{point_to_lsp, BufferRow, CharClassifier, Runnable, RunnableRange};
  114use linked_editing_ranges::refresh_linked_ranges;
  115use mouse_context_menu::MouseContextMenu;
  116use persistence::DB;
  117use project::{
  118    debugger::breakpoint_store::{BreakpointEditAction, BreakpointStore, BreakpointStoreEvent},
  119    ProjectPath,
  120};
  121
  122pub use proposed_changes_editor::{
  123    ProposedChangeLocation, ProposedChangesEditor, ProposedChangesEditorToolbar,
  124};
  125use smallvec::smallvec;
  126use std::{cell::OnceCell, iter::Peekable};
  127use task::{ResolvedTask, TaskTemplate, TaskVariables};
  128
  129pub use lsp::CompletionContext;
  130use lsp::{
  131    CodeActionKind, CompletionItemKind, CompletionTriggerKind, DiagnosticSeverity,
  132    InsertTextFormat, LanguageServerId, LanguageServerName,
  133};
  134
  135use language::BufferSnapshot;
  136use movement::TextLayoutDetails;
  137pub use multi_buffer::{
  138    Anchor, AnchorRangeExt, ExcerptId, ExcerptRange, MultiBuffer, MultiBufferSnapshot, RowInfo,
  139    ToOffset, ToPoint,
  140};
  141use multi_buffer::{
  142    ExcerptInfo, ExpandExcerptDirection, MultiBufferDiffHunk, MultiBufferPoint, MultiBufferRow,
  143    MultiOrSingleBufferOffsetRange, ToOffsetUtf16,
  144};
  145use parking_lot::Mutex;
  146use project::{
  147    debugger::breakpoint_store::{Breakpoint, BreakpointKind},
  148    lsp_store::{CompletionDocumentation, FormatTrigger, LspFormatTarget, OpenLspBufferHandle},
  149    project_settings::{GitGutterSetting, ProjectSettings},
  150    CodeAction, Completion, CompletionIntent, CompletionSource, DocumentHighlight, InlayHint,
  151    Location, LocationLink, PrepareRenameResponse, Project, ProjectItem, ProjectTransaction,
  152    TaskSourceKind,
  153};
  154use rand::prelude::*;
  155use rpc::{proto::*, ErrorExt};
  156use scroll::{Autoscroll, OngoingScroll, ScrollAnchor, ScrollManager, ScrollbarAutoHide};
  157use selections_collection::{
  158    resolve_selections, MutableSelectionsCollection, SelectionsCollection,
  159};
  160use serde::{Deserialize, Serialize};
  161use settings::{update_settings_file, Settings, SettingsLocation, SettingsStore};
  162use smallvec::SmallVec;
  163use snippet::Snippet;
  164use std::sync::Arc;
  165use std::{
  166    any::TypeId,
  167    borrow::Cow,
  168    cell::RefCell,
  169    cmp::{self, Ordering, Reverse},
  170    mem,
  171    num::NonZeroU32,
  172    ops::{ControlFlow, Deref, DerefMut, Not as _, Range, RangeInclusive},
  173    path::{Path, PathBuf},
  174    rc::Rc,
  175    time::{Duration, Instant},
  176};
  177pub use sum_tree::Bias;
  178use sum_tree::TreeMap;
  179use text::{BufferId, OffsetUtf16, Rope};
  180use theme::{
  181    observe_buffer_font_size_adjustment, ActiveTheme, PlayerColor, StatusColors, SyntaxTheme,
  182    ThemeColors, ThemeSettings,
  183};
  184use ui::{
  185    h_flex, prelude::*, ButtonSize, ButtonStyle, Disclosure, IconButton, IconName, IconSize, Key,
  186    Tooltip,
  187};
  188use util::{maybe, post_inc, RangeExt, ResultExt, TryFutureExt};
  189use workspace::{
  190    item::{ItemHandle, PreviewTabsSettings},
  191    notifications::{DetachAndPromptErr, NotificationId, NotifyTaskExt},
  192    searchable::SearchEvent,
  193    Item as WorkspaceItem, ItemId, ItemNavHistory, OpenInTerminal, OpenTerminal,
  194    RestoreOnStartupBehavior, SplitDirection, TabBarSettings, Toast, ViewId, Workspace,
  195    WorkspaceId, WorkspaceSettings, SERIALIZATION_THROTTLE_TIME,
  196};
  197
  198use crate::hover_links::{find_url, find_url_from_range};
  199use crate::signature_help::{SignatureHelpHiddenBy, SignatureHelpState};
  200
  201pub const FILE_HEADER_HEIGHT: u32 = 2;
  202pub const MULTI_BUFFER_EXCERPT_HEADER_HEIGHT: u32 = 1;
  203pub const DEFAULT_MULTIBUFFER_CONTEXT: u32 = 2;
  204const CURSOR_BLINK_INTERVAL: Duration = Duration::from_millis(500);
  205const MAX_LINE_LEN: usize = 1024;
  206const MIN_NAVIGATION_HISTORY_ROW_DELTA: i64 = 10;
  207const MAX_SELECTION_HISTORY_LEN: usize = 1024;
  208pub(crate) const CURSORS_VISIBLE_FOR: Duration = Duration::from_millis(2000);
  209#[doc(hidden)]
  210pub const CODE_ACTIONS_DEBOUNCE_TIMEOUT: Duration = Duration::from_millis(250);
  211
  212pub(crate) const CODE_ACTION_TIMEOUT: Duration = Duration::from_secs(5);
  213pub(crate) const FORMAT_TIMEOUT: Duration = Duration::from_secs(5);
  214pub(crate) const SCROLL_CENTER_TOP_BOTTOM_DEBOUNCE_TIMEOUT: Duration = Duration::from_secs(1);
  215
  216pub(crate) const EDIT_PREDICTION_KEY_CONTEXT: &str = "edit_prediction";
  217pub(crate) const EDIT_PREDICTION_CONFLICT_KEY_CONTEXT: &str = "edit_prediction_conflict";
  218pub(crate) const MIN_LINE_NUMBER_DIGITS: u32 = 4;
  219
  220const COLUMNAR_SELECTION_MODIFIERS: Modifiers = Modifiers {
  221    alt: true,
  222    shift: true,
  223    control: false,
  224    platform: false,
  225    function: false,
  226};
  227
  228#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
  229pub enum InlayId {
  230    InlineCompletion(usize),
  231    Hint(usize),
  232}
  233
  234impl InlayId {
  235    fn id(&self) -> usize {
  236        match self {
  237            Self::InlineCompletion(id) => *id,
  238            Self::Hint(id) => *id,
  239        }
  240    }
  241}
  242
  243pub enum DebugCurrentRowHighlight {}
  244enum DocumentHighlightRead {}
  245enum DocumentHighlightWrite {}
  246enum InputComposition {}
  247enum SelectedTextHighlight {}
  248
  249#[derive(Debug, Copy, Clone, PartialEq, Eq)]
  250pub enum Navigated {
  251    Yes,
  252    No,
  253}
  254
  255impl Navigated {
  256    pub fn from_bool(yes: bool) -> Navigated {
  257        if yes {
  258            Navigated::Yes
  259        } else {
  260            Navigated::No
  261        }
  262    }
  263}
  264
  265#[derive(Debug, Clone, PartialEq, Eq)]
  266enum DisplayDiffHunk {
  267    Folded {
  268        display_row: DisplayRow,
  269    },
  270    Unfolded {
  271        is_created_file: bool,
  272        diff_base_byte_range: Range<usize>,
  273        display_row_range: Range<DisplayRow>,
  274        multi_buffer_range: Range<Anchor>,
  275        status: DiffHunkStatus,
  276    },
  277}
  278
  279pub fn init_settings(cx: &mut App) {
  280    EditorSettings::register(cx);
  281}
  282
  283pub fn init(cx: &mut App) {
  284    init_settings(cx);
  285
  286    workspace::register_project_item::<Editor>(cx);
  287    workspace::FollowableViewRegistry::register::<Editor>(cx);
  288    workspace::register_serializable_item::<Editor>(cx);
  289
  290    cx.observe_new(
  291        |workspace: &mut Workspace, _: Option<&mut Window>, _cx: &mut Context<Workspace>| {
  292            workspace.register_action(Editor::new_file);
  293            workspace.register_action(Editor::new_file_vertical);
  294            workspace.register_action(Editor::new_file_horizontal);
  295            workspace.register_action(Editor::cancel_language_server_work);
  296        },
  297    )
  298    .detach();
  299
  300    cx.on_action(move |_: &workspace::NewFile, cx| {
  301        let app_state = workspace::AppState::global(cx);
  302        if let Some(app_state) = app_state.upgrade() {
  303            workspace::open_new(
  304                Default::default(),
  305                app_state,
  306                cx,
  307                |workspace, window, cx| {
  308                    Editor::new_file(workspace, &Default::default(), window, cx)
  309                },
  310            )
  311            .detach();
  312        }
  313    });
  314    cx.on_action(move |_: &workspace::NewWindow, cx| {
  315        let app_state = workspace::AppState::global(cx);
  316        if let Some(app_state) = app_state.upgrade() {
  317            workspace::open_new(
  318                Default::default(),
  319                app_state,
  320                cx,
  321                |workspace, window, cx| {
  322                    cx.activate(true);
  323                    Editor::new_file(workspace, &Default::default(), window, cx)
  324                },
  325            )
  326            .detach();
  327        }
  328    });
  329}
  330
  331pub struct SearchWithinRange;
  332
  333trait InvalidationRegion {
  334    fn ranges(&self) -> &[Range<Anchor>];
  335}
  336
  337#[derive(Clone, Debug, PartialEq)]
  338pub enum SelectPhase {
  339    Begin {
  340        position: DisplayPoint,
  341        add: bool,
  342        click_count: usize,
  343    },
  344    BeginColumnar {
  345        position: DisplayPoint,
  346        reset: bool,
  347        goal_column: u32,
  348    },
  349    Extend {
  350        position: DisplayPoint,
  351        click_count: usize,
  352    },
  353    Update {
  354        position: DisplayPoint,
  355        goal_column: u32,
  356        scroll_delta: gpui::Point<f32>,
  357    },
  358    End,
  359}
  360
  361#[derive(Clone, Debug)]
  362pub enum SelectMode {
  363    Character,
  364    Word(Range<Anchor>),
  365    Line(Range<Anchor>),
  366    All,
  367}
  368
  369#[derive(Copy, Clone, PartialEq, Eq, Debug)]
  370pub enum EditorMode {
  371    SingleLine { auto_width: bool },
  372    AutoHeight { max_lines: usize },
  373    Full,
  374}
  375
  376#[derive(Copy, Clone, Debug)]
  377pub enum SoftWrap {
  378    /// Prefer not to wrap at all.
  379    ///
  380    /// Note: this is currently internal, as actually limited by [`crate::MAX_LINE_LEN`] until it wraps.
  381    /// The mode is used inside git diff hunks, where it's seems currently more useful to not wrap as much as possible.
  382    GitDiff,
  383    /// Prefer a single line generally, unless an overly long line is encountered.
  384    None,
  385    /// Soft wrap lines that exceed the editor width.
  386    EditorWidth,
  387    /// Soft wrap lines at the preferred line length.
  388    Column(u32),
  389    /// Soft wrap line at the preferred line length or the editor width (whichever is smaller).
  390    Bounded(u32),
  391}
  392
  393#[derive(Clone)]
  394pub struct EditorStyle {
  395    pub background: Hsla,
  396    pub local_player: PlayerColor,
  397    pub text: TextStyle,
  398    pub scrollbar_width: Pixels,
  399    pub syntax: Arc<SyntaxTheme>,
  400    pub status: StatusColors,
  401    pub inlay_hints_style: HighlightStyle,
  402    pub inline_completion_styles: InlineCompletionStyles,
  403    pub unnecessary_code_fade: f32,
  404}
  405
  406impl Default for EditorStyle {
  407    fn default() -> Self {
  408        Self {
  409            background: Hsla::default(),
  410            local_player: PlayerColor::default(),
  411            text: TextStyle::default(),
  412            scrollbar_width: Pixels::default(),
  413            syntax: Default::default(),
  414            // HACK: Status colors don't have a real default.
  415            // We should look into removing the status colors from the editor
  416            // style and retrieve them directly from the theme.
  417            status: StatusColors::dark(),
  418            inlay_hints_style: HighlightStyle::default(),
  419            inline_completion_styles: InlineCompletionStyles {
  420                insertion: HighlightStyle::default(),
  421                whitespace: HighlightStyle::default(),
  422            },
  423            unnecessary_code_fade: Default::default(),
  424        }
  425    }
  426}
  427
  428pub fn make_inlay_hints_style(cx: &mut App) -> HighlightStyle {
  429    let show_background = language_settings::language_settings(None, None, cx)
  430        .inlay_hints
  431        .show_background;
  432
  433    HighlightStyle {
  434        color: Some(cx.theme().status().hint),
  435        background_color: show_background.then(|| cx.theme().status().hint_background),
  436        ..HighlightStyle::default()
  437    }
  438}
  439
  440pub fn make_suggestion_styles(cx: &mut App) -> InlineCompletionStyles {
  441    InlineCompletionStyles {
  442        insertion: HighlightStyle {
  443            color: Some(cx.theme().status().predictive),
  444            ..HighlightStyle::default()
  445        },
  446        whitespace: HighlightStyle {
  447            background_color: Some(cx.theme().status().created_background),
  448            ..HighlightStyle::default()
  449        },
  450    }
  451}
  452
  453type CompletionId = usize;
  454
  455pub(crate) enum EditDisplayMode {
  456    TabAccept,
  457    DiffPopover,
  458    Inline,
  459}
  460
  461enum InlineCompletion {
  462    Edit {
  463        edits: Vec<(Range<Anchor>, String)>,
  464        edit_preview: Option<EditPreview>,
  465        display_mode: EditDisplayMode,
  466        snapshot: BufferSnapshot,
  467    },
  468    Move {
  469        target: Anchor,
  470        snapshot: BufferSnapshot,
  471    },
  472}
  473
  474struct InlineCompletionState {
  475    inlay_ids: Vec<InlayId>,
  476    completion: InlineCompletion,
  477    completion_id: Option<SharedString>,
  478    invalidation_range: Range<Anchor>,
  479}
  480
  481enum EditPredictionSettings {
  482    Disabled,
  483    Enabled {
  484        show_in_menu: bool,
  485        preview_requires_modifier: bool,
  486    },
  487}
  488
  489enum InlineCompletionHighlight {}
  490
  491#[derive(Debug, Clone)]
  492struct InlineDiagnostic {
  493    message: SharedString,
  494    group_id: usize,
  495    is_primary: bool,
  496    start: Point,
  497    severity: DiagnosticSeverity,
  498}
  499
  500pub enum MenuInlineCompletionsPolicy {
  501    Never,
  502    ByProvider,
  503}
  504
  505pub enum EditPredictionPreview {
  506    /// Modifier is not pressed
  507    Inactive { released_too_fast: bool },
  508    /// Modifier pressed
  509    Active {
  510        since: Instant,
  511        previous_scroll_position: Option<ScrollAnchor>,
  512    },
  513}
  514
  515impl EditPredictionPreview {
  516    pub fn released_too_fast(&self) -> bool {
  517        match self {
  518            EditPredictionPreview::Inactive { released_too_fast } => *released_too_fast,
  519            EditPredictionPreview::Active { .. } => false,
  520        }
  521    }
  522
  523    pub fn set_previous_scroll_position(&mut self, scroll_position: Option<ScrollAnchor>) {
  524        if let EditPredictionPreview::Active {
  525            previous_scroll_position,
  526            ..
  527        } = self
  528        {
  529            *previous_scroll_position = scroll_position;
  530        }
  531    }
  532}
  533
  534#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Debug, Default)]
  535struct EditorActionId(usize);
  536
  537impl EditorActionId {
  538    pub fn post_inc(&mut self) -> Self {
  539        let answer = self.0;
  540
  541        *self = Self(answer + 1);
  542
  543        Self(answer)
  544    }
  545}
  546
  547// type GetFieldEditorTheme = dyn Fn(&theme::Theme) -> theme::FieldEditor;
  548// type OverrideTextStyle = dyn Fn(&EditorStyle) -> Option<HighlightStyle>;
  549
  550type BackgroundHighlight = (fn(&ThemeColors) -> Hsla, Arc<[Range<Anchor>]>);
  551type GutterHighlight = (fn(&App) -> Hsla, Arc<[Range<Anchor>]>);
  552
  553#[derive(Default)]
  554struct ScrollbarMarkerState {
  555    scrollbar_size: Size<Pixels>,
  556    dirty: bool,
  557    markers: Arc<[PaintQuad]>,
  558    pending_refresh: Option<Task<Result<()>>>,
  559}
  560
  561impl ScrollbarMarkerState {
  562    fn should_refresh(&self, scrollbar_size: Size<Pixels>) -> bool {
  563        self.pending_refresh.is_none() && (self.scrollbar_size != scrollbar_size || self.dirty)
  564    }
  565}
  566
  567#[derive(Clone, Debug)]
  568struct RunnableTasks {
  569    templates: Vec<(TaskSourceKind, TaskTemplate)>,
  570    offset: multi_buffer::Anchor,
  571    // We need the column at which the task context evaluation should take place (when we're spawning it via gutter).
  572    column: u32,
  573    // Values of all named captures, including those starting with '_'
  574    extra_variables: HashMap<String, String>,
  575    // Full range of the tagged region. We use it to determine which `extra_variables` to grab for context resolution in e.g. a modal.
  576    context_range: Range<BufferOffset>,
  577}
  578
  579impl RunnableTasks {
  580    fn resolve<'a>(
  581        &'a self,
  582        cx: &'a task::TaskContext,
  583    ) -> impl Iterator<Item = (TaskSourceKind, ResolvedTask)> + 'a {
  584        self.templates.iter().filter_map(|(kind, template)| {
  585            template
  586                .resolve_task(&kind.to_id_base(), cx)
  587                .map(|task| (kind.clone(), task))
  588        })
  589    }
  590}
  591
  592#[derive(Clone)]
  593struct ResolvedTasks {
  594    templates: SmallVec<[(TaskSourceKind, ResolvedTask); 1]>,
  595    position: Anchor,
  596}
  597
  598#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
  599struct BufferOffset(usize);
  600
  601// Addons allow storing per-editor state in other crates (e.g. Vim)
  602pub trait Addon: 'static {
  603    fn extend_key_context(&self, _: &mut KeyContext, _: &App) {}
  604
  605    fn render_buffer_header_controls(
  606        &self,
  607        _: &ExcerptInfo,
  608        _: &Window,
  609        _: &App,
  610    ) -> Option<AnyElement> {
  611        None
  612    }
  613
  614    fn to_any(&self) -> &dyn std::any::Any;
  615}
  616
  617/// Zed's primary implementation of text input, allowing users to edit a [`MultiBuffer`].
  618///
  619/// See the [module level documentation](self) for more information.
  620pub struct Editor {
  621    focus_handle: FocusHandle,
  622    last_focused_descendant: Option<WeakFocusHandle>,
  623    /// The text buffer being edited
  624    buffer: Entity<MultiBuffer>,
  625    /// Map of how text in the buffer should be displayed.
  626    /// Handles soft wraps, folds, fake inlay text insertions, etc.
  627    pub display_map: Entity<DisplayMap>,
  628    pub selections: SelectionsCollection,
  629    pub scroll_manager: ScrollManager,
  630    /// When inline assist editors are linked, they all render cursors because
  631    /// typing enters text into each of them, even the ones that aren't focused.
  632    pub(crate) show_cursor_when_unfocused: bool,
  633    columnar_selection_tail: Option<Anchor>,
  634    add_selections_state: Option<AddSelectionsState>,
  635    select_next_state: Option<SelectNextState>,
  636    select_prev_state: Option<SelectNextState>,
  637    selection_history: SelectionHistory,
  638    autoclose_regions: Vec<AutocloseRegion>,
  639    snippet_stack: InvalidationStack<SnippetState>,
  640    select_syntax_node_history: SelectSyntaxNodeHistory,
  641    ime_transaction: Option<TransactionId>,
  642    active_diagnostics: Option<ActiveDiagnosticGroup>,
  643    show_inline_diagnostics: bool,
  644    inline_diagnostics_update: Task<()>,
  645    inline_diagnostics_enabled: bool,
  646    inline_diagnostics: Vec<(Anchor, InlineDiagnostic)>,
  647    soft_wrap_mode_override: Option<language_settings::SoftWrap>,
  648    hard_wrap: Option<usize>,
  649
  650    // TODO: make this a access method
  651    pub project: Option<Entity<Project>>,
  652    semantics_provider: Option<Rc<dyn SemanticsProvider>>,
  653    completion_provider: Option<Box<dyn CompletionProvider>>,
  654    collaboration_hub: Option<Box<dyn CollaborationHub>>,
  655    blink_manager: Entity<BlinkManager>,
  656    show_cursor_names: bool,
  657    hovered_cursors: HashMap<HoveredCursor, Task<()>>,
  658    pub show_local_selections: bool,
  659    mode: EditorMode,
  660    show_breadcrumbs: bool,
  661    show_gutter: bool,
  662    show_scrollbars: bool,
  663    show_line_numbers: Option<bool>,
  664    use_relative_line_numbers: Option<bool>,
  665    show_git_diff_gutter: Option<bool>,
  666    show_code_actions: Option<bool>,
  667    show_runnables: Option<bool>,
  668    show_breakpoints: Option<bool>,
  669    show_wrap_guides: Option<bool>,
  670    show_indent_guides: Option<bool>,
  671    placeholder_text: Option<Arc<str>>,
  672    highlight_order: usize,
  673    highlighted_rows: HashMap<TypeId, Vec<RowHighlight>>,
  674    background_highlights: TreeMap<TypeId, BackgroundHighlight>,
  675    gutter_highlights: TreeMap<TypeId, GutterHighlight>,
  676    scrollbar_marker_state: ScrollbarMarkerState,
  677    active_indent_guides_state: ActiveIndentGuidesState,
  678    nav_history: Option<ItemNavHistory>,
  679    context_menu: RefCell<Option<CodeContextMenu>>,
  680    mouse_context_menu: Option<MouseContextMenu>,
  681    completion_tasks: Vec<(CompletionId, Task<Option<()>>)>,
  682    signature_help_state: SignatureHelpState,
  683    auto_signature_help: Option<bool>,
  684    find_all_references_task_sources: Vec<Anchor>,
  685    next_completion_id: CompletionId,
  686    available_code_actions: Option<(Location, Rc<[AvailableCodeAction]>)>,
  687    code_actions_task: Option<Task<Result<()>>>,
  688    selection_highlight_task: Option<Task<()>>,
  689    document_highlights_task: Option<Task<()>>,
  690    linked_editing_range_task: Option<Task<Option<()>>>,
  691    linked_edit_ranges: linked_editing_ranges::LinkedEditingRanges,
  692    pending_rename: Option<RenameState>,
  693    searchable: bool,
  694    cursor_shape: CursorShape,
  695    current_line_highlight: Option<CurrentLineHighlight>,
  696    collapse_matches: bool,
  697    autoindent_mode: Option<AutoindentMode>,
  698    workspace: Option<(WeakEntity<Workspace>, Option<WorkspaceId>)>,
  699    input_enabled: bool,
  700    use_modal_editing: bool,
  701    read_only: bool,
  702    leader_peer_id: Option<PeerId>,
  703    remote_id: Option<ViewId>,
  704    hover_state: HoverState,
  705    pending_mouse_down: Option<Rc<RefCell<Option<MouseDownEvent>>>>,
  706    gutter_hovered: bool,
  707    hovered_link_state: Option<HoveredLinkState>,
  708    edit_prediction_provider: Option<RegisteredInlineCompletionProvider>,
  709    code_action_providers: Vec<Rc<dyn CodeActionProvider>>,
  710    active_inline_completion: Option<InlineCompletionState>,
  711    /// Used to prevent flickering as the user types while the menu is open
  712    stale_inline_completion_in_menu: Option<InlineCompletionState>,
  713    edit_prediction_settings: EditPredictionSettings,
  714    inline_completions_hidden_for_vim_mode: bool,
  715    show_inline_completions_override: Option<bool>,
  716    menu_inline_completions_policy: MenuInlineCompletionsPolicy,
  717    edit_prediction_preview: EditPredictionPreview,
  718    edit_prediction_indent_conflict: bool,
  719    edit_prediction_requires_modifier_in_indent_conflict: bool,
  720    inlay_hint_cache: InlayHintCache,
  721    next_inlay_id: usize,
  722    _subscriptions: Vec<Subscription>,
  723    pixel_position_of_newest_cursor: Option<gpui::Point<Pixels>>,
  724    gutter_dimensions: GutterDimensions,
  725    style: Option<EditorStyle>,
  726    text_style_refinement: Option<TextStyleRefinement>,
  727    next_editor_action_id: EditorActionId,
  728    editor_actions:
  729        Rc<RefCell<BTreeMap<EditorActionId, Box<dyn Fn(&mut Window, &mut Context<Self>)>>>>,
  730    use_autoclose: bool,
  731    use_auto_surround: bool,
  732    auto_replace_emoji_shortcode: bool,
  733    jsx_tag_auto_close_enabled_in_any_buffer: bool,
  734    show_git_blame_gutter: bool,
  735    show_git_blame_inline: bool,
  736    show_git_blame_inline_delay_task: Option<Task<()>>,
  737    git_blame_inline_tooltip: Option<WeakEntity<crate::commit_tooltip::CommitTooltip>>,
  738    git_blame_inline_enabled: bool,
  739    serialize_dirty_buffers: bool,
  740    show_selection_menu: Option<bool>,
  741    blame: Option<Entity<GitBlame>>,
  742    blame_subscription: Option<Subscription>,
  743    custom_context_menu: Option<
  744        Box<
  745            dyn 'static
  746                + Fn(
  747                    &mut Self,
  748                    DisplayPoint,
  749                    &mut Window,
  750                    &mut Context<Self>,
  751                ) -> Option<Entity<ui::ContextMenu>>,
  752        >,
  753    >,
  754    last_bounds: Option<Bounds<Pixels>>,
  755    last_position_map: Option<Rc<PositionMap>>,
  756    expect_bounds_change: Option<Bounds<Pixels>>,
  757    tasks: BTreeMap<(BufferId, BufferRow), RunnableTasks>,
  758    tasks_update_task: Option<Task<()>>,
  759    pub breakpoint_store: Option<Entity<BreakpointStore>>,
  760    /// Allow's a user to create a breakpoint by selecting this indicator
  761    /// It should be None while a user is not hovering over the gutter
  762    /// Otherwise it represents the point that the breakpoint will be shown
  763    pub gutter_breakpoint_indicator: Option<DisplayPoint>,
  764    in_project_search: bool,
  765    previous_search_ranges: Option<Arc<[Range<Anchor>]>>,
  766    breadcrumb_header: Option<String>,
  767    focused_block: Option<FocusedBlock>,
  768    next_scroll_position: NextScrollCursorCenterTopBottom,
  769    addons: HashMap<TypeId, Box<dyn Addon>>,
  770    registered_buffers: HashMap<BufferId, OpenLspBufferHandle>,
  771    load_diff_task: Option<Shared<Task<()>>>,
  772    selection_mark_mode: bool,
  773    toggle_fold_multiple_buffers: Task<()>,
  774    _scroll_cursor_center_top_bottom_task: Task<()>,
  775    serialize_selections: Task<()>,
  776    serialize_folds: Task<()>,
  777}
  778
  779#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)]
  780enum NextScrollCursorCenterTopBottom {
  781    #[default]
  782    Center,
  783    Top,
  784    Bottom,
  785}
  786
  787impl NextScrollCursorCenterTopBottom {
  788    fn next(&self) -> Self {
  789        match self {
  790            Self::Center => Self::Top,
  791            Self::Top => Self::Bottom,
  792            Self::Bottom => Self::Center,
  793        }
  794    }
  795}
  796
  797#[derive(Clone)]
  798pub struct EditorSnapshot {
  799    pub mode: EditorMode,
  800    show_gutter: bool,
  801    show_line_numbers: Option<bool>,
  802    show_git_diff_gutter: Option<bool>,
  803    show_code_actions: Option<bool>,
  804    show_runnables: Option<bool>,
  805    show_breakpoints: Option<bool>,
  806    git_blame_gutter_max_author_length: Option<usize>,
  807    pub display_snapshot: DisplaySnapshot,
  808    pub placeholder_text: Option<Arc<str>>,
  809    is_focused: bool,
  810    scroll_anchor: ScrollAnchor,
  811    ongoing_scroll: OngoingScroll,
  812    current_line_highlight: CurrentLineHighlight,
  813    gutter_hovered: bool,
  814}
  815
  816const GIT_BLAME_MAX_AUTHOR_CHARS_DISPLAYED: usize = 20;
  817
  818#[derive(Default, Debug, Clone, Copy)]
  819pub struct GutterDimensions {
  820    pub left_padding: Pixels,
  821    pub right_padding: Pixels,
  822    pub width: Pixels,
  823    pub margin: Pixels,
  824    pub git_blame_entries_width: Option<Pixels>,
  825}
  826
  827impl GutterDimensions {
  828    /// The full width of the space taken up by the gutter.
  829    pub fn full_width(&self) -> Pixels {
  830        self.margin + self.width
  831    }
  832
  833    /// The width of the space reserved for the fold indicators,
  834    /// use alongside 'justify_end' and `gutter_width` to
  835    /// right align content with the line numbers
  836    pub fn fold_area_width(&self) -> Pixels {
  837        self.margin + self.right_padding
  838    }
  839}
  840
  841#[derive(Debug)]
  842pub struct RemoteSelection {
  843    pub replica_id: ReplicaId,
  844    pub selection: Selection<Anchor>,
  845    pub cursor_shape: CursorShape,
  846    pub peer_id: PeerId,
  847    pub line_mode: bool,
  848    pub participant_index: Option<ParticipantIndex>,
  849    pub user_name: Option<SharedString>,
  850}
  851
  852#[derive(Clone, Debug)]
  853struct SelectionHistoryEntry {
  854    selections: Arc<[Selection<Anchor>]>,
  855    select_next_state: Option<SelectNextState>,
  856    select_prev_state: Option<SelectNextState>,
  857    add_selections_state: Option<AddSelectionsState>,
  858}
  859
  860enum SelectionHistoryMode {
  861    Normal,
  862    Undoing,
  863    Redoing,
  864}
  865
  866#[derive(Clone, PartialEq, Eq, Hash)]
  867struct HoveredCursor {
  868    replica_id: u16,
  869    selection_id: usize,
  870}
  871
  872impl Default for SelectionHistoryMode {
  873    fn default() -> Self {
  874        Self::Normal
  875    }
  876}
  877
  878#[derive(Default)]
  879struct SelectionHistory {
  880    #[allow(clippy::type_complexity)]
  881    selections_by_transaction:
  882        HashMap<TransactionId, (Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)>,
  883    mode: SelectionHistoryMode,
  884    undo_stack: VecDeque<SelectionHistoryEntry>,
  885    redo_stack: VecDeque<SelectionHistoryEntry>,
  886}
  887
  888impl SelectionHistory {
  889    fn insert_transaction(
  890        &mut self,
  891        transaction_id: TransactionId,
  892        selections: Arc<[Selection<Anchor>]>,
  893    ) {
  894        self.selections_by_transaction
  895            .insert(transaction_id, (selections, None));
  896    }
  897
  898    #[allow(clippy::type_complexity)]
  899    fn transaction(
  900        &self,
  901        transaction_id: TransactionId,
  902    ) -> Option<&(Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)> {
  903        self.selections_by_transaction.get(&transaction_id)
  904    }
  905
  906    #[allow(clippy::type_complexity)]
  907    fn transaction_mut(
  908        &mut self,
  909        transaction_id: TransactionId,
  910    ) -> Option<&mut (Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)> {
  911        self.selections_by_transaction.get_mut(&transaction_id)
  912    }
  913
  914    fn push(&mut self, entry: SelectionHistoryEntry) {
  915        if !entry.selections.is_empty() {
  916            match self.mode {
  917                SelectionHistoryMode::Normal => {
  918                    self.push_undo(entry);
  919                    self.redo_stack.clear();
  920                }
  921                SelectionHistoryMode::Undoing => self.push_redo(entry),
  922                SelectionHistoryMode::Redoing => self.push_undo(entry),
  923            }
  924        }
  925    }
  926
  927    fn push_undo(&mut self, entry: SelectionHistoryEntry) {
  928        if self
  929            .undo_stack
  930            .back()
  931            .map_or(true, |e| e.selections != entry.selections)
  932        {
  933            self.undo_stack.push_back(entry);
  934            if self.undo_stack.len() > MAX_SELECTION_HISTORY_LEN {
  935                self.undo_stack.pop_front();
  936            }
  937        }
  938    }
  939
  940    fn push_redo(&mut self, entry: SelectionHistoryEntry) {
  941        if self
  942            .redo_stack
  943            .back()
  944            .map_or(true, |e| e.selections != entry.selections)
  945        {
  946            self.redo_stack.push_back(entry);
  947            if self.redo_stack.len() > MAX_SELECTION_HISTORY_LEN {
  948                self.redo_stack.pop_front();
  949            }
  950        }
  951    }
  952}
  953
  954struct RowHighlight {
  955    index: usize,
  956    range: Range<Anchor>,
  957    color: Hsla,
  958    should_autoscroll: bool,
  959}
  960
  961#[derive(Clone, Debug)]
  962struct AddSelectionsState {
  963    above: bool,
  964    stack: Vec<usize>,
  965}
  966
  967#[derive(Clone)]
  968struct SelectNextState {
  969    query: AhoCorasick,
  970    wordwise: bool,
  971    done: bool,
  972}
  973
  974impl std::fmt::Debug for SelectNextState {
  975    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  976        f.debug_struct(std::any::type_name::<Self>())
  977            .field("wordwise", &self.wordwise)
  978            .field("done", &self.done)
  979            .finish()
  980    }
  981}
  982
  983#[derive(Debug)]
  984struct AutocloseRegion {
  985    selection_id: usize,
  986    range: Range<Anchor>,
  987    pair: BracketPair,
  988}
  989
  990#[derive(Debug)]
  991struct SnippetState {
  992    ranges: Vec<Vec<Range<Anchor>>>,
  993    active_index: usize,
  994    choices: Vec<Option<Vec<String>>>,
  995}
  996
  997#[doc(hidden)]
  998pub struct RenameState {
  999    pub range: Range<Anchor>,
 1000    pub old_name: Arc<str>,
 1001    pub editor: Entity<Editor>,
 1002    block_id: CustomBlockId,
 1003}
 1004
 1005struct InvalidationStack<T>(Vec<T>);
 1006
 1007struct RegisteredInlineCompletionProvider {
 1008    provider: Arc<dyn InlineCompletionProviderHandle>,
 1009    _subscription: Subscription,
 1010}
 1011
 1012#[derive(Debug, PartialEq, Eq)]
 1013struct ActiveDiagnosticGroup {
 1014    primary_range: Range<Anchor>,
 1015    primary_message: String,
 1016    group_id: usize,
 1017    blocks: HashMap<CustomBlockId, Diagnostic>,
 1018    is_valid: bool,
 1019}
 1020
 1021#[derive(Serialize, Deserialize, Clone, Debug)]
 1022pub struct ClipboardSelection {
 1023    /// The number of bytes in this selection.
 1024    pub len: usize,
 1025    /// Whether this was a full-line selection.
 1026    pub is_entire_line: bool,
 1027    /// The indentation of the first line when this content was originally copied.
 1028    pub first_line_indent: u32,
 1029}
 1030
 1031// selections, scroll behavior, was newest selection reversed
 1032type SelectSyntaxNodeHistoryState = (
 1033    Box<[Selection<usize>]>,
 1034    SelectSyntaxNodeScrollBehavior,
 1035    bool,
 1036);
 1037
 1038#[derive(Default)]
 1039struct SelectSyntaxNodeHistory {
 1040    stack: Vec<SelectSyntaxNodeHistoryState>,
 1041    // disable temporarily to allow changing selections without losing the stack
 1042    pub disable_clearing: bool,
 1043}
 1044
 1045impl SelectSyntaxNodeHistory {
 1046    pub fn try_clear(&mut self) {
 1047        if !self.disable_clearing {
 1048            self.stack.clear();
 1049        }
 1050    }
 1051
 1052    pub fn push(&mut self, selection: SelectSyntaxNodeHistoryState) {
 1053        self.stack.push(selection);
 1054    }
 1055
 1056    pub fn pop(&mut self) -> Option<SelectSyntaxNodeHistoryState> {
 1057        self.stack.pop()
 1058    }
 1059}
 1060
 1061enum SelectSyntaxNodeScrollBehavior {
 1062    CursorTop,
 1063    CenterSelection,
 1064    CursorBottom,
 1065}
 1066
 1067#[derive(Debug)]
 1068pub(crate) struct NavigationData {
 1069    cursor_anchor: Anchor,
 1070    cursor_position: Point,
 1071    scroll_anchor: ScrollAnchor,
 1072    scroll_top_row: u32,
 1073}
 1074
 1075#[derive(Debug, Clone, Copy, PartialEq, Eq)]
 1076pub enum GotoDefinitionKind {
 1077    Symbol,
 1078    Declaration,
 1079    Type,
 1080    Implementation,
 1081}
 1082
 1083#[derive(Debug, Clone)]
 1084enum InlayHintRefreshReason {
 1085    ModifiersChanged(bool),
 1086    Toggle(bool),
 1087    SettingsChange(InlayHintSettings),
 1088    NewLinesShown,
 1089    BufferEdited(HashSet<Arc<Language>>),
 1090    RefreshRequested,
 1091    ExcerptsRemoved(Vec<ExcerptId>),
 1092}
 1093
 1094impl InlayHintRefreshReason {
 1095    fn description(&self) -> &'static str {
 1096        match self {
 1097            Self::ModifiersChanged(_) => "modifiers changed",
 1098            Self::Toggle(_) => "toggle",
 1099            Self::SettingsChange(_) => "settings change",
 1100            Self::NewLinesShown => "new lines shown",
 1101            Self::BufferEdited(_) => "buffer edited",
 1102            Self::RefreshRequested => "refresh requested",
 1103            Self::ExcerptsRemoved(_) => "excerpts removed",
 1104        }
 1105    }
 1106}
 1107
 1108pub enum FormatTarget {
 1109    Buffers,
 1110    Ranges(Vec<Range<MultiBufferPoint>>),
 1111}
 1112
 1113pub(crate) struct FocusedBlock {
 1114    id: BlockId,
 1115    focus_handle: WeakFocusHandle,
 1116}
 1117
 1118#[derive(Clone)]
 1119enum JumpData {
 1120    MultiBufferRow {
 1121        row: MultiBufferRow,
 1122        line_offset_from_top: u32,
 1123    },
 1124    MultiBufferPoint {
 1125        excerpt_id: ExcerptId,
 1126        position: Point,
 1127        anchor: text::Anchor,
 1128        line_offset_from_top: u32,
 1129    },
 1130}
 1131
 1132pub enum MultibufferSelectionMode {
 1133    First,
 1134    All,
 1135}
 1136
 1137#[derive(Clone, Copy, Debug, Default)]
 1138pub struct RewrapOptions {
 1139    pub override_language_settings: bool,
 1140    pub preserve_existing_whitespace: bool,
 1141}
 1142
 1143impl Editor {
 1144    pub fn single_line(window: &mut Window, cx: &mut Context<Self>) -> Self {
 1145        let buffer = cx.new(|cx| Buffer::local("", cx));
 1146        let buffer = cx.new(|cx| MultiBuffer::singleton(buffer, cx));
 1147        Self::new(
 1148            EditorMode::SingleLine { auto_width: false },
 1149            buffer,
 1150            None,
 1151            window,
 1152            cx,
 1153        )
 1154    }
 1155
 1156    pub fn multi_line(window: &mut Window, cx: &mut Context<Self>) -> Self {
 1157        let buffer = cx.new(|cx| Buffer::local("", cx));
 1158        let buffer = cx.new(|cx| MultiBuffer::singleton(buffer, cx));
 1159        Self::new(EditorMode::Full, buffer, None, window, cx)
 1160    }
 1161
 1162    pub fn auto_width(window: &mut Window, cx: &mut Context<Self>) -> Self {
 1163        let buffer = cx.new(|cx| Buffer::local("", cx));
 1164        let buffer = cx.new(|cx| MultiBuffer::singleton(buffer, cx));
 1165        Self::new(
 1166            EditorMode::SingleLine { auto_width: true },
 1167            buffer,
 1168            None,
 1169            window,
 1170            cx,
 1171        )
 1172    }
 1173
 1174    pub fn auto_height(max_lines: usize, window: &mut Window, cx: &mut Context<Self>) -> Self {
 1175        let buffer = cx.new(|cx| Buffer::local("", cx));
 1176        let buffer = cx.new(|cx| MultiBuffer::singleton(buffer, cx));
 1177        Self::new(
 1178            EditorMode::AutoHeight { max_lines },
 1179            buffer,
 1180            None,
 1181            window,
 1182            cx,
 1183        )
 1184    }
 1185
 1186    pub fn for_buffer(
 1187        buffer: Entity<Buffer>,
 1188        project: Option<Entity<Project>>,
 1189        window: &mut Window,
 1190        cx: &mut Context<Self>,
 1191    ) -> Self {
 1192        let buffer = cx.new(|cx| MultiBuffer::singleton(buffer, cx));
 1193        Self::new(EditorMode::Full, buffer, project, window, cx)
 1194    }
 1195
 1196    pub fn for_multibuffer(
 1197        buffer: Entity<MultiBuffer>,
 1198        project: Option<Entity<Project>>,
 1199        window: &mut Window,
 1200        cx: &mut Context<Self>,
 1201    ) -> Self {
 1202        Self::new(EditorMode::Full, buffer, project, window, cx)
 1203    }
 1204
 1205    pub fn clone(&self, window: &mut Window, cx: &mut Context<Self>) -> Self {
 1206        let mut clone = Self::new(
 1207            self.mode,
 1208            self.buffer.clone(),
 1209            self.project.clone(),
 1210            window,
 1211            cx,
 1212        );
 1213        self.display_map.update(cx, |display_map, cx| {
 1214            let snapshot = display_map.snapshot(cx);
 1215            clone.display_map.update(cx, |display_map, cx| {
 1216                display_map.set_state(&snapshot, cx);
 1217            });
 1218        });
 1219        clone.folds_did_change(cx);
 1220        clone.selections.clone_state(&self.selections);
 1221        clone.scroll_manager.clone_state(&self.scroll_manager);
 1222        clone.searchable = self.searchable;
 1223        clone
 1224    }
 1225
 1226    pub fn new(
 1227        mode: EditorMode,
 1228        buffer: Entity<MultiBuffer>,
 1229        project: Option<Entity<Project>>,
 1230        window: &mut Window,
 1231        cx: &mut Context<Self>,
 1232    ) -> Self {
 1233        let style = window.text_style();
 1234        let font_size = style.font_size.to_pixels(window.rem_size());
 1235        let editor = cx.entity().downgrade();
 1236        let fold_placeholder = FoldPlaceholder {
 1237            constrain_width: true,
 1238            render: Arc::new(move |fold_id, fold_range, cx| {
 1239                let editor = editor.clone();
 1240                div()
 1241                    .id(fold_id)
 1242                    .bg(cx.theme().colors().ghost_element_background)
 1243                    .hover(|style| style.bg(cx.theme().colors().ghost_element_hover))
 1244                    .active(|style| style.bg(cx.theme().colors().ghost_element_active))
 1245                    .rounded_xs()
 1246                    .size_full()
 1247                    .cursor_pointer()
 1248                    .child("")
 1249                    .on_mouse_down(MouseButton::Left, |_, _, cx| cx.stop_propagation())
 1250                    .on_click(move |_, _window, cx| {
 1251                        editor
 1252                            .update(cx, |editor, cx| {
 1253                                editor.unfold_ranges(
 1254                                    &[fold_range.start..fold_range.end],
 1255                                    true,
 1256                                    false,
 1257                                    cx,
 1258                                );
 1259                                cx.stop_propagation();
 1260                            })
 1261                            .ok();
 1262                    })
 1263                    .into_any()
 1264            }),
 1265            merge_adjacent: true,
 1266            ..Default::default()
 1267        };
 1268        let display_map = cx.new(|cx| {
 1269            DisplayMap::new(
 1270                buffer.clone(),
 1271                style.font(),
 1272                font_size,
 1273                None,
 1274                FILE_HEADER_HEIGHT,
 1275                MULTI_BUFFER_EXCERPT_HEADER_HEIGHT,
 1276                fold_placeholder,
 1277                cx,
 1278            )
 1279        });
 1280
 1281        let selections = SelectionsCollection::new(display_map.clone(), buffer.clone());
 1282
 1283        let blink_manager = cx.new(|cx| BlinkManager::new(CURSOR_BLINK_INTERVAL, cx));
 1284
 1285        let soft_wrap_mode_override = matches!(mode, EditorMode::SingleLine { .. })
 1286            .then(|| language_settings::SoftWrap::None);
 1287
 1288        let mut project_subscriptions = Vec::new();
 1289        if mode == EditorMode::Full {
 1290            if let Some(project) = project.as_ref() {
 1291                project_subscriptions.push(cx.subscribe_in(
 1292                    project,
 1293                    window,
 1294                    |editor, _, event, window, cx| match event {
 1295                        project::Event::RefreshCodeLens => {
 1296                            // we always query lens with actions, without storing them, always refreshing them
 1297                        }
 1298                        project::Event::RefreshInlayHints => {
 1299                            editor
 1300                                .refresh_inlay_hints(InlayHintRefreshReason::RefreshRequested, cx);
 1301                        }
 1302                        project::Event::SnippetEdit(id, snippet_edits) => {
 1303                            if let Some(buffer) = editor.buffer.read(cx).buffer(*id) {
 1304                                let focus_handle = editor.focus_handle(cx);
 1305                                if focus_handle.is_focused(window) {
 1306                                    let snapshot = buffer.read(cx).snapshot();
 1307                                    for (range, snippet) in snippet_edits {
 1308                                        let editor_range =
 1309                                            language::range_from_lsp(*range).to_offset(&snapshot);
 1310                                        editor
 1311                                            .insert_snippet(
 1312                                                &[editor_range],
 1313                                                snippet.clone(),
 1314                                                window,
 1315                                                cx,
 1316                                            )
 1317                                            .ok();
 1318                                    }
 1319                                }
 1320                            }
 1321                        }
 1322                        _ => {}
 1323                    },
 1324                ));
 1325                if let Some(task_inventory) = project
 1326                    .read(cx)
 1327                    .task_store()
 1328                    .read(cx)
 1329                    .task_inventory()
 1330                    .cloned()
 1331                {
 1332                    project_subscriptions.push(cx.observe_in(
 1333                        &task_inventory,
 1334                        window,
 1335                        |editor, _, window, cx| {
 1336                            editor.tasks_update_task = Some(editor.refresh_runnables(window, cx));
 1337                        },
 1338                    ));
 1339                };
 1340
 1341                project_subscriptions.push(cx.subscribe_in(
 1342                    &project.read(cx).breakpoint_store(),
 1343                    window,
 1344                    |editor, _, event, window, cx| match event {
 1345                        BreakpointStoreEvent::ActiveDebugLineChanged => {
 1346                            editor.go_to_active_debug_line(window, cx);
 1347                        }
 1348                        _ => {}
 1349                    },
 1350                ));
 1351            }
 1352        }
 1353
 1354        let buffer_snapshot = buffer.read(cx).snapshot(cx);
 1355
 1356        let inlay_hint_settings =
 1357            inlay_hint_settings(selections.newest_anchor().head(), &buffer_snapshot, cx);
 1358        let focus_handle = cx.focus_handle();
 1359        cx.on_focus(&focus_handle, window, Self::handle_focus)
 1360            .detach();
 1361        cx.on_focus_in(&focus_handle, window, Self::handle_focus_in)
 1362            .detach();
 1363        cx.on_focus_out(&focus_handle, window, Self::handle_focus_out)
 1364            .detach();
 1365        cx.on_blur(&focus_handle, window, Self::handle_blur)
 1366            .detach();
 1367
 1368        let show_indent_guides = if matches!(mode, EditorMode::SingleLine { .. }) {
 1369            Some(false)
 1370        } else {
 1371            None
 1372        };
 1373
 1374        let breakpoint_store = match (mode, project.as_ref()) {
 1375            (EditorMode::Full, Some(project)) => Some(project.read(cx).breakpoint_store()),
 1376            _ => None,
 1377        };
 1378
 1379        let mut code_action_providers = Vec::new();
 1380        let mut load_uncommitted_diff = None;
 1381        if let Some(project) = project.clone() {
 1382            load_uncommitted_diff = Some(
 1383                get_uncommitted_diff_for_buffer(
 1384                    &project,
 1385                    buffer.read(cx).all_buffers(),
 1386                    buffer.clone(),
 1387                    cx,
 1388                )
 1389                .shared(),
 1390            );
 1391            code_action_providers.push(Rc::new(project) as Rc<_>);
 1392        }
 1393
 1394        let mut this = Self {
 1395            focus_handle,
 1396            show_cursor_when_unfocused: false,
 1397            last_focused_descendant: None,
 1398            buffer: buffer.clone(),
 1399            display_map: display_map.clone(),
 1400            selections,
 1401            scroll_manager: ScrollManager::new(cx),
 1402            columnar_selection_tail: None,
 1403            add_selections_state: None,
 1404            select_next_state: None,
 1405            select_prev_state: None,
 1406            selection_history: Default::default(),
 1407            autoclose_regions: Default::default(),
 1408            snippet_stack: Default::default(),
 1409            select_syntax_node_history: SelectSyntaxNodeHistory::default(),
 1410            ime_transaction: Default::default(),
 1411            active_diagnostics: None,
 1412            show_inline_diagnostics: ProjectSettings::get_global(cx).diagnostics.inline.enabled,
 1413            inline_diagnostics_update: Task::ready(()),
 1414            inline_diagnostics: Vec::new(),
 1415            soft_wrap_mode_override,
 1416            hard_wrap: None,
 1417            completion_provider: project.clone().map(|project| Box::new(project) as _),
 1418            semantics_provider: project.clone().map(|project| Rc::new(project) as _),
 1419            collaboration_hub: project.clone().map(|project| Box::new(project) as _),
 1420            project,
 1421            blink_manager: blink_manager.clone(),
 1422            show_local_selections: true,
 1423            show_scrollbars: true,
 1424            mode,
 1425            show_breadcrumbs: EditorSettings::get_global(cx).toolbar.breadcrumbs,
 1426            show_gutter: mode == EditorMode::Full,
 1427            show_line_numbers: None,
 1428            use_relative_line_numbers: None,
 1429            show_git_diff_gutter: None,
 1430            show_code_actions: None,
 1431            show_runnables: None,
 1432            show_breakpoints: None,
 1433            show_wrap_guides: None,
 1434            show_indent_guides,
 1435            placeholder_text: None,
 1436            highlight_order: 0,
 1437            highlighted_rows: HashMap::default(),
 1438            background_highlights: Default::default(),
 1439            gutter_highlights: TreeMap::default(),
 1440            scrollbar_marker_state: ScrollbarMarkerState::default(),
 1441            active_indent_guides_state: ActiveIndentGuidesState::default(),
 1442            nav_history: None,
 1443            context_menu: RefCell::new(None),
 1444            mouse_context_menu: None,
 1445            completion_tasks: Default::default(),
 1446            signature_help_state: SignatureHelpState::default(),
 1447            auto_signature_help: None,
 1448            find_all_references_task_sources: Vec::new(),
 1449            next_completion_id: 0,
 1450            next_inlay_id: 0,
 1451            code_action_providers,
 1452            available_code_actions: Default::default(),
 1453            code_actions_task: Default::default(),
 1454            selection_highlight_task: Default::default(),
 1455            document_highlights_task: Default::default(),
 1456            linked_editing_range_task: Default::default(),
 1457            pending_rename: Default::default(),
 1458            searchable: true,
 1459            cursor_shape: EditorSettings::get_global(cx)
 1460                .cursor_shape
 1461                .unwrap_or_default(),
 1462            current_line_highlight: None,
 1463            autoindent_mode: Some(AutoindentMode::EachLine),
 1464            collapse_matches: false,
 1465            workspace: None,
 1466            input_enabled: true,
 1467            use_modal_editing: mode == EditorMode::Full,
 1468            read_only: false,
 1469            use_autoclose: true,
 1470            use_auto_surround: true,
 1471            auto_replace_emoji_shortcode: false,
 1472            jsx_tag_auto_close_enabled_in_any_buffer: false,
 1473            leader_peer_id: None,
 1474            remote_id: None,
 1475            hover_state: Default::default(),
 1476            pending_mouse_down: None,
 1477            hovered_link_state: Default::default(),
 1478            edit_prediction_provider: None,
 1479            active_inline_completion: None,
 1480            stale_inline_completion_in_menu: None,
 1481            edit_prediction_preview: EditPredictionPreview::Inactive {
 1482                released_too_fast: false,
 1483            },
 1484            inline_diagnostics_enabled: mode == EditorMode::Full,
 1485            inlay_hint_cache: InlayHintCache::new(inlay_hint_settings),
 1486
 1487            gutter_hovered: false,
 1488            pixel_position_of_newest_cursor: None,
 1489            last_bounds: None,
 1490            last_position_map: None,
 1491            expect_bounds_change: None,
 1492            gutter_dimensions: GutterDimensions::default(),
 1493            style: None,
 1494            show_cursor_names: false,
 1495            hovered_cursors: Default::default(),
 1496            next_editor_action_id: EditorActionId::default(),
 1497            editor_actions: Rc::default(),
 1498            inline_completions_hidden_for_vim_mode: false,
 1499            show_inline_completions_override: None,
 1500            menu_inline_completions_policy: MenuInlineCompletionsPolicy::ByProvider,
 1501            edit_prediction_settings: EditPredictionSettings::Disabled,
 1502            edit_prediction_indent_conflict: false,
 1503            edit_prediction_requires_modifier_in_indent_conflict: true,
 1504            custom_context_menu: None,
 1505            show_git_blame_gutter: false,
 1506            show_git_blame_inline: false,
 1507            show_selection_menu: None,
 1508            show_git_blame_inline_delay_task: None,
 1509            git_blame_inline_tooltip: None,
 1510            git_blame_inline_enabled: ProjectSettings::get_global(cx).git.inline_blame_enabled(),
 1511            serialize_dirty_buffers: ProjectSettings::get_global(cx)
 1512                .session
 1513                .restore_unsaved_buffers,
 1514            blame: None,
 1515            blame_subscription: None,
 1516            tasks: Default::default(),
 1517
 1518            breakpoint_store,
 1519            gutter_breakpoint_indicator: None,
 1520            _subscriptions: vec![
 1521                cx.observe(&buffer, Self::on_buffer_changed),
 1522                cx.subscribe_in(&buffer, window, Self::on_buffer_event),
 1523                cx.observe_in(&display_map, window, Self::on_display_map_changed),
 1524                cx.observe(&blink_manager, |_, _, cx| cx.notify()),
 1525                cx.observe_global_in::<SettingsStore>(window, Self::settings_changed),
 1526                observe_buffer_font_size_adjustment(cx, |_, cx| cx.notify()),
 1527                cx.observe_window_activation(window, |editor, window, cx| {
 1528                    let active = window.is_window_active();
 1529                    editor.blink_manager.update(cx, |blink_manager, cx| {
 1530                        if active {
 1531                            blink_manager.enable(cx);
 1532                        } else {
 1533                            blink_manager.disable(cx);
 1534                        }
 1535                    });
 1536                }),
 1537            ],
 1538            tasks_update_task: None,
 1539            linked_edit_ranges: Default::default(),
 1540            in_project_search: false,
 1541            previous_search_ranges: None,
 1542            breadcrumb_header: None,
 1543            focused_block: None,
 1544            next_scroll_position: NextScrollCursorCenterTopBottom::default(),
 1545            addons: HashMap::default(),
 1546            registered_buffers: HashMap::default(),
 1547            _scroll_cursor_center_top_bottom_task: Task::ready(()),
 1548            selection_mark_mode: false,
 1549            toggle_fold_multiple_buffers: Task::ready(()),
 1550            serialize_selections: Task::ready(()),
 1551            serialize_folds: Task::ready(()),
 1552            text_style_refinement: None,
 1553            load_diff_task: load_uncommitted_diff,
 1554        };
 1555        if let Some(breakpoints) = this.breakpoint_store.as_ref() {
 1556            this._subscriptions
 1557                .push(cx.observe(breakpoints, |_, _, cx| {
 1558                    cx.notify();
 1559                }));
 1560        }
 1561        this.tasks_update_task = Some(this.refresh_runnables(window, cx));
 1562        this._subscriptions.extend(project_subscriptions);
 1563
 1564        this.end_selection(window, cx);
 1565        this.scroll_manager.show_scrollbar(window, cx);
 1566        jsx_tag_auto_close::refresh_enabled_in_any_buffer(&mut this, &buffer, cx);
 1567
 1568        if mode == EditorMode::Full {
 1569            let should_auto_hide_scrollbars = cx.should_auto_hide_scrollbars();
 1570            cx.set_global(ScrollbarAutoHide(should_auto_hide_scrollbars));
 1571
 1572            if this.git_blame_inline_enabled {
 1573                this.git_blame_inline_enabled = true;
 1574                this.start_git_blame_inline(false, window, cx);
 1575            }
 1576
 1577            this.go_to_active_debug_line(window, cx);
 1578
 1579            if let Some(buffer) = buffer.read(cx).as_singleton() {
 1580                if let Some(project) = this.project.as_ref() {
 1581                    let handle = project.update(cx, |project, cx| {
 1582                        project.register_buffer_with_language_servers(&buffer, cx)
 1583                    });
 1584                    this.registered_buffers
 1585                        .insert(buffer.read(cx).remote_id(), handle);
 1586                }
 1587            }
 1588        }
 1589
 1590        this.report_editor_event("Editor Opened", None, cx);
 1591        this
 1592    }
 1593
 1594    pub fn mouse_menu_is_focused(&self, window: &Window, cx: &App) -> bool {
 1595        self.mouse_context_menu
 1596            .as_ref()
 1597            .is_some_and(|menu| menu.context_menu.focus_handle(cx).is_focused(window))
 1598    }
 1599
 1600    fn key_context(&self, window: &Window, cx: &App) -> KeyContext {
 1601        self.key_context_internal(self.has_active_inline_completion(), window, cx)
 1602    }
 1603
 1604    fn key_context_internal(
 1605        &self,
 1606        has_active_edit_prediction: bool,
 1607        window: &Window,
 1608        cx: &App,
 1609    ) -> KeyContext {
 1610        let mut key_context = KeyContext::new_with_defaults();
 1611        key_context.add("Editor");
 1612        let mode = match self.mode {
 1613            EditorMode::SingleLine { .. } => "single_line",
 1614            EditorMode::AutoHeight { .. } => "auto_height",
 1615            EditorMode::Full => "full",
 1616        };
 1617
 1618        if EditorSettings::jupyter_enabled(cx) {
 1619            key_context.add("jupyter");
 1620        }
 1621
 1622        key_context.set("mode", mode);
 1623        if self.pending_rename.is_some() {
 1624            key_context.add("renaming");
 1625        }
 1626
 1627        match self.context_menu.borrow().as_ref() {
 1628            Some(CodeContextMenu::Completions(_)) => {
 1629                key_context.add("menu");
 1630                key_context.add("showing_completions");
 1631            }
 1632            Some(CodeContextMenu::CodeActions(_)) => {
 1633                key_context.add("menu");
 1634                key_context.add("showing_code_actions")
 1635            }
 1636            None => {}
 1637        }
 1638
 1639        // Disable vim contexts when a sub-editor (e.g. rename/inline assistant) is focused.
 1640        if !self.focus_handle(cx).contains_focused(window, cx)
 1641            || (self.is_focused(window) || self.mouse_menu_is_focused(window, cx))
 1642        {
 1643            for addon in self.addons.values() {
 1644                addon.extend_key_context(&mut key_context, cx)
 1645            }
 1646        }
 1647
 1648        if let Some(singleton_buffer) = self.buffer.read(cx).as_singleton() {
 1649            if let Some(extension) = singleton_buffer
 1650                .read(cx)
 1651                .file()
 1652                .and_then(|file| file.path().extension()?.to_str())
 1653            {
 1654                key_context.set("extension", extension.to_string());
 1655            }
 1656        } else {
 1657            key_context.add("multibuffer");
 1658        }
 1659
 1660        if has_active_edit_prediction {
 1661            if self.edit_prediction_in_conflict() {
 1662                key_context.add(EDIT_PREDICTION_CONFLICT_KEY_CONTEXT);
 1663            } else {
 1664                key_context.add(EDIT_PREDICTION_KEY_CONTEXT);
 1665                key_context.add("copilot_suggestion");
 1666            }
 1667        }
 1668
 1669        if self.selection_mark_mode {
 1670            key_context.add("selection_mode");
 1671        }
 1672
 1673        key_context
 1674    }
 1675
 1676    pub fn edit_prediction_in_conflict(&self) -> bool {
 1677        if !self.show_edit_predictions_in_menu() {
 1678            return false;
 1679        }
 1680
 1681        let showing_completions = self
 1682            .context_menu
 1683            .borrow()
 1684            .as_ref()
 1685            .map_or(false, |context| {
 1686                matches!(context, CodeContextMenu::Completions(_))
 1687            });
 1688
 1689        showing_completions
 1690            || self.edit_prediction_requires_modifier()
 1691            // Require modifier key when the cursor is on leading whitespace, to allow `tab`
 1692            // bindings to insert tab characters.
 1693            || (self.edit_prediction_requires_modifier_in_indent_conflict && self.edit_prediction_indent_conflict)
 1694    }
 1695
 1696    pub fn accept_edit_prediction_keybind(
 1697        &self,
 1698        window: &Window,
 1699        cx: &App,
 1700    ) -> AcceptEditPredictionBinding {
 1701        let key_context = self.key_context_internal(true, window, cx);
 1702        let in_conflict = self.edit_prediction_in_conflict();
 1703
 1704        AcceptEditPredictionBinding(
 1705            window
 1706                .bindings_for_action_in_context(&AcceptEditPrediction, key_context)
 1707                .into_iter()
 1708                .filter(|binding| {
 1709                    !in_conflict
 1710                        || binding
 1711                            .keystrokes()
 1712                            .first()
 1713                            .map_or(false, |keystroke| keystroke.modifiers.modified())
 1714                })
 1715                .rev()
 1716                .min_by_key(|binding| {
 1717                    binding
 1718                        .keystrokes()
 1719                        .first()
 1720                        .map_or(u8::MAX, |k| k.modifiers.number_of_modifiers())
 1721                }),
 1722        )
 1723    }
 1724
 1725    pub fn new_file(
 1726        workspace: &mut Workspace,
 1727        _: &workspace::NewFile,
 1728        window: &mut Window,
 1729        cx: &mut Context<Workspace>,
 1730    ) {
 1731        Self::new_in_workspace(workspace, window, cx).detach_and_prompt_err(
 1732            "Failed to create buffer",
 1733            window,
 1734            cx,
 1735            |e, _, _| match e.error_code() {
 1736                ErrorCode::RemoteUpgradeRequired => Some(format!(
 1737                "The remote instance of Zed does not support this yet. It must be upgraded to {}",
 1738                e.error_tag("required").unwrap_or("the latest version")
 1739            )),
 1740                _ => None,
 1741            },
 1742        );
 1743    }
 1744
 1745    pub fn new_in_workspace(
 1746        workspace: &mut Workspace,
 1747        window: &mut Window,
 1748        cx: &mut Context<Workspace>,
 1749    ) -> Task<Result<Entity<Editor>>> {
 1750        let project = workspace.project().clone();
 1751        let create = project.update(cx, |project, cx| project.create_buffer(cx));
 1752
 1753        cx.spawn_in(window, async move |workspace, cx| {
 1754            let buffer = create.await?;
 1755            workspace.update_in(cx, |workspace, window, cx| {
 1756                let editor =
 1757                    cx.new(|cx| Editor::for_buffer(buffer, Some(project.clone()), window, cx));
 1758                workspace.add_item_to_active_pane(Box::new(editor.clone()), None, true, window, cx);
 1759                editor
 1760            })
 1761        })
 1762    }
 1763
 1764    fn new_file_vertical(
 1765        workspace: &mut Workspace,
 1766        _: &workspace::NewFileSplitVertical,
 1767        window: &mut Window,
 1768        cx: &mut Context<Workspace>,
 1769    ) {
 1770        Self::new_file_in_direction(workspace, SplitDirection::vertical(cx), window, cx)
 1771    }
 1772
 1773    fn new_file_horizontal(
 1774        workspace: &mut Workspace,
 1775        _: &workspace::NewFileSplitHorizontal,
 1776        window: &mut Window,
 1777        cx: &mut Context<Workspace>,
 1778    ) {
 1779        Self::new_file_in_direction(workspace, SplitDirection::horizontal(cx), window, cx)
 1780    }
 1781
 1782    fn new_file_in_direction(
 1783        workspace: &mut Workspace,
 1784        direction: SplitDirection,
 1785        window: &mut Window,
 1786        cx: &mut Context<Workspace>,
 1787    ) {
 1788        let project = workspace.project().clone();
 1789        let create = project.update(cx, |project, cx| project.create_buffer(cx));
 1790
 1791        cx.spawn_in(window, async move |workspace, cx| {
 1792            let buffer = create.await?;
 1793            workspace.update_in(cx, move |workspace, window, cx| {
 1794                workspace.split_item(
 1795                    direction,
 1796                    Box::new(
 1797                        cx.new(|cx| Editor::for_buffer(buffer, Some(project.clone()), window, cx)),
 1798                    ),
 1799                    window,
 1800                    cx,
 1801                )
 1802            })?;
 1803            anyhow::Ok(())
 1804        })
 1805        .detach_and_prompt_err("Failed to create buffer", window, cx, |e, _, _| {
 1806            match e.error_code() {
 1807                ErrorCode::RemoteUpgradeRequired => Some(format!(
 1808                "The remote instance of Zed does not support this yet. It must be upgraded to {}",
 1809                e.error_tag("required").unwrap_or("the latest version")
 1810            )),
 1811                _ => None,
 1812            }
 1813        });
 1814    }
 1815
 1816    pub fn leader_peer_id(&self) -> Option<PeerId> {
 1817        self.leader_peer_id
 1818    }
 1819
 1820    pub fn buffer(&self) -> &Entity<MultiBuffer> {
 1821        &self.buffer
 1822    }
 1823
 1824    pub fn workspace(&self) -> Option<Entity<Workspace>> {
 1825        self.workspace.as_ref()?.0.upgrade()
 1826    }
 1827
 1828    pub fn title<'a>(&self, cx: &'a App) -> Cow<'a, str> {
 1829        self.buffer().read(cx).title(cx)
 1830    }
 1831
 1832    pub fn snapshot(&self, window: &mut Window, cx: &mut App) -> EditorSnapshot {
 1833        let git_blame_gutter_max_author_length = self
 1834            .render_git_blame_gutter(cx)
 1835            .then(|| {
 1836                if let Some(blame) = self.blame.as_ref() {
 1837                    let max_author_length =
 1838                        blame.update(cx, |blame, cx| blame.max_author_length(cx));
 1839                    Some(max_author_length)
 1840                } else {
 1841                    None
 1842                }
 1843            })
 1844            .flatten();
 1845
 1846        EditorSnapshot {
 1847            mode: self.mode,
 1848            show_gutter: self.show_gutter,
 1849            show_line_numbers: self.show_line_numbers,
 1850            show_git_diff_gutter: self.show_git_diff_gutter,
 1851            show_code_actions: self.show_code_actions,
 1852            show_runnables: self.show_runnables,
 1853            show_breakpoints: self.show_breakpoints,
 1854            git_blame_gutter_max_author_length,
 1855            display_snapshot: self.display_map.update(cx, |map, cx| map.snapshot(cx)),
 1856            scroll_anchor: self.scroll_manager.anchor(),
 1857            ongoing_scroll: self.scroll_manager.ongoing_scroll(),
 1858            placeholder_text: self.placeholder_text.clone(),
 1859            is_focused: self.focus_handle.is_focused(window),
 1860            current_line_highlight: self
 1861                .current_line_highlight
 1862                .unwrap_or_else(|| EditorSettings::get_global(cx).current_line_highlight),
 1863            gutter_hovered: self.gutter_hovered,
 1864        }
 1865    }
 1866
 1867    pub fn language_at<T: ToOffset>(&self, point: T, cx: &App) -> Option<Arc<Language>> {
 1868        self.buffer.read(cx).language_at(point, cx)
 1869    }
 1870
 1871    pub fn file_at<T: ToOffset>(&self, point: T, cx: &App) -> Option<Arc<dyn language::File>> {
 1872        self.buffer.read(cx).read(cx).file_at(point).cloned()
 1873    }
 1874
 1875    pub fn active_excerpt(
 1876        &self,
 1877        cx: &App,
 1878    ) -> Option<(ExcerptId, Entity<Buffer>, Range<text::Anchor>)> {
 1879        self.buffer
 1880            .read(cx)
 1881            .excerpt_containing(self.selections.newest_anchor().head(), cx)
 1882    }
 1883
 1884    pub fn mode(&self) -> EditorMode {
 1885        self.mode
 1886    }
 1887
 1888    pub fn collaboration_hub(&self) -> Option<&dyn CollaborationHub> {
 1889        self.collaboration_hub.as_deref()
 1890    }
 1891
 1892    pub fn set_collaboration_hub(&mut self, hub: Box<dyn CollaborationHub>) {
 1893        self.collaboration_hub = Some(hub);
 1894    }
 1895
 1896    pub fn set_in_project_search(&mut self, in_project_search: bool) {
 1897        self.in_project_search = in_project_search;
 1898    }
 1899
 1900    pub fn set_custom_context_menu(
 1901        &mut self,
 1902        f: impl 'static
 1903            + Fn(
 1904                &mut Self,
 1905                DisplayPoint,
 1906                &mut Window,
 1907                &mut Context<Self>,
 1908            ) -> Option<Entity<ui::ContextMenu>>,
 1909    ) {
 1910        self.custom_context_menu = Some(Box::new(f))
 1911    }
 1912
 1913    pub fn set_completion_provider(&mut self, provider: Option<Box<dyn CompletionProvider>>) {
 1914        self.completion_provider = provider;
 1915    }
 1916
 1917    pub fn semantics_provider(&self) -> Option<Rc<dyn SemanticsProvider>> {
 1918        self.semantics_provider.clone()
 1919    }
 1920
 1921    pub fn set_semantics_provider(&mut self, provider: Option<Rc<dyn SemanticsProvider>>) {
 1922        self.semantics_provider = provider;
 1923    }
 1924
 1925    pub fn set_edit_prediction_provider<T>(
 1926        &mut self,
 1927        provider: Option<Entity<T>>,
 1928        window: &mut Window,
 1929        cx: &mut Context<Self>,
 1930    ) where
 1931        T: EditPredictionProvider,
 1932    {
 1933        self.edit_prediction_provider =
 1934            provider.map(|provider| RegisteredInlineCompletionProvider {
 1935                _subscription: cx.observe_in(&provider, window, |this, _, window, cx| {
 1936                    if this.focus_handle.is_focused(window) {
 1937                        this.update_visible_inline_completion(window, cx);
 1938                    }
 1939                }),
 1940                provider: Arc::new(provider),
 1941            });
 1942        self.update_edit_prediction_settings(cx);
 1943        self.refresh_inline_completion(false, false, window, cx);
 1944    }
 1945
 1946    pub fn placeholder_text(&self) -> Option<&str> {
 1947        self.placeholder_text.as_deref()
 1948    }
 1949
 1950    pub fn set_placeholder_text(
 1951        &mut self,
 1952        placeholder_text: impl Into<Arc<str>>,
 1953        cx: &mut Context<Self>,
 1954    ) {
 1955        let placeholder_text = Some(placeholder_text.into());
 1956        if self.placeholder_text != placeholder_text {
 1957            self.placeholder_text = placeholder_text;
 1958            cx.notify();
 1959        }
 1960    }
 1961
 1962    pub fn set_cursor_shape(&mut self, cursor_shape: CursorShape, cx: &mut Context<Self>) {
 1963        self.cursor_shape = cursor_shape;
 1964
 1965        // Disrupt blink for immediate user feedback that the cursor shape has changed
 1966        self.blink_manager.update(cx, BlinkManager::show_cursor);
 1967
 1968        cx.notify();
 1969    }
 1970
 1971    pub fn set_current_line_highlight(
 1972        &mut self,
 1973        current_line_highlight: Option<CurrentLineHighlight>,
 1974    ) {
 1975        self.current_line_highlight = current_line_highlight;
 1976    }
 1977
 1978    pub fn set_collapse_matches(&mut self, collapse_matches: bool) {
 1979        self.collapse_matches = collapse_matches;
 1980    }
 1981
 1982    fn register_buffers_with_language_servers(&mut self, cx: &mut Context<Self>) {
 1983        let buffers = self.buffer.read(cx).all_buffers();
 1984        let Some(project) = self.project.as_ref() else {
 1985            return;
 1986        };
 1987        project.update(cx, |project, cx| {
 1988            for buffer in buffers {
 1989                self.registered_buffers
 1990                    .entry(buffer.read(cx).remote_id())
 1991                    .or_insert_with(|| project.register_buffer_with_language_servers(&buffer, cx));
 1992            }
 1993        })
 1994    }
 1995
 1996    pub fn range_for_match<T: std::marker::Copy>(&self, range: &Range<T>) -> Range<T> {
 1997        if self.collapse_matches {
 1998            return range.start..range.start;
 1999        }
 2000        range.clone()
 2001    }
 2002
 2003    pub fn set_clip_at_line_ends(&mut self, clip: bool, cx: &mut Context<Self>) {
 2004        if self.display_map.read(cx).clip_at_line_ends != clip {
 2005            self.display_map
 2006                .update(cx, |map, _| map.clip_at_line_ends = clip);
 2007        }
 2008    }
 2009
 2010    pub fn set_input_enabled(&mut self, input_enabled: bool) {
 2011        self.input_enabled = input_enabled;
 2012    }
 2013
 2014    pub fn set_inline_completions_hidden_for_vim_mode(
 2015        &mut self,
 2016        hidden: bool,
 2017        window: &mut Window,
 2018        cx: &mut Context<Self>,
 2019    ) {
 2020        if hidden != self.inline_completions_hidden_for_vim_mode {
 2021            self.inline_completions_hidden_for_vim_mode = hidden;
 2022            if hidden {
 2023                self.update_visible_inline_completion(window, cx);
 2024            } else {
 2025                self.refresh_inline_completion(true, false, window, cx);
 2026            }
 2027        }
 2028    }
 2029
 2030    pub fn set_menu_inline_completions_policy(&mut self, value: MenuInlineCompletionsPolicy) {
 2031        self.menu_inline_completions_policy = value;
 2032    }
 2033
 2034    pub fn set_autoindent(&mut self, autoindent: bool) {
 2035        if autoindent {
 2036            self.autoindent_mode = Some(AutoindentMode::EachLine);
 2037        } else {
 2038            self.autoindent_mode = None;
 2039        }
 2040    }
 2041
 2042    pub fn read_only(&self, cx: &App) -> bool {
 2043        self.read_only || self.buffer.read(cx).read_only()
 2044    }
 2045
 2046    pub fn set_read_only(&mut self, read_only: bool) {
 2047        self.read_only = read_only;
 2048    }
 2049
 2050    pub fn set_use_autoclose(&mut self, autoclose: bool) {
 2051        self.use_autoclose = autoclose;
 2052    }
 2053
 2054    pub fn set_use_auto_surround(&mut self, auto_surround: bool) {
 2055        self.use_auto_surround = auto_surround;
 2056    }
 2057
 2058    pub fn set_auto_replace_emoji_shortcode(&mut self, auto_replace: bool) {
 2059        self.auto_replace_emoji_shortcode = auto_replace;
 2060    }
 2061
 2062    pub fn toggle_edit_predictions(
 2063        &mut self,
 2064        _: &ToggleEditPrediction,
 2065        window: &mut Window,
 2066        cx: &mut Context<Self>,
 2067    ) {
 2068        if self.show_inline_completions_override.is_some() {
 2069            self.set_show_edit_predictions(None, window, cx);
 2070        } else {
 2071            let show_edit_predictions = !self.edit_predictions_enabled();
 2072            self.set_show_edit_predictions(Some(show_edit_predictions), window, cx);
 2073        }
 2074    }
 2075
 2076    pub fn set_show_edit_predictions(
 2077        &mut self,
 2078        show_edit_predictions: Option<bool>,
 2079        window: &mut Window,
 2080        cx: &mut Context<Self>,
 2081    ) {
 2082        self.show_inline_completions_override = show_edit_predictions;
 2083        self.update_edit_prediction_settings(cx);
 2084
 2085        if let Some(false) = show_edit_predictions {
 2086            self.discard_inline_completion(false, cx);
 2087        } else {
 2088            self.refresh_inline_completion(false, true, window, cx);
 2089        }
 2090    }
 2091
 2092    fn inline_completions_disabled_in_scope(
 2093        &self,
 2094        buffer: &Entity<Buffer>,
 2095        buffer_position: language::Anchor,
 2096        cx: &App,
 2097    ) -> bool {
 2098        let snapshot = buffer.read(cx).snapshot();
 2099        let settings = snapshot.settings_at(buffer_position, cx);
 2100
 2101        let Some(scope) = snapshot.language_scope_at(buffer_position) else {
 2102            return false;
 2103        };
 2104
 2105        scope.override_name().map_or(false, |scope_name| {
 2106            settings
 2107                .edit_predictions_disabled_in
 2108                .iter()
 2109                .any(|s| s == scope_name)
 2110        })
 2111    }
 2112
 2113    pub fn set_use_modal_editing(&mut self, to: bool) {
 2114        self.use_modal_editing = to;
 2115    }
 2116
 2117    pub fn use_modal_editing(&self) -> bool {
 2118        self.use_modal_editing
 2119    }
 2120
 2121    fn selections_did_change(
 2122        &mut self,
 2123        local: bool,
 2124        old_cursor_position: &Anchor,
 2125        show_completions: bool,
 2126        window: &mut Window,
 2127        cx: &mut Context<Self>,
 2128    ) {
 2129        window.invalidate_character_coordinates();
 2130
 2131        // Copy selections to primary selection buffer
 2132        #[cfg(any(target_os = "linux", target_os = "freebsd"))]
 2133        if local {
 2134            let selections = self.selections.all::<usize>(cx);
 2135            let buffer_handle = self.buffer.read(cx).read(cx);
 2136
 2137            let mut text = String::new();
 2138            for (index, selection) in selections.iter().enumerate() {
 2139                let text_for_selection = buffer_handle
 2140                    .text_for_range(selection.start..selection.end)
 2141                    .collect::<String>();
 2142
 2143                text.push_str(&text_for_selection);
 2144                if index != selections.len() - 1 {
 2145                    text.push('\n');
 2146                }
 2147            }
 2148
 2149            if !text.is_empty() {
 2150                cx.write_to_primary(ClipboardItem::new_string(text));
 2151            }
 2152        }
 2153
 2154        if self.focus_handle.is_focused(window) && self.leader_peer_id.is_none() {
 2155            self.buffer.update(cx, |buffer, cx| {
 2156                buffer.set_active_selections(
 2157                    &self.selections.disjoint_anchors(),
 2158                    self.selections.line_mode,
 2159                    self.cursor_shape,
 2160                    cx,
 2161                )
 2162            });
 2163        }
 2164        let display_map = self
 2165            .display_map
 2166            .update(cx, |display_map, cx| display_map.snapshot(cx));
 2167        let buffer = &display_map.buffer_snapshot;
 2168        self.add_selections_state = None;
 2169        self.select_next_state = None;
 2170        self.select_prev_state = None;
 2171        self.select_syntax_node_history.try_clear();
 2172        self.invalidate_autoclose_regions(&self.selections.disjoint_anchors(), buffer);
 2173        self.snippet_stack
 2174            .invalidate(&self.selections.disjoint_anchors(), buffer);
 2175        self.take_rename(false, window, cx);
 2176
 2177        let new_cursor_position = self.selections.newest_anchor().head();
 2178
 2179        self.push_to_nav_history(
 2180            *old_cursor_position,
 2181            Some(new_cursor_position.to_point(buffer)),
 2182            false,
 2183            cx,
 2184        );
 2185
 2186        if local {
 2187            let new_cursor_position = self.selections.newest_anchor().head();
 2188            let mut context_menu = self.context_menu.borrow_mut();
 2189            let completion_menu = match context_menu.as_ref() {
 2190                Some(CodeContextMenu::Completions(menu)) => Some(menu),
 2191                _ => {
 2192                    *context_menu = None;
 2193                    None
 2194                }
 2195            };
 2196            if let Some(buffer_id) = new_cursor_position.buffer_id {
 2197                if !self.registered_buffers.contains_key(&buffer_id) {
 2198                    if let Some(project) = self.project.as_ref() {
 2199                        project.update(cx, |project, cx| {
 2200                            let Some(buffer) = self.buffer.read(cx).buffer(buffer_id) else {
 2201                                return;
 2202                            };
 2203                            self.registered_buffers.insert(
 2204                                buffer_id,
 2205                                project.register_buffer_with_language_servers(&buffer, cx),
 2206                            );
 2207                        })
 2208                    }
 2209                }
 2210            }
 2211
 2212            if let Some(completion_menu) = completion_menu {
 2213                let cursor_position = new_cursor_position.to_offset(buffer);
 2214                let (word_range, kind) =
 2215                    buffer.surrounding_word(completion_menu.initial_position, true);
 2216                if kind == Some(CharKind::Word)
 2217                    && word_range.to_inclusive().contains(&cursor_position)
 2218                {
 2219                    let mut completion_menu = completion_menu.clone();
 2220                    drop(context_menu);
 2221
 2222                    let query = Self::completion_query(buffer, cursor_position);
 2223                    cx.spawn(async move |this, cx| {
 2224                        completion_menu
 2225                            .filter(query.as_deref(), cx.background_executor().clone())
 2226                            .await;
 2227
 2228                        this.update(cx, |this, cx| {
 2229                            let mut context_menu = this.context_menu.borrow_mut();
 2230                            let Some(CodeContextMenu::Completions(menu)) = context_menu.as_ref()
 2231                            else {
 2232                                return;
 2233                            };
 2234
 2235                            if menu.id > completion_menu.id {
 2236                                return;
 2237                            }
 2238
 2239                            *context_menu = Some(CodeContextMenu::Completions(completion_menu));
 2240                            drop(context_menu);
 2241                            cx.notify();
 2242                        })
 2243                    })
 2244                    .detach();
 2245
 2246                    if show_completions {
 2247                        self.show_completions(&ShowCompletions { trigger: None }, window, cx);
 2248                    }
 2249                } else {
 2250                    drop(context_menu);
 2251                    self.hide_context_menu(window, cx);
 2252                }
 2253            } else {
 2254                drop(context_menu);
 2255            }
 2256
 2257            hide_hover(self, cx);
 2258
 2259            if old_cursor_position.to_display_point(&display_map).row()
 2260                != new_cursor_position.to_display_point(&display_map).row()
 2261            {
 2262                self.available_code_actions.take();
 2263            }
 2264            self.refresh_code_actions(window, cx);
 2265            self.refresh_document_highlights(cx);
 2266            self.refresh_selected_text_highlights(window, cx);
 2267            refresh_matching_bracket_highlights(self, window, cx);
 2268            self.update_visible_inline_completion(window, cx);
 2269            self.edit_prediction_requires_modifier_in_indent_conflict = true;
 2270            linked_editing_ranges::refresh_linked_ranges(self, window, cx);
 2271            if self.git_blame_inline_enabled {
 2272                self.start_inline_blame_timer(window, cx);
 2273            }
 2274        }
 2275
 2276        self.blink_manager.update(cx, BlinkManager::pause_blinking);
 2277        cx.emit(EditorEvent::SelectionsChanged { local });
 2278
 2279        let selections = &self.selections.disjoint;
 2280        if selections.len() == 1 {
 2281            cx.emit(SearchEvent::ActiveMatchChanged)
 2282        }
 2283        if local
 2284            && self.is_singleton(cx)
 2285            && WorkspaceSettings::get(None, cx).restore_on_startup != RestoreOnStartupBehavior::None
 2286        {
 2287            if let Some(workspace_id) = self.workspace.as_ref().and_then(|workspace| workspace.1) {
 2288                let background_executor = cx.background_executor().clone();
 2289                let editor_id = cx.entity().entity_id().as_u64() as ItemId;
 2290                let snapshot = self.buffer().read(cx).snapshot(cx);
 2291                let selections = selections.clone();
 2292                self.serialize_selections = cx.background_spawn(async move {
 2293                    background_executor.timer(SERIALIZATION_THROTTLE_TIME).await;
 2294                    let selections = selections
 2295                        .iter()
 2296                        .map(|selection| {
 2297                            (
 2298                                selection.start.to_offset(&snapshot),
 2299                                selection.end.to_offset(&snapshot),
 2300                            )
 2301                        })
 2302                        .collect();
 2303                    DB.save_editor_selections(editor_id, workspace_id, selections)
 2304                        .await
 2305                        .with_context(|| format!("persisting editor selections for editor {editor_id}, workspace {workspace_id:?}"))
 2306                        .log_err();
 2307                });
 2308            }
 2309        }
 2310
 2311        cx.notify();
 2312    }
 2313
 2314    fn folds_did_change(&mut self, cx: &mut Context<Self>) {
 2315        if !self.is_singleton(cx)
 2316            || WorkspaceSettings::get(None, cx).restore_on_startup == RestoreOnStartupBehavior::None
 2317        {
 2318            return;
 2319        }
 2320
 2321        let Some(workspace_id) = self.workspace.as_ref().and_then(|workspace| workspace.1) else {
 2322            return;
 2323        };
 2324        let background_executor = cx.background_executor().clone();
 2325        let editor_id = cx.entity().entity_id().as_u64() as ItemId;
 2326        let snapshot = self.buffer().read(cx).snapshot(cx);
 2327        let folds = self.display_map.update(cx, |display_map, cx| {
 2328            display_map
 2329                .snapshot(cx)
 2330                .folds_in_range(0..snapshot.len())
 2331                .map(|fold| {
 2332                    (
 2333                        fold.range.start.to_offset(&snapshot),
 2334                        fold.range.end.to_offset(&snapshot),
 2335                    )
 2336                })
 2337                .collect()
 2338        });
 2339        self.serialize_folds = cx.background_spawn(async move {
 2340            background_executor.timer(SERIALIZATION_THROTTLE_TIME).await;
 2341            DB.save_editor_folds(editor_id, workspace_id, folds)
 2342                .await
 2343                .with_context(|| format!("persisting editor folds for editor {editor_id}, workspace {workspace_id:?}"))
 2344                .log_err();
 2345        });
 2346    }
 2347
 2348    pub fn sync_selections(
 2349        &mut self,
 2350        other: Entity<Editor>,
 2351        cx: &mut Context<Self>,
 2352    ) -> gpui::Subscription {
 2353        let other_selections = other.read(cx).selections.disjoint.to_vec();
 2354        self.selections.change_with(cx, |selections| {
 2355            selections.select_anchors(other_selections);
 2356        });
 2357
 2358        let other_subscription =
 2359            cx.subscribe(&other, |this, other, other_evt, cx| match other_evt {
 2360                EditorEvent::SelectionsChanged { local: true } => {
 2361                    let other_selections = other.read(cx).selections.disjoint.to_vec();
 2362                    if other_selections.is_empty() {
 2363                        return;
 2364                    }
 2365                    this.selections.change_with(cx, |selections| {
 2366                        selections.select_anchors(other_selections);
 2367                    });
 2368                }
 2369                _ => {}
 2370            });
 2371
 2372        let this_subscription =
 2373            cx.subscribe_self::<EditorEvent>(move |this, this_evt, cx| match this_evt {
 2374                EditorEvent::SelectionsChanged { local: true } => {
 2375                    let these_selections = this.selections.disjoint.to_vec();
 2376                    if these_selections.is_empty() {
 2377                        return;
 2378                    }
 2379                    other.update(cx, |other_editor, cx| {
 2380                        other_editor.selections.change_with(cx, |selections| {
 2381                            selections.select_anchors(these_selections);
 2382                        })
 2383                    });
 2384                }
 2385                _ => {}
 2386            });
 2387
 2388        Subscription::join(other_subscription, this_subscription)
 2389    }
 2390
 2391    pub fn change_selections<R>(
 2392        &mut self,
 2393        autoscroll: Option<Autoscroll>,
 2394        window: &mut Window,
 2395        cx: &mut Context<Self>,
 2396        change: impl FnOnce(&mut MutableSelectionsCollection<'_>) -> R,
 2397    ) -> R {
 2398        self.change_selections_inner(autoscroll, true, window, cx, change)
 2399    }
 2400
 2401    fn change_selections_inner<R>(
 2402        &mut self,
 2403        autoscroll: Option<Autoscroll>,
 2404        request_completions: bool,
 2405        window: &mut Window,
 2406        cx: &mut Context<Self>,
 2407        change: impl FnOnce(&mut MutableSelectionsCollection<'_>) -> R,
 2408    ) -> R {
 2409        let old_cursor_position = self.selections.newest_anchor().head();
 2410        self.push_to_selection_history();
 2411
 2412        let (changed, result) = self.selections.change_with(cx, change);
 2413
 2414        if changed {
 2415            if let Some(autoscroll) = autoscroll {
 2416                self.request_autoscroll(autoscroll, cx);
 2417            }
 2418            self.selections_did_change(true, &old_cursor_position, request_completions, window, cx);
 2419
 2420            if self.should_open_signature_help_automatically(
 2421                &old_cursor_position,
 2422                self.signature_help_state.backspace_pressed(),
 2423                cx,
 2424            ) {
 2425                self.show_signature_help(&ShowSignatureHelp, window, cx);
 2426            }
 2427            self.signature_help_state.set_backspace_pressed(false);
 2428        }
 2429
 2430        result
 2431    }
 2432
 2433    pub fn edit<I, S, T>(&mut self, edits: I, cx: &mut Context<Self>)
 2434    where
 2435        I: IntoIterator<Item = (Range<S>, T)>,
 2436        S: ToOffset,
 2437        T: Into<Arc<str>>,
 2438    {
 2439        if self.read_only(cx) {
 2440            return;
 2441        }
 2442
 2443        self.buffer
 2444            .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
 2445    }
 2446
 2447    pub fn edit_with_autoindent<I, S, T>(&mut self, edits: I, cx: &mut Context<Self>)
 2448    where
 2449        I: IntoIterator<Item = (Range<S>, T)>,
 2450        S: ToOffset,
 2451        T: Into<Arc<str>>,
 2452    {
 2453        if self.read_only(cx) {
 2454            return;
 2455        }
 2456
 2457        self.buffer.update(cx, |buffer, cx| {
 2458            buffer.edit(edits, self.autoindent_mode.clone(), cx)
 2459        });
 2460    }
 2461
 2462    pub fn edit_with_block_indent<I, S, T>(
 2463        &mut self,
 2464        edits: I,
 2465        original_indent_columns: Vec<Option<u32>>,
 2466        cx: &mut Context<Self>,
 2467    ) where
 2468        I: IntoIterator<Item = (Range<S>, T)>,
 2469        S: ToOffset,
 2470        T: Into<Arc<str>>,
 2471    {
 2472        if self.read_only(cx) {
 2473            return;
 2474        }
 2475
 2476        self.buffer.update(cx, |buffer, cx| {
 2477            buffer.edit(
 2478                edits,
 2479                Some(AutoindentMode::Block {
 2480                    original_indent_columns,
 2481                }),
 2482                cx,
 2483            )
 2484        });
 2485    }
 2486
 2487    fn select(&mut self, phase: SelectPhase, window: &mut Window, cx: &mut Context<Self>) {
 2488        self.hide_context_menu(window, cx);
 2489
 2490        match phase {
 2491            SelectPhase::Begin {
 2492                position,
 2493                add,
 2494                click_count,
 2495            } => self.begin_selection(position, add, click_count, window, cx),
 2496            SelectPhase::BeginColumnar {
 2497                position,
 2498                goal_column,
 2499                reset,
 2500            } => self.begin_columnar_selection(position, goal_column, reset, window, cx),
 2501            SelectPhase::Extend {
 2502                position,
 2503                click_count,
 2504            } => self.extend_selection(position, click_count, window, cx),
 2505            SelectPhase::Update {
 2506                position,
 2507                goal_column,
 2508                scroll_delta,
 2509            } => self.update_selection(position, goal_column, scroll_delta, window, cx),
 2510            SelectPhase::End => self.end_selection(window, cx),
 2511        }
 2512    }
 2513
 2514    fn extend_selection(
 2515        &mut self,
 2516        position: DisplayPoint,
 2517        click_count: usize,
 2518        window: &mut Window,
 2519        cx: &mut Context<Self>,
 2520    ) {
 2521        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 2522        let tail = self.selections.newest::<usize>(cx).tail();
 2523        self.begin_selection(position, false, click_count, window, cx);
 2524
 2525        let position = position.to_offset(&display_map, Bias::Left);
 2526        let tail_anchor = display_map.buffer_snapshot.anchor_before(tail);
 2527
 2528        let mut pending_selection = self
 2529            .selections
 2530            .pending_anchor()
 2531            .expect("extend_selection not called with pending selection");
 2532        if position >= tail {
 2533            pending_selection.start = tail_anchor;
 2534        } else {
 2535            pending_selection.end = tail_anchor;
 2536            pending_selection.reversed = true;
 2537        }
 2538
 2539        let mut pending_mode = self.selections.pending_mode().unwrap();
 2540        match &mut pending_mode {
 2541            SelectMode::Word(range) | SelectMode::Line(range) => *range = tail_anchor..tail_anchor,
 2542            _ => {}
 2543        }
 2544
 2545        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 2546            s.set_pending(pending_selection, pending_mode)
 2547        });
 2548    }
 2549
 2550    fn begin_selection(
 2551        &mut self,
 2552        position: DisplayPoint,
 2553        add: bool,
 2554        click_count: usize,
 2555        window: &mut Window,
 2556        cx: &mut Context<Self>,
 2557    ) {
 2558        if !self.focus_handle.is_focused(window) {
 2559            self.last_focused_descendant = None;
 2560            window.focus(&self.focus_handle);
 2561        }
 2562
 2563        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 2564        let buffer = &display_map.buffer_snapshot;
 2565        let newest_selection = self.selections.newest_anchor().clone();
 2566        let position = display_map.clip_point(position, Bias::Left);
 2567
 2568        let start;
 2569        let end;
 2570        let mode;
 2571        let mut auto_scroll;
 2572        match click_count {
 2573            1 => {
 2574                start = buffer.anchor_before(position.to_point(&display_map));
 2575                end = start;
 2576                mode = SelectMode::Character;
 2577                auto_scroll = true;
 2578            }
 2579            2 => {
 2580                let range = movement::surrounding_word(&display_map, position);
 2581                start = buffer.anchor_before(range.start.to_point(&display_map));
 2582                end = buffer.anchor_before(range.end.to_point(&display_map));
 2583                mode = SelectMode::Word(start..end);
 2584                auto_scroll = true;
 2585            }
 2586            3 => {
 2587                let position = display_map
 2588                    .clip_point(position, Bias::Left)
 2589                    .to_point(&display_map);
 2590                let line_start = display_map.prev_line_boundary(position).0;
 2591                let next_line_start = buffer.clip_point(
 2592                    display_map.next_line_boundary(position).0 + Point::new(1, 0),
 2593                    Bias::Left,
 2594                );
 2595                start = buffer.anchor_before(line_start);
 2596                end = buffer.anchor_before(next_line_start);
 2597                mode = SelectMode::Line(start..end);
 2598                auto_scroll = true;
 2599            }
 2600            _ => {
 2601                start = buffer.anchor_before(0);
 2602                end = buffer.anchor_before(buffer.len());
 2603                mode = SelectMode::All;
 2604                auto_scroll = false;
 2605            }
 2606        }
 2607        auto_scroll &= EditorSettings::get_global(cx).autoscroll_on_clicks;
 2608
 2609        let point_to_delete: Option<usize> = {
 2610            let selected_points: Vec<Selection<Point>> =
 2611                self.selections.disjoint_in_range(start..end, cx);
 2612
 2613            if !add || click_count > 1 {
 2614                None
 2615            } else if !selected_points.is_empty() {
 2616                Some(selected_points[0].id)
 2617            } else {
 2618                let clicked_point_already_selected =
 2619                    self.selections.disjoint.iter().find(|selection| {
 2620                        selection.start.to_point(buffer) == start.to_point(buffer)
 2621                            || selection.end.to_point(buffer) == end.to_point(buffer)
 2622                    });
 2623
 2624                clicked_point_already_selected.map(|selection| selection.id)
 2625            }
 2626        };
 2627
 2628        let selections_count = self.selections.count();
 2629
 2630        self.change_selections(auto_scroll.then(Autoscroll::newest), window, cx, |s| {
 2631            if let Some(point_to_delete) = point_to_delete {
 2632                s.delete(point_to_delete);
 2633
 2634                if selections_count == 1 {
 2635                    s.set_pending_anchor_range(start..end, mode);
 2636                }
 2637            } else {
 2638                if !add {
 2639                    s.clear_disjoint();
 2640                } else if click_count > 1 {
 2641                    s.delete(newest_selection.id)
 2642                }
 2643
 2644                s.set_pending_anchor_range(start..end, mode);
 2645            }
 2646        });
 2647    }
 2648
 2649    fn begin_columnar_selection(
 2650        &mut self,
 2651        position: DisplayPoint,
 2652        goal_column: u32,
 2653        reset: bool,
 2654        window: &mut Window,
 2655        cx: &mut Context<Self>,
 2656    ) {
 2657        if !self.focus_handle.is_focused(window) {
 2658            self.last_focused_descendant = None;
 2659            window.focus(&self.focus_handle);
 2660        }
 2661
 2662        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 2663
 2664        if reset {
 2665            let pointer_position = display_map
 2666                .buffer_snapshot
 2667                .anchor_before(position.to_point(&display_map));
 2668
 2669            self.change_selections(Some(Autoscroll::newest()), window, cx, |s| {
 2670                s.clear_disjoint();
 2671                s.set_pending_anchor_range(
 2672                    pointer_position..pointer_position,
 2673                    SelectMode::Character,
 2674                );
 2675            });
 2676        }
 2677
 2678        let tail = self.selections.newest::<Point>(cx).tail();
 2679        self.columnar_selection_tail = Some(display_map.buffer_snapshot.anchor_before(tail));
 2680
 2681        if !reset {
 2682            self.select_columns(
 2683                tail.to_display_point(&display_map),
 2684                position,
 2685                goal_column,
 2686                &display_map,
 2687                window,
 2688                cx,
 2689            );
 2690        }
 2691    }
 2692
 2693    fn update_selection(
 2694        &mut self,
 2695        position: DisplayPoint,
 2696        goal_column: u32,
 2697        scroll_delta: gpui::Point<f32>,
 2698        window: &mut Window,
 2699        cx: &mut Context<Self>,
 2700    ) {
 2701        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 2702
 2703        if let Some(tail) = self.columnar_selection_tail.as_ref() {
 2704            let tail = tail.to_display_point(&display_map);
 2705            self.select_columns(tail, position, goal_column, &display_map, window, cx);
 2706        } else if let Some(mut pending) = self.selections.pending_anchor() {
 2707            let buffer = self.buffer.read(cx).snapshot(cx);
 2708            let head;
 2709            let tail;
 2710            let mode = self.selections.pending_mode().unwrap();
 2711            match &mode {
 2712                SelectMode::Character => {
 2713                    head = position.to_point(&display_map);
 2714                    tail = pending.tail().to_point(&buffer);
 2715                }
 2716                SelectMode::Word(original_range) => {
 2717                    let original_display_range = original_range.start.to_display_point(&display_map)
 2718                        ..original_range.end.to_display_point(&display_map);
 2719                    let original_buffer_range = original_display_range.start.to_point(&display_map)
 2720                        ..original_display_range.end.to_point(&display_map);
 2721                    if movement::is_inside_word(&display_map, position)
 2722                        || original_display_range.contains(&position)
 2723                    {
 2724                        let word_range = movement::surrounding_word(&display_map, position);
 2725                        if word_range.start < original_display_range.start {
 2726                            head = word_range.start.to_point(&display_map);
 2727                        } else {
 2728                            head = word_range.end.to_point(&display_map);
 2729                        }
 2730                    } else {
 2731                        head = position.to_point(&display_map);
 2732                    }
 2733
 2734                    if head <= original_buffer_range.start {
 2735                        tail = original_buffer_range.end;
 2736                    } else {
 2737                        tail = original_buffer_range.start;
 2738                    }
 2739                }
 2740                SelectMode::Line(original_range) => {
 2741                    let original_range = original_range.to_point(&display_map.buffer_snapshot);
 2742
 2743                    let position = display_map
 2744                        .clip_point(position, Bias::Left)
 2745                        .to_point(&display_map);
 2746                    let line_start = display_map.prev_line_boundary(position).0;
 2747                    let next_line_start = buffer.clip_point(
 2748                        display_map.next_line_boundary(position).0 + Point::new(1, 0),
 2749                        Bias::Left,
 2750                    );
 2751
 2752                    if line_start < original_range.start {
 2753                        head = line_start
 2754                    } else {
 2755                        head = next_line_start
 2756                    }
 2757
 2758                    if head <= original_range.start {
 2759                        tail = original_range.end;
 2760                    } else {
 2761                        tail = original_range.start;
 2762                    }
 2763                }
 2764                SelectMode::All => {
 2765                    return;
 2766                }
 2767            };
 2768
 2769            if head < tail {
 2770                pending.start = buffer.anchor_before(head);
 2771                pending.end = buffer.anchor_before(tail);
 2772                pending.reversed = true;
 2773            } else {
 2774                pending.start = buffer.anchor_before(tail);
 2775                pending.end = buffer.anchor_before(head);
 2776                pending.reversed = false;
 2777            }
 2778
 2779            self.change_selections(None, window, cx, |s| {
 2780                s.set_pending(pending, mode);
 2781            });
 2782        } else {
 2783            log::error!("update_selection dispatched with no pending selection");
 2784            return;
 2785        }
 2786
 2787        self.apply_scroll_delta(scroll_delta, window, cx);
 2788        cx.notify();
 2789    }
 2790
 2791    fn end_selection(&mut self, window: &mut Window, cx: &mut Context<Self>) {
 2792        self.columnar_selection_tail.take();
 2793        if self.selections.pending_anchor().is_some() {
 2794            let selections = self.selections.all::<usize>(cx);
 2795            self.change_selections(None, window, cx, |s| {
 2796                s.select(selections);
 2797                s.clear_pending();
 2798            });
 2799        }
 2800    }
 2801
 2802    fn select_columns(
 2803        &mut self,
 2804        tail: DisplayPoint,
 2805        head: DisplayPoint,
 2806        goal_column: u32,
 2807        display_map: &DisplaySnapshot,
 2808        window: &mut Window,
 2809        cx: &mut Context<Self>,
 2810    ) {
 2811        let start_row = cmp::min(tail.row(), head.row());
 2812        let end_row = cmp::max(tail.row(), head.row());
 2813        let start_column = cmp::min(tail.column(), goal_column);
 2814        let end_column = cmp::max(tail.column(), goal_column);
 2815        let reversed = start_column < tail.column();
 2816
 2817        let selection_ranges = (start_row.0..=end_row.0)
 2818            .map(DisplayRow)
 2819            .filter_map(|row| {
 2820                if start_column <= display_map.line_len(row) && !display_map.is_block_line(row) {
 2821                    let start = display_map
 2822                        .clip_point(DisplayPoint::new(row, start_column), Bias::Left)
 2823                        .to_point(display_map);
 2824                    let end = display_map
 2825                        .clip_point(DisplayPoint::new(row, end_column), Bias::Right)
 2826                        .to_point(display_map);
 2827                    if reversed {
 2828                        Some(end..start)
 2829                    } else {
 2830                        Some(start..end)
 2831                    }
 2832                } else {
 2833                    None
 2834                }
 2835            })
 2836            .collect::<Vec<_>>();
 2837
 2838        self.change_selections(None, window, cx, |s| {
 2839            s.select_ranges(selection_ranges);
 2840        });
 2841        cx.notify();
 2842    }
 2843
 2844    pub fn has_pending_nonempty_selection(&self) -> bool {
 2845        let pending_nonempty_selection = match self.selections.pending_anchor() {
 2846            Some(Selection { start, end, .. }) => start != end,
 2847            None => false,
 2848        };
 2849
 2850        pending_nonempty_selection
 2851            || (self.columnar_selection_tail.is_some() && self.selections.disjoint.len() > 1)
 2852    }
 2853
 2854    pub fn has_pending_selection(&self) -> bool {
 2855        self.selections.pending_anchor().is_some() || self.columnar_selection_tail.is_some()
 2856    }
 2857
 2858    pub fn cancel(&mut self, _: &Cancel, window: &mut Window, cx: &mut Context<Self>) {
 2859        self.selection_mark_mode = false;
 2860
 2861        if self.clear_expanded_diff_hunks(cx) {
 2862            cx.notify();
 2863            return;
 2864        }
 2865        if self.dismiss_menus_and_popups(true, window, cx) {
 2866            return;
 2867        }
 2868
 2869        if self.mode == EditorMode::Full
 2870            && self.change_selections(Some(Autoscroll::fit()), window, cx, |s| s.try_cancel())
 2871        {
 2872            return;
 2873        }
 2874
 2875        cx.propagate();
 2876    }
 2877
 2878    pub fn dismiss_menus_and_popups(
 2879        &mut self,
 2880        is_user_requested: bool,
 2881        window: &mut Window,
 2882        cx: &mut Context<Self>,
 2883    ) -> bool {
 2884        if self.take_rename(false, window, cx).is_some() {
 2885            return true;
 2886        }
 2887
 2888        if hide_hover(self, cx) {
 2889            return true;
 2890        }
 2891
 2892        if self.hide_signature_help(cx, SignatureHelpHiddenBy::Escape) {
 2893            return true;
 2894        }
 2895
 2896        if self.hide_context_menu(window, cx).is_some() {
 2897            return true;
 2898        }
 2899
 2900        if self.mouse_context_menu.take().is_some() {
 2901            return true;
 2902        }
 2903
 2904        if is_user_requested && self.discard_inline_completion(true, cx) {
 2905            return true;
 2906        }
 2907
 2908        if self.snippet_stack.pop().is_some() {
 2909            return true;
 2910        }
 2911
 2912        if self.mode == EditorMode::Full && self.active_diagnostics.is_some() {
 2913            self.dismiss_diagnostics(cx);
 2914            return true;
 2915        }
 2916
 2917        false
 2918    }
 2919
 2920    fn linked_editing_ranges_for(
 2921        &self,
 2922        selection: Range<text::Anchor>,
 2923        cx: &App,
 2924    ) -> Option<HashMap<Entity<Buffer>, Vec<Range<text::Anchor>>>> {
 2925        if self.linked_edit_ranges.is_empty() {
 2926            return None;
 2927        }
 2928        let ((base_range, linked_ranges), buffer_snapshot, buffer) =
 2929            selection.end.buffer_id.and_then(|end_buffer_id| {
 2930                if selection.start.buffer_id != Some(end_buffer_id) {
 2931                    return None;
 2932                }
 2933                let buffer = self.buffer.read(cx).buffer(end_buffer_id)?;
 2934                let snapshot = buffer.read(cx).snapshot();
 2935                self.linked_edit_ranges
 2936                    .get(end_buffer_id, selection.start..selection.end, &snapshot)
 2937                    .map(|ranges| (ranges, snapshot, buffer))
 2938            })?;
 2939        use text::ToOffset as TO;
 2940        // find offset from the start of current range to current cursor position
 2941        let start_byte_offset = TO::to_offset(&base_range.start, &buffer_snapshot);
 2942
 2943        let start_offset = TO::to_offset(&selection.start, &buffer_snapshot);
 2944        let start_difference = start_offset - start_byte_offset;
 2945        let end_offset = TO::to_offset(&selection.end, &buffer_snapshot);
 2946        let end_difference = end_offset - start_byte_offset;
 2947        // Current range has associated linked ranges.
 2948        let mut linked_edits = HashMap::<_, Vec<_>>::default();
 2949        for range in linked_ranges.iter() {
 2950            let start_offset = TO::to_offset(&range.start, &buffer_snapshot);
 2951            let end_offset = start_offset + end_difference;
 2952            let start_offset = start_offset + start_difference;
 2953            if start_offset > buffer_snapshot.len() || end_offset > buffer_snapshot.len() {
 2954                continue;
 2955            }
 2956            if self.selections.disjoint_anchor_ranges().any(|s| {
 2957                if s.start.buffer_id != selection.start.buffer_id
 2958                    || s.end.buffer_id != selection.end.buffer_id
 2959                {
 2960                    return false;
 2961                }
 2962                TO::to_offset(&s.start.text_anchor, &buffer_snapshot) <= end_offset
 2963                    && TO::to_offset(&s.end.text_anchor, &buffer_snapshot) >= start_offset
 2964            }) {
 2965                continue;
 2966            }
 2967            let start = buffer_snapshot.anchor_after(start_offset);
 2968            let end = buffer_snapshot.anchor_after(end_offset);
 2969            linked_edits
 2970                .entry(buffer.clone())
 2971                .or_default()
 2972                .push(start..end);
 2973        }
 2974        Some(linked_edits)
 2975    }
 2976
 2977    pub fn handle_input(&mut self, text: &str, window: &mut Window, cx: &mut Context<Self>) {
 2978        let text: Arc<str> = text.into();
 2979
 2980        if self.read_only(cx) {
 2981            return;
 2982        }
 2983
 2984        let selections = self.selections.all_adjusted(cx);
 2985        let mut bracket_inserted = false;
 2986        let mut edits = Vec::new();
 2987        let mut linked_edits = HashMap::<_, Vec<_>>::default();
 2988        let mut new_selections = Vec::with_capacity(selections.len());
 2989        let mut new_autoclose_regions = Vec::new();
 2990        let snapshot = self.buffer.read(cx).read(cx);
 2991
 2992        for (selection, autoclose_region) in
 2993            self.selections_with_autoclose_regions(selections, &snapshot)
 2994        {
 2995            if let Some(scope) = snapshot.language_scope_at(selection.head()) {
 2996                // Determine if the inserted text matches the opening or closing
 2997                // bracket of any of this language's bracket pairs.
 2998                let mut bracket_pair = None;
 2999                let mut is_bracket_pair_start = false;
 3000                let mut is_bracket_pair_end = false;
 3001                if !text.is_empty() {
 3002                    // `text` can be empty when a user is using IME (e.g. Chinese Wubi Simplified)
 3003                    //  and they are removing the character that triggered IME popup.
 3004                    for (pair, enabled) in scope.brackets() {
 3005                        if !pair.close && !pair.surround {
 3006                            continue;
 3007                        }
 3008
 3009                        if enabled && pair.start.ends_with(text.as_ref()) {
 3010                            let prefix_len = pair.start.len() - text.len();
 3011                            let preceding_text_matches_prefix = prefix_len == 0
 3012                                || (selection.start.column >= (prefix_len as u32)
 3013                                    && snapshot.contains_str_at(
 3014                                        Point::new(
 3015                                            selection.start.row,
 3016                                            selection.start.column - (prefix_len as u32),
 3017                                        ),
 3018                                        &pair.start[..prefix_len],
 3019                                    ));
 3020                            if preceding_text_matches_prefix {
 3021                                bracket_pair = Some(pair.clone());
 3022                                is_bracket_pair_start = true;
 3023                                break;
 3024                            }
 3025                        }
 3026                        if pair.end.as_str() == text.as_ref() {
 3027                            bracket_pair = Some(pair.clone());
 3028                            is_bracket_pair_end = true;
 3029                            break;
 3030                        }
 3031                    }
 3032                }
 3033
 3034                if let Some(bracket_pair) = bracket_pair {
 3035                    let snapshot_settings = snapshot.language_settings_at(selection.start, cx);
 3036                    let autoclose = self.use_autoclose && snapshot_settings.use_autoclose;
 3037                    let auto_surround =
 3038                        self.use_auto_surround && snapshot_settings.use_auto_surround;
 3039                    if selection.is_empty() {
 3040                        if is_bracket_pair_start {
 3041                            // If the inserted text is a suffix of an opening bracket and the
 3042                            // selection is preceded by the rest of the opening bracket, then
 3043                            // insert the closing bracket.
 3044                            let following_text_allows_autoclose = snapshot
 3045                                .chars_at(selection.start)
 3046                                .next()
 3047                                .map_or(true, |c| scope.should_autoclose_before(c));
 3048
 3049                            let preceding_text_allows_autoclose = selection.start.column == 0
 3050                                || snapshot.reversed_chars_at(selection.start).next().map_or(
 3051                                    true,
 3052                                    |c| {
 3053                                        bracket_pair.start != bracket_pair.end
 3054                                            || !snapshot
 3055                                                .char_classifier_at(selection.start)
 3056                                                .is_word(c)
 3057                                    },
 3058                                );
 3059
 3060                            let is_closing_quote = if bracket_pair.end == bracket_pair.start
 3061                                && bracket_pair.start.len() == 1
 3062                            {
 3063                                let target = bracket_pair.start.chars().next().unwrap();
 3064                                let current_line_count = snapshot
 3065                                    .reversed_chars_at(selection.start)
 3066                                    .take_while(|&c| c != '\n')
 3067                                    .filter(|&c| c == target)
 3068                                    .count();
 3069                                current_line_count % 2 == 1
 3070                            } else {
 3071                                false
 3072                            };
 3073
 3074                            if autoclose
 3075                                && bracket_pair.close
 3076                                && following_text_allows_autoclose
 3077                                && preceding_text_allows_autoclose
 3078                                && !is_closing_quote
 3079                            {
 3080                                let anchor = snapshot.anchor_before(selection.end);
 3081                                new_selections.push((selection.map(|_| anchor), text.len()));
 3082                                new_autoclose_regions.push((
 3083                                    anchor,
 3084                                    text.len(),
 3085                                    selection.id,
 3086                                    bracket_pair.clone(),
 3087                                ));
 3088                                edits.push((
 3089                                    selection.range(),
 3090                                    format!("{}{}", text, bracket_pair.end).into(),
 3091                                ));
 3092                                bracket_inserted = true;
 3093                                continue;
 3094                            }
 3095                        }
 3096
 3097                        if let Some(region) = autoclose_region {
 3098                            // If the selection is followed by an auto-inserted closing bracket,
 3099                            // then don't insert that closing bracket again; just move the selection
 3100                            // past the closing bracket.
 3101                            let should_skip = selection.end == region.range.end.to_point(&snapshot)
 3102                                && text.as_ref() == region.pair.end.as_str();
 3103                            if should_skip {
 3104                                let anchor = snapshot.anchor_after(selection.end);
 3105                                new_selections
 3106                                    .push((selection.map(|_| anchor), region.pair.end.len()));
 3107                                continue;
 3108                            }
 3109                        }
 3110
 3111                        let always_treat_brackets_as_autoclosed = snapshot
 3112                            .language_settings_at(selection.start, cx)
 3113                            .always_treat_brackets_as_autoclosed;
 3114                        if always_treat_brackets_as_autoclosed
 3115                            && is_bracket_pair_end
 3116                            && snapshot.contains_str_at(selection.end, text.as_ref())
 3117                        {
 3118                            // Otherwise, when `always_treat_brackets_as_autoclosed` is set to `true
 3119                            // and the inserted text is a closing bracket and the selection is followed
 3120                            // by the closing bracket then move the selection past the closing bracket.
 3121                            let anchor = snapshot.anchor_after(selection.end);
 3122                            new_selections.push((selection.map(|_| anchor), text.len()));
 3123                            continue;
 3124                        }
 3125                    }
 3126                    // If an opening bracket is 1 character long and is typed while
 3127                    // text is selected, then surround that text with the bracket pair.
 3128                    else if auto_surround
 3129                        && bracket_pair.surround
 3130                        && is_bracket_pair_start
 3131                        && bracket_pair.start.chars().count() == 1
 3132                    {
 3133                        edits.push((selection.start..selection.start, text.clone()));
 3134                        edits.push((
 3135                            selection.end..selection.end,
 3136                            bracket_pair.end.as_str().into(),
 3137                        ));
 3138                        bracket_inserted = true;
 3139                        new_selections.push((
 3140                            Selection {
 3141                                id: selection.id,
 3142                                start: snapshot.anchor_after(selection.start),
 3143                                end: snapshot.anchor_before(selection.end),
 3144                                reversed: selection.reversed,
 3145                                goal: selection.goal,
 3146                            },
 3147                            0,
 3148                        ));
 3149                        continue;
 3150                    }
 3151                }
 3152            }
 3153
 3154            if self.auto_replace_emoji_shortcode
 3155                && selection.is_empty()
 3156                && text.as_ref().ends_with(':')
 3157            {
 3158                if let Some(possible_emoji_short_code) =
 3159                    Self::find_possible_emoji_shortcode_at_position(&snapshot, selection.start)
 3160                {
 3161                    if !possible_emoji_short_code.is_empty() {
 3162                        if let Some(emoji) = emojis::get_by_shortcode(&possible_emoji_short_code) {
 3163                            let emoji_shortcode_start = Point::new(
 3164                                selection.start.row,
 3165                                selection.start.column - possible_emoji_short_code.len() as u32 - 1,
 3166                            );
 3167
 3168                            // Remove shortcode from buffer
 3169                            edits.push((
 3170                                emoji_shortcode_start..selection.start,
 3171                                "".to_string().into(),
 3172                            ));
 3173                            new_selections.push((
 3174                                Selection {
 3175                                    id: selection.id,
 3176                                    start: snapshot.anchor_after(emoji_shortcode_start),
 3177                                    end: snapshot.anchor_before(selection.start),
 3178                                    reversed: selection.reversed,
 3179                                    goal: selection.goal,
 3180                                },
 3181                                0,
 3182                            ));
 3183
 3184                            // Insert emoji
 3185                            let selection_start_anchor = snapshot.anchor_after(selection.start);
 3186                            new_selections.push((selection.map(|_| selection_start_anchor), 0));
 3187                            edits.push((selection.start..selection.end, emoji.to_string().into()));
 3188
 3189                            continue;
 3190                        }
 3191                    }
 3192                }
 3193            }
 3194
 3195            // If not handling any auto-close operation, then just replace the selected
 3196            // text with the given input and move the selection to the end of the
 3197            // newly inserted text.
 3198            let anchor = snapshot.anchor_after(selection.end);
 3199            if !self.linked_edit_ranges.is_empty() {
 3200                let start_anchor = snapshot.anchor_before(selection.start);
 3201
 3202                let is_word_char = text.chars().next().map_or(true, |char| {
 3203                    let classifier = snapshot.char_classifier_at(start_anchor.to_offset(&snapshot));
 3204                    classifier.is_word(char)
 3205                });
 3206
 3207                if is_word_char {
 3208                    if let Some(ranges) = self
 3209                        .linked_editing_ranges_for(start_anchor.text_anchor..anchor.text_anchor, cx)
 3210                    {
 3211                        for (buffer, edits) in ranges {
 3212                            linked_edits
 3213                                .entry(buffer.clone())
 3214                                .or_default()
 3215                                .extend(edits.into_iter().map(|range| (range, text.clone())));
 3216                        }
 3217                    }
 3218                }
 3219            }
 3220
 3221            new_selections.push((selection.map(|_| anchor), 0));
 3222            edits.push((selection.start..selection.end, text.clone()));
 3223        }
 3224
 3225        drop(snapshot);
 3226
 3227        self.transact(window, cx, |this, window, cx| {
 3228            let initial_buffer_versions =
 3229                jsx_tag_auto_close::construct_initial_buffer_versions_map(this, &edits, cx);
 3230
 3231            this.buffer.update(cx, |buffer, cx| {
 3232                buffer.edit(edits, this.autoindent_mode.clone(), cx);
 3233            });
 3234            for (buffer, edits) in linked_edits {
 3235                buffer.update(cx, |buffer, cx| {
 3236                    let snapshot = buffer.snapshot();
 3237                    let edits = edits
 3238                        .into_iter()
 3239                        .map(|(range, text)| {
 3240                            use text::ToPoint as TP;
 3241                            let end_point = TP::to_point(&range.end, &snapshot);
 3242                            let start_point = TP::to_point(&range.start, &snapshot);
 3243                            (start_point..end_point, text)
 3244                        })
 3245                        .sorted_by_key(|(range, _)| range.start)
 3246                        .collect::<Vec<_>>();
 3247                    buffer.edit(edits, None, cx);
 3248                })
 3249            }
 3250            let new_anchor_selections = new_selections.iter().map(|e| &e.0);
 3251            let new_selection_deltas = new_selections.iter().map(|e| e.1);
 3252            let map = this.display_map.update(cx, |map, cx| map.snapshot(cx));
 3253            let new_selections = resolve_selections::<usize, _>(new_anchor_selections, &map)
 3254                .zip(new_selection_deltas)
 3255                .map(|(selection, delta)| Selection {
 3256                    id: selection.id,
 3257                    start: selection.start + delta,
 3258                    end: selection.end + delta,
 3259                    reversed: selection.reversed,
 3260                    goal: SelectionGoal::None,
 3261                })
 3262                .collect::<Vec<_>>();
 3263
 3264            let mut i = 0;
 3265            for (position, delta, selection_id, pair) in new_autoclose_regions {
 3266                let position = position.to_offset(&map.buffer_snapshot) + delta;
 3267                let start = map.buffer_snapshot.anchor_before(position);
 3268                let end = map.buffer_snapshot.anchor_after(position);
 3269                while let Some(existing_state) = this.autoclose_regions.get(i) {
 3270                    match existing_state.range.start.cmp(&start, &map.buffer_snapshot) {
 3271                        Ordering::Less => i += 1,
 3272                        Ordering::Greater => break,
 3273                        Ordering::Equal => {
 3274                            match end.cmp(&existing_state.range.end, &map.buffer_snapshot) {
 3275                                Ordering::Less => i += 1,
 3276                                Ordering::Equal => break,
 3277                                Ordering::Greater => break,
 3278                            }
 3279                        }
 3280                    }
 3281                }
 3282                this.autoclose_regions.insert(
 3283                    i,
 3284                    AutocloseRegion {
 3285                        selection_id,
 3286                        range: start..end,
 3287                        pair,
 3288                    },
 3289                );
 3290            }
 3291
 3292            let had_active_inline_completion = this.has_active_inline_completion();
 3293            this.change_selections_inner(Some(Autoscroll::fit()), false, window, cx, |s| {
 3294                s.select(new_selections)
 3295            });
 3296
 3297            if !bracket_inserted {
 3298                if let Some(on_type_format_task) =
 3299                    this.trigger_on_type_formatting(text.to_string(), window, cx)
 3300                {
 3301                    on_type_format_task.detach_and_log_err(cx);
 3302                }
 3303            }
 3304
 3305            let editor_settings = EditorSettings::get_global(cx);
 3306            if bracket_inserted
 3307                && (editor_settings.auto_signature_help
 3308                    || editor_settings.show_signature_help_after_edits)
 3309            {
 3310                this.show_signature_help(&ShowSignatureHelp, window, cx);
 3311            }
 3312
 3313            let trigger_in_words =
 3314                this.show_edit_predictions_in_menu() || !had_active_inline_completion;
 3315            if this.hard_wrap.is_some() {
 3316                let latest: Range<Point> = this.selections.newest(cx).range();
 3317                if latest.is_empty()
 3318                    && this
 3319                        .buffer()
 3320                        .read(cx)
 3321                        .snapshot(cx)
 3322                        .line_len(MultiBufferRow(latest.start.row))
 3323                        == latest.start.column
 3324                {
 3325                    this.rewrap_impl(
 3326                        RewrapOptions {
 3327                            override_language_settings: true,
 3328                            preserve_existing_whitespace: true,
 3329                        },
 3330                        cx,
 3331                    )
 3332                }
 3333            }
 3334            this.trigger_completion_on_input(&text, trigger_in_words, window, cx);
 3335            linked_editing_ranges::refresh_linked_ranges(this, window, cx);
 3336            this.refresh_inline_completion(true, false, window, cx);
 3337            jsx_tag_auto_close::handle_from(this, initial_buffer_versions, window, cx);
 3338        });
 3339    }
 3340
 3341    fn find_possible_emoji_shortcode_at_position(
 3342        snapshot: &MultiBufferSnapshot,
 3343        position: Point,
 3344    ) -> Option<String> {
 3345        let mut chars = Vec::new();
 3346        let mut found_colon = false;
 3347        for char in snapshot.reversed_chars_at(position).take(100) {
 3348            // Found a possible emoji shortcode in the middle of the buffer
 3349            if found_colon {
 3350                if char.is_whitespace() {
 3351                    chars.reverse();
 3352                    return Some(chars.iter().collect());
 3353                }
 3354                // If the previous character is not a whitespace, we are in the middle of a word
 3355                // and we only want to complete the shortcode if the word is made up of other emojis
 3356                let mut containing_word = String::new();
 3357                for ch in snapshot
 3358                    .reversed_chars_at(position)
 3359                    .skip(chars.len() + 1)
 3360                    .take(100)
 3361                {
 3362                    if ch.is_whitespace() {
 3363                        break;
 3364                    }
 3365                    containing_word.push(ch);
 3366                }
 3367                let containing_word = containing_word.chars().rev().collect::<String>();
 3368                if util::word_consists_of_emojis(containing_word.as_str()) {
 3369                    chars.reverse();
 3370                    return Some(chars.iter().collect());
 3371                }
 3372            }
 3373
 3374            if char.is_whitespace() || !char.is_ascii() {
 3375                return None;
 3376            }
 3377            if char == ':' {
 3378                found_colon = true;
 3379            } else {
 3380                chars.push(char);
 3381            }
 3382        }
 3383        // Found a possible emoji shortcode at the beginning of the buffer
 3384        chars.reverse();
 3385        Some(chars.iter().collect())
 3386    }
 3387
 3388    pub fn newline(&mut self, _: &Newline, window: &mut Window, cx: &mut Context<Self>) {
 3389        self.transact(window, cx, |this, window, cx| {
 3390            let (edits, selection_fixup_info): (Vec<_>, Vec<_>) = {
 3391                let selections = this.selections.all::<usize>(cx);
 3392                let multi_buffer = this.buffer.read(cx);
 3393                let buffer = multi_buffer.snapshot(cx);
 3394                selections
 3395                    .iter()
 3396                    .map(|selection| {
 3397                        let start_point = selection.start.to_point(&buffer);
 3398                        let mut indent =
 3399                            buffer.indent_size_for_line(MultiBufferRow(start_point.row));
 3400                        indent.len = cmp::min(indent.len, start_point.column);
 3401                        let start = selection.start;
 3402                        let end = selection.end;
 3403                        let selection_is_empty = start == end;
 3404                        let language_scope = buffer.language_scope_at(start);
 3405                        let (comment_delimiter, insert_extra_newline) = if let Some(language) =
 3406                            &language_scope
 3407                        {
 3408                            let insert_extra_newline =
 3409                                insert_extra_newline_brackets(&buffer, start..end, language)
 3410                                    || insert_extra_newline_tree_sitter(&buffer, start..end);
 3411
 3412                            // Comment extension on newline is allowed only for cursor selections
 3413                            let comment_delimiter = maybe!({
 3414                                if !selection_is_empty {
 3415                                    return None;
 3416                                }
 3417
 3418                                if !multi_buffer.language_settings(cx).extend_comment_on_newline {
 3419                                    return None;
 3420                                }
 3421
 3422                                let delimiters = language.line_comment_prefixes();
 3423                                let max_len_of_delimiter =
 3424                                    delimiters.iter().map(|delimiter| delimiter.len()).max()?;
 3425                                let (snapshot, range) =
 3426                                    buffer.buffer_line_for_row(MultiBufferRow(start_point.row))?;
 3427
 3428                                let mut index_of_first_non_whitespace = 0;
 3429                                let comment_candidate = snapshot
 3430                                    .chars_for_range(range)
 3431                                    .skip_while(|c| {
 3432                                        let should_skip = c.is_whitespace();
 3433                                        if should_skip {
 3434                                            index_of_first_non_whitespace += 1;
 3435                                        }
 3436                                        should_skip
 3437                                    })
 3438                                    .take(max_len_of_delimiter)
 3439                                    .collect::<String>();
 3440                                let comment_prefix = delimiters.iter().find(|comment_prefix| {
 3441                                    comment_candidate.starts_with(comment_prefix.as_ref())
 3442                                })?;
 3443                                let cursor_is_placed_after_comment_marker =
 3444                                    index_of_first_non_whitespace + comment_prefix.len()
 3445                                        <= start_point.column as usize;
 3446                                if cursor_is_placed_after_comment_marker {
 3447                                    Some(comment_prefix.clone())
 3448                                } else {
 3449                                    None
 3450                                }
 3451                            });
 3452                            (comment_delimiter, insert_extra_newline)
 3453                        } else {
 3454                            (None, false)
 3455                        };
 3456
 3457                        let capacity_for_delimiter = comment_delimiter
 3458                            .as_deref()
 3459                            .map(str::len)
 3460                            .unwrap_or_default();
 3461                        let mut new_text =
 3462                            String::with_capacity(1 + capacity_for_delimiter + indent.len as usize);
 3463                        new_text.push('\n');
 3464                        new_text.extend(indent.chars());
 3465                        if let Some(delimiter) = &comment_delimiter {
 3466                            new_text.push_str(delimiter);
 3467                        }
 3468                        if insert_extra_newline {
 3469                            new_text = new_text.repeat(2);
 3470                        }
 3471
 3472                        let anchor = buffer.anchor_after(end);
 3473                        let new_selection = selection.map(|_| anchor);
 3474                        (
 3475                            (start..end, new_text),
 3476                            (insert_extra_newline, new_selection),
 3477                        )
 3478                    })
 3479                    .unzip()
 3480            };
 3481
 3482            this.edit_with_autoindent(edits, cx);
 3483            let buffer = this.buffer.read(cx).snapshot(cx);
 3484            let new_selections = selection_fixup_info
 3485                .into_iter()
 3486                .map(|(extra_newline_inserted, new_selection)| {
 3487                    let mut cursor = new_selection.end.to_point(&buffer);
 3488                    if extra_newline_inserted {
 3489                        cursor.row -= 1;
 3490                        cursor.column = buffer.line_len(MultiBufferRow(cursor.row));
 3491                    }
 3492                    new_selection.map(|_| cursor)
 3493                })
 3494                .collect();
 3495
 3496            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 3497                s.select(new_selections)
 3498            });
 3499            this.refresh_inline_completion(true, false, window, cx);
 3500        });
 3501    }
 3502
 3503    pub fn newline_above(&mut self, _: &NewlineAbove, window: &mut Window, cx: &mut Context<Self>) {
 3504        let buffer = self.buffer.read(cx);
 3505        let snapshot = buffer.snapshot(cx);
 3506
 3507        let mut edits = Vec::new();
 3508        let mut rows = Vec::new();
 3509
 3510        for (rows_inserted, selection) in self.selections.all_adjusted(cx).into_iter().enumerate() {
 3511            let cursor = selection.head();
 3512            let row = cursor.row;
 3513
 3514            let start_of_line = snapshot.clip_point(Point::new(row, 0), Bias::Left);
 3515
 3516            let newline = "\n".to_string();
 3517            edits.push((start_of_line..start_of_line, newline));
 3518
 3519            rows.push(row + rows_inserted as u32);
 3520        }
 3521
 3522        self.transact(window, cx, |editor, window, cx| {
 3523            editor.edit(edits, cx);
 3524
 3525            editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 3526                let mut index = 0;
 3527                s.move_cursors_with(|map, _, _| {
 3528                    let row = rows[index];
 3529                    index += 1;
 3530
 3531                    let point = Point::new(row, 0);
 3532                    let boundary = map.next_line_boundary(point).1;
 3533                    let clipped = map.clip_point(boundary, Bias::Left);
 3534
 3535                    (clipped, SelectionGoal::None)
 3536                });
 3537            });
 3538
 3539            let mut indent_edits = Vec::new();
 3540            let multibuffer_snapshot = editor.buffer.read(cx).snapshot(cx);
 3541            for row in rows {
 3542                let indents = multibuffer_snapshot.suggested_indents(row..row + 1, cx);
 3543                for (row, indent) in indents {
 3544                    if indent.len == 0 {
 3545                        continue;
 3546                    }
 3547
 3548                    let text = match indent.kind {
 3549                        IndentKind::Space => " ".repeat(indent.len as usize),
 3550                        IndentKind::Tab => "\t".repeat(indent.len as usize),
 3551                    };
 3552                    let point = Point::new(row.0, 0);
 3553                    indent_edits.push((point..point, text));
 3554                }
 3555            }
 3556            editor.edit(indent_edits, cx);
 3557        });
 3558    }
 3559
 3560    pub fn newline_below(&mut self, _: &NewlineBelow, window: &mut Window, cx: &mut Context<Self>) {
 3561        let buffer = self.buffer.read(cx);
 3562        let snapshot = buffer.snapshot(cx);
 3563
 3564        let mut edits = Vec::new();
 3565        let mut rows = Vec::new();
 3566        let mut rows_inserted = 0;
 3567
 3568        for selection in self.selections.all_adjusted(cx) {
 3569            let cursor = selection.head();
 3570            let row = cursor.row;
 3571
 3572            let point = Point::new(row + 1, 0);
 3573            let start_of_line = snapshot.clip_point(point, Bias::Left);
 3574
 3575            let newline = "\n".to_string();
 3576            edits.push((start_of_line..start_of_line, newline));
 3577
 3578            rows_inserted += 1;
 3579            rows.push(row + rows_inserted);
 3580        }
 3581
 3582        self.transact(window, cx, |editor, window, cx| {
 3583            editor.edit(edits, cx);
 3584
 3585            editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 3586                let mut index = 0;
 3587                s.move_cursors_with(|map, _, _| {
 3588                    let row = rows[index];
 3589                    index += 1;
 3590
 3591                    let point = Point::new(row, 0);
 3592                    let boundary = map.next_line_boundary(point).1;
 3593                    let clipped = map.clip_point(boundary, Bias::Left);
 3594
 3595                    (clipped, SelectionGoal::None)
 3596                });
 3597            });
 3598
 3599            let mut indent_edits = Vec::new();
 3600            let multibuffer_snapshot = editor.buffer.read(cx).snapshot(cx);
 3601            for row in rows {
 3602                let indents = multibuffer_snapshot.suggested_indents(row..row + 1, cx);
 3603                for (row, indent) in indents {
 3604                    if indent.len == 0 {
 3605                        continue;
 3606                    }
 3607
 3608                    let text = match indent.kind {
 3609                        IndentKind::Space => " ".repeat(indent.len as usize),
 3610                        IndentKind::Tab => "\t".repeat(indent.len as usize),
 3611                    };
 3612                    let point = Point::new(row.0, 0);
 3613                    indent_edits.push((point..point, text));
 3614                }
 3615            }
 3616            editor.edit(indent_edits, cx);
 3617        });
 3618    }
 3619
 3620    pub fn insert(&mut self, text: &str, window: &mut Window, cx: &mut Context<Self>) {
 3621        let autoindent = text.is_empty().not().then(|| AutoindentMode::Block {
 3622            original_indent_columns: Vec::new(),
 3623        });
 3624        self.insert_with_autoindent_mode(text, autoindent, window, cx);
 3625    }
 3626
 3627    fn insert_with_autoindent_mode(
 3628        &mut self,
 3629        text: &str,
 3630        autoindent_mode: Option<AutoindentMode>,
 3631        window: &mut Window,
 3632        cx: &mut Context<Self>,
 3633    ) {
 3634        if self.read_only(cx) {
 3635            return;
 3636        }
 3637
 3638        let text: Arc<str> = text.into();
 3639        self.transact(window, cx, |this, window, cx| {
 3640            let old_selections = this.selections.all_adjusted(cx);
 3641            let selection_anchors = this.buffer.update(cx, |buffer, cx| {
 3642                let anchors = {
 3643                    let snapshot = buffer.read(cx);
 3644                    old_selections
 3645                        .iter()
 3646                        .map(|s| {
 3647                            let anchor = snapshot.anchor_after(s.head());
 3648                            s.map(|_| anchor)
 3649                        })
 3650                        .collect::<Vec<_>>()
 3651                };
 3652                buffer.edit(
 3653                    old_selections
 3654                        .iter()
 3655                        .map(|s| (s.start..s.end, text.clone())),
 3656                    autoindent_mode,
 3657                    cx,
 3658                );
 3659                anchors
 3660            });
 3661
 3662            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 3663                s.select_anchors(selection_anchors);
 3664            });
 3665
 3666            cx.notify();
 3667        });
 3668    }
 3669
 3670    fn trigger_completion_on_input(
 3671        &mut self,
 3672        text: &str,
 3673        trigger_in_words: bool,
 3674        window: &mut Window,
 3675        cx: &mut Context<Self>,
 3676    ) {
 3677        let ignore_completion_provider = self
 3678            .context_menu
 3679            .borrow()
 3680            .as_ref()
 3681            .map(|menu| match menu {
 3682                CodeContextMenu::Completions(completions_menu) => {
 3683                    completions_menu.ignore_completion_provider
 3684                }
 3685                CodeContextMenu::CodeActions(_) => false,
 3686            })
 3687            .unwrap_or(false);
 3688
 3689        if ignore_completion_provider {
 3690            self.show_word_completions(&ShowWordCompletions, window, cx);
 3691        } else if self.is_completion_trigger(text, trigger_in_words, cx) {
 3692            self.show_completions(
 3693                &ShowCompletions {
 3694                    trigger: Some(text.to_owned()).filter(|x| !x.is_empty()),
 3695                },
 3696                window,
 3697                cx,
 3698            );
 3699        } else {
 3700            self.hide_context_menu(window, cx);
 3701        }
 3702    }
 3703
 3704    fn is_completion_trigger(
 3705        &self,
 3706        text: &str,
 3707        trigger_in_words: bool,
 3708        cx: &mut Context<Self>,
 3709    ) -> bool {
 3710        let position = self.selections.newest_anchor().head();
 3711        let multibuffer = self.buffer.read(cx);
 3712        let Some(buffer) = position
 3713            .buffer_id
 3714            .and_then(|buffer_id| multibuffer.buffer(buffer_id).clone())
 3715        else {
 3716            return false;
 3717        };
 3718
 3719        if let Some(completion_provider) = &self.completion_provider {
 3720            completion_provider.is_completion_trigger(
 3721                &buffer,
 3722                position.text_anchor,
 3723                text,
 3724                trigger_in_words,
 3725                cx,
 3726            )
 3727        } else {
 3728            false
 3729        }
 3730    }
 3731
 3732    /// If any empty selections is touching the start of its innermost containing autoclose
 3733    /// region, expand it to select the brackets.
 3734    fn select_autoclose_pair(&mut self, window: &mut Window, cx: &mut Context<Self>) {
 3735        let selections = self.selections.all::<usize>(cx);
 3736        let buffer = self.buffer.read(cx).read(cx);
 3737        let new_selections = self
 3738            .selections_with_autoclose_regions(selections, &buffer)
 3739            .map(|(mut selection, region)| {
 3740                if !selection.is_empty() {
 3741                    return selection;
 3742                }
 3743
 3744                if let Some(region) = region {
 3745                    let mut range = region.range.to_offset(&buffer);
 3746                    if selection.start == range.start && range.start >= region.pair.start.len() {
 3747                        range.start -= region.pair.start.len();
 3748                        if buffer.contains_str_at(range.start, &region.pair.start)
 3749                            && buffer.contains_str_at(range.end, &region.pair.end)
 3750                        {
 3751                            range.end += region.pair.end.len();
 3752                            selection.start = range.start;
 3753                            selection.end = range.end;
 3754
 3755                            return selection;
 3756                        }
 3757                    }
 3758                }
 3759
 3760                let always_treat_brackets_as_autoclosed = buffer
 3761                    .language_settings_at(selection.start, cx)
 3762                    .always_treat_brackets_as_autoclosed;
 3763
 3764                if !always_treat_brackets_as_autoclosed {
 3765                    return selection;
 3766                }
 3767
 3768                if let Some(scope) = buffer.language_scope_at(selection.start) {
 3769                    for (pair, enabled) in scope.brackets() {
 3770                        if !enabled || !pair.close {
 3771                            continue;
 3772                        }
 3773
 3774                        if buffer.contains_str_at(selection.start, &pair.end) {
 3775                            let pair_start_len = pair.start.len();
 3776                            if buffer.contains_str_at(
 3777                                selection.start.saturating_sub(pair_start_len),
 3778                                &pair.start,
 3779                            ) {
 3780                                selection.start -= pair_start_len;
 3781                                selection.end += pair.end.len();
 3782
 3783                                return selection;
 3784                            }
 3785                        }
 3786                    }
 3787                }
 3788
 3789                selection
 3790            })
 3791            .collect();
 3792
 3793        drop(buffer);
 3794        self.change_selections(None, window, cx, |selections| {
 3795            selections.select(new_selections)
 3796        });
 3797    }
 3798
 3799    /// Iterate the given selections, and for each one, find the smallest surrounding
 3800    /// autoclose region. This uses the ordering of the selections and the autoclose
 3801    /// regions to avoid repeated comparisons.
 3802    fn selections_with_autoclose_regions<'a, D: ToOffset + Clone>(
 3803        &'a self,
 3804        selections: impl IntoIterator<Item = Selection<D>>,
 3805        buffer: &'a MultiBufferSnapshot,
 3806    ) -> impl Iterator<Item = (Selection<D>, Option<&'a AutocloseRegion>)> {
 3807        let mut i = 0;
 3808        let mut regions = self.autoclose_regions.as_slice();
 3809        selections.into_iter().map(move |selection| {
 3810            let range = selection.start.to_offset(buffer)..selection.end.to_offset(buffer);
 3811
 3812            let mut enclosing = None;
 3813            while let Some(pair_state) = regions.get(i) {
 3814                if pair_state.range.end.to_offset(buffer) < range.start {
 3815                    regions = &regions[i + 1..];
 3816                    i = 0;
 3817                } else if pair_state.range.start.to_offset(buffer) > range.end {
 3818                    break;
 3819                } else {
 3820                    if pair_state.selection_id == selection.id {
 3821                        enclosing = Some(pair_state);
 3822                    }
 3823                    i += 1;
 3824                }
 3825            }
 3826
 3827            (selection, enclosing)
 3828        })
 3829    }
 3830
 3831    /// Remove any autoclose regions that no longer contain their selection.
 3832    fn invalidate_autoclose_regions(
 3833        &mut self,
 3834        mut selections: &[Selection<Anchor>],
 3835        buffer: &MultiBufferSnapshot,
 3836    ) {
 3837        self.autoclose_regions.retain(|state| {
 3838            let mut i = 0;
 3839            while let Some(selection) = selections.get(i) {
 3840                if selection.end.cmp(&state.range.start, buffer).is_lt() {
 3841                    selections = &selections[1..];
 3842                    continue;
 3843                }
 3844                if selection.start.cmp(&state.range.end, buffer).is_gt() {
 3845                    break;
 3846                }
 3847                if selection.id == state.selection_id {
 3848                    return true;
 3849                } else {
 3850                    i += 1;
 3851                }
 3852            }
 3853            false
 3854        });
 3855    }
 3856
 3857    fn completion_query(buffer: &MultiBufferSnapshot, position: impl ToOffset) -> Option<String> {
 3858        let offset = position.to_offset(buffer);
 3859        let (word_range, kind) = buffer.surrounding_word(offset, true);
 3860        if offset > word_range.start && kind == Some(CharKind::Word) {
 3861            Some(
 3862                buffer
 3863                    .text_for_range(word_range.start..offset)
 3864                    .collect::<String>(),
 3865            )
 3866        } else {
 3867            None
 3868        }
 3869    }
 3870
 3871    pub fn toggle_inlay_hints(
 3872        &mut self,
 3873        _: &ToggleInlayHints,
 3874        _: &mut Window,
 3875        cx: &mut Context<Self>,
 3876    ) {
 3877        self.refresh_inlay_hints(
 3878            InlayHintRefreshReason::Toggle(!self.inlay_hints_enabled()),
 3879            cx,
 3880        );
 3881    }
 3882
 3883    pub fn inlay_hints_enabled(&self) -> bool {
 3884        self.inlay_hint_cache.enabled
 3885    }
 3886
 3887    fn refresh_inlay_hints(&mut self, reason: InlayHintRefreshReason, cx: &mut Context<Self>) {
 3888        if self.semantics_provider.is_none() || self.mode != EditorMode::Full {
 3889            return;
 3890        }
 3891
 3892        let reason_description = reason.description();
 3893        let ignore_debounce = matches!(
 3894            reason,
 3895            InlayHintRefreshReason::SettingsChange(_)
 3896                | InlayHintRefreshReason::Toggle(_)
 3897                | InlayHintRefreshReason::ExcerptsRemoved(_)
 3898                | InlayHintRefreshReason::ModifiersChanged(_)
 3899        );
 3900        let (invalidate_cache, required_languages) = match reason {
 3901            InlayHintRefreshReason::ModifiersChanged(enabled) => {
 3902                match self.inlay_hint_cache.modifiers_override(enabled) {
 3903                    Some(enabled) => {
 3904                        if enabled {
 3905                            (InvalidationStrategy::RefreshRequested, None)
 3906                        } else {
 3907                            self.splice_inlays(
 3908                                &self
 3909                                    .visible_inlay_hints(cx)
 3910                                    .iter()
 3911                                    .map(|inlay| inlay.id)
 3912                                    .collect::<Vec<InlayId>>(),
 3913                                Vec::new(),
 3914                                cx,
 3915                            );
 3916                            return;
 3917                        }
 3918                    }
 3919                    None => return,
 3920                }
 3921            }
 3922            InlayHintRefreshReason::Toggle(enabled) => {
 3923                if self.inlay_hint_cache.toggle(enabled) {
 3924                    if enabled {
 3925                        (InvalidationStrategy::RefreshRequested, None)
 3926                    } else {
 3927                        self.splice_inlays(
 3928                            &self
 3929                                .visible_inlay_hints(cx)
 3930                                .iter()
 3931                                .map(|inlay| inlay.id)
 3932                                .collect::<Vec<InlayId>>(),
 3933                            Vec::new(),
 3934                            cx,
 3935                        );
 3936                        return;
 3937                    }
 3938                } else {
 3939                    return;
 3940                }
 3941            }
 3942            InlayHintRefreshReason::SettingsChange(new_settings) => {
 3943                match self.inlay_hint_cache.update_settings(
 3944                    &self.buffer,
 3945                    new_settings,
 3946                    self.visible_inlay_hints(cx),
 3947                    cx,
 3948                ) {
 3949                    ControlFlow::Break(Some(InlaySplice {
 3950                        to_remove,
 3951                        to_insert,
 3952                    })) => {
 3953                        self.splice_inlays(&to_remove, to_insert, cx);
 3954                        return;
 3955                    }
 3956                    ControlFlow::Break(None) => return,
 3957                    ControlFlow::Continue(()) => (InvalidationStrategy::RefreshRequested, None),
 3958                }
 3959            }
 3960            InlayHintRefreshReason::ExcerptsRemoved(excerpts_removed) => {
 3961                if let Some(InlaySplice {
 3962                    to_remove,
 3963                    to_insert,
 3964                }) = self.inlay_hint_cache.remove_excerpts(excerpts_removed)
 3965                {
 3966                    self.splice_inlays(&to_remove, to_insert, cx);
 3967                }
 3968                return;
 3969            }
 3970            InlayHintRefreshReason::NewLinesShown => (InvalidationStrategy::None, None),
 3971            InlayHintRefreshReason::BufferEdited(buffer_languages) => {
 3972                (InvalidationStrategy::BufferEdited, Some(buffer_languages))
 3973            }
 3974            InlayHintRefreshReason::RefreshRequested => {
 3975                (InvalidationStrategy::RefreshRequested, None)
 3976            }
 3977        };
 3978
 3979        if let Some(InlaySplice {
 3980            to_remove,
 3981            to_insert,
 3982        }) = self.inlay_hint_cache.spawn_hint_refresh(
 3983            reason_description,
 3984            self.excerpts_for_inlay_hints_query(required_languages.as_ref(), cx),
 3985            invalidate_cache,
 3986            ignore_debounce,
 3987            cx,
 3988        ) {
 3989            self.splice_inlays(&to_remove, to_insert, cx);
 3990        }
 3991    }
 3992
 3993    fn visible_inlay_hints(&self, cx: &Context<Editor>) -> Vec<Inlay> {
 3994        self.display_map
 3995            .read(cx)
 3996            .current_inlays()
 3997            .filter(move |inlay| matches!(inlay.id, InlayId::Hint(_)))
 3998            .cloned()
 3999            .collect()
 4000    }
 4001
 4002    pub fn excerpts_for_inlay_hints_query(
 4003        &self,
 4004        restrict_to_languages: Option<&HashSet<Arc<Language>>>,
 4005        cx: &mut Context<Editor>,
 4006    ) -> HashMap<ExcerptId, (Entity<Buffer>, clock::Global, Range<usize>)> {
 4007        let Some(project) = self.project.as_ref() else {
 4008            return HashMap::default();
 4009        };
 4010        let project = project.read(cx);
 4011        let multi_buffer = self.buffer().read(cx);
 4012        let multi_buffer_snapshot = multi_buffer.snapshot(cx);
 4013        let multi_buffer_visible_start = self
 4014            .scroll_manager
 4015            .anchor()
 4016            .anchor
 4017            .to_point(&multi_buffer_snapshot);
 4018        let multi_buffer_visible_end = multi_buffer_snapshot.clip_point(
 4019            multi_buffer_visible_start
 4020                + Point::new(self.visible_line_count().unwrap_or(0.).ceil() as u32, 0),
 4021            Bias::Left,
 4022        );
 4023        let multi_buffer_visible_range = multi_buffer_visible_start..multi_buffer_visible_end;
 4024        multi_buffer_snapshot
 4025            .range_to_buffer_ranges(multi_buffer_visible_range)
 4026            .into_iter()
 4027            .filter(|(_, excerpt_visible_range, _)| !excerpt_visible_range.is_empty())
 4028            .filter_map(|(buffer, excerpt_visible_range, excerpt_id)| {
 4029                let buffer_file = project::File::from_dyn(buffer.file())?;
 4030                let buffer_worktree = project.worktree_for_id(buffer_file.worktree_id(cx), cx)?;
 4031                let worktree_entry = buffer_worktree
 4032                    .read(cx)
 4033                    .entry_for_id(buffer_file.project_entry_id(cx)?)?;
 4034                if worktree_entry.is_ignored {
 4035                    return None;
 4036                }
 4037
 4038                let language = buffer.language()?;
 4039                if let Some(restrict_to_languages) = restrict_to_languages {
 4040                    if !restrict_to_languages.contains(language) {
 4041                        return None;
 4042                    }
 4043                }
 4044                Some((
 4045                    excerpt_id,
 4046                    (
 4047                        multi_buffer.buffer(buffer.remote_id()).unwrap(),
 4048                        buffer.version().clone(),
 4049                        excerpt_visible_range,
 4050                    ),
 4051                ))
 4052            })
 4053            .collect()
 4054    }
 4055
 4056    pub fn text_layout_details(&self, window: &mut Window) -> TextLayoutDetails {
 4057        TextLayoutDetails {
 4058            text_system: window.text_system().clone(),
 4059            editor_style: self.style.clone().unwrap(),
 4060            rem_size: window.rem_size(),
 4061            scroll_anchor: self.scroll_manager.anchor(),
 4062            visible_rows: self.visible_line_count(),
 4063            vertical_scroll_margin: self.scroll_manager.vertical_scroll_margin,
 4064        }
 4065    }
 4066
 4067    pub fn splice_inlays(
 4068        &self,
 4069        to_remove: &[InlayId],
 4070        to_insert: Vec<Inlay>,
 4071        cx: &mut Context<Self>,
 4072    ) {
 4073        self.display_map.update(cx, |display_map, cx| {
 4074            display_map.splice_inlays(to_remove, to_insert, cx)
 4075        });
 4076        cx.notify();
 4077    }
 4078
 4079    fn trigger_on_type_formatting(
 4080        &self,
 4081        input: String,
 4082        window: &mut Window,
 4083        cx: &mut Context<Self>,
 4084    ) -> Option<Task<Result<()>>> {
 4085        if input.len() != 1 {
 4086            return None;
 4087        }
 4088
 4089        let project = self.project.as_ref()?;
 4090        let position = self.selections.newest_anchor().head();
 4091        let (buffer, buffer_position) = self
 4092            .buffer
 4093            .read(cx)
 4094            .text_anchor_for_position(position, cx)?;
 4095
 4096        let settings = language_settings::language_settings(
 4097            buffer
 4098                .read(cx)
 4099                .language_at(buffer_position)
 4100                .map(|l| l.name()),
 4101            buffer.read(cx).file(),
 4102            cx,
 4103        );
 4104        if !settings.use_on_type_format {
 4105            return None;
 4106        }
 4107
 4108        // OnTypeFormatting returns a list of edits, no need to pass them between Zed instances,
 4109        // hence we do LSP request & edit on host side only — add formats to host's history.
 4110        let push_to_lsp_host_history = true;
 4111        // If this is not the host, append its history with new edits.
 4112        let push_to_client_history = project.read(cx).is_via_collab();
 4113
 4114        let on_type_formatting = project.update(cx, |project, cx| {
 4115            project.on_type_format(
 4116                buffer.clone(),
 4117                buffer_position,
 4118                input,
 4119                push_to_lsp_host_history,
 4120                cx,
 4121            )
 4122        });
 4123        Some(cx.spawn_in(window, async move |editor, cx| {
 4124            if let Some(transaction) = on_type_formatting.await? {
 4125                if push_to_client_history {
 4126                    buffer
 4127                        .update(cx, |buffer, _| {
 4128                            buffer.push_transaction(transaction, Instant::now());
 4129                        })
 4130                        .ok();
 4131                }
 4132                editor.update(cx, |editor, cx| {
 4133                    editor.refresh_document_highlights(cx);
 4134                })?;
 4135            }
 4136            Ok(())
 4137        }))
 4138    }
 4139
 4140    pub fn show_word_completions(
 4141        &mut self,
 4142        _: &ShowWordCompletions,
 4143        window: &mut Window,
 4144        cx: &mut Context<Self>,
 4145    ) {
 4146        self.open_completions_menu(true, None, window, cx);
 4147    }
 4148
 4149    pub fn show_completions(
 4150        &mut self,
 4151        options: &ShowCompletions,
 4152        window: &mut Window,
 4153        cx: &mut Context<Self>,
 4154    ) {
 4155        self.open_completions_menu(false, options.trigger.as_deref(), window, cx);
 4156    }
 4157
 4158    fn open_completions_menu(
 4159        &mut self,
 4160        ignore_completion_provider: bool,
 4161        trigger: Option<&str>,
 4162        window: &mut Window,
 4163        cx: &mut Context<Self>,
 4164    ) {
 4165        if self.pending_rename.is_some() {
 4166            return;
 4167        }
 4168        if !self.snippet_stack.is_empty() && self.context_menu.borrow().as_ref().is_some() {
 4169            return;
 4170        }
 4171
 4172        let position = self.selections.newest_anchor().head();
 4173        if position.diff_base_anchor.is_some() {
 4174            return;
 4175        }
 4176        let (buffer, buffer_position) =
 4177            if let Some(output) = self.buffer.read(cx).text_anchor_for_position(position, cx) {
 4178                output
 4179            } else {
 4180                return;
 4181            };
 4182        let buffer_snapshot = buffer.read(cx).snapshot();
 4183        let show_completion_documentation = buffer_snapshot
 4184            .settings_at(buffer_position, cx)
 4185            .show_completion_documentation;
 4186
 4187        let query = Self::completion_query(&self.buffer.read(cx).read(cx), position);
 4188
 4189        let trigger_kind = match trigger {
 4190            Some(trigger) if buffer.read(cx).completion_triggers().contains(trigger) => {
 4191                CompletionTriggerKind::TRIGGER_CHARACTER
 4192            }
 4193            _ => CompletionTriggerKind::INVOKED,
 4194        };
 4195        let completion_context = CompletionContext {
 4196            trigger_character: trigger.and_then(|trigger| {
 4197                if trigger_kind == CompletionTriggerKind::TRIGGER_CHARACTER {
 4198                    Some(String::from(trigger))
 4199                } else {
 4200                    None
 4201                }
 4202            }),
 4203            trigger_kind,
 4204        };
 4205
 4206        let (old_range, word_kind) = buffer_snapshot.surrounding_word(buffer_position);
 4207        let (old_range, word_to_exclude) = if word_kind == Some(CharKind::Word) {
 4208            let word_to_exclude = buffer_snapshot
 4209                .text_for_range(old_range.clone())
 4210                .collect::<String>();
 4211            (
 4212                buffer_snapshot.anchor_before(old_range.start)
 4213                    ..buffer_snapshot.anchor_after(old_range.end),
 4214                Some(word_to_exclude),
 4215            )
 4216        } else {
 4217            (buffer_position..buffer_position, None)
 4218        };
 4219
 4220        let completion_settings = language_settings(
 4221            buffer_snapshot
 4222                .language_at(buffer_position)
 4223                .map(|language| language.name()),
 4224            buffer_snapshot.file(),
 4225            cx,
 4226        )
 4227        .completions;
 4228
 4229        // The document can be large, so stay in reasonable bounds when searching for words,
 4230        // otherwise completion pop-up might be slow to appear.
 4231        const WORD_LOOKUP_ROWS: u32 = 5_000;
 4232        let buffer_row = text::ToPoint::to_point(&buffer_position, &buffer_snapshot).row;
 4233        let min_word_search = buffer_snapshot.clip_point(
 4234            Point::new(buffer_row.saturating_sub(WORD_LOOKUP_ROWS), 0),
 4235            Bias::Left,
 4236        );
 4237        let max_word_search = buffer_snapshot.clip_point(
 4238            Point::new(buffer_row + WORD_LOOKUP_ROWS, 0).min(buffer_snapshot.max_point()),
 4239            Bias::Right,
 4240        );
 4241        let word_search_range = buffer_snapshot.point_to_offset(min_word_search)
 4242            ..buffer_snapshot.point_to_offset(max_word_search);
 4243
 4244        let provider = self
 4245            .completion_provider
 4246            .as_ref()
 4247            .filter(|_| !ignore_completion_provider);
 4248        let skip_digits = query
 4249            .as_ref()
 4250            .map_or(true, |query| !query.chars().any(|c| c.is_digit(10)));
 4251
 4252        let (mut words, provided_completions) = match provider {
 4253            Some(provider) => {
 4254                let completions =
 4255                    provider.completions(&buffer, buffer_position, completion_context, window, cx);
 4256
 4257                let words = match completion_settings.words {
 4258                    WordsCompletionMode::Disabled => Task::ready(HashMap::default()),
 4259                    WordsCompletionMode::Enabled | WordsCompletionMode::Fallback => cx
 4260                        .background_spawn(async move {
 4261                            buffer_snapshot.words_in_range(WordsQuery {
 4262                                fuzzy_contents: None,
 4263                                range: word_search_range,
 4264                                skip_digits,
 4265                            })
 4266                        }),
 4267                };
 4268
 4269                (words, completions)
 4270            }
 4271            None => (
 4272                cx.background_spawn(async move {
 4273                    buffer_snapshot.words_in_range(WordsQuery {
 4274                        fuzzy_contents: None,
 4275                        range: word_search_range,
 4276                        skip_digits,
 4277                    })
 4278                }),
 4279                Task::ready(Ok(None)),
 4280            ),
 4281        };
 4282
 4283        let sort_completions = provider
 4284            .as_ref()
 4285            .map_or(true, |provider| provider.sort_completions());
 4286
 4287        let id = post_inc(&mut self.next_completion_id);
 4288        let task = cx.spawn_in(window, async move |editor, cx| {
 4289            async move {
 4290                editor.update(cx, |this, _| {
 4291                    this.completion_tasks.retain(|(task_id, _)| *task_id >= id);
 4292                })?;
 4293
 4294                let mut completions = Vec::new();
 4295                if let Some(provided_completions) = provided_completions.await.log_err().flatten() {
 4296                    completions.extend(provided_completions);
 4297                    if completion_settings.words == WordsCompletionMode::Fallback {
 4298                        words = Task::ready(HashMap::default());
 4299                    }
 4300                }
 4301
 4302                let mut words = words.await;
 4303                if let Some(word_to_exclude) = &word_to_exclude {
 4304                    words.remove(word_to_exclude);
 4305                }
 4306                for lsp_completion in &completions {
 4307                    words.remove(&lsp_completion.new_text);
 4308                }
 4309                completions.extend(words.into_iter().map(|(word, word_range)| Completion {
 4310                    old_range: old_range.clone(),
 4311                    new_text: word.clone(),
 4312                    label: CodeLabel::plain(word, None),
 4313                    documentation: None,
 4314                    source: CompletionSource::BufferWord {
 4315                        word_range,
 4316                        resolved: false,
 4317                    },
 4318                    confirm: None,
 4319                }));
 4320
 4321                let menu = if completions.is_empty() {
 4322                    None
 4323                } else {
 4324                    let mut menu = CompletionsMenu::new(
 4325                        id,
 4326                        sort_completions,
 4327                        show_completion_documentation,
 4328                        ignore_completion_provider,
 4329                        position,
 4330                        buffer.clone(),
 4331                        completions.into(),
 4332                    );
 4333
 4334                    menu.filter(query.as_deref(), cx.background_executor().clone())
 4335                        .await;
 4336
 4337                    menu.visible().then_some(menu)
 4338                };
 4339
 4340                editor.update_in(cx, |editor, window, cx| {
 4341                    match editor.context_menu.borrow().as_ref() {
 4342                        None => {}
 4343                        Some(CodeContextMenu::Completions(prev_menu)) => {
 4344                            if prev_menu.id > id {
 4345                                return;
 4346                            }
 4347                        }
 4348                        _ => return,
 4349                    }
 4350
 4351                    if editor.focus_handle.is_focused(window) && menu.is_some() {
 4352                        let mut menu = menu.unwrap();
 4353                        menu.resolve_visible_completions(editor.completion_provider.as_deref(), cx);
 4354
 4355                        *editor.context_menu.borrow_mut() =
 4356                            Some(CodeContextMenu::Completions(menu));
 4357
 4358                        if editor.show_edit_predictions_in_menu() {
 4359                            editor.update_visible_inline_completion(window, cx);
 4360                        } else {
 4361                            editor.discard_inline_completion(false, cx);
 4362                        }
 4363
 4364                        cx.notify();
 4365                    } else if editor.completion_tasks.len() <= 1 {
 4366                        // If there are no more completion tasks and the last menu was
 4367                        // empty, we should hide it.
 4368                        let was_hidden = editor.hide_context_menu(window, cx).is_none();
 4369                        // If it was already hidden and we don't show inline
 4370                        // completions in the menu, we should also show the
 4371                        // inline-completion when available.
 4372                        if was_hidden && editor.show_edit_predictions_in_menu() {
 4373                            editor.update_visible_inline_completion(window, cx);
 4374                        }
 4375                    }
 4376                })?;
 4377
 4378                anyhow::Ok(())
 4379            }
 4380            .log_err()
 4381            .await
 4382        });
 4383
 4384        self.completion_tasks.push((id, task));
 4385    }
 4386
 4387    pub fn confirm_completion(
 4388        &mut self,
 4389        action: &ConfirmCompletion,
 4390        window: &mut Window,
 4391        cx: &mut Context<Self>,
 4392    ) -> Option<Task<Result<()>>> {
 4393        self.do_completion(action.item_ix, CompletionIntent::Complete, window, cx)
 4394    }
 4395
 4396    pub fn compose_completion(
 4397        &mut self,
 4398        action: &ComposeCompletion,
 4399        window: &mut Window,
 4400        cx: &mut Context<Self>,
 4401    ) -> Option<Task<Result<()>>> {
 4402        self.do_completion(action.item_ix, CompletionIntent::Compose, window, cx)
 4403    }
 4404
 4405    fn do_completion(
 4406        &mut self,
 4407        item_ix: Option<usize>,
 4408        intent: CompletionIntent,
 4409        window: &mut Window,
 4410        cx: &mut Context<Editor>,
 4411    ) -> Option<Task<std::result::Result<(), anyhow::Error>>> {
 4412        use language::ToOffset as _;
 4413
 4414        let completions_menu =
 4415            if let CodeContextMenu::Completions(menu) = self.hide_context_menu(window, cx)? {
 4416                menu
 4417            } else {
 4418                return None;
 4419            };
 4420
 4421        let entries = completions_menu.entries.borrow();
 4422        let mat = entries.get(item_ix.unwrap_or(completions_menu.selected_item))?;
 4423        if self.show_edit_predictions_in_menu() {
 4424            self.discard_inline_completion(true, cx);
 4425        }
 4426        let candidate_id = mat.candidate_id;
 4427        drop(entries);
 4428
 4429        let buffer_handle = completions_menu.buffer;
 4430        let completion = completions_menu
 4431            .completions
 4432            .borrow()
 4433            .get(candidate_id)?
 4434            .clone();
 4435        cx.stop_propagation();
 4436
 4437        let snippet;
 4438        let text;
 4439
 4440        if completion.is_snippet() {
 4441            snippet = Some(Snippet::parse(&completion.new_text).log_err()?);
 4442            text = snippet.as_ref().unwrap().text.clone();
 4443        } else {
 4444            snippet = None;
 4445            text = completion.new_text.clone();
 4446        };
 4447        let selections = self.selections.all::<usize>(cx);
 4448        let buffer = buffer_handle.read(cx);
 4449        let old_range = completion.old_range.to_offset(buffer);
 4450        let old_text = buffer.text_for_range(old_range.clone()).collect::<String>();
 4451
 4452        let newest_selection = self.selections.newest_anchor();
 4453        if newest_selection.start.buffer_id != Some(buffer_handle.read(cx).remote_id()) {
 4454            return None;
 4455        }
 4456
 4457        let lookbehind = newest_selection
 4458            .start
 4459            .text_anchor
 4460            .to_offset(buffer)
 4461            .saturating_sub(old_range.start);
 4462        let lookahead = old_range
 4463            .end
 4464            .saturating_sub(newest_selection.end.text_anchor.to_offset(buffer));
 4465        let mut common_prefix_len = old_text
 4466            .bytes()
 4467            .zip(text.bytes())
 4468            .take_while(|(a, b)| a == b)
 4469            .count();
 4470
 4471        let snapshot = self.buffer.read(cx).snapshot(cx);
 4472        let mut range_to_replace: Option<Range<isize>> = None;
 4473        let mut ranges = Vec::new();
 4474        let mut linked_edits = HashMap::<_, Vec<_>>::default();
 4475        for selection in &selections {
 4476            if snapshot.contains_str_at(selection.start.saturating_sub(lookbehind), &old_text) {
 4477                let start = selection.start.saturating_sub(lookbehind);
 4478                let end = selection.end + lookahead;
 4479                if selection.id == newest_selection.id {
 4480                    range_to_replace = Some(
 4481                        ((start + common_prefix_len) as isize - selection.start as isize)
 4482                            ..(end as isize - selection.start as isize),
 4483                    );
 4484                }
 4485                ranges.push(start + common_prefix_len..end);
 4486            } else {
 4487                common_prefix_len = 0;
 4488                ranges.clear();
 4489                ranges.extend(selections.iter().map(|s| {
 4490                    if s.id == newest_selection.id {
 4491                        range_to_replace = Some(
 4492                            old_range.start.to_offset_utf16(&snapshot).0 as isize
 4493                                - selection.start as isize
 4494                                ..old_range.end.to_offset_utf16(&snapshot).0 as isize
 4495                                    - selection.start as isize,
 4496                        );
 4497                        old_range.clone()
 4498                    } else {
 4499                        s.start..s.end
 4500                    }
 4501                }));
 4502                break;
 4503            }
 4504            if !self.linked_edit_ranges.is_empty() {
 4505                let start_anchor = snapshot.anchor_before(selection.head());
 4506                let end_anchor = snapshot.anchor_after(selection.tail());
 4507                if let Some(ranges) = self
 4508                    .linked_editing_ranges_for(start_anchor.text_anchor..end_anchor.text_anchor, cx)
 4509                {
 4510                    for (buffer, edits) in ranges {
 4511                        linked_edits.entry(buffer.clone()).or_default().extend(
 4512                            edits
 4513                                .into_iter()
 4514                                .map(|range| (range, text[common_prefix_len..].to_owned())),
 4515                        );
 4516                    }
 4517                }
 4518            }
 4519        }
 4520        let text = &text[common_prefix_len..];
 4521
 4522        cx.emit(EditorEvent::InputHandled {
 4523            utf16_range_to_replace: range_to_replace,
 4524            text: text.into(),
 4525        });
 4526
 4527        self.transact(window, cx, |this, window, cx| {
 4528            if let Some(mut snippet) = snippet {
 4529                snippet.text = text.to_string();
 4530                for tabstop in snippet
 4531                    .tabstops
 4532                    .iter_mut()
 4533                    .flat_map(|tabstop| tabstop.ranges.iter_mut())
 4534                {
 4535                    tabstop.start -= common_prefix_len as isize;
 4536                    tabstop.end -= common_prefix_len as isize;
 4537                }
 4538
 4539                this.insert_snippet(&ranges, snippet, window, cx).log_err();
 4540            } else {
 4541                this.buffer.update(cx, |buffer, cx| {
 4542                    buffer.edit(
 4543                        ranges.iter().map(|range| (range.clone(), text)),
 4544                        this.autoindent_mode.clone(),
 4545                        cx,
 4546                    );
 4547                });
 4548            }
 4549            for (buffer, edits) in linked_edits {
 4550                buffer.update(cx, |buffer, cx| {
 4551                    let snapshot = buffer.snapshot();
 4552                    let edits = edits
 4553                        .into_iter()
 4554                        .map(|(range, text)| {
 4555                            use text::ToPoint as TP;
 4556                            let end_point = TP::to_point(&range.end, &snapshot);
 4557                            let start_point = TP::to_point(&range.start, &snapshot);
 4558                            (start_point..end_point, text)
 4559                        })
 4560                        .sorted_by_key(|(range, _)| range.start)
 4561                        .collect::<Vec<_>>();
 4562                    buffer.edit(edits, None, cx);
 4563                })
 4564            }
 4565
 4566            this.refresh_inline_completion(true, false, window, cx);
 4567        });
 4568
 4569        let show_new_completions_on_confirm = completion
 4570            .confirm
 4571            .as_ref()
 4572            .map_or(false, |confirm| confirm(intent, window, cx));
 4573        if show_new_completions_on_confirm {
 4574            self.show_completions(&ShowCompletions { trigger: None }, window, cx);
 4575        }
 4576
 4577        let provider = self.completion_provider.as_ref()?;
 4578        drop(completion);
 4579        let apply_edits = provider.apply_additional_edits_for_completion(
 4580            buffer_handle,
 4581            completions_menu.completions.clone(),
 4582            candidate_id,
 4583            true,
 4584            cx,
 4585        );
 4586
 4587        let editor_settings = EditorSettings::get_global(cx);
 4588        if editor_settings.show_signature_help_after_edits || editor_settings.auto_signature_help {
 4589            // After the code completion is finished, users often want to know what signatures are needed.
 4590            // so we should automatically call signature_help
 4591            self.show_signature_help(&ShowSignatureHelp, window, cx);
 4592        }
 4593
 4594        Some(cx.foreground_executor().spawn(async move {
 4595            apply_edits.await?;
 4596            Ok(())
 4597        }))
 4598    }
 4599
 4600    pub fn toggle_code_actions(
 4601        &mut self,
 4602        action: &ToggleCodeActions,
 4603        window: &mut Window,
 4604        cx: &mut Context<Self>,
 4605    ) {
 4606        let mut context_menu = self.context_menu.borrow_mut();
 4607        if let Some(CodeContextMenu::CodeActions(code_actions)) = context_menu.as_ref() {
 4608            if code_actions.deployed_from_indicator == action.deployed_from_indicator {
 4609                // Toggle if we're selecting the same one
 4610                *context_menu = None;
 4611                cx.notify();
 4612                return;
 4613            } else {
 4614                // Otherwise, clear it and start a new one
 4615                *context_menu = None;
 4616                cx.notify();
 4617            }
 4618        }
 4619        drop(context_menu);
 4620        let snapshot = self.snapshot(window, cx);
 4621        let deployed_from_indicator = action.deployed_from_indicator;
 4622        let mut task = self.code_actions_task.take();
 4623        let action = action.clone();
 4624        cx.spawn_in(window, async move |editor, cx| {
 4625            while let Some(prev_task) = task {
 4626                prev_task.await.log_err();
 4627                task = editor.update(cx, |this, _| this.code_actions_task.take())?;
 4628            }
 4629
 4630            let spawned_test_task = editor.update_in(cx, |editor, window, cx| {
 4631                if editor.focus_handle.is_focused(window) {
 4632                    let multibuffer_point = action
 4633                        .deployed_from_indicator
 4634                        .map(|row| DisplayPoint::new(row, 0).to_point(&snapshot))
 4635                        .unwrap_or_else(|| editor.selections.newest::<Point>(cx).head());
 4636                    let (buffer, buffer_row) = snapshot
 4637                        .buffer_snapshot
 4638                        .buffer_line_for_row(MultiBufferRow(multibuffer_point.row))
 4639                        .and_then(|(buffer_snapshot, range)| {
 4640                            editor
 4641                                .buffer
 4642                                .read(cx)
 4643                                .buffer(buffer_snapshot.remote_id())
 4644                                .map(|buffer| (buffer, range.start.row))
 4645                        })?;
 4646                    let (_, code_actions) = editor
 4647                        .available_code_actions
 4648                        .clone()
 4649                        .and_then(|(location, code_actions)| {
 4650                            let snapshot = location.buffer.read(cx).snapshot();
 4651                            let point_range = location.range.to_point(&snapshot);
 4652                            let point_range = point_range.start.row..=point_range.end.row;
 4653                            if point_range.contains(&buffer_row) {
 4654                                Some((location, code_actions))
 4655                            } else {
 4656                                None
 4657                            }
 4658                        })
 4659                        .unzip();
 4660                    let buffer_id = buffer.read(cx).remote_id();
 4661                    let tasks = editor
 4662                        .tasks
 4663                        .get(&(buffer_id, buffer_row))
 4664                        .map(|t| Arc::new(t.to_owned()));
 4665                    if tasks.is_none() && code_actions.is_none() {
 4666                        return None;
 4667                    }
 4668
 4669                    editor.completion_tasks.clear();
 4670                    editor.discard_inline_completion(false, cx);
 4671                    let task_context =
 4672                        tasks
 4673                            .as_ref()
 4674                            .zip(editor.project.clone())
 4675                            .map(|(tasks, project)| {
 4676                                Self::build_tasks_context(&project, &buffer, buffer_row, tasks, cx)
 4677                            });
 4678
 4679                    Some(cx.spawn_in(window, async move |editor, cx| {
 4680                        let task_context = match task_context {
 4681                            Some(task_context) => task_context.await,
 4682                            None => None,
 4683                        };
 4684                        let resolved_tasks =
 4685                            tasks.zip(task_context).map(|(tasks, task_context)| {
 4686                                Rc::new(ResolvedTasks {
 4687                                    templates: tasks.resolve(&task_context).collect(),
 4688                                    position: snapshot.buffer_snapshot.anchor_before(Point::new(
 4689                                        multibuffer_point.row,
 4690                                        tasks.column,
 4691                                    )),
 4692                                })
 4693                            });
 4694                        let spawn_straight_away = resolved_tasks
 4695                            .as_ref()
 4696                            .map_or(false, |tasks| tasks.templates.len() == 1)
 4697                            && code_actions
 4698                                .as_ref()
 4699                                .map_or(true, |actions| actions.is_empty());
 4700                        if let Ok(task) = editor.update_in(cx, |editor, window, cx| {
 4701                            *editor.context_menu.borrow_mut() =
 4702                                Some(CodeContextMenu::CodeActions(CodeActionsMenu {
 4703                                    buffer,
 4704                                    actions: CodeActionContents {
 4705                                        tasks: resolved_tasks,
 4706                                        actions: code_actions,
 4707                                    },
 4708                                    selected_item: Default::default(),
 4709                                    scroll_handle: UniformListScrollHandle::default(),
 4710                                    deployed_from_indicator,
 4711                                }));
 4712                            if spawn_straight_away {
 4713                                if let Some(task) = editor.confirm_code_action(
 4714                                    &ConfirmCodeAction { item_ix: Some(0) },
 4715                                    window,
 4716                                    cx,
 4717                                ) {
 4718                                    cx.notify();
 4719                                    return task;
 4720                                }
 4721                            }
 4722                            cx.notify();
 4723                            Task::ready(Ok(()))
 4724                        }) {
 4725                            task.await
 4726                        } else {
 4727                            Ok(())
 4728                        }
 4729                    }))
 4730                } else {
 4731                    Some(Task::ready(Ok(())))
 4732                }
 4733            })?;
 4734            if let Some(task) = spawned_test_task {
 4735                task.await?;
 4736            }
 4737
 4738            Ok::<_, anyhow::Error>(())
 4739        })
 4740        .detach_and_log_err(cx);
 4741    }
 4742
 4743    pub fn confirm_code_action(
 4744        &mut self,
 4745        action: &ConfirmCodeAction,
 4746        window: &mut Window,
 4747        cx: &mut Context<Self>,
 4748    ) -> Option<Task<Result<()>>> {
 4749        let actions_menu =
 4750            if let CodeContextMenu::CodeActions(menu) = self.hide_context_menu(window, cx)? {
 4751                menu
 4752            } else {
 4753                return None;
 4754            };
 4755        let action_ix = action.item_ix.unwrap_or(actions_menu.selected_item);
 4756        let action = actions_menu.actions.get(action_ix)?;
 4757        let title = action.label();
 4758        let buffer = actions_menu.buffer;
 4759        let workspace = self.workspace()?;
 4760
 4761        match action {
 4762            CodeActionsItem::Task(task_source_kind, resolved_task) => {
 4763                workspace.update(cx, |workspace, cx| {
 4764                    workspace::tasks::schedule_resolved_task(
 4765                        workspace,
 4766                        task_source_kind,
 4767                        resolved_task,
 4768                        false,
 4769                        cx,
 4770                    );
 4771
 4772                    Some(Task::ready(Ok(())))
 4773                })
 4774            }
 4775            CodeActionsItem::CodeAction {
 4776                excerpt_id,
 4777                action,
 4778                provider,
 4779            } => {
 4780                let apply_code_action =
 4781                    provider.apply_code_action(buffer, action, excerpt_id, true, window, cx);
 4782                let workspace = workspace.downgrade();
 4783                Some(cx.spawn_in(window, async move |editor, cx| {
 4784                    let project_transaction = apply_code_action.await?;
 4785                    Self::open_project_transaction(
 4786                        &editor,
 4787                        workspace,
 4788                        project_transaction,
 4789                        title,
 4790                        cx,
 4791                    )
 4792                    .await
 4793                }))
 4794            }
 4795        }
 4796    }
 4797
 4798    pub async fn open_project_transaction(
 4799        this: &WeakEntity<Editor>,
 4800        workspace: WeakEntity<Workspace>,
 4801        transaction: ProjectTransaction,
 4802        title: String,
 4803        cx: &mut AsyncWindowContext,
 4804    ) -> Result<()> {
 4805        let mut entries = transaction.0.into_iter().collect::<Vec<_>>();
 4806        cx.update(|_, cx| {
 4807            entries.sort_unstable_by_key(|(buffer, _)| {
 4808                buffer.read(cx).file().map(|f| f.path().clone())
 4809            });
 4810        })?;
 4811
 4812        // If the project transaction's edits are all contained within this editor, then
 4813        // avoid opening a new editor to display them.
 4814
 4815        if let Some((buffer, transaction)) = entries.first() {
 4816            if entries.len() == 1 {
 4817                let excerpt = this.update(cx, |editor, cx| {
 4818                    editor
 4819                        .buffer()
 4820                        .read(cx)
 4821                        .excerpt_containing(editor.selections.newest_anchor().head(), cx)
 4822                })?;
 4823                if let Some((_, excerpted_buffer, excerpt_range)) = excerpt {
 4824                    if excerpted_buffer == *buffer {
 4825                        let all_edits_within_excerpt = buffer.read_with(cx, |buffer, _| {
 4826                            let excerpt_range = excerpt_range.to_offset(buffer);
 4827                            buffer
 4828                                .edited_ranges_for_transaction::<usize>(transaction)
 4829                                .all(|range| {
 4830                                    excerpt_range.start <= range.start
 4831                                        && excerpt_range.end >= range.end
 4832                                })
 4833                        })?;
 4834
 4835                        if all_edits_within_excerpt {
 4836                            return Ok(());
 4837                        }
 4838                    }
 4839                }
 4840            }
 4841        } else {
 4842            return Ok(());
 4843        }
 4844
 4845        let mut ranges_to_highlight = Vec::new();
 4846        let excerpt_buffer = cx.new(|cx| {
 4847            let mut multibuffer = MultiBuffer::new(Capability::ReadWrite).with_title(title);
 4848            for (buffer_handle, transaction) in &entries {
 4849                let buffer = buffer_handle.read(cx);
 4850                ranges_to_highlight.extend(
 4851                    multibuffer.push_excerpts_with_context_lines(
 4852                        buffer_handle.clone(),
 4853                        buffer
 4854                            .edited_ranges_for_transaction::<usize>(transaction)
 4855                            .collect(),
 4856                        DEFAULT_MULTIBUFFER_CONTEXT,
 4857                        cx,
 4858                    ),
 4859                );
 4860            }
 4861            multibuffer.push_transaction(entries.iter().map(|(b, t)| (b, t)), cx);
 4862            multibuffer
 4863        })?;
 4864
 4865        workspace.update_in(cx, |workspace, window, cx| {
 4866            let project = workspace.project().clone();
 4867            let editor =
 4868                cx.new(|cx| Editor::for_multibuffer(excerpt_buffer, Some(project), window, cx));
 4869            workspace.add_item_to_active_pane(Box::new(editor.clone()), None, true, window, cx);
 4870            editor.update(cx, |editor, cx| {
 4871                editor.highlight_background::<Self>(
 4872                    &ranges_to_highlight,
 4873                    |theme| theme.editor_highlighted_line_background,
 4874                    cx,
 4875                );
 4876            });
 4877        })?;
 4878
 4879        Ok(())
 4880    }
 4881
 4882    pub fn clear_code_action_providers(&mut self) {
 4883        self.code_action_providers.clear();
 4884        self.available_code_actions.take();
 4885    }
 4886
 4887    pub fn add_code_action_provider(
 4888        &mut self,
 4889        provider: Rc<dyn CodeActionProvider>,
 4890        window: &mut Window,
 4891        cx: &mut Context<Self>,
 4892    ) {
 4893        if self
 4894            .code_action_providers
 4895            .iter()
 4896            .any(|existing_provider| existing_provider.id() == provider.id())
 4897        {
 4898            return;
 4899        }
 4900
 4901        self.code_action_providers.push(provider);
 4902        self.refresh_code_actions(window, cx);
 4903    }
 4904
 4905    pub fn remove_code_action_provider(
 4906        &mut self,
 4907        id: Arc<str>,
 4908        window: &mut Window,
 4909        cx: &mut Context<Self>,
 4910    ) {
 4911        self.code_action_providers
 4912            .retain(|provider| provider.id() != id);
 4913        self.refresh_code_actions(window, cx);
 4914    }
 4915
 4916    fn refresh_code_actions(&mut self, window: &mut Window, cx: &mut Context<Self>) -> Option<()> {
 4917        let buffer = self.buffer.read(cx);
 4918        let newest_selection = self.selections.newest_anchor().clone();
 4919        if newest_selection.head().diff_base_anchor.is_some() {
 4920            return None;
 4921        }
 4922        let (start_buffer, start) = buffer.text_anchor_for_position(newest_selection.start, cx)?;
 4923        let (end_buffer, end) = buffer.text_anchor_for_position(newest_selection.end, cx)?;
 4924        if start_buffer != end_buffer {
 4925            return None;
 4926        }
 4927
 4928        self.code_actions_task = Some(cx.spawn_in(window, async move |this, cx| {
 4929            cx.background_executor()
 4930                .timer(CODE_ACTIONS_DEBOUNCE_TIMEOUT)
 4931                .await;
 4932
 4933            let (providers, tasks) = this.update_in(cx, |this, window, cx| {
 4934                let providers = this.code_action_providers.clone();
 4935                let tasks = this
 4936                    .code_action_providers
 4937                    .iter()
 4938                    .map(|provider| provider.code_actions(&start_buffer, start..end, window, cx))
 4939                    .collect::<Vec<_>>();
 4940                (providers, tasks)
 4941            })?;
 4942
 4943            let mut actions = Vec::new();
 4944            for (provider, provider_actions) in
 4945                providers.into_iter().zip(future::join_all(tasks).await)
 4946            {
 4947                if let Some(provider_actions) = provider_actions.log_err() {
 4948                    actions.extend(provider_actions.into_iter().map(|action| {
 4949                        AvailableCodeAction {
 4950                            excerpt_id: newest_selection.start.excerpt_id,
 4951                            action,
 4952                            provider: provider.clone(),
 4953                        }
 4954                    }));
 4955                }
 4956            }
 4957
 4958            this.update(cx, |this, cx| {
 4959                this.available_code_actions = if actions.is_empty() {
 4960                    None
 4961                } else {
 4962                    Some((
 4963                        Location {
 4964                            buffer: start_buffer,
 4965                            range: start..end,
 4966                        },
 4967                        actions.into(),
 4968                    ))
 4969                };
 4970                cx.notify();
 4971            })
 4972        }));
 4973        None
 4974    }
 4975
 4976    fn start_inline_blame_timer(&mut self, window: &mut Window, cx: &mut Context<Self>) {
 4977        if let Some(delay) = ProjectSettings::get_global(cx).git.inline_blame_delay() {
 4978            self.show_git_blame_inline = false;
 4979
 4980            self.show_git_blame_inline_delay_task =
 4981                Some(cx.spawn_in(window, async move |this, cx| {
 4982                    cx.background_executor().timer(delay).await;
 4983
 4984                    this.update(cx, |this, cx| {
 4985                        this.show_git_blame_inline = true;
 4986                        cx.notify();
 4987                    })
 4988                    .log_err();
 4989                }));
 4990        }
 4991    }
 4992
 4993    fn refresh_document_highlights(&mut self, cx: &mut Context<Self>) -> Option<()> {
 4994        if self.pending_rename.is_some() {
 4995            return None;
 4996        }
 4997
 4998        let provider = self.semantics_provider.clone()?;
 4999        let buffer = self.buffer.read(cx);
 5000        let newest_selection = self.selections.newest_anchor().clone();
 5001        let cursor_position = newest_selection.head();
 5002        let (cursor_buffer, cursor_buffer_position) =
 5003            buffer.text_anchor_for_position(cursor_position, cx)?;
 5004        let (tail_buffer, _) = buffer.text_anchor_for_position(newest_selection.tail(), cx)?;
 5005        if cursor_buffer != tail_buffer {
 5006            return None;
 5007        }
 5008        let debounce = EditorSettings::get_global(cx).lsp_highlight_debounce;
 5009        self.document_highlights_task = Some(cx.spawn(async move |this, cx| {
 5010            cx.background_executor()
 5011                .timer(Duration::from_millis(debounce))
 5012                .await;
 5013
 5014            let highlights = if let Some(highlights) = cx
 5015                .update(|cx| {
 5016                    provider.document_highlights(&cursor_buffer, cursor_buffer_position, cx)
 5017                })
 5018                .ok()
 5019                .flatten()
 5020            {
 5021                highlights.await.log_err()
 5022            } else {
 5023                None
 5024            };
 5025
 5026            if let Some(highlights) = highlights {
 5027                this.update(cx, |this, cx| {
 5028                    if this.pending_rename.is_some() {
 5029                        return;
 5030                    }
 5031
 5032                    let buffer_id = cursor_position.buffer_id;
 5033                    let buffer = this.buffer.read(cx);
 5034                    if !buffer
 5035                        .text_anchor_for_position(cursor_position, cx)
 5036                        .map_or(false, |(buffer, _)| buffer == cursor_buffer)
 5037                    {
 5038                        return;
 5039                    }
 5040
 5041                    let cursor_buffer_snapshot = cursor_buffer.read(cx);
 5042                    let mut write_ranges = Vec::new();
 5043                    let mut read_ranges = Vec::new();
 5044                    for highlight in highlights {
 5045                        for (excerpt_id, excerpt_range) in
 5046                            buffer.excerpts_for_buffer(cursor_buffer.read(cx).remote_id(), cx)
 5047                        {
 5048                            let start = highlight
 5049                                .range
 5050                                .start
 5051                                .max(&excerpt_range.context.start, cursor_buffer_snapshot);
 5052                            let end = highlight
 5053                                .range
 5054                                .end
 5055                                .min(&excerpt_range.context.end, cursor_buffer_snapshot);
 5056                            if start.cmp(&end, cursor_buffer_snapshot).is_ge() {
 5057                                continue;
 5058                            }
 5059
 5060                            let range = Anchor {
 5061                                buffer_id,
 5062                                excerpt_id,
 5063                                text_anchor: start,
 5064                                diff_base_anchor: None,
 5065                            }..Anchor {
 5066                                buffer_id,
 5067                                excerpt_id,
 5068                                text_anchor: end,
 5069                                diff_base_anchor: None,
 5070                            };
 5071                            if highlight.kind == lsp::DocumentHighlightKind::WRITE {
 5072                                write_ranges.push(range);
 5073                            } else {
 5074                                read_ranges.push(range);
 5075                            }
 5076                        }
 5077                    }
 5078
 5079                    this.highlight_background::<DocumentHighlightRead>(
 5080                        &read_ranges,
 5081                        |theme| theme.editor_document_highlight_read_background,
 5082                        cx,
 5083                    );
 5084                    this.highlight_background::<DocumentHighlightWrite>(
 5085                        &write_ranges,
 5086                        |theme| theme.editor_document_highlight_write_background,
 5087                        cx,
 5088                    );
 5089                    cx.notify();
 5090                })
 5091                .log_err();
 5092            }
 5093        }));
 5094        None
 5095    }
 5096
 5097    pub fn refresh_selected_text_highlights(
 5098        &mut self,
 5099        window: &mut Window,
 5100        cx: &mut Context<Editor>,
 5101    ) {
 5102        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 5103            return;
 5104        }
 5105        self.selection_highlight_task.take();
 5106        if !EditorSettings::get_global(cx).selection_highlight {
 5107            self.clear_background_highlights::<SelectedTextHighlight>(cx);
 5108            return;
 5109        }
 5110        if self.selections.count() != 1 || self.selections.line_mode {
 5111            self.clear_background_highlights::<SelectedTextHighlight>(cx);
 5112            return;
 5113        }
 5114        let selection = self.selections.newest::<Point>(cx);
 5115        if selection.is_empty() || selection.start.row != selection.end.row {
 5116            self.clear_background_highlights::<SelectedTextHighlight>(cx);
 5117            return;
 5118        }
 5119        let debounce = EditorSettings::get_global(cx).selection_highlight_debounce;
 5120        self.selection_highlight_task = Some(cx.spawn_in(window, async move |editor, cx| {
 5121            cx.background_executor()
 5122                .timer(Duration::from_millis(debounce))
 5123                .await;
 5124            let Some(Some(matches_task)) = editor
 5125                .update_in(cx, |editor, _, cx| {
 5126                    if editor.selections.count() != 1 || editor.selections.line_mode {
 5127                        editor.clear_background_highlights::<SelectedTextHighlight>(cx);
 5128                        return None;
 5129                    }
 5130                    let selection = editor.selections.newest::<Point>(cx);
 5131                    if selection.is_empty() || selection.start.row != selection.end.row {
 5132                        editor.clear_background_highlights::<SelectedTextHighlight>(cx);
 5133                        return None;
 5134                    }
 5135                    let buffer = editor.buffer().read(cx).snapshot(cx);
 5136                    let query = buffer.text_for_range(selection.range()).collect::<String>();
 5137                    if query.trim().is_empty() {
 5138                        editor.clear_background_highlights::<SelectedTextHighlight>(cx);
 5139                        return None;
 5140                    }
 5141                    Some(cx.background_spawn(async move {
 5142                        let mut ranges = Vec::new();
 5143                        let selection_anchors = selection.range().to_anchors(&buffer);
 5144                        for range in [buffer.anchor_before(0)..buffer.anchor_after(buffer.len())] {
 5145                            for (search_buffer, search_range, excerpt_id) in
 5146                                buffer.range_to_buffer_ranges(range)
 5147                            {
 5148                                ranges.extend(
 5149                                    project::search::SearchQuery::text(
 5150                                        query.clone(),
 5151                                        false,
 5152                                        false,
 5153                                        false,
 5154                                        Default::default(),
 5155                                        Default::default(),
 5156                                        None,
 5157                                    )
 5158                                    .unwrap()
 5159                                    .search(search_buffer, Some(search_range.clone()))
 5160                                    .await
 5161                                    .into_iter()
 5162                                    .filter_map(
 5163                                        |match_range| {
 5164                                            let start = search_buffer.anchor_after(
 5165                                                search_range.start + match_range.start,
 5166                                            );
 5167                                            let end = search_buffer.anchor_before(
 5168                                                search_range.start + match_range.end,
 5169                                            );
 5170                                            let range = Anchor::range_in_buffer(
 5171                                                excerpt_id,
 5172                                                search_buffer.remote_id(),
 5173                                                start..end,
 5174                                            );
 5175                                            (range != selection_anchors).then_some(range)
 5176                                        },
 5177                                    ),
 5178                                );
 5179                            }
 5180                        }
 5181                        ranges
 5182                    }))
 5183                })
 5184                .log_err()
 5185            else {
 5186                return;
 5187            };
 5188            let matches = matches_task.await;
 5189            editor
 5190                .update_in(cx, |editor, _, cx| {
 5191                    editor.clear_background_highlights::<SelectedTextHighlight>(cx);
 5192                    if !matches.is_empty() {
 5193                        editor.highlight_background::<SelectedTextHighlight>(
 5194                            &matches,
 5195                            |theme| theme.editor_document_highlight_bracket_background,
 5196                            cx,
 5197                        )
 5198                    }
 5199                })
 5200                .log_err();
 5201        }));
 5202    }
 5203
 5204    pub fn refresh_inline_completion(
 5205        &mut self,
 5206        debounce: bool,
 5207        user_requested: bool,
 5208        window: &mut Window,
 5209        cx: &mut Context<Self>,
 5210    ) -> Option<()> {
 5211        let provider = self.edit_prediction_provider()?;
 5212        let cursor = self.selections.newest_anchor().head();
 5213        let (buffer, cursor_buffer_position) =
 5214            self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
 5215
 5216        if !self.edit_predictions_enabled_in_buffer(&buffer, cursor_buffer_position, cx) {
 5217            self.discard_inline_completion(false, cx);
 5218            return None;
 5219        }
 5220
 5221        if !user_requested
 5222            && (!self.should_show_edit_predictions()
 5223                || !self.is_focused(window)
 5224                || buffer.read(cx).is_empty())
 5225        {
 5226            self.discard_inline_completion(false, cx);
 5227            return None;
 5228        }
 5229
 5230        self.update_visible_inline_completion(window, cx);
 5231        provider.refresh(
 5232            self.project.clone(),
 5233            buffer,
 5234            cursor_buffer_position,
 5235            debounce,
 5236            cx,
 5237        );
 5238        Some(())
 5239    }
 5240
 5241    fn show_edit_predictions_in_menu(&self) -> bool {
 5242        match self.edit_prediction_settings {
 5243            EditPredictionSettings::Disabled => false,
 5244            EditPredictionSettings::Enabled { show_in_menu, .. } => show_in_menu,
 5245        }
 5246    }
 5247
 5248    pub fn edit_predictions_enabled(&self) -> bool {
 5249        match self.edit_prediction_settings {
 5250            EditPredictionSettings::Disabled => false,
 5251            EditPredictionSettings::Enabled { .. } => true,
 5252        }
 5253    }
 5254
 5255    fn edit_prediction_requires_modifier(&self) -> bool {
 5256        match self.edit_prediction_settings {
 5257            EditPredictionSettings::Disabled => false,
 5258            EditPredictionSettings::Enabled {
 5259                preview_requires_modifier,
 5260                ..
 5261            } => preview_requires_modifier,
 5262        }
 5263    }
 5264
 5265    pub fn update_edit_prediction_settings(&mut self, cx: &mut Context<Self>) {
 5266        if self.edit_prediction_provider.is_none() {
 5267            self.edit_prediction_settings = EditPredictionSettings::Disabled;
 5268        } else {
 5269            let selection = self.selections.newest_anchor();
 5270            let cursor = selection.head();
 5271
 5272            if let Some((buffer, cursor_buffer_position)) =
 5273                self.buffer.read(cx).text_anchor_for_position(cursor, cx)
 5274            {
 5275                self.edit_prediction_settings =
 5276                    self.edit_prediction_settings_at_position(&buffer, cursor_buffer_position, cx);
 5277            }
 5278        }
 5279    }
 5280
 5281    fn edit_prediction_settings_at_position(
 5282        &self,
 5283        buffer: &Entity<Buffer>,
 5284        buffer_position: language::Anchor,
 5285        cx: &App,
 5286    ) -> EditPredictionSettings {
 5287        if self.mode != EditorMode::Full
 5288            || !self.show_inline_completions_override.unwrap_or(true)
 5289            || self.inline_completions_disabled_in_scope(buffer, buffer_position, cx)
 5290        {
 5291            return EditPredictionSettings::Disabled;
 5292        }
 5293
 5294        let buffer = buffer.read(cx);
 5295
 5296        let file = buffer.file();
 5297
 5298        if !language_settings(buffer.language().map(|l| l.name()), file, cx).show_edit_predictions {
 5299            return EditPredictionSettings::Disabled;
 5300        };
 5301
 5302        let by_provider = matches!(
 5303            self.menu_inline_completions_policy,
 5304            MenuInlineCompletionsPolicy::ByProvider
 5305        );
 5306
 5307        let show_in_menu = by_provider
 5308            && self
 5309                .edit_prediction_provider
 5310                .as_ref()
 5311                .map_or(false, |provider| {
 5312                    provider.provider.show_completions_in_menu()
 5313                });
 5314
 5315        let preview_requires_modifier =
 5316            all_language_settings(file, cx).edit_predictions_mode() == EditPredictionsMode::Subtle;
 5317
 5318        EditPredictionSettings::Enabled {
 5319            show_in_menu,
 5320            preview_requires_modifier,
 5321        }
 5322    }
 5323
 5324    fn should_show_edit_predictions(&self) -> bool {
 5325        self.snippet_stack.is_empty() && self.edit_predictions_enabled()
 5326    }
 5327
 5328    pub fn edit_prediction_preview_is_active(&self) -> bool {
 5329        matches!(
 5330            self.edit_prediction_preview,
 5331            EditPredictionPreview::Active { .. }
 5332        )
 5333    }
 5334
 5335    pub fn edit_predictions_enabled_at_cursor(&self, cx: &App) -> bool {
 5336        let cursor = self.selections.newest_anchor().head();
 5337        if let Some((buffer, cursor_position)) =
 5338            self.buffer.read(cx).text_anchor_for_position(cursor, cx)
 5339        {
 5340            self.edit_predictions_enabled_in_buffer(&buffer, cursor_position, cx)
 5341        } else {
 5342            false
 5343        }
 5344    }
 5345
 5346    fn edit_predictions_enabled_in_buffer(
 5347        &self,
 5348        buffer: &Entity<Buffer>,
 5349        buffer_position: language::Anchor,
 5350        cx: &App,
 5351    ) -> bool {
 5352        maybe!({
 5353            if self.read_only(cx) {
 5354                return Some(false);
 5355            }
 5356            let provider = self.edit_prediction_provider()?;
 5357            if !provider.is_enabled(&buffer, buffer_position, cx) {
 5358                return Some(false);
 5359            }
 5360            let buffer = buffer.read(cx);
 5361            let Some(file) = buffer.file() else {
 5362                return Some(true);
 5363            };
 5364            let settings = all_language_settings(Some(file), cx);
 5365            Some(settings.edit_predictions_enabled_for_file(file, cx))
 5366        })
 5367        .unwrap_or(false)
 5368    }
 5369
 5370    fn cycle_inline_completion(
 5371        &mut self,
 5372        direction: Direction,
 5373        window: &mut Window,
 5374        cx: &mut Context<Self>,
 5375    ) -> Option<()> {
 5376        let provider = self.edit_prediction_provider()?;
 5377        let cursor = self.selections.newest_anchor().head();
 5378        let (buffer, cursor_buffer_position) =
 5379            self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
 5380        if self.inline_completions_hidden_for_vim_mode || !self.should_show_edit_predictions() {
 5381            return None;
 5382        }
 5383
 5384        provider.cycle(buffer, cursor_buffer_position, direction, cx);
 5385        self.update_visible_inline_completion(window, cx);
 5386
 5387        Some(())
 5388    }
 5389
 5390    pub fn show_inline_completion(
 5391        &mut self,
 5392        _: &ShowEditPrediction,
 5393        window: &mut Window,
 5394        cx: &mut Context<Self>,
 5395    ) {
 5396        if !self.has_active_inline_completion() {
 5397            self.refresh_inline_completion(false, true, window, cx);
 5398            return;
 5399        }
 5400
 5401        self.update_visible_inline_completion(window, cx);
 5402    }
 5403
 5404    pub fn display_cursor_names(
 5405        &mut self,
 5406        _: &DisplayCursorNames,
 5407        window: &mut Window,
 5408        cx: &mut Context<Self>,
 5409    ) {
 5410        self.show_cursor_names(window, cx);
 5411    }
 5412
 5413    fn show_cursor_names(&mut self, window: &mut Window, cx: &mut Context<Self>) {
 5414        self.show_cursor_names = true;
 5415        cx.notify();
 5416        cx.spawn_in(window, async move |this, cx| {
 5417            cx.background_executor().timer(CURSORS_VISIBLE_FOR).await;
 5418            this.update(cx, |this, cx| {
 5419                this.show_cursor_names = false;
 5420                cx.notify()
 5421            })
 5422            .ok()
 5423        })
 5424        .detach();
 5425    }
 5426
 5427    pub fn next_edit_prediction(
 5428        &mut self,
 5429        _: &NextEditPrediction,
 5430        window: &mut Window,
 5431        cx: &mut Context<Self>,
 5432    ) {
 5433        if self.has_active_inline_completion() {
 5434            self.cycle_inline_completion(Direction::Next, window, cx);
 5435        } else {
 5436            let is_copilot_disabled = self
 5437                .refresh_inline_completion(false, true, window, cx)
 5438                .is_none();
 5439            if is_copilot_disabled {
 5440                cx.propagate();
 5441            }
 5442        }
 5443    }
 5444
 5445    pub fn previous_edit_prediction(
 5446        &mut self,
 5447        _: &PreviousEditPrediction,
 5448        window: &mut Window,
 5449        cx: &mut Context<Self>,
 5450    ) {
 5451        if self.has_active_inline_completion() {
 5452            self.cycle_inline_completion(Direction::Prev, window, cx);
 5453        } else {
 5454            let is_copilot_disabled = self
 5455                .refresh_inline_completion(false, true, window, cx)
 5456                .is_none();
 5457            if is_copilot_disabled {
 5458                cx.propagate();
 5459            }
 5460        }
 5461    }
 5462
 5463    pub fn accept_edit_prediction(
 5464        &mut self,
 5465        _: &AcceptEditPrediction,
 5466        window: &mut Window,
 5467        cx: &mut Context<Self>,
 5468    ) {
 5469        if self.show_edit_predictions_in_menu() {
 5470            self.hide_context_menu(window, cx);
 5471        }
 5472
 5473        let Some(active_inline_completion) = self.active_inline_completion.as_ref() else {
 5474            return;
 5475        };
 5476
 5477        self.report_inline_completion_event(
 5478            active_inline_completion.completion_id.clone(),
 5479            true,
 5480            cx,
 5481        );
 5482
 5483        match &active_inline_completion.completion {
 5484            InlineCompletion::Move { target, .. } => {
 5485                let target = *target;
 5486
 5487                if let Some(position_map) = &self.last_position_map {
 5488                    if position_map
 5489                        .visible_row_range
 5490                        .contains(&target.to_display_point(&position_map.snapshot).row())
 5491                        || !self.edit_prediction_requires_modifier()
 5492                    {
 5493                        self.unfold_ranges(&[target..target], true, false, cx);
 5494                        // Note that this is also done in vim's handler of the Tab action.
 5495                        self.change_selections(
 5496                            Some(Autoscroll::newest()),
 5497                            window,
 5498                            cx,
 5499                            |selections| {
 5500                                selections.select_anchor_ranges([target..target]);
 5501                            },
 5502                        );
 5503                        self.clear_row_highlights::<EditPredictionPreview>();
 5504
 5505                        self.edit_prediction_preview
 5506                            .set_previous_scroll_position(None);
 5507                    } else {
 5508                        self.edit_prediction_preview
 5509                            .set_previous_scroll_position(Some(
 5510                                position_map.snapshot.scroll_anchor,
 5511                            ));
 5512
 5513                        self.highlight_rows::<EditPredictionPreview>(
 5514                            target..target,
 5515                            cx.theme().colors().editor_highlighted_line_background,
 5516                            true,
 5517                            cx,
 5518                        );
 5519                        self.request_autoscroll(Autoscroll::fit(), cx);
 5520                    }
 5521                }
 5522            }
 5523            InlineCompletion::Edit { edits, .. } => {
 5524                if let Some(provider) = self.edit_prediction_provider() {
 5525                    provider.accept(cx);
 5526                }
 5527
 5528                let snapshot = self.buffer.read(cx).snapshot(cx);
 5529                let last_edit_end = edits.last().unwrap().0.end.bias_right(&snapshot);
 5530
 5531                self.buffer.update(cx, |buffer, cx| {
 5532                    buffer.edit(edits.iter().cloned(), None, cx)
 5533                });
 5534
 5535                self.change_selections(None, window, cx, |s| {
 5536                    s.select_anchor_ranges([last_edit_end..last_edit_end])
 5537                });
 5538
 5539                self.update_visible_inline_completion(window, cx);
 5540                if self.active_inline_completion.is_none() {
 5541                    self.refresh_inline_completion(true, true, window, cx);
 5542                }
 5543
 5544                cx.notify();
 5545            }
 5546        }
 5547
 5548        self.edit_prediction_requires_modifier_in_indent_conflict = false;
 5549    }
 5550
 5551    pub fn accept_partial_inline_completion(
 5552        &mut self,
 5553        _: &AcceptPartialEditPrediction,
 5554        window: &mut Window,
 5555        cx: &mut Context<Self>,
 5556    ) {
 5557        let Some(active_inline_completion) = self.active_inline_completion.as_ref() else {
 5558            return;
 5559        };
 5560        if self.selections.count() != 1 {
 5561            return;
 5562        }
 5563
 5564        self.report_inline_completion_event(
 5565            active_inline_completion.completion_id.clone(),
 5566            true,
 5567            cx,
 5568        );
 5569
 5570        match &active_inline_completion.completion {
 5571            InlineCompletion::Move { target, .. } => {
 5572                let target = *target;
 5573                self.change_selections(Some(Autoscroll::newest()), window, cx, |selections| {
 5574                    selections.select_anchor_ranges([target..target]);
 5575                });
 5576            }
 5577            InlineCompletion::Edit { edits, .. } => {
 5578                // Find an insertion that starts at the cursor position.
 5579                let snapshot = self.buffer.read(cx).snapshot(cx);
 5580                let cursor_offset = self.selections.newest::<usize>(cx).head();
 5581                let insertion = edits.iter().find_map(|(range, text)| {
 5582                    let range = range.to_offset(&snapshot);
 5583                    if range.is_empty() && range.start == cursor_offset {
 5584                        Some(text)
 5585                    } else {
 5586                        None
 5587                    }
 5588                });
 5589
 5590                if let Some(text) = insertion {
 5591                    let mut partial_completion = text
 5592                        .chars()
 5593                        .by_ref()
 5594                        .take_while(|c| c.is_alphabetic())
 5595                        .collect::<String>();
 5596                    if partial_completion.is_empty() {
 5597                        partial_completion = text
 5598                            .chars()
 5599                            .by_ref()
 5600                            .take_while(|c| c.is_whitespace() || !c.is_alphabetic())
 5601                            .collect::<String>();
 5602                    }
 5603
 5604                    cx.emit(EditorEvent::InputHandled {
 5605                        utf16_range_to_replace: None,
 5606                        text: partial_completion.clone().into(),
 5607                    });
 5608
 5609                    self.insert_with_autoindent_mode(&partial_completion, None, window, cx);
 5610
 5611                    self.refresh_inline_completion(true, true, window, cx);
 5612                    cx.notify();
 5613                } else {
 5614                    self.accept_edit_prediction(&Default::default(), window, cx);
 5615                }
 5616            }
 5617        }
 5618    }
 5619
 5620    fn discard_inline_completion(
 5621        &mut self,
 5622        should_report_inline_completion_event: bool,
 5623        cx: &mut Context<Self>,
 5624    ) -> bool {
 5625        if should_report_inline_completion_event {
 5626            let completion_id = self
 5627                .active_inline_completion
 5628                .as_ref()
 5629                .and_then(|active_completion| active_completion.completion_id.clone());
 5630
 5631            self.report_inline_completion_event(completion_id, false, cx);
 5632        }
 5633
 5634        if let Some(provider) = self.edit_prediction_provider() {
 5635            provider.discard(cx);
 5636        }
 5637
 5638        self.take_active_inline_completion(cx)
 5639    }
 5640
 5641    fn report_inline_completion_event(&self, id: Option<SharedString>, accepted: bool, cx: &App) {
 5642        let Some(provider) = self.edit_prediction_provider() else {
 5643            return;
 5644        };
 5645
 5646        let Some((_, buffer, _)) = self
 5647            .buffer
 5648            .read(cx)
 5649            .excerpt_containing(self.selections.newest_anchor().head(), cx)
 5650        else {
 5651            return;
 5652        };
 5653
 5654        let extension = buffer
 5655            .read(cx)
 5656            .file()
 5657            .and_then(|file| Some(file.path().extension()?.to_string_lossy().to_string()));
 5658
 5659        let event_type = match accepted {
 5660            true => "Edit Prediction Accepted",
 5661            false => "Edit Prediction Discarded",
 5662        };
 5663        telemetry::event!(
 5664            event_type,
 5665            provider = provider.name(),
 5666            prediction_id = id,
 5667            suggestion_accepted = accepted,
 5668            file_extension = extension,
 5669        );
 5670    }
 5671
 5672    pub fn has_active_inline_completion(&self) -> bool {
 5673        self.active_inline_completion.is_some()
 5674    }
 5675
 5676    fn take_active_inline_completion(&mut self, cx: &mut Context<Self>) -> bool {
 5677        let Some(active_inline_completion) = self.active_inline_completion.take() else {
 5678            return false;
 5679        };
 5680
 5681        self.splice_inlays(&active_inline_completion.inlay_ids, Default::default(), cx);
 5682        self.clear_highlights::<InlineCompletionHighlight>(cx);
 5683        self.stale_inline_completion_in_menu = Some(active_inline_completion);
 5684        true
 5685    }
 5686
 5687    /// Returns true when we're displaying the edit prediction popover below the cursor
 5688    /// like we are not previewing and the LSP autocomplete menu is visible
 5689    /// or we are in `when_holding_modifier` mode.
 5690    pub fn edit_prediction_visible_in_cursor_popover(&self, has_completion: bool) -> bool {
 5691        if self.edit_prediction_preview_is_active()
 5692            || !self.show_edit_predictions_in_menu()
 5693            || !self.edit_predictions_enabled()
 5694        {
 5695            return false;
 5696        }
 5697
 5698        if self.has_visible_completions_menu() {
 5699            return true;
 5700        }
 5701
 5702        has_completion && self.edit_prediction_requires_modifier()
 5703    }
 5704
 5705    fn handle_modifiers_changed(
 5706        &mut self,
 5707        modifiers: Modifiers,
 5708        position_map: &PositionMap,
 5709        window: &mut Window,
 5710        cx: &mut Context<Self>,
 5711    ) {
 5712        if self.show_edit_predictions_in_menu() {
 5713            self.update_edit_prediction_preview(&modifiers, window, cx);
 5714        }
 5715
 5716        self.update_selection_mode(&modifiers, position_map, window, cx);
 5717
 5718        let mouse_position = window.mouse_position();
 5719        if !position_map.text_hitbox.is_hovered(window) {
 5720            return;
 5721        }
 5722
 5723        self.update_hovered_link(
 5724            position_map.point_for_position(mouse_position),
 5725            &position_map.snapshot,
 5726            modifiers,
 5727            window,
 5728            cx,
 5729        )
 5730    }
 5731
 5732    fn update_selection_mode(
 5733        &mut self,
 5734        modifiers: &Modifiers,
 5735        position_map: &PositionMap,
 5736        window: &mut Window,
 5737        cx: &mut Context<Self>,
 5738    ) {
 5739        if modifiers != &COLUMNAR_SELECTION_MODIFIERS || self.selections.pending.is_none() {
 5740            return;
 5741        }
 5742
 5743        let mouse_position = window.mouse_position();
 5744        let point_for_position = position_map.point_for_position(mouse_position);
 5745        let position = point_for_position.previous_valid;
 5746
 5747        self.select(
 5748            SelectPhase::BeginColumnar {
 5749                position,
 5750                reset: false,
 5751                goal_column: point_for_position.exact_unclipped.column(),
 5752            },
 5753            window,
 5754            cx,
 5755        );
 5756    }
 5757
 5758    fn update_edit_prediction_preview(
 5759        &mut self,
 5760        modifiers: &Modifiers,
 5761        window: &mut Window,
 5762        cx: &mut Context<Self>,
 5763    ) {
 5764        let accept_keybind = self.accept_edit_prediction_keybind(window, cx);
 5765        let Some(accept_keystroke) = accept_keybind.keystroke() else {
 5766            return;
 5767        };
 5768
 5769        if &accept_keystroke.modifiers == modifiers && accept_keystroke.modifiers.modified() {
 5770            if matches!(
 5771                self.edit_prediction_preview,
 5772                EditPredictionPreview::Inactive { .. }
 5773            ) {
 5774                self.edit_prediction_preview = EditPredictionPreview::Active {
 5775                    previous_scroll_position: None,
 5776                    since: Instant::now(),
 5777                };
 5778
 5779                self.update_visible_inline_completion(window, cx);
 5780                cx.notify();
 5781            }
 5782        } else if let EditPredictionPreview::Active {
 5783            previous_scroll_position,
 5784            since,
 5785        } = self.edit_prediction_preview
 5786        {
 5787            if let (Some(previous_scroll_position), Some(position_map)) =
 5788                (previous_scroll_position, self.last_position_map.as_ref())
 5789            {
 5790                self.set_scroll_position(
 5791                    previous_scroll_position
 5792                        .scroll_position(&position_map.snapshot.display_snapshot),
 5793                    window,
 5794                    cx,
 5795                );
 5796            }
 5797
 5798            self.edit_prediction_preview = EditPredictionPreview::Inactive {
 5799                released_too_fast: since.elapsed() < Duration::from_millis(200),
 5800            };
 5801            self.clear_row_highlights::<EditPredictionPreview>();
 5802            self.update_visible_inline_completion(window, cx);
 5803            cx.notify();
 5804        }
 5805    }
 5806
 5807    fn update_visible_inline_completion(
 5808        &mut self,
 5809        _window: &mut Window,
 5810        cx: &mut Context<Self>,
 5811    ) -> Option<()> {
 5812        let selection = self.selections.newest_anchor();
 5813        let cursor = selection.head();
 5814        let multibuffer = self.buffer.read(cx).snapshot(cx);
 5815        let offset_selection = selection.map(|endpoint| endpoint.to_offset(&multibuffer));
 5816        let excerpt_id = cursor.excerpt_id;
 5817
 5818        let show_in_menu = self.show_edit_predictions_in_menu();
 5819        let completions_menu_has_precedence = !show_in_menu
 5820            && (self.context_menu.borrow().is_some()
 5821                || (!self.completion_tasks.is_empty() && !self.has_active_inline_completion()));
 5822
 5823        if completions_menu_has_precedence
 5824            || !offset_selection.is_empty()
 5825            || self
 5826                .active_inline_completion
 5827                .as_ref()
 5828                .map_or(false, |completion| {
 5829                    let invalidation_range = completion.invalidation_range.to_offset(&multibuffer);
 5830                    let invalidation_range = invalidation_range.start..=invalidation_range.end;
 5831                    !invalidation_range.contains(&offset_selection.head())
 5832                })
 5833        {
 5834            self.discard_inline_completion(false, cx);
 5835            return None;
 5836        }
 5837
 5838        self.take_active_inline_completion(cx);
 5839        let Some(provider) = self.edit_prediction_provider() else {
 5840            self.edit_prediction_settings = EditPredictionSettings::Disabled;
 5841            return None;
 5842        };
 5843
 5844        let (buffer, cursor_buffer_position) =
 5845            self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
 5846
 5847        self.edit_prediction_settings =
 5848            self.edit_prediction_settings_at_position(&buffer, cursor_buffer_position, cx);
 5849
 5850        self.edit_prediction_indent_conflict = multibuffer.is_line_whitespace_upto(cursor);
 5851
 5852        if self.edit_prediction_indent_conflict {
 5853            let cursor_point = cursor.to_point(&multibuffer);
 5854
 5855            let indents = multibuffer.suggested_indents(cursor_point.row..cursor_point.row + 1, cx);
 5856
 5857            if let Some((_, indent)) = indents.iter().next() {
 5858                if indent.len == cursor_point.column {
 5859                    self.edit_prediction_indent_conflict = false;
 5860                }
 5861            }
 5862        }
 5863
 5864        let inline_completion = provider.suggest(&buffer, cursor_buffer_position, cx)?;
 5865        let edits = inline_completion
 5866            .edits
 5867            .into_iter()
 5868            .flat_map(|(range, new_text)| {
 5869                let start = multibuffer.anchor_in_excerpt(excerpt_id, range.start)?;
 5870                let end = multibuffer.anchor_in_excerpt(excerpt_id, range.end)?;
 5871                Some((start..end, new_text))
 5872            })
 5873            .collect::<Vec<_>>();
 5874        if edits.is_empty() {
 5875            return None;
 5876        }
 5877
 5878        let first_edit_start = edits.first().unwrap().0.start;
 5879        let first_edit_start_point = first_edit_start.to_point(&multibuffer);
 5880        let edit_start_row = first_edit_start_point.row.saturating_sub(2);
 5881
 5882        let last_edit_end = edits.last().unwrap().0.end;
 5883        let last_edit_end_point = last_edit_end.to_point(&multibuffer);
 5884        let edit_end_row = cmp::min(multibuffer.max_point().row, last_edit_end_point.row + 2);
 5885
 5886        let cursor_row = cursor.to_point(&multibuffer).row;
 5887
 5888        let snapshot = multibuffer.buffer_for_excerpt(excerpt_id).cloned()?;
 5889
 5890        let mut inlay_ids = Vec::new();
 5891        let invalidation_row_range;
 5892        let move_invalidation_row_range = if cursor_row < edit_start_row {
 5893            Some(cursor_row..edit_end_row)
 5894        } else if cursor_row > edit_end_row {
 5895            Some(edit_start_row..cursor_row)
 5896        } else {
 5897            None
 5898        };
 5899        let is_move =
 5900            move_invalidation_row_range.is_some() || self.inline_completions_hidden_for_vim_mode;
 5901        let completion = if is_move {
 5902            invalidation_row_range =
 5903                move_invalidation_row_range.unwrap_or(edit_start_row..edit_end_row);
 5904            let target = first_edit_start;
 5905            InlineCompletion::Move { target, snapshot }
 5906        } else {
 5907            let show_completions_in_buffer = !self.edit_prediction_visible_in_cursor_popover(true)
 5908                && !self.inline_completions_hidden_for_vim_mode;
 5909
 5910            if show_completions_in_buffer {
 5911                if edits
 5912                    .iter()
 5913                    .all(|(range, _)| range.to_offset(&multibuffer).is_empty())
 5914                {
 5915                    let mut inlays = Vec::new();
 5916                    for (range, new_text) in &edits {
 5917                        let inlay = Inlay::inline_completion(
 5918                            post_inc(&mut self.next_inlay_id),
 5919                            range.start,
 5920                            new_text.as_str(),
 5921                        );
 5922                        inlay_ids.push(inlay.id);
 5923                        inlays.push(inlay);
 5924                    }
 5925
 5926                    self.splice_inlays(&[], inlays, cx);
 5927                } else {
 5928                    let background_color = cx.theme().status().deleted_background;
 5929                    self.highlight_text::<InlineCompletionHighlight>(
 5930                        edits.iter().map(|(range, _)| range.clone()).collect(),
 5931                        HighlightStyle {
 5932                            background_color: Some(background_color),
 5933                            ..Default::default()
 5934                        },
 5935                        cx,
 5936                    );
 5937                }
 5938            }
 5939
 5940            invalidation_row_range = edit_start_row..edit_end_row;
 5941
 5942            let display_mode = if all_edits_insertions_or_deletions(&edits, &multibuffer) {
 5943                if provider.show_tab_accept_marker() {
 5944                    EditDisplayMode::TabAccept
 5945                } else {
 5946                    EditDisplayMode::Inline
 5947                }
 5948            } else {
 5949                EditDisplayMode::DiffPopover
 5950            };
 5951
 5952            InlineCompletion::Edit {
 5953                edits,
 5954                edit_preview: inline_completion.edit_preview,
 5955                display_mode,
 5956                snapshot,
 5957            }
 5958        };
 5959
 5960        let invalidation_range = multibuffer
 5961            .anchor_before(Point::new(invalidation_row_range.start, 0))
 5962            ..multibuffer.anchor_after(Point::new(
 5963                invalidation_row_range.end,
 5964                multibuffer.line_len(MultiBufferRow(invalidation_row_range.end)),
 5965            ));
 5966
 5967        self.stale_inline_completion_in_menu = None;
 5968        self.active_inline_completion = Some(InlineCompletionState {
 5969            inlay_ids,
 5970            completion,
 5971            completion_id: inline_completion.id,
 5972            invalidation_range,
 5973        });
 5974
 5975        cx.notify();
 5976
 5977        Some(())
 5978    }
 5979
 5980    pub fn edit_prediction_provider(&self) -> Option<Arc<dyn InlineCompletionProviderHandle>> {
 5981        Some(self.edit_prediction_provider.as_ref()?.provider.clone())
 5982    }
 5983
 5984    fn render_code_actions_indicator(
 5985        &self,
 5986        _style: &EditorStyle,
 5987        row: DisplayRow,
 5988        is_active: bool,
 5989        breakpoint: Option<&(Anchor, Breakpoint)>,
 5990        cx: &mut Context<Self>,
 5991    ) -> Option<IconButton> {
 5992        let color = Color::Muted;
 5993
 5994        let position = breakpoint.as_ref().map(|(anchor, _)| *anchor);
 5995        let bp_kind = Arc::new(
 5996            breakpoint
 5997                .map(|(_, bp)| bp.kind.clone())
 5998                .unwrap_or(BreakpointKind::Standard),
 5999        );
 6000
 6001        if self.available_code_actions.is_some() {
 6002            Some(
 6003                IconButton::new("code_actions_indicator", ui::IconName::Bolt)
 6004                    .shape(ui::IconButtonShape::Square)
 6005                    .icon_size(IconSize::XSmall)
 6006                    .icon_color(color)
 6007                    .toggle_state(is_active)
 6008                    .tooltip({
 6009                        let focus_handle = self.focus_handle.clone();
 6010                        move |window, cx| {
 6011                            Tooltip::for_action_in(
 6012                                "Toggle Code Actions",
 6013                                &ToggleCodeActions {
 6014                                    deployed_from_indicator: None,
 6015                                },
 6016                                &focus_handle,
 6017                                window,
 6018                                cx,
 6019                            )
 6020                        }
 6021                    })
 6022                    .on_click(cx.listener(move |editor, _e, window, cx| {
 6023                        window.focus(&editor.focus_handle(cx));
 6024                        editor.toggle_code_actions(
 6025                            &ToggleCodeActions {
 6026                                deployed_from_indicator: Some(row),
 6027                            },
 6028                            window,
 6029                            cx,
 6030                        );
 6031                    }))
 6032                    .on_right_click(cx.listener(move |editor, event: &ClickEvent, window, cx| {
 6033                        editor.set_breakpoint_context_menu(
 6034                            row,
 6035                            position,
 6036                            bp_kind.clone(),
 6037                            event.down.position,
 6038                            window,
 6039                            cx,
 6040                        );
 6041                    })),
 6042            )
 6043        } else {
 6044            None
 6045        }
 6046    }
 6047
 6048    fn clear_tasks(&mut self) {
 6049        self.tasks.clear()
 6050    }
 6051
 6052    fn insert_tasks(&mut self, key: (BufferId, BufferRow), value: RunnableTasks) {
 6053        if self.tasks.insert(key, value).is_some() {
 6054            // This case should hopefully be rare, but just in case...
 6055            log::error!("multiple different run targets found on a single line, only the last target will be rendered")
 6056        }
 6057    }
 6058
 6059    /// Get all display points of breakpoints that will be rendered within editor
 6060    ///
 6061    /// This function is used to handle overlaps between breakpoints and Code action/runner symbol.
 6062    /// It's also used to set the color of line numbers with breakpoints to the breakpoint color.
 6063    /// TODO debugger: Use this function to color toggle symbols that house nested breakpoints
 6064    fn active_breakpoints(
 6065        &mut self,
 6066        range: Range<DisplayRow>,
 6067        window: &mut Window,
 6068        cx: &mut Context<Self>,
 6069    ) -> HashMap<DisplayRow, (Anchor, Breakpoint)> {
 6070        let mut breakpoint_display_points = HashMap::default();
 6071
 6072        let Some(breakpoint_store) = self.breakpoint_store.clone() else {
 6073            return breakpoint_display_points;
 6074        };
 6075
 6076        let snapshot = self.snapshot(window, cx);
 6077
 6078        let multi_buffer_snapshot = &snapshot.display_snapshot.buffer_snapshot;
 6079        let Some(project) = self.project.as_ref() else {
 6080            return breakpoint_display_points;
 6081        };
 6082
 6083        if let Some(buffer) = self.buffer.read(cx).as_singleton() {
 6084            let buffer_snapshot = buffer.read(cx).snapshot();
 6085
 6086            for breakpoint in
 6087                breakpoint_store
 6088                    .read(cx)
 6089                    .breakpoints(&buffer, None, buffer_snapshot.clone(), cx)
 6090            {
 6091                let point = buffer_snapshot.summary_for_anchor::<Point>(&breakpoint.0);
 6092                let mut anchor = multi_buffer_snapshot.anchor_before(point);
 6093                anchor.text_anchor = breakpoint.0;
 6094
 6095                breakpoint_display_points.insert(
 6096                    snapshot
 6097                        .point_to_display_point(
 6098                            MultiBufferPoint {
 6099                                row: point.row,
 6100                                column: point.column,
 6101                            },
 6102                            Bias::Left,
 6103                        )
 6104                        .row(),
 6105                    (anchor, breakpoint.1.clone()),
 6106                );
 6107            }
 6108
 6109            return breakpoint_display_points;
 6110        }
 6111
 6112        let range = snapshot.display_point_to_point(DisplayPoint::new(range.start, 0), Bias::Left)
 6113            ..snapshot.display_point_to_point(DisplayPoint::new(range.end, 0), Bias::Right);
 6114        for excerpt_boundary in multi_buffer_snapshot.excerpt_boundaries_in_range(range) {
 6115            let info = excerpt_boundary.next;
 6116
 6117            let Some(excerpt_ranges) = multi_buffer_snapshot.range_for_excerpt(info.id) else {
 6118                continue;
 6119            };
 6120
 6121            let Some(buffer) =
 6122                project.read_with(cx, |this, cx| this.buffer_for_id(info.buffer_id, cx))
 6123            else {
 6124                continue;
 6125            };
 6126
 6127            if buffer.read(cx).file().is_none() {
 6128                continue;
 6129            }
 6130            let breakpoints = breakpoint_store.read(cx).breakpoints(
 6131                &buffer,
 6132                Some(info.range.context.start..info.range.context.end),
 6133                info.buffer.clone(),
 6134                cx,
 6135            );
 6136
 6137            // To translate a breakpoint's position within a singular buffer to a multi buffer
 6138            // position we need to know it's excerpt starting location, it's position within
 6139            // the singular buffer, and if that position is within the excerpt's range.
 6140            let excerpt_head = excerpt_ranges
 6141                .start
 6142                .to_display_point(&snapshot.display_snapshot);
 6143
 6144            let buffer_start = info
 6145                .buffer
 6146                .summary_for_anchor::<Point>(&info.range.context.start);
 6147
 6148            for (anchor, breakpoint) in breakpoints {
 6149                let as_row = info.buffer.summary_for_anchor::<Point>(&anchor).row;
 6150                let delta = as_row - buffer_start.row;
 6151
 6152                let position = excerpt_head + DisplayPoint::new(DisplayRow(delta), 0);
 6153
 6154                let anchor = snapshot.display_point_to_anchor(position, Bias::Left);
 6155
 6156                breakpoint_display_points.insert(position.row(), (anchor, breakpoint.clone()));
 6157            }
 6158        }
 6159
 6160        breakpoint_display_points
 6161    }
 6162
 6163    fn breakpoint_context_menu(
 6164        &self,
 6165        anchor: Anchor,
 6166        kind: Arc<BreakpointKind>,
 6167        window: &mut Window,
 6168        cx: &mut Context<Self>,
 6169    ) -> Entity<ui::ContextMenu> {
 6170        let weak_editor = cx.weak_entity();
 6171        let focus_handle = self.focus_handle(cx);
 6172
 6173        let second_entry_msg = if kind.log_message().is_some() {
 6174            "Edit Log Breakpoint"
 6175        } else {
 6176            "Add Log Breakpoint"
 6177        };
 6178
 6179        ui::ContextMenu::build(window, cx, |menu, _, _cx| {
 6180            menu.on_blur_subscription(Subscription::new(|| {}))
 6181                .context(focus_handle)
 6182                .entry("Toggle Breakpoint", None, {
 6183                    let weak_editor = weak_editor.clone();
 6184                    move |_window, cx| {
 6185                        weak_editor
 6186                            .update(cx, |this, cx| {
 6187                                this.edit_breakpoint_at_anchor(
 6188                                    anchor,
 6189                                    BreakpointKind::Standard,
 6190                                    BreakpointEditAction::Toggle,
 6191                                    cx,
 6192                                );
 6193                            })
 6194                            .log_err();
 6195                    }
 6196                })
 6197                .entry(second_entry_msg, None, move |window, cx| {
 6198                    weak_editor
 6199                        .update(cx, |this, cx| {
 6200                            this.add_edit_breakpoint_block(anchor, kind.as_ref(), window, cx);
 6201                        })
 6202                        .log_err();
 6203                })
 6204        })
 6205    }
 6206
 6207    fn render_breakpoint(
 6208        &self,
 6209        position: Anchor,
 6210        row: DisplayRow,
 6211        kind: &BreakpointKind,
 6212        cx: &mut Context<Self>,
 6213    ) -> IconButton {
 6214        let color = if self
 6215            .gutter_breakpoint_indicator
 6216            .is_some_and(|gutter_bp| gutter_bp.row() == row)
 6217        {
 6218            Color::Hint
 6219        } else {
 6220            Color::Debugger
 6221        };
 6222
 6223        let icon = match &kind {
 6224            BreakpointKind::Standard => ui::IconName::DebugBreakpoint,
 6225            BreakpointKind::Log(_) => ui::IconName::DebugLogBreakpoint,
 6226        };
 6227        let arc_kind = Arc::new(kind.clone());
 6228        let arc_kind2 = arc_kind.clone();
 6229
 6230        IconButton::new(("breakpoint_indicator", row.0 as usize), icon)
 6231            .icon_size(IconSize::XSmall)
 6232            .size(ui::ButtonSize::None)
 6233            .icon_color(color)
 6234            .style(ButtonStyle::Transparent)
 6235            .on_click(cx.listener(move |editor, _e, window, cx| {
 6236                window.focus(&editor.focus_handle(cx));
 6237                editor.edit_breakpoint_at_anchor(
 6238                    position,
 6239                    arc_kind.as_ref().clone(),
 6240                    BreakpointEditAction::Toggle,
 6241                    cx,
 6242                );
 6243            }))
 6244            .on_right_click(cx.listener(move |editor, event: &ClickEvent, window, cx| {
 6245                editor.set_breakpoint_context_menu(
 6246                    row,
 6247                    Some(position),
 6248                    arc_kind2.clone(),
 6249                    event.down.position,
 6250                    window,
 6251                    cx,
 6252                );
 6253            }))
 6254    }
 6255
 6256    fn build_tasks_context(
 6257        project: &Entity<Project>,
 6258        buffer: &Entity<Buffer>,
 6259        buffer_row: u32,
 6260        tasks: &Arc<RunnableTasks>,
 6261        cx: &mut Context<Self>,
 6262    ) -> Task<Option<task::TaskContext>> {
 6263        let position = Point::new(buffer_row, tasks.column);
 6264        let range_start = buffer.read(cx).anchor_at(position, Bias::Right);
 6265        let location = Location {
 6266            buffer: buffer.clone(),
 6267            range: range_start..range_start,
 6268        };
 6269        // Fill in the environmental variables from the tree-sitter captures
 6270        let mut captured_task_variables = TaskVariables::default();
 6271        for (capture_name, value) in tasks.extra_variables.clone() {
 6272            captured_task_variables.insert(
 6273                task::VariableName::Custom(capture_name.into()),
 6274                value.clone(),
 6275            );
 6276        }
 6277        project.update(cx, |project, cx| {
 6278            project.task_store().update(cx, |task_store, cx| {
 6279                task_store.task_context_for_location(captured_task_variables, location, cx)
 6280            })
 6281        })
 6282    }
 6283
 6284    pub fn spawn_nearest_task(
 6285        &mut self,
 6286        action: &SpawnNearestTask,
 6287        window: &mut Window,
 6288        cx: &mut Context<Self>,
 6289    ) {
 6290        let Some((workspace, _)) = self.workspace.clone() else {
 6291            return;
 6292        };
 6293        let Some(project) = self.project.clone() else {
 6294            return;
 6295        };
 6296
 6297        // Try to find a closest, enclosing node using tree-sitter that has a
 6298        // task
 6299        let Some((buffer, buffer_row, tasks)) = self
 6300            .find_enclosing_node_task(cx)
 6301            // Or find the task that's closest in row-distance.
 6302            .or_else(|| self.find_closest_task(cx))
 6303        else {
 6304            return;
 6305        };
 6306
 6307        let reveal_strategy = action.reveal;
 6308        let task_context = Self::build_tasks_context(&project, &buffer, buffer_row, &tasks, cx);
 6309        cx.spawn_in(window, async move |_, cx| {
 6310            let context = task_context.await?;
 6311            let (task_source_kind, mut resolved_task) = tasks.resolve(&context).next()?;
 6312
 6313            let resolved = resolved_task.resolved.as_mut()?;
 6314            resolved.reveal = reveal_strategy;
 6315
 6316            workspace
 6317                .update(cx, |workspace, cx| {
 6318                    workspace::tasks::schedule_resolved_task(
 6319                        workspace,
 6320                        task_source_kind,
 6321                        resolved_task,
 6322                        false,
 6323                        cx,
 6324                    );
 6325                })
 6326                .ok()
 6327        })
 6328        .detach();
 6329    }
 6330
 6331    fn find_closest_task(
 6332        &mut self,
 6333        cx: &mut Context<Self>,
 6334    ) -> Option<(Entity<Buffer>, u32, Arc<RunnableTasks>)> {
 6335        let cursor_row = self.selections.newest_adjusted(cx).head().row;
 6336
 6337        let ((buffer_id, row), tasks) = self
 6338            .tasks
 6339            .iter()
 6340            .min_by_key(|((_, row), _)| cursor_row.abs_diff(*row))?;
 6341
 6342        let buffer = self.buffer.read(cx).buffer(*buffer_id)?;
 6343        let tasks = Arc::new(tasks.to_owned());
 6344        Some((buffer, *row, tasks))
 6345    }
 6346
 6347    fn find_enclosing_node_task(
 6348        &mut self,
 6349        cx: &mut Context<Self>,
 6350    ) -> Option<(Entity<Buffer>, u32, Arc<RunnableTasks>)> {
 6351        let snapshot = self.buffer.read(cx).snapshot(cx);
 6352        let offset = self.selections.newest::<usize>(cx).head();
 6353        let excerpt = snapshot.excerpt_containing(offset..offset)?;
 6354        let buffer_id = excerpt.buffer().remote_id();
 6355
 6356        let layer = excerpt.buffer().syntax_layer_at(offset)?;
 6357        let mut cursor = layer.node().walk();
 6358
 6359        while cursor.goto_first_child_for_byte(offset).is_some() {
 6360            if cursor.node().end_byte() == offset {
 6361                cursor.goto_next_sibling();
 6362            }
 6363        }
 6364
 6365        // Ascend to the smallest ancestor that contains the range and has a task.
 6366        loop {
 6367            let node = cursor.node();
 6368            let node_range = node.byte_range();
 6369            let symbol_start_row = excerpt.buffer().offset_to_point(node.start_byte()).row;
 6370
 6371            // Check if this node contains our offset
 6372            if node_range.start <= offset && node_range.end >= offset {
 6373                // If it contains offset, check for task
 6374                if let Some(tasks) = self.tasks.get(&(buffer_id, symbol_start_row)) {
 6375                    let buffer = self.buffer.read(cx).buffer(buffer_id)?;
 6376                    return Some((buffer, symbol_start_row, Arc::new(tasks.to_owned())));
 6377                }
 6378            }
 6379
 6380            if !cursor.goto_parent() {
 6381                break;
 6382            }
 6383        }
 6384        None
 6385    }
 6386
 6387    fn render_run_indicator(
 6388        &self,
 6389        _style: &EditorStyle,
 6390        is_active: bool,
 6391        row: DisplayRow,
 6392        breakpoint: Option<(Anchor, Breakpoint)>,
 6393        cx: &mut Context<Self>,
 6394    ) -> IconButton {
 6395        let color = Color::Muted;
 6396
 6397        let position = breakpoint.as_ref().map(|(anchor, _)| *anchor);
 6398        let bp_kind = Arc::new(
 6399            breakpoint
 6400                .map(|(_, bp)| bp.kind)
 6401                .unwrap_or(BreakpointKind::Standard),
 6402        );
 6403
 6404        IconButton::new(("run_indicator", row.0 as usize), ui::IconName::Play)
 6405            .shape(ui::IconButtonShape::Square)
 6406            .icon_size(IconSize::XSmall)
 6407            .icon_color(color)
 6408            .toggle_state(is_active)
 6409            .on_click(cx.listener(move |editor, _e, window, cx| {
 6410                window.focus(&editor.focus_handle(cx));
 6411                editor.toggle_code_actions(
 6412                    &ToggleCodeActions {
 6413                        deployed_from_indicator: Some(row),
 6414                    },
 6415                    window,
 6416                    cx,
 6417                );
 6418            }))
 6419            .on_right_click(cx.listener(move |editor, event: &ClickEvent, window, cx| {
 6420                editor.set_breakpoint_context_menu(
 6421                    row,
 6422                    position,
 6423                    bp_kind.clone(),
 6424                    event.down.position,
 6425                    window,
 6426                    cx,
 6427                );
 6428            }))
 6429    }
 6430
 6431    pub fn context_menu_visible(&self) -> bool {
 6432        !self.edit_prediction_preview_is_active()
 6433            && self
 6434                .context_menu
 6435                .borrow()
 6436                .as_ref()
 6437                .map_or(false, |menu| menu.visible())
 6438    }
 6439
 6440    fn context_menu_origin(&self) -> Option<ContextMenuOrigin> {
 6441        self.context_menu
 6442            .borrow()
 6443            .as_ref()
 6444            .map(|menu| menu.origin())
 6445    }
 6446
 6447    const EDIT_PREDICTION_POPOVER_PADDING_X: Pixels = Pixels(24.);
 6448    const EDIT_PREDICTION_POPOVER_PADDING_Y: Pixels = Pixels(2.);
 6449
 6450    fn render_edit_prediction_popover(
 6451        &mut self,
 6452        text_bounds: &Bounds<Pixels>,
 6453        content_origin: gpui::Point<Pixels>,
 6454        editor_snapshot: &EditorSnapshot,
 6455        visible_row_range: Range<DisplayRow>,
 6456        scroll_top: f32,
 6457        scroll_bottom: f32,
 6458        line_layouts: &[LineWithInvisibles],
 6459        line_height: Pixels,
 6460        scroll_pixel_position: gpui::Point<Pixels>,
 6461        newest_selection_head: Option<DisplayPoint>,
 6462        editor_width: Pixels,
 6463        style: &EditorStyle,
 6464        window: &mut Window,
 6465        cx: &mut App,
 6466    ) -> Option<(AnyElement, gpui::Point<Pixels>)> {
 6467        let active_inline_completion = self.active_inline_completion.as_ref()?;
 6468
 6469        if self.edit_prediction_visible_in_cursor_popover(true) {
 6470            return None;
 6471        }
 6472
 6473        match &active_inline_completion.completion {
 6474            InlineCompletion::Move { target, .. } => {
 6475                let target_display_point = target.to_display_point(editor_snapshot);
 6476
 6477                if self.edit_prediction_requires_modifier() {
 6478                    if !self.edit_prediction_preview_is_active() {
 6479                        return None;
 6480                    }
 6481
 6482                    self.render_edit_prediction_modifier_jump_popover(
 6483                        text_bounds,
 6484                        content_origin,
 6485                        visible_row_range,
 6486                        line_layouts,
 6487                        line_height,
 6488                        scroll_pixel_position,
 6489                        newest_selection_head,
 6490                        target_display_point,
 6491                        window,
 6492                        cx,
 6493                    )
 6494                } else {
 6495                    self.render_edit_prediction_eager_jump_popover(
 6496                        text_bounds,
 6497                        content_origin,
 6498                        editor_snapshot,
 6499                        visible_row_range,
 6500                        scroll_top,
 6501                        scroll_bottom,
 6502                        line_height,
 6503                        scroll_pixel_position,
 6504                        target_display_point,
 6505                        editor_width,
 6506                        window,
 6507                        cx,
 6508                    )
 6509                }
 6510            }
 6511            InlineCompletion::Edit {
 6512                display_mode: EditDisplayMode::Inline,
 6513                ..
 6514            } => None,
 6515            InlineCompletion::Edit {
 6516                display_mode: EditDisplayMode::TabAccept,
 6517                edits,
 6518                ..
 6519            } => {
 6520                let range = &edits.first()?.0;
 6521                let target_display_point = range.end.to_display_point(editor_snapshot);
 6522
 6523                self.render_edit_prediction_end_of_line_popover(
 6524                    "Accept",
 6525                    editor_snapshot,
 6526                    visible_row_range,
 6527                    target_display_point,
 6528                    line_height,
 6529                    scroll_pixel_position,
 6530                    content_origin,
 6531                    editor_width,
 6532                    window,
 6533                    cx,
 6534                )
 6535            }
 6536            InlineCompletion::Edit {
 6537                edits,
 6538                edit_preview,
 6539                display_mode: EditDisplayMode::DiffPopover,
 6540                snapshot,
 6541            } => self.render_edit_prediction_diff_popover(
 6542                text_bounds,
 6543                content_origin,
 6544                editor_snapshot,
 6545                visible_row_range,
 6546                line_layouts,
 6547                line_height,
 6548                scroll_pixel_position,
 6549                newest_selection_head,
 6550                editor_width,
 6551                style,
 6552                edits,
 6553                edit_preview,
 6554                snapshot,
 6555                window,
 6556                cx,
 6557            ),
 6558        }
 6559    }
 6560
 6561    fn render_edit_prediction_modifier_jump_popover(
 6562        &mut self,
 6563        text_bounds: &Bounds<Pixels>,
 6564        content_origin: gpui::Point<Pixels>,
 6565        visible_row_range: Range<DisplayRow>,
 6566        line_layouts: &[LineWithInvisibles],
 6567        line_height: Pixels,
 6568        scroll_pixel_position: gpui::Point<Pixels>,
 6569        newest_selection_head: Option<DisplayPoint>,
 6570        target_display_point: DisplayPoint,
 6571        window: &mut Window,
 6572        cx: &mut App,
 6573    ) -> Option<(AnyElement, gpui::Point<Pixels>)> {
 6574        let scrolled_content_origin =
 6575            content_origin - gpui::Point::new(scroll_pixel_position.x, Pixels(0.0));
 6576
 6577        const SCROLL_PADDING_Y: Pixels = px(12.);
 6578
 6579        if target_display_point.row() < visible_row_range.start {
 6580            return self.render_edit_prediction_scroll_popover(
 6581                |_| SCROLL_PADDING_Y,
 6582                IconName::ArrowUp,
 6583                visible_row_range,
 6584                line_layouts,
 6585                newest_selection_head,
 6586                scrolled_content_origin,
 6587                window,
 6588                cx,
 6589            );
 6590        } else if target_display_point.row() >= visible_row_range.end {
 6591            return self.render_edit_prediction_scroll_popover(
 6592                |size| text_bounds.size.height - size.height - SCROLL_PADDING_Y,
 6593                IconName::ArrowDown,
 6594                visible_row_range,
 6595                line_layouts,
 6596                newest_selection_head,
 6597                scrolled_content_origin,
 6598                window,
 6599                cx,
 6600            );
 6601        }
 6602
 6603        const POLE_WIDTH: Pixels = px(2.);
 6604
 6605        let line_layout =
 6606            line_layouts.get(target_display_point.row().minus(visible_row_range.start) as usize)?;
 6607        let target_column = target_display_point.column() as usize;
 6608
 6609        let target_x = line_layout.x_for_index(target_column);
 6610        let target_y =
 6611            (target_display_point.row().as_f32() * line_height) - scroll_pixel_position.y;
 6612
 6613        let flag_on_right = target_x < text_bounds.size.width / 2.;
 6614
 6615        let mut border_color = Self::edit_prediction_callout_popover_border_color(cx);
 6616        border_color.l += 0.001;
 6617
 6618        let mut element = v_flex()
 6619            .items_end()
 6620            .when(flag_on_right, |el| el.items_start())
 6621            .child(if flag_on_right {
 6622                self.render_edit_prediction_line_popover("Jump", None, window, cx)?
 6623                    .rounded_bl(px(0.))
 6624                    .rounded_tl(px(0.))
 6625                    .border_l_2()
 6626                    .border_color(border_color)
 6627            } else {
 6628                self.render_edit_prediction_line_popover("Jump", None, window, cx)?
 6629                    .rounded_br(px(0.))
 6630                    .rounded_tr(px(0.))
 6631                    .border_r_2()
 6632                    .border_color(border_color)
 6633            })
 6634            .child(div().w(POLE_WIDTH).bg(border_color).h(line_height))
 6635            .into_any();
 6636
 6637        let size = element.layout_as_root(AvailableSpace::min_size(), window, cx);
 6638
 6639        let mut origin = scrolled_content_origin + point(target_x, target_y)
 6640            - point(
 6641                if flag_on_right {
 6642                    POLE_WIDTH
 6643                } else {
 6644                    size.width - POLE_WIDTH
 6645                },
 6646                size.height - line_height,
 6647            );
 6648
 6649        origin.x = origin.x.max(content_origin.x);
 6650
 6651        element.prepaint_at(origin, window, cx);
 6652
 6653        Some((element, origin))
 6654    }
 6655
 6656    fn render_edit_prediction_scroll_popover(
 6657        &mut self,
 6658        to_y: impl Fn(Size<Pixels>) -> Pixels,
 6659        scroll_icon: IconName,
 6660        visible_row_range: Range<DisplayRow>,
 6661        line_layouts: &[LineWithInvisibles],
 6662        newest_selection_head: Option<DisplayPoint>,
 6663        scrolled_content_origin: gpui::Point<Pixels>,
 6664        window: &mut Window,
 6665        cx: &mut App,
 6666    ) -> Option<(AnyElement, gpui::Point<Pixels>)> {
 6667        let mut element = self
 6668            .render_edit_prediction_line_popover("Scroll", Some(scroll_icon), window, cx)?
 6669            .into_any();
 6670
 6671        let size = element.layout_as_root(AvailableSpace::min_size(), window, cx);
 6672
 6673        let cursor = newest_selection_head?;
 6674        let cursor_row_layout =
 6675            line_layouts.get(cursor.row().minus(visible_row_range.start) as usize)?;
 6676        let cursor_column = cursor.column() as usize;
 6677
 6678        let cursor_character_x = cursor_row_layout.x_for_index(cursor_column);
 6679
 6680        let origin = scrolled_content_origin + point(cursor_character_x, to_y(size));
 6681
 6682        element.prepaint_at(origin, window, cx);
 6683        Some((element, origin))
 6684    }
 6685
 6686    fn render_edit_prediction_eager_jump_popover(
 6687        &mut self,
 6688        text_bounds: &Bounds<Pixels>,
 6689        content_origin: gpui::Point<Pixels>,
 6690        editor_snapshot: &EditorSnapshot,
 6691        visible_row_range: Range<DisplayRow>,
 6692        scroll_top: f32,
 6693        scroll_bottom: f32,
 6694        line_height: Pixels,
 6695        scroll_pixel_position: gpui::Point<Pixels>,
 6696        target_display_point: DisplayPoint,
 6697        editor_width: Pixels,
 6698        window: &mut Window,
 6699        cx: &mut App,
 6700    ) -> Option<(AnyElement, gpui::Point<Pixels>)> {
 6701        if target_display_point.row().as_f32() < scroll_top {
 6702            let mut element = self
 6703                .render_edit_prediction_line_popover(
 6704                    "Jump to Edit",
 6705                    Some(IconName::ArrowUp),
 6706                    window,
 6707                    cx,
 6708                )?
 6709                .into_any();
 6710
 6711            let size = element.layout_as_root(AvailableSpace::min_size(), window, cx);
 6712            let offset = point(
 6713                (text_bounds.size.width - size.width) / 2.,
 6714                Self::EDIT_PREDICTION_POPOVER_PADDING_Y,
 6715            );
 6716
 6717            let origin = text_bounds.origin + offset;
 6718            element.prepaint_at(origin, window, cx);
 6719            Some((element, origin))
 6720        } else if (target_display_point.row().as_f32() + 1.) > scroll_bottom {
 6721            let mut element = self
 6722                .render_edit_prediction_line_popover(
 6723                    "Jump to Edit",
 6724                    Some(IconName::ArrowDown),
 6725                    window,
 6726                    cx,
 6727                )?
 6728                .into_any();
 6729
 6730            let size = element.layout_as_root(AvailableSpace::min_size(), window, cx);
 6731            let offset = point(
 6732                (text_bounds.size.width - size.width) / 2.,
 6733                text_bounds.size.height - size.height - Self::EDIT_PREDICTION_POPOVER_PADDING_Y,
 6734            );
 6735
 6736            let origin = text_bounds.origin + offset;
 6737            element.prepaint_at(origin, window, cx);
 6738            Some((element, origin))
 6739        } else {
 6740            self.render_edit_prediction_end_of_line_popover(
 6741                "Jump to Edit",
 6742                editor_snapshot,
 6743                visible_row_range,
 6744                target_display_point,
 6745                line_height,
 6746                scroll_pixel_position,
 6747                content_origin,
 6748                editor_width,
 6749                window,
 6750                cx,
 6751            )
 6752        }
 6753    }
 6754
 6755    fn render_edit_prediction_end_of_line_popover(
 6756        self: &mut Editor,
 6757        label: &'static str,
 6758        editor_snapshot: &EditorSnapshot,
 6759        visible_row_range: Range<DisplayRow>,
 6760        target_display_point: DisplayPoint,
 6761        line_height: Pixels,
 6762        scroll_pixel_position: gpui::Point<Pixels>,
 6763        content_origin: gpui::Point<Pixels>,
 6764        editor_width: Pixels,
 6765        window: &mut Window,
 6766        cx: &mut App,
 6767    ) -> Option<(AnyElement, gpui::Point<Pixels>)> {
 6768        let target_line_end = DisplayPoint::new(
 6769            target_display_point.row(),
 6770            editor_snapshot.line_len(target_display_point.row()),
 6771        );
 6772
 6773        let mut element = self
 6774            .render_edit_prediction_line_popover(label, None, window, cx)?
 6775            .into_any();
 6776
 6777        let size = element.layout_as_root(AvailableSpace::min_size(), window, cx);
 6778
 6779        let line_origin = self.display_to_pixel_point(target_line_end, editor_snapshot, window)?;
 6780
 6781        let start_point = content_origin - point(scroll_pixel_position.x, Pixels::ZERO);
 6782        let mut origin = start_point
 6783            + line_origin
 6784            + point(Self::EDIT_PREDICTION_POPOVER_PADDING_X, Pixels::ZERO);
 6785        origin.x = origin.x.max(content_origin.x);
 6786
 6787        let max_x = content_origin.x + editor_width - size.width;
 6788
 6789        if origin.x > max_x {
 6790            let offset = line_height + Self::EDIT_PREDICTION_POPOVER_PADDING_Y;
 6791
 6792            let icon = if visible_row_range.contains(&(target_display_point.row() + 2)) {
 6793                origin.y += offset;
 6794                IconName::ArrowUp
 6795            } else {
 6796                origin.y -= offset;
 6797                IconName::ArrowDown
 6798            };
 6799
 6800            element = self
 6801                .render_edit_prediction_line_popover(label, Some(icon), window, cx)?
 6802                .into_any();
 6803
 6804            let size = element.layout_as_root(AvailableSpace::min_size(), window, cx);
 6805
 6806            origin.x = content_origin.x + editor_width - size.width - px(2.);
 6807        }
 6808
 6809        element.prepaint_at(origin, window, cx);
 6810        Some((element, origin))
 6811    }
 6812
 6813    fn render_edit_prediction_diff_popover(
 6814        self: &Editor,
 6815        text_bounds: &Bounds<Pixels>,
 6816        content_origin: gpui::Point<Pixels>,
 6817        editor_snapshot: &EditorSnapshot,
 6818        visible_row_range: Range<DisplayRow>,
 6819        line_layouts: &[LineWithInvisibles],
 6820        line_height: Pixels,
 6821        scroll_pixel_position: gpui::Point<Pixels>,
 6822        newest_selection_head: Option<DisplayPoint>,
 6823        editor_width: Pixels,
 6824        style: &EditorStyle,
 6825        edits: &Vec<(Range<Anchor>, String)>,
 6826        edit_preview: &Option<language::EditPreview>,
 6827        snapshot: &language::BufferSnapshot,
 6828        window: &mut Window,
 6829        cx: &mut App,
 6830    ) -> Option<(AnyElement, gpui::Point<Pixels>)> {
 6831        let edit_start = edits
 6832            .first()
 6833            .unwrap()
 6834            .0
 6835            .start
 6836            .to_display_point(editor_snapshot);
 6837        let edit_end = edits
 6838            .last()
 6839            .unwrap()
 6840            .0
 6841            .end
 6842            .to_display_point(editor_snapshot);
 6843
 6844        let is_visible = visible_row_range.contains(&edit_start.row())
 6845            || visible_row_range.contains(&edit_end.row());
 6846        if !is_visible {
 6847            return None;
 6848        }
 6849
 6850        let highlighted_edits =
 6851            crate::inline_completion_edit_text(&snapshot, edits, edit_preview.as_ref()?, false, cx);
 6852
 6853        let styled_text = highlighted_edits.to_styled_text(&style.text);
 6854        let line_count = highlighted_edits.text.lines().count();
 6855
 6856        const BORDER_WIDTH: Pixels = px(1.);
 6857
 6858        let keybind = self.render_edit_prediction_accept_keybind(window, cx);
 6859        let has_keybind = keybind.is_some();
 6860
 6861        let mut element = h_flex()
 6862            .items_start()
 6863            .child(
 6864                h_flex()
 6865                    .bg(cx.theme().colors().editor_background)
 6866                    .border(BORDER_WIDTH)
 6867                    .shadow_sm()
 6868                    .border_color(cx.theme().colors().border)
 6869                    .rounded_l_lg()
 6870                    .when(line_count > 1, |el| el.rounded_br_lg())
 6871                    .pr_1()
 6872                    .child(styled_text),
 6873            )
 6874            .child(
 6875                h_flex()
 6876                    .h(line_height + BORDER_WIDTH * px(2.))
 6877                    .px_1p5()
 6878                    .gap_1()
 6879                    // Workaround: For some reason, there's a gap if we don't do this
 6880                    .ml(-BORDER_WIDTH)
 6881                    .shadow(smallvec![gpui::BoxShadow {
 6882                        color: gpui::black().opacity(0.05),
 6883                        offset: point(px(1.), px(1.)),
 6884                        blur_radius: px(2.),
 6885                        spread_radius: px(0.),
 6886                    }])
 6887                    .bg(Editor::edit_prediction_line_popover_bg_color(cx))
 6888                    .border(BORDER_WIDTH)
 6889                    .border_color(cx.theme().colors().border)
 6890                    .rounded_r_lg()
 6891                    .id("edit_prediction_diff_popover_keybind")
 6892                    .when(!has_keybind, |el| {
 6893                        let status_colors = cx.theme().status();
 6894
 6895                        el.bg(status_colors.error_background)
 6896                            .border_color(status_colors.error.opacity(0.6))
 6897                            .child(Icon::new(IconName::Info).color(Color::Error))
 6898                            .cursor_default()
 6899                            .hoverable_tooltip(move |_window, cx| {
 6900                                cx.new(|_| MissingEditPredictionKeybindingTooltip).into()
 6901                            })
 6902                    })
 6903                    .children(keybind),
 6904            )
 6905            .into_any();
 6906
 6907        let longest_row =
 6908            editor_snapshot.longest_row_in_range(edit_start.row()..edit_end.row() + 1);
 6909        let longest_line_width = if visible_row_range.contains(&longest_row) {
 6910            line_layouts[(longest_row.0 - visible_row_range.start.0) as usize].width
 6911        } else {
 6912            layout_line(
 6913                longest_row,
 6914                editor_snapshot,
 6915                style,
 6916                editor_width,
 6917                |_| false,
 6918                window,
 6919                cx,
 6920            )
 6921            .width
 6922        };
 6923
 6924        let viewport_bounds =
 6925            Bounds::new(Default::default(), window.viewport_size()).extend(Edges {
 6926                right: -EditorElement::SCROLLBAR_WIDTH,
 6927                ..Default::default()
 6928            });
 6929
 6930        let x_after_longest =
 6931            text_bounds.origin.x + longest_line_width + Self::EDIT_PREDICTION_POPOVER_PADDING_X
 6932                - scroll_pixel_position.x;
 6933
 6934        let element_bounds = element.layout_as_root(AvailableSpace::min_size(), window, cx);
 6935
 6936        // Fully visible if it can be displayed within the window (allow overlapping other
 6937        // panes). However, this is only allowed if the popover starts within text_bounds.
 6938        let can_position_to_the_right = x_after_longest < text_bounds.right()
 6939            && x_after_longest + element_bounds.width < viewport_bounds.right();
 6940
 6941        let mut origin = if can_position_to_the_right {
 6942            point(
 6943                x_after_longest,
 6944                text_bounds.origin.y + edit_start.row().as_f32() * line_height
 6945                    - scroll_pixel_position.y,
 6946            )
 6947        } else {
 6948            let cursor_row = newest_selection_head.map(|head| head.row());
 6949            let above_edit = edit_start
 6950                .row()
 6951                .0
 6952                .checked_sub(line_count as u32)
 6953                .map(DisplayRow);
 6954            let below_edit = Some(edit_end.row() + 1);
 6955            let above_cursor =
 6956                cursor_row.and_then(|row| row.0.checked_sub(line_count as u32).map(DisplayRow));
 6957            let below_cursor = cursor_row.map(|cursor_row| cursor_row + 1);
 6958
 6959            // Place the edit popover adjacent to the edit if there is a location
 6960            // available that is onscreen and does not obscure the cursor. Otherwise,
 6961            // place it adjacent to the cursor.
 6962            let row_target = [above_edit, below_edit, above_cursor, below_cursor]
 6963                .into_iter()
 6964                .flatten()
 6965                .find(|&start_row| {
 6966                    let end_row = start_row + line_count as u32;
 6967                    visible_row_range.contains(&start_row)
 6968                        && visible_row_range.contains(&end_row)
 6969                        && cursor_row.map_or(true, |cursor_row| {
 6970                            !((start_row..end_row).contains(&cursor_row))
 6971                        })
 6972                })?;
 6973
 6974            content_origin
 6975                + point(
 6976                    -scroll_pixel_position.x,
 6977                    row_target.as_f32() * line_height - scroll_pixel_position.y,
 6978                )
 6979        };
 6980
 6981        origin.x -= BORDER_WIDTH;
 6982
 6983        window.defer_draw(element, origin, 1);
 6984
 6985        // Do not return an element, since it will already be drawn due to defer_draw.
 6986        None
 6987    }
 6988
 6989    fn edit_prediction_cursor_popover_height(&self) -> Pixels {
 6990        px(30.)
 6991    }
 6992
 6993    fn current_user_player_color(&self, cx: &mut App) -> PlayerColor {
 6994        if self.read_only(cx) {
 6995            cx.theme().players().read_only()
 6996        } else {
 6997            self.style.as_ref().unwrap().local_player
 6998        }
 6999    }
 7000
 7001    fn render_edit_prediction_accept_keybind(
 7002        &self,
 7003        window: &mut Window,
 7004        cx: &App,
 7005    ) -> Option<AnyElement> {
 7006        let accept_binding = self.accept_edit_prediction_keybind(window, cx);
 7007        let accept_keystroke = accept_binding.keystroke()?;
 7008
 7009        let is_platform_style_mac = PlatformStyle::platform() == PlatformStyle::Mac;
 7010
 7011        let modifiers_color = if accept_keystroke.modifiers == window.modifiers() {
 7012            Color::Accent
 7013        } else {
 7014            Color::Muted
 7015        };
 7016
 7017        h_flex()
 7018            .px_0p5()
 7019            .when(is_platform_style_mac, |parent| parent.gap_0p5())
 7020            .font(theme::ThemeSettings::get_global(cx).buffer_font.clone())
 7021            .text_size(TextSize::XSmall.rems(cx))
 7022            .child(h_flex().children(ui::render_modifiers(
 7023                &accept_keystroke.modifiers,
 7024                PlatformStyle::platform(),
 7025                Some(modifiers_color),
 7026                Some(IconSize::XSmall.rems().into()),
 7027                true,
 7028            )))
 7029            .when(is_platform_style_mac, |parent| {
 7030                parent.child(accept_keystroke.key.clone())
 7031            })
 7032            .when(!is_platform_style_mac, |parent| {
 7033                parent.child(
 7034                    Key::new(
 7035                        util::capitalize(&accept_keystroke.key),
 7036                        Some(Color::Default),
 7037                    )
 7038                    .size(Some(IconSize::XSmall.rems().into())),
 7039                )
 7040            })
 7041            .into_any()
 7042            .into()
 7043    }
 7044
 7045    fn render_edit_prediction_line_popover(
 7046        &self,
 7047        label: impl Into<SharedString>,
 7048        icon: Option<IconName>,
 7049        window: &mut Window,
 7050        cx: &App,
 7051    ) -> Option<Stateful<Div>> {
 7052        let padding_right = if icon.is_some() { px(4.) } else { px(8.) };
 7053
 7054        let keybind = self.render_edit_prediction_accept_keybind(window, cx);
 7055        let has_keybind = keybind.is_some();
 7056
 7057        let result = h_flex()
 7058            .id("ep-line-popover")
 7059            .py_0p5()
 7060            .pl_1()
 7061            .pr(padding_right)
 7062            .gap_1()
 7063            .rounded_md()
 7064            .border_1()
 7065            .bg(Self::edit_prediction_line_popover_bg_color(cx))
 7066            .border_color(Self::edit_prediction_callout_popover_border_color(cx))
 7067            .shadow_sm()
 7068            .when(!has_keybind, |el| {
 7069                let status_colors = cx.theme().status();
 7070
 7071                el.bg(status_colors.error_background)
 7072                    .border_color(status_colors.error.opacity(0.6))
 7073                    .pl_2()
 7074                    .child(Icon::new(IconName::ZedPredictError).color(Color::Error))
 7075                    .cursor_default()
 7076                    .hoverable_tooltip(move |_window, cx| {
 7077                        cx.new(|_| MissingEditPredictionKeybindingTooltip).into()
 7078                    })
 7079            })
 7080            .children(keybind)
 7081            .child(
 7082                Label::new(label)
 7083                    .size(LabelSize::Small)
 7084                    .when(!has_keybind, |el| {
 7085                        el.color(cx.theme().status().error.into()).strikethrough()
 7086                    }),
 7087            )
 7088            .when(!has_keybind, |el| {
 7089                el.child(
 7090                    h_flex().ml_1().child(
 7091                        Icon::new(IconName::Info)
 7092                            .size(IconSize::Small)
 7093                            .color(cx.theme().status().error.into()),
 7094                    ),
 7095                )
 7096            })
 7097            .when_some(icon, |element, icon| {
 7098                element.child(
 7099                    div()
 7100                        .mt(px(1.5))
 7101                        .child(Icon::new(icon).size(IconSize::Small)),
 7102                )
 7103            });
 7104
 7105        Some(result)
 7106    }
 7107
 7108    fn edit_prediction_line_popover_bg_color(cx: &App) -> Hsla {
 7109        let accent_color = cx.theme().colors().text_accent;
 7110        let editor_bg_color = cx.theme().colors().editor_background;
 7111        editor_bg_color.blend(accent_color.opacity(0.1))
 7112    }
 7113
 7114    fn edit_prediction_callout_popover_border_color(cx: &App) -> Hsla {
 7115        let accent_color = cx.theme().colors().text_accent;
 7116        let editor_bg_color = cx.theme().colors().editor_background;
 7117        editor_bg_color.blend(accent_color.opacity(0.6))
 7118    }
 7119
 7120    fn render_edit_prediction_cursor_popover(
 7121        &self,
 7122        min_width: Pixels,
 7123        max_width: Pixels,
 7124        cursor_point: Point,
 7125        style: &EditorStyle,
 7126        accept_keystroke: Option<&gpui::Keystroke>,
 7127        _window: &Window,
 7128        cx: &mut Context<Editor>,
 7129    ) -> Option<AnyElement> {
 7130        let provider = self.edit_prediction_provider.as_ref()?;
 7131
 7132        if provider.provider.needs_terms_acceptance(cx) {
 7133            return Some(
 7134                h_flex()
 7135                    .min_w(min_width)
 7136                    .flex_1()
 7137                    .px_2()
 7138                    .py_1()
 7139                    .gap_3()
 7140                    .elevation_2(cx)
 7141                    .hover(|style| style.bg(cx.theme().colors().element_hover))
 7142                    .id("accept-terms")
 7143                    .cursor_pointer()
 7144                    .on_mouse_down(MouseButton::Left, |_, window, _| window.prevent_default())
 7145                    .on_click(cx.listener(|this, _event, window, cx| {
 7146                        cx.stop_propagation();
 7147                        this.report_editor_event("Edit Prediction Provider ToS Clicked", None, cx);
 7148                        window.dispatch_action(
 7149                            zed_actions::OpenZedPredictOnboarding.boxed_clone(),
 7150                            cx,
 7151                        );
 7152                    }))
 7153                    .child(
 7154                        h_flex()
 7155                            .flex_1()
 7156                            .gap_2()
 7157                            .child(Icon::new(IconName::ZedPredict))
 7158                            .child(Label::new("Accept Terms of Service"))
 7159                            .child(div().w_full())
 7160                            .child(
 7161                                Icon::new(IconName::ArrowUpRight)
 7162                                    .color(Color::Muted)
 7163                                    .size(IconSize::Small),
 7164                            )
 7165                            .into_any_element(),
 7166                    )
 7167                    .into_any(),
 7168            );
 7169        }
 7170
 7171        let is_refreshing = provider.provider.is_refreshing(cx);
 7172
 7173        fn pending_completion_container() -> Div {
 7174            h_flex()
 7175                .h_full()
 7176                .flex_1()
 7177                .gap_2()
 7178                .child(Icon::new(IconName::ZedPredict))
 7179        }
 7180
 7181        let completion = match &self.active_inline_completion {
 7182            Some(prediction) => {
 7183                if !self.has_visible_completions_menu() {
 7184                    const RADIUS: Pixels = px(6.);
 7185                    const BORDER_WIDTH: Pixels = px(1.);
 7186
 7187                    return Some(
 7188                        h_flex()
 7189                            .elevation_2(cx)
 7190                            .border(BORDER_WIDTH)
 7191                            .border_color(cx.theme().colors().border)
 7192                            .when(accept_keystroke.is_none(), |el| {
 7193                                el.border_color(cx.theme().status().error)
 7194                            })
 7195                            .rounded(RADIUS)
 7196                            .rounded_tl(px(0.))
 7197                            .overflow_hidden()
 7198                            .child(div().px_1p5().child(match &prediction.completion {
 7199                                InlineCompletion::Move { target, snapshot } => {
 7200                                    use text::ToPoint as _;
 7201                                    if target.text_anchor.to_point(&snapshot).row > cursor_point.row
 7202                                    {
 7203                                        Icon::new(IconName::ZedPredictDown)
 7204                                    } else {
 7205                                        Icon::new(IconName::ZedPredictUp)
 7206                                    }
 7207                                }
 7208                                InlineCompletion::Edit { .. } => Icon::new(IconName::ZedPredict),
 7209                            }))
 7210                            .child(
 7211                                h_flex()
 7212                                    .gap_1()
 7213                                    .py_1()
 7214                                    .px_2()
 7215                                    .rounded_r(RADIUS - BORDER_WIDTH)
 7216                                    .border_l_1()
 7217                                    .border_color(cx.theme().colors().border)
 7218                                    .bg(Self::edit_prediction_line_popover_bg_color(cx))
 7219                                    .when(self.edit_prediction_preview.released_too_fast(), |el| {
 7220                                        el.child(
 7221                                            Label::new("Hold")
 7222                                                .size(LabelSize::Small)
 7223                                                .when(accept_keystroke.is_none(), |el| {
 7224                                                    el.strikethrough()
 7225                                                })
 7226                                                .line_height_style(LineHeightStyle::UiLabel),
 7227                                        )
 7228                                    })
 7229                                    .id("edit_prediction_cursor_popover_keybind")
 7230                                    .when(accept_keystroke.is_none(), |el| {
 7231                                        let status_colors = cx.theme().status();
 7232
 7233                                        el.bg(status_colors.error_background)
 7234                                            .border_color(status_colors.error.opacity(0.6))
 7235                                            .child(Icon::new(IconName::Info).color(Color::Error))
 7236                                            .cursor_default()
 7237                                            .hoverable_tooltip(move |_window, cx| {
 7238                                                cx.new(|_| MissingEditPredictionKeybindingTooltip)
 7239                                                    .into()
 7240                                            })
 7241                                    })
 7242                                    .when_some(
 7243                                        accept_keystroke.as_ref(),
 7244                                        |el, accept_keystroke| {
 7245                                            el.child(h_flex().children(ui::render_modifiers(
 7246                                                &accept_keystroke.modifiers,
 7247                                                PlatformStyle::platform(),
 7248                                                Some(Color::Default),
 7249                                                Some(IconSize::XSmall.rems().into()),
 7250                                                false,
 7251                                            )))
 7252                                        },
 7253                                    ),
 7254                            )
 7255                            .into_any(),
 7256                    );
 7257                }
 7258
 7259                self.render_edit_prediction_cursor_popover_preview(
 7260                    prediction,
 7261                    cursor_point,
 7262                    style,
 7263                    cx,
 7264                )?
 7265            }
 7266
 7267            None if is_refreshing => match &self.stale_inline_completion_in_menu {
 7268                Some(stale_completion) => self.render_edit_prediction_cursor_popover_preview(
 7269                    stale_completion,
 7270                    cursor_point,
 7271                    style,
 7272                    cx,
 7273                )?,
 7274
 7275                None => {
 7276                    pending_completion_container().child(Label::new("...").size(LabelSize::Small))
 7277                }
 7278            },
 7279
 7280            None => pending_completion_container().child(Label::new("No Prediction")),
 7281        };
 7282
 7283        let completion = if is_refreshing {
 7284            completion
 7285                .with_animation(
 7286                    "loading-completion",
 7287                    Animation::new(Duration::from_secs(2))
 7288                        .repeat()
 7289                        .with_easing(pulsating_between(0.4, 0.8)),
 7290                    |label, delta| label.opacity(delta),
 7291                )
 7292                .into_any_element()
 7293        } else {
 7294            completion.into_any_element()
 7295        };
 7296
 7297        let has_completion = self.active_inline_completion.is_some();
 7298
 7299        let is_platform_style_mac = PlatformStyle::platform() == PlatformStyle::Mac;
 7300        Some(
 7301            h_flex()
 7302                .min_w(min_width)
 7303                .max_w(max_width)
 7304                .flex_1()
 7305                .elevation_2(cx)
 7306                .border_color(cx.theme().colors().border)
 7307                .child(
 7308                    div()
 7309                        .flex_1()
 7310                        .py_1()
 7311                        .px_2()
 7312                        .overflow_hidden()
 7313                        .child(completion),
 7314                )
 7315                .when_some(accept_keystroke, |el, accept_keystroke| {
 7316                    if !accept_keystroke.modifiers.modified() {
 7317                        return el;
 7318                    }
 7319
 7320                    el.child(
 7321                        h_flex()
 7322                            .h_full()
 7323                            .border_l_1()
 7324                            .rounded_r_lg()
 7325                            .border_color(cx.theme().colors().border)
 7326                            .bg(Self::edit_prediction_line_popover_bg_color(cx))
 7327                            .gap_1()
 7328                            .py_1()
 7329                            .px_2()
 7330                            .child(
 7331                                h_flex()
 7332                                    .font(theme::ThemeSettings::get_global(cx).buffer_font.clone())
 7333                                    .when(is_platform_style_mac, |parent| parent.gap_1())
 7334                                    .child(h_flex().children(ui::render_modifiers(
 7335                                        &accept_keystroke.modifiers,
 7336                                        PlatformStyle::platform(),
 7337                                        Some(if !has_completion {
 7338                                            Color::Muted
 7339                                        } else {
 7340                                            Color::Default
 7341                                        }),
 7342                                        None,
 7343                                        false,
 7344                                    ))),
 7345                            )
 7346                            .child(Label::new("Preview").into_any_element())
 7347                            .opacity(if has_completion { 1.0 } else { 0.4 }),
 7348                    )
 7349                })
 7350                .into_any(),
 7351        )
 7352    }
 7353
 7354    fn render_edit_prediction_cursor_popover_preview(
 7355        &self,
 7356        completion: &InlineCompletionState,
 7357        cursor_point: Point,
 7358        style: &EditorStyle,
 7359        cx: &mut Context<Editor>,
 7360    ) -> Option<Div> {
 7361        use text::ToPoint as _;
 7362
 7363        fn render_relative_row_jump(
 7364            prefix: impl Into<String>,
 7365            current_row: u32,
 7366            target_row: u32,
 7367        ) -> Div {
 7368            let (row_diff, arrow) = if target_row < current_row {
 7369                (current_row - target_row, IconName::ArrowUp)
 7370            } else {
 7371                (target_row - current_row, IconName::ArrowDown)
 7372            };
 7373
 7374            h_flex()
 7375                .child(
 7376                    Label::new(format!("{}{}", prefix.into(), row_diff))
 7377                        .color(Color::Muted)
 7378                        .size(LabelSize::Small),
 7379                )
 7380                .child(Icon::new(arrow).color(Color::Muted).size(IconSize::Small))
 7381        }
 7382
 7383        match &completion.completion {
 7384            InlineCompletion::Move {
 7385                target, snapshot, ..
 7386            } => Some(
 7387                h_flex()
 7388                    .px_2()
 7389                    .gap_2()
 7390                    .flex_1()
 7391                    .child(
 7392                        if target.text_anchor.to_point(&snapshot).row > cursor_point.row {
 7393                            Icon::new(IconName::ZedPredictDown)
 7394                        } else {
 7395                            Icon::new(IconName::ZedPredictUp)
 7396                        },
 7397                    )
 7398                    .child(Label::new("Jump to Edit")),
 7399            ),
 7400
 7401            InlineCompletion::Edit {
 7402                edits,
 7403                edit_preview,
 7404                snapshot,
 7405                display_mode: _,
 7406            } => {
 7407                let first_edit_row = edits.first()?.0.start.text_anchor.to_point(&snapshot).row;
 7408
 7409                let (highlighted_edits, has_more_lines) = crate::inline_completion_edit_text(
 7410                    &snapshot,
 7411                    &edits,
 7412                    edit_preview.as_ref()?,
 7413                    true,
 7414                    cx,
 7415                )
 7416                .first_line_preview();
 7417
 7418                let styled_text = gpui::StyledText::new(highlighted_edits.text)
 7419                    .with_default_highlights(&style.text, highlighted_edits.highlights);
 7420
 7421                let preview = h_flex()
 7422                    .gap_1()
 7423                    .min_w_16()
 7424                    .child(styled_text)
 7425                    .when(has_more_lines, |parent| parent.child(""));
 7426
 7427                let left = if first_edit_row != cursor_point.row {
 7428                    render_relative_row_jump("", cursor_point.row, first_edit_row)
 7429                        .into_any_element()
 7430                } else {
 7431                    Icon::new(IconName::ZedPredict).into_any_element()
 7432                };
 7433
 7434                Some(
 7435                    h_flex()
 7436                        .h_full()
 7437                        .flex_1()
 7438                        .gap_2()
 7439                        .pr_1()
 7440                        .overflow_x_hidden()
 7441                        .font(theme::ThemeSettings::get_global(cx).buffer_font.clone())
 7442                        .child(left)
 7443                        .child(preview),
 7444                )
 7445            }
 7446        }
 7447    }
 7448
 7449    fn render_context_menu(
 7450        &self,
 7451        style: &EditorStyle,
 7452        max_height_in_lines: u32,
 7453        y_flipped: bool,
 7454        window: &mut Window,
 7455        cx: &mut Context<Editor>,
 7456    ) -> Option<AnyElement> {
 7457        let menu = self.context_menu.borrow();
 7458        let menu = menu.as_ref()?;
 7459        if !menu.visible() {
 7460            return None;
 7461        };
 7462        Some(menu.render(style, max_height_in_lines, y_flipped, window, cx))
 7463    }
 7464
 7465    fn render_context_menu_aside(
 7466        &mut self,
 7467        max_size: Size<Pixels>,
 7468        window: &mut Window,
 7469        cx: &mut Context<Editor>,
 7470    ) -> Option<AnyElement> {
 7471        self.context_menu.borrow_mut().as_mut().and_then(|menu| {
 7472            if menu.visible() {
 7473                menu.render_aside(self, max_size, window, cx)
 7474            } else {
 7475                None
 7476            }
 7477        })
 7478    }
 7479
 7480    fn hide_context_menu(
 7481        &mut self,
 7482        window: &mut Window,
 7483        cx: &mut Context<Self>,
 7484    ) -> Option<CodeContextMenu> {
 7485        cx.notify();
 7486        self.completion_tasks.clear();
 7487        let context_menu = self.context_menu.borrow_mut().take();
 7488        self.stale_inline_completion_in_menu.take();
 7489        self.update_visible_inline_completion(window, cx);
 7490        context_menu
 7491    }
 7492
 7493    fn show_snippet_choices(
 7494        &mut self,
 7495        choices: &Vec<String>,
 7496        selection: Range<Anchor>,
 7497        cx: &mut Context<Self>,
 7498    ) {
 7499        if selection.start.buffer_id.is_none() {
 7500            return;
 7501        }
 7502        let buffer_id = selection.start.buffer_id.unwrap();
 7503        let buffer = self.buffer().read(cx).buffer(buffer_id);
 7504        let id = post_inc(&mut self.next_completion_id);
 7505
 7506        if let Some(buffer) = buffer {
 7507            *self.context_menu.borrow_mut() = Some(CodeContextMenu::Completions(
 7508                CompletionsMenu::new_snippet_choices(id, true, choices, selection, buffer),
 7509            ));
 7510        }
 7511    }
 7512
 7513    pub fn insert_snippet(
 7514        &mut self,
 7515        insertion_ranges: &[Range<usize>],
 7516        snippet: Snippet,
 7517        window: &mut Window,
 7518        cx: &mut Context<Self>,
 7519    ) -> Result<()> {
 7520        struct Tabstop<T> {
 7521            is_end_tabstop: bool,
 7522            ranges: Vec<Range<T>>,
 7523            choices: Option<Vec<String>>,
 7524        }
 7525
 7526        let tabstops = self.buffer.update(cx, |buffer, cx| {
 7527            let snippet_text: Arc<str> = snippet.text.clone().into();
 7528            buffer.edit(
 7529                insertion_ranges
 7530                    .iter()
 7531                    .cloned()
 7532                    .map(|range| (range, snippet_text.clone())),
 7533                Some(AutoindentMode::EachLine),
 7534                cx,
 7535            );
 7536
 7537            let snapshot = &*buffer.read(cx);
 7538            let snippet = &snippet;
 7539            snippet
 7540                .tabstops
 7541                .iter()
 7542                .map(|tabstop| {
 7543                    let is_end_tabstop = tabstop.ranges.first().map_or(false, |tabstop| {
 7544                        tabstop.is_empty() && tabstop.start == snippet.text.len() as isize
 7545                    });
 7546                    let mut tabstop_ranges = tabstop
 7547                        .ranges
 7548                        .iter()
 7549                        .flat_map(|tabstop_range| {
 7550                            let mut delta = 0_isize;
 7551                            insertion_ranges.iter().map(move |insertion_range| {
 7552                                let insertion_start = insertion_range.start as isize + delta;
 7553                                delta +=
 7554                                    snippet.text.len() as isize - insertion_range.len() as isize;
 7555
 7556                                let start = ((insertion_start + tabstop_range.start) as usize)
 7557                                    .min(snapshot.len());
 7558                                let end = ((insertion_start + tabstop_range.end) as usize)
 7559                                    .min(snapshot.len());
 7560                                snapshot.anchor_before(start)..snapshot.anchor_after(end)
 7561                            })
 7562                        })
 7563                        .collect::<Vec<_>>();
 7564                    tabstop_ranges.sort_unstable_by(|a, b| a.start.cmp(&b.start, snapshot));
 7565
 7566                    Tabstop {
 7567                        is_end_tabstop,
 7568                        ranges: tabstop_ranges,
 7569                        choices: tabstop.choices.clone(),
 7570                    }
 7571                })
 7572                .collect::<Vec<_>>()
 7573        });
 7574        if let Some(tabstop) = tabstops.first() {
 7575            self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 7576                s.select_ranges(tabstop.ranges.iter().cloned());
 7577            });
 7578
 7579            if let Some(choices) = &tabstop.choices {
 7580                if let Some(selection) = tabstop.ranges.first() {
 7581                    self.show_snippet_choices(choices, selection.clone(), cx)
 7582                }
 7583            }
 7584
 7585            // If we're already at the last tabstop and it's at the end of the snippet,
 7586            // we're done, we don't need to keep the state around.
 7587            if !tabstop.is_end_tabstop {
 7588                let choices = tabstops
 7589                    .iter()
 7590                    .map(|tabstop| tabstop.choices.clone())
 7591                    .collect();
 7592
 7593                let ranges = tabstops
 7594                    .into_iter()
 7595                    .map(|tabstop| tabstop.ranges)
 7596                    .collect::<Vec<_>>();
 7597
 7598                self.snippet_stack.push(SnippetState {
 7599                    active_index: 0,
 7600                    ranges,
 7601                    choices,
 7602                });
 7603            }
 7604
 7605            // Check whether the just-entered snippet ends with an auto-closable bracket.
 7606            if self.autoclose_regions.is_empty() {
 7607                let snapshot = self.buffer.read(cx).snapshot(cx);
 7608                for selection in &mut self.selections.all::<Point>(cx) {
 7609                    let selection_head = selection.head();
 7610                    let Some(scope) = snapshot.language_scope_at(selection_head) else {
 7611                        continue;
 7612                    };
 7613
 7614                    let mut bracket_pair = None;
 7615                    let next_chars = snapshot.chars_at(selection_head).collect::<String>();
 7616                    let prev_chars = snapshot
 7617                        .reversed_chars_at(selection_head)
 7618                        .collect::<String>();
 7619                    for (pair, enabled) in scope.brackets() {
 7620                        if enabled
 7621                            && pair.close
 7622                            && prev_chars.starts_with(pair.start.as_str())
 7623                            && next_chars.starts_with(pair.end.as_str())
 7624                        {
 7625                            bracket_pair = Some(pair.clone());
 7626                            break;
 7627                        }
 7628                    }
 7629                    if let Some(pair) = bracket_pair {
 7630                        let start = snapshot.anchor_after(selection_head);
 7631                        let end = snapshot.anchor_after(selection_head);
 7632                        self.autoclose_regions.push(AutocloseRegion {
 7633                            selection_id: selection.id,
 7634                            range: start..end,
 7635                            pair,
 7636                        });
 7637                    }
 7638                }
 7639            }
 7640        }
 7641        Ok(())
 7642    }
 7643
 7644    pub fn move_to_next_snippet_tabstop(
 7645        &mut self,
 7646        window: &mut Window,
 7647        cx: &mut Context<Self>,
 7648    ) -> bool {
 7649        self.move_to_snippet_tabstop(Bias::Right, window, cx)
 7650    }
 7651
 7652    pub fn move_to_prev_snippet_tabstop(
 7653        &mut self,
 7654        window: &mut Window,
 7655        cx: &mut Context<Self>,
 7656    ) -> bool {
 7657        self.move_to_snippet_tabstop(Bias::Left, window, cx)
 7658    }
 7659
 7660    pub fn move_to_snippet_tabstop(
 7661        &mut self,
 7662        bias: Bias,
 7663        window: &mut Window,
 7664        cx: &mut Context<Self>,
 7665    ) -> bool {
 7666        if let Some(mut snippet) = self.snippet_stack.pop() {
 7667            match bias {
 7668                Bias::Left => {
 7669                    if snippet.active_index > 0 {
 7670                        snippet.active_index -= 1;
 7671                    } else {
 7672                        self.snippet_stack.push(snippet);
 7673                        return false;
 7674                    }
 7675                }
 7676                Bias::Right => {
 7677                    if snippet.active_index + 1 < snippet.ranges.len() {
 7678                        snippet.active_index += 1;
 7679                    } else {
 7680                        self.snippet_stack.push(snippet);
 7681                        return false;
 7682                    }
 7683                }
 7684            }
 7685            if let Some(current_ranges) = snippet.ranges.get(snippet.active_index) {
 7686                self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 7687                    s.select_anchor_ranges(current_ranges.iter().cloned())
 7688                });
 7689
 7690                if let Some(choices) = &snippet.choices[snippet.active_index] {
 7691                    if let Some(selection) = current_ranges.first() {
 7692                        self.show_snippet_choices(&choices, selection.clone(), cx);
 7693                    }
 7694                }
 7695
 7696                // If snippet state is not at the last tabstop, push it back on the stack
 7697                if snippet.active_index + 1 < snippet.ranges.len() {
 7698                    self.snippet_stack.push(snippet);
 7699                }
 7700                return true;
 7701            }
 7702        }
 7703
 7704        false
 7705    }
 7706
 7707    pub fn clear(&mut self, window: &mut Window, cx: &mut Context<Self>) {
 7708        self.transact(window, cx, |this, window, cx| {
 7709            this.select_all(&SelectAll, window, cx);
 7710            this.insert("", window, cx);
 7711        });
 7712    }
 7713
 7714    pub fn backspace(&mut self, _: &Backspace, window: &mut Window, cx: &mut Context<Self>) {
 7715        self.transact(window, cx, |this, window, cx| {
 7716            this.select_autoclose_pair(window, cx);
 7717            let mut linked_ranges = HashMap::<_, Vec<_>>::default();
 7718            if !this.linked_edit_ranges.is_empty() {
 7719                let selections = this.selections.all::<MultiBufferPoint>(cx);
 7720                let snapshot = this.buffer.read(cx).snapshot(cx);
 7721
 7722                for selection in selections.iter() {
 7723                    let selection_start = snapshot.anchor_before(selection.start).text_anchor;
 7724                    let selection_end = snapshot.anchor_after(selection.end).text_anchor;
 7725                    if selection_start.buffer_id != selection_end.buffer_id {
 7726                        continue;
 7727                    }
 7728                    if let Some(ranges) =
 7729                        this.linked_editing_ranges_for(selection_start..selection_end, cx)
 7730                    {
 7731                        for (buffer, entries) in ranges {
 7732                            linked_ranges.entry(buffer).or_default().extend(entries);
 7733                        }
 7734                    }
 7735                }
 7736            }
 7737
 7738            let mut selections = this.selections.all::<MultiBufferPoint>(cx);
 7739            if !this.selections.line_mode {
 7740                let display_map = this.display_map.update(cx, |map, cx| map.snapshot(cx));
 7741                for selection in &mut selections {
 7742                    if selection.is_empty() {
 7743                        let old_head = selection.head();
 7744                        let mut new_head =
 7745                            movement::left(&display_map, old_head.to_display_point(&display_map))
 7746                                .to_point(&display_map);
 7747                        if let Some((buffer, line_buffer_range)) = display_map
 7748                            .buffer_snapshot
 7749                            .buffer_line_for_row(MultiBufferRow(old_head.row))
 7750                        {
 7751                            let indent_size =
 7752                                buffer.indent_size_for_line(line_buffer_range.start.row);
 7753                            let indent_len = match indent_size.kind {
 7754                                IndentKind::Space => {
 7755                                    buffer.settings_at(line_buffer_range.start, cx).tab_size
 7756                                }
 7757                                IndentKind::Tab => NonZeroU32::new(1).unwrap(),
 7758                            };
 7759                            if old_head.column <= indent_size.len && old_head.column > 0 {
 7760                                let indent_len = indent_len.get();
 7761                                new_head = cmp::min(
 7762                                    new_head,
 7763                                    MultiBufferPoint::new(
 7764                                        old_head.row,
 7765                                        ((old_head.column - 1) / indent_len) * indent_len,
 7766                                    ),
 7767                                );
 7768                            }
 7769                        }
 7770
 7771                        selection.set_head(new_head, SelectionGoal::None);
 7772                    }
 7773                }
 7774            }
 7775
 7776            this.signature_help_state.set_backspace_pressed(true);
 7777            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 7778                s.select(selections)
 7779            });
 7780            this.insert("", window, cx);
 7781            let empty_str: Arc<str> = Arc::from("");
 7782            for (buffer, edits) in linked_ranges {
 7783                let snapshot = buffer.read(cx).snapshot();
 7784                use text::ToPoint as TP;
 7785
 7786                let edits = edits
 7787                    .into_iter()
 7788                    .map(|range| {
 7789                        let end_point = TP::to_point(&range.end, &snapshot);
 7790                        let mut start_point = TP::to_point(&range.start, &snapshot);
 7791
 7792                        if end_point == start_point {
 7793                            let offset = text::ToOffset::to_offset(&range.start, &snapshot)
 7794                                .saturating_sub(1);
 7795                            start_point =
 7796                                snapshot.clip_point(TP::to_point(&offset, &snapshot), Bias::Left);
 7797                        };
 7798
 7799                        (start_point..end_point, empty_str.clone())
 7800                    })
 7801                    .sorted_by_key(|(range, _)| range.start)
 7802                    .collect::<Vec<_>>();
 7803                buffer.update(cx, |this, cx| {
 7804                    this.edit(edits, None, cx);
 7805                })
 7806            }
 7807            this.refresh_inline_completion(true, false, window, cx);
 7808            linked_editing_ranges::refresh_linked_ranges(this, window, cx);
 7809        });
 7810    }
 7811
 7812    pub fn delete(&mut self, _: &Delete, window: &mut Window, cx: &mut Context<Self>) {
 7813        self.transact(window, cx, |this, window, cx| {
 7814            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 7815                let line_mode = s.line_mode;
 7816                s.move_with(|map, selection| {
 7817                    if selection.is_empty() && !line_mode {
 7818                        let cursor = movement::right(map, selection.head());
 7819                        selection.end = cursor;
 7820                        selection.reversed = true;
 7821                        selection.goal = SelectionGoal::None;
 7822                    }
 7823                })
 7824            });
 7825            this.insert("", window, cx);
 7826            this.refresh_inline_completion(true, false, window, cx);
 7827        });
 7828    }
 7829
 7830    pub fn backtab(&mut self, _: &Backtab, window: &mut Window, cx: &mut Context<Self>) {
 7831        if self.move_to_prev_snippet_tabstop(window, cx) {
 7832            return;
 7833        }
 7834
 7835        self.outdent(&Outdent, window, cx);
 7836    }
 7837
 7838    pub fn tab(&mut self, _: &Tab, window: &mut Window, cx: &mut Context<Self>) {
 7839        if self.move_to_next_snippet_tabstop(window, cx) || self.read_only(cx) {
 7840            return;
 7841        }
 7842
 7843        let mut selections = self.selections.all_adjusted(cx);
 7844        let buffer = self.buffer.read(cx);
 7845        let snapshot = buffer.snapshot(cx);
 7846        let rows_iter = selections.iter().map(|s| s.head().row);
 7847        let suggested_indents = snapshot.suggested_indents(rows_iter, cx);
 7848
 7849        let mut edits = Vec::new();
 7850        let mut prev_edited_row = 0;
 7851        let mut row_delta = 0;
 7852        for selection in &mut selections {
 7853            if selection.start.row != prev_edited_row {
 7854                row_delta = 0;
 7855            }
 7856            prev_edited_row = selection.end.row;
 7857
 7858            // If the selection is non-empty, then increase the indentation of the selected lines.
 7859            if !selection.is_empty() {
 7860                row_delta =
 7861                    Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
 7862                continue;
 7863            }
 7864
 7865            // If the selection is empty and the cursor is in the leading whitespace before the
 7866            // suggested indentation, then auto-indent the line.
 7867            let cursor = selection.head();
 7868            let current_indent = snapshot.indent_size_for_line(MultiBufferRow(cursor.row));
 7869            if let Some(suggested_indent) =
 7870                suggested_indents.get(&MultiBufferRow(cursor.row)).copied()
 7871            {
 7872                if cursor.column < suggested_indent.len
 7873                    && cursor.column <= current_indent.len
 7874                    && current_indent.len <= suggested_indent.len
 7875                {
 7876                    selection.start = Point::new(cursor.row, suggested_indent.len);
 7877                    selection.end = selection.start;
 7878                    if row_delta == 0 {
 7879                        edits.extend(Buffer::edit_for_indent_size_adjustment(
 7880                            cursor.row,
 7881                            current_indent,
 7882                            suggested_indent,
 7883                        ));
 7884                        row_delta = suggested_indent.len - current_indent.len;
 7885                    }
 7886                    continue;
 7887                }
 7888            }
 7889
 7890            // Otherwise, insert a hard or soft tab.
 7891            let settings = buffer.language_settings_at(cursor, cx);
 7892            let tab_size = if settings.hard_tabs {
 7893                IndentSize::tab()
 7894            } else {
 7895                let tab_size = settings.tab_size.get();
 7896                let char_column = snapshot
 7897                    .text_for_range(Point::new(cursor.row, 0)..cursor)
 7898                    .flat_map(str::chars)
 7899                    .count()
 7900                    + row_delta as usize;
 7901                let chars_to_next_tab_stop = tab_size - (char_column as u32 % tab_size);
 7902                IndentSize::spaces(chars_to_next_tab_stop)
 7903            };
 7904            selection.start = Point::new(cursor.row, cursor.column + row_delta + tab_size.len);
 7905            selection.end = selection.start;
 7906            edits.push((cursor..cursor, tab_size.chars().collect::<String>()));
 7907            row_delta += tab_size.len;
 7908        }
 7909
 7910        self.transact(window, cx, |this, window, cx| {
 7911            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
 7912            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 7913                s.select(selections)
 7914            });
 7915            this.refresh_inline_completion(true, false, window, cx);
 7916        });
 7917    }
 7918
 7919    pub fn indent(&mut self, _: &Indent, window: &mut Window, cx: &mut Context<Self>) {
 7920        if self.read_only(cx) {
 7921            return;
 7922        }
 7923        let mut selections = self.selections.all::<Point>(cx);
 7924        let mut prev_edited_row = 0;
 7925        let mut row_delta = 0;
 7926        let mut edits = Vec::new();
 7927        let buffer = self.buffer.read(cx);
 7928        let snapshot = buffer.snapshot(cx);
 7929        for selection in &mut selections {
 7930            if selection.start.row != prev_edited_row {
 7931                row_delta = 0;
 7932            }
 7933            prev_edited_row = selection.end.row;
 7934
 7935            row_delta =
 7936                Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
 7937        }
 7938
 7939        self.transact(window, cx, |this, window, cx| {
 7940            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
 7941            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 7942                s.select(selections)
 7943            });
 7944        });
 7945    }
 7946
 7947    fn indent_selection(
 7948        buffer: &MultiBuffer,
 7949        snapshot: &MultiBufferSnapshot,
 7950        selection: &mut Selection<Point>,
 7951        edits: &mut Vec<(Range<Point>, String)>,
 7952        delta_for_start_row: u32,
 7953        cx: &App,
 7954    ) -> u32 {
 7955        let settings = buffer.language_settings_at(selection.start, cx);
 7956        let tab_size = settings.tab_size.get();
 7957        let indent_kind = if settings.hard_tabs {
 7958            IndentKind::Tab
 7959        } else {
 7960            IndentKind::Space
 7961        };
 7962        let mut start_row = selection.start.row;
 7963        let mut end_row = selection.end.row + 1;
 7964
 7965        // If a selection ends at the beginning of a line, don't indent
 7966        // that last line.
 7967        if selection.end.column == 0 && selection.end.row > selection.start.row {
 7968            end_row -= 1;
 7969        }
 7970
 7971        // Avoid re-indenting a row that has already been indented by a
 7972        // previous selection, but still update this selection's column
 7973        // to reflect that indentation.
 7974        if delta_for_start_row > 0 {
 7975            start_row += 1;
 7976            selection.start.column += delta_for_start_row;
 7977            if selection.end.row == selection.start.row {
 7978                selection.end.column += delta_for_start_row;
 7979            }
 7980        }
 7981
 7982        let mut delta_for_end_row = 0;
 7983        let has_multiple_rows = start_row + 1 != end_row;
 7984        for row in start_row..end_row {
 7985            let current_indent = snapshot.indent_size_for_line(MultiBufferRow(row));
 7986            let indent_delta = match (current_indent.kind, indent_kind) {
 7987                (IndentKind::Space, IndentKind::Space) => {
 7988                    let columns_to_next_tab_stop = tab_size - (current_indent.len % tab_size);
 7989                    IndentSize::spaces(columns_to_next_tab_stop)
 7990                }
 7991                (IndentKind::Tab, IndentKind::Space) => IndentSize::spaces(tab_size),
 7992                (_, IndentKind::Tab) => IndentSize::tab(),
 7993            };
 7994
 7995            let start = if has_multiple_rows || current_indent.len < selection.start.column {
 7996                0
 7997            } else {
 7998                selection.start.column
 7999            };
 8000            let row_start = Point::new(row, start);
 8001            edits.push((
 8002                row_start..row_start,
 8003                indent_delta.chars().collect::<String>(),
 8004            ));
 8005
 8006            // Update this selection's endpoints to reflect the indentation.
 8007            if row == selection.start.row {
 8008                selection.start.column += indent_delta.len;
 8009            }
 8010            if row == selection.end.row {
 8011                selection.end.column += indent_delta.len;
 8012                delta_for_end_row = indent_delta.len;
 8013            }
 8014        }
 8015
 8016        if selection.start.row == selection.end.row {
 8017            delta_for_start_row + delta_for_end_row
 8018        } else {
 8019            delta_for_end_row
 8020        }
 8021    }
 8022
 8023    pub fn outdent(&mut self, _: &Outdent, window: &mut Window, cx: &mut Context<Self>) {
 8024        if self.read_only(cx) {
 8025            return;
 8026        }
 8027        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8028        let selections = self.selections.all::<Point>(cx);
 8029        let mut deletion_ranges = Vec::new();
 8030        let mut last_outdent = None;
 8031        {
 8032            let buffer = self.buffer.read(cx);
 8033            let snapshot = buffer.snapshot(cx);
 8034            for selection in &selections {
 8035                let settings = buffer.language_settings_at(selection.start, cx);
 8036                let tab_size = settings.tab_size.get();
 8037                let mut rows = selection.spanned_rows(false, &display_map);
 8038
 8039                // Avoid re-outdenting a row that has already been outdented by a
 8040                // previous selection.
 8041                if let Some(last_row) = last_outdent {
 8042                    if last_row == rows.start {
 8043                        rows.start = rows.start.next_row();
 8044                    }
 8045                }
 8046                let has_multiple_rows = rows.len() > 1;
 8047                for row in rows.iter_rows() {
 8048                    let indent_size = snapshot.indent_size_for_line(row);
 8049                    if indent_size.len > 0 {
 8050                        let deletion_len = match indent_size.kind {
 8051                            IndentKind::Space => {
 8052                                let columns_to_prev_tab_stop = indent_size.len % tab_size;
 8053                                if columns_to_prev_tab_stop == 0 {
 8054                                    tab_size
 8055                                } else {
 8056                                    columns_to_prev_tab_stop
 8057                                }
 8058                            }
 8059                            IndentKind::Tab => 1,
 8060                        };
 8061                        let start = if has_multiple_rows
 8062                            || deletion_len > selection.start.column
 8063                            || indent_size.len < selection.start.column
 8064                        {
 8065                            0
 8066                        } else {
 8067                            selection.start.column - deletion_len
 8068                        };
 8069                        deletion_ranges.push(
 8070                            Point::new(row.0, start)..Point::new(row.0, start + deletion_len),
 8071                        );
 8072                        last_outdent = Some(row);
 8073                    }
 8074                }
 8075            }
 8076        }
 8077
 8078        self.transact(window, cx, |this, window, cx| {
 8079            this.buffer.update(cx, |buffer, cx| {
 8080                let empty_str: Arc<str> = Arc::default();
 8081                buffer.edit(
 8082                    deletion_ranges
 8083                        .into_iter()
 8084                        .map(|range| (range, empty_str.clone())),
 8085                    None,
 8086                    cx,
 8087                );
 8088            });
 8089            let selections = this.selections.all::<usize>(cx);
 8090            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8091                s.select(selections)
 8092            });
 8093        });
 8094    }
 8095
 8096    pub fn autoindent(&mut self, _: &AutoIndent, window: &mut Window, cx: &mut Context<Self>) {
 8097        if self.read_only(cx) {
 8098            return;
 8099        }
 8100        let selections = self
 8101            .selections
 8102            .all::<usize>(cx)
 8103            .into_iter()
 8104            .map(|s| s.range());
 8105
 8106        self.transact(window, cx, |this, window, cx| {
 8107            this.buffer.update(cx, |buffer, cx| {
 8108                buffer.autoindent_ranges(selections, cx);
 8109            });
 8110            let selections = this.selections.all::<usize>(cx);
 8111            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8112                s.select(selections)
 8113            });
 8114        });
 8115    }
 8116
 8117    pub fn delete_line(&mut self, _: &DeleteLine, window: &mut Window, cx: &mut Context<Self>) {
 8118        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8119        let selections = self.selections.all::<Point>(cx);
 8120
 8121        let mut new_cursors = Vec::new();
 8122        let mut edit_ranges = Vec::new();
 8123        let mut selections = selections.iter().peekable();
 8124        while let Some(selection) = selections.next() {
 8125            let mut rows = selection.spanned_rows(false, &display_map);
 8126            let goal_display_column = selection.head().to_display_point(&display_map).column();
 8127
 8128            // Accumulate contiguous regions of rows that we want to delete.
 8129            while let Some(next_selection) = selections.peek() {
 8130                let next_rows = next_selection.spanned_rows(false, &display_map);
 8131                if next_rows.start <= rows.end {
 8132                    rows.end = next_rows.end;
 8133                    selections.next().unwrap();
 8134                } else {
 8135                    break;
 8136                }
 8137            }
 8138
 8139            let buffer = &display_map.buffer_snapshot;
 8140            let mut edit_start = Point::new(rows.start.0, 0).to_offset(buffer);
 8141            let edit_end;
 8142            let cursor_buffer_row;
 8143            if buffer.max_point().row >= rows.end.0 {
 8144                // If there's a line after the range, delete the \n from the end of the row range
 8145                // and position the cursor on the next line.
 8146                edit_end = Point::new(rows.end.0, 0).to_offset(buffer);
 8147                cursor_buffer_row = rows.end;
 8148            } else {
 8149                // If there isn't a line after the range, delete the \n from the line before the
 8150                // start of the row range and position the cursor there.
 8151                edit_start = edit_start.saturating_sub(1);
 8152                edit_end = buffer.len();
 8153                cursor_buffer_row = rows.start.previous_row();
 8154            }
 8155
 8156            let mut cursor = Point::new(cursor_buffer_row.0, 0).to_display_point(&display_map);
 8157            *cursor.column_mut() =
 8158                cmp::min(goal_display_column, display_map.line_len(cursor.row()));
 8159
 8160            new_cursors.push((
 8161                selection.id,
 8162                buffer.anchor_after(cursor.to_point(&display_map)),
 8163            ));
 8164            edit_ranges.push(edit_start..edit_end);
 8165        }
 8166
 8167        self.transact(window, cx, |this, window, cx| {
 8168            let buffer = this.buffer.update(cx, |buffer, cx| {
 8169                let empty_str: Arc<str> = Arc::default();
 8170                buffer.edit(
 8171                    edit_ranges
 8172                        .into_iter()
 8173                        .map(|range| (range, empty_str.clone())),
 8174                    None,
 8175                    cx,
 8176                );
 8177                buffer.snapshot(cx)
 8178            });
 8179            let new_selections = new_cursors
 8180                .into_iter()
 8181                .map(|(id, cursor)| {
 8182                    let cursor = cursor.to_point(&buffer);
 8183                    Selection {
 8184                        id,
 8185                        start: cursor,
 8186                        end: cursor,
 8187                        reversed: false,
 8188                        goal: SelectionGoal::None,
 8189                    }
 8190                })
 8191                .collect();
 8192
 8193            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8194                s.select(new_selections);
 8195            });
 8196        });
 8197    }
 8198
 8199    pub fn join_lines_impl(
 8200        &mut self,
 8201        insert_whitespace: bool,
 8202        window: &mut Window,
 8203        cx: &mut Context<Self>,
 8204    ) {
 8205        if self.read_only(cx) {
 8206            return;
 8207        }
 8208        let mut row_ranges = Vec::<Range<MultiBufferRow>>::new();
 8209        for selection in self.selections.all::<Point>(cx) {
 8210            let start = MultiBufferRow(selection.start.row);
 8211            // Treat single line selections as if they include the next line. Otherwise this action
 8212            // would do nothing for single line selections individual cursors.
 8213            let end = if selection.start.row == selection.end.row {
 8214                MultiBufferRow(selection.start.row + 1)
 8215            } else {
 8216                MultiBufferRow(selection.end.row)
 8217            };
 8218
 8219            if let Some(last_row_range) = row_ranges.last_mut() {
 8220                if start <= last_row_range.end {
 8221                    last_row_range.end = end;
 8222                    continue;
 8223                }
 8224            }
 8225            row_ranges.push(start..end);
 8226        }
 8227
 8228        let snapshot = self.buffer.read(cx).snapshot(cx);
 8229        let mut cursor_positions = Vec::new();
 8230        for row_range in &row_ranges {
 8231            let anchor = snapshot.anchor_before(Point::new(
 8232                row_range.end.previous_row().0,
 8233                snapshot.line_len(row_range.end.previous_row()),
 8234            ));
 8235            cursor_positions.push(anchor..anchor);
 8236        }
 8237
 8238        self.transact(window, cx, |this, window, cx| {
 8239            for row_range in row_ranges.into_iter().rev() {
 8240                for row in row_range.iter_rows().rev() {
 8241                    let end_of_line = Point::new(row.0, snapshot.line_len(row));
 8242                    let next_line_row = row.next_row();
 8243                    let indent = snapshot.indent_size_for_line(next_line_row);
 8244                    let start_of_next_line = Point::new(next_line_row.0, indent.len);
 8245
 8246                    let replace =
 8247                        if snapshot.line_len(next_line_row) > indent.len && insert_whitespace {
 8248                            " "
 8249                        } else {
 8250                            ""
 8251                        };
 8252
 8253                    this.buffer.update(cx, |buffer, cx| {
 8254                        buffer.edit([(end_of_line..start_of_next_line, replace)], None, cx)
 8255                    });
 8256                }
 8257            }
 8258
 8259            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8260                s.select_anchor_ranges(cursor_positions)
 8261            });
 8262        });
 8263    }
 8264
 8265    pub fn join_lines(&mut self, _: &JoinLines, window: &mut Window, cx: &mut Context<Self>) {
 8266        self.join_lines_impl(true, window, cx);
 8267    }
 8268
 8269    pub fn sort_lines_case_sensitive(
 8270        &mut self,
 8271        _: &SortLinesCaseSensitive,
 8272        window: &mut Window,
 8273        cx: &mut Context<Self>,
 8274    ) {
 8275        self.manipulate_lines(window, cx, |lines| lines.sort())
 8276    }
 8277
 8278    pub fn sort_lines_case_insensitive(
 8279        &mut self,
 8280        _: &SortLinesCaseInsensitive,
 8281        window: &mut Window,
 8282        cx: &mut Context<Self>,
 8283    ) {
 8284        self.manipulate_lines(window, cx, |lines| {
 8285            lines.sort_by_key(|line| line.to_lowercase())
 8286        })
 8287    }
 8288
 8289    pub fn unique_lines_case_insensitive(
 8290        &mut self,
 8291        _: &UniqueLinesCaseInsensitive,
 8292        window: &mut Window,
 8293        cx: &mut Context<Self>,
 8294    ) {
 8295        self.manipulate_lines(window, cx, |lines| {
 8296            let mut seen = HashSet::default();
 8297            lines.retain(|line| seen.insert(line.to_lowercase()));
 8298        })
 8299    }
 8300
 8301    pub fn unique_lines_case_sensitive(
 8302        &mut self,
 8303        _: &UniqueLinesCaseSensitive,
 8304        window: &mut Window,
 8305        cx: &mut Context<Self>,
 8306    ) {
 8307        self.manipulate_lines(window, cx, |lines| {
 8308            let mut seen = HashSet::default();
 8309            lines.retain(|line| seen.insert(*line));
 8310        })
 8311    }
 8312
 8313    pub fn reload_file(&mut self, _: &ReloadFile, window: &mut Window, cx: &mut Context<Self>) {
 8314        let Some(project) = self.project.clone() else {
 8315            return;
 8316        };
 8317        self.reload(project, window, cx)
 8318            .detach_and_notify_err(window, cx);
 8319    }
 8320
 8321    pub fn restore_file(
 8322        &mut self,
 8323        _: &::git::RestoreFile,
 8324        window: &mut Window,
 8325        cx: &mut Context<Self>,
 8326    ) {
 8327        let mut buffer_ids = HashSet::default();
 8328        let snapshot = self.buffer().read(cx).snapshot(cx);
 8329        for selection in self.selections.all::<usize>(cx) {
 8330            buffer_ids.extend(snapshot.buffer_ids_for_range(selection.range()))
 8331        }
 8332
 8333        let buffer = self.buffer().read(cx);
 8334        let ranges = buffer_ids
 8335            .into_iter()
 8336            .flat_map(|buffer_id| buffer.excerpt_ranges_for_buffer(buffer_id, cx))
 8337            .collect::<Vec<_>>();
 8338
 8339        self.restore_hunks_in_ranges(ranges, window, cx);
 8340    }
 8341
 8342    pub fn git_restore(&mut self, _: &Restore, window: &mut Window, cx: &mut Context<Self>) {
 8343        let selections = self
 8344            .selections
 8345            .all(cx)
 8346            .into_iter()
 8347            .map(|s| s.range())
 8348            .collect();
 8349        self.restore_hunks_in_ranges(selections, window, cx);
 8350    }
 8351
 8352    fn restore_hunks_in_ranges(
 8353        &mut self,
 8354        ranges: Vec<Range<Point>>,
 8355        window: &mut Window,
 8356        cx: &mut Context<Editor>,
 8357    ) {
 8358        let mut revert_changes = HashMap::default();
 8359        let chunk_by = self
 8360            .snapshot(window, cx)
 8361            .hunks_for_ranges(ranges)
 8362            .into_iter()
 8363            .chunk_by(|hunk| hunk.buffer_id);
 8364        for (buffer_id, hunks) in &chunk_by {
 8365            let hunks = hunks.collect::<Vec<_>>();
 8366            for hunk in &hunks {
 8367                self.prepare_restore_change(&mut revert_changes, hunk, cx);
 8368            }
 8369            self.do_stage_or_unstage(false, buffer_id, hunks.into_iter(), cx);
 8370        }
 8371        drop(chunk_by);
 8372        if !revert_changes.is_empty() {
 8373            self.transact(window, cx, |editor, window, cx| {
 8374                editor.restore(revert_changes, window, cx);
 8375            });
 8376        }
 8377    }
 8378
 8379    pub fn open_active_item_in_terminal(
 8380        &mut self,
 8381        _: &OpenInTerminal,
 8382        window: &mut Window,
 8383        cx: &mut Context<Self>,
 8384    ) {
 8385        if let Some(working_directory) = self.active_excerpt(cx).and_then(|(_, buffer, _)| {
 8386            let project_path = buffer.read(cx).project_path(cx)?;
 8387            let project = self.project.as_ref()?.read(cx);
 8388            let entry = project.entry_for_path(&project_path, cx)?;
 8389            let parent = match &entry.canonical_path {
 8390                Some(canonical_path) => canonical_path.to_path_buf(),
 8391                None => project.absolute_path(&project_path, cx)?,
 8392            }
 8393            .parent()?
 8394            .to_path_buf();
 8395            Some(parent)
 8396        }) {
 8397            window.dispatch_action(OpenTerminal { working_directory }.boxed_clone(), cx);
 8398        }
 8399    }
 8400
 8401    fn set_breakpoint_context_menu(
 8402        &mut self,
 8403        row: DisplayRow,
 8404        position: Option<Anchor>,
 8405        kind: Arc<BreakpointKind>,
 8406        clicked_point: gpui::Point<Pixels>,
 8407        window: &mut Window,
 8408        cx: &mut Context<Self>,
 8409    ) {
 8410        if !cx.has_flag::<Debugger>() {
 8411            return;
 8412        }
 8413        let source = self
 8414            .buffer
 8415            .read(cx)
 8416            .snapshot(cx)
 8417            .anchor_before(Point::new(row.0, 0u32));
 8418
 8419        let context_menu =
 8420            self.breakpoint_context_menu(position.unwrap_or(source), kind, window, cx);
 8421
 8422        self.mouse_context_menu = MouseContextMenu::pinned_to_editor(
 8423            self,
 8424            source,
 8425            clicked_point,
 8426            context_menu,
 8427            window,
 8428            cx,
 8429        );
 8430    }
 8431
 8432    fn add_edit_breakpoint_block(
 8433        &mut self,
 8434        anchor: Anchor,
 8435        kind: &BreakpointKind,
 8436        window: &mut Window,
 8437        cx: &mut Context<Self>,
 8438    ) {
 8439        let weak_editor = cx.weak_entity();
 8440        let bp_prompt =
 8441            cx.new(|cx| BreakpointPromptEditor::new(weak_editor, anchor, kind.clone(), window, cx));
 8442
 8443        let height = bp_prompt.update(cx, |this, cx| {
 8444            this.prompt
 8445                .update(cx, |prompt, cx| prompt.max_point(cx).row().0 + 1 + 2)
 8446        });
 8447        let cloned_prompt = bp_prompt.clone();
 8448        let blocks = vec![BlockProperties {
 8449            style: BlockStyle::Sticky,
 8450            placement: BlockPlacement::Above(anchor),
 8451            height,
 8452            render: Arc::new(move |cx| {
 8453                *cloned_prompt.read(cx).gutter_dimensions.lock() = *cx.gutter_dimensions;
 8454                cloned_prompt.clone().into_any_element()
 8455            }),
 8456            priority: 0,
 8457        }];
 8458
 8459        let focus_handle = bp_prompt.focus_handle(cx);
 8460        window.focus(&focus_handle);
 8461
 8462        let block_ids = self.insert_blocks(blocks, None, cx);
 8463        bp_prompt.update(cx, |prompt, _| {
 8464            prompt.add_block_ids(block_ids);
 8465        });
 8466    }
 8467
 8468    pub(crate) fn breakpoint_at_cursor_head(
 8469        &self,
 8470        window: &mut Window,
 8471        cx: &mut Context<Self>,
 8472    ) -> Option<(Anchor, Breakpoint)> {
 8473        let cursor_position: Point = self.selections.newest(cx).head();
 8474        let snapshot = self.snapshot(window, cx);
 8475        // We Set the column position to zero so this function interacts correctly
 8476        // between calls by clicking on the gutter & using an action to toggle a
 8477        // breakpoint. Otherwise, toggling a breakpoint through an action wouldn't
 8478        // untoggle a breakpoint that was added through clicking on the gutter
 8479        let cursor_position = snapshot
 8480            .display_snapshot
 8481            .buffer_snapshot
 8482            .anchor_before(Point::new(cursor_position.row, 0));
 8483
 8484        let project = self.project.clone();
 8485
 8486        let buffer_id = cursor_position.text_anchor.buffer_id?;
 8487        let enclosing_excerpt = snapshot
 8488            .buffer_snapshot
 8489            .excerpt_ids_for_range(cursor_position..cursor_position)
 8490            .next()?;
 8491        let buffer = project?.read_with(cx, |project, cx| project.buffer_for_id(buffer_id, cx))?;
 8492        let buffer_snapshot = buffer.read(cx).snapshot();
 8493
 8494        let row = buffer_snapshot
 8495            .summary_for_anchor::<text::PointUtf16>(&cursor_position.text_anchor)
 8496            .row;
 8497
 8498        let bp = self
 8499            .breakpoint_store
 8500            .as_ref()?
 8501            .read_with(cx, |breakpoint_store, cx| {
 8502                breakpoint_store
 8503                    .breakpoints(
 8504                        &buffer,
 8505                        Some(cursor_position.text_anchor..(text::Anchor::MAX)),
 8506                        buffer_snapshot.clone(),
 8507                        cx,
 8508                    )
 8509                    .next()
 8510                    .and_then(move |(anchor, bp)| {
 8511                        let breakpoint_row = buffer_snapshot
 8512                            .summary_for_anchor::<text::PointUtf16>(anchor)
 8513                            .row;
 8514
 8515                        if breakpoint_row == row {
 8516                            snapshot
 8517                                .buffer_snapshot
 8518                                .anchor_in_excerpt(enclosing_excerpt, *anchor)
 8519                                .map(|anchor| (anchor, bp.clone()))
 8520                        } else {
 8521                            None
 8522                        }
 8523                    })
 8524            });
 8525        bp
 8526    }
 8527
 8528    pub fn edit_log_breakpoint(
 8529        &mut self,
 8530        _: &EditLogBreakpoint,
 8531        window: &mut Window,
 8532        cx: &mut Context<Self>,
 8533    ) {
 8534        let (anchor, bp) = self
 8535            .breakpoint_at_cursor_head(window, cx)
 8536            .unwrap_or_else(|| {
 8537                let cursor_position: Point = self.selections.newest(cx).head();
 8538
 8539                let breakpoint_position = self
 8540                    .snapshot(window, cx)
 8541                    .display_snapshot
 8542                    .buffer_snapshot
 8543                    .anchor_before(Point::new(cursor_position.row, 0));
 8544
 8545                (
 8546                    breakpoint_position,
 8547                    Breakpoint {
 8548                        kind: BreakpointKind::Standard,
 8549                    },
 8550                )
 8551            });
 8552
 8553        self.add_edit_breakpoint_block(anchor, &bp.kind, window, cx);
 8554    }
 8555
 8556    pub fn toggle_breakpoint(
 8557        &mut self,
 8558        _: &crate::actions::ToggleBreakpoint,
 8559        window: &mut Window,
 8560        cx: &mut Context<Self>,
 8561    ) {
 8562        let edit_action = BreakpointEditAction::Toggle;
 8563
 8564        if let Some((anchor, breakpoint)) = self.breakpoint_at_cursor_head(window, cx) {
 8565            self.edit_breakpoint_at_anchor(anchor, breakpoint.kind, edit_action, cx);
 8566        } else {
 8567            let cursor_position: Point = self.selections.newest(cx).head();
 8568
 8569            let breakpoint_position = self
 8570                .snapshot(window, cx)
 8571                .display_snapshot
 8572                .buffer_snapshot
 8573                .anchor_before(Point::new(cursor_position.row, 0));
 8574
 8575            self.edit_breakpoint_at_anchor(
 8576                breakpoint_position,
 8577                BreakpointKind::Standard,
 8578                edit_action,
 8579                cx,
 8580            );
 8581        }
 8582    }
 8583
 8584    pub fn edit_breakpoint_at_anchor(
 8585        &mut self,
 8586        breakpoint_position: Anchor,
 8587        kind: BreakpointKind,
 8588        edit_action: BreakpointEditAction,
 8589        cx: &mut Context<Self>,
 8590    ) {
 8591        let Some(breakpoint_store) = &self.breakpoint_store else {
 8592            return;
 8593        };
 8594
 8595        let Some(buffer_id) = breakpoint_position.buffer_id.or_else(|| {
 8596            if breakpoint_position == Anchor::min() {
 8597                self.buffer()
 8598                    .read(cx)
 8599                    .excerpt_buffer_ids()
 8600                    .into_iter()
 8601                    .next()
 8602            } else {
 8603                None
 8604            }
 8605        }) else {
 8606            return;
 8607        };
 8608
 8609        let Some(buffer) = self.buffer().read(cx).buffer(buffer_id) else {
 8610            return;
 8611        };
 8612
 8613        breakpoint_store.update(cx, |breakpoint_store, cx| {
 8614            breakpoint_store.toggle_breakpoint(
 8615                buffer,
 8616                (breakpoint_position.text_anchor, Breakpoint { kind }),
 8617                edit_action,
 8618                cx,
 8619            );
 8620        });
 8621
 8622        cx.notify();
 8623    }
 8624
 8625    #[cfg(any(test, feature = "test-support"))]
 8626    pub fn breakpoint_store(&self) -> Option<Entity<BreakpointStore>> {
 8627        self.breakpoint_store.clone()
 8628    }
 8629
 8630    pub fn prepare_restore_change(
 8631        &self,
 8632        revert_changes: &mut HashMap<BufferId, Vec<(Range<text::Anchor>, Rope)>>,
 8633        hunk: &MultiBufferDiffHunk,
 8634        cx: &mut App,
 8635    ) -> Option<()> {
 8636        if hunk.is_created_file() {
 8637            return None;
 8638        }
 8639        let buffer = self.buffer.read(cx);
 8640        let diff = buffer.diff_for(hunk.buffer_id)?;
 8641        let buffer = buffer.buffer(hunk.buffer_id)?;
 8642        let buffer = buffer.read(cx);
 8643        let original_text = diff
 8644            .read(cx)
 8645            .base_text()
 8646            .as_rope()
 8647            .slice(hunk.diff_base_byte_range.clone());
 8648        let buffer_snapshot = buffer.snapshot();
 8649        let buffer_revert_changes = revert_changes.entry(buffer.remote_id()).or_default();
 8650        if let Err(i) = buffer_revert_changes.binary_search_by(|probe| {
 8651            probe
 8652                .0
 8653                .start
 8654                .cmp(&hunk.buffer_range.start, &buffer_snapshot)
 8655                .then(probe.0.end.cmp(&hunk.buffer_range.end, &buffer_snapshot))
 8656        }) {
 8657            buffer_revert_changes.insert(i, (hunk.buffer_range.clone(), original_text));
 8658            Some(())
 8659        } else {
 8660            None
 8661        }
 8662    }
 8663
 8664    pub fn reverse_lines(&mut self, _: &ReverseLines, window: &mut Window, cx: &mut Context<Self>) {
 8665        self.manipulate_lines(window, cx, |lines| lines.reverse())
 8666    }
 8667
 8668    pub fn shuffle_lines(&mut self, _: &ShuffleLines, window: &mut Window, cx: &mut Context<Self>) {
 8669        self.manipulate_lines(window, cx, |lines| lines.shuffle(&mut thread_rng()))
 8670    }
 8671
 8672    fn manipulate_lines<Fn>(
 8673        &mut self,
 8674        window: &mut Window,
 8675        cx: &mut Context<Self>,
 8676        mut callback: Fn,
 8677    ) where
 8678        Fn: FnMut(&mut Vec<&str>),
 8679    {
 8680        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8681        let buffer = self.buffer.read(cx).snapshot(cx);
 8682
 8683        let mut edits = Vec::new();
 8684
 8685        let selections = self.selections.all::<Point>(cx);
 8686        let mut selections = selections.iter().peekable();
 8687        let mut contiguous_row_selections = Vec::new();
 8688        let mut new_selections = Vec::new();
 8689        let mut added_lines = 0;
 8690        let mut removed_lines = 0;
 8691
 8692        while let Some(selection) = selections.next() {
 8693            let (start_row, end_row) = consume_contiguous_rows(
 8694                &mut contiguous_row_selections,
 8695                selection,
 8696                &display_map,
 8697                &mut selections,
 8698            );
 8699
 8700            let start_point = Point::new(start_row.0, 0);
 8701            let end_point = Point::new(
 8702                end_row.previous_row().0,
 8703                buffer.line_len(end_row.previous_row()),
 8704            );
 8705            let text = buffer
 8706                .text_for_range(start_point..end_point)
 8707                .collect::<String>();
 8708
 8709            let mut lines = text.split('\n').collect_vec();
 8710
 8711            let lines_before = lines.len();
 8712            callback(&mut lines);
 8713            let lines_after = lines.len();
 8714
 8715            edits.push((start_point..end_point, lines.join("\n")));
 8716
 8717            // Selections must change based on added and removed line count
 8718            let start_row =
 8719                MultiBufferRow(start_point.row + added_lines as u32 - removed_lines as u32);
 8720            let end_row = MultiBufferRow(start_row.0 + lines_after.saturating_sub(1) as u32);
 8721            new_selections.push(Selection {
 8722                id: selection.id,
 8723                start: start_row,
 8724                end: end_row,
 8725                goal: SelectionGoal::None,
 8726                reversed: selection.reversed,
 8727            });
 8728
 8729            if lines_after > lines_before {
 8730                added_lines += lines_after - lines_before;
 8731            } else if lines_before > lines_after {
 8732                removed_lines += lines_before - lines_after;
 8733            }
 8734        }
 8735
 8736        self.transact(window, cx, |this, window, cx| {
 8737            let buffer = this.buffer.update(cx, |buffer, cx| {
 8738                buffer.edit(edits, None, cx);
 8739                buffer.snapshot(cx)
 8740            });
 8741
 8742            // Recalculate offsets on newly edited buffer
 8743            let new_selections = new_selections
 8744                .iter()
 8745                .map(|s| {
 8746                    let start_point = Point::new(s.start.0, 0);
 8747                    let end_point = Point::new(s.end.0, buffer.line_len(s.end));
 8748                    Selection {
 8749                        id: s.id,
 8750                        start: buffer.point_to_offset(start_point),
 8751                        end: buffer.point_to_offset(end_point),
 8752                        goal: s.goal,
 8753                        reversed: s.reversed,
 8754                    }
 8755                })
 8756                .collect();
 8757
 8758            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8759                s.select(new_selections);
 8760            });
 8761
 8762            this.request_autoscroll(Autoscroll::fit(), cx);
 8763        });
 8764    }
 8765
 8766    pub fn convert_to_upper_case(
 8767        &mut self,
 8768        _: &ConvertToUpperCase,
 8769        window: &mut Window,
 8770        cx: &mut Context<Self>,
 8771    ) {
 8772        self.manipulate_text(window, cx, |text| text.to_uppercase())
 8773    }
 8774
 8775    pub fn convert_to_lower_case(
 8776        &mut self,
 8777        _: &ConvertToLowerCase,
 8778        window: &mut Window,
 8779        cx: &mut Context<Self>,
 8780    ) {
 8781        self.manipulate_text(window, cx, |text| text.to_lowercase())
 8782    }
 8783
 8784    pub fn convert_to_title_case(
 8785        &mut self,
 8786        _: &ConvertToTitleCase,
 8787        window: &mut Window,
 8788        cx: &mut Context<Self>,
 8789    ) {
 8790        self.manipulate_text(window, cx, |text| {
 8791            text.split('\n')
 8792                .map(|line| line.to_case(Case::Title))
 8793                .join("\n")
 8794        })
 8795    }
 8796
 8797    pub fn convert_to_snake_case(
 8798        &mut self,
 8799        _: &ConvertToSnakeCase,
 8800        window: &mut Window,
 8801        cx: &mut Context<Self>,
 8802    ) {
 8803        self.manipulate_text(window, cx, |text| text.to_case(Case::Snake))
 8804    }
 8805
 8806    pub fn convert_to_kebab_case(
 8807        &mut self,
 8808        _: &ConvertToKebabCase,
 8809        window: &mut Window,
 8810        cx: &mut Context<Self>,
 8811    ) {
 8812        self.manipulate_text(window, cx, |text| text.to_case(Case::Kebab))
 8813    }
 8814
 8815    pub fn convert_to_upper_camel_case(
 8816        &mut self,
 8817        _: &ConvertToUpperCamelCase,
 8818        window: &mut Window,
 8819        cx: &mut Context<Self>,
 8820    ) {
 8821        self.manipulate_text(window, cx, |text| {
 8822            text.split('\n')
 8823                .map(|line| line.to_case(Case::UpperCamel))
 8824                .join("\n")
 8825        })
 8826    }
 8827
 8828    pub fn convert_to_lower_camel_case(
 8829        &mut self,
 8830        _: &ConvertToLowerCamelCase,
 8831        window: &mut Window,
 8832        cx: &mut Context<Self>,
 8833    ) {
 8834        self.manipulate_text(window, cx, |text| text.to_case(Case::Camel))
 8835    }
 8836
 8837    pub fn convert_to_opposite_case(
 8838        &mut self,
 8839        _: &ConvertToOppositeCase,
 8840        window: &mut Window,
 8841        cx: &mut Context<Self>,
 8842    ) {
 8843        self.manipulate_text(window, cx, |text| {
 8844            text.chars()
 8845                .fold(String::with_capacity(text.len()), |mut t, c| {
 8846                    if c.is_uppercase() {
 8847                        t.extend(c.to_lowercase());
 8848                    } else {
 8849                        t.extend(c.to_uppercase());
 8850                    }
 8851                    t
 8852                })
 8853        })
 8854    }
 8855
 8856    fn manipulate_text<Fn>(&mut self, window: &mut Window, cx: &mut Context<Self>, mut callback: Fn)
 8857    where
 8858        Fn: FnMut(&str) -> String,
 8859    {
 8860        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8861        let buffer = self.buffer.read(cx).snapshot(cx);
 8862
 8863        let mut new_selections = Vec::new();
 8864        let mut edits = Vec::new();
 8865        let mut selection_adjustment = 0i32;
 8866
 8867        for selection in self.selections.all::<usize>(cx) {
 8868            let selection_is_empty = selection.is_empty();
 8869
 8870            let (start, end) = if selection_is_empty {
 8871                let word_range = movement::surrounding_word(
 8872                    &display_map,
 8873                    selection.start.to_display_point(&display_map),
 8874                );
 8875                let start = word_range.start.to_offset(&display_map, Bias::Left);
 8876                let end = word_range.end.to_offset(&display_map, Bias::Left);
 8877                (start, end)
 8878            } else {
 8879                (selection.start, selection.end)
 8880            };
 8881
 8882            let text = buffer.text_for_range(start..end).collect::<String>();
 8883            let old_length = text.len() as i32;
 8884            let text = callback(&text);
 8885
 8886            new_selections.push(Selection {
 8887                start: (start as i32 - selection_adjustment) as usize,
 8888                end: ((start + text.len()) as i32 - selection_adjustment) as usize,
 8889                goal: SelectionGoal::None,
 8890                ..selection
 8891            });
 8892
 8893            selection_adjustment += old_length - text.len() as i32;
 8894
 8895            edits.push((start..end, text));
 8896        }
 8897
 8898        self.transact(window, cx, |this, window, cx| {
 8899            this.buffer.update(cx, |buffer, cx| {
 8900                buffer.edit(edits, None, cx);
 8901            });
 8902
 8903            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8904                s.select(new_selections);
 8905            });
 8906
 8907            this.request_autoscroll(Autoscroll::fit(), cx);
 8908        });
 8909    }
 8910
 8911    pub fn duplicate(
 8912        &mut self,
 8913        upwards: bool,
 8914        whole_lines: bool,
 8915        window: &mut Window,
 8916        cx: &mut Context<Self>,
 8917    ) {
 8918        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8919        let buffer = &display_map.buffer_snapshot;
 8920        let selections = self.selections.all::<Point>(cx);
 8921
 8922        let mut edits = Vec::new();
 8923        let mut selections_iter = selections.iter().peekable();
 8924        while let Some(selection) = selections_iter.next() {
 8925            let mut rows = selection.spanned_rows(false, &display_map);
 8926            // duplicate line-wise
 8927            if whole_lines || selection.start == selection.end {
 8928                // Avoid duplicating the same lines twice.
 8929                while let Some(next_selection) = selections_iter.peek() {
 8930                    let next_rows = next_selection.spanned_rows(false, &display_map);
 8931                    if next_rows.start < rows.end {
 8932                        rows.end = next_rows.end;
 8933                        selections_iter.next().unwrap();
 8934                    } else {
 8935                        break;
 8936                    }
 8937                }
 8938
 8939                // Copy the text from the selected row region and splice it either at the start
 8940                // or end of the region.
 8941                let start = Point::new(rows.start.0, 0);
 8942                let end = Point::new(
 8943                    rows.end.previous_row().0,
 8944                    buffer.line_len(rows.end.previous_row()),
 8945                );
 8946                let text = buffer
 8947                    .text_for_range(start..end)
 8948                    .chain(Some("\n"))
 8949                    .collect::<String>();
 8950                let insert_location = if upwards {
 8951                    Point::new(rows.end.0, 0)
 8952                } else {
 8953                    start
 8954                };
 8955                edits.push((insert_location..insert_location, text));
 8956            } else {
 8957                // duplicate character-wise
 8958                let start = selection.start;
 8959                let end = selection.end;
 8960                let text = buffer.text_for_range(start..end).collect::<String>();
 8961                edits.push((selection.end..selection.end, text));
 8962            }
 8963        }
 8964
 8965        self.transact(window, cx, |this, _, cx| {
 8966            this.buffer.update(cx, |buffer, cx| {
 8967                buffer.edit(edits, None, cx);
 8968            });
 8969
 8970            this.request_autoscroll(Autoscroll::fit(), cx);
 8971        });
 8972    }
 8973
 8974    pub fn duplicate_line_up(
 8975        &mut self,
 8976        _: &DuplicateLineUp,
 8977        window: &mut Window,
 8978        cx: &mut Context<Self>,
 8979    ) {
 8980        self.duplicate(true, true, window, cx);
 8981    }
 8982
 8983    pub fn duplicate_line_down(
 8984        &mut self,
 8985        _: &DuplicateLineDown,
 8986        window: &mut Window,
 8987        cx: &mut Context<Self>,
 8988    ) {
 8989        self.duplicate(false, true, window, cx);
 8990    }
 8991
 8992    pub fn duplicate_selection(
 8993        &mut self,
 8994        _: &DuplicateSelection,
 8995        window: &mut Window,
 8996        cx: &mut Context<Self>,
 8997    ) {
 8998        self.duplicate(false, false, window, cx);
 8999    }
 9000
 9001    pub fn move_line_up(&mut self, _: &MoveLineUp, window: &mut Window, cx: &mut Context<Self>) {
 9002        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 9003        let buffer = self.buffer.read(cx).snapshot(cx);
 9004
 9005        let mut edits = Vec::new();
 9006        let mut unfold_ranges = Vec::new();
 9007        let mut refold_creases = Vec::new();
 9008
 9009        let selections = self.selections.all::<Point>(cx);
 9010        let mut selections = selections.iter().peekable();
 9011        let mut contiguous_row_selections = Vec::new();
 9012        let mut new_selections = Vec::new();
 9013
 9014        while let Some(selection) = selections.next() {
 9015            // Find all the selections that span a contiguous row range
 9016            let (start_row, end_row) = consume_contiguous_rows(
 9017                &mut contiguous_row_selections,
 9018                selection,
 9019                &display_map,
 9020                &mut selections,
 9021            );
 9022
 9023            // Move the text spanned by the row range to be before the line preceding the row range
 9024            if start_row.0 > 0 {
 9025                let range_to_move = Point::new(
 9026                    start_row.previous_row().0,
 9027                    buffer.line_len(start_row.previous_row()),
 9028                )
 9029                    ..Point::new(
 9030                        end_row.previous_row().0,
 9031                        buffer.line_len(end_row.previous_row()),
 9032                    );
 9033                let insertion_point = display_map
 9034                    .prev_line_boundary(Point::new(start_row.previous_row().0, 0))
 9035                    .0;
 9036
 9037                // Don't move lines across excerpts
 9038                if buffer
 9039                    .excerpt_containing(insertion_point..range_to_move.end)
 9040                    .is_some()
 9041                {
 9042                    let text = buffer
 9043                        .text_for_range(range_to_move.clone())
 9044                        .flat_map(|s| s.chars())
 9045                        .skip(1)
 9046                        .chain(['\n'])
 9047                        .collect::<String>();
 9048
 9049                    edits.push((
 9050                        buffer.anchor_after(range_to_move.start)
 9051                            ..buffer.anchor_before(range_to_move.end),
 9052                        String::new(),
 9053                    ));
 9054                    let insertion_anchor = buffer.anchor_after(insertion_point);
 9055                    edits.push((insertion_anchor..insertion_anchor, text));
 9056
 9057                    let row_delta = range_to_move.start.row - insertion_point.row + 1;
 9058
 9059                    // Move selections up
 9060                    new_selections.extend(contiguous_row_selections.drain(..).map(
 9061                        |mut selection| {
 9062                            selection.start.row -= row_delta;
 9063                            selection.end.row -= row_delta;
 9064                            selection
 9065                        },
 9066                    ));
 9067
 9068                    // Move folds up
 9069                    unfold_ranges.push(range_to_move.clone());
 9070                    for fold in display_map.folds_in_range(
 9071                        buffer.anchor_before(range_to_move.start)
 9072                            ..buffer.anchor_after(range_to_move.end),
 9073                    ) {
 9074                        let mut start = fold.range.start.to_point(&buffer);
 9075                        let mut end = fold.range.end.to_point(&buffer);
 9076                        start.row -= row_delta;
 9077                        end.row -= row_delta;
 9078                        refold_creases.push(Crease::simple(start..end, fold.placeholder.clone()));
 9079                    }
 9080                }
 9081            }
 9082
 9083            // If we didn't move line(s), preserve the existing selections
 9084            new_selections.append(&mut contiguous_row_selections);
 9085        }
 9086
 9087        self.transact(window, cx, |this, window, cx| {
 9088            this.unfold_ranges(&unfold_ranges, true, true, cx);
 9089            this.buffer.update(cx, |buffer, cx| {
 9090                for (range, text) in edits {
 9091                    buffer.edit([(range, text)], None, cx);
 9092                }
 9093            });
 9094            this.fold_creases(refold_creases, true, window, cx);
 9095            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9096                s.select(new_selections);
 9097            })
 9098        });
 9099    }
 9100
 9101    pub fn move_line_down(
 9102        &mut self,
 9103        _: &MoveLineDown,
 9104        window: &mut Window,
 9105        cx: &mut Context<Self>,
 9106    ) {
 9107        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 9108        let buffer = self.buffer.read(cx).snapshot(cx);
 9109
 9110        let mut edits = Vec::new();
 9111        let mut unfold_ranges = Vec::new();
 9112        let mut refold_creases = Vec::new();
 9113
 9114        let selections = self.selections.all::<Point>(cx);
 9115        let mut selections = selections.iter().peekable();
 9116        let mut contiguous_row_selections = Vec::new();
 9117        let mut new_selections = Vec::new();
 9118
 9119        while let Some(selection) = selections.next() {
 9120            // Find all the selections that span a contiguous row range
 9121            let (start_row, end_row) = consume_contiguous_rows(
 9122                &mut contiguous_row_selections,
 9123                selection,
 9124                &display_map,
 9125                &mut selections,
 9126            );
 9127
 9128            // Move the text spanned by the row range to be after the last line of the row range
 9129            if end_row.0 <= buffer.max_point().row {
 9130                let range_to_move =
 9131                    MultiBufferPoint::new(start_row.0, 0)..MultiBufferPoint::new(end_row.0, 0);
 9132                let insertion_point = display_map
 9133                    .next_line_boundary(MultiBufferPoint::new(end_row.0, 0))
 9134                    .0;
 9135
 9136                // Don't move lines across excerpt boundaries
 9137                if buffer
 9138                    .excerpt_containing(range_to_move.start..insertion_point)
 9139                    .is_some()
 9140                {
 9141                    let mut text = String::from("\n");
 9142                    text.extend(buffer.text_for_range(range_to_move.clone()));
 9143                    text.pop(); // Drop trailing newline
 9144                    edits.push((
 9145                        buffer.anchor_after(range_to_move.start)
 9146                            ..buffer.anchor_before(range_to_move.end),
 9147                        String::new(),
 9148                    ));
 9149                    let insertion_anchor = buffer.anchor_after(insertion_point);
 9150                    edits.push((insertion_anchor..insertion_anchor, text));
 9151
 9152                    let row_delta = insertion_point.row - range_to_move.end.row + 1;
 9153
 9154                    // Move selections down
 9155                    new_selections.extend(contiguous_row_selections.drain(..).map(
 9156                        |mut selection| {
 9157                            selection.start.row += row_delta;
 9158                            selection.end.row += row_delta;
 9159                            selection
 9160                        },
 9161                    ));
 9162
 9163                    // Move folds down
 9164                    unfold_ranges.push(range_to_move.clone());
 9165                    for fold in display_map.folds_in_range(
 9166                        buffer.anchor_before(range_to_move.start)
 9167                            ..buffer.anchor_after(range_to_move.end),
 9168                    ) {
 9169                        let mut start = fold.range.start.to_point(&buffer);
 9170                        let mut end = fold.range.end.to_point(&buffer);
 9171                        start.row += row_delta;
 9172                        end.row += row_delta;
 9173                        refold_creases.push(Crease::simple(start..end, fold.placeholder.clone()));
 9174                    }
 9175                }
 9176            }
 9177
 9178            // If we didn't move line(s), preserve the existing selections
 9179            new_selections.append(&mut contiguous_row_selections);
 9180        }
 9181
 9182        self.transact(window, cx, |this, window, cx| {
 9183            this.unfold_ranges(&unfold_ranges, true, true, cx);
 9184            this.buffer.update(cx, |buffer, cx| {
 9185                for (range, text) in edits {
 9186                    buffer.edit([(range, text)], None, cx);
 9187                }
 9188            });
 9189            this.fold_creases(refold_creases, true, window, cx);
 9190            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9191                s.select(new_selections)
 9192            });
 9193        });
 9194    }
 9195
 9196    pub fn transpose(&mut self, _: &Transpose, window: &mut Window, cx: &mut Context<Self>) {
 9197        let text_layout_details = &self.text_layout_details(window);
 9198        self.transact(window, cx, |this, window, cx| {
 9199            let edits = this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9200                let mut edits: Vec<(Range<usize>, String)> = Default::default();
 9201                let line_mode = s.line_mode;
 9202                s.move_with(|display_map, selection| {
 9203                    if !selection.is_empty() || line_mode {
 9204                        return;
 9205                    }
 9206
 9207                    let mut head = selection.head();
 9208                    let mut transpose_offset = head.to_offset(display_map, Bias::Right);
 9209                    if head.column() == display_map.line_len(head.row()) {
 9210                        transpose_offset = display_map
 9211                            .buffer_snapshot
 9212                            .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
 9213                    }
 9214
 9215                    if transpose_offset == 0 {
 9216                        return;
 9217                    }
 9218
 9219                    *head.column_mut() += 1;
 9220                    head = display_map.clip_point(head, Bias::Right);
 9221                    let goal = SelectionGoal::HorizontalPosition(
 9222                        display_map
 9223                            .x_for_display_point(head, text_layout_details)
 9224                            .into(),
 9225                    );
 9226                    selection.collapse_to(head, goal);
 9227
 9228                    let transpose_start = display_map
 9229                        .buffer_snapshot
 9230                        .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
 9231                    if edits.last().map_or(true, |e| e.0.end <= transpose_start) {
 9232                        let transpose_end = display_map
 9233                            .buffer_snapshot
 9234                            .clip_offset(transpose_offset + 1, Bias::Right);
 9235                        if let Some(ch) =
 9236                            display_map.buffer_snapshot.chars_at(transpose_start).next()
 9237                        {
 9238                            edits.push((transpose_start..transpose_offset, String::new()));
 9239                            edits.push((transpose_end..transpose_end, ch.to_string()));
 9240                        }
 9241                    }
 9242                });
 9243                edits
 9244            });
 9245            this.buffer
 9246                .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
 9247            let selections = this.selections.all::<usize>(cx);
 9248            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9249                s.select(selections);
 9250            });
 9251        });
 9252    }
 9253
 9254    pub fn rewrap(&mut self, _: &Rewrap, _: &mut Window, cx: &mut Context<Self>) {
 9255        self.rewrap_impl(RewrapOptions::default(), cx)
 9256    }
 9257
 9258    pub fn rewrap_impl(&mut self, options: RewrapOptions, cx: &mut Context<Self>) {
 9259        let buffer = self.buffer.read(cx).snapshot(cx);
 9260        let selections = self.selections.all::<Point>(cx);
 9261        let mut selections = selections.iter().peekable();
 9262
 9263        let mut edits = Vec::new();
 9264        let mut rewrapped_row_ranges = Vec::<RangeInclusive<u32>>::new();
 9265
 9266        while let Some(selection) = selections.next() {
 9267            let mut start_row = selection.start.row;
 9268            let mut end_row = selection.end.row;
 9269
 9270            // Skip selections that overlap with a range that has already been rewrapped.
 9271            let selection_range = start_row..end_row;
 9272            if rewrapped_row_ranges
 9273                .iter()
 9274                .any(|range| range.overlaps(&selection_range))
 9275            {
 9276                continue;
 9277            }
 9278
 9279            let tab_size = buffer.language_settings_at(selection.head(), cx).tab_size;
 9280
 9281            // Since not all lines in the selection may be at the same indent
 9282            // level, choose the indent size that is the most common between all
 9283            // of the lines.
 9284            //
 9285            // If there is a tie, we use the deepest indent.
 9286            let (indent_size, indent_end) = {
 9287                let mut indent_size_occurrences = HashMap::default();
 9288                let mut rows_by_indent_size = HashMap::<IndentSize, Vec<u32>>::default();
 9289
 9290                for row in start_row..=end_row {
 9291                    let indent = buffer.indent_size_for_line(MultiBufferRow(row));
 9292                    rows_by_indent_size.entry(indent).or_default().push(row);
 9293                    *indent_size_occurrences.entry(indent).or_insert(0) += 1;
 9294                }
 9295
 9296                let indent_size = indent_size_occurrences
 9297                    .into_iter()
 9298                    .max_by_key(|(indent, count)| (*count, indent.len_with_expanded_tabs(tab_size)))
 9299                    .map(|(indent, _)| indent)
 9300                    .unwrap_or_default();
 9301                let row = rows_by_indent_size[&indent_size][0];
 9302                let indent_end = Point::new(row, indent_size.len);
 9303
 9304                (indent_size, indent_end)
 9305            };
 9306
 9307            let mut line_prefix = indent_size.chars().collect::<String>();
 9308
 9309            let mut inside_comment = false;
 9310            if let Some(comment_prefix) =
 9311                buffer
 9312                    .language_scope_at(selection.head())
 9313                    .and_then(|language| {
 9314                        language
 9315                            .line_comment_prefixes()
 9316                            .iter()
 9317                            .find(|prefix| buffer.contains_str_at(indent_end, prefix))
 9318                            .cloned()
 9319                    })
 9320            {
 9321                line_prefix.push_str(&comment_prefix);
 9322                inside_comment = true;
 9323            }
 9324
 9325            let language_settings = buffer.language_settings_at(selection.head(), cx);
 9326            let allow_rewrap_based_on_language = match language_settings.allow_rewrap {
 9327                RewrapBehavior::InComments => inside_comment,
 9328                RewrapBehavior::InSelections => !selection.is_empty(),
 9329                RewrapBehavior::Anywhere => true,
 9330            };
 9331
 9332            let should_rewrap = options.override_language_settings
 9333                || allow_rewrap_based_on_language
 9334                || self.hard_wrap.is_some();
 9335            if !should_rewrap {
 9336                continue;
 9337            }
 9338
 9339            if selection.is_empty() {
 9340                'expand_upwards: while start_row > 0 {
 9341                    let prev_row = start_row - 1;
 9342                    if buffer.contains_str_at(Point::new(prev_row, 0), &line_prefix)
 9343                        && buffer.line_len(MultiBufferRow(prev_row)) as usize > line_prefix.len()
 9344                    {
 9345                        start_row = prev_row;
 9346                    } else {
 9347                        break 'expand_upwards;
 9348                    }
 9349                }
 9350
 9351                'expand_downwards: while end_row < buffer.max_point().row {
 9352                    let next_row = end_row + 1;
 9353                    if buffer.contains_str_at(Point::new(next_row, 0), &line_prefix)
 9354                        && buffer.line_len(MultiBufferRow(next_row)) as usize > line_prefix.len()
 9355                    {
 9356                        end_row = next_row;
 9357                    } else {
 9358                        break 'expand_downwards;
 9359                    }
 9360                }
 9361            }
 9362
 9363            let start = Point::new(start_row, 0);
 9364            let start_offset = start.to_offset(&buffer);
 9365            let end = Point::new(end_row, buffer.line_len(MultiBufferRow(end_row)));
 9366            let selection_text = buffer.text_for_range(start..end).collect::<String>();
 9367            let Some(lines_without_prefixes) = selection_text
 9368                .lines()
 9369                .map(|line| {
 9370                    line.strip_prefix(&line_prefix)
 9371                        .or_else(|| line.trim_start().strip_prefix(&line_prefix.trim_start()))
 9372                        .ok_or_else(|| {
 9373                            anyhow!("line did not start with prefix {line_prefix:?}: {line:?}")
 9374                        })
 9375                })
 9376                .collect::<Result<Vec<_>, _>>()
 9377                .log_err()
 9378            else {
 9379                continue;
 9380            };
 9381
 9382            let wrap_column = self.hard_wrap.unwrap_or_else(|| {
 9383                buffer
 9384                    .language_settings_at(Point::new(start_row, 0), cx)
 9385                    .preferred_line_length as usize
 9386            });
 9387            let wrapped_text = wrap_with_prefix(
 9388                line_prefix,
 9389                lines_without_prefixes.join("\n"),
 9390                wrap_column,
 9391                tab_size,
 9392                options.preserve_existing_whitespace,
 9393            );
 9394
 9395            // TODO: should always use char-based diff while still supporting cursor behavior that
 9396            // matches vim.
 9397            let mut diff_options = DiffOptions::default();
 9398            if options.override_language_settings {
 9399                diff_options.max_word_diff_len = 0;
 9400                diff_options.max_word_diff_line_count = 0;
 9401            } else {
 9402                diff_options.max_word_diff_len = usize::MAX;
 9403                diff_options.max_word_diff_line_count = usize::MAX;
 9404            }
 9405
 9406            for (old_range, new_text) in
 9407                text_diff_with_options(&selection_text, &wrapped_text, diff_options)
 9408            {
 9409                let edit_start = buffer.anchor_after(start_offset + old_range.start);
 9410                let edit_end = buffer.anchor_after(start_offset + old_range.end);
 9411                edits.push((edit_start..edit_end, new_text));
 9412            }
 9413
 9414            rewrapped_row_ranges.push(start_row..=end_row);
 9415        }
 9416
 9417        self.buffer
 9418            .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
 9419    }
 9420
 9421    pub fn cut_common(&mut self, window: &mut Window, cx: &mut Context<Self>) -> ClipboardItem {
 9422        let mut text = String::new();
 9423        let buffer = self.buffer.read(cx).snapshot(cx);
 9424        let mut selections = self.selections.all::<Point>(cx);
 9425        let mut clipboard_selections = Vec::with_capacity(selections.len());
 9426        {
 9427            let max_point = buffer.max_point();
 9428            let mut is_first = true;
 9429            for selection in &mut selections {
 9430                let is_entire_line = selection.is_empty() || self.selections.line_mode;
 9431                if is_entire_line {
 9432                    selection.start = Point::new(selection.start.row, 0);
 9433                    if !selection.is_empty() && selection.end.column == 0 {
 9434                        selection.end = cmp::min(max_point, selection.end);
 9435                    } else {
 9436                        selection.end = cmp::min(max_point, Point::new(selection.end.row + 1, 0));
 9437                    }
 9438                    selection.goal = SelectionGoal::None;
 9439                }
 9440                if is_first {
 9441                    is_first = false;
 9442                } else {
 9443                    text += "\n";
 9444                }
 9445                let mut len = 0;
 9446                for chunk in buffer.text_for_range(selection.start..selection.end) {
 9447                    text.push_str(chunk);
 9448                    len += chunk.len();
 9449                }
 9450                clipboard_selections.push(ClipboardSelection {
 9451                    len,
 9452                    is_entire_line,
 9453                    first_line_indent: buffer
 9454                        .indent_size_for_line(MultiBufferRow(selection.start.row))
 9455                        .len,
 9456                });
 9457            }
 9458        }
 9459
 9460        self.transact(window, cx, |this, window, cx| {
 9461            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9462                s.select(selections);
 9463            });
 9464            this.insert("", window, cx);
 9465        });
 9466        ClipboardItem::new_string_with_json_metadata(text, clipboard_selections)
 9467    }
 9468
 9469    pub fn cut(&mut self, _: &Cut, window: &mut Window, cx: &mut Context<Self>) {
 9470        let item = self.cut_common(window, cx);
 9471        cx.write_to_clipboard(item);
 9472    }
 9473
 9474    pub fn kill_ring_cut(&mut self, _: &KillRingCut, window: &mut Window, cx: &mut Context<Self>) {
 9475        self.change_selections(None, window, cx, |s| {
 9476            s.move_with(|snapshot, sel| {
 9477                if sel.is_empty() {
 9478                    sel.end = DisplayPoint::new(sel.end.row(), snapshot.line_len(sel.end.row()))
 9479                }
 9480            });
 9481        });
 9482        let item = self.cut_common(window, cx);
 9483        cx.set_global(KillRing(item))
 9484    }
 9485
 9486    pub fn kill_ring_yank(
 9487        &mut self,
 9488        _: &KillRingYank,
 9489        window: &mut Window,
 9490        cx: &mut Context<Self>,
 9491    ) {
 9492        let (text, metadata) = if let Some(KillRing(item)) = cx.try_global() {
 9493            if let Some(ClipboardEntry::String(kill_ring)) = item.entries().first() {
 9494                (kill_ring.text().to_string(), kill_ring.metadata_json())
 9495            } else {
 9496                return;
 9497            }
 9498        } else {
 9499            return;
 9500        };
 9501        self.do_paste(&text, metadata, false, window, cx);
 9502    }
 9503
 9504    pub fn copy_and_trim(&mut self, _: &CopyAndTrim, _: &mut Window, cx: &mut Context<Self>) {
 9505        self.do_copy(true, cx);
 9506    }
 9507
 9508    pub fn copy(&mut self, _: &Copy, _: &mut Window, cx: &mut Context<Self>) {
 9509        self.do_copy(false, cx);
 9510    }
 9511
 9512    fn do_copy(&self, strip_leading_indents: bool, cx: &mut Context<Self>) {
 9513        let selections = self.selections.all::<Point>(cx);
 9514        let buffer = self.buffer.read(cx).read(cx);
 9515        let mut text = String::new();
 9516
 9517        let mut clipboard_selections = Vec::with_capacity(selections.len());
 9518        {
 9519            let max_point = buffer.max_point();
 9520            let mut is_first = true;
 9521            for selection in &selections {
 9522                let mut start = selection.start;
 9523                let mut end = selection.end;
 9524                let is_entire_line = selection.is_empty() || self.selections.line_mode;
 9525                if is_entire_line {
 9526                    start = Point::new(start.row, 0);
 9527                    end = cmp::min(max_point, Point::new(end.row + 1, 0));
 9528                }
 9529
 9530                let mut trimmed_selections = Vec::new();
 9531                if strip_leading_indents && end.row.saturating_sub(start.row) > 0 {
 9532                    let row = MultiBufferRow(start.row);
 9533                    let first_indent = buffer.indent_size_for_line(row);
 9534                    if first_indent.len == 0 || start.column > first_indent.len {
 9535                        trimmed_selections.push(start..end);
 9536                    } else {
 9537                        trimmed_selections.push(
 9538                            Point::new(row.0, first_indent.len)
 9539                                ..Point::new(row.0, buffer.line_len(row)),
 9540                        );
 9541                        for row in start.row + 1..=end.row {
 9542                            let row_indent_size = buffer.indent_size_for_line(MultiBufferRow(row));
 9543                            if row_indent_size.len >= first_indent.len {
 9544                                trimmed_selections.push(
 9545                                    Point::new(row, first_indent.len)
 9546                                        ..Point::new(row, buffer.line_len(MultiBufferRow(row))),
 9547                                );
 9548                            } else {
 9549                                trimmed_selections.clear();
 9550                                trimmed_selections.push(start..end);
 9551                                break;
 9552                            }
 9553                        }
 9554                    }
 9555                } else {
 9556                    trimmed_selections.push(start..end);
 9557                }
 9558
 9559                for trimmed_range in trimmed_selections {
 9560                    if is_first {
 9561                        is_first = false;
 9562                    } else {
 9563                        text += "\n";
 9564                    }
 9565                    let mut len = 0;
 9566                    for chunk in buffer.text_for_range(trimmed_range.start..trimmed_range.end) {
 9567                        text.push_str(chunk);
 9568                        len += chunk.len();
 9569                    }
 9570                    clipboard_selections.push(ClipboardSelection {
 9571                        len,
 9572                        is_entire_line,
 9573                        first_line_indent: buffer
 9574                            .indent_size_for_line(MultiBufferRow(trimmed_range.start.row))
 9575                            .len,
 9576                    });
 9577                }
 9578            }
 9579        }
 9580
 9581        cx.write_to_clipboard(ClipboardItem::new_string_with_json_metadata(
 9582            text,
 9583            clipboard_selections,
 9584        ));
 9585    }
 9586
 9587    pub fn do_paste(
 9588        &mut self,
 9589        text: &String,
 9590        clipboard_selections: Option<Vec<ClipboardSelection>>,
 9591        handle_entire_lines: bool,
 9592        window: &mut Window,
 9593        cx: &mut Context<Self>,
 9594    ) {
 9595        if self.read_only(cx) {
 9596            return;
 9597        }
 9598
 9599        let clipboard_text = Cow::Borrowed(text);
 9600
 9601        self.transact(window, cx, |this, window, cx| {
 9602            if let Some(mut clipboard_selections) = clipboard_selections {
 9603                let old_selections = this.selections.all::<usize>(cx);
 9604                let all_selections_were_entire_line =
 9605                    clipboard_selections.iter().all(|s| s.is_entire_line);
 9606                let first_selection_indent_column =
 9607                    clipboard_selections.first().map(|s| s.first_line_indent);
 9608                if clipboard_selections.len() != old_selections.len() {
 9609                    clipboard_selections.drain(..);
 9610                }
 9611                let cursor_offset = this.selections.last::<usize>(cx).head();
 9612                let mut auto_indent_on_paste = true;
 9613
 9614                this.buffer.update(cx, |buffer, cx| {
 9615                    let snapshot = buffer.read(cx);
 9616                    auto_indent_on_paste = snapshot
 9617                        .language_settings_at(cursor_offset, cx)
 9618                        .auto_indent_on_paste;
 9619
 9620                    let mut start_offset = 0;
 9621                    let mut edits = Vec::new();
 9622                    let mut original_indent_columns = Vec::new();
 9623                    for (ix, selection) in old_selections.iter().enumerate() {
 9624                        let to_insert;
 9625                        let entire_line;
 9626                        let original_indent_column;
 9627                        if let Some(clipboard_selection) = clipboard_selections.get(ix) {
 9628                            let end_offset = start_offset + clipboard_selection.len;
 9629                            to_insert = &clipboard_text[start_offset..end_offset];
 9630                            entire_line = clipboard_selection.is_entire_line;
 9631                            start_offset = end_offset + 1;
 9632                            original_indent_column = Some(clipboard_selection.first_line_indent);
 9633                        } else {
 9634                            to_insert = clipboard_text.as_str();
 9635                            entire_line = all_selections_were_entire_line;
 9636                            original_indent_column = first_selection_indent_column
 9637                        }
 9638
 9639                        // If the corresponding selection was empty when this slice of the
 9640                        // clipboard text was written, then the entire line containing the
 9641                        // selection was copied. If this selection is also currently empty,
 9642                        // then paste the line before the current line of the buffer.
 9643                        let range = if selection.is_empty() && handle_entire_lines && entire_line {
 9644                            let column = selection.start.to_point(&snapshot).column as usize;
 9645                            let line_start = selection.start - column;
 9646                            line_start..line_start
 9647                        } else {
 9648                            selection.range()
 9649                        };
 9650
 9651                        edits.push((range, to_insert));
 9652                        original_indent_columns.push(original_indent_column);
 9653                    }
 9654                    drop(snapshot);
 9655
 9656                    buffer.edit(
 9657                        edits,
 9658                        if auto_indent_on_paste {
 9659                            Some(AutoindentMode::Block {
 9660                                original_indent_columns,
 9661                            })
 9662                        } else {
 9663                            None
 9664                        },
 9665                        cx,
 9666                    );
 9667                });
 9668
 9669                let selections = this.selections.all::<usize>(cx);
 9670                this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9671                    s.select(selections)
 9672                });
 9673            } else {
 9674                this.insert(&clipboard_text, window, cx);
 9675            }
 9676        });
 9677    }
 9678
 9679    pub fn paste(&mut self, _: &Paste, window: &mut Window, cx: &mut Context<Self>) {
 9680        if let Some(item) = cx.read_from_clipboard() {
 9681            let entries = item.entries();
 9682
 9683            match entries.first() {
 9684                // For now, we only support applying metadata if there's one string. In the future, we can incorporate all the selections
 9685                // of all the pasted entries.
 9686                Some(ClipboardEntry::String(clipboard_string)) if entries.len() == 1 => self
 9687                    .do_paste(
 9688                        clipboard_string.text(),
 9689                        clipboard_string.metadata_json::<Vec<ClipboardSelection>>(),
 9690                        true,
 9691                        window,
 9692                        cx,
 9693                    ),
 9694                _ => self.do_paste(&item.text().unwrap_or_default(), None, true, window, cx),
 9695            }
 9696        }
 9697    }
 9698
 9699    pub fn undo(&mut self, _: &Undo, window: &mut Window, cx: &mut Context<Self>) {
 9700        if self.read_only(cx) {
 9701            return;
 9702        }
 9703
 9704        if let Some(transaction_id) = self.buffer.update(cx, |buffer, cx| buffer.undo(cx)) {
 9705            if let Some((selections, _)) =
 9706                self.selection_history.transaction(transaction_id).cloned()
 9707            {
 9708                self.change_selections(None, window, cx, |s| {
 9709                    s.select_anchors(selections.to_vec());
 9710                });
 9711            } else {
 9712                log::error!(
 9713                    "No entry in selection_history found for undo. \
 9714                     This may correspond to a bug where undo does not update the selection. \
 9715                     If this is occurring, please add details to \
 9716                     https://github.com/zed-industries/zed/issues/22692"
 9717                );
 9718            }
 9719            self.request_autoscroll(Autoscroll::fit(), cx);
 9720            self.unmark_text(window, cx);
 9721            self.refresh_inline_completion(true, false, window, cx);
 9722            cx.emit(EditorEvent::Edited { transaction_id });
 9723            cx.emit(EditorEvent::TransactionUndone { transaction_id });
 9724        }
 9725    }
 9726
 9727    pub fn redo(&mut self, _: &Redo, window: &mut Window, cx: &mut Context<Self>) {
 9728        if self.read_only(cx) {
 9729            return;
 9730        }
 9731
 9732        if let Some(transaction_id) = self.buffer.update(cx, |buffer, cx| buffer.redo(cx)) {
 9733            if let Some((_, Some(selections))) =
 9734                self.selection_history.transaction(transaction_id).cloned()
 9735            {
 9736                self.change_selections(None, window, cx, |s| {
 9737                    s.select_anchors(selections.to_vec());
 9738                });
 9739            } else {
 9740                log::error!(
 9741                    "No entry in selection_history found for redo. \
 9742                     This may correspond to a bug where undo does not update the selection. \
 9743                     If this is occurring, please add details to \
 9744                     https://github.com/zed-industries/zed/issues/22692"
 9745                );
 9746            }
 9747            self.request_autoscroll(Autoscroll::fit(), cx);
 9748            self.unmark_text(window, cx);
 9749            self.refresh_inline_completion(true, false, window, cx);
 9750            cx.emit(EditorEvent::Edited { transaction_id });
 9751        }
 9752    }
 9753
 9754    pub fn finalize_last_transaction(&mut self, cx: &mut Context<Self>) {
 9755        self.buffer
 9756            .update(cx, |buffer, cx| buffer.finalize_last_transaction(cx));
 9757    }
 9758
 9759    pub fn group_until_transaction(&mut self, tx_id: TransactionId, cx: &mut Context<Self>) {
 9760        self.buffer
 9761            .update(cx, |buffer, cx| buffer.group_until_transaction(tx_id, cx));
 9762    }
 9763
 9764    pub fn move_left(&mut self, _: &MoveLeft, window: &mut Window, cx: &mut Context<Self>) {
 9765        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9766            let line_mode = s.line_mode;
 9767            s.move_with(|map, selection| {
 9768                let cursor = if selection.is_empty() && !line_mode {
 9769                    movement::left(map, selection.start)
 9770                } else {
 9771                    selection.start
 9772                };
 9773                selection.collapse_to(cursor, SelectionGoal::None);
 9774            });
 9775        })
 9776    }
 9777
 9778    pub fn select_left(&mut self, _: &SelectLeft, window: &mut Window, cx: &mut Context<Self>) {
 9779        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9780            s.move_heads_with(|map, head, _| (movement::left(map, head), SelectionGoal::None));
 9781        })
 9782    }
 9783
 9784    pub fn move_right(&mut self, _: &MoveRight, window: &mut Window, cx: &mut Context<Self>) {
 9785        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9786            let line_mode = s.line_mode;
 9787            s.move_with(|map, selection| {
 9788                let cursor = if selection.is_empty() && !line_mode {
 9789                    movement::right(map, selection.end)
 9790                } else {
 9791                    selection.end
 9792                };
 9793                selection.collapse_to(cursor, SelectionGoal::None)
 9794            });
 9795        })
 9796    }
 9797
 9798    pub fn select_right(&mut self, _: &SelectRight, window: &mut Window, cx: &mut Context<Self>) {
 9799        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9800            s.move_heads_with(|map, head, _| (movement::right(map, head), SelectionGoal::None));
 9801        })
 9802    }
 9803
 9804    pub fn move_up(&mut self, _: &MoveUp, window: &mut Window, cx: &mut Context<Self>) {
 9805        if self.take_rename(true, window, cx).is_some() {
 9806            return;
 9807        }
 9808
 9809        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 9810            cx.propagate();
 9811            return;
 9812        }
 9813
 9814        let text_layout_details = &self.text_layout_details(window);
 9815        let selection_count = self.selections.count();
 9816        let first_selection = self.selections.first_anchor();
 9817
 9818        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9819            let line_mode = s.line_mode;
 9820            s.move_with(|map, selection| {
 9821                if !selection.is_empty() && !line_mode {
 9822                    selection.goal = SelectionGoal::None;
 9823                }
 9824                let (cursor, goal) = movement::up(
 9825                    map,
 9826                    selection.start,
 9827                    selection.goal,
 9828                    false,
 9829                    text_layout_details,
 9830                );
 9831                selection.collapse_to(cursor, goal);
 9832            });
 9833        });
 9834
 9835        if selection_count == 1 && first_selection.range() == self.selections.first_anchor().range()
 9836        {
 9837            cx.propagate();
 9838        }
 9839    }
 9840
 9841    pub fn move_up_by_lines(
 9842        &mut self,
 9843        action: &MoveUpByLines,
 9844        window: &mut Window,
 9845        cx: &mut Context<Self>,
 9846    ) {
 9847        if self.take_rename(true, window, cx).is_some() {
 9848            return;
 9849        }
 9850
 9851        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 9852            cx.propagate();
 9853            return;
 9854        }
 9855
 9856        let text_layout_details = &self.text_layout_details(window);
 9857
 9858        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9859            let line_mode = s.line_mode;
 9860            s.move_with(|map, selection| {
 9861                if !selection.is_empty() && !line_mode {
 9862                    selection.goal = SelectionGoal::None;
 9863                }
 9864                let (cursor, goal) = movement::up_by_rows(
 9865                    map,
 9866                    selection.start,
 9867                    action.lines,
 9868                    selection.goal,
 9869                    false,
 9870                    text_layout_details,
 9871                );
 9872                selection.collapse_to(cursor, goal);
 9873            });
 9874        })
 9875    }
 9876
 9877    pub fn move_down_by_lines(
 9878        &mut self,
 9879        action: &MoveDownByLines,
 9880        window: &mut Window,
 9881        cx: &mut Context<Self>,
 9882    ) {
 9883        if self.take_rename(true, window, cx).is_some() {
 9884            return;
 9885        }
 9886
 9887        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 9888            cx.propagate();
 9889            return;
 9890        }
 9891
 9892        let text_layout_details = &self.text_layout_details(window);
 9893
 9894        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9895            let line_mode = s.line_mode;
 9896            s.move_with(|map, selection| {
 9897                if !selection.is_empty() && !line_mode {
 9898                    selection.goal = SelectionGoal::None;
 9899                }
 9900                let (cursor, goal) = movement::down_by_rows(
 9901                    map,
 9902                    selection.start,
 9903                    action.lines,
 9904                    selection.goal,
 9905                    false,
 9906                    text_layout_details,
 9907                );
 9908                selection.collapse_to(cursor, goal);
 9909            });
 9910        })
 9911    }
 9912
 9913    pub fn select_down_by_lines(
 9914        &mut self,
 9915        action: &SelectDownByLines,
 9916        window: &mut Window,
 9917        cx: &mut Context<Self>,
 9918    ) {
 9919        let text_layout_details = &self.text_layout_details(window);
 9920        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9921            s.move_heads_with(|map, head, goal| {
 9922                movement::down_by_rows(map, head, action.lines, goal, false, text_layout_details)
 9923            })
 9924        })
 9925    }
 9926
 9927    pub fn select_up_by_lines(
 9928        &mut self,
 9929        action: &SelectUpByLines,
 9930        window: &mut Window,
 9931        cx: &mut Context<Self>,
 9932    ) {
 9933        let text_layout_details = &self.text_layout_details(window);
 9934        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9935            s.move_heads_with(|map, head, goal| {
 9936                movement::up_by_rows(map, head, action.lines, goal, false, text_layout_details)
 9937            })
 9938        })
 9939    }
 9940
 9941    pub fn select_page_up(
 9942        &mut self,
 9943        _: &SelectPageUp,
 9944        window: &mut Window,
 9945        cx: &mut Context<Self>,
 9946    ) {
 9947        let Some(row_count) = self.visible_row_count() else {
 9948            return;
 9949        };
 9950
 9951        let text_layout_details = &self.text_layout_details(window);
 9952
 9953        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9954            s.move_heads_with(|map, head, goal| {
 9955                movement::up_by_rows(map, head, row_count, goal, false, text_layout_details)
 9956            })
 9957        })
 9958    }
 9959
 9960    pub fn move_page_up(
 9961        &mut self,
 9962        action: &MovePageUp,
 9963        window: &mut Window,
 9964        cx: &mut Context<Self>,
 9965    ) {
 9966        if self.take_rename(true, window, cx).is_some() {
 9967            return;
 9968        }
 9969
 9970        if self
 9971            .context_menu
 9972            .borrow_mut()
 9973            .as_mut()
 9974            .map(|menu| menu.select_first(self.completion_provider.as_deref(), cx))
 9975            .unwrap_or(false)
 9976        {
 9977            return;
 9978        }
 9979
 9980        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 9981            cx.propagate();
 9982            return;
 9983        }
 9984
 9985        let Some(row_count) = self.visible_row_count() else {
 9986            return;
 9987        };
 9988
 9989        let autoscroll = if action.center_cursor {
 9990            Autoscroll::center()
 9991        } else {
 9992            Autoscroll::fit()
 9993        };
 9994
 9995        let text_layout_details = &self.text_layout_details(window);
 9996
 9997        self.change_selections(Some(autoscroll), window, cx, |s| {
 9998            let line_mode = s.line_mode;
 9999            s.move_with(|map, selection| {
10000                if !selection.is_empty() && !line_mode {
10001                    selection.goal = SelectionGoal::None;
10002                }
10003                let (cursor, goal) = movement::up_by_rows(
10004                    map,
10005                    selection.end,
10006                    row_count,
10007                    selection.goal,
10008                    false,
10009                    text_layout_details,
10010                );
10011                selection.collapse_to(cursor, goal);
10012            });
10013        });
10014    }
10015
10016    pub fn select_up(&mut self, _: &SelectUp, window: &mut Window, cx: &mut Context<Self>) {
10017        let text_layout_details = &self.text_layout_details(window);
10018        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10019            s.move_heads_with(|map, head, goal| {
10020                movement::up(map, head, goal, false, text_layout_details)
10021            })
10022        })
10023    }
10024
10025    pub fn move_down(&mut self, _: &MoveDown, window: &mut Window, cx: &mut Context<Self>) {
10026        self.take_rename(true, window, cx);
10027
10028        if matches!(self.mode, EditorMode::SingleLine { .. }) {
10029            cx.propagate();
10030            return;
10031        }
10032
10033        let text_layout_details = &self.text_layout_details(window);
10034        let selection_count = self.selections.count();
10035        let first_selection = self.selections.first_anchor();
10036
10037        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10038            let line_mode = s.line_mode;
10039            s.move_with(|map, selection| {
10040                if !selection.is_empty() && !line_mode {
10041                    selection.goal = SelectionGoal::None;
10042                }
10043                let (cursor, goal) = movement::down(
10044                    map,
10045                    selection.end,
10046                    selection.goal,
10047                    false,
10048                    text_layout_details,
10049                );
10050                selection.collapse_to(cursor, goal);
10051            });
10052        });
10053
10054        if selection_count == 1 && first_selection.range() == self.selections.first_anchor().range()
10055        {
10056            cx.propagate();
10057        }
10058    }
10059
10060    pub fn select_page_down(
10061        &mut self,
10062        _: &SelectPageDown,
10063        window: &mut Window,
10064        cx: &mut Context<Self>,
10065    ) {
10066        let Some(row_count) = self.visible_row_count() else {
10067            return;
10068        };
10069
10070        let text_layout_details = &self.text_layout_details(window);
10071
10072        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10073            s.move_heads_with(|map, head, goal| {
10074                movement::down_by_rows(map, head, row_count, goal, false, text_layout_details)
10075            })
10076        })
10077    }
10078
10079    pub fn move_page_down(
10080        &mut self,
10081        action: &MovePageDown,
10082        window: &mut Window,
10083        cx: &mut Context<Self>,
10084    ) {
10085        if self.take_rename(true, window, cx).is_some() {
10086            return;
10087        }
10088
10089        if self
10090            .context_menu
10091            .borrow_mut()
10092            .as_mut()
10093            .map(|menu| menu.select_last(self.completion_provider.as_deref(), cx))
10094            .unwrap_or(false)
10095        {
10096            return;
10097        }
10098
10099        if matches!(self.mode, EditorMode::SingleLine { .. }) {
10100            cx.propagate();
10101            return;
10102        }
10103
10104        let Some(row_count) = self.visible_row_count() else {
10105            return;
10106        };
10107
10108        let autoscroll = if action.center_cursor {
10109            Autoscroll::center()
10110        } else {
10111            Autoscroll::fit()
10112        };
10113
10114        let text_layout_details = &self.text_layout_details(window);
10115        self.change_selections(Some(autoscroll), window, cx, |s| {
10116            let line_mode = s.line_mode;
10117            s.move_with(|map, selection| {
10118                if !selection.is_empty() && !line_mode {
10119                    selection.goal = SelectionGoal::None;
10120                }
10121                let (cursor, goal) = movement::down_by_rows(
10122                    map,
10123                    selection.end,
10124                    row_count,
10125                    selection.goal,
10126                    false,
10127                    text_layout_details,
10128                );
10129                selection.collapse_to(cursor, goal);
10130            });
10131        });
10132    }
10133
10134    pub fn select_down(&mut self, _: &SelectDown, window: &mut Window, cx: &mut Context<Self>) {
10135        let text_layout_details = &self.text_layout_details(window);
10136        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10137            s.move_heads_with(|map, head, goal| {
10138                movement::down(map, head, goal, false, text_layout_details)
10139            })
10140        });
10141    }
10142
10143    pub fn context_menu_first(
10144        &mut self,
10145        _: &ContextMenuFirst,
10146        _window: &mut Window,
10147        cx: &mut Context<Self>,
10148    ) {
10149        if let Some(context_menu) = self.context_menu.borrow_mut().as_mut() {
10150            context_menu.select_first(self.completion_provider.as_deref(), cx);
10151        }
10152    }
10153
10154    pub fn context_menu_prev(
10155        &mut self,
10156        _: &ContextMenuPrevious,
10157        _window: &mut Window,
10158        cx: &mut Context<Self>,
10159    ) {
10160        if let Some(context_menu) = self.context_menu.borrow_mut().as_mut() {
10161            context_menu.select_prev(self.completion_provider.as_deref(), cx);
10162        }
10163    }
10164
10165    pub fn context_menu_next(
10166        &mut self,
10167        _: &ContextMenuNext,
10168        _window: &mut Window,
10169        cx: &mut Context<Self>,
10170    ) {
10171        if let Some(context_menu) = self.context_menu.borrow_mut().as_mut() {
10172            context_menu.select_next(self.completion_provider.as_deref(), cx);
10173        }
10174    }
10175
10176    pub fn context_menu_last(
10177        &mut self,
10178        _: &ContextMenuLast,
10179        _window: &mut Window,
10180        cx: &mut Context<Self>,
10181    ) {
10182        if let Some(context_menu) = self.context_menu.borrow_mut().as_mut() {
10183            context_menu.select_last(self.completion_provider.as_deref(), cx);
10184        }
10185    }
10186
10187    pub fn move_to_previous_word_start(
10188        &mut self,
10189        _: &MoveToPreviousWordStart,
10190        window: &mut Window,
10191        cx: &mut Context<Self>,
10192    ) {
10193        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10194            s.move_cursors_with(|map, head, _| {
10195                (
10196                    movement::previous_word_start(map, head),
10197                    SelectionGoal::None,
10198                )
10199            });
10200        })
10201    }
10202
10203    pub fn move_to_previous_subword_start(
10204        &mut self,
10205        _: &MoveToPreviousSubwordStart,
10206        window: &mut Window,
10207        cx: &mut Context<Self>,
10208    ) {
10209        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10210            s.move_cursors_with(|map, head, _| {
10211                (
10212                    movement::previous_subword_start(map, head),
10213                    SelectionGoal::None,
10214                )
10215            });
10216        })
10217    }
10218
10219    pub fn select_to_previous_word_start(
10220        &mut self,
10221        _: &SelectToPreviousWordStart,
10222        window: &mut Window,
10223        cx: &mut Context<Self>,
10224    ) {
10225        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10226            s.move_heads_with(|map, head, _| {
10227                (
10228                    movement::previous_word_start(map, head),
10229                    SelectionGoal::None,
10230                )
10231            });
10232        })
10233    }
10234
10235    pub fn select_to_previous_subword_start(
10236        &mut self,
10237        _: &SelectToPreviousSubwordStart,
10238        window: &mut Window,
10239        cx: &mut Context<Self>,
10240    ) {
10241        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10242            s.move_heads_with(|map, head, _| {
10243                (
10244                    movement::previous_subword_start(map, head),
10245                    SelectionGoal::None,
10246                )
10247            });
10248        })
10249    }
10250
10251    pub fn delete_to_previous_word_start(
10252        &mut self,
10253        action: &DeleteToPreviousWordStart,
10254        window: &mut Window,
10255        cx: &mut Context<Self>,
10256    ) {
10257        self.transact(window, cx, |this, window, cx| {
10258            this.select_autoclose_pair(window, cx);
10259            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10260                let line_mode = s.line_mode;
10261                s.move_with(|map, selection| {
10262                    if selection.is_empty() && !line_mode {
10263                        let cursor = if action.ignore_newlines {
10264                            movement::previous_word_start(map, selection.head())
10265                        } else {
10266                            movement::previous_word_start_or_newline(map, selection.head())
10267                        };
10268                        selection.set_head(cursor, SelectionGoal::None);
10269                    }
10270                });
10271            });
10272            this.insert("", window, cx);
10273        });
10274    }
10275
10276    pub fn delete_to_previous_subword_start(
10277        &mut self,
10278        _: &DeleteToPreviousSubwordStart,
10279        window: &mut Window,
10280        cx: &mut Context<Self>,
10281    ) {
10282        self.transact(window, cx, |this, window, cx| {
10283            this.select_autoclose_pair(window, cx);
10284            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10285                let line_mode = s.line_mode;
10286                s.move_with(|map, selection| {
10287                    if selection.is_empty() && !line_mode {
10288                        let cursor = movement::previous_subword_start(map, selection.head());
10289                        selection.set_head(cursor, SelectionGoal::None);
10290                    }
10291                });
10292            });
10293            this.insert("", window, cx);
10294        });
10295    }
10296
10297    pub fn move_to_next_word_end(
10298        &mut self,
10299        _: &MoveToNextWordEnd,
10300        window: &mut Window,
10301        cx: &mut Context<Self>,
10302    ) {
10303        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10304            s.move_cursors_with(|map, head, _| {
10305                (movement::next_word_end(map, head), SelectionGoal::None)
10306            });
10307        })
10308    }
10309
10310    pub fn move_to_next_subword_end(
10311        &mut self,
10312        _: &MoveToNextSubwordEnd,
10313        window: &mut Window,
10314        cx: &mut Context<Self>,
10315    ) {
10316        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10317            s.move_cursors_with(|map, head, _| {
10318                (movement::next_subword_end(map, head), SelectionGoal::None)
10319            });
10320        })
10321    }
10322
10323    pub fn select_to_next_word_end(
10324        &mut self,
10325        _: &SelectToNextWordEnd,
10326        window: &mut Window,
10327        cx: &mut Context<Self>,
10328    ) {
10329        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10330            s.move_heads_with(|map, head, _| {
10331                (movement::next_word_end(map, head), SelectionGoal::None)
10332            });
10333        })
10334    }
10335
10336    pub fn select_to_next_subword_end(
10337        &mut self,
10338        _: &SelectToNextSubwordEnd,
10339        window: &mut Window,
10340        cx: &mut Context<Self>,
10341    ) {
10342        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10343            s.move_heads_with(|map, head, _| {
10344                (movement::next_subword_end(map, head), SelectionGoal::None)
10345            });
10346        })
10347    }
10348
10349    pub fn delete_to_next_word_end(
10350        &mut self,
10351        action: &DeleteToNextWordEnd,
10352        window: &mut Window,
10353        cx: &mut Context<Self>,
10354    ) {
10355        self.transact(window, cx, |this, window, cx| {
10356            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10357                let line_mode = s.line_mode;
10358                s.move_with(|map, selection| {
10359                    if selection.is_empty() && !line_mode {
10360                        let cursor = if action.ignore_newlines {
10361                            movement::next_word_end(map, selection.head())
10362                        } else {
10363                            movement::next_word_end_or_newline(map, selection.head())
10364                        };
10365                        selection.set_head(cursor, SelectionGoal::None);
10366                    }
10367                });
10368            });
10369            this.insert("", window, cx);
10370        });
10371    }
10372
10373    pub fn delete_to_next_subword_end(
10374        &mut self,
10375        _: &DeleteToNextSubwordEnd,
10376        window: &mut Window,
10377        cx: &mut Context<Self>,
10378    ) {
10379        self.transact(window, cx, |this, window, cx| {
10380            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10381                s.move_with(|map, selection| {
10382                    if selection.is_empty() {
10383                        let cursor = movement::next_subword_end(map, selection.head());
10384                        selection.set_head(cursor, SelectionGoal::None);
10385                    }
10386                });
10387            });
10388            this.insert("", window, cx);
10389        });
10390    }
10391
10392    pub fn move_to_beginning_of_line(
10393        &mut self,
10394        action: &MoveToBeginningOfLine,
10395        window: &mut Window,
10396        cx: &mut Context<Self>,
10397    ) {
10398        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10399            s.move_cursors_with(|map, head, _| {
10400                (
10401                    movement::indented_line_beginning(
10402                        map,
10403                        head,
10404                        action.stop_at_soft_wraps,
10405                        action.stop_at_indent,
10406                    ),
10407                    SelectionGoal::None,
10408                )
10409            });
10410        })
10411    }
10412
10413    pub fn select_to_beginning_of_line(
10414        &mut self,
10415        action: &SelectToBeginningOfLine,
10416        window: &mut Window,
10417        cx: &mut Context<Self>,
10418    ) {
10419        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10420            s.move_heads_with(|map, head, _| {
10421                (
10422                    movement::indented_line_beginning(
10423                        map,
10424                        head,
10425                        action.stop_at_soft_wraps,
10426                        action.stop_at_indent,
10427                    ),
10428                    SelectionGoal::None,
10429                )
10430            });
10431        });
10432    }
10433
10434    pub fn delete_to_beginning_of_line(
10435        &mut self,
10436        action: &DeleteToBeginningOfLine,
10437        window: &mut Window,
10438        cx: &mut Context<Self>,
10439    ) {
10440        self.transact(window, cx, |this, window, cx| {
10441            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10442                s.move_with(|_, selection| {
10443                    selection.reversed = true;
10444                });
10445            });
10446
10447            this.select_to_beginning_of_line(
10448                &SelectToBeginningOfLine {
10449                    stop_at_soft_wraps: false,
10450                    stop_at_indent: action.stop_at_indent,
10451                },
10452                window,
10453                cx,
10454            );
10455            this.backspace(&Backspace, window, cx);
10456        });
10457    }
10458
10459    pub fn move_to_end_of_line(
10460        &mut self,
10461        action: &MoveToEndOfLine,
10462        window: &mut Window,
10463        cx: &mut Context<Self>,
10464    ) {
10465        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10466            s.move_cursors_with(|map, head, _| {
10467                (
10468                    movement::line_end(map, head, action.stop_at_soft_wraps),
10469                    SelectionGoal::None,
10470                )
10471            });
10472        })
10473    }
10474
10475    pub fn select_to_end_of_line(
10476        &mut self,
10477        action: &SelectToEndOfLine,
10478        window: &mut Window,
10479        cx: &mut Context<Self>,
10480    ) {
10481        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10482            s.move_heads_with(|map, head, _| {
10483                (
10484                    movement::line_end(map, head, action.stop_at_soft_wraps),
10485                    SelectionGoal::None,
10486                )
10487            });
10488        })
10489    }
10490
10491    pub fn delete_to_end_of_line(
10492        &mut self,
10493        _: &DeleteToEndOfLine,
10494        window: &mut Window,
10495        cx: &mut Context<Self>,
10496    ) {
10497        self.transact(window, cx, |this, window, cx| {
10498            this.select_to_end_of_line(
10499                &SelectToEndOfLine {
10500                    stop_at_soft_wraps: false,
10501                },
10502                window,
10503                cx,
10504            );
10505            this.delete(&Delete, window, cx);
10506        });
10507    }
10508
10509    pub fn cut_to_end_of_line(
10510        &mut self,
10511        _: &CutToEndOfLine,
10512        window: &mut Window,
10513        cx: &mut Context<Self>,
10514    ) {
10515        self.transact(window, cx, |this, window, cx| {
10516            this.select_to_end_of_line(
10517                &SelectToEndOfLine {
10518                    stop_at_soft_wraps: false,
10519                },
10520                window,
10521                cx,
10522            );
10523            this.cut(&Cut, window, cx);
10524        });
10525    }
10526
10527    pub fn move_to_start_of_paragraph(
10528        &mut self,
10529        _: &MoveToStartOfParagraph,
10530        window: &mut Window,
10531        cx: &mut Context<Self>,
10532    ) {
10533        if matches!(self.mode, EditorMode::SingleLine { .. }) {
10534            cx.propagate();
10535            return;
10536        }
10537
10538        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10539            s.move_with(|map, selection| {
10540                selection.collapse_to(
10541                    movement::start_of_paragraph(map, selection.head(), 1),
10542                    SelectionGoal::None,
10543                )
10544            });
10545        })
10546    }
10547
10548    pub fn move_to_end_of_paragraph(
10549        &mut self,
10550        _: &MoveToEndOfParagraph,
10551        window: &mut Window,
10552        cx: &mut Context<Self>,
10553    ) {
10554        if matches!(self.mode, EditorMode::SingleLine { .. }) {
10555            cx.propagate();
10556            return;
10557        }
10558
10559        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10560            s.move_with(|map, selection| {
10561                selection.collapse_to(
10562                    movement::end_of_paragraph(map, selection.head(), 1),
10563                    SelectionGoal::None,
10564                )
10565            });
10566        })
10567    }
10568
10569    pub fn select_to_start_of_paragraph(
10570        &mut self,
10571        _: &SelectToStartOfParagraph,
10572        window: &mut Window,
10573        cx: &mut Context<Self>,
10574    ) {
10575        if matches!(self.mode, EditorMode::SingleLine { .. }) {
10576            cx.propagate();
10577            return;
10578        }
10579
10580        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10581            s.move_heads_with(|map, head, _| {
10582                (
10583                    movement::start_of_paragraph(map, head, 1),
10584                    SelectionGoal::None,
10585                )
10586            });
10587        })
10588    }
10589
10590    pub fn select_to_end_of_paragraph(
10591        &mut self,
10592        _: &SelectToEndOfParagraph,
10593        window: &mut Window,
10594        cx: &mut Context<Self>,
10595    ) {
10596        if matches!(self.mode, EditorMode::SingleLine { .. }) {
10597            cx.propagate();
10598            return;
10599        }
10600
10601        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10602            s.move_heads_with(|map, head, _| {
10603                (
10604                    movement::end_of_paragraph(map, head, 1),
10605                    SelectionGoal::None,
10606                )
10607            });
10608        })
10609    }
10610
10611    pub fn move_to_start_of_excerpt(
10612        &mut self,
10613        _: &MoveToStartOfExcerpt,
10614        window: &mut Window,
10615        cx: &mut Context<Self>,
10616    ) {
10617        if matches!(self.mode, EditorMode::SingleLine { .. }) {
10618            cx.propagate();
10619            return;
10620        }
10621
10622        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10623            s.move_with(|map, selection| {
10624                selection.collapse_to(
10625                    movement::start_of_excerpt(
10626                        map,
10627                        selection.head(),
10628                        workspace::searchable::Direction::Prev,
10629                    ),
10630                    SelectionGoal::None,
10631                )
10632            });
10633        })
10634    }
10635
10636    pub fn move_to_start_of_next_excerpt(
10637        &mut self,
10638        _: &MoveToStartOfNextExcerpt,
10639        window: &mut Window,
10640        cx: &mut Context<Self>,
10641    ) {
10642        if matches!(self.mode, EditorMode::SingleLine { .. }) {
10643            cx.propagate();
10644            return;
10645        }
10646
10647        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10648            s.move_with(|map, selection| {
10649                selection.collapse_to(
10650                    movement::start_of_excerpt(
10651                        map,
10652                        selection.head(),
10653                        workspace::searchable::Direction::Next,
10654                    ),
10655                    SelectionGoal::None,
10656                )
10657            });
10658        })
10659    }
10660
10661    pub fn move_to_end_of_excerpt(
10662        &mut self,
10663        _: &MoveToEndOfExcerpt,
10664        window: &mut Window,
10665        cx: &mut Context<Self>,
10666    ) {
10667        if matches!(self.mode, EditorMode::SingleLine { .. }) {
10668            cx.propagate();
10669            return;
10670        }
10671
10672        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10673            s.move_with(|map, selection| {
10674                selection.collapse_to(
10675                    movement::end_of_excerpt(
10676                        map,
10677                        selection.head(),
10678                        workspace::searchable::Direction::Next,
10679                    ),
10680                    SelectionGoal::None,
10681                )
10682            });
10683        })
10684    }
10685
10686    pub fn move_to_end_of_previous_excerpt(
10687        &mut self,
10688        _: &MoveToEndOfPreviousExcerpt,
10689        window: &mut Window,
10690        cx: &mut Context<Self>,
10691    ) {
10692        if matches!(self.mode, EditorMode::SingleLine { .. }) {
10693            cx.propagate();
10694            return;
10695        }
10696
10697        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10698            s.move_with(|map, selection| {
10699                selection.collapse_to(
10700                    movement::end_of_excerpt(
10701                        map,
10702                        selection.head(),
10703                        workspace::searchable::Direction::Prev,
10704                    ),
10705                    SelectionGoal::None,
10706                )
10707            });
10708        })
10709    }
10710
10711    pub fn select_to_start_of_excerpt(
10712        &mut self,
10713        _: &SelectToStartOfExcerpt,
10714        window: &mut Window,
10715        cx: &mut Context<Self>,
10716    ) {
10717        if matches!(self.mode, EditorMode::SingleLine { .. }) {
10718            cx.propagate();
10719            return;
10720        }
10721
10722        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10723            s.move_heads_with(|map, head, _| {
10724                (
10725                    movement::start_of_excerpt(map, head, workspace::searchable::Direction::Prev),
10726                    SelectionGoal::None,
10727                )
10728            });
10729        })
10730    }
10731
10732    pub fn select_to_start_of_next_excerpt(
10733        &mut self,
10734        _: &SelectToStartOfNextExcerpt,
10735        window: &mut Window,
10736        cx: &mut Context<Self>,
10737    ) {
10738        if matches!(self.mode, EditorMode::SingleLine { .. }) {
10739            cx.propagate();
10740            return;
10741        }
10742
10743        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10744            s.move_heads_with(|map, head, _| {
10745                (
10746                    movement::start_of_excerpt(map, head, workspace::searchable::Direction::Next),
10747                    SelectionGoal::None,
10748                )
10749            });
10750        })
10751    }
10752
10753    pub fn select_to_end_of_excerpt(
10754        &mut self,
10755        _: &SelectToEndOfExcerpt,
10756        window: &mut Window,
10757        cx: &mut Context<Self>,
10758    ) {
10759        if matches!(self.mode, EditorMode::SingleLine { .. }) {
10760            cx.propagate();
10761            return;
10762        }
10763
10764        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10765            s.move_heads_with(|map, head, _| {
10766                (
10767                    movement::end_of_excerpt(map, head, workspace::searchable::Direction::Next),
10768                    SelectionGoal::None,
10769                )
10770            });
10771        })
10772    }
10773
10774    pub fn select_to_end_of_previous_excerpt(
10775        &mut self,
10776        _: &SelectToEndOfPreviousExcerpt,
10777        window: &mut Window,
10778        cx: &mut Context<Self>,
10779    ) {
10780        if matches!(self.mode, EditorMode::SingleLine { .. }) {
10781            cx.propagate();
10782            return;
10783        }
10784
10785        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10786            s.move_heads_with(|map, head, _| {
10787                (
10788                    movement::end_of_excerpt(map, head, workspace::searchable::Direction::Prev),
10789                    SelectionGoal::None,
10790                )
10791            });
10792        })
10793    }
10794
10795    pub fn move_to_beginning(
10796        &mut self,
10797        _: &MoveToBeginning,
10798        window: &mut Window,
10799        cx: &mut Context<Self>,
10800    ) {
10801        if matches!(self.mode, EditorMode::SingleLine { .. }) {
10802            cx.propagate();
10803            return;
10804        }
10805
10806        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10807            s.select_ranges(vec![0..0]);
10808        });
10809    }
10810
10811    pub fn select_to_beginning(
10812        &mut self,
10813        _: &SelectToBeginning,
10814        window: &mut Window,
10815        cx: &mut Context<Self>,
10816    ) {
10817        let mut selection = self.selections.last::<Point>(cx);
10818        selection.set_head(Point::zero(), SelectionGoal::None);
10819
10820        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10821            s.select(vec![selection]);
10822        });
10823    }
10824
10825    pub fn move_to_end(&mut self, _: &MoveToEnd, window: &mut Window, cx: &mut Context<Self>) {
10826        if matches!(self.mode, EditorMode::SingleLine { .. }) {
10827            cx.propagate();
10828            return;
10829        }
10830
10831        let cursor = self.buffer.read(cx).read(cx).len();
10832        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10833            s.select_ranges(vec![cursor..cursor])
10834        });
10835    }
10836
10837    pub fn set_nav_history(&mut self, nav_history: Option<ItemNavHistory>) {
10838        self.nav_history = nav_history;
10839    }
10840
10841    pub fn nav_history(&self) -> Option<&ItemNavHistory> {
10842        self.nav_history.as_ref()
10843    }
10844
10845    pub fn create_nav_history_entry(&mut self, cx: &mut Context<Self>) {
10846        self.push_to_nav_history(self.selections.newest_anchor().head(), None, false, cx);
10847    }
10848
10849    fn push_to_nav_history(
10850        &mut self,
10851        cursor_anchor: Anchor,
10852        new_position: Option<Point>,
10853        is_deactivate: bool,
10854        cx: &mut Context<Self>,
10855    ) {
10856        if let Some(nav_history) = self.nav_history.as_mut() {
10857            let buffer = self.buffer.read(cx).read(cx);
10858            let cursor_position = cursor_anchor.to_point(&buffer);
10859            let scroll_state = self.scroll_manager.anchor();
10860            let scroll_top_row = scroll_state.top_row(&buffer);
10861            drop(buffer);
10862
10863            if let Some(new_position) = new_position {
10864                let row_delta = (new_position.row as i64 - cursor_position.row as i64).abs();
10865                if row_delta < MIN_NAVIGATION_HISTORY_ROW_DELTA {
10866                    return;
10867                }
10868            }
10869
10870            nav_history.push(
10871                Some(NavigationData {
10872                    cursor_anchor,
10873                    cursor_position,
10874                    scroll_anchor: scroll_state,
10875                    scroll_top_row,
10876                }),
10877                cx,
10878            );
10879            cx.emit(EditorEvent::PushedToNavHistory {
10880                anchor: cursor_anchor,
10881                is_deactivate,
10882            })
10883        }
10884    }
10885
10886    pub fn select_to_end(&mut self, _: &SelectToEnd, window: &mut Window, cx: &mut Context<Self>) {
10887        let buffer = self.buffer.read(cx).snapshot(cx);
10888        let mut selection = self.selections.first::<usize>(cx);
10889        selection.set_head(buffer.len(), SelectionGoal::None);
10890        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10891            s.select(vec![selection]);
10892        });
10893    }
10894
10895    pub fn select_all(&mut self, _: &SelectAll, window: &mut Window, cx: &mut Context<Self>) {
10896        let end = self.buffer.read(cx).read(cx).len();
10897        self.change_selections(None, window, cx, |s| {
10898            s.select_ranges(vec![0..end]);
10899        });
10900    }
10901
10902    pub fn select_line(&mut self, _: &SelectLine, window: &mut Window, cx: &mut Context<Self>) {
10903        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
10904        let mut selections = self.selections.all::<Point>(cx);
10905        let max_point = display_map.buffer_snapshot.max_point();
10906        for selection in &mut selections {
10907            let rows = selection.spanned_rows(true, &display_map);
10908            selection.start = Point::new(rows.start.0, 0);
10909            selection.end = cmp::min(max_point, Point::new(rows.end.0, 0));
10910            selection.reversed = false;
10911        }
10912        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10913            s.select(selections);
10914        });
10915    }
10916
10917    pub fn split_selection_into_lines(
10918        &mut self,
10919        _: &SplitSelectionIntoLines,
10920        window: &mut Window,
10921        cx: &mut Context<Self>,
10922    ) {
10923        let selections = self
10924            .selections
10925            .all::<Point>(cx)
10926            .into_iter()
10927            .map(|selection| selection.start..selection.end)
10928            .collect::<Vec<_>>();
10929        self.unfold_ranges(&selections, true, true, cx);
10930
10931        let mut new_selection_ranges = Vec::new();
10932        {
10933            let buffer = self.buffer.read(cx).read(cx);
10934            for selection in selections {
10935                for row in selection.start.row..selection.end.row {
10936                    let cursor = Point::new(row, buffer.line_len(MultiBufferRow(row)));
10937                    new_selection_ranges.push(cursor..cursor);
10938                }
10939
10940                let is_multiline_selection = selection.start.row != selection.end.row;
10941                // Don't insert last one if it's a multi-line selection ending at the start of a line,
10942                // so this action feels more ergonomic when paired with other selection operations
10943                let should_skip_last = is_multiline_selection && selection.end.column == 0;
10944                if !should_skip_last {
10945                    new_selection_ranges.push(selection.end..selection.end);
10946                }
10947            }
10948        }
10949        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10950            s.select_ranges(new_selection_ranges);
10951        });
10952    }
10953
10954    pub fn add_selection_above(
10955        &mut self,
10956        _: &AddSelectionAbove,
10957        window: &mut Window,
10958        cx: &mut Context<Self>,
10959    ) {
10960        self.add_selection(true, window, cx);
10961    }
10962
10963    pub fn add_selection_below(
10964        &mut self,
10965        _: &AddSelectionBelow,
10966        window: &mut Window,
10967        cx: &mut Context<Self>,
10968    ) {
10969        self.add_selection(false, window, cx);
10970    }
10971
10972    fn add_selection(&mut self, above: bool, window: &mut Window, cx: &mut Context<Self>) {
10973        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
10974        let mut selections = self.selections.all::<Point>(cx);
10975        let text_layout_details = self.text_layout_details(window);
10976        let mut state = self.add_selections_state.take().unwrap_or_else(|| {
10977            let oldest_selection = selections.iter().min_by_key(|s| s.id).unwrap().clone();
10978            let range = oldest_selection.display_range(&display_map).sorted();
10979
10980            let start_x = display_map.x_for_display_point(range.start, &text_layout_details);
10981            let end_x = display_map.x_for_display_point(range.end, &text_layout_details);
10982            let positions = start_x.min(end_x)..start_x.max(end_x);
10983
10984            selections.clear();
10985            let mut stack = Vec::new();
10986            for row in range.start.row().0..=range.end.row().0 {
10987                if let Some(selection) = self.selections.build_columnar_selection(
10988                    &display_map,
10989                    DisplayRow(row),
10990                    &positions,
10991                    oldest_selection.reversed,
10992                    &text_layout_details,
10993                ) {
10994                    stack.push(selection.id);
10995                    selections.push(selection);
10996                }
10997            }
10998
10999            if above {
11000                stack.reverse();
11001            }
11002
11003            AddSelectionsState { above, stack }
11004        });
11005
11006        let last_added_selection = *state.stack.last().unwrap();
11007        let mut new_selections = Vec::new();
11008        if above == state.above {
11009            let end_row = if above {
11010                DisplayRow(0)
11011            } else {
11012                display_map.max_point().row()
11013            };
11014
11015            'outer: for selection in selections {
11016                if selection.id == last_added_selection {
11017                    let range = selection.display_range(&display_map).sorted();
11018                    debug_assert_eq!(range.start.row(), range.end.row());
11019                    let mut row = range.start.row();
11020                    let positions =
11021                        if let SelectionGoal::HorizontalRange { start, end } = selection.goal {
11022                            px(start)..px(end)
11023                        } else {
11024                            let start_x =
11025                                display_map.x_for_display_point(range.start, &text_layout_details);
11026                            let end_x =
11027                                display_map.x_for_display_point(range.end, &text_layout_details);
11028                            start_x.min(end_x)..start_x.max(end_x)
11029                        };
11030
11031                    while row != end_row {
11032                        if above {
11033                            row.0 -= 1;
11034                        } else {
11035                            row.0 += 1;
11036                        }
11037
11038                        if let Some(new_selection) = self.selections.build_columnar_selection(
11039                            &display_map,
11040                            row,
11041                            &positions,
11042                            selection.reversed,
11043                            &text_layout_details,
11044                        ) {
11045                            state.stack.push(new_selection.id);
11046                            if above {
11047                                new_selections.push(new_selection);
11048                                new_selections.push(selection);
11049                            } else {
11050                                new_selections.push(selection);
11051                                new_selections.push(new_selection);
11052                            }
11053
11054                            continue 'outer;
11055                        }
11056                    }
11057                }
11058
11059                new_selections.push(selection);
11060            }
11061        } else {
11062            new_selections = selections;
11063            new_selections.retain(|s| s.id != last_added_selection);
11064            state.stack.pop();
11065        }
11066
11067        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
11068            s.select(new_selections);
11069        });
11070        if state.stack.len() > 1 {
11071            self.add_selections_state = Some(state);
11072        }
11073    }
11074
11075    pub fn select_next_match_internal(
11076        &mut self,
11077        display_map: &DisplaySnapshot,
11078        replace_newest: bool,
11079        autoscroll: Option<Autoscroll>,
11080        window: &mut Window,
11081        cx: &mut Context<Self>,
11082    ) -> Result<()> {
11083        fn select_next_match_ranges(
11084            this: &mut Editor,
11085            range: Range<usize>,
11086            replace_newest: bool,
11087            auto_scroll: Option<Autoscroll>,
11088            window: &mut Window,
11089            cx: &mut Context<Editor>,
11090        ) {
11091            this.unfold_ranges(&[range.clone()], false, true, cx);
11092            this.change_selections(auto_scroll, window, cx, |s| {
11093                if replace_newest {
11094                    s.delete(s.newest_anchor().id);
11095                }
11096                s.insert_range(range.clone());
11097            });
11098        }
11099
11100        let buffer = &display_map.buffer_snapshot;
11101        let mut selections = self.selections.all::<usize>(cx);
11102        if let Some(mut select_next_state) = self.select_next_state.take() {
11103            let query = &select_next_state.query;
11104            if !select_next_state.done {
11105                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
11106                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
11107                let mut next_selected_range = None;
11108
11109                let bytes_after_last_selection =
11110                    buffer.bytes_in_range(last_selection.end..buffer.len());
11111                let bytes_before_first_selection = buffer.bytes_in_range(0..first_selection.start);
11112                let query_matches = query
11113                    .stream_find_iter(bytes_after_last_selection)
11114                    .map(|result| (last_selection.end, result))
11115                    .chain(
11116                        query
11117                            .stream_find_iter(bytes_before_first_selection)
11118                            .map(|result| (0, result)),
11119                    );
11120
11121                for (start_offset, query_match) in query_matches {
11122                    let query_match = query_match.unwrap(); // can only fail due to I/O
11123                    let offset_range =
11124                        start_offset + query_match.start()..start_offset + query_match.end();
11125                    let display_range = offset_range.start.to_display_point(display_map)
11126                        ..offset_range.end.to_display_point(display_map);
11127
11128                    if !select_next_state.wordwise
11129                        || (!movement::is_inside_word(display_map, display_range.start)
11130                            && !movement::is_inside_word(display_map, display_range.end))
11131                    {
11132                        // TODO: This is n^2, because we might check all the selections
11133                        if !selections
11134                            .iter()
11135                            .any(|selection| selection.range().overlaps(&offset_range))
11136                        {
11137                            next_selected_range = Some(offset_range);
11138                            break;
11139                        }
11140                    }
11141                }
11142
11143                if let Some(next_selected_range) = next_selected_range {
11144                    select_next_match_ranges(
11145                        self,
11146                        next_selected_range,
11147                        replace_newest,
11148                        autoscroll,
11149                        window,
11150                        cx,
11151                    );
11152                } else {
11153                    select_next_state.done = true;
11154                }
11155            }
11156
11157            self.select_next_state = Some(select_next_state);
11158        } else {
11159            let mut only_carets = true;
11160            let mut same_text_selected = true;
11161            let mut selected_text = None;
11162
11163            let mut selections_iter = selections.iter().peekable();
11164            while let Some(selection) = selections_iter.next() {
11165                if selection.start != selection.end {
11166                    only_carets = false;
11167                }
11168
11169                if same_text_selected {
11170                    if selected_text.is_none() {
11171                        selected_text =
11172                            Some(buffer.text_for_range(selection.range()).collect::<String>());
11173                    }
11174
11175                    if let Some(next_selection) = selections_iter.peek() {
11176                        if next_selection.range().len() == selection.range().len() {
11177                            let next_selected_text = buffer
11178                                .text_for_range(next_selection.range())
11179                                .collect::<String>();
11180                            if Some(next_selected_text) != selected_text {
11181                                same_text_selected = false;
11182                                selected_text = None;
11183                            }
11184                        } else {
11185                            same_text_selected = false;
11186                            selected_text = None;
11187                        }
11188                    }
11189                }
11190            }
11191
11192            if only_carets {
11193                for selection in &mut selections {
11194                    let word_range = movement::surrounding_word(
11195                        display_map,
11196                        selection.start.to_display_point(display_map),
11197                    );
11198                    selection.start = word_range.start.to_offset(display_map, Bias::Left);
11199                    selection.end = word_range.end.to_offset(display_map, Bias::Left);
11200                    selection.goal = SelectionGoal::None;
11201                    selection.reversed = false;
11202                    select_next_match_ranges(
11203                        self,
11204                        selection.start..selection.end,
11205                        replace_newest,
11206                        autoscroll,
11207                        window,
11208                        cx,
11209                    );
11210                }
11211
11212                if selections.len() == 1 {
11213                    let selection = selections
11214                        .last()
11215                        .expect("ensured that there's only one selection");
11216                    let query = buffer
11217                        .text_for_range(selection.start..selection.end)
11218                        .collect::<String>();
11219                    let is_empty = query.is_empty();
11220                    let select_state = SelectNextState {
11221                        query: AhoCorasick::new(&[query])?,
11222                        wordwise: true,
11223                        done: is_empty,
11224                    };
11225                    self.select_next_state = Some(select_state);
11226                } else {
11227                    self.select_next_state = None;
11228                }
11229            } else if let Some(selected_text) = selected_text {
11230                self.select_next_state = Some(SelectNextState {
11231                    query: AhoCorasick::new(&[selected_text])?,
11232                    wordwise: false,
11233                    done: false,
11234                });
11235                self.select_next_match_internal(
11236                    display_map,
11237                    replace_newest,
11238                    autoscroll,
11239                    window,
11240                    cx,
11241                )?;
11242            }
11243        }
11244        Ok(())
11245    }
11246
11247    pub fn select_all_matches(
11248        &mut self,
11249        _action: &SelectAllMatches,
11250        window: &mut Window,
11251        cx: &mut Context<Self>,
11252    ) -> Result<()> {
11253        self.push_to_selection_history();
11254        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
11255
11256        self.select_next_match_internal(&display_map, false, None, window, cx)?;
11257        let Some(select_next_state) = self.select_next_state.as_mut() else {
11258            return Ok(());
11259        };
11260        if select_next_state.done {
11261            return Ok(());
11262        }
11263
11264        let mut new_selections = self.selections.all::<usize>(cx);
11265
11266        let buffer = &display_map.buffer_snapshot;
11267        let query_matches = select_next_state
11268            .query
11269            .stream_find_iter(buffer.bytes_in_range(0..buffer.len()));
11270
11271        for query_match in query_matches {
11272            let query_match = query_match.unwrap(); // can only fail due to I/O
11273            let offset_range = query_match.start()..query_match.end();
11274            let display_range = offset_range.start.to_display_point(&display_map)
11275                ..offset_range.end.to_display_point(&display_map);
11276
11277            if !select_next_state.wordwise
11278                || (!movement::is_inside_word(&display_map, display_range.start)
11279                    && !movement::is_inside_word(&display_map, display_range.end))
11280            {
11281                self.selections.change_with(cx, |selections| {
11282                    new_selections.push(Selection {
11283                        id: selections.new_selection_id(),
11284                        start: offset_range.start,
11285                        end: offset_range.end,
11286                        reversed: false,
11287                        goal: SelectionGoal::None,
11288                    });
11289                });
11290            }
11291        }
11292
11293        new_selections.sort_by_key(|selection| selection.start);
11294        let mut ix = 0;
11295        while ix + 1 < new_selections.len() {
11296            let current_selection = &new_selections[ix];
11297            let next_selection = &new_selections[ix + 1];
11298            if current_selection.range().overlaps(&next_selection.range()) {
11299                if current_selection.id < next_selection.id {
11300                    new_selections.remove(ix + 1);
11301                } else {
11302                    new_selections.remove(ix);
11303                }
11304            } else {
11305                ix += 1;
11306            }
11307        }
11308
11309        let reversed = self.selections.oldest::<usize>(cx).reversed;
11310
11311        for selection in new_selections.iter_mut() {
11312            selection.reversed = reversed;
11313        }
11314
11315        select_next_state.done = true;
11316        self.unfold_ranges(
11317            &new_selections
11318                .iter()
11319                .map(|selection| selection.range())
11320                .collect::<Vec<_>>(),
11321            false,
11322            false,
11323            cx,
11324        );
11325        self.change_selections(Some(Autoscroll::fit()), window, cx, |selections| {
11326            selections.select(new_selections)
11327        });
11328
11329        Ok(())
11330    }
11331
11332    pub fn select_next(
11333        &mut self,
11334        action: &SelectNext,
11335        window: &mut Window,
11336        cx: &mut Context<Self>,
11337    ) -> Result<()> {
11338        self.push_to_selection_history();
11339        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
11340        self.select_next_match_internal(
11341            &display_map,
11342            action.replace_newest,
11343            Some(Autoscroll::newest()),
11344            window,
11345            cx,
11346        )?;
11347        Ok(())
11348    }
11349
11350    pub fn select_previous(
11351        &mut self,
11352        action: &SelectPrevious,
11353        window: &mut Window,
11354        cx: &mut Context<Self>,
11355    ) -> Result<()> {
11356        self.push_to_selection_history();
11357        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
11358        let buffer = &display_map.buffer_snapshot;
11359        let mut selections = self.selections.all::<usize>(cx);
11360        if let Some(mut select_prev_state) = self.select_prev_state.take() {
11361            let query = &select_prev_state.query;
11362            if !select_prev_state.done {
11363                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
11364                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
11365                let mut next_selected_range = None;
11366                // When we're iterating matches backwards, the oldest match will actually be the furthest one in the buffer.
11367                let bytes_before_last_selection =
11368                    buffer.reversed_bytes_in_range(0..last_selection.start);
11369                let bytes_after_first_selection =
11370                    buffer.reversed_bytes_in_range(first_selection.end..buffer.len());
11371                let query_matches = query
11372                    .stream_find_iter(bytes_before_last_selection)
11373                    .map(|result| (last_selection.start, result))
11374                    .chain(
11375                        query
11376                            .stream_find_iter(bytes_after_first_selection)
11377                            .map(|result| (buffer.len(), result)),
11378                    );
11379                for (end_offset, query_match) in query_matches {
11380                    let query_match = query_match.unwrap(); // can only fail due to I/O
11381                    let offset_range =
11382                        end_offset - query_match.end()..end_offset - query_match.start();
11383                    let display_range = offset_range.start.to_display_point(&display_map)
11384                        ..offset_range.end.to_display_point(&display_map);
11385
11386                    if !select_prev_state.wordwise
11387                        || (!movement::is_inside_word(&display_map, display_range.start)
11388                            && !movement::is_inside_word(&display_map, display_range.end))
11389                    {
11390                        next_selected_range = Some(offset_range);
11391                        break;
11392                    }
11393                }
11394
11395                if let Some(next_selected_range) = next_selected_range {
11396                    self.unfold_ranges(&[next_selected_range.clone()], false, true, cx);
11397                    self.change_selections(Some(Autoscroll::newest()), window, cx, |s| {
11398                        if action.replace_newest {
11399                            s.delete(s.newest_anchor().id);
11400                        }
11401                        s.insert_range(next_selected_range);
11402                    });
11403                } else {
11404                    select_prev_state.done = true;
11405                }
11406            }
11407
11408            self.select_prev_state = Some(select_prev_state);
11409        } else {
11410            let mut only_carets = true;
11411            let mut same_text_selected = true;
11412            let mut selected_text = None;
11413
11414            let mut selections_iter = selections.iter().peekable();
11415            while let Some(selection) = selections_iter.next() {
11416                if selection.start != selection.end {
11417                    only_carets = false;
11418                }
11419
11420                if same_text_selected {
11421                    if selected_text.is_none() {
11422                        selected_text =
11423                            Some(buffer.text_for_range(selection.range()).collect::<String>());
11424                    }
11425
11426                    if let Some(next_selection) = selections_iter.peek() {
11427                        if next_selection.range().len() == selection.range().len() {
11428                            let next_selected_text = buffer
11429                                .text_for_range(next_selection.range())
11430                                .collect::<String>();
11431                            if Some(next_selected_text) != selected_text {
11432                                same_text_selected = false;
11433                                selected_text = None;
11434                            }
11435                        } else {
11436                            same_text_selected = false;
11437                            selected_text = None;
11438                        }
11439                    }
11440                }
11441            }
11442
11443            if only_carets {
11444                for selection in &mut selections {
11445                    let word_range = movement::surrounding_word(
11446                        &display_map,
11447                        selection.start.to_display_point(&display_map),
11448                    );
11449                    selection.start = word_range.start.to_offset(&display_map, Bias::Left);
11450                    selection.end = word_range.end.to_offset(&display_map, Bias::Left);
11451                    selection.goal = SelectionGoal::None;
11452                    selection.reversed = false;
11453                }
11454                if selections.len() == 1 {
11455                    let selection = selections
11456                        .last()
11457                        .expect("ensured that there's only one selection");
11458                    let query = buffer
11459                        .text_for_range(selection.start..selection.end)
11460                        .collect::<String>();
11461                    let is_empty = query.is_empty();
11462                    let select_state = SelectNextState {
11463                        query: AhoCorasick::new(&[query.chars().rev().collect::<String>()])?,
11464                        wordwise: true,
11465                        done: is_empty,
11466                    };
11467                    self.select_prev_state = Some(select_state);
11468                } else {
11469                    self.select_prev_state = None;
11470                }
11471
11472                self.unfold_ranges(
11473                    &selections.iter().map(|s| s.range()).collect::<Vec<_>>(),
11474                    false,
11475                    true,
11476                    cx,
11477                );
11478                self.change_selections(Some(Autoscroll::newest()), window, cx, |s| {
11479                    s.select(selections);
11480                });
11481            } else if let Some(selected_text) = selected_text {
11482                self.select_prev_state = Some(SelectNextState {
11483                    query: AhoCorasick::new(&[selected_text.chars().rev().collect::<String>()])?,
11484                    wordwise: false,
11485                    done: false,
11486                });
11487                self.select_previous(action, window, cx)?;
11488            }
11489        }
11490        Ok(())
11491    }
11492
11493    pub fn toggle_comments(
11494        &mut self,
11495        action: &ToggleComments,
11496        window: &mut Window,
11497        cx: &mut Context<Self>,
11498    ) {
11499        if self.read_only(cx) {
11500            return;
11501        }
11502        let text_layout_details = &self.text_layout_details(window);
11503        self.transact(window, cx, |this, window, cx| {
11504            let mut selections = this.selections.all::<MultiBufferPoint>(cx);
11505            let mut edits = Vec::new();
11506            let mut selection_edit_ranges = Vec::new();
11507            let mut last_toggled_row = None;
11508            let snapshot = this.buffer.read(cx).read(cx);
11509            let empty_str: Arc<str> = Arc::default();
11510            let mut suffixes_inserted = Vec::new();
11511            let ignore_indent = action.ignore_indent;
11512
11513            fn comment_prefix_range(
11514                snapshot: &MultiBufferSnapshot,
11515                row: MultiBufferRow,
11516                comment_prefix: &str,
11517                comment_prefix_whitespace: &str,
11518                ignore_indent: bool,
11519            ) -> Range<Point> {
11520                let indent_size = if ignore_indent {
11521                    0
11522                } else {
11523                    snapshot.indent_size_for_line(row).len
11524                };
11525
11526                let start = Point::new(row.0, indent_size);
11527
11528                let mut line_bytes = snapshot
11529                    .bytes_in_range(start..snapshot.max_point())
11530                    .flatten()
11531                    .copied();
11532
11533                // If this line currently begins with the line comment prefix, then record
11534                // the range containing the prefix.
11535                if line_bytes
11536                    .by_ref()
11537                    .take(comment_prefix.len())
11538                    .eq(comment_prefix.bytes())
11539                {
11540                    // Include any whitespace that matches the comment prefix.
11541                    let matching_whitespace_len = line_bytes
11542                        .zip(comment_prefix_whitespace.bytes())
11543                        .take_while(|(a, b)| a == b)
11544                        .count() as u32;
11545                    let end = Point::new(
11546                        start.row,
11547                        start.column + comment_prefix.len() as u32 + matching_whitespace_len,
11548                    );
11549                    start..end
11550                } else {
11551                    start..start
11552                }
11553            }
11554
11555            fn comment_suffix_range(
11556                snapshot: &MultiBufferSnapshot,
11557                row: MultiBufferRow,
11558                comment_suffix: &str,
11559                comment_suffix_has_leading_space: bool,
11560            ) -> Range<Point> {
11561                let end = Point::new(row.0, snapshot.line_len(row));
11562                let suffix_start_column = end.column.saturating_sub(comment_suffix.len() as u32);
11563
11564                let mut line_end_bytes = snapshot
11565                    .bytes_in_range(Point::new(end.row, suffix_start_column.saturating_sub(1))..end)
11566                    .flatten()
11567                    .copied();
11568
11569                let leading_space_len = if suffix_start_column > 0
11570                    && line_end_bytes.next() == Some(b' ')
11571                    && comment_suffix_has_leading_space
11572                {
11573                    1
11574                } else {
11575                    0
11576                };
11577
11578                // If this line currently begins with the line comment prefix, then record
11579                // the range containing the prefix.
11580                if line_end_bytes.by_ref().eq(comment_suffix.bytes()) {
11581                    let start = Point::new(end.row, suffix_start_column - leading_space_len);
11582                    start..end
11583                } else {
11584                    end..end
11585                }
11586            }
11587
11588            // TODO: Handle selections that cross excerpts
11589            for selection in &mut selections {
11590                let start_column = snapshot
11591                    .indent_size_for_line(MultiBufferRow(selection.start.row))
11592                    .len;
11593                let language = if let Some(language) =
11594                    snapshot.language_scope_at(Point::new(selection.start.row, start_column))
11595                {
11596                    language
11597                } else {
11598                    continue;
11599                };
11600
11601                selection_edit_ranges.clear();
11602
11603                // If multiple selections contain a given row, avoid processing that
11604                // row more than once.
11605                let mut start_row = MultiBufferRow(selection.start.row);
11606                if last_toggled_row == Some(start_row) {
11607                    start_row = start_row.next_row();
11608                }
11609                let end_row =
11610                    if selection.end.row > selection.start.row && selection.end.column == 0 {
11611                        MultiBufferRow(selection.end.row - 1)
11612                    } else {
11613                        MultiBufferRow(selection.end.row)
11614                    };
11615                last_toggled_row = Some(end_row);
11616
11617                if start_row > end_row {
11618                    continue;
11619                }
11620
11621                // If the language has line comments, toggle those.
11622                let mut full_comment_prefixes = language.line_comment_prefixes().to_vec();
11623
11624                // If ignore_indent is set, trim spaces from the right side of all full_comment_prefixes
11625                if ignore_indent {
11626                    full_comment_prefixes = full_comment_prefixes
11627                        .into_iter()
11628                        .map(|s| Arc::from(s.trim_end()))
11629                        .collect();
11630                }
11631
11632                if !full_comment_prefixes.is_empty() {
11633                    let first_prefix = full_comment_prefixes
11634                        .first()
11635                        .expect("prefixes is non-empty");
11636                    let prefix_trimmed_lengths = full_comment_prefixes
11637                        .iter()
11638                        .map(|p| p.trim_end_matches(' ').len())
11639                        .collect::<SmallVec<[usize; 4]>>();
11640
11641                    let mut all_selection_lines_are_comments = true;
11642
11643                    for row in start_row.0..=end_row.0 {
11644                        let row = MultiBufferRow(row);
11645                        if start_row < end_row && snapshot.is_line_blank(row) {
11646                            continue;
11647                        }
11648
11649                        let prefix_range = full_comment_prefixes
11650                            .iter()
11651                            .zip(prefix_trimmed_lengths.iter().copied())
11652                            .map(|(prefix, trimmed_prefix_len)| {
11653                                comment_prefix_range(
11654                                    snapshot.deref(),
11655                                    row,
11656                                    &prefix[..trimmed_prefix_len],
11657                                    &prefix[trimmed_prefix_len..],
11658                                    ignore_indent,
11659                                )
11660                            })
11661                            .max_by_key(|range| range.end.column - range.start.column)
11662                            .expect("prefixes is non-empty");
11663
11664                        if prefix_range.is_empty() {
11665                            all_selection_lines_are_comments = false;
11666                        }
11667
11668                        selection_edit_ranges.push(prefix_range);
11669                    }
11670
11671                    if all_selection_lines_are_comments {
11672                        edits.extend(
11673                            selection_edit_ranges
11674                                .iter()
11675                                .cloned()
11676                                .map(|range| (range, empty_str.clone())),
11677                        );
11678                    } else {
11679                        let min_column = selection_edit_ranges
11680                            .iter()
11681                            .map(|range| range.start.column)
11682                            .min()
11683                            .unwrap_or(0);
11684                        edits.extend(selection_edit_ranges.iter().map(|range| {
11685                            let position = Point::new(range.start.row, min_column);
11686                            (position..position, first_prefix.clone())
11687                        }));
11688                    }
11689                } else if let Some((full_comment_prefix, comment_suffix)) =
11690                    language.block_comment_delimiters()
11691                {
11692                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
11693                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
11694                    let prefix_range = comment_prefix_range(
11695                        snapshot.deref(),
11696                        start_row,
11697                        comment_prefix,
11698                        comment_prefix_whitespace,
11699                        ignore_indent,
11700                    );
11701                    let suffix_range = comment_suffix_range(
11702                        snapshot.deref(),
11703                        end_row,
11704                        comment_suffix.trim_start_matches(' '),
11705                        comment_suffix.starts_with(' '),
11706                    );
11707
11708                    if prefix_range.is_empty() || suffix_range.is_empty() {
11709                        edits.push((
11710                            prefix_range.start..prefix_range.start,
11711                            full_comment_prefix.clone(),
11712                        ));
11713                        edits.push((suffix_range.end..suffix_range.end, comment_suffix.clone()));
11714                        suffixes_inserted.push((end_row, comment_suffix.len()));
11715                    } else {
11716                        edits.push((prefix_range, empty_str.clone()));
11717                        edits.push((suffix_range, empty_str.clone()));
11718                    }
11719                } else {
11720                    continue;
11721                }
11722            }
11723
11724            drop(snapshot);
11725            this.buffer.update(cx, |buffer, cx| {
11726                buffer.edit(edits, None, cx);
11727            });
11728
11729            // Adjust selections so that they end before any comment suffixes that
11730            // were inserted.
11731            let mut suffixes_inserted = suffixes_inserted.into_iter().peekable();
11732            let mut selections = this.selections.all::<Point>(cx);
11733            let snapshot = this.buffer.read(cx).read(cx);
11734            for selection in &mut selections {
11735                while let Some((row, suffix_len)) = suffixes_inserted.peek().copied() {
11736                    match row.cmp(&MultiBufferRow(selection.end.row)) {
11737                        Ordering::Less => {
11738                            suffixes_inserted.next();
11739                            continue;
11740                        }
11741                        Ordering::Greater => break,
11742                        Ordering::Equal => {
11743                            if selection.end.column == snapshot.line_len(row) {
11744                                if selection.is_empty() {
11745                                    selection.start.column -= suffix_len as u32;
11746                                }
11747                                selection.end.column -= suffix_len as u32;
11748                            }
11749                            break;
11750                        }
11751                    }
11752                }
11753            }
11754
11755            drop(snapshot);
11756            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
11757                s.select(selections)
11758            });
11759
11760            let selections = this.selections.all::<Point>(cx);
11761            let selections_on_single_row = selections.windows(2).all(|selections| {
11762                selections[0].start.row == selections[1].start.row
11763                    && selections[0].end.row == selections[1].end.row
11764                    && selections[0].start.row == selections[0].end.row
11765            });
11766            let selections_selecting = selections
11767                .iter()
11768                .any(|selection| selection.start != selection.end);
11769            let advance_downwards = action.advance_downwards
11770                && selections_on_single_row
11771                && !selections_selecting
11772                && !matches!(this.mode, EditorMode::SingleLine { .. });
11773
11774            if advance_downwards {
11775                let snapshot = this.buffer.read(cx).snapshot(cx);
11776
11777                this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
11778                    s.move_cursors_with(|display_snapshot, display_point, _| {
11779                        let mut point = display_point.to_point(display_snapshot);
11780                        point.row += 1;
11781                        point = snapshot.clip_point(point, Bias::Left);
11782                        let display_point = point.to_display_point(display_snapshot);
11783                        let goal = SelectionGoal::HorizontalPosition(
11784                            display_snapshot
11785                                .x_for_display_point(display_point, text_layout_details)
11786                                .into(),
11787                        );
11788                        (display_point, goal)
11789                    })
11790                });
11791            }
11792        });
11793    }
11794
11795    pub fn select_enclosing_symbol(
11796        &mut self,
11797        _: &SelectEnclosingSymbol,
11798        window: &mut Window,
11799        cx: &mut Context<Self>,
11800    ) {
11801        let buffer = self.buffer.read(cx).snapshot(cx);
11802        let old_selections = self.selections.all::<usize>(cx).into_boxed_slice();
11803
11804        fn update_selection(
11805            selection: &Selection<usize>,
11806            buffer_snap: &MultiBufferSnapshot,
11807        ) -> Option<Selection<usize>> {
11808            let cursor = selection.head();
11809            let (_buffer_id, symbols) = buffer_snap.symbols_containing(cursor, None)?;
11810            for symbol in symbols.iter().rev() {
11811                let start = symbol.range.start.to_offset(buffer_snap);
11812                let end = symbol.range.end.to_offset(buffer_snap);
11813                let new_range = start..end;
11814                if start < selection.start || end > selection.end {
11815                    return Some(Selection {
11816                        id: selection.id,
11817                        start: new_range.start,
11818                        end: new_range.end,
11819                        goal: SelectionGoal::None,
11820                        reversed: selection.reversed,
11821                    });
11822                }
11823            }
11824            None
11825        }
11826
11827        let mut selected_larger_symbol = false;
11828        let new_selections = old_selections
11829            .iter()
11830            .map(|selection| match update_selection(selection, &buffer) {
11831                Some(new_selection) => {
11832                    if new_selection.range() != selection.range() {
11833                        selected_larger_symbol = true;
11834                    }
11835                    new_selection
11836                }
11837                None => selection.clone(),
11838            })
11839            .collect::<Vec<_>>();
11840
11841        if selected_larger_symbol {
11842            self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
11843                s.select(new_selections);
11844            });
11845        }
11846    }
11847
11848    pub fn select_larger_syntax_node(
11849        &mut self,
11850        _: &SelectLargerSyntaxNode,
11851        window: &mut Window,
11852        cx: &mut Context<Self>,
11853    ) {
11854        let Some(visible_row_count) = self.visible_row_count() else {
11855            return;
11856        };
11857        let old_selections: Box<[_]> = self.selections.all::<usize>(cx).into();
11858        if old_selections.is_empty() {
11859            return;
11860        }
11861
11862        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
11863        let buffer = self.buffer.read(cx).snapshot(cx);
11864
11865        let mut selected_larger_node = false;
11866        let mut new_selections = old_selections
11867            .iter()
11868            .map(|selection| {
11869                let old_range = selection.start..selection.end;
11870                let mut new_range = old_range.clone();
11871                let mut new_node = None;
11872                while let Some((node, containing_range)) = buffer.syntax_ancestor(new_range.clone())
11873                {
11874                    new_node = Some(node);
11875                    new_range = match containing_range {
11876                        MultiOrSingleBufferOffsetRange::Single(_) => break,
11877                        MultiOrSingleBufferOffsetRange::Multi(range) => range,
11878                    };
11879                    if !display_map.intersects_fold(new_range.start)
11880                        && !display_map.intersects_fold(new_range.end)
11881                    {
11882                        break;
11883                    }
11884                }
11885
11886                if let Some(node) = new_node {
11887                    // Log the ancestor, to support using this action as a way to explore TreeSitter
11888                    // nodes. Parent and grandparent are also logged because this operation will not
11889                    // visit nodes that have the same range as their parent.
11890                    log::info!("Node: {node:?}");
11891                    let parent = node.parent();
11892                    log::info!("Parent: {parent:?}");
11893                    let grandparent = parent.and_then(|x| x.parent());
11894                    log::info!("Grandparent: {grandparent:?}");
11895                }
11896
11897                selected_larger_node |= new_range != old_range;
11898                Selection {
11899                    id: selection.id,
11900                    start: new_range.start,
11901                    end: new_range.end,
11902                    goal: SelectionGoal::None,
11903                    reversed: selection.reversed,
11904                }
11905            })
11906            .collect::<Vec<_>>();
11907
11908        if !selected_larger_node {
11909            return; // don't put this call in the history
11910        }
11911
11912        // scroll based on transformation done to the last selection created by the user
11913        let (last_old, last_new) = old_selections
11914            .last()
11915            .zip(new_selections.last().cloned())
11916            .expect("old_selections isn't empty");
11917
11918        // revert selection
11919        let is_selection_reversed = {
11920            let should_newest_selection_be_reversed = last_old.start != last_new.start;
11921            new_selections.last_mut().expect("checked above").reversed =
11922                should_newest_selection_be_reversed;
11923            should_newest_selection_be_reversed
11924        };
11925
11926        if selected_larger_node {
11927            self.select_syntax_node_history.disable_clearing = true;
11928            self.change_selections(None, window, cx, |s| {
11929                s.select(new_selections.clone());
11930            });
11931            self.select_syntax_node_history.disable_clearing = false;
11932        }
11933
11934        let start_row = last_new.start.to_display_point(&display_map).row().0;
11935        let end_row = last_new.end.to_display_point(&display_map).row().0;
11936        let selection_height = end_row - start_row + 1;
11937        let scroll_margin_rows = self.vertical_scroll_margin() as u32;
11938
11939        // if fits on screen (considering margin), keep it in the middle, else, scroll to selection head
11940        let scroll_behavior = if visible_row_count >= selection_height + scroll_margin_rows * 2 {
11941            let middle_row = (end_row + start_row) / 2;
11942            let selection_center = middle_row.saturating_sub(visible_row_count / 2);
11943            self.set_scroll_top_row(DisplayRow(selection_center), window, cx);
11944            SelectSyntaxNodeScrollBehavior::CenterSelection
11945        } else if is_selection_reversed {
11946            self.scroll_cursor_top(&Default::default(), window, cx);
11947            SelectSyntaxNodeScrollBehavior::CursorTop
11948        } else {
11949            self.scroll_cursor_bottom(&Default::default(), window, cx);
11950            SelectSyntaxNodeScrollBehavior::CursorBottom
11951        };
11952
11953        self.select_syntax_node_history.push((
11954            old_selections,
11955            scroll_behavior,
11956            is_selection_reversed,
11957        ));
11958    }
11959
11960    pub fn select_smaller_syntax_node(
11961        &mut self,
11962        _: &SelectSmallerSyntaxNode,
11963        window: &mut Window,
11964        cx: &mut Context<Self>,
11965    ) {
11966        let Some(visible_row_count) = self.visible_row_count() else {
11967            return;
11968        };
11969
11970        if let Some((mut selections, scroll_behavior, is_selection_reversed)) =
11971            self.select_syntax_node_history.pop()
11972        {
11973            let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
11974
11975            if let Some(selection) = selections.last_mut() {
11976                selection.reversed = is_selection_reversed;
11977            }
11978
11979            self.select_syntax_node_history.disable_clearing = true;
11980            self.change_selections(None, window, cx, |s| {
11981                s.select(selections.to_vec());
11982            });
11983            self.select_syntax_node_history.disable_clearing = false;
11984
11985            let newest = self.selections.newest::<usize>(cx);
11986            let start_row = newest.start.to_display_point(&display_map).row().0;
11987            let end_row = newest.end.to_display_point(&display_map).row().0;
11988
11989            match scroll_behavior {
11990                SelectSyntaxNodeScrollBehavior::CursorTop => {
11991                    self.scroll_cursor_top(&Default::default(), window, cx);
11992                }
11993                SelectSyntaxNodeScrollBehavior::CenterSelection => {
11994                    let middle_row = (end_row + start_row) / 2;
11995                    let selection_center = middle_row.saturating_sub(visible_row_count / 2);
11996                    // centralize the selection, not the cursor
11997                    self.set_scroll_top_row(DisplayRow(selection_center), window, cx);
11998                }
11999                SelectSyntaxNodeScrollBehavior::CursorBottom => {
12000                    self.scroll_cursor_bottom(&Default::default(), window, cx);
12001                }
12002            }
12003        }
12004    }
12005
12006    fn refresh_runnables(&mut self, window: &mut Window, cx: &mut Context<Self>) -> Task<()> {
12007        if !EditorSettings::get_global(cx).gutter.runnables {
12008            self.clear_tasks();
12009            return Task::ready(());
12010        }
12011        let project = self.project.as_ref().map(Entity::downgrade);
12012        cx.spawn_in(window, async move |this, cx| {
12013            cx.background_executor().timer(UPDATE_DEBOUNCE).await;
12014            let Some(project) = project.and_then(|p| p.upgrade()) else {
12015                return;
12016            };
12017            let Ok(display_snapshot) = this.update(cx, |this, cx| {
12018                this.display_map.update(cx, |map, cx| map.snapshot(cx))
12019            }) else {
12020                return;
12021            };
12022
12023            let hide_runnables = project
12024                .update(cx, |project, cx| {
12025                    // Do not display any test indicators in non-dev server remote projects.
12026                    project.is_via_collab() && project.ssh_connection_string(cx).is_none()
12027                })
12028                .unwrap_or(true);
12029            if hide_runnables {
12030                return;
12031            }
12032            let new_rows =
12033                cx.background_spawn({
12034                    let snapshot = display_snapshot.clone();
12035                    async move {
12036                        Self::fetch_runnable_ranges(&snapshot, Anchor::min()..Anchor::max())
12037                    }
12038                })
12039                    .await;
12040
12041            let rows = Self::runnable_rows(project, display_snapshot, new_rows, cx.clone());
12042            this.update(cx, |this, _| {
12043                this.clear_tasks();
12044                for (key, value) in rows {
12045                    this.insert_tasks(key, value);
12046                }
12047            })
12048            .ok();
12049        })
12050    }
12051    fn fetch_runnable_ranges(
12052        snapshot: &DisplaySnapshot,
12053        range: Range<Anchor>,
12054    ) -> Vec<language::RunnableRange> {
12055        snapshot.buffer_snapshot.runnable_ranges(range).collect()
12056    }
12057
12058    fn runnable_rows(
12059        project: Entity<Project>,
12060        snapshot: DisplaySnapshot,
12061        runnable_ranges: Vec<RunnableRange>,
12062        mut cx: AsyncWindowContext,
12063    ) -> Vec<((BufferId, u32), RunnableTasks)> {
12064        runnable_ranges
12065            .into_iter()
12066            .filter_map(|mut runnable| {
12067                let tasks = cx
12068                    .update(|_, cx| Self::templates_with_tags(&project, &mut runnable.runnable, cx))
12069                    .ok()?;
12070                if tasks.is_empty() {
12071                    return None;
12072                }
12073
12074                let point = runnable.run_range.start.to_point(&snapshot.buffer_snapshot);
12075
12076                let row = snapshot
12077                    .buffer_snapshot
12078                    .buffer_line_for_row(MultiBufferRow(point.row))?
12079                    .1
12080                    .start
12081                    .row;
12082
12083                let context_range =
12084                    BufferOffset(runnable.full_range.start)..BufferOffset(runnable.full_range.end);
12085                Some((
12086                    (runnable.buffer_id, row),
12087                    RunnableTasks {
12088                        templates: tasks,
12089                        offset: snapshot
12090                            .buffer_snapshot
12091                            .anchor_before(runnable.run_range.start),
12092                        context_range,
12093                        column: point.column,
12094                        extra_variables: runnable.extra_captures,
12095                    },
12096                ))
12097            })
12098            .collect()
12099    }
12100
12101    fn templates_with_tags(
12102        project: &Entity<Project>,
12103        runnable: &mut Runnable,
12104        cx: &mut App,
12105    ) -> Vec<(TaskSourceKind, TaskTemplate)> {
12106        let (inventory, worktree_id, file) = project.read_with(cx, |project, cx| {
12107            let (worktree_id, file) = project
12108                .buffer_for_id(runnable.buffer, cx)
12109                .and_then(|buffer| buffer.read(cx).file())
12110                .map(|file| (file.worktree_id(cx), file.clone()))
12111                .unzip();
12112
12113            (
12114                project.task_store().read(cx).task_inventory().cloned(),
12115                worktree_id,
12116                file,
12117            )
12118        });
12119
12120        let tags = mem::take(&mut runnable.tags);
12121        let mut tags: Vec<_> = tags
12122            .into_iter()
12123            .flat_map(|tag| {
12124                let tag = tag.0.clone();
12125                inventory
12126                    .as_ref()
12127                    .into_iter()
12128                    .flat_map(|inventory| {
12129                        inventory.read(cx).list_tasks(
12130                            file.clone(),
12131                            Some(runnable.language.clone()),
12132                            worktree_id,
12133                            cx,
12134                        )
12135                    })
12136                    .filter(move |(_, template)| {
12137                        template.tags.iter().any(|source_tag| source_tag == &tag)
12138                    })
12139            })
12140            .sorted_by_key(|(kind, _)| kind.to_owned())
12141            .collect();
12142        if let Some((leading_tag_source, _)) = tags.first() {
12143            // Strongest source wins; if we have worktree tag binding, prefer that to
12144            // global and language bindings;
12145            // if we have a global binding, prefer that to language binding.
12146            let first_mismatch = tags
12147                .iter()
12148                .position(|(tag_source, _)| tag_source != leading_tag_source);
12149            if let Some(index) = first_mismatch {
12150                tags.truncate(index);
12151            }
12152        }
12153
12154        tags
12155    }
12156
12157    pub fn move_to_enclosing_bracket(
12158        &mut self,
12159        _: &MoveToEnclosingBracket,
12160        window: &mut Window,
12161        cx: &mut Context<Self>,
12162    ) {
12163        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
12164            s.move_offsets_with(|snapshot, selection| {
12165                let Some(enclosing_bracket_ranges) =
12166                    snapshot.enclosing_bracket_ranges(selection.start..selection.end)
12167                else {
12168                    return;
12169                };
12170
12171                let mut best_length = usize::MAX;
12172                let mut best_inside = false;
12173                let mut best_in_bracket_range = false;
12174                let mut best_destination = None;
12175                for (open, close) in enclosing_bracket_ranges {
12176                    let close = close.to_inclusive();
12177                    let length = close.end() - open.start;
12178                    let inside = selection.start >= open.end && selection.end <= *close.start();
12179                    let in_bracket_range = open.to_inclusive().contains(&selection.head())
12180                        || close.contains(&selection.head());
12181
12182                    // If best is next to a bracket and current isn't, skip
12183                    if !in_bracket_range && best_in_bracket_range {
12184                        continue;
12185                    }
12186
12187                    // Prefer smaller lengths unless best is inside and current isn't
12188                    if length > best_length && (best_inside || !inside) {
12189                        continue;
12190                    }
12191
12192                    best_length = length;
12193                    best_inside = inside;
12194                    best_in_bracket_range = in_bracket_range;
12195                    best_destination = Some(
12196                        if close.contains(&selection.start) && close.contains(&selection.end) {
12197                            if inside {
12198                                open.end
12199                            } else {
12200                                open.start
12201                            }
12202                        } else if inside {
12203                            *close.start()
12204                        } else {
12205                            *close.end()
12206                        },
12207                    );
12208                }
12209
12210                if let Some(destination) = best_destination {
12211                    selection.collapse_to(destination, SelectionGoal::None);
12212                }
12213            })
12214        });
12215    }
12216
12217    pub fn undo_selection(
12218        &mut self,
12219        _: &UndoSelection,
12220        window: &mut Window,
12221        cx: &mut Context<Self>,
12222    ) {
12223        self.end_selection(window, cx);
12224        self.selection_history.mode = SelectionHistoryMode::Undoing;
12225        if let Some(entry) = self.selection_history.undo_stack.pop_back() {
12226            self.change_selections(None, window, cx, |s| {
12227                s.select_anchors(entry.selections.to_vec())
12228            });
12229            self.select_next_state = entry.select_next_state;
12230            self.select_prev_state = entry.select_prev_state;
12231            self.add_selections_state = entry.add_selections_state;
12232            self.request_autoscroll(Autoscroll::newest(), cx);
12233        }
12234        self.selection_history.mode = SelectionHistoryMode::Normal;
12235    }
12236
12237    pub fn redo_selection(
12238        &mut self,
12239        _: &RedoSelection,
12240        window: &mut Window,
12241        cx: &mut Context<Self>,
12242    ) {
12243        self.end_selection(window, cx);
12244        self.selection_history.mode = SelectionHistoryMode::Redoing;
12245        if let Some(entry) = self.selection_history.redo_stack.pop_back() {
12246            self.change_selections(None, window, cx, |s| {
12247                s.select_anchors(entry.selections.to_vec())
12248            });
12249            self.select_next_state = entry.select_next_state;
12250            self.select_prev_state = entry.select_prev_state;
12251            self.add_selections_state = entry.add_selections_state;
12252            self.request_autoscroll(Autoscroll::newest(), cx);
12253        }
12254        self.selection_history.mode = SelectionHistoryMode::Normal;
12255    }
12256
12257    pub fn expand_excerpts(
12258        &mut self,
12259        action: &ExpandExcerpts,
12260        _: &mut Window,
12261        cx: &mut Context<Self>,
12262    ) {
12263        self.expand_excerpts_for_direction(action.lines, ExpandExcerptDirection::UpAndDown, cx)
12264    }
12265
12266    pub fn expand_excerpts_down(
12267        &mut self,
12268        action: &ExpandExcerptsDown,
12269        _: &mut Window,
12270        cx: &mut Context<Self>,
12271    ) {
12272        self.expand_excerpts_for_direction(action.lines, ExpandExcerptDirection::Down, cx)
12273    }
12274
12275    pub fn expand_excerpts_up(
12276        &mut self,
12277        action: &ExpandExcerptsUp,
12278        _: &mut Window,
12279        cx: &mut Context<Self>,
12280    ) {
12281        self.expand_excerpts_for_direction(action.lines, ExpandExcerptDirection::Up, cx)
12282    }
12283
12284    pub fn expand_excerpts_for_direction(
12285        &mut self,
12286        lines: u32,
12287        direction: ExpandExcerptDirection,
12288
12289        cx: &mut Context<Self>,
12290    ) {
12291        let selections = self.selections.disjoint_anchors();
12292
12293        let lines = if lines == 0 {
12294            EditorSettings::get_global(cx).expand_excerpt_lines
12295        } else {
12296            lines
12297        };
12298
12299        self.buffer.update(cx, |buffer, cx| {
12300            let snapshot = buffer.snapshot(cx);
12301            let mut excerpt_ids = selections
12302                .iter()
12303                .flat_map(|selection| snapshot.excerpt_ids_for_range(selection.range()))
12304                .collect::<Vec<_>>();
12305            excerpt_ids.sort();
12306            excerpt_ids.dedup();
12307            buffer.expand_excerpts(excerpt_ids, lines, direction, cx)
12308        })
12309    }
12310
12311    pub fn expand_excerpt(
12312        &mut self,
12313        excerpt: ExcerptId,
12314        direction: ExpandExcerptDirection,
12315        window: &mut Window,
12316        cx: &mut Context<Self>,
12317    ) {
12318        let current_scroll_position = self.scroll_position(cx);
12319        let lines = EditorSettings::get_global(cx).expand_excerpt_lines;
12320        self.buffer.update(cx, |buffer, cx| {
12321            buffer.expand_excerpts([excerpt], lines, direction, cx)
12322        });
12323        if direction == ExpandExcerptDirection::Down {
12324            let new_scroll_position = current_scroll_position + gpui::Point::new(0.0, lines as f32);
12325            self.set_scroll_position(new_scroll_position, window, cx);
12326        }
12327    }
12328
12329    pub fn go_to_singleton_buffer_point(
12330        &mut self,
12331        point: Point,
12332        window: &mut Window,
12333        cx: &mut Context<Self>,
12334    ) {
12335        self.go_to_singleton_buffer_range(point..point, window, cx);
12336    }
12337
12338    pub fn go_to_singleton_buffer_range(
12339        &mut self,
12340        range: Range<Point>,
12341        window: &mut Window,
12342        cx: &mut Context<Self>,
12343    ) {
12344        let multibuffer = self.buffer().read(cx);
12345        let Some(buffer) = multibuffer.as_singleton() else {
12346            return;
12347        };
12348        let Some(start) = multibuffer.buffer_point_to_anchor(&buffer, range.start, cx) else {
12349            return;
12350        };
12351        let Some(end) = multibuffer.buffer_point_to_anchor(&buffer, range.end, cx) else {
12352            return;
12353        };
12354        self.change_selections(Some(Autoscroll::center()), window, cx, |s| {
12355            s.select_anchor_ranges([start..end])
12356        });
12357    }
12358
12359    fn go_to_diagnostic(
12360        &mut self,
12361        _: &GoToDiagnostic,
12362        window: &mut Window,
12363        cx: &mut Context<Self>,
12364    ) {
12365        self.go_to_diagnostic_impl(Direction::Next, window, cx)
12366    }
12367
12368    fn go_to_prev_diagnostic(
12369        &mut self,
12370        _: &GoToPreviousDiagnostic,
12371        window: &mut Window,
12372        cx: &mut Context<Self>,
12373    ) {
12374        self.go_to_diagnostic_impl(Direction::Prev, window, cx)
12375    }
12376
12377    pub fn go_to_diagnostic_impl(
12378        &mut self,
12379        direction: Direction,
12380        window: &mut Window,
12381        cx: &mut Context<Self>,
12382    ) {
12383        let buffer = self.buffer.read(cx).snapshot(cx);
12384        let selection = self.selections.newest::<usize>(cx);
12385
12386        // If there is an active Diagnostic Popover jump to its diagnostic instead.
12387        if direction == Direction::Next {
12388            if let Some(popover) = self.hover_state.diagnostic_popover.as_ref() {
12389                let Some(buffer_id) = popover.local_diagnostic.range.start.buffer_id else {
12390                    return;
12391                };
12392                self.activate_diagnostics(
12393                    buffer_id,
12394                    popover.local_diagnostic.diagnostic.group_id,
12395                    window,
12396                    cx,
12397                );
12398                if let Some(active_diagnostics) = self.active_diagnostics.as_ref() {
12399                    let primary_range_start = active_diagnostics.primary_range.start;
12400                    self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
12401                        let mut new_selection = s.newest_anchor().clone();
12402                        new_selection.collapse_to(primary_range_start, SelectionGoal::None);
12403                        s.select_anchors(vec![new_selection.clone()]);
12404                    });
12405                    self.refresh_inline_completion(false, true, window, cx);
12406                }
12407                return;
12408            }
12409        }
12410
12411        let active_group_id = self
12412            .active_diagnostics
12413            .as_ref()
12414            .map(|active_group| active_group.group_id);
12415        let active_primary_range = self.active_diagnostics.as_ref().map(|active_diagnostics| {
12416            active_diagnostics
12417                .primary_range
12418                .to_offset(&buffer)
12419                .to_inclusive()
12420        });
12421        let search_start = if let Some(active_primary_range) = active_primary_range.as_ref() {
12422            if active_primary_range.contains(&selection.head()) {
12423                *active_primary_range.start()
12424            } else {
12425                selection.head()
12426            }
12427        } else {
12428            selection.head()
12429        };
12430
12431        let snapshot = self.snapshot(window, cx);
12432        let primary_diagnostics_before = buffer
12433            .diagnostics_in_range::<usize>(0..search_start)
12434            .filter(|entry| entry.diagnostic.is_primary)
12435            .filter(|entry| entry.range.start != entry.range.end)
12436            .filter(|entry| entry.diagnostic.severity <= DiagnosticSeverity::WARNING)
12437            .filter(|entry| !snapshot.intersects_fold(entry.range.start))
12438            .collect::<Vec<_>>();
12439        let last_same_group_diagnostic_before = active_group_id.and_then(|active_group_id| {
12440            primary_diagnostics_before
12441                .iter()
12442                .position(|entry| entry.diagnostic.group_id == active_group_id)
12443        });
12444
12445        let primary_diagnostics_after = buffer
12446            .diagnostics_in_range::<usize>(search_start..buffer.len())
12447            .filter(|entry| entry.diagnostic.is_primary)
12448            .filter(|entry| entry.range.start != entry.range.end)
12449            .filter(|entry| entry.diagnostic.severity <= DiagnosticSeverity::WARNING)
12450            .filter(|diagnostic| !snapshot.intersects_fold(diagnostic.range.start))
12451            .collect::<Vec<_>>();
12452        let last_same_group_diagnostic_after = active_group_id.and_then(|active_group_id| {
12453            primary_diagnostics_after
12454                .iter()
12455                .enumerate()
12456                .rev()
12457                .find_map(|(i, entry)| {
12458                    if entry.diagnostic.group_id == active_group_id {
12459                        Some(i)
12460                    } else {
12461                        None
12462                    }
12463                })
12464        });
12465
12466        let next_primary_diagnostic = match direction {
12467            Direction::Prev => primary_diagnostics_before
12468                .iter()
12469                .take(last_same_group_diagnostic_before.unwrap_or(usize::MAX))
12470                .rev()
12471                .next(),
12472            Direction::Next => primary_diagnostics_after
12473                .iter()
12474                .skip(
12475                    last_same_group_diagnostic_after
12476                        .map(|index| index + 1)
12477                        .unwrap_or(0),
12478                )
12479                .next(),
12480        };
12481
12482        // Cycle around to the start of the buffer, potentially moving back to the start of
12483        // the currently active diagnostic.
12484        let cycle_around = || match direction {
12485            Direction::Prev => primary_diagnostics_after
12486                .iter()
12487                .rev()
12488                .chain(primary_diagnostics_before.iter().rev())
12489                .next(),
12490            Direction::Next => primary_diagnostics_before
12491                .iter()
12492                .chain(primary_diagnostics_after.iter())
12493                .next(),
12494        };
12495
12496        if let Some((primary_range, group_id)) = next_primary_diagnostic
12497            .or_else(cycle_around)
12498            .map(|entry| (&entry.range, entry.diagnostic.group_id))
12499        {
12500            let Some(buffer_id) = buffer.anchor_after(primary_range.start).buffer_id else {
12501                return;
12502            };
12503            self.activate_diagnostics(buffer_id, group_id, window, cx);
12504            if self.active_diagnostics.is_some() {
12505                self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
12506                    s.select(vec![Selection {
12507                        id: selection.id,
12508                        start: primary_range.start,
12509                        end: primary_range.start,
12510                        reversed: false,
12511                        goal: SelectionGoal::None,
12512                    }]);
12513                });
12514                self.refresh_inline_completion(false, true, window, cx);
12515            }
12516        }
12517    }
12518
12519    fn go_to_next_hunk(&mut self, _: &GoToHunk, window: &mut Window, cx: &mut Context<Self>) {
12520        let snapshot = self.snapshot(window, cx);
12521        let selection = self.selections.newest::<Point>(cx);
12522        self.go_to_hunk_before_or_after_position(
12523            &snapshot,
12524            selection.head(),
12525            Direction::Next,
12526            window,
12527            cx,
12528        );
12529    }
12530
12531    fn go_to_hunk_before_or_after_position(
12532        &mut self,
12533        snapshot: &EditorSnapshot,
12534        position: Point,
12535        direction: Direction,
12536        window: &mut Window,
12537        cx: &mut Context<Editor>,
12538    ) {
12539        let row = if direction == Direction::Next {
12540            self.hunk_after_position(snapshot, position)
12541                .map(|hunk| hunk.row_range.start)
12542        } else {
12543            self.hunk_before_position(snapshot, position)
12544        };
12545
12546        if let Some(row) = row {
12547            let destination = Point::new(row.0, 0);
12548            let autoscroll = Autoscroll::center();
12549
12550            self.unfold_ranges(&[destination..destination], false, false, cx);
12551            self.change_selections(Some(autoscroll), window, cx, |s| {
12552                s.select_ranges([destination..destination]);
12553            });
12554        }
12555    }
12556
12557    fn hunk_after_position(
12558        &mut self,
12559        snapshot: &EditorSnapshot,
12560        position: Point,
12561    ) -> Option<MultiBufferDiffHunk> {
12562        snapshot
12563            .buffer_snapshot
12564            .diff_hunks_in_range(position..snapshot.buffer_snapshot.max_point())
12565            .find(|hunk| hunk.row_range.start.0 > position.row)
12566            .or_else(|| {
12567                snapshot
12568                    .buffer_snapshot
12569                    .diff_hunks_in_range(Point::zero()..position)
12570                    .find(|hunk| hunk.row_range.end.0 < position.row)
12571            })
12572    }
12573
12574    fn go_to_prev_hunk(
12575        &mut self,
12576        _: &GoToPreviousHunk,
12577        window: &mut Window,
12578        cx: &mut Context<Self>,
12579    ) {
12580        let snapshot = self.snapshot(window, cx);
12581        let selection = self.selections.newest::<Point>(cx);
12582        self.go_to_hunk_before_or_after_position(
12583            &snapshot,
12584            selection.head(),
12585            Direction::Prev,
12586            window,
12587            cx,
12588        );
12589    }
12590
12591    fn hunk_before_position(
12592        &mut self,
12593        snapshot: &EditorSnapshot,
12594        position: Point,
12595    ) -> Option<MultiBufferRow> {
12596        snapshot
12597            .buffer_snapshot
12598            .diff_hunk_before(position)
12599            .or_else(|| snapshot.buffer_snapshot.diff_hunk_before(Point::MAX))
12600    }
12601
12602    fn go_to_line<T: 'static>(
12603        &mut self,
12604        position: Anchor,
12605        highlight_color: Option<Hsla>,
12606        window: &mut Window,
12607        cx: &mut Context<Self>,
12608    ) {
12609        let snapshot = self.snapshot(window, cx).display_snapshot;
12610        let position = position.to_point(&snapshot.buffer_snapshot);
12611        let start = snapshot
12612            .buffer_snapshot
12613            .clip_point(Point::new(position.row, 0), Bias::Left);
12614        let end = start + Point::new(1, 0);
12615        let start = snapshot.buffer_snapshot.anchor_before(start);
12616        let end = snapshot.buffer_snapshot.anchor_before(end);
12617
12618        self.clear_row_highlights::<T>();
12619        self.highlight_rows::<T>(
12620            start..end,
12621            highlight_color
12622                .unwrap_or_else(|| cx.theme().colors().editor_highlighted_line_background),
12623            true,
12624            cx,
12625        );
12626        self.request_autoscroll(Autoscroll::center(), cx);
12627    }
12628
12629    pub fn go_to_definition(
12630        &mut self,
12631        _: &GoToDefinition,
12632        window: &mut Window,
12633        cx: &mut Context<Self>,
12634    ) -> Task<Result<Navigated>> {
12635        let definition =
12636            self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, false, window, cx);
12637        cx.spawn_in(window, async move |editor, cx| {
12638            if definition.await? == Navigated::Yes {
12639                return Ok(Navigated::Yes);
12640            }
12641            match editor.update_in(cx, |editor, window, cx| {
12642                editor.find_all_references(&FindAllReferences, window, cx)
12643            })? {
12644                Some(references) => references.await,
12645                None => Ok(Navigated::No),
12646            }
12647        })
12648    }
12649
12650    pub fn go_to_declaration(
12651        &mut self,
12652        _: &GoToDeclaration,
12653        window: &mut Window,
12654        cx: &mut Context<Self>,
12655    ) -> Task<Result<Navigated>> {
12656        self.go_to_definition_of_kind(GotoDefinitionKind::Declaration, false, window, cx)
12657    }
12658
12659    pub fn go_to_declaration_split(
12660        &mut self,
12661        _: &GoToDeclaration,
12662        window: &mut Window,
12663        cx: &mut Context<Self>,
12664    ) -> Task<Result<Navigated>> {
12665        self.go_to_definition_of_kind(GotoDefinitionKind::Declaration, true, window, cx)
12666    }
12667
12668    pub fn go_to_implementation(
12669        &mut self,
12670        _: &GoToImplementation,
12671        window: &mut Window,
12672        cx: &mut Context<Self>,
12673    ) -> Task<Result<Navigated>> {
12674        self.go_to_definition_of_kind(GotoDefinitionKind::Implementation, false, window, cx)
12675    }
12676
12677    pub fn go_to_implementation_split(
12678        &mut self,
12679        _: &GoToImplementationSplit,
12680        window: &mut Window,
12681        cx: &mut Context<Self>,
12682    ) -> Task<Result<Navigated>> {
12683        self.go_to_definition_of_kind(GotoDefinitionKind::Implementation, true, window, cx)
12684    }
12685
12686    pub fn go_to_type_definition(
12687        &mut self,
12688        _: &GoToTypeDefinition,
12689        window: &mut Window,
12690        cx: &mut Context<Self>,
12691    ) -> Task<Result<Navigated>> {
12692        self.go_to_definition_of_kind(GotoDefinitionKind::Type, false, window, cx)
12693    }
12694
12695    pub fn go_to_definition_split(
12696        &mut self,
12697        _: &GoToDefinitionSplit,
12698        window: &mut Window,
12699        cx: &mut Context<Self>,
12700    ) -> Task<Result<Navigated>> {
12701        self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, true, window, cx)
12702    }
12703
12704    pub fn go_to_type_definition_split(
12705        &mut self,
12706        _: &GoToTypeDefinitionSplit,
12707        window: &mut Window,
12708        cx: &mut Context<Self>,
12709    ) -> Task<Result<Navigated>> {
12710        self.go_to_definition_of_kind(GotoDefinitionKind::Type, true, window, cx)
12711    }
12712
12713    fn go_to_definition_of_kind(
12714        &mut self,
12715        kind: GotoDefinitionKind,
12716        split: bool,
12717        window: &mut Window,
12718        cx: &mut Context<Self>,
12719    ) -> Task<Result<Navigated>> {
12720        let Some(provider) = self.semantics_provider.clone() else {
12721            return Task::ready(Ok(Navigated::No));
12722        };
12723        let head = self.selections.newest::<usize>(cx).head();
12724        let buffer = self.buffer.read(cx);
12725        let (buffer, head) = if let Some(text_anchor) = buffer.text_anchor_for_position(head, cx) {
12726            text_anchor
12727        } else {
12728            return Task::ready(Ok(Navigated::No));
12729        };
12730
12731        let Some(definitions) = provider.definitions(&buffer, head, kind, cx) else {
12732            return Task::ready(Ok(Navigated::No));
12733        };
12734
12735        cx.spawn_in(window, async move |editor, cx| {
12736            let definitions = definitions.await?;
12737            let navigated = editor
12738                .update_in(cx, |editor, window, cx| {
12739                    editor.navigate_to_hover_links(
12740                        Some(kind),
12741                        definitions
12742                            .into_iter()
12743                            .filter(|location| {
12744                                hover_links::exclude_link_to_position(&buffer, &head, location, cx)
12745                            })
12746                            .map(HoverLink::Text)
12747                            .collect::<Vec<_>>(),
12748                        split,
12749                        window,
12750                        cx,
12751                    )
12752                })?
12753                .await?;
12754            anyhow::Ok(navigated)
12755        })
12756    }
12757
12758    pub fn open_url(&mut self, _: &OpenUrl, window: &mut Window, cx: &mut Context<Self>) {
12759        let selection = self.selections.newest_anchor();
12760        let head = selection.head();
12761        let tail = selection.tail();
12762
12763        let Some((buffer, start_position)) =
12764            self.buffer.read(cx).text_anchor_for_position(head, cx)
12765        else {
12766            return;
12767        };
12768
12769        let end_position = if head != tail {
12770            let Some((_, pos)) = self.buffer.read(cx).text_anchor_for_position(tail, cx) else {
12771                return;
12772            };
12773            Some(pos)
12774        } else {
12775            None
12776        };
12777
12778        let url_finder = cx.spawn_in(window, async move |editor, cx| {
12779            let url = if let Some(end_pos) = end_position {
12780                find_url_from_range(&buffer, start_position..end_pos, cx.clone())
12781            } else {
12782                find_url(&buffer, start_position, cx.clone()).map(|(_, url)| url)
12783            };
12784
12785            if let Some(url) = url {
12786                editor.update(cx, |_, cx| {
12787                    cx.open_url(&url);
12788                })
12789            } else {
12790                Ok(())
12791            }
12792        });
12793
12794        url_finder.detach();
12795    }
12796
12797    pub fn open_selected_filename(
12798        &mut self,
12799        _: &OpenSelectedFilename,
12800        window: &mut Window,
12801        cx: &mut Context<Self>,
12802    ) {
12803        let Some(workspace) = self.workspace() else {
12804            return;
12805        };
12806
12807        let position = self.selections.newest_anchor().head();
12808
12809        let Some((buffer, buffer_position)) =
12810            self.buffer.read(cx).text_anchor_for_position(position, cx)
12811        else {
12812            return;
12813        };
12814
12815        let project = self.project.clone();
12816
12817        cx.spawn_in(window, async move |_, cx| {
12818            let result = find_file(&buffer, project, buffer_position, cx).await;
12819
12820            if let Some((_, path)) = result {
12821                workspace
12822                    .update_in(cx, |workspace, window, cx| {
12823                        workspace.open_resolved_path(path, window, cx)
12824                    })?
12825                    .await?;
12826            }
12827            anyhow::Ok(())
12828        })
12829        .detach();
12830    }
12831
12832    pub(crate) fn navigate_to_hover_links(
12833        &mut self,
12834        kind: Option<GotoDefinitionKind>,
12835        mut definitions: Vec<HoverLink>,
12836        split: bool,
12837        window: &mut Window,
12838        cx: &mut Context<Editor>,
12839    ) -> Task<Result<Navigated>> {
12840        // If there is one definition, just open it directly
12841        if definitions.len() == 1 {
12842            let definition = definitions.pop().unwrap();
12843
12844            enum TargetTaskResult {
12845                Location(Option<Location>),
12846                AlreadyNavigated,
12847            }
12848
12849            let target_task = match definition {
12850                HoverLink::Text(link) => {
12851                    Task::ready(anyhow::Ok(TargetTaskResult::Location(Some(link.target))))
12852                }
12853                HoverLink::InlayHint(lsp_location, server_id) => {
12854                    let computation =
12855                        self.compute_target_location(lsp_location, server_id, window, cx);
12856                    cx.background_spawn(async move {
12857                        let location = computation.await?;
12858                        Ok(TargetTaskResult::Location(location))
12859                    })
12860                }
12861                HoverLink::Url(url) => {
12862                    cx.open_url(&url);
12863                    Task::ready(Ok(TargetTaskResult::AlreadyNavigated))
12864                }
12865                HoverLink::File(path) => {
12866                    if let Some(workspace) = self.workspace() {
12867                        cx.spawn_in(window, async move |_, cx| {
12868                            workspace
12869                                .update_in(cx, |workspace, window, cx| {
12870                                    workspace.open_resolved_path(path, window, cx)
12871                                })?
12872                                .await
12873                                .map(|_| TargetTaskResult::AlreadyNavigated)
12874                        })
12875                    } else {
12876                        Task::ready(Ok(TargetTaskResult::Location(None)))
12877                    }
12878                }
12879            };
12880            cx.spawn_in(window, async move |editor, cx| {
12881                let target = match target_task.await.context("target resolution task")? {
12882                    TargetTaskResult::AlreadyNavigated => return Ok(Navigated::Yes),
12883                    TargetTaskResult::Location(None) => return Ok(Navigated::No),
12884                    TargetTaskResult::Location(Some(target)) => target,
12885                };
12886
12887                editor.update_in(cx, |editor, window, cx| {
12888                    let Some(workspace) = editor.workspace() else {
12889                        return Navigated::No;
12890                    };
12891                    let pane = workspace.read(cx).active_pane().clone();
12892
12893                    let range = target.range.to_point(target.buffer.read(cx));
12894                    let range = editor.range_for_match(&range);
12895                    let range = collapse_multiline_range(range);
12896
12897                    if !split
12898                        && Some(&target.buffer) == editor.buffer.read(cx).as_singleton().as_ref()
12899                    {
12900                        editor.go_to_singleton_buffer_range(range.clone(), window, cx);
12901                    } else {
12902                        window.defer(cx, move |window, cx| {
12903                            let target_editor: Entity<Self> =
12904                                workspace.update(cx, |workspace, cx| {
12905                                    let pane = if split {
12906                                        workspace.adjacent_pane(window, cx)
12907                                    } else {
12908                                        workspace.active_pane().clone()
12909                                    };
12910
12911                                    workspace.open_project_item(
12912                                        pane,
12913                                        target.buffer.clone(),
12914                                        true,
12915                                        true,
12916                                        window,
12917                                        cx,
12918                                    )
12919                                });
12920                            target_editor.update(cx, |target_editor, cx| {
12921                                // When selecting a definition in a different buffer, disable the nav history
12922                                // to avoid creating a history entry at the previous cursor location.
12923                                pane.update(cx, |pane, _| pane.disable_history());
12924                                target_editor.go_to_singleton_buffer_range(range, window, cx);
12925                                pane.update(cx, |pane, _| pane.enable_history());
12926                            });
12927                        });
12928                    }
12929                    Navigated::Yes
12930                })
12931            })
12932        } else if !definitions.is_empty() {
12933            cx.spawn_in(window, async move |editor, cx| {
12934                let (title, location_tasks, workspace) = editor
12935                    .update_in(cx, |editor, window, cx| {
12936                        let tab_kind = match kind {
12937                            Some(GotoDefinitionKind::Implementation) => "Implementations",
12938                            _ => "Definitions",
12939                        };
12940                        let title = definitions
12941                            .iter()
12942                            .find_map(|definition| match definition {
12943                                HoverLink::Text(link) => link.origin.as_ref().map(|origin| {
12944                                    let buffer = origin.buffer.read(cx);
12945                                    format!(
12946                                        "{} for {}",
12947                                        tab_kind,
12948                                        buffer
12949                                            .text_for_range(origin.range.clone())
12950                                            .collect::<String>()
12951                                    )
12952                                }),
12953                                HoverLink::InlayHint(_, _) => None,
12954                                HoverLink::Url(_) => None,
12955                                HoverLink::File(_) => None,
12956                            })
12957                            .unwrap_or(tab_kind.to_string());
12958                        let location_tasks = definitions
12959                            .into_iter()
12960                            .map(|definition| match definition {
12961                                HoverLink::Text(link) => Task::ready(Ok(Some(link.target))),
12962                                HoverLink::InlayHint(lsp_location, server_id) => editor
12963                                    .compute_target_location(lsp_location, server_id, window, cx),
12964                                HoverLink::Url(_) => Task::ready(Ok(None)),
12965                                HoverLink::File(_) => Task::ready(Ok(None)),
12966                            })
12967                            .collect::<Vec<_>>();
12968                        (title, location_tasks, editor.workspace().clone())
12969                    })
12970                    .context("location tasks preparation")?;
12971
12972                let locations = future::join_all(location_tasks)
12973                    .await
12974                    .into_iter()
12975                    .filter_map(|location| location.transpose())
12976                    .collect::<Result<_>>()
12977                    .context("location tasks")?;
12978
12979                let Some(workspace) = workspace else {
12980                    return Ok(Navigated::No);
12981                };
12982                let opened = workspace
12983                    .update_in(cx, |workspace, window, cx| {
12984                        Self::open_locations_in_multibuffer(
12985                            workspace,
12986                            locations,
12987                            title,
12988                            split,
12989                            MultibufferSelectionMode::First,
12990                            window,
12991                            cx,
12992                        )
12993                    })
12994                    .ok();
12995
12996                anyhow::Ok(Navigated::from_bool(opened.is_some()))
12997            })
12998        } else {
12999            Task::ready(Ok(Navigated::No))
13000        }
13001    }
13002
13003    fn compute_target_location(
13004        &self,
13005        lsp_location: lsp::Location,
13006        server_id: LanguageServerId,
13007        window: &mut Window,
13008        cx: &mut Context<Self>,
13009    ) -> Task<anyhow::Result<Option<Location>>> {
13010        let Some(project) = self.project.clone() else {
13011            return Task::ready(Ok(None));
13012        };
13013
13014        cx.spawn_in(window, async move |editor, cx| {
13015            let location_task = editor.update(cx, |_, cx| {
13016                project.update(cx, |project, cx| {
13017                    let language_server_name = project
13018                        .language_server_statuses(cx)
13019                        .find(|(id, _)| server_id == *id)
13020                        .map(|(_, status)| LanguageServerName::from(status.name.as_str()));
13021                    language_server_name.map(|language_server_name| {
13022                        project.open_local_buffer_via_lsp(
13023                            lsp_location.uri.clone(),
13024                            server_id,
13025                            language_server_name,
13026                            cx,
13027                        )
13028                    })
13029                })
13030            })?;
13031            let location = match location_task {
13032                Some(task) => Some({
13033                    let target_buffer_handle = task.await.context("open local buffer")?;
13034                    let range = target_buffer_handle.update(cx, |target_buffer, _| {
13035                        let target_start = target_buffer
13036                            .clip_point_utf16(point_from_lsp(lsp_location.range.start), Bias::Left);
13037                        let target_end = target_buffer
13038                            .clip_point_utf16(point_from_lsp(lsp_location.range.end), Bias::Left);
13039                        target_buffer.anchor_after(target_start)
13040                            ..target_buffer.anchor_before(target_end)
13041                    })?;
13042                    Location {
13043                        buffer: target_buffer_handle,
13044                        range,
13045                    }
13046                }),
13047                None => None,
13048            };
13049            Ok(location)
13050        })
13051    }
13052
13053    pub fn find_all_references(
13054        &mut self,
13055        _: &FindAllReferences,
13056        window: &mut Window,
13057        cx: &mut Context<Self>,
13058    ) -> Option<Task<Result<Navigated>>> {
13059        let selection = self.selections.newest::<usize>(cx);
13060        let multi_buffer = self.buffer.read(cx);
13061        let head = selection.head();
13062
13063        let multi_buffer_snapshot = multi_buffer.snapshot(cx);
13064        let head_anchor = multi_buffer_snapshot.anchor_at(
13065            head,
13066            if head < selection.tail() {
13067                Bias::Right
13068            } else {
13069                Bias::Left
13070            },
13071        );
13072
13073        match self
13074            .find_all_references_task_sources
13075            .binary_search_by(|anchor| anchor.cmp(&head_anchor, &multi_buffer_snapshot))
13076        {
13077            Ok(_) => {
13078                log::info!(
13079                    "Ignoring repeated FindAllReferences invocation with the position of already running task"
13080                );
13081                return None;
13082            }
13083            Err(i) => {
13084                self.find_all_references_task_sources.insert(i, head_anchor);
13085            }
13086        }
13087
13088        let (buffer, head) = multi_buffer.text_anchor_for_position(head, cx)?;
13089        let workspace = self.workspace()?;
13090        let project = workspace.read(cx).project().clone();
13091        let references = project.update(cx, |project, cx| project.references(&buffer, head, cx));
13092        Some(cx.spawn_in(window, async move |editor, cx| {
13093            let _cleanup = cx.on_drop(&editor, move |editor, _| {
13094                if let Ok(i) = editor
13095                    .find_all_references_task_sources
13096                    .binary_search_by(|anchor| anchor.cmp(&head_anchor, &multi_buffer_snapshot))
13097                {
13098                    editor.find_all_references_task_sources.remove(i);
13099                }
13100            });
13101
13102            let locations = references.await?;
13103            if locations.is_empty() {
13104                return anyhow::Ok(Navigated::No);
13105            }
13106
13107            workspace.update_in(cx, |workspace, window, cx| {
13108                let title = locations
13109                    .first()
13110                    .as_ref()
13111                    .map(|location| {
13112                        let buffer = location.buffer.read(cx);
13113                        format!(
13114                            "References to `{}`",
13115                            buffer
13116                                .text_for_range(location.range.clone())
13117                                .collect::<String>()
13118                        )
13119                    })
13120                    .unwrap();
13121                Self::open_locations_in_multibuffer(
13122                    workspace,
13123                    locations,
13124                    title,
13125                    false,
13126                    MultibufferSelectionMode::First,
13127                    window,
13128                    cx,
13129                );
13130                Navigated::Yes
13131            })
13132        }))
13133    }
13134
13135    /// Opens a multibuffer with the given project locations in it
13136    pub fn open_locations_in_multibuffer(
13137        workspace: &mut Workspace,
13138        mut locations: Vec<Location>,
13139        title: String,
13140        split: bool,
13141        multibuffer_selection_mode: MultibufferSelectionMode,
13142        window: &mut Window,
13143        cx: &mut Context<Workspace>,
13144    ) {
13145        // If there are multiple definitions, open them in a multibuffer
13146        locations.sort_by_key(|location| location.buffer.read(cx).remote_id());
13147        let mut locations = locations.into_iter().peekable();
13148        let mut ranges = Vec::new();
13149        let capability = workspace.project().read(cx).capability();
13150
13151        let excerpt_buffer = cx.new(|cx| {
13152            let mut multibuffer = MultiBuffer::new(capability);
13153            while let Some(location) = locations.next() {
13154                let buffer = location.buffer.read(cx);
13155                let mut ranges_for_buffer = Vec::new();
13156                let range = location.range.to_offset(buffer);
13157                ranges_for_buffer.push(range.clone());
13158
13159                while let Some(next_location) = locations.peek() {
13160                    if next_location.buffer == location.buffer {
13161                        ranges_for_buffer.push(next_location.range.to_offset(buffer));
13162                        locations.next();
13163                    } else {
13164                        break;
13165                    }
13166                }
13167
13168                ranges_for_buffer.sort_by_key(|range| (range.start, Reverse(range.end)));
13169                ranges.extend(multibuffer.push_excerpts_with_context_lines(
13170                    location.buffer.clone(),
13171                    ranges_for_buffer,
13172                    DEFAULT_MULTIBUFFER_CONTEXT,
13173                    cx,
13174                ))
13175            }
13176
13177            multibuffer.with_title(title)
13178        });
13179
13180        let editor = cx.new(|cx| {
13181            Editor::for_multibuffer(
13182                excerpt_buffer,
13183                Some(workspace.project().clone()),
13184                window,
13185                cx,
13186            )
13187        });
13188        editor.update(cx, |editor, cx| {
13189            match multibuffer_selection_mode {
13190                MultibufferSelectionMode::First => {
13191                    if let Some(first_range) = ranges.first() {
13192                        editor.change_selections(None, window, cx, |selections| {
13193                            selections.clear_disjoint();
13194                            selections.select_anchor_ranges(std::iter::once(first_range.clone()));
13195                        });
13196                    }
13197                    editor.highlight_background::<Self>(
13198                        &ranges,
13199                        |theme| theme.editor_highlighted_line_background,
13200                        cx,
13201                    );
13202                }
13203                MultibufferSelectionMode::All => {
13204                    editor.change_selections(None, window, cx, |selections| {
13205                        selections.clear_disjoint();
13206                        selections.select_anchor_ranges(ranges);
13207                    });
13208                }
13209            }
13210            editor.register_buffers_with_language_servers(cx);
13211        });
13212
13213        let item = Box::new(editor);
13214        let item_id = item.item_id();
13215
13216        if split {
13217            workspace.split_item(SplitDirection::Right, item.clone(), window, cx);
13218        } else {
13219            if PreviewTabsSettings::get_global(cx).enable_preview_from_code_navigation {
13220                let (preview_item_id, preview_item_idx) =
13221                    workspace.active_pane().update(cx, |pane, _| {
13222                        (pane.preview_item_id(), pane.preview_item_idx())
13223                    });
13224
13225                workspace.add_item_to_active_pane(item.clone(), preview_item_idx, true, window, cx);
13226
13227                if let Some(preview_item_id) = preview_item_id {
13228                    workspace.active_pane().update(cx, |pane, cx| {
13229                        pane.remove_item(preview_item_id, false, false, window, cx);
13230                    });
13231                }
13232            } else {
13233                workspace.add_item_to_active_pane(item.clone(), None, true, window, cx);
13234            }
13235        }
13236        workspace.active_pane().update(cx, |pane, cx| {
13237            pane.set_preview_item_id(Some(item_id), cx);
13238        });
13239    }
13240
13241    pub fn rename(
13242        &mut self,
13243        _: &Rename,
13244        window: &mut Window,
13245        cx: &mut Context<Self>,
13246    ) -> Option<Task<Result<()>>> {
13247        use language::ToOffset as _;
13248
13249        let provider = self.semantics_provider.clone()?;
13250        let selection = self.selections.newest_anchor().clone();
13251        let (cursor_buffer, cursor_buffer_position) = self
13252            .buffer
13253            .read(cx)
13254            .text_anchor_for_position(selection.head(), cx)?;
13255        let (tail_buffer, cursor_buffer_position_end) = self
13256            .buffer
13257            .read(cx)
13258            .text_anchor_for_position(selection.tail(), cx)?;
13259        if tail_buffer != cursor_buffer {
13260            return None;
13261        }
13262
13263        let snapshot = cursor_buffer.read(cx).snapshot();
13264        let cursor_buffer_offset = cursor_buffer_position.to_offset(&snapshot);
13265        let cursor_buffer_offset_end = cursor_buffer_position_end.to_offset(&snapshot);
13266        let prepare_rename = provider
13267            .range_for_rename(&cursor_buffer, cursor_buffer_position, cx)
13268            .unwrap_or_else(|| Task::ready(Ok(None)));
13269        drop(snapshot);
13270
13271        Some(cx.spawn_in(window, async move |this, cx| {
13272            let rename_range = if let Some(range) = prepare_rename.await? {
13273                Some(range)
13274            } else {
13275                this.update(cx, |this, cx| {
13276                    let buffer = this.buffer.read(cx).snapshot(cx);
13277                    let mut buffer_highlights = this
13278                        .document_highlights_for_position(selection.head(), &buffer)
13279                        .filter(|highlight| {
13280                            highlight.start.excerpt_id == selection.head().excerpt_id
13281                                && highlight.end.excerpt_id == selection.head().excerpt_id
13282                        });
13283                    buffer_highlights
13284                        .next()
13285                        .map(|highlight| highlight.start.text_anchor..highlight.end.text_anchor)
13286                })?
13287            };
13288            if let Some(rename_range) = rename_range {
13289                this.update_in(cx, |this, window, cx| {
13290                    let snapshot = cursor_buffer.read(cx).snapshot();
13291                    let rename_buffer_range = rename_range.to_offset(&snapshot);
13292                    let cursor_offset_in_rename_range =
13293                        cursor_buffer_offset.saturating_sub(rename_buffer_range.start);
13294                    let cursor_offset_in_rename_range_end =
13295                        cursor_buffer_offset_end.saturating_sub(rename_buffer_range.start);
13296
13297                    this.take_rename(false, window, cx);
13298                    let buffer = this.buffer.read(cx).read(cx);
13299                    let cursor_offset = selection.head().to_offset(&buffer);
13300                    let rename_start = cursor_offset.saturating_sub(cursor_offset_in_rename_range);
13301                    let rename_end = rename_start + rename_buffer_range.len();
13302                    let range = buffer.anchor_before(rename_start)..buffer.anchor_after(rename_end);
13303                    let mut old_highlight_id = None;
13304                    let old_name: Arc<str> = buffer
13305                        .chunks(rename_start..rename_end, true)
13306                        .map(|chunk| {
13307                            if old_highlight_id.is_none() {
13308                                old_highlight_id = chunk.syntax_highlight_id;
13309                            }
13310                            chunk.text
13311                        })
13312                        .collect::<String>()
13313                        .into();
13314
13315                    drop(buffer);
13316
13317                    // Position the selection in the rename editor so that it matches the current selection.
13318                    this.show_local_selections = false;
13319                    let rename_editor = cx.new(|cx| {
13320                        let mut editor = Editor::single_line(window, cx);
13321                        editor.buffer.update(cx, |buffer, cx| {
13322                            buffer.edit([(0..0, old_name.clone())], None, cx)
13323                        });
13324                        let rename_selection_range = match cursor_offset_in_rename_range
13325                            .cmp(&cursor_offset_in_rename_range_end)
13326                        {
13327                            Ordering::Equal => {
13328                                editor.select_all(&SelectAll, window, cx);
13329                                return editor;
13330                            }
13331                            Ordering::Less => {
13332                                cursor_offset_in_rename_range..cursor_offset_in_rename_range_end
13333                            }
13334                            Ordering::Greater => {
13335                                cursor_offset_in_rename_range_end..cursor_offset_in_rename_range
13336                            }
13337                        };
13338                        if rename_selection_range.end > old_name.len() {
13339                            editor.select_all(&SelectAll, window, cx);
13340                        } else {
13341                            editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
13342                                s.select_ranges([rename_selection_range]);
13343                            });
13344                        }
13345                        editor
13346                    });
13347                    cx.subscribe(&rename_editor, |_, _, e: &EditorEvent, cx| {
13348                        if e == &EditorEvent::Focused {
13349                            cx.emit(EditorEvent::FocusedIn)
13350                        }
13351                    })
13352                    .detach();
13353
13354                    let write_highlights =
13355                        this.clear_background_highlights::<DocumentHighlightWrite>(cx);
13356                    let read_highlights =
13357                        this.clear_background_highlights::<DocumentHighlightRead>(cx);
13358                    let ranges = write_highlights
13359                        .iter()
13360                        .flat_map(|(_, ranges)| ranges.iter())
13361                        .chain(read_highlights.iter().flat_map(|(_, ranges)| ranges.iter()))
13362                        .cloned()
13363                        .collect();
13364
13365                    this.highlight_text::<Rename>(
13366                        ranges,
13367                        HighlightStyle {
13368                            fade_out: Some(0.6),
13369                            ..Default::default()
13370                        },
13371                        cx,
13372                    );
13373                    let rename_focus_handle = rename_editor.focus_handle(cx);
13374                    window.focus(&rename_focus_handle);
13375                    let block_id = this.insert_blocks(
13376                        [BlockProperties {
13377                            style: BlockStyle::Flex,
13378                            placement: BlockPlacement::Below(range.start),
13379                            height: 1,
13380                            render: Arc::new({
13381                                let rename_editor = rename_editor.clone();
13382                                move |cx: &mut BlockContext| {
13383                                    let mut text_style = cx.editor_style.text.clone();
13384                                    if let Some(highlight_style) = old_highlight_id
13385                                        .and_then(|h| h.style(&cx.editor_style.syntax))
13386                                    {
13387                                        text_style = text_style.highlight(highlight_style);
13388                                    }
13389                                    div()
13390                                        .block_mouse_down()
13391                                        .pl(cx.anchor_x)
13392                                        .child(EditorElement::new(
13393                                            &rename_editor,
13394                                            EditorStyle {
13395                                                background: cx.theme().system().transparent,
13396                                                local_player: cx.editor_style.local_player,
13397                                                text: text_style,
13398                                                scrollbar_width: cx.editor_style.scrollbar_width,
13399                                                syntax: cx.editor_style.syntax.clone(),
13400                                                status: cx.editor_style.status.clone(),
13401                                                inlay_hints_style: HighlightStyle {
13402                                                    font_weight: Some(FontWeight::BOLD),
13403                                                    ..make_inlay_hints_style(cx.app)
13404                                                },
13405                                                inline_completion_styles: make_suggestion_styles(
13406                                                    cx.app,
13407                                                ),
13408                                                ..EditorStyle::default()
13409                                            },
13410                                        ))
13411                                        .into_any_element()
13412                                }
13413                            }),
13414                            priority: 0,
13415                        }],
13416                        Some(Autoscroll::fit()),
13417                        cx,
13418                    )[0];
13419                    this.pending_rename = Some(RenameState {
13420                        range,
13421                        old_name,
13422                        editor: rename_editor,
13423                        block_id,
13424                    });
13425                })?;
13426            }
13427
13428            Ok(())
13429        }))
13430    }
13431
13432    pub fn confirm_rename(
13433        &mut self,
13434        _: &ConfirmRename,
13435        window: &mut Window,
13436        cx: &mut Context<Self>,
13437    ) -> Option<Task<Result<()>>> {
13438        let rename = self.take_rename(false, window, cx)?;
13439        let workspace = self.workspace()?.downgrade();
13440        let (buffer, start) = self
13441            .buffer
13442            .read(cx)
13443            .text_anchor_for_position(rename.range.start, cx)?;
13444        let (end_buffer, _) = self
13445            .buffer
13446            .read(cx)
13447            .text_anchor_for_position(rename.range.end, cx)?;
13448        if buffer != end_buffer {
13449            return None;
13450        }
13451
13452        let old_name = rename.old_name;
13453        let new_name = rename.editor.read(cx).text(cx);
13454
13455        let rename = self.semantics_provider.as_ref()?.perform_rename(
13456            &buffer,
13457            start,
13458            new_name.clone(),
13459            cx,
13460        )?;
13461
13462        Some(cx.spawn_in(window, async move |editor, cx| {
13463            let project_transaction = rename.await?;
13464            Self::open_project_transaction(
13465                &editor,
13466                workspace,
13467                project_transaction,
13468                format!("Rename: {}{}", old_name, new_name),
13469                cx,
13470            )
13471            .await?;
13472
13473            editor.update(cx, |editor, cx| {
13474                editor.refresh_document_highlights(cx);
13475            })?;
13476            Ok(())
13477        }))
13478    }
13479
13480    fn take_rename(
13481        &mut self,
13482        moving_cursor: bool,
13483        window: &mut Window,
13484        cx: &mut Context<Self>,
13485    ) -> Option<RenameState> {
13486        let rename = self.pending_rename.take()?;
13487        if rename.editor.focus_handle(cx).is_focused(window) {
13488            window.focus(&self.focus_handle);
13489        }
13490
13491        self.remove_blocks(
13492            [rename.block_id].into_iter().collect(),
13493            Some(Autoscroll::fit()),
13494            cx,
13495        );
13496        self.clear_highlights::<Rename>(cx);
13497        self.show_local_selections = true;
13498
13499        if moving_cursor {
13500            let cursor_in_rename_editor = rename.editor.update(cx, |editor, cx| {
13501                editor.selections.newest::<usize>(cx).head()
13502            });
13503
13504            // Update the selection to match the position of the selection inside
13505            // the rename editor.
13506            let snapshot = self.buffer.read(cx).read(cx);
13507            let rename_range = rename.range.to_offset(&snapshot);
13508            let cursor_in_editor = snapshot
13509                .clip_offset(rename_range.start + cursor_in_rename_editor, Bias::Left)
13510                .min(rename_range.end);
13511            drop(snapshot);
13512
13513            self.change_selections(None, window, cx, |s| {
13514                s.select_ranges(vec![cursor_in_editor..cursor_in_editor])
13515            });
13516        } else {
13517            self.refresh_document_highlights(cx);
13518        }
13519
13520        Some(rename)
13521    }
13522
13523    pub fn pending_rename(&self) -> Option<&RenameState> {
13524        self.pending_rename.as_ref()
13525    }
13526
13527    fn format(
13528        &mut self,
13529        _: &Format,
13530        window: &mut Window,
13531        cx: &mut Context<Self>,
13532    ) -> Option<Task<Result<()>>> {
13533        let project = match &self.project {
13534            Some(project) => project.clone(),
13535            None => return None,
13536        };
13537
13538        Some(self.perform_format(
13539            project,
13540            FormatTrigger::Manual,
13541            FormatTarget::Buffers,
13542            window,
13543            cx,
13544        ))
13545    }
13546
13547    fn format_selections(
13548        &mut self,
13549        _: &FormatSelections,
13550        window: &mut Window,
13551        cx: &mut Context<Self>,
13552    ) -> Option<Task<Result<()>>> {
13553        let project = match &self.project {
13554            Some(project) => project.clone(),
13555            None => return None,
13556        };
13557
13558        let ranges = self
13559            .selections
13560            .all_adjusted(cx)
13561            .into_iter()
13562            .map(|selection| selection.range())
13563            .collect_vec();
13564
13565        Some(self.perform_format(
13566            project,
13567            FormatTrigger::Manual,
13568            FormatTarget::Ranges(ranges),
13569            window,
13570            cx,
13571        ))
13572    }
13573
13574    fn perform_format(
13575        &mut self,
13576        project: Entity<Project>,
13577        trigger: FormatTrigger,
13578        target: FormatTarget,
13579        window: &mut Window,
13580        cx: &mut Context<Self>,
13581    ) -> Task<Result<()>> {
13582        let buffer = self.buffer.clone();
13583        let (buffers, target) = match target {
13584            FormatTarget::Buffers => {
13585                let mut buffers = buffer.read(cx).all_buffers();
13586                if trigger == FormatTrigger::Save {
13587                    buffers.retain(|buffer| buffer.read(cx).is_dirty());
13588                }
13589                (buffers, LspFormatTarget::Buffers)
13590            }
13591            FormatTarget::Ranges(selection_ranges) => {
13592                let multi_buffer = buffer.read(cx);
13593                let snapshot = multi_buffer.read(cx);
13594                let mut buffers = HashSet::default();
13595                let mut buffer_id_to_ranges: BTreeMap<BufferId, Vec<Range<text::Anchor>>> =
13596                    BTreeMap::new();
13597                for selection_range in selection_ranges {
13598                    for (buffer, buffer_range, _) in
13599                        snapshot.range_to_buffer_ranges(selection_range)
13600                    {
13601                        let buffer_id = buffer.remote_id();
13602                        let start = buffer.anchor_before(buffer_range.start);
13603                        let end = buffer.anchor_after(buffer_range.end);
13604                        buffers.insert(multi_buffer.buffer(buffer_id).unwrap());
13605                        buffer_id_to_ranges
13606                            .entry(buffer_id)
13607                            .and_modify(|buffer_ranges| buffer_ranges.push(start..end))
13608                            .or_insert_with(|| vec![start..end]);
13609                    }
13610                }
13611                (buffers, LspFormatTarget::Ranges(buffer_id_to_ranges))
13612            }
13613        };
13614
13615        let mut timeout = cx.background_executor().timer(FORMAT_TIMEOUT).fuse();
13616        let format = project.update(cx, |project, cx| {
13617            project.format(buffers, target, true, trigger, cx)
13618        });
13619
13620        cx.spawn_in(window, async move |_, cx| {
13621            let transaction = futures::select_biased! {
13622                transaction = format.log_err().fuse() => transaction,
13623                () = timeout => {
13624                    log::warn!("timed out waiting for formatting");
13625                    None
13626                }
13627            };
13628
13629            buffer
13630                .update(cx, |buffer, cx| {
13631                    if let Some(transaction) = transaction {
13632                        if !buffer.is_singleton() {
13633                            buffer.push_transaction(&transaction.0, cx);
13634                        }
13635                    }
13636                    cx.notify();
13637                })
13638                .ok();
13639
13640            Ok(())
13641        })
13642    }
13643
13644    fn organize_imports(
13645        &mut self,
13646        _: &OrganizeImports,
13647        window: &mut Window,
13648        cx: &mut Context<Self>,
13649    ) -> Option<Task<Result<()>>> {
13650        let project = match &self.project {
13651            Some(project) => project.clone(),
13652            None => return None,
13653        };
13654        Some(self.perform_code_action_kind(
13655            project,
13656            CodeActionKind::SOURCE_ORGANIZE_IMPORTS,
13657            window,
13658            cx,
13659        ))
13660    }
13661
13662    fn perform_code_action_kind(
13663        &mut self,
13664        project: Entity<Project>,
13665        kind: CodeActionKind,
13666        window: &mut Window,
13667        cx: &mut Context<Self>,
13668    ) -> Task<Result<()>> {
13669        let buffer = self.buffer.clone();
13670        let buffers = buffer.read(cx).all_buffers();
13671        let mut timeout = cx.background_executor().timer(CODE_ACTION_TIMEOUT).fuse();
13672        let apply_action = project.update(cx, |project, cx| {
13673            project.apply_code_action_kind(buffers, kind, true, cx)
13674        });
13675        cx.spawn_in(window, async move |_, cx| {
13676            let transaction = futures::select_biased! {
13677                () = timeout => {
13678                    log::warn!("timed out waiting for executing code action");
13679                    None
13680                }
13681                transaction = apply_action.log_err().fuse() => transaction,
13682            };
13683            buffer
13684                .update(cx, |buffer, cx| {
13685                    // check if we need this
13686                    if let Some(transaction) = transaction {
13687                        if !buffer.is_singleton() {
13688                            buffer.push_transaction(&transaction.0, cx);
13689                        }
13690                    }
13691                    cx.notify();
13692                })
13693                .ok();
13694            Ok(())
13695        })
13696    }
13697
13698    fn restart_language_server(
13699        &mut self,
13700        _: &RestartLanguageServer,
13701        _: &mut Window,
13702        cx: &mut Context<Self>,
13703    ) {
13704        if let Some(project) = self.project.clone() {
13705            self.buffer.update(cx, |multi_buffer, cx| {
13706                project.update(cx, |project, cx| {
13707                    project.restart_language_servers_for_buffers(
13708                        multi_buffer.all_buffers().into_iter().collect(),
13709                        cx,
13710                    );
13711                });
13712            })
13713        }
13714    }
13715
13716    fn cancel_language_server_work(
13717        workspace: &mut Workspace,
13718        _: &actions::CancelLanguageServerWork,
13719        _: &mut Window,
13720        cx: &mut Context<Workspace>,
13721    ) {
13722        let project = workspace.project();
13723        let buffers = workspace
13724            .active_item(cx)
13725            .and_then(|item| item.act_as::<Editor>(cx))
13726            .map_or(HashSet::default(), |editor| {
13727                editor.read(cx).buffer.read(cx).all_buffers()
13728            });
13729        project.update(cx, |project, cx| {
13730            project.cancel_language_server_work_for_buffers(buffers, cx);
13731        });
13732    }
13733
13734    fn show_character_palette(
13735        &mut self,
13736        _: &ShowCharacterPalette,
13737        window: &mut Window,
13738        _: &mut Context<Self>,
13739    ) {
13740        window.show_character_palette();
13741    }
13742
13743    fn refresh_active_diagnostics(&mut self, cx: &mut Context<Editor>) {
13744        if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
13745            let buffer = self.buffer.read(cx).snapshot(cx);
13746            let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
13747            let primary_range_end = active_diagnostics.primary_range.end.to_offset(&buffer);
13748            let is_valid = buffer
13749                .diagnostics_in_range::<usize>(primary_range_start..primary_range_end)
13750                .any(|entry| {
13751                    entry.diagnostic.is_primary
13752                        && !entry.range.is_empty()
13753                        && entry.range.start == primary_range_start
13754                        && entry.diagnostic.message == active_diagnostics.primary_message
13755                });
13756
13757            if is_valid != active_diagnostics.is_valid {
13758                active_diagnostics.is_valid = is_valid;
13759                if is_valid {
13760                    let mut new_styles = HashMap::default();
13761                    for (block_id, diagnostic) in &active_diagnostics.blocks {
13762                        new_styles.insert(
13763                            *block_id,
13764                            diagnostic_block_renderer(diagnostic.clone(), None, true),
13765                        );
13766                    }
13767                    self.display_map.update(cx, |display_map, _cx| {
13768                        display_map.replace_blocks(new_styles);
13769                    });
13770                } else {
13771                    self.dismiss_diagnostics(cx);
13772                }
13773            }
13774        }
13775    }
13776
13777    fn activate_diagnostics(
13778        &mut self,
13779        buffer_id: BufferId,
13780        group_id: usize,
13781        window: &mut Window,
13782        cx: &mut Context<Self>,
13783    ) {
13784        self.dismiss_diagnostics(cx);
13785        let snapshot = self.snapshot(window, cx);
13786        self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
13787            let buffer = self.buffer.read(cx).snapshot(cx);
13788
13789            let mut primary_range = None;
13790            let mut primary_message = None;
13791            let diagnostic_group = buffer
13792                .diagnostic_group(buffer_id, group_id)
13793                .filter_map(|entry| {
13794                    let start = entry.range.start;
13795                    let end = entry.range.end;
13796                    if snapshot.is_line_folded(MultiBufferRow(start.row))
13797                        && (start.row == end.row
13798                            || snapshot.is_line_folded(MultiBufferRow(end.row)))
13799                    {
13800                        return None;
13801                    }
13802                    if entry.diagnostic.is_primary {
13803                        primary_range = Some(entry.range.clone());
13804                        primary_message = Some(entry.diagnostic.message.clone());
13805                    }
13806                    Some(entry)
13807                })
13808                .collect::<Vec<_>>();
13809            let primary_range = primary_range?;
13810            let primary_message = primary_message?;
13811
13812            let blocks = display_map
13813                .insert_blocks(
13814                    diagnostic_group.iter().map(|entry| {
13815                        let diagnostic = entry.diagnostic.clone();
13816                        let message_height = diagnostic.message.matches('\n').count() as u32 + 1;
13817                        BlockProperties {
13818                            style: BlockStyle::Fixed,
13819                            placement: BlockPlacement::Below(
13820                                buffer.anchor_after(entry.range.start),
13821                            ),
13822                            height: message_height,
13823                            render: diagnostic_block_renderer(diagnostic, None, true),
13824                            priority: 0,
13825                        }
13826                    }),
13827                    cx,
13828                )
13829                .into_iter()
13830                .zip(diagnostic_group.into_iter().map(|entry| entry.diagnostic))
13831                .collect();
13832
13833            Some(ActiveDiagnosticGroup {
13834                primary_range: buffer.anchor_before(primary_range.start)
13835                    ..buffer.anchor_after(primary_range.end),
13836                primary_message,
13837                group_id,
13838                blocks,
13839                is_valid: true,
13840            })
13841        });
13842    }
13843
13844    fn dismiss_diagnostics(&mut self, cx: &mut Context<Self>) {
13845        if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
13846            self.display_map.update(cx, |display_map, cx| {
13847                display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx);
13848            });
13849            cx.notify();
13850        }
13851    }
13852
13853    /// Disable inline diagnostics rendering for this editor.
13854    pub fn disable_inline_diagnostics(&mut self) {
13855        self.inline_diagnostics_enabled = false;
13856        self.inline_diagnostics_update = Task::ready(());
13857        self.inline_diagnostics.clear();
13858    }
13859
13860    pub fn inline_diagnostics_enabled(&self) -> bool {
13861        self.inline_diagnostics_enabled
13862    }
13863
13864    pub fn show_inline_diagnostics(&self) -> bool {
13865        self.show_inline_diagnostics
13866    }
13867
13868    pub fn toggle_inline_diagnostics(
13869        &mut self,
13870        _: &ToggleInlineDiagnostics,
13871        window: &mut Window,
13872        cx: &mut Context<'_, Editor>,
13873    ) {
13874        self.show_inline_diagnostics = !self.show_inline_diagnostics;
13875        self.refresh_inline_diagnostics(false, window, cx);
13876    }
13877
13878    fn refresh_inline_diagnostics(
13879        &mut self,
13880        debounce: bool,
13881        window: &mut Window,
13882        cx: &mut Context<Self>,
13883    ) {
13884        if !self.inline_diagnostics_enabled || !self.show_inline_diagnostics {
13885            self.inline_diagnostics_update = Task::ready(());
13886            self.inline_diagnostics.clear();
13887            return;
13888        }
13889
13890        let debounce_ms = ProjectSettings::get_global(cx)
13891            .diagnostics
13892            .inline
13893            .update_debounce_ms;
13894        let debounce = if debounce && debounce_ms > 0 {
13895            Some(Duration::from_millis(debounce_ms))
13896        } else {
13897            None
13898        };
13899        self.inline_diagnostics_update = cx.spawn_in(window, async move |editor, cx| {
13900            if let Some(debounce) = debounce {
13901                cx.background_executor().timer(debounce).await;
13902            }
13903            let Some(snapshot) = editor
13904                .update(cx, |editor, cx| editor.buffer().read(cx).snapshot(cx))
13905                .ok()
13906            else {
13907                return;
13908            };
13909
13910            let new_inline_diagnostics = cx
13911                .background_spawn(async move {
13912                    let mut inline_diagnostics = Vec::<(Anchor, InlineDiagnostic)>::new();
13913                    for diagnostic_entry in snapshot.diagnostics_in_range(0..snapshot.len()) {
13914                        let message = diagnostic_entry
13915                            .diagnostic
13916                            .message
13917                            .split_once('\n')
13918                            .map(|(line, _)| line)
13919                            .map(SharedString::new)
13920                            .unwrap_or_else(|| {
13921                                SharedString::from(diagnostic_entry.diagnostic.message)
13922                            });
13923                        let start_anchor = snapshot.anchor_before(diagnostic_entry.range.start);
13924                        let (Ok(i) | Err(i)) = inline_diagnostics
13925                            .binary_search_by(|(probe, _)| probe.cmp(&start_anchor, &snapshot));
13926                        inline_diagnostics.insert(
13927                            i,
13928                            (
13929                                start_anchor,
13930                                InlineDiagnostic {
13931                                    message,
13932                                    group_id: diagnostic_entry.diagnostic.group_id,
13933                                    start: diagnostic_entry.range.start.to_point(&snapshot),
13934                                    is_primary: diagnostic_entry.diagnostic.is_primary,
13935                                    severity: diagnostic_entry.diagnostic.severity,
13936                                },
13937                            ),
13938                        );
13939                    }
13940                    inline_diagnostics
13941                })
13942                .await;
13943
13944            editor
13945                .update(cx, |editor, cx| {
13946                    editor.inline_diagnostics = new_inline_diagnostics;
13947                    cx.notify();
13948                })
13949                .ok();
13950        });
13951    }
13952
13953    pub fn set_selections_from_remote(
13954        &mut self,
13955        selections: Vec<Selection<Anchor>>,
13956        pending_selection: Option<Selection<Anchor>>,
13957        window: &mut Window,
13958        cx: &mut Context<Self>,
13959    ) {
13960        let old_cursor_position = self.selections.newest_anchor().head();
13961        self.selections.change_with(cx, |s| {
13962            s.select_anchors(selections);
13963            if let Some(pending_selection) = pending_selection {
13964                s.set_pending(pending_selection, SelectMode::Character);
13965            } else {
13966                s.clear_pending();
13967            }
13968        });
13969        self.selections_did_change(false, &old_cursor_position, true, window, cx);
13970    }
13971
13972    fn push_to_selection_history(&mut self) {
13973        self.selection_history.push(SelectionHistoryEntry {
13974            selections: self.selections.disjoint_anchors(),
13975            select_next_state: self.select_next_state.clone(),
13976            select_prev_state: self.select_prev_state.clone(),
13977            add_selections_state: self.add_selections_state.clone(),
13978        });
13979    }
13980
13981    pub fn transact(
13982        &mut self,
13983        window: &mut Window,
13984        cx: &mut Context<Self>,
13985        update: impl FnOnce(&mut Self, &mut Window, &mut Context<Self>),
13986    ) -> Option<TransactionId> {
13987        self.start_transaction_at(Instant::now(), window, cx);
13988        update(self, window, cx);
13989        self.end_transaction_at(Instant::now(), cx)
13990    }
13991
13992    pub fn start_transaction_at(
13993        &mut self,
13994        now: Instant,
13995        window: &mut Window,
13996        cx: &mut Context<Self>,
13997    ) {
13998        self.end_selection(window, cx);
13999        if let Some(tx_id) = self
14000            .buffer
14001            .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx))
14002        {
14003            self.selection_history
14004                .insert_transaction(tx_id, self.selections.disjoint_anchors());
14005            cx.emit(EditorEvent::TransactionBegun {
14006                transaction_id: tx_id,
14007            })
14008        }
14009    }
14010
14011    pub fn end_transaction_at(
14012        &mut self,
14013        now: Instant,
14014        cx: &mut Context<Self>,
14015    ) -> Option<TransactionId> {
14016        if let Some(transaction_id) = self
14017            .buffer
14018            .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
14019        {
14020            if let Some((_, end_selections)) =
14021                self.selection_history.transaction_mut(transaction_id)
14022            {
14023                *end_selections = Some(self.selections.disjoint_anchors());
14024            } else {
14025                log::error!("unexpectedly ended a transaction that wasn't started by this editor");
14026            }
14027
14028            cx.emit(EditorEvent::Edited { transaction_id });
14029            Some(transaction_id)
14030        } else {
14031            None
14032        }
14033    }
14034
14035    pub fn set_mark(&mut self, _: &actions::SetMark, window: &mut Window, cx: &mut Context<Self>) {
14036        if self.selection_mark_mode {
14037            self.change_selections(None, window, cx, |s| {
14038                s.move_with(|_, sel| {
14039                    sel.collapse_to(sel.head(), SelectionGoal::None);
14040                });
14041            })
14042        }
14043        self.selection_mark_mode = true;
14044        cx.notify();
14045    }
14046
14047    pub fn swap_selection_ends(
14048        &mut self,
14049        _: &actions::SwapSelectionEnds,
14050        window: &mut Window,
14051        cx: &mut Context<Self>,
14052    ) {
14053        self.change_selections(None, window, cx, |s| {
14054            s.move_with(|_, sel| {
14055                if sel.start != sel.end {
14056                    sel.reversed = !sel.reversed
14057                }
14058            });
14059        });
14060        self.request_autoscroll(Autoscroll::newest(), cx);
14061        cx.notify();
14062    }
14063
14064    pub fn toggle_fold(
14065        &mut self,
14066        _: &actions::ToggleFold,
14067        window: &mut Window,
14068        cx: &mut Context<Self>,
14069    ) {
14070        if self.is_singleton(cx) {
14071            let selection = self.selections.newest::<Point>(cx);
14072
14073            let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
14074            let range = if selection.is_empty() {
14075                let point = selection.head().to_display_point(&display_map);
14076                let start = DisplayPoint::new(point.row(), 0).to_point(&display_map);
14077                let end = DisplayPoint::new(point.row(), display_map.line_len(point.row()))
14078                    .to_point(&display_map);
14079                start..end
14080            } else {
14081                selection.range()
14082            };
14083            if display_map.folds_in_range(range).next().is_some() {
14084                self.unfold_lines(&Default::default(), window, cx)
14085            } else {
14086                self.fold(&Default::default(), window, cx)
14087            }
14088        } else {
14089            let multi_buffer_snapshot = self.buffer.read(cx).snapshot(cx);
14090            let buffer_ids: HashSet<_> = self
14091                .selections
14092                .disjoint_anchor_ranges()
14093                .flat_map(|range| multi_buffer_snapshot.buffer_ids_for_range(range))
14094                .collect();
14095
14096            let should_unfold = buffer_ids
14097                .iter()
14098                .any(|buffer_id| self.is_buffer_folded(*buffer_id, cx));
14099
14100            for buffer_id in buffer_ids {
14101                if should_unfold {
14102                    self.unfold_buffer(buffer_id, cx);
14103                } else {
14104                    self.fold_buffer(buffer_id, cx);
14105                }
14106            }
14107        }
14108    }
14109
14110    pub fn toggle_fold_recursive(
14111        &mut self,
14112        _: &actions::ToggleFoldRecursive,
14113        window: &mut Window,
14114        cx: &mut Context<Self>,
14115    ) {
14116        let selection = self.selections.newest::<Point>(cx);
14117
14118        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
14119        let range = if selection.is_empty() {
14120            let point = selection.head().to_display_point(&display_map);
14121            let start = DisplayPoint::new(point.row(), 0).to_point(&display_map);
14122            let end = DisplayPoint::new(point.row(), display_map.line_len(point.row()))
14123                .to_point(&display_map);
14124            start..end
14125        } else {
14126            selection.range()
14127        };
14128        if display_map.folds_in_range(range).next().is_some() {
14129            self.unfold_recursive(&Default::default(), window, cx)
14130        } else {
14131            self.fold_recursive(&Default::default(), window, cx)
14132        }
14133    }
14134
14135    pub fn fold(&mut self, _: &actions::Fold, window: &mut Window, cx: &mut Context<Self>) {
14136        if self.is_singleton(cx) {
14137            let mut to_fold = Vec::new();
14138            let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
14139            let selections = self.selections.all_adjusted(cx);
14140
14141            for selection in selections {
14142                let range = selection.range().sorted();
14143                let buffer_start_row = range.start.row;
14144
14145                if range.start.row != range.end.row {
14146                    let mut found = false;
14147                    let mut row = range.start.row;
14148                    while row <= range.end.row {
14149                        if let Some(crease) = display_map.crease_for_buffer_row(MultiBufferRow(row))
14150                        {
14151                            found = true;
14152                            row = crease.range().end.row + 1;
14153                            to_fold.push(crease);
14154                        } else {
14155                            row += 1
14156                        }
14157                    }
14158                    if found {
14159                        continue;
14160                    }
14161                }
14162
14163                for row in (0..=range.start.row).rev() {
14164                    if let Some(crease) = display_map.crease_for_buffer_row(MultiBufferRow(row)) {
14165                        if crease.range().end.row >= buffer_start_row {
14166                            to_fold.push(crease);
14167                            if row <= range.start.row {
14168                                break;
14169                            }
14170                        }
14171                    }
14172                }
14173            }
14174
14175            self.fold_creases(to_fold, true, window, cx);
14176        } else {
14177            let multi_buffer_snapshot = self.buffer.read(cx).snapshot(cx);
14178            let buffer_ids = self
14179                .selections
14180                .disjoint_anchor_ranges()
14181                .flat_map(|range| multi_buffer_snapshot.buffer_ids_for_range(range))
14182                .collect::<HashSet<_>>();
14183            for buffer_id in buffer_ids {
14184                self.fold_buffer(buffer_id, cx);
14185            }
14186        }
14187    }
14188
14189    fn fold_at_level(
14190        &mut self,
14191        fold_at: &FoldAtLevel,
14192        window: &mut Window,
14193        cx: &mut Context<Self>,
14194    ) {
14195        if !self.buffer.read(cx).is_singleton() {
14196            return;
14197        }
14198
14199        let fold_at_level = fold_at.0;
14200        let snapshot = self.buffer.read(cx).snapshot(cx);
14201        let mut to_fold = Vec::new();
14202        let mut stack = vec![(0, snapshot.max_row().0, 1)];
14203
14204        while let Some((mut start_row, end_row, current_level)) = stack.pop() {
14205            while start_row < end_row {
14206                match self
14207                    .snapshot(window, cx)
14208                    .crease_for_buffer_row(MultiBufferRow(start_row))
14209                {
14210                    Some(crease) => {
14211                        let nested_start_row = crease.range().start.row + 1;
14212                        let nested_end_row = crease.range().end.row;
14213
14214                        if current_level < fold_at_level {
14215                            stack.push((nested_start_row, nested_end_row, current_level + 1));
14216                        } else if current_level == fold_at_level {
14217                            to_fold.push(crease);
14218                        }
14219
14220                        start_row = nested_end_row + 1;
14221                    }
14222                    None => start_row += 1,
14223                }
14224            }
14225        }
14226
14227        self.fold_creases(to_fold, true, window, cx);
14228    }
14229
14230    pub fn fold_all(&mut self, _: &actions::FoldAll, window: &mut Window, cx: &mut Context<Self>) {
14231        if self.buffer.read(cx).is_singleton() {
14232            let mut fold_ranges = Vec::new();
14233            let snapshot = self.buffer.read(cx).snapshot(cx);
14234
14235            for row in 0..snapshot.max_row().0 {
14236                if let Some(foldable_range) = self
14237                    .snapshot(window, cx)
14238                    .crease_for_buffer_row(MultiBufferRow(row))
14239                {
14240                    fold_ranges.push(foldable_range);
14241                }
14242            }
14243
14244            self.fold_creases(fold_ranges, true, window, cx);
14245        } else {
14246            self.toggle_fold_multiple_buffers = cx.spawn_in(window, async move |editor, cx| {
14247                editor
14248                    .update_in(cx, |editor, _, cx| {
14249                        for buffer_id in editor.buffer.read(cx).excerpt_buffer_ids() {
14250                            editor.fold_buffer(buffer_id, cx);
14251                        }
14252                    })
14253                    .ok();
14254            });
14255        }
14256    }
14257
14258    pub fn fold_function_bodies(
14259        &mut self,
14260        _: &actions::FoldFunctionBodies,
14261        window: &mut Window,
14262        cx: &mut Context<Self>,
14263    ) {
14264        let snapshot = self.buffer.read(cx).snapshot(cx);
14265
14266        let ranges = snapshot
14267            .text_object_ranges(0..snapshot.len(), TreeSitterOptions::default())
14268            .filter_map(|(range, obj)| (obj == TextObject::InsideFunction).then_some(range))
14269            .collect::<Vec<_>>();
14270
14271        let creases = ranges
14272            .into_iter()
14273            .map(|range| Crease::simple(range, self.display_map.read(cx).fold_placeholder.clone()))
14274            .collect();
14275
14276        self.fold_creases(creases, true, window, cx);
14277    }
14278
14279    pub fn fold_recursive(
14280        &mut self,
14281        _: &actions::FoldRecursive,
14282        window: &mut Window,
14283        cx: &mut Context<Self>,
14284    ) {
14285        let mut to_fold = Vec::new();
14286        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
14287        let selections = self.selections.all_adjusted(cx);
14288
14289        for selection in selections {
14290            let range = selection.range().sorted();
14291            let buffer_start_row = range.start.row;
14292
14293            if range.start.row != range.end.row {
14294                let mut found = false;
14295                for row in range.start.row..=range.end.row {
14296                    if let Some(crease) = display_map.crease_for_buffer_row(MultiBufferRow(row)) {
14297                        found = true;
14298                        to_fold.push(crease);
14299                    }
14300                }
14301                if found {
14302                    continue;
14303                }
14304            }
14305
14306            for row in (0..=range.start.row).rev() {
14307                if let Some(crease) = display_map.crease_for_buffer_row(MultiBufferRow(row)) {
14308                    if crease.range().end.row >= buffer_start_row {
14309                        to_fold.push(crease);
14310                    } else {
14311                        break;
14312                    }
14313                }
14314            }
14315        }
14316
14317        self.fold_creases(to_fold, true, window, cx);
14318    }
14319
14320    pub fn fold_at(&mut self, fold_at: &FoldAt, window: &mut Window, cx: &mut Context<Self>) {
14321        let buffer_row = fold_at.buffer_row;
14322        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
14323
14324        if let Some(crease) = display_map.crease_for_buffer_row(buffer_row) {
14325            let autoscroll = self
14326                .selections
14327                .all::<Point>(cx)
14328                .iter()
14329                .any(|selection| crease.range().overlaps(&selection.range()));
14330
14331            self.fold_creases(vec![crease], autoscroll, window, cx);
14332        }
14333    }
14334
14335    pub fn unfold_lines(&mut self, _: &UnfoldLines, _window: &mut Window, cx: &mut Context<Self>) {
14336        if self.is_singleton(cx) {
14337            let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
14338            let buffer = &display_map.buffer_snapshot;
14339            let selections = self.selections.all::<Point>(cx);
14340            let ranges = selections
14341                .iter()
14342                .map(|s| {
14343                    let range = s.display_range(&display_map).sorted();
14344                    let mut start = range.start.to_point(&display_map);
14345                    let mut end = range.end.to_point(&display_map);
14346                    start.column = 0;
14347                    end.column = buffer.line_len(MultiBufferRow(end.row));
14348                    start..end
14349                })
14350                .collect::<Vec<_>>();
14351
14352            self.unfold_ranges(&ranges, true, true, cx);
14353        } else {
14354            let multi_buffer_snapshot = self.buffer.read(cx).snapshot(cx);
14355            let buffer_ids = self
14356                .selections
14357                .disjoint_anchor_ranges()
14358                .flat_map(|range| multi_buffer_snapshot.buffer_ids_for_range(range))
14359                .collect::<HashSet<_>>();
14360            for buffer_id in buffer_ids {
14361                self.unfold_buffer(buffer_id, cx);
14362            }
14363        }
14364    }
14365
14366    pub fn unfold_recursive(
14367        &mut self,
14368        _: &UnfoldRecursive,
14369        _window: &mut Window,
14370        cx: &mut Context<Self>,
14371    ) {
14372        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
14373        let selections = self.selections.all::<Point>(cx);
14374        let ranges = selections
14375            .iter()
14376            .map(|s| {
14377                let mut range = s.display_range(&display_map).sorted();
14378                *range.start.column_mut() = 0;
14379                *range.end.column_mut() = display_map.line_len(range.end.row());
14380                let start = range.start.to_point(&display_map);
14381                let end = range.end.to_point(&display_map);
14382                start..end
14383            })
14384            .collect::<Vec<_>>();
14385
14386        self.unfold_ranges(&ranges, true, true, cx);
14387    }
14388
14389    pub fn unfold_at(
14390        &mut self,
14391        unfold_at: &UnfoldAt,
14392        _window: &mut Window,
14393        cx: &mut Context<Self>,
14394    ) {
14395        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
14396
14397        let intersection_range = Point::new(unfold_at.buffer_row.0, 0)
14398            ..Point::new(
14399                unfold_at.buffer_row.0,
14400                display_map.buffer_snapshot.line_len(unfold_at.buffer_row),
14401            );
14402
14403        let autoscroll = self
14404            .selections
14405            .all::<Point>(cx)
14406            .iter()
14407            .any(|selection| RangeExt::overlaps(&selection.range(), &intersection_range));
14408
14409        self.unfold_ranges(&[intersection_range], true, autoscroll, cx);
14410    }
14411
14412    pub fn unfold_all(
14413        &mut self,
14414        _: &actions::UnfoldAll,
14415        _window: &mut Window,
14416        cx: &mut Context<Self>,
14417    ) {
14418        if self.buffer.read(cx).is_singleton() {
14419            let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
14420            self.unfold_ranges(&[0..display_map.buffer_snapshot.len()], true, true, cx);
14421        } else {
14422            self.toggle_fold_multiple_buffers = cx.spawn(async move |editor, cx| {
14423                editor
14424                    .update(cx, |editor, cx| {
14425                        for buffer_id in editor.buffer.read(cx).excerpt_buffer_ids() {
14426                            editor.unfold_buffer(buffer_id, cx);
14427                        }
14428                    })
14429                    .ok();
14430            });
14431        }
14432    }
14433
14434    pub fn fold_selected_ranges(
14435        &mut self,
14436        _: &FoldSelectedRanges,
14437        window: &mut Window,
14438        cx: &mut Context<Self>,
14439    ) {
14440        let selections = self.selections.all::<Point>(cx);
14441        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
14442        let line_mode = self.selections.line_mode;
14443        let ranges = selections
14444            .into_iter()
14445            .map(|s| {
14446                if line_mode {
14447                    let start = Point::new(s.start.row, 0);
14448                    let end = Point::new(
14449                        s.end.row,
14450                        display_map
14451                            .buffer_snapshot
14452                            .line_len(MultiBufferRow(s.end.row)),
14453                    );
14454                    Crease::simple(start..end, display_map.fold_placeholder.clone())
14455                } else {
14456                    Crease::simple(s.start..s.end, display_map.fold_placeholder.clone())
14457                }
14458            })
14459            .collect::<Vec<_>>();
14460        self.fold_creases(ranges, true, window, cx);
14461    }
14462
14463    pub fn fold_ranges<T: ToOffset + Clone>(
14464        &mut self,
14465        ranges: Vec<Range<T>>,
14466        auto_scroll: bool,
14467        window: &mut Window,
14468        cx: &mut Context<Self>,
14469    ) {
14470        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
14471        let ranges = ranges
14472            .into_iter()
14473            .map(|r| Crease::simple(r, display_map.fold_placeholder.clone()))
14474            .collect::<Vec<_>>();
14475        self.fold_creases(ranges, auto_scroll, window, cx);
14476    }
14477
14478    pub fn fold_creases<T: ToOffset + Clone>(
14479        &mut self,
14480        creases: Vec<Crease<T>>,
14481        auto_scroll: bool,
14482        window: &mut Window,
14483        cx: &mut Context<Self>,
14484    ) {
14485        if creases.is_empty() {
14486            return;
14487        }
14488
14489        let mut buffers_affected = HashSet::default();
14490        let multi_buffer = self.buffer().read(cx);
14491        for crease in &creases {
14492            if let Some((_, buffer, _)) =
14493                multi_buffer.excerpt_containing(crease.range().start.clone(), cx)
14494            {
14495                buffers_affected.insert(buffer.read(cx).remote_id());
14496            };
14497        }
14498
14499        self.display_map.update(cx, |map, cx| map.fold(creases, cx));
14500
14501        if auto_scroll {
14502            self.request_autoscroll(Autoscroll::fit(), cx);
14503        }
14504
14505        cx.notify();
14506
14507        if let Some(active_diagnostics) = self.active_diagnostics.take() {
14508            // Clear diagnostics block when folding a range that contains it.
14509            let snapshot = self.snapshot(window, cx);
14510            if snapshot.intersects_fold(active_diagnostics.primary_range.start) {
14511                drop(snapshot);
14512                self.active_diagnostics = Some(active_diagnostics);
14513                self.dismiss_diagnostics(cx);
14514            } else {
14515                self.active_diagnostics = Some(active_diagnostics);
14516            }
14517        }
14518
14519        self.scrollbar_marker_state.dirty = true;
14520        self.folds_did_change(cx);
14521    }
14522
14523    /// Removes any folds whose ranges intersect any of the given ranges.
14524    pub fn unfold_ranges<T: ToOffset + Clone>(
14525        &mut self,
14526        ranges: &[Range<T>],
14527        inclusive: bool,
14528        auto_scroll: bool,
14529        cx: &mut Context<Self>,
14530    ) {
14531        self.remove_folds_with(ranges, auto_scroll, cx, |map, cx| {
14532            map.unfold_intersecting(ranges.iter().cloned(), inclusive, cx)
14533        });
14534        self.folds_did_change(cx);
14535    }
14536
14537    pub fn fold_buffer(&mut self, buffer_id: BufferId, cx: &mut Context<Self>) {
14538        if self.buffer().read(cx).is_singleton() || self.is_buffer_folded(buffer_id, cx) {
14539            return;
14540        }
14541        let folded_excerpts = self.buffer().read(cx).excerpts_for_buffer(buffer_id, cx);
14542        self.display_map.update(cx, |display_map, cx| {
14543            display_map.fold_buffers([buffer_id], cx)
14544        });
14545        cx.emit(EditorEvent::BufferFoldToggled {
14546            ids: folded_excerpts.iter().map(|&(id, _)| id).collect(),
14547            folded: true,
14548        });
14549        cx.notify();
14550    }
14551
14552    pub fn unfold_buffer(&mut self, buffer_id: BufferId, cx: &mut Context<Self>) {
14553        if self.buffer().read(cx).is_singleton() || !self.is_buffer_folded(buffer_id, cx) {
14554            return;
14555        }
14556        let unfolded_excerpts = self.buffer().read(cx).excerpts_for_buffer(buffer_id, cx);
14557        self.display_map.update(cx, |display_map, cx| {
14558            display_map.unfold_buffers([buffer_id], cx);
14559        });
14560        cx.emit(EditorEvent::BufferFoldToggled {
14561            ids: unfolded_excerpts.iter().map(|&(id, _)| id).collect(),
14562            folded: false,
14563        });
14564        cx.notify();
14565    }
14566
14567    pub fn is_buffer_folded(&self, buffer: BufferId, cx: &App) -> bool {
14568        self.display_map.read(cx).is_buffer_folded(buffer)
14569    }
14570
14571    pub fn folded_buffers<'a>(&self, cx: &'a App) -> &'a HashSet<BufferId> {
14572        self.display_map.read(cx).folded_buffers()
14573    }
14574
14575    /// Removes any folds with the given ranges.
14576    pub fn remove_folds_with_type<T: ToOffset + Clone>(
14577        &mut self,
14578        ranges: &[Range<T>],
14579        type_id: TypeId,
14580        auto_scroll: bool,
14581        cx: &mut Context<Self>,
14582    ) {
14583        self.remove_folds_with(ranges, auto_scroll, cx, |map, cx| {
14584            map.remove_folds_with_type(ranges.iter().cloned(), type_id, cx)
14585        });
14586        self.folds_did_change(cx);
14587    }
14588
14589    fn remove_folds_with<T: ToOffset + Clone>(
14590        &mut self,
14591        ranges: &[Range<T>],
14592        auto_scroll: bool,
14593        cx: &mut Context<Self>,
14594        update: impl FnOnce(&mut DisplayMap, &mut Context<DisplayMap>),
14595    ) {
14596        if ranges.is_empty() {
14597            return;
14598        }
14599
14600        let mut buffers_affected = HashSet::default();
14601        let multi_buffer = self.buffer().read(cx);
14602        for range in ranges {
14603            if let Some((_, buffer, _)) = multi_buffer.excerpt_containing(range.start.clone(), cx) {
14604                buffers_affected.insert(buffer.read(cx).remote_id());
14605            };
14606        }
14607
14608        self.display_map.update(cx, update);
14609
14610        if auto_scroll {
14611            self.request_autoscroll(Autoscroll::fit(), cx);
14612        }
14613
14614        cx.notify();
14615        self.scrollbar_marker_state.dirty = true;
14616        self.active_indent_guides_state.dirty = true;
14617    }
14618
14619    pub fn default_fold_placeholder(&self, cx: &App) -> FoldPlaceholder {
14620        self.display_map.read(cx).fold_placeholder.clone()
14621    }
14622
14623    pub fn set_expand_all_diff_hunks(&mut self, cx: &mut App) {
14624        self.buffer.update(cx, |buffer, cx| {
14625            buffer.set_all_diff_hunks_expanded(cx);
14626        });
14627    }
14628
14629    pub fn expand_all_diff_hunks(
14630        &mut self,
14631        _: &ExpandAllDiffHunks,
14632        _window: &mut Window,
14633        cx: &mut Context<Self>,
14634    ) {
14635        self.buffer.update(cx, |buffer, cx| {
14636            buffer.expand_diff_hunks(vec![Anchor::min()..Anchor::max()], cx)
14637        });
14638    }
14639
14640    pub fn toggle_selected_diff_hunks(
14641        &mut self,
14642        _: &ToggleSelectedDiffHunks,
14643        _window: &mut Window,
14644        cx: &mut Context<Self>,
14645    ) {
14646        let ranges: Vec<_> = self.selections.disjoint.iter().map(|s| s.range()).collect();
14647        self.toggle_diff_hunks_in_ranges(ranges, cx);
14648    }
14649
14650    pub fn diff_hunks_in_ranges<'a>(
14651        &'a self,
14652        ranges: &'a [Range<Anchor>],
14653        buffer: &'a MultiBufferSnapshot,
14654    ) -> impl 'a + Iterator<Item = MultiBufferDiffHunk> {
14655        ranges.iter().flat_map(move |range| {
14656            let end_excerpt_id = range.end.excerpt_id;
14657            let range = range.to_point(buffer);
14658            let mut peek_end = range.end;
14659            if range.end.row < buffer.max_row().0 {
14660                peek_end = Point::new(range.end.row + 1, 0);
14661            }
14662            buffer
14663                .diff_hunks_in_range(range.start..peek_end)
14664                .filter(move |hunk| hunk.excerpt_id.cmp(&end_excerpt_id, buffer).is_le())
14665        })
14666    }
14667
14668    pub fn has_stageable_diff_hunks_in_ranges(
14669        &self,
14670        ranges: &[Range<Anchor>],
14671        snapshot: &MultiBufferSnapshot,
14672    ) -> bool {
14673        let mut hunks = self.diff_hunks_in_ranges(ranges, &snapshot);
14674        hunks.any(|hunk| hunk.status().has_secondary_hunk())
14675    }
14676
14677    pub fn toggle_staged_selected_diff_hunks(
14678        &mut self,
14679        _: &::git::ToggleStaged,
14680        _: &mut Window,
14681        cx: &mut Context<Self>,
14682    ) {
14683        let snapshot = self.buffer.read(cx).snapshot(cx);
14684        let ranges: Vec<_> = self.selections.disjoint.iter().map(|s| s.range()).collect();
14685        let stage = self.has_stageable_diff_hunks_in_ranges(&ranges, &snapshot);
14686        self.stage_or_unstage_diff_hunks(stage, ranges, cx);
14687    }
14688
14689    pub fn stage_and_next(
14690        &mut self,
14691        _: &::git::StageAndNext,
14692        window: &mut Window,
14693        cx: &mut Context<Self>,
14694    ) {
14695        self.do_stage_or_unstage_and_next(true, window, cx);
14696    }
14697
14698    pub fn unstage_and_next(
14699        &mut self,
14700        _: &::git::UnstageAndNext,
14701        window: &mut Window,
14702        cx: &mut Context<Self>,
14703    ) {
14704        self.do_stage_or_unstage_and_next(false, window, cx);
14705    }
14706
14707    pub fn stage_or_unstage_diff_hunks(
14708        &mut self,
14709        stage: bool,
14710        ranges: Vec<Range<Anchor>>,
14711        cx: &mut Context<Self>,
14712    ) {
14713        let task = self.save_buffers_for_ranges_if_needed(&ranges, cx);
14714        cx.spawn(async move |this, cx| {
14715            task.await?;
14716            this.update(cx, |this, cx| {
14717                let snapshot = this.buffer.read(cx).snapshot(cx);
14718                let chunk_by = this
14719                    .diff_hunks_in_ranges(&ranges, &snapshot)
14720                    .chunk_by(|hunk| hunk.buffer_id);
14721                for (buffer_id, hunks) in &chunk_by {
14722                    this.do_stage_or_unstage(stage, buffer_id, hunks, cx);
14723                }
14724            })
14725        })
14726        .detach_and_log_err(cx);
14727    }
14728
14729    fn save_buffers_for_ranges_if_needed(
14730        &mut self,
14731        ranges: &[Range<Anchor>],
14732        cx: &mut Context<'_, Editor>,
14733    ) -> Task<Result<()>> {
14734        let multibuffer = self.buffer.read(cx);
14735        let snapshot = multibuffer.read(cx);
14736        let buffer_ids: HashSet<_> = ranges
14737            .iter()
14738            .flat_map(|range| snapshot.buffer_ids_for_range(range.clone()))
14739            .collect();
14740        drop(snapshot);
14741
14742        let mut buffers = HashSet::default();
14743        for buffer_id in buffer_ids {
14744            if let Some(buffer_entity) = multibuffer.buffer(buffer_id) {
14745                let buffer = buffer_entity.read(cx);
14746                if buffer.file().is_some_and(|file| file.disk_state().exists()) && buffer.is_dirty()
14747                {
14748                    buffers.insert(buffer_entity);
14749                }
14750            }
14751        }
14752
14753        if let Some(project) = &self.project {
14754            project.update(cx, |project, cx| project.save_buffers(buffers, cx))
14755        } else {
14756            Task::ready(Ok(()))
14757        }
14758    }
14759
14760    fn do_stage_or_unstage_and_next(
14761        &mut self,
14762        stage: bool,
14763        window: &mut Window,
14764        cx: &mut Context<Self>,
14765    ) {
14766        let ranges = self.selections.disjoint_anchor_ranges().collect::<Vec<_>>();
14767
14768        if ranges.iter().any(|range| range.start != range.end) {
14769            self.stage_or_unstage_diff_hunks(stage, ranges, cx);
14770            return;
14771        }
14772
14773        self.stage_or_unstage_diff_hunks(stage, ranges, cx);
14774        let snapshot = self.snapshot(window, cx);
14775        let position = self.selections.newest::<Point>(cx).head();
14776        let mut row = snapshot
14777            .buffer_snapshot
14778            .diff_hunks_in_range(position..snapshot.buffer_snapshot.max_point())
14779            .find(|hunk| hunk.row_range.start.0 > position.row)
14780            .map(|hunk| hunk.row_range.start);
14781
14782        let all_diff_hunks_expanded = self.buffer().read(cx).all_diff_hunks_expanded();
14783        // Outside of the project diff editor, wrap around to the beginning.
14784        if !all_diff_hunks_expanded {
14785            row = row.or_else(|| {
14786                snapshot
14787                    .buffer_snapshot
14788                    .diff_hunks_in_range(Point::zero()..position)
14789                    .find(|hunk| hunk.row_range.end.0 < position.row)
14790                    .map(|hunk| hunk.row_range.start)
14791            });
14792        }
14793
14794        if let Some(row) = row {
14795            let destination = Point::new(row.0, 0);
14796            let autoscroll = Autoscroll::center();
14797
14798            self.unfold_ranges(&[destination..destination], false, false, cx);
14799            self.change_selections(Some(autoscroll), window, cx, |s| {
14800                s.select_ranges([destination..destination]);
14801            });
14802        }
14803    }
14804
14805    fn do_stage_or_unstage(
14806        &self,
14807        stage: bool,
14808        buffer_id: BufferId,
14809        hunks: impl Iterator<Item = MultiBufferDiffHunk>,
14810        cx: &mut App,
14811    ) -> Option<()> {
14812        let project = self.project.as_ref()?;
14813        let buffer = project.read(cx).buffer_for_id(buffer_id, cx)?;
14814        let diff = self.buffer.read(cx).diff_for(buffer_id)?;
14815        let buffer_snapshot = buffer.read(cx).snapshot();
14816        let file_exists = buffer_snapshot
14817            .file()
14818            .is_some_and(|file| file.disk_state().exists());
14819        diff.update(cx, |diff, cx| {
14820            diff.stage_or_unstage_hunks(
14821                stage,
14822                &hunks
14823                    .map(|hunk| buffer_diff::DiffHunk {
14824                        buffer_range: hunk.buffer_range,
14825                        diff_base_byte_range: hunk.diff_base_byte_range,
14826                        secondary_status: hunk.secondary_status,
14827                        range: Point::zero()..Point::zero(), // unused
14828                    })
14829                    .collect::<Vec<_>>(),
14830                &buffer_snapshot,
14831                file_exists,
14832                cx,
14833            )
14834        });
14835        None
14836    }
14837
14838    pub fn expand_selected_diff_hunks(&mut self, cx: &mut Context<Self>) {
14839        let ranges: Vec<_> = self.selections.disjoint.iter().map(|s| s.range()).collect();
14840        self.buffer
14841            .update(cx, |buffer, cx| buffer.expand_diff_hunks(ranges, cx))
14842    }
14843
14844    pub fn clear_expanded_diff_hunks(&mut self, cx: &mut Context<Self>) -> bool {
14845        self.buffer.update(cx, |buffer, cx| {
14846            let ranges = vec![Anchor::min()..Anchor::max()];
14847            if !buffer.all_diff_hunks_expanded()
14848                && buffer.has_expanded_diff_hunks_in_ranges(&ranges, cx)
14849            {
14850                buffer.collapse_diff_hunks(ranges, cx);
14851                true
14852            } else {
14853                false
14854            }
14855        })
14856    }
14857
14858    fn toggle_diff_hunks_in_ranges(
14859        &mut self,
14860        ranges: Vec<Range<Anchor>>,
14861        cx: &mut Context<'_, Editor>,
14862    ) {
14863        self.buffer.update(cx, |buffer, cx| {
14864            let expand = !buffer.has_expanded_diff_hunks_in_ranges(&ranges, cx);
14865            buffer.expand_or_collapse_diff_hunks(ranges, expand, cx);
14866        })
14867    }
14868
14869    fn toggle_single_diff_hunk(&mut self, range: Range<Anchor>, cx: &mut Context<Self>) {
14870        self.buffer.update(cx, |buffer, cx| {
14871            let snapshot = buffer.snapshot(cx);
14872            let excerpt_id = range.end.excerpt_id;
14873            let point_range = range.to_point(&snapshot);
14874            let expand = !buffer.single_hunk_is_expanded(range, cx);
14875            buffer.expand_or_collapse_diff_hunks_inner([(point_range, excerpt_id)], expand, cx);
14876        })
14877    }
14878
14879    pub(crate) fn apply_all_diff_hunks(
14880        &mut self,
14881        _: &ApplyAllDiffHunks,
14882        window: &mut Window,
14883        cx: &mut Context<Self>,
14884    ) {
14885        let buffers = self.buffer.read(cx).all_buffers();
14886        for branch_buffer in buffers {
14887            branch_buffer.update(cx, |branch_buffer, cx| {
14888                branch_buffer.merge_into_base(Vec::new(), cx);
14889            });
14890        }
14891
14892        if let Some(project) = self.project.clone() {
14893            self.save(true, project, window, cx).detach_and_log_err(cx);
14894        }
14895    }
14896
14897    pub(crate) fn apply_selected_diff_hunks(
14898        &mut self,
14899        _: &ApplyDiffHunk,
14900        window: &mut Window,
14901        cx: &mut Context<Self>,
14902    ) {
14903        let snapshot = self.snapshot(window, cx);
14904        let hunks = snapshot.hunks_for_ranges(self.selections.ranges(cx));
14905        let mut ranges_by_buffer = HashMap::default();
14906        self.transact(window, cx, |editor, _window, cx| {
14907            for hunk in hunks {
14908                if let Some(buffer) = editor.buffer.read(cx).buffer(hunk.buffer_id) {
14909                    ranges_by_buffer
14910                        .entry(buffer.clone())
14911                        .or_insert_with(Vec::new)
14912                        .push(hunk.buffer_range.to_offset(buffer.read(cx)));
14913                }
14914            }
14915
14916            for (buffer, ranges) in ranges_by_buffer {
14917                buffer.update(cx, |buffer, cx| {
14918                    buffer.merge_into_base(ranges, cx);
14919                });
14920            }
14921        });
14922
14923        if let Some(project) = self.project.clone() {
14924            self.save(true, project, window, cx).detach_and_log_err(cx);
14925        }
14926    }
14927
14928    pub fn set_gutter_hovered(&mut self, hovered: bool, cx: &mut Context<Self>) {
14929        if hovered != self.gutter_hovered {
14930            self.gutter_hovered = hovered;
14931            cx.notify();
14932        }
14933    }
14934
14935    pub fn insert_blocks(
14936        &mut self,
14937        blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
14938        autoscroll: Option<Autoscroll>,
14939        cx: &mut Context<Self>,
14940    ) -> Vec<CustomBlockId> {
14941        let blocks = self
14942            .display_map
14943            .update(cx, |display_map, cx| display_map.insert_blocks(blocks, cx));
14944        if let Some(autoscroll) = autoscroll {
14945            self.request_autoscroll(autoscroll, cx);
14946        }
14947        cx.notify();
14948        blocks
14949    }
14950
14951    pub fn resize_blocks(
14952        &mut self,
14953        heights: HashMap<CustomBlockId, u32>,
14954        autoscroll: Option<Autoscroll>,
14955        cx: &mut Context<Self>,
14956    ) {
14957        self.display_map
14958            .update(cx, |display_map, cx| display_map.resize_blocks(heights, cx));
14959        if let Some(autoscroll) = autoscroll {
14960            self.request_autoscroll(autoscroll, cx);
14961        }
14962        cx.notify();
14963    }
14964
14965    pub fn replace_blocks(
14966        &mut self,
14967        renderers: HashMap<CustomBlockId, RenderBlock>,
14968        autoscroll: Option<Autoscroll>,
14969        cx: &mut Context<Self>,
14970    ) {
14971        self.display_map
14972            .update(cx, |display_map, _cx| display_map.replace_blocks(renderers));
14973        if let Some(autoscroll) = autoscroll {
14974            self.request_autoscroll(autoscroll, cx);
14975        }
14976        cx.notify();
14977    }
14978
14979    pub fn remove_blocks(
14980        &mut self,
14981        block_ids: HashSet<CustomBlockId>,
14982        autoscroll: Option<Autoscroll>,
14983        cx: &mut Context<Self>,
14984    ) {
14985        self.display_map.update(cx, |display_map, cx| {
14986            display_map.remove_blocks(block_ids, cx)
14987        });
14988        if let Some(autoscroll) = autoscroll {
14989            self.request_autoscroll(autoscroll, cx);
14990        }
14991        cx.notify();
14992    }
14993
14994    pub fn row_for_block(
14995        &self,
14996        block_id: CustomBlockId,
14997        cx: &mut Context<Self>,
14998    ) -> Option<DisplayRow> {
14999        self.display_map
15000            .update(cx, |map, cx| map.row_for_block(block_id, cx))
15001    }
15002
15003    pub(crate) fn set_focused_block(&mut self, focused_block: FocusedBlock) {
15004        self.focused_block = Some(focused_block);
15005    }
15006
15007    pub(crate) fn take_focused_block(&mut self) -> Option<FocusedBlock> {
15008        self.focused_block.take()
15009    }
15010
15011    pub fn insert_creases(
15012        &mut self,
15013        creases: impl IntoIterator<Item = Crease<Anchor>>,
15014        cx: &mut Context<Self>,
15015    ) -> Vec<CreaseId> {
15016        self.display_map
15017            .update(cx, |map, cx| map.insert_creases(creases, cx))
15018    }
15019
15020    pub fn remove_creases(
15021        &mut self,
15022        ids: impl IntoIterator<Item = CreaseId>,
15023        cx: &mut Context<Self>,
15024    ) {
15025        self.display_map
15026            .update(cx, |map, cx| map.remove_creases(ids, cx));
15027    }
15028
15029    pub fn longest_row(&self, cx: &mut App) -> DisplayRow {
15030        self.display_map
15031            .update(cx, |map, cx| map.snapshot(cx))
15032            .longest_row()
15033    }
15034
15035    pub fn max_point(&self, cx: &mut App) -> DisplayPoint {
15036        self.display_map
15037            .update(cx, |map, cx| map.snapshot(cx))
15038            .max_point()
15039    }
15040
15041    pub fn text(&self, cx: &App) -> String {
15042        self.buffer.read(cx).read(cx).text()
15043    }
15044
15045    pub fn is_empty(&self, cx: &App) -> bool {
15046        self.buffer.read(cx).read(cx).is_empty()
15047    }
15048
15049    pub fn text_option(&self, cx: &App) -> Option<String> {
15050        let text = self.text(cx);
15051        let text = text.trim();
15052
15053        if text.is_empty() {
15054            return None;
15055        }
15056
15057        Some(text.to_string())
15058    }
15059
15060    pub fn set_text(
15061        &mut self,
15062        text: impl Into<Arc<str>>,
15063        window: &mut Window,
15064        cx: &mut Context<Self>,
15065    ) {
15066        self.transact(window, cx, |this, _, cx| {
15067            this.buffer
15068                .read(cx)
15069                .as_singleton()
15070                .expect("you can only call set_text on editors for singleton buffers")
15071                .update(cx, |buffer, cx| buffer.set_text(text, cx));
15072        });
15073    }
15074
15075    pub fn display_text(&self, cx: &mut App) -> String {
15076        self.display_map
15077            .update(cx, |map, cx| map.snapshot(cx))
15078            .text()
15079    }
15080
15081    pub fn wrap_guides(&self, cx: &App) -> SmallVec<[(usize, bool); 2]> {
15082        let mut wrap_guides = smallvec::smallvec![];
15083
15084        if self.show_wrap_guides == Some(false) {
15085            return wrap_guides;
15086        }
15087
15088        let settings = self.buffer.read(cx).language_settings(cx);
15089        if settings.show_wrap_guides {
15090            match self.soft_wrap_mode(cx) {
15091                SoftWrap::Column(soft_wrap) => {
15092                    wrap_guides.push((soft_wrap as usize, true));
15093                }
15094                SoftWrap::Bounded(soft_wrap) => {
15095                    wrap_guides.push((soft_wrap as usize, true));
15096                }
15097                SoftWrap::GitDiff | SoftWrap::None | SoftWrap::EditorWidth => {}
15098            }
15099            wrap_guides.extend(settings.wrap_guides.iter().map(|guide| (*guide, false)))
15100        }
15101
15102        wrap_guides
15103    }
15104
15105    pub fn soft_wrap_mode(&self, cx: &App) -> SoftWrap {
15106        let settings = self.buffer.read(cx).language_settings(cx);
15107        let mode = self.soft_wrap_mode_override.unwrap_or(settings.soft_wrap);
15108        match mode {
15109            language_settings::SoftWrap::PreferLine | language_settings::SoftWrap::None => {
15110                SoftWrap::None
15111            }
15112            language_settings::SoftWrap::EditorWidth => SoftWrap::EditorWidth,
15113            language_settings::SoftWrap::PreferredLineLength => {
15114                SoftWrap::Column(settings.preferred_line_length)
15115            }
15116            language_settings::SoftWrap::Bounded => {
15117                SoftWrap::Bounded(settings.preferred_line_length)
15118            }
15119        }
15120    }
15121
15122    pub fn set_soft_wrap_mode(
15123        &mut self,
15124        mode: language_settings::SoftWrap,
15125
15126        cx: &mut Context<Self>,
15127    ) {
15128        self.soft_wrap_mode_override = Some(mode);
15129        cx.notify();
15130    }
15131
15132    pub fn set_hard_wrap(&mut self, hard_wrap: Option<usize>, cx: &mut Context<Self>) {
15133        self.hard_wrap = hard_wrap;
15134        cx.notify();
15135    }
15136
15137    pub fn set_text_style_refinement(&mut self, style: TextStyleRefinement) {
15138        self.text_style_refinement = Some(style);
15139    }
15140
15141    /// called by the Element so we know what style we were most recently rendered with.
15142    pub(crate) fn set_style(
15143        &mut self,
15144        style: EditorStyle,
15145        window: &mut Window,
15146        cx: &mut Context<Self>,
15147    ) {
15148        let rem_size = window.rem_size();
15149        self.display_map.update(cx, |map, cx| {
15150            map.set_font(
15151                style.text.font(),
15152                style.text.font_size.to_pixels(rem_size),
15153                cx,
15154            )
15155        });
15156        self.style = Some(style);
15157    }
15158
15159    pub fn style(&self) -> Option<&EditorStyle> {
15160        self.style.as_ref()
15161    }
15162
15163    // Called by the element. This method is not designed to be called outside of the editor
15164    // element's layout code because it does not notify when rewrapping is computed synchronously.
15165    pub(crate) fn set_wrap_width(&self, width: Option<Pixels>, cx: &mut App) -> bool {
15166        self.display_map
15167            .update(cx, |map, cx| map.set_wrap_width(width, cx))
15168    }
15169
15170    pub fn set_soft_wrap(&mut self) {
15171        self.soft_wrap_mode_override = Some(language_settings::SoftWrap::EditorWidth)
15172    }
15173
15174    pub fn toggle_soft_wrap(&mut self, _: &ToggleSoftWrap, _: &mut Window, cx: &mut Context<Self>) {
15175        if self.soft_wrap_mode_override.is_some() {
15176            self.soft_wrap_mode_override.take();
15177        } else {
15178            let soft_wrap = match self.soft_wrap_mode(cx) {
15179                SoftWrap::GitDiff => return,
15180                SoftWrap::None => language_settings::SoftWrap::EditorWidth,
15181                SoftWrap::EditorWidth | SoftWrap::Column(_) | SoftWrap::Bounded(_) => {
15182                    language_settings::SoftWrap::None
15183                }
15184            };
15185            self.soft_wrap_mode_override = Some(soft_wrap);
15186        }
15187        cx.notify();
15188    }
15189
15190    pub fn toggle_tab_bar(&mut self, _: &ToggleTabBar, _: &mut Window, cx: &mut Context<Self>) {
15191        let Some(workspace) = self.workspace() else {
15192            return;
15193        };
15194        let fs = workspace.read(cx).app_state().fs.clone();
15195        let current_show = TabBarSettings::get_global(cx).show;
15196        update_settings_file::<TabBarSettings>(fs, cx, move |setting, _| {
15197            setting.show = Some(!current_show);
15198        });
15199    }
15200
15201    pub fn toggle_indent_guides(
15202        &mut self,
15203        _: &ToggleIndentGuides,
15204        _: &mut Window,
15205        cx: &mut Context<Self>,
15206    ) {
15207        let currently_enabled = self.should_show_indent_guides().unwrap_or_else(|| {
15208            self.buffer
15209                .read(cx)
15210                .language_settings(cx)
15211                .indent_guides
15212                .enabled
15213        });
15214        self.show_indent_guides = Some(!currently_enabled);
15215        cx.notify();
15216    }
15217
15218    fn should_show_indent_guides(&self) -> Option<bool> {
15219        self.show_indent_guides
15220    }
15221
15222    pub fn toggle_line_numbers(
15223        &mut self,
15224        _: &ToggleLineNumbers,
15225        _: &mut Window,
15226        cx: &mut Context<Self>,
15227    ) {
15228        let mut editor_settings = EditorSettings::get_global(cx).clone();
15229        editor_settings.gutter.line_numbers = !editor_settings.gutter.line_numbers;
15230        EditorSettings::override_global(editor_settings, cx);
15231    }
15232
15233    pub fn line_numbers_enabled(&self, cx: &App) -> bool {
15234        if let Some(show_line_numbers) = self.show_line_numbers {
15235            return show_line_numbers;
15236        }
15237        EditorSettings::get_global(cx).gutter.line_numbers
15238    }
15239
15240    pub fn should_use_relative_line_numbers(&self, cx: &mut App) -> bool {
15241        self.use_relative_line_numbers
15242            .unwrap_or(EditorSettings::get_global(cx).relative_line_numbers)
15243    }
15244
15245    pub fn toggle_relative_line_numbers(
15246        &mut self,
15247        _: &ToggleRelativeLineNumbers,
15248        _: &mut Window,
15249        cx: &mut Context<Self>,
15250    ) {
15251        let is_relative = self.should_use_relative_line_numbers(cx);
15252        self.set_relative_line_number(Some(!is_relative), cx)
15253    }
15254
15255    pub fn set_relative_line_number(&mut self, is_relative: Option<bool>, cx: &mut Context<Self>) {
15256        self.use_relative_line_numbers = is_relative;
15257        cx.notify();
15258    }
15259
15260    pub fn set_show_gutter(&mut self, show_gutter: bool, cx: &mut Context<Self>) {
15261        self.show_gutter = show_gutter;
15262        cx.notify();
15263    }
15264
15265    pub fn set_show_scrollbars(&mut self, show_scrollbars: bool, cx: &mut Context<Self>) {
15266        self.show_scrollbars = show_scrollbars;
15267        cx.notify();
15268    }
15269
15270    pub fn set_show_line_numbers(&mut self, show_line_numbers: bool, cx: &mut Context<Self>) {
15271        self.show_line_numbers = Some(show_line_numbers);
15272        cx.notify();
15273    }
15274
15275    pub fn set_show_git_diff_gutter(&mut self, show_git_diff_gutter: bool, cx: &mut Context<Self>) {
15276        self.show_git_diff_gutter = Some(show_git_diff_gutter);
15277        cx.notify();
15278    }
15279
15280    pub fn set_show_code_actions(&mut self, show_code_actions: bool, cx: &mut Context<Self>) {
15281        self.show_code_actions = Some(show_code_actions);
15282        cx.notify();
15283    }
15284
15285    pub fn set_show_runnables(&mut self, show_runnables: bool, cx: &mut Context<Self>) {
15286        self.show_runnables = Some(show_runnables);
15287        cx.notify();
15288    }
15289
15290    pub fn set_show_breakpoints(&mut self, show_breakpoints: bool, cx: &mut Context<Self>) {
15291        self.show_breakpoints = Some(show_breakpoints);
15292        cx.notify();
15293    }
15294
15295    pub fn set_masked(&mut self, masked: bool, cx: &mut Context<Self>) {
15296        if self.display_map.read(cx).masked != masked {
15297            self.display_map.update(cx, |map, _| map.masked = masked);
15298        }
15299        cx.notify()
15300    }
15301
15302    pub fn set_show_wrap_guides(&mut self, show_wrap_guides: bool, cx: &mut Context<Self>) {
15303        self.show_wrap_guides = Some(show_wrap_guides);
15304        cx.notify();
15305    }
15306
15307    pub fn set_show_indent_guides(&mut self, show_indent_guides: bool, cx: &mut Context<Self>) {
15308        self.show_indent_guides = Some(show_indent_guides);
15309        cx.notify();
15310    }
15311
15312    pub fn working_directory(&self, cx: &App) -> Option<PathBuf> {
15313        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
15314            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
15315                if let Some(dir) = file.abs_path(cx).parent() {
15316                    return Some(dir.to_owned());
15317                }
15318            }
15319
15320            if let Some(project_path) = buffer.read(cx).project_path(cx) {
15321                return Some(project_path.path.to_path_buf());
15322            }
15323        }
15324
15325        None
15326    }
15327
15328    fn target_file<'a>(&self, cx: &'a App) -> Option<&'a dyn language::LocalFile> {
15329        self.active_excerpt(cx)?
15330            .1
15331            .read(cx)
15332            .file()
15333            .and_then(|f| f.as_local())
15334    }
15335
15336    pub fn target_file_abs_path(&self, cx: &mut Context<Self>) -> Option<PathBuf> {
15337        self.active_excerpt(cx).and_then(|(_, buffer, _)| {
15338            let buffer = buffer.read(cx);
15339            if let Some(project_path) = buffer.project_path(cx) {
15340                let project = self.project.as_ref()?.read(cx);
15341                project.absolute_path(&project_path, cx)
15342            } else {
15343                buffer
15344                    .file()
15345                    .and_then(|file| file.as_local().map(|file| file.abs_path(cx)))
15346            }
15347        })
15348    }
15349
15350    fn target_file_path(&self, cx: &mut Context<Self>) -> Option<PathBuf> {
15351        self.active_excerpt(cx).and_then(|(_, buffer, _)| {
15352            let project_path = buffer.read(cx).project_path(cx)?;
15353            let project = self.project.as_ref()?.read(cx);
15354            let entry = project.entry_for_path(&project_path, cx)?;
15355            let path = entry.path.to_path_buf();
15356            Some(path)
15357        })
15358    }
15359
15360    pub fn reveal_in_finder(
15361        &mut self,
15362        _: &RevealInFileManager,
15363        _window: &mut Window,
15364        cx: &mut Context<Self>,
15365    ) {
15366        if let Some(target) = self.target_file(cx) {
15367            cx.reveal_path(&target.abs_path(cx));
15368        }
15369    }
15370
15371    pub fn copy_path(
15372        &mut self,
15373        _: &zed_actions::workspace::CopyPath,
15374        _window: &mut Window,
15375        cx: &mut Context<Self>,
15376    ) {
15377        if let Some(path) = self.target_file_abs_path(cx) {
15378            if let Some(path) = path.to_str() {
15379                cx.write_to_clipboard(ClipboardItem::new_string(path.to_string()));
15380            }
15381        }
15382    }
15383
15384    pub fn copy_relative_path(
15385        &mut self,
15386        _: &zed_actions::workspace::CopyRelativePath,
15387        _window: &mut Window,
15388        cx: &mut Context<Self>,
15389    ) {
15390        if let Some(path) = self.target_file_path(cx) {
15391            if let Some(path) = path.to_str() {
15392                cx.write_to_clipboard(ClipboardItem::new_string(path.to_string()));
15393            }
15394        }
15395    }
15396
15397    pub fn project_path(&self, cx: &mut Context<Self>) -> Option<ProjectPath> {
15398        if let Some(buffer) = self.buffer.read(cx).as_singleton() {
15399            buffer.read_with(cx, |buffer, cx| buffer.project_path(cx))
15400        } else {
15401            None
15402        }
15403    }
15404
15405    pub fn go_to_active_debug_line(&mut self, window: &mut Window, cx: &mut Context<Self>) {
15406        let _ = maybe!({
15407            let breakpoint_store = self.breakpoint_store.as_ref()?;
15408
15409            let Some((_, _, active_position)) =
15410                breakpoint_store.read(cx).active_position().cloned()
15411            else {
15412                self.clear_row_highlights::<DebugCurrentRowHighlight>();
15413                return None;
15414            };
15415
15416            let snapshot = self
15417                .project
15418                .as_ref()?
15419                .read(cx)
15420                .buffer_for_id(active_position.buffer_id?, cx)?
15421                .read(cx)
15422                .snapshot();
15423
15424            for (id, ExcerptRange { context, .. }) in self
15425                .buffer
15426                .read(cx)
15427                .excerpts_for_buffer(active_position.buffer_id?, cx)
15428            {
15429                if context.start.cmp(&active_position, &snapshot).is_ge()
15430                    || context.end.cmp(&active_position, &snapshot).is_lt()
15431                {
15432                    continue;
15433                }
15434                let snapshot = self.buffer.read(cx).snapshot(cx);
15435                let multibuffer_anchor = snapshot.anchor_in_excerpt(id, active_position)?;
15436
15437                self.clear_row_highlights::<DebugCurrentRowHighlight>();
15438                self.go_to_line::<DebugCurrentRowHighlight>(
15439                    multibuffer_anchor,
15440                    Some(cx.theme().colors().editor_debugger_active_line_background),
15441                    window,
15442                    cx,
15443                );
15444
15445                cx.notify();
15446            }
15447
15448            Some(())
15449        });
15450    }
15451
15452    pub fn copy_file_name_without_extension(
15453        &mut self,
15454        _: &CopyFileNameWithoutExtension,
15455        _: &mut Window,
15456        cx: &mut Context<Self>,
15457    ) {
15458        if let Some(file) = self.target_file(cx) {
15459            if let Some(file_stem) = file.path().file_stem() {
15460                if let Some(name) = file_stem.to_str() {
15461                    cx.write_to_clipboard(ClipboardItem::new_string(name.to_string()));
15462                }
15463            }
15464        }
15465    }
15466
15467    pub fn copy_file_name(&mut self, _: &CopyFileName, _: &mut Window, cx: &mut Context<Self>) {
15468        if let Some(file) = self.target_file(cx) {
15469            if let Some(file_name) = file.path().file_name() {
15470                if let Some(name) = file_name.to_str() {
15471                    cx.write_to_clipboard(ClipboardItem::new_string(name.to_string()));
15472                }
15473            }
15474        }
15475    }
15476
15477    pub fn toggle_git_blame(
15478        &mut self,
15479        _: &::git::Blame,
15480        window: &mut Window,
15481        cx: &mut Context<Self>,
15482    ) {
15483        self.show_git_blame_gutter = !self.show_git_blame_gutter;
15484
15485        if self.show_git_blame_gutter && !self.has_blame_entries(cx) {
15486            self.start_git_blame(true, window, cx);
15487        }
15488
15489        cx.notify();
15490    }
15491
15492    pub fn toggle_git_blame_inline(
15493        &mut self,
15494        _: &ToggleGitBlameInline,
15495        window: &mut Window,
15496        cx: &mut Context<Self>,
15497    ) {
15498        self.toggle_git_blame_inline_internal(true, window, cx);
15499        cx.notify();
15500    }
15501
15502    pub fn git_blame_inline_enabled(&self) -> bool {
15503        self.git_blame_inline_enabled
15504    }
15505
15506    pub fn toggle_selection_menu(
15507        &mut self,
15508        _: &ToggleSelectionMenu,
15509        _: &mut Window,
15510        cx: &mut Context<Self>,
15511    ) {
15512        self.show_selection_menu = self
15513            .show_selection_menu
15514            .map(|show_selections_menu| !show_selections_menu)
15515            .or_else(|| Some(!EditorSettings::get_global(cx).toolbar.selections_menu));
15516
15517        cx.notify();
15518    }
15519
15520    pub fn selection_menu_enabled(&self, cx: &App) -> bool {
15521        self.show_selection_menu
15522            .unwrap_or_else(|| EditorSettings::get_global(cx).toolbar.selections_menu)
15523    }
15524
15525    fn start_git_blame(
15526        &mut self,
15527        user_triggered: bool,
15528        window: &mut Window,
15529        cx: &mut Context<Self>,
15530    ) {
15531        if let Some(project) = self.project.as_ref() {
15532            let Some(buffer) = self.buffer().read(cx).as_singleton() else {
15533                return;
15534            };
15535
15536            if buffer.read(cx).file().is_none() {
15537                return;
15538            }
15539
15540            let focused = self.focus_handle(cx).contains_focused(window, cx);
15541
15542            let project = project.clone();
15543            let blame = cx.new(|cx| GitBlame::new(buffer, project, user_triggered, focused, cx));
15544            self.blame_subscription =
15545                Some(cx.observe_in(&blame, window, |_, _, _, cx| cx.notify()));
15546            self.blame = Some(blame);
15547        }
15548    }
15549
15550    fn toggle_git_blame_inline_internal(
15551        &mut self,
15552        user_triggered: bool,
15553        window: &mut Window,
15554        cx: &mut Context<Self>,
15555    ) {
15556        if self.git_blame_inline_enabled {
15557            self.git_blame_inline_enabled = false;
15558            self.show_git_blame_inline = false;
15559            self.show_git_blame_inline_delay_task.take();
15560        } else {
15561            self.git_blame_inline_enabled = true;
15562            self.start_git_blame_inline(user_triggered, window, cx);
15563        }
15564
15565        cx.notify();
15566    }
15567
15568    fn start_git_blame_inline(
15569        &mut self,
15570        user_triggered: bool,
15571        window: &mut Window,
15572        cx: &mut Context<Self>,
15573    ) {
15574        self.start_git_blame(user_triggered, window, cx);
15575
15576        if ProjectSettings::get_global(cx)
15577            .git
15578            .inline_blame_delay()
15579            .is_some()
15580        {
15581            self.start_inline_blame_timer(window, cx);
15582        } else {
15583            self.show_git_blame_inline = true
15584        }
15585    }
15586
15587    pub fn blame(&self) -> Option<&Entity<GitBlame>> {
15588        self.blame.as_ref()
15589    }
15590
15591    pub fn show_git_blame_gutter(&self) -> bool {
15592        self.show_git_blame_gutter
15593    }
15594
15595    pub fn render_git_blame_gutter(&self, cx: &App) -> bool {
15596        self.show_git_blame_gutter && self.has_blame_entries(cx)
15597    }
15598
15599    pub fn render_git_blame_inline(&self, window: &Window, cx: &App) -> bool {
15600        self.show_git_blame_inline
15601            && (self.focus_handle.is_focused(window)
15602                || self
15603                    .git_blame_inline_tooltip
15604                    .as_ref()
15605                    .and_then(|t| t.upgrade())
15606                    .is_some())
15607            && !self.newest_selection_head_on_empty_line(cx)
15608            && self.has_blame_entries(cx)
15609    }
15610
15611    fn has_blame_entries(&self, cx: &App) -> bool {
15612        self.blame()
15613            .map_or(false, |blame| blame.read(cx).has_generated_entries())
15614    }
15615
15616    fn newest_selection_head_on_empty_line(&self, cx: &App) -> bool {
15617        let cursor_anchor = self.selections.newest_anchor().head();
15618
15619        let snapshot = self.buffer.read(cx).snapshot(cx);
15620        let buffer_row = MultiBufferRow(cursor_anchor.to_point(&snapshot).row);
15621
15622        snapshot.line_len(buffer_row) == 0
15623    }
15624
15625    fn get_permalink_to_line(&self, cx: &mut Context<Self>) -> Task<Result<url::Url>> {
15626        let buffer_and_selection = maybe!({
15627            let selection = self.selections.newest::<Point>(cx);
15628            let selection_range = selection.range();
15629
15630            let multi_buffer = self.buffer().read(cx);
15631            let multi_buffer_snapshot = multi_buffer.snapshot(cx);
15632            let buffer_ranges = multi_buffer_snapshot.range_to_buffer_ranges(selection_range);
15633
15634            let (buffer, range, _) = if selection.reversed {
15635                buffer_ranges.first()
15636            } else {
15637                buffer_ranges.last()
15638            }?;
15639
15640            let selection = text::ToPoint::to_point(&range.start, &buffer).row
15641                ..text::ToPoint::to_point(&range.end, &buffer).row;
15642            Some((
15643                multi_buffer.buffer(buffer.remote_id()).unwrap().clone(),
15644                selection,
15645            ))
15646        });
15647
15648        let Some((buffer, selection)) = buffer_and_selection else {
15649            return Task::ready(Err(anyhow!("failed to determine buffer and selection")));
15650        };
15651
15652        let Some(project) = self.project.as_ref() else {
15653            return Task::ready(Err(anyhow!("editor does not have project")));
15654        };
15655
15656        project.update(cx, |project, cx| {
15657            project.get_permalink_to_line(&buffer, selection, cx)
15658        })
15659    }
15660
15661    pub fn copy_permalink_to_line(
15662        &mut self,
15663        _: &CopyPermalinkToLine,
15664        window: &mut Window,
15665        cx: &mut Context<Self>,
15666    ) {
15667        let permalink_task = self.get_permalink_to_line(cx);
15668        let workspace = self.workspace();
15669
15670        cx.spawn_in(window, async move |_, cx| match permalink_task.await {
15671            Ok(permalink) => {
15672                cx.update(|_, cx| {
15673                    cx.write_to_clipboard(ClipboardItem::new_string(permalink.to_string()));
15674                })
15675                .ok();
15676            }
15677            Err(err) => {
15678                let message = format!("Failed to copy permalink: {err}");
15679
15680                Err::<(), anyhow::Error>(err).log_err();
15681
15682                if let Some(workspace) = workspace {
15683                    workspace
15684                        .update_in(cx, |workspace, _, cx| {
15685                            struct CopyPermalinkToLine;
15686
15687                            workspace.show_toast(
15688                                Toast::new(
15689                                    NotificationId::unique::<CopyPermalinkToLine>(),
15690                                    message,
15691                                ),
15692                                cx,
15693                            )
15694                        })
15695                        .ok();
15696                }
15697            }
15698        })
15699        .detach();
15700    }
15701
15702    pub fn copy_file_location(
15703        &mut self,
15704        _: &CopyFileLocation,
15705        _: &mut Window,
15706        cx: &mut Context<Self>,
15707    ) {
15708        let selection = self.selections.newest::<Point>(cx).start.row + 1;
15709        if let Some(file) = self.target_file(cx) {
15710            if let Some(path) = file.path().to_str() {
15711                cx.write_to_clipboard(ClipboardItem::new_string(format!("{path}:{selection}")));
15712            }
15713        }
15714    }
15715
15716    pub fn open_permalink_to_line(
15717        &mut self,
15718        _: &OpenPermalinkToLine,
15719        window: &mut Window,
15720        cx: &mut Context<Self>,
15721    ) {
15722        let permalink_task = self.get_permalink_to_line(cx);
15723        let workspace = self.workspace();
15724
15725        cx.spawn_in(window, async move |_, cx| match permalink_task.await {
15726            Ok(permalink) => {
15727                cx.update(|_, cx| {
15728                    cx.open_url(permalink.as_ref());
15729                })
15730                .ok();
15731            }
15732            Err(err) => {
15733                let message = format!("Failed to open permalink: {err}");
15734
15735                Err::<(), anyhow::Error>(err).log_err();
15736
15737                if let Some(workspace) = workspace {
15738                    workspace
15739                        .update(cx, |workspace, cx| {
15740                            struct OpenPermalinkToLine;
15741
15742                            workspace.show_toast(
15743                                Toast::new(
15744                                    NotificationId::unique::<OpenPermalinkToLine>(),
15745                                    message,
15746                                ),
15747                                cx,
15748                            )
15749                        })
15750                        .ok();
15751                }
15752            }
15753        })
15754        .detach();
15755    }
15756
15757    pub fn insert_uuid_v4(
15758        &mut self,
15759        _: &InsertUuidV4,
15760        window: &mut Window,
15761        cx: &mut Context<Self>,
15762    ) {
15763        self.insert_uuid(UuidVersion::V4, window, cx);
15764    }
15765
15766    pub fn insert_uuid_v7(
15767        &mut self,
15768        _: &InsertUuidV7,
15769        window: &mut Window,
15770        cx: &mut Context<Self>,
15771    ) {
15772        self.insert_uuid(UuidVersion::V7, window, cx);
15773    }
15774
15775    fn insert_uuid(&mut self, version: UuidVersion, window: &mut Window, cx: &mut Context<Self>) {
15776        self.transact(window, cx, |this, window, cx| {
15777            let edits = this
15778                .selections
15779                .all::<Point>(cx)
15780                .into_iter()
15781                .map(|selection| {
15782                    let uuid = match version {
15783                        UuidVersion::V4 => uuid::Uuid::new_v4(),
15784                        UuidVersion::V7 => uuid::Uuid::now_v7(),
15785                    };
15786
15787                    (selection.range(), uuid.to_string())
15788                });
15789            this.edit(edits, cx);
15790            this.refresh_inline_completion(true, false, window, cx);
15791        });
15792    }
15793
15794    pub fn open_selections_in_multibuffer(
15795        &mut self,
15796        _: &OpenSelectionsInMultibuffer,
15797        window: &mut Window,
15798        cx: &mut Context<Self>,
15799    ) {
15800        let multibuffer = self.buffer.read(cx);
15801
15802        let Some(buffer) = multibuffer.as_singleton() else {
15803            return;
15804        };
15805
15806        let Some(workspace) = self.workspace() else {
15807            return;
15808        };
15809
15810        let locations = self
15811            .selections
15812            .disjoint_anchors()
15813            .iter()
15814            .map(|range| Location {
15815                buffer: buffer.clone(),
15816                range: range.start.text_anchor..range.end.text_anchor,
15817            })
15818            .collect::<Vec<_>>();
15819
15820        let title = multibuffer.title(cx).to_string();
15821
15822        cx.spawn_in(window, async move |_, cx| {
15823            workspace.update_in(cx, |workspace, window, cx| {
15824                Self::open_locations_in_multibuffer(
15825                    workspace,
15826                    locations,
15827                    format!("Selections for '{title}'"),
15828                    false,
15829                    MultibufferSelectionMode::All,
15830                    window,
15831                    cx,
15832                );
15833            })
15834        })
15835        .detach();
15836    }
15837
15838    /// Adds a row highlight for the given range. If a row has multiple highlights, the
15839    /// last highlight added will be used.
15840    ///
15841    /// If the range ends at the beginning of a line, then that line will not be highlighted.
15842    pub fn highlight_rows<T: 'static>(
15843        &mut self,
15844        range: Range<Anchor>,
15845        color: Hsla,
15846        should_autoscroll: bool,
15847        cx: &mut Context<Self>,
15848    ) {
15849        let snapshot = self.buffer().read(cx).snapshot(cx);
15850        let row_highlights = self.highlighted_rows.entry(TypeId::of::<T>()).or_default();
15851        let ix = row_highlights.binary_search_by(|highlight| {
15852            Ordering::Equal
15853                .then_with(|| highlight.range.start.cmp(&range.start, &snapshot))
15854                .then_with(|| highlight.range.end.cmp(&range.end, &snapshot))
15855        });
15856
15857        if let Err(mut ix) = ix {
15858            let index = post_inc(&mut self.highlight_order);
15859
15860            // If this range intersects with the preceding highlight, then merge it with
15861            // the preceding highlight. Otherwise insert a new highlight.
15862            let mut merged = false;
15863            if ix > 0 {
15864                let prev_highlight = &mut row_highlights[ix - 1];
15865                if prev_highlight
15866                    .range
15867                    .end
15868                    .cmp(&range.start, &snapshot)
15869                    .is_ge()
15870                {
15871                    ix -= 1;
15872                    if prev_highlight.range.end.cmp(&range.end, &snapshot).is_lt() {
15873                        prev_highlight.range.end = range.end;
15874                    }
15875                    merged = true;
15876                    prev_highlight.index = index;
15877                    prev_highlight.color = color;
15878                    prev_highlight.should_autoscroll = should_autoscroll;
15879                }
15880            }
15881
15882            if !merged {
15883                row_highlights.insert(
15884                    ix,
15885                    RowHighlight {
15886                        range: range.clone(),
15887                        index,
15888                        color,
15889                        should_autoscroll,
15890                    },
15891                );
15892            }
15893
15894            // If any of the following highlights intersect with this one, merge them.
15895            while let Some(next_highlight) = row_highlights.get(ix + 1) {
15896                let highlight = &row_highlights[ix];
15897                if next_highlight
15898                    .range
15899                    .start
15900                    .cmp(&highlight.range.end, &snapshot)
15901                    .is_le()
15902                {
15903                    if next_highlight
15904                        .range
15905                        .end
15906                        .cmp(&highlight.range.end, &snapshot)
15907                        .is_gt()
15908                    {
15909                        row_highlights[ix].range.end = next_highlight.range.end;
15910                    }
15911                    row_highlights.remove(ix + 1);
15912                } else {
15913                    break;
15914                }
15915            }
15916        }
15917    }
15918
15919    /// Remove any highlighted row ranges of the given type that intersect the
15920    /// given ranges.
15921    pub fn remove_highlighted_rows<T: 'static>(
15922        &mut self,
15923        ranges_to_remove: Vec<Range<Anchor>>,
15924        cx: &mut Context<Self>,
15925    ) {
15926        let snapshot = self.buffer().read(cx).snapshot(cx);
15927        let row_highlights = self.highlighted_rows.entry(TypeId::of::<T>()).or_default();
15928        let mut ranges_to_remove = ranges_to_remove.iter().peekable();
15929        row_highlights.retain(|highlight| {
15930            while let Some(range_to_remove) = ranges_to_remove.peek() {
15931                match range_to_remove.end.cmp(&highlight.range.start, &snapshot) {
15932                    Ordering::Less | Ordering::Equal => {
15933                        ranges_to_remove.next();
15934                    }
15935                    Ordering::Greater => {
15936                        match range_to_remove.start.cmp(&highlight.range.end, &snapshot) {
15937                            Ordering::Less | Ordering::Equal => {
15938                                return false;
15939                            }
15940                            Ordering::Greater => break,
15941                        }
15942                    }
15943                }
15944            }
15945
15946            true
15947        })
15948    }
15949
15950    /// Clear all anchor ranges for a certain highlight context type, so no corresponding rows will be highlighted.
15951    pub fn clear_row_highlights<T: 'static>(&mut self) {
15952        self.highlighted_rows.remove(&TypeId::of::<T>());
15953    }
15954
15955    /// For a highlight given context type, gets all anchor ranges that will be used for row highlighting.
15956    pub fn highlighted_rows<T: 'static>(&self) -> impl '_ + Iterator<Item = (Range<Anchor>, Hsla)> {
15957        self.highlighted_rows
15958            .get(&TypeId::of::<T>())
15959            .map_or(&[] as &[_], |vec| vec.as_slice())
15960            .iter()
15961            .map(|highlight| (highlight.range.clone(), highlight.color))
15962    }
15963
15964    /// Merges all anchor ranges for all context types ever set, picking the last highlight added in case of a row conflict.
15965    /// Returns a map of display rows that are highlighted and their corresponding highlight color.
15966    /// Allows to ignore certain kinds of highlights.
15967    pub fn highlighted_display_rows(
15968        &self,
15969        window: &mut Window,
15970        cx: &mut App,
15971    ) -> BTreeMap<DisplayRow, LineHighlight> {
15972        let snapshot = self.snapshot(window, cx);
15973        let mut used_highlight_orders = HashMap::default();
15974        self.highlighted_rows
15975            .iter()
15976            .flat_map(|(_, highlighted_rows)| highlighted_rows.iter())
15977            .fold(
15978                BTreeMap::<DisplayRow, LineHighlight>::new(),
15979                |mut unique_rows, highlight| {
15980                    let start = highlight.range.start.to_display_point(&snapshot);
15981                    let end = highlight.range.end.to_display_point(&snapshot);
15982                    let start_row = start.row().0;
15983                    let end_row = if highlight.range.end.text_anchor != text::Anchor::MAX
15984                        && end.column() == 0
15985                    {
15986                        end.row().0.saturating_sub(1)
15987                    } else {
15988                        end.row().0
15989                    };
15990                    for row in start_row..=end_row {
15991                        let used_index =
15992                            used_highlight_orders.entry(row).or_insert(highlight.index);
15993                        if highlight.index >= *used_index {
15994                            *used_index = highlight.index;
15995                            unique_rows.insert(DisplayRow(row), highlight.color.into());
15996                        }
15997                    }
15998                    unique_rows
15999                },
16000            )
16001    }
16002
16003    pub fn highlighted_display_row_for_autoscroll(
16004        &self,
16005        snapshot: &DisplaySnapshot,
16006    ) -> Option<DisplayRow> {
16007        self.highlighted_rows
16008            .values()
16009            .flat_map(|highlighted_rows| highlighted_rows.iter())
16010            .filter_map(|highlight| {
16011                if highlight.should_autoscroll {
16012                    Some(highlight.range.start.to_display_point(snapshot).row())
16013                } else {
16014                    None
16015                }
16016            })
16017            .min()
16018    }
16019
16020    pub fn set_search_within_ranges(&mut self, ranges: &[Range<Anchor>], cx: &mut Context<Self>) {
16021        self.highlight_background::<SearchWithinRange>(
16022            ranges,
16023            |colors| colors.editor_document_highlight_read_background,
16024            cx,
16025        )
16026    }
16027
16028    pub fn set_breadcrumb_header(&mut self, new_header: String) {
16029        self.breadcrumb_header = Some(new_header);
16030    }
16031
16032    pub fn clear_search_within_ranges(&mut self, cx: &mut Context<Self>) {
16033        self.clear_background_highlights::<SearchWithinRange>(cx);
16034    }
16035
16036    pub fn highlight_background<T: 'static>(
16037        &mut self,
16038        ranges: &[Range<Anchor>],
16039        color_fetcher: fn(&ThemeColors) -> Hsla,
16040        cx: &mut Context<Self>,
16041    ) {
16042        self.background_highlights
16043            .insert(TypeId::of::<T>(), (color_fetcher, Arc::from(ranges)));
16044        self.scrollbar_marker_state.dirty = true;
16045        cx.notify();
16046    }
16047
16048    pub fn clear_background_highlights<T: 'static>(
16049        &mut self,
16050        cx: &mut Context<Self>,
16051    ) -> Option<BackgroundHighlight> {
16052        let text_highlights = self.background_highlights.remove(&TypeId::of::<T>())?;
16053        if !text_highlights.1.is_empty() {
16054            self.scrollbar_marker_state.dirty = true;
16055            cx.notify();
16056        }
16057        Some(text_highlights)
16058    }
16059
16060    pub fn highlight_gutter<T: 'static>(
16061        &mut self,
16062        ranges: &[Range<Anchor>],
16063        color_fetcher: fn(&App) -> Hsla,
16064        cx: &mut Context<Self>,
16065    ) {
16066        self.gutter_highlights
16067            .insert(TypeId::of::<T>(), (color_fetcher, Arc::from(ranges)));
16068        cx.notify();
16069    }
16070
16071    pub fn clear_gutter_highlights<T: 'static>(
16072        &mut self,
16073        cx: &mut Context<Self>,
16074    ) -> Option<GutterHighlight> {
16075        cx.notify();
16076        self.gutter_highlights.remove(&TypeId::of::<T>())
16077    }
16078
16079    #[cfg(feature = "test-support")]
16080    pub fn all_text_background_highlights(
16081        &self,
16082        window: &mut Window,
16083        cx: &mut Context<Self>,
16084    ) -> Vec<(Range<DisplayPoint>, Hsla)> {
16085        let snapshot = self.snapshot(window, cx);
16086        let buffer = &snapshot.buffer_snapshot;
16087        let start = buffer.anchor_before(0);
16088        let end = buffer.anchor_after(buffer.len());
16089        let theme = cx.theme().colors();
16090        self.background_highlights_in_range(start..end, &snapshot, theme)
16091    }
16092
16093    #[cfg(feature = "test-support")]
16094    pub fn search_background_highlights(&mut self, cx: &mut Context<Self>) -> Vec<Range<Point>> {
16095        let snapshot = self.buffer().read(cx).snapshot(cx);
16096
16097        let highlights = self
16098            .background_highlights
16099            .get(&TypeId::of::<items::BufferSearchHighlights>());
16100
16101        if let Some((_color, ranges)) = highlights {
16102            ranges
16103                .iter()
16104                .map(|range| range.start.to_point(&snapshot)..range.end.to_point(&snapshot))
16105                .collect_vec()
16106        } else {
16107            vec![]
16108        }
16109    }
16110
16111    fn document_highlights_for_position<'a>(
16112        &'a self,
16113        position: Anchor,
16114        buffer: &'a MultiBufferSnapshot,
16115    ) -> impl 'a + Iterator<Item = &'a Range<Anchor>> {
16116        let read_highlights = self
16117            .background_highlights
16118            .get(&TypeId::of::<DocumentHighlightRead>())
16119            .map(|h| &h.1);
16120        let write_highlights = self
16121            .background_highlights
16122            .get(&TypeId::of::<DocumentHighlightWrite>())
16123            .map(|h| &h.1);
16124        let left_position = position.bias_left(buffer);
16125        let right_position = position.bias_right(buffer);
16126        read_highlights
16127            .into_iter()
16128            .chain(write_highlights)
16129            .flat_map(move |ranges| {
16130                let start_ix = match ranges.binary_search_by(|probe| {
16131                    let cmp = probe.end.cmp(&left_position, buffer);
16132                    if cmp.is_ge() {
16133                        Ordering::Greater
16134                    } else {
16135                        Ordering::Less
16136                    }
16137                }) {
16138                    Ok(i) | Err(i) => i,
16139                };
16140
16141                ranges[start_ix..]
16142                    .iter()
16143                    .take_while(move |range| range.start.cmp(&right_position, buffer).is_le())
16144            })
16145    }
16146
16147    pub fn has_background_highlights<T: 'static>(&self) -> bool {
16148        self.background_highlights
16149            .get(&TypeId::of::<T>())
16150            .map_or(false, |(_, highlights)| !highlights.is_empty())
16151    }
16152
16153    pub fn background_highlights_in_range(
16154        &self,
16155        search_range: Range<Anchor>,
16156        display_snapshot: &DisplaySnapshot,
16157        theme: &ThemeColors,
16158    ) -> Vec<(Range<DisplayPoint>, Hsla)> {
16159        let mut results = Vec::new();
16160        for (color_fetcher, ranges) in self.background_highlights.values() {
16161            let color = color_fetcher(theme);
16162            let start_ix = match ranges.binary_search_by(|probe| {
16163                let cmp = probe
16164                    .end
16165                    .cmp(&search_range.start, &display_snapshot.buffer_snapshot);
16166                if cmp.is_gt() {
16167                    Ordering::Greater
16168                } else {
16169                    Ordering::Less
16170                }
16171            }) {
16172                Ok(i) | Err(i) => i,
16173            };
16174            for range in &ranges[start_ix..] {
16175                if range
16176                    .start
16177                    .cmp(&search_range.end, &display_snapshot.buffer_snapshot)
16178                    .is_ge()
16179                {
16180                    break;
16181                }
16182
16183                let start = range.start.to_display_point(display_snapshot);
16184                let end = range.end.to_display_point(display_snapshot);
16185                results.push((start..end, color))
16186            }
16187        }
16188        results
16189    }
16190
16191    pub fn background_highlight_row_ranges<T: 'static>(
16192        &self,
16193        search_range: Range<Anchor>,
16194        display_snapshot: &DisplaySnapshot,
16195        count: usize,
16196    ) -> Vec<RangeInclusive<DisplayPoint>> {
16197        let mut results = Vec::new();
16198        let Some((_, ranges)) = self.background_highlights.get(&TypeId::of::<T>()) else {
16199            return vec![];
16200        };
16201
16202        let start_ix = match ranges.binary_search_by(|probe| {
16203            let cmp = probe
16204                .end
16205                .cmp(&search_range.start, &display_snapshot.buffer_snapshot);
16206            if cmp.is_gt() {
16207                Ordering::Greater
16208            } else {
16209                Ordering::Less
16210            }
16211        }) {
16212            Ok(i) | Err(i) => i,
16213        };
16214        let mut push_region = |start: Option<Point>, end: Option<Point>| {
16215            if let (Some(start_display), Some(end_display)) = (start, end) {
16216                results.push(
16217                    start_display.to_display_point(display_snapshot)
16218                        ..=end_display.to_display_point(display_snapshot),
16219                );
16220            }
16221        };
16222        let mut start_row: Option<Point> = None;
16223        let mut end_row: Option<Point> = None;
16224        if ranges.len() > count {
16225            return Vec::new();
16226        }
16227        for range in &ranges[start_ix..] {
16228            if range
16229                .start
16230                .cmp(&search_range.end, &display_snapshot.buffer_snapshot)
16231                .is_ge()
16232            {
16233                break;
16234            }
16235            let end = range.end.to_point(&display_snapshot.buffer_snapshot);
16236            if let Some(current_row) = &end_row {
16237                if end.row == current_row.row {
16238                    continue;
16239                }
16240            }
16241            let start = range.start.to_point(&display_snapshot.buffer_snapshot);
16242            if start_row.is_none() {
16243                assert_eq!(end_row, None);
16244                start_row = Some(start);
16245                end_row = Some(end);
16246                continue;
16247            }
16248            if let Some(current_end) = end_row.as_mut() {
16249                if start.row > current_end.row + 1 {
16250                    push_region(start_row, end_row);
16251                    start_row = Some(start);
16252                    end_row = Some(end);
16253                } else {
16254                    // Merge two hunks.
16255                    *current_end = end;
16256                }
16257            } else {
16258                unreachable!();
16259            }
16260        }
16261        // We might still have a hunk that was not rendered (if there was a search hit on the last line)
16262        push_region(start_row, end_row);
16263        results
16264    }
16265
16266    pub fn gutter_highlights_in_range(
16267        &self,
16268        search_range: Range<Anchor>,
16269        display_snapshot: &DisplaySnapshot,
16270        cx: &App,
16271    ) -> Vec<(Range<DisplayPoint>, Hsla)> {
16272        let mut results = Vec::new();
16273        for (color_fetcher, ranges) in self.gutter_highlights.values() {
16274            let color = color_fetcher(cx);
16275            let start_ix = match ranges.binary_search_by(|probe| {
16276                let cmp = probe
16277                    .end
16278                    .cmp(&search_range.start, &display_snapshot.buffer_snapshot);
16279                if cmp.is_gt() {
16280                    Ordering::Greater
16281                } else {
16282                    Ordering::Less
16283                }
16284            }) {
16285                Ok(i) | Err(i) => i,
16286            };
16287            for range in &ranges[start_ix..] {
16288                if range
16289                    .start
16290                    .cmp(&search_range.end, &display_snapshot.buffer_snapshot)
16291                    .is_ge()
16292                {
16293                    break;
16294                }
16295
16296                let start = range.start.to_display_point(display_snapshot);
16297                let end = range.end.to_display_point(display_snapshot);
16298                results.push((start..end, color))
16299            }
16300        }
16301        results
16302    }
16303
16304    /// Get the text ranges corresponding to the redaction query
16305    pub fn redacted_ranges(
16306        &self,
16307        search_range: Range<Anchor>,
16308        display_snapshot: &DisplaySnapshot,
16309        cx: &App,
16310    ) -> Vec<Range<DisplayPoint>> {
16311        display_snapshot
16312            .buffer_snapshot
16313            .redacted_ranges(search_range, |file| {
16314                if let Some(file) = file {
16315                    file.is_private()
16316                        && EditorSettings::get(
16317                            Some(SettingsLocation {
16318                                worktree_id: file.worktree_id(cx),
16319                                path: file.path().as_ref(),
16320                            }),
16321                            cx,
16322                        )
16323                        .redact_private_values
16324                } else {
16325                    false
16326                }
16327            })
16328            .map(|range| {
16329                range.start.to_display_point(display_snapshot)
16330                    ..range.end.to_display_point(display_snapshot)
16331            })
16332            .collect()
16333    }
16334
16335    pub fn highlight_text<T: 'static>(
16336        &mut self,
16337        ranges: Vec<Range<Anchor>>,
16338        style: HighlightStyle,
16339        cx: &mut Context<Self>,
16340    ) {
16341        self.display_map.update(cx, |map, _| {
16342            map.highlight_text(TypeId::of::<T>(), ranges, style)
16343        });
16344        cx.notify();
16345    }
16346
16347    pub(crate) fn highlight_inlays<T: 'static>(
16348        &mut self,
16349        highlights: Vec<InlayHighlight>,
16350        style: HighlightStyle,
16351        cx: &mut Context<Self>,
16352    ) {
16353        self.display_map.update(cx, |map, _| {
16354            map.highlight_inlays(TypeId::of::<T>(), highlights, style)
16355        });
16356        cx.notify();
16357    }
16358
16359    pub fn text_highlights<'a, T: 'static>(
16360        &'a self,
16361        cx: &'a App,
16362    ) -> Option<(HighlightStyle, &'a [Range<Anchor>])> {
16363        self.display_map.read(cx).text_highlights(TypeId::of::<T>())
16364    }
16365
16366    pub fn clear_highlights<T: 'static>(&mut self, cx: &mut Context<Self>) {
16367        let cleared = self
16368            .display_map
16369            .update(cx, |map, _| map.clear_highlights(TypeId::of::<T>()));
16370        if cleared {
16371            cx.notify();
16372        }
16373    }
16374
16375    pub fn show_local_cursors(&self, window: &mut Window, cx: &mut App) -> bool {
16376        (self.read_only(cx) || self.blink_manager.read(cx).visible())
16377            && self.focus_handle.is_focused(window)
16378    }
16379
16380    pub fn set_show_cursor_when_unfocused(&mut self, is_enabled: bool, cx: &mut Context<Self>) {
16381        self.show_cursor_when_unfocused = is_enabled;
16382        cx.notify();
16383    }
16384
16385    fn on_buffer_changed(&mut self, _: Entity<MultiBuffer>, cx: &mut Context<Self>) {
16386        cx.notify();
16387    }
16388
16389    fn on_buffer_event(
16390        &mut self,
16391        multibuffer: &Entity<MultiBuffer>,
16392        event: &multi_buffer::Event,
16393        window: &mut Window,
16394        cx: &mut Context<Self>,
16395    ) {
16396        match event {
16397            multi_buffer::Event::Edited {
16398                singleton_buffer_edited,
16399                edited_buffer: buffer_edited,
16400            } => {
16401                self.scrollbar_marker_state.dirty = true;
16402                self.active_indent_guides_state.dirty = true;
16403                self.refresh_active_diagnostics(cx);
16404                self.refresh_code_actions(window, cx);
16405                if self.has_active_inline_completion() {
16406                    self.update_visible_inline_completion(window, cx);
16407                }
16408                if let Some(buffer) = buffer_edited {
16409                    let buffer_id = buffer.read(cx).remote_id();
16410                    if !self.registered_buffers.contains_key(&buffer_id) {
16411                        if let Some(project) = self.project.as_ref() {
16412                            project.update(cx, |project, cx| {
16413                                self.registered_buffers.insert(
16414                                    buffer_id,
16415                                    project.register_buffer_with_language_servers(&buffer, cx),
16416                                );
16417                            })
16418                        }
16419                    }
16420                }
16421                cx.emit(EditorEvent::BufferEdited);
16422                cx.emit(SearchEvent::MatchesInvalidated);
16423                if *singleton_buffer_edited {
16424                    if let Some(project) = &self.project {
16425                        #[allow(clippy::mutable_key_type)]
16426                        let languages_affected = multibuffer.update(cx, |multibuffer, cx| {
16427                            multibuffer
16428                                .all_buffers()
16429                                .into_iter()
16430                                .filter_map(|buffer| {
16431                                    buffer.update(cx, |buffer, cx| {
16432                                        let language = buffer.language()?;
16433                                        let should_discard = project.update(cx, |project, cx| {
16434                                            project.is_local()
16435                                                && !project.has_language_servers_for(buffer, cx)
16436                                        });
16437                                        should_discard.not().then_some(language.clone())
16438                                    })
16439                                })
16440                                .collect::<HashSet<_>>()
16441                        });
16442                        if !languages_affected.is_empty() {
16443                            self.refresh_inlay_hints(
16444                                InlayHintRefreshReason::BufferEdited(languages_affected),
16445                                cx,
16446                            );
16447                        }
16448                    }
16449                }
16450
16451                let Some(project) = &self.project else { return };
16452                let (telemetry, is_via_ssh) = {
16453                    let project = project.read(cx);
16454                    let telemetry = project.client().telemetry().clone();
16455                    let is_via_ssh = project.is_via_ssh();
16456                    (telemetry, is_via_ssh)
16457                };
16458                refresh_linked_ranges(self, window, cx);
16459                telemetry.log_edit_event("editor", is_via_ssh);
16460            }
16461            multi_buffer::Event::ExcerptsAdded {
16462                buffer,
16463                predecessor,
16464                excerpts,
16465            } => {
16466                self.tasks_update_task = Some(self.refresh_runnables(window, cx));
16467                let buffer_id = buffer.read(cx).remote_id();
16468                if self.buffer.read(cx).diff_for(buffer_id).is_none() {
16469                    if let Some(project) = &self.project {
16470                        get_uncommitted_diff_for_buffer(
16471                            project,
16472                            [buffer.clone()],
16473                            self.buffer.clone(),
16474                            cx,
16475                        )
16476                        .detach();
16477                    }
16478                }
16479                cx.emit(EditorEvent::ExcerptsAdded {
16480                    buffer: buffer.clone(),
16481                    predecessor: *predecessor,
16482                    excerpts: excerpts.clone(),
16483                });
16484                self.refresh_inlay_hints(InlayHintRefreshReason::NewLinesShown, cx);
16485            }
16486            multi_buffer::Event::ExcerptsRemoved { ids } => {
16487                self.refresh_inlay_hints(InlayHintRefreshReason::ExcerptsRemoved(ids.clone()), cx);
16488                let buffer = self.buffer.read(cx);
16489                self.registered_buffers
16490                    .retain(|buffer_id, _| buffer.buffer(*buffer_id).is_some());
16491                jsx_tag_auto_close::refresh_enabled_in_any_buffer(self, multibuffer, cx);
16492                cx.emit(EditorEvent::ExcerptsRemoved { ids: ids.clone() })
16493            }
16494            multi_buffer::Event::ExcerptsEdited {
16495                excerpt_ids,
16496                buffer_ids,
16497            } => {
16498                self.display_map.update(cx, |map, cx| {
16499                    map.unfold_buffers(buffer_ids.iter().copied(), cx)
16500                });
16501                cx.emit(EditorEvent::ExcerptsEdited {
16502                    ids: excerpt_ids.clone(),
16503                })
16504            }
16505            multi_buffer::Event::ExcerptsExpanded { ids } => {
16506                self.refresh_inlay_hints(InlayHintRefreshReason::NewLinesShown, cx);
16507                cx.emit(EditorEvent::ExcerptsExpanded { ids: ids.clone() })
16508            }
16509            multi_buffer::Event::Reparsed(buffer_id) => {
16510                self.tasks_update_task = Some(self.refresh_runnables(window, cx));
16511                jsx_tag_auto_close::refresh_enabled_in_any_buffer(self, multibuffer, cx);
16512
16513                cx.emit(EditorEvent::Reparsed(*buffer_id));
16514            }
16515            multi_buffer::Event::DiffHunksToggled => {
16516                self.tasks_update_task = Some(self.refresh_runnables(window, cx));
16517            }
16518            multi_buffer::Event::LanguageChanged(buffer_id) => {
16519                linked_editing_ranges::refresh_linked_ranges(self, window, cx);
16520                jsx_tag_auto_close::refresh_enabled_in_any_buffer(self, multibuffer, cx);
16521                cx.emit(EditorEvent::Reparsed(*buffer_id));
16522                cx.notify();
16523            }
16524            multi_buffer::Event::DirtyChanged => cx.emit(EditorEvent::DirtyChanged),
16525            multi_buffer::Event::Saved => cx.emit(EditorEvent::Saved),
16526            multi_buffer::Event::FileHandleChanged
16527            | multi_buffer::Event::Reloaded
16528            | multi_buffer::Event::BufferDiffChanged => cx.emit(EditorEvent::TitleChanged),
16529            multi_buffer::Event::Closed => cx.emit(EditorEvent::Closed),
16530            multi_buffer::Event::DiagnosticsUpdated => {
16531                self.refresh_active_diagnostics(cx);
16532                self.refresh_inline_diagnostics(true, window, cx);
16533                self.scrollbar_marker_state.dirty = true;
16534                cx.notify();
16535            }
16536            _ => {}
16537        };
16538    }
16539
16540    fn on_display_map_changed(
16541        &mut self,
16542        _: Entity<DisplayMap>,
16543        _: &mut Window,
16544        cx: &mut Context<Self>,
16545    ) {
16546        cx.notify();
16547    }
16548
16549    fn settings_changed(&mut self, window: &mut Window, cx: &mut Context<Self>) {
16550        self.tasks_update_task = Some(self.refresh_runnables(window, cx));
16551        self.update_edit_prediction_settings(cx);
16552        self.refresh_inline_completion(true, false, window, cx);
16553        self.refresh_inlay_hints(
16554            InlayHintRefreshReason::SettingsChange(inlay_hint_settings(
16555                self.selections.newest_anchor().head(),
16556                &self.buffer.read(cx).snapshot(cx),
16557                cx,
16558            )),
16559            cx,
16560        );
16561
16562        let old_cursor_shape = self.cursor_shape;
16563
16564        {
16565            let editor_settings = EditorSettings::get_global(cx);
16566            self.scroll_manager.vertical_scroll_margin = editor_settings.vertical_scroll_margin;
16567            self.show_breadcrumbs = editor_settings.toolbar.breadcrumbs;
16568            self.cursor_shape = editor_settings.cursor_shape.unwrap_or_default();
16569        }
16570
16571        if old_cursor_shape != self.cursor_shape {
16572            cx.emit(EditorEvent::CursorShapeChanged);
16573        }
16574
16575        let project_settings = ProjectSettings::get_global(cx);
16576        self.serialize_dirty_buffers = project_settings.session.restore_unsaved_buffers;
16577
16578        if self.mode == EditorMode::Full {
16579            let show_inline_diagnostics = project_settings.diagnostics.inline.enabled;
16580            let inline_blame_enabled = project_settings.git.inline_blame_enabled();
16581            if self.show_inline_diagnostics != show_inline_diagnostics {
16582                self.show_inline_diagnostics = show_inline_diagnostics;
16583                self.refresh_inline_diagnostics(false, window, cx);
16584            }
16585
16586            if self.git_blame_inline_enabled != inline_blame_enabled {
16587                self.toggle_git_blame_inline_internal(false, window, cx);
16588            }
16589        }
16590
16591        cx.notify();
16592    }
16593
16594    pub fn set_searchable(&mut self, searchable: bool) {
16595        self.searchable = searchable;
16596    }
16597
16598    pub fn searchable(&self) -> bool {
16599        self.searchable
16600    }
16601
16602    fn open_proposed_changes_editor(
16603        &mut self,
16604        _: &OpenProposedChangesEditor,
16605        window: &mut Window,
16606        cx: &mut Context<Self>,
16607    ) {
16608        let Some(workspace) = self.workspace() else {
16609            cx.propagate();
16610            return;
16611        };
16612
16613        let selections = self.selections.all::<usize>(cx);
16614        let multi_buffer = self.buffer.read(cx);
16615        let multi_buffer_snapshot = multi_buffer.snapshot(cx);
16616        let mut new_selections_by_buffer = HashMap::default();
16617        for selection in selections {
16618            for (buffer, range, _) in
16619                multi_buffer_snapshot.range_to_buffer_ranges(selection.start..selection.end)
16620            {
16621                let mut range = range.to_point(buffer);
16622                range.start.column = 0;
16623                range.end.column = buffer.line_len(range.end.row);
16624                new_selections_by_buffer
16625                    .entry(multi_buffer.buffer(buffer.remote_id()).unwrap())
16626                    .or_insert(Vec::new())
16627                    .push(range)
16628            }
16629        }
16630
16631        let proposed_changes_buffers = new_selections_by_buffer
16632            .into_iter()
16633            .map(|(buffer, ranges)| ProposedChangeLocation { buffer, ranges })
16634            .collect::<Vec<_>>();
16635        let proposed_changes_editor = cx.new(|cx| {
16636            ProposedChangesEditor::new(
16637                "Proposed changes",
16638                proposed_changes_buffers,
16639                self.project.clone(),
16640                window,
16641                cx,
16642            )
16643        });
16644
16645        window.defer(cx, move |window, cx| {
16646            workspace.update(cx, |workspace, cx| {
16647                workspace.active_pane().update(cx, |pane, cx| {
16648                    pane.add_item(
16649                        Box::new(proposed_changes_editor),
16650                        true,
16651                        true,
16652                        None,
16653                        window,
16654                        cx,
16655                    );
16656                });
16657            });
16658        });
16659    }
16660
16661    pub fn open_excerpts_in_split(
16662        &mut self,
16663        _: &OpenExcerptsSplit,
16664        window: &mut Window,
16665        cx: &mut Context<Self>,
16666    ) {
16667        self.open_excerpts_common(None, true, window, cx)
16668    }
16669
16670    pub fn open_excerpts(&mut self, _: &OpenExcerpts, window: &mut Window, cx: &mut Context<Self>) {
16671        self.open_excerpts_common(None, false, window, cx)
16672    }
16673
16674    fn open_excerpts_common(
16675        &mut self,
16676        jump_data: Option<JumpData>,
16677        split: bool,
16678        window: &mut Window,
16679        cx: &mut Context<Self>,
16680    ) {
16681        let Some(workspace) = self.workspace() else {
16682            cx.propagate();
16683            return;
16684        };
16685
16686        if self.buffer.read(cx).is_singleton() {
16687            cx.propagate();
16688            return;
16689        }
16690
16691        let mut new_selections_by_buffer = HashMap::default();
16692        match &jump_data {
16693            Some(JumpData::MultiBufferPoint {
16694                excerpt_id,
16695                position,
16696                anchor,
16697                line_offset_from_top,
16698            }) => {
16699                let multi_buffer_snapshot = self.buffer.read(cx).snapshot(cx);
16700                if let Some(buffer) = multi_buffer_snapshot
16701                    .buffer_id_for_excerpt(*excerpt_id)
16702                    .and_then(|buffer_id| self.buffer.read(cx).buffer(buffer_id))
16703                {
16704                    let buffer_snapshot = buffer.read(cx).snapshot();
16705                    let jump_to_point = if buffer_snapshot.can_resolve(anchor) {
16706                        language::ToPoint::to_point(anchor, &buffer_snapshot)
16707                    } else {
16708                        buffer_snapshot.clip_point(*position, Bias::Left)
16709                    };
16710                    let jump_to_offset = buffer_snapshot.point_to_offset(jump_to_point);
16711                    new_selections_by_buffer.insert(
16712                        buffer,
16713                        (
16714                            vec![jump_to_offset..jump_to_offset],
16715                            Some(*line_offset_from_top),
16716                        ),
16717                    );
16718                }
16719            }
16720            Some(JumpData::MultiBufferRow {
16721                row,
16722                line_offset_from_top,
16723            }) => {
16724                let point = MultiBufferPoint::new(row.0, 0);
16725                if let Some((buffer, buffer_point, _)) =
16726                    self.buffer.read(cx).point_to_buffer_point(point, cx)
16727                {
16728                    let buffer_offset = buffer.read(cx).point_to_offset(buffer_point);
16729                    new_selections_by_buffer
16730                        .entry(buffer)
16731                        .or_insert((Vec::new(), Some(*line_offset_from_top)))
16732                        .0
16733                        .push(buffer_offset..buffer_offset)
16734                }
16735            }
16736            None => {
16737                let selections = self.selections.all::<usize>(cx);
16738                let multi_buffer = self.buffer.read(cx);
16739                for selection in selections {
16740                    for (snapshot, range, _, anchor) in multi_buffer
16741                        .snapshot(cx)
16742                        .range_to_buffer_ranges_with_deleted_hunks(selection.range())
16743                    {
16744                        if let Some(anchor) = anchor {
16745                            // selection is in a deleted hunk
16746                            let Some(buffer_id) = anchor.buffer_id else {
16747                                continue;
16748                            };
16749                            let Some(buffer_handle) = multi_buffer.buffer(buffer_id) else {
16750                                continue;
16751                            };
16752                            let offset = text::ToOffset::to_offset(
16753                                &anchor.text_anchor,
16754                                &buffer_handle.read(cx).snapshot(),
16755                            );
16756                            let range = offset..offset;
16757                            new_selections_by_buffer
16758                                .entry(buffer_handle)
16759                                .or_insert((Vec::new(), None))
16760                                .0
16761                                .push(range)
16762                        } else {
16763                            let Some(buffer_handle) = multi_buffer.buffer(snapshot.remote_id())
16764                            else {
16765                                continue;
16766                            };
16767                            new_selections_by_buffer
16768                                .entry(buffer_handle)
16769                                .or_insert((Vec::new(), None))
16770                                .0
16771                                .push(range)
16772                        }
16773                    }
16774                }
16775            }
16776        }
16777
16778        if new_selections_by_buffer.is_empty() {
16779            return;
16780        }
16781
16782        // We defer the pane interaction because we ourselves are a workspace item
16783        // and activating a new item causes the pane to call a method on us reentrantly,
16784        // which panics if we're on the stack.
16785        window.defer(cx, move |window, cx| {
16786            workspace.update(cx, |workspace, cx| {
16787                let pane = if split {
16788                    workspace.adjacent_pane(window, cx)
16789                } else {
16790                    workspace.active_pane().clone()
16791                };
16792
16793                for (buffer, (ranges, scroll_offset)) in new_selections_by_buffer {
16794                    let editor = buffer
16795                        .read(cx)
16796                        .file()
16797                        .is_none()
16798                        .then(|| {
16799                            // Handle file-less buffers separately: those are not really the project items, so won't have a project path or entity id,
16800                            // so `workspace.open_project_item` will never find them, always opening a new editor.
16801                            // Instead, we try to activate the existing editor in the pane first.
16802                            let (editor, pane_item_index) =
16803                                pane.read(cx).items().enumerate().find_map(|(i, item)| {
16804                                    let editor = item.downcast::<Editor>()?;
16805                                    let singleton_buffer =
16806                                        editor.read(cx).buffer().read(cx).as_singleton()?;
16807                                    if singleton_buffer == buffer {
16808                                        Some((editor, i))
16809                                    } else {
16810                                        None
16811                                    }
16812                                })?;
16813                            pane.update(cx, |pane, cx| {
16814                                pane.activate_item(pane_item_index, true, true, window, cx)
16815                            });
16816                            Some(editor)
16817                        })
16818                        .flatten()
16819                        .unwrap_or_else(|| {
16820                            workspace.open_project_item::<Self>(
16821                                pane.clone(),
16822                                buffer,
16823                                true,
16824                                true,
16825                                window,
16826                                cx,
16827                            )
16828                        });
16829
16830                    editor.update(cx, |editor, cx| {
16831                        let autoscroll = match scroll_offset {
16832                            Some(scroll_offset) => Autoscroll::top_relative(scroll_offset as usize),
16833                            None => Autoscroll::newest(),
16834                        };
16835                        let nav_history = editor.nav_history.take();
16836                        editor.change_selections(Some(autoscroll), window, cx, |s| {
16837                            s.select_ranges(ranges);
16838                        });
16839                        editor.nav_history = nav_history;
16840                    });
16841                }
16842            })
16843        });
16844    }
16845
16846    fn marked_text_ranges(&self, cx: &App) -> Option<Vec<Range<OffsetUtf16>>> {
16847        let snapshot = self.buffer.read(cx).read(cx);
16848        let (_, ranges) = self.text_highlights::<InputComposition>(cx)?;
16849        Some(
16850            ranges
16851                .iter()
16852                .map(move |range| {
16853                    range.start.to_offset_utf16(&snapshot)..range.end.to_offset_utf16(&snapshot)
16854                })
16855                .collect(),
16856        )
16857    }
16858
16859    fn selection_replacement_ranges(
16860        &self,
16861        range: Range<OffsetUtf16>,
16862        cx: &mut App,
16863    ) -> Vec<Range<OffsetUtf16>> {
16864        let selections = self.selections.all::<OffsetUtf16>(cx);
16865        let newest_selection = selections
16866            .iter()
16867            .max_by_key(|selection| selection.id)
16868            .unwrap();
16869        let start_delta = range.start.0 as isize - newest_selection.start.0 as isize;
16870        let end_delta = range.end.0 as isize - newest_selection.end.0 as isize;
16871        let snapshot = self.buffer.read(cx).read(cx);
16872        selections
16873            .into_iter()
16874            .map(|mut selection| {
16875                selection.start.0 =
16876                    (selection.start.0 as isize).saturating_add(start_delta) as usize;
16877                selection.end.0 = (selection.end.0 as isize).saturating_add(end_delta) as usize;
16878                snapshot.clip_offset_utf16(selection.start, Bias::Left)
16879                    ..snapshot.clip_offset_utf16(selection.end, Bias::Right)
16880            })
16881            .collect()
16882    }
16883
16884    fn report_editor_event(
16885        &self,
16886        event_type: &'static str,
16887        file_extension: Option<String>,
16888        cx: &App,
16889    ) {
16890        if cfg!(any(test, feature = "test-support")) {
16891            return;
16892        }
16893
16894        let Some(project) = &self.project else { return };
16895
16896        // If None, we are in a file without an extension
16897        let file = self
16898            .buffer
16899            .read(cx)
16900            .as_singleton()
16901            .and_then(|b| b.read(cx).file());
16902        let file_extension = file_extension.or(file
16903            .as_ref()
16904            .and_then(|file| Path::new(file.file_name(cx)).extension())
16905            .and_then(|e| e.to_str())
16906            .map(|a| a.to_string()));
16907
16908        let vim_mode = cx
16909            .global::<SettingsStore>()
16910            .raw_user_settings()
16911            .get("vim_mode")
16912            == Some(&serde_json::Value::Bool(true));
16913
16914        let edit_predictions_provider = all_language_settings(file, cx).edit_predictions.provider;
16915        let copilot_enabled = edit_predictions_provider
16916            == language::language_settings::EditPredictionProvider::Copilot;
16917        let copilot_enabled_for_language = self
16918            .buffer
16919            .read(cx)
16920            .language_settings(cx)
16921            .show_edit_predictions;
16922
16923        let project = project.read(cx);
16924        telemetry::event!(
16925            event_type,
16926            file_extension,
16927            vim_mode,
16928            copilot_enabled,
16929            copilot_enabled_for_language,
16930            edit_predictions_provider,
16931            is_via_ssh = project.is_via_ssh(),
16932        );
16933    }
16934
16935    /// Copy the highlighted chunks to the clipboard as JSON. The format is an array of lines,
16936    /// with each line being an array of {text, highlight} objects.
16937    fn copy_highlight_json(
16938        &mut self,
16939        _: &CopyHighlightJson,
16940        window: &mut Window,
16941        cx: &mut Context<Self>,
16942    ) {
16943        #[derive(Serialize)]
16944        struct Chunk<'a> {
16945            text: String,
16946            highlight: Option<&'a str>,
16947        }
16948
16949        let snapshot = self.buffer.read(cx).snapshot(cx);
16950        let range = self
16951            .selected_text_range(false, window, cx)
16952            .and_then(|selection| {
16953                if selection.range.is_empty() {
16954                    None
16955                } else {
16956                    Some(selection.range)
16957                }
16958            })
16959            .unwrap_or_else(|| 0..snapshot.len());
16960
16961        let chunks = snapshot.chunks(range, true);
16962        let mut lines = Vec::new();
16963        let mut line: VecDeque<Chunk> = VecDeque::new();
16964
16965        let Some(style) = self.style.as_ref() else {
16966            return;
16967        };
16968
16969        for chunk in chunks {
16970            let highlight = chunk
16971                .syntax_highlight_id
16972                .and_then(|id| id.name(&style.syntax));
16973            let mut chunk_lines = chunk.text.split('\n').peekable();
16974            while let Some(text) = chunk_lines.next() {
16975                let mut merged_with_last_token = false;
16976                if let Some(last_token) = line.back_mut() {
16977                    if last_token.highlight == highlight {
16978                        last_token.text.push_str(text);
16979                        merged_with_last_token = true;
16980                    }
16981                }
16982
16983                if !merged_with_last_token {
16984                    line.push_back(Chunk {
16985                        text: text.into(),
16986                        highlight,
16987                    });
16988                }
16989
16990                if chunk_lines.peek().is_some() {
16991                    if line.len() > 1 && line.front().unwrap().text.is_empty() {
16992                        line.pop_front();
16993                    }
16994                    if line.len() > 1 && line.back().unwrap().text.is_empty() {
16995                        line.pop_back();
16996                    }
16997
16998                    lines.push(mem::take(&mut line));
16999                }
17000            }
17001        }
17002
17003        let Some(lines) = serde_json::to_string_pretty(&lines).log_err() else {
17004            return;
17005        };
17006        cx.write_to_clipboard(ClipboardItem::new_string(lines));
17007    }
17008
17009    pub fn open_context_menu(
17010        &mut self,
17011        _: &OpenContextMenu,
17012        window: &mut Window,
17013        cx: &mut Context<Self>,
17014    ) {
17015        self.request_autoscroll(Autoscroll::newest(), cx);
17016        let position = self.selections.newest_display(cx).start;
17017        mouse_context_menu::deploy_context_menu(self, None, position, window, cx);
17018    }
17019
17020    pub fn inlay_hint_cache(&self) -> &InlayHintCache {
17021        &self.inlay_hint_cache
17022    }
17023
17024    pub fn replay_insert_event(
17025        &mut self,
17026        text: &str,
17027        relative_utf16_range: Option<Range<isize>>,
17028        window: &mut Window,
17029        cx: &mut Context<Self>,
17030    ) {
17031        if !self.input_enabled {
17032            cx.emit(EditorEvent::InputIgnored { text: text.into() });
17033            return;
17034        }
17035        if let Some(relative_utf16_range) = relative_utf16_range {
17036            let selections = self.selections.all::<OffsetUtf16>(cx);
17037            self.change_selections(None, window, cx, |s| {
17038                let new_ranges = selections.into_iter().map(|range| {
17039                    let start = OffsetUtf16(
17040                        range
17041                            .head()
17042                            .0
17043                            .saturating_add_signed(relative_utf16_range.start),
17044                    );
17045                    let end = OffsetUtf16(
17046                        range
17047                            .head()
17048                            .0
17049                            .saturating_add_signed(relative_utf16_range.end),
17050                    );
17051                    start..end
17052                });
17053                s.select_ranges(new_ranges);
17054            });
17055        }
17056
17057        self.handle_input(text, window, cx);
17058    }
17059
17060    pub fn supports_inlay_hints(&self, cx: &mut App) -> bool {
17061        let Some(provider) = self.semantics_provider.as_ref() else {
17062            return false;
17063        };
17064
17065        let mut supports = false;
17066        self.buffer().update(cx, |this, cx| {
17067            this.for_each_buffer(|buffer| {
17068                supports |= provider.supports_inlay_hints(buffer, cx);
17069            });
17070        });
17071
17072        supports
17073    }
17074
17075    pub fn is_focused(&self, window: &Window) -> bool {
17076        self.focus_handle.is_focused(window)
17077    }
17078
17079    fn handle_focus(&mut self, window: &mut Window, cx: &mut Context<Self>) {
17080        cx.emit(EditorEvent::Focused);
17081
17082        if let Some(descendant) = self
17083            .last_focused_descendant
17084            .take()
17085            .and_then(|descendant| descendant.upgrade())
17086        {
17087            window.focus(&descendant);
17088        } else {
17089            if let Some(blame) = self.blame.as_ref() {
17090                blame.update(cx, GitBlame::focus)
17091            }
17092
17093            self.blink_manager.update(cx, BlinkManager::enable);
17094            self.show_cursor_names(window, cx);
17095            self.buffer.update(cx, |buffer, cx| {
17096                buffer.finalize_last_transaction(cx);
17097                if self.leader_peer_id.is_none() {
17098                    buffer.set_active_selections(
17099                        &self.selections.disjoint_anchors(),
17100                        self.selections.line_mode,
17101                        self.cursor_shape,
17102                        cx,
17103                    );
17104                }
17105            });
17106        }
17107    }
17108
17109    fn handle_focus_in(&mut self, _: &mut Window, cx: &mut Context<Self>) {
17110        cx.emit(EditorEvent::FocusedIn)
17111    }
17112
17113    fn handle_focus_out(
17114        &mut self,
17115        event: FocusOutEvent,
17116        _window: &mut Window,
17117        cx: &mut Context<Self>,
17118    ) {
17119        if event.blurred != self.focus_handle {
17120            self.last_focused_descendant = Some(event.blurred);
17121        }
17122        self.refresh_inlay_hints(InlayHintRefreshReason::ModifiersChanged(false), cx);
17123    }
17124
17125    pub fn handle_blur(&mut self, window: &mut Window, cx: &mut Context<Self>) {
17126        self.blink_manager.update(cx, BlinkManager::disable);
17127        self.buffer
17128            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
17129
17130        if let Some(blame) = self.blame.as_ref() {
17131            blame.update(cx, GitBlame::blur)
17132        }
17133        if !self.hover_state.focused(window, cx) {
17134            hide_hover(self, cx);
17135        }
17136        if !self
17137            .context_menu
17138            .borrow()
17139            .as_ref()
17140            .is_some_and(|context_menu| context_menu.focused(window, cx))
17141        {
17142            self.hide_context_menu(window, cx);
17143        }
17144        self.discard_inline_completion(false, cx);
17145        cx.emit(EditorEvent::Blurred);
17146        cx.notify();
17147    }
17148
17149    pub fn register_action<A: Action>(
17150        &mut self,
17151        listener: impl Fn(&A, &mut Window, &mut App) + 'static,
17152    ) -> Subscription {
17153        let id = self.next_editor_action_id.post_inc();
17154        let listener = Arc::new(listener);
17155        self.editor_actions.borrow_mut().insert(
17156            id,
17157            Box::new(move |window, _| {
17158                let listener = listener.clone();
17159                window.on_action(TypeId::of::<A>(), move |action, phase, window, cx| {
17160                    let action = action.downcast_ref().unwrap();
17161                    if phase == DispatchPhase::Bubble {
17162                        listener(action, window, cx)
17163                    }
17164                })
17165            }),
17166        );
17167
17168        let editor_actions = self.editor_actions.clone();
17169        Subscription::new(move || {
17170            editor_actions.borrow_mut().remove(&id);
17171        })
17172    }
17173
17174    pub fn file_header_size(&self) -> u32 {
17175        FILE_HEADER_HEIGHT
17176    }
17177
17178    pub fn restore(
17179        &mut self,
17180        revert_changes: HashMap<BufferId, Vec<(Range<text::Anchor>, Rope)>>,
17181        window: &mut Window,
17182        cx: &mut Context<Self>,
17183    ) {
17184        let workspace = self.workspace();
17185        let project = self.project.as_ref();
17186        let save_tasks = self.buffer().update(cx, |multi_buffer, cx| {
17187            let mut tasks = Vec::new();
17188            for (buffer_id, changes) in revert_changes {
17189                if let Some(buffer) = multi_buffer.buffer(buffer_id) {
17190                    buffer.update(cx, |buffer, cx| {
17191                        buffer.edit(
17192                            changes
17193                                .into_iter()
17194                                .map(|(range, text)| (range, text.to_string())),
17195                            None,
17196                            cx,
17197                        );
17198                    });
17199
17200                    if let Some(project) =
17201                        project.filter(|_| multi_buffer.all_diff_hunks_expanded())
17202                    {
17203                        project.update(cx, |project, cx| {
17204                            tasks.push((buffer.clone(), project.save_buffer(buffer, cx)));
17205                        })
17206                    }
17207                }
17208            }
17209            tasks
17210        });
17211        cx.spawn_in(window, async move |_, cx| {
17212            for (buffer, task) in save_tasks {
17213                let result = task.await;
17214                if result.is_err() {
17215                    let Some(path) = buffer
17216                        .read_with(cx, |buffer, cx| buffer.project_path(cx))
17217                        .ok()
17218                    else {
17219                        continue;
17220                    };
17221                    if let Some((workspace, path)) = workspace.as_ref().zip(path) {
17222                        let Some(task) = cx
17223                            .update_window_entity(&workspace, |workspace, window, cx| {
17224                                workspace
17225                                    .open_path_preview(path, None, false, false, false, window, cx)
17226                            })
17227                            .ok()
17228                        else {
17229                            continue;
17230                        };
17231                        task.await.log_err();
17232                    }
17233                }
17234            }
17235        })
17236        .detach();
17237        self.change_selections(None, window, cx, |selections| selections.refresh());
17238    }
17239
17240    pub fn to_pixel_point(
17241        &self,
17242        source: multi_buffer::Anchor,
17243        editor_snapshot: &EditorSnapshot,
17244        window: &mut Window,
17245    ) -> Option<gpui::Point<Pixels>> {
17246        let source_point = source.to_display_point(editor_snapshot);
17247        self.display_to_pixel_point(source_point, editor_snapshot, window)
17248    }
17249
17250    pub fn display_to_pixel_point(
17251        &self,
17252        source: DisplayPoint,
17253        editor_snapshot: &EditorSnapshot,
17254        window: &mut Window,
17255    ) -> Option<gpui::Point<Pixels>> {
17256        let line_height = self.style()?.text.line_height_in_pixels(window.rem_size());
17257        let text_layout_details = self.text_layout_details(window);
17258        let scroll_top = text_layout_details
17259            .scroll_anchor
17260            .scroll_position(editor_snapshot)
17261            .y;
17262
17263        if source.row().as_f32() < scroll_top.floor() {
17264            return None;
17265        }
17266        let source_x = editor_snapshot.x_for_display_point(source, &text_layout_details);
17267        let source_y = line_height * (source.row().as_f32() - scroll_top);
17268        Some(gpui::Point::new(source_x, source_y))
17269    }
17270
17271    pub fn has_visible_completions_menu(&self) -> bool {
17272        !self.edit_prediction_preview_is_active()
17273            && self.context_menu.borrow().as_ref().map_or(false, |menu| {
17274                menu.visible() && matches!(menu, CodeContextMenu::Completions(_))
17275            })
17276    }
17277
17278    pub fn register_addon<T: Addon>(&mut self, instance: T) {
17279        self.addons
17280            .insert(std::any::TypeId::of::<T>(), Box::new(instance));
17281    }
17282
17283    pub fn unregister_addon<T: Addon>(&mut self) {
17284        self.addons.remove(&std::any::TypeId::of::<T>());
17285    }
17286
17287    pub fn addon<T: Addon>(&self) -> Option<&T> {
17288        let type_id = std::any::TypeId::of::<T>();
17289        self.addons
17290            .get(&type_id)
17291            .and_then(|item| item.to_any().downcast_ref::<T>())
17292    }
17293
17294    fn character_size(&self, window: &mut Window) -> gpui::Size<Pixels> {
17295        let text_layout_details = self.text_layout_details(window);
17296        let style = &text_layout_details.editor_style;
17297        let font_id = window.text_system().resolve_font(&style.text.font());
17298        let font_size = style.text.font_size.to_pixels(window.rem_size());
17299        let line_height = style.text.line_height_in_pixels(window.rem_size());
17300        let em_width = window.text_system().em_width(font_id, font_size).unwrap();
17301
17302        gpui::Size::new(em_width, line_height)
17303    }
17304
17305    pub fn wait_for_diff_to_load(&self) -> Option<Shared<Task<()>>> {
17306        self.load_diff_task.clone()
17307    }
17308
17309    fn read_metadata_from_db(
17310        &mut self,
17311        item_id: u64,
17312        workspace_id: WorkspaceId,
17313        window: &mut Window,
17314        cx: &mut Context<Editor>,
17315    ) {
17316        if self.is_singleton(cx)
17317            && WorkspaceSettings::get(None, cx).restore_on_startup != RestoreOnStartupBehavior::None
17318        {
17319            let buffer_snapshot = OnceCell::new();
17320
17321            if let Some(selections) = DB.get_editor_selections(item_id, workspace_id).log_err() {
17322                if !selections.is_empty() {
17323                    let snapshot =
17324                        buffer_snapshot.get_or_init(|| self.buffer.read(cx).snapshot(cx));
17325                    self.change_selections(None, window, cx, |s| {
17326                        s.select_ranges(selections.into_iter().map(|(start, end)| {
17327                            snapshot.clip_offset(start, Bias::Left)
17328                                ..snapshot.clip_offset(end, Bias::Right)
17329                        }));
17330                    });
17331                }
17332            };
17333
17334            if let Some(folds) = DB.get_editor_folds(item_id, workspace_id).log_err() {
17335                if !folds.is_empty() {
17336                    let snapshot =
17337                        buffer_snapshot.get_or_init(|| self.buffer.read(cx).snapshot(cx));
17338                    self.fold_ranges(
17339                        folds
17340                            .into_iter()
17341                            .map(|(start, end)| {
17342                                snapshot.clip_offset(start, Bias::Left)
17343                                    ..snapshot.clip_offset(end, Bias::Right)
17344                            })
17345                            .collect(),
17346                        false,
17347                        window,
17348                        cx,
17349                    );
17350                }
17351            }
17352        }
17353
17354        self.read_scroll_position_from_db(item_id, workspace_id, window, cx);
17355    }
17356}
17357
17358fn insert_extra_newline_brackets(
17359    buffer: &MultiBufferSnapshot,
17360    range: Range<usize>,
17361    language: &language::LanguageScope,
17362) -> bool {
17363    let leading_whitespace_len = buffer
17364        .reversed_chars_at(range.start)
17365        .take_while(|c| c.is_whitespace() && *c != '\n')
17366        .map(|c| c.len_utf8())
17367        .sum::<usize>();
17368    let trailing_whitespace_len = buffer
17369        .chars_at(range.end)
17370        .take_while(|c| c.is_whitespace() && *c != '\n')
17371        .map(|c| c.len_utf8())
17372        .sum::<usize>();
17373    let range = range.start - leading_whitespace_len..range.end + trailing_whitespace_len;
17374
17375    language.brackets().any(|(pair, enabled)| {
17376        let pair_start = pair.start.trim_end();
17377        let pair_end = pair.end.trim_start();
17378
17379        enabled
17380            && pair.newline
17381            && buffer.contains_str_at(range.end, pair_end)
17382            && buffer.contains_str_at(range.start.saturating_sub(pair_start.len()), pair_start)
17383    })
17384}
17385
17386fn insert_extra_newline_tree_sitter(buffer: &MultiBufferSnapshot, range: Range<usize>) -> bool {
17387    let (buffer, range) = match buffer.range_to_buffer_ranges(range).as_slice() {
17388        [(buffer, range, _)] => (*buffer, range.clone()),
17389        _ => return false,
17390    };
17391    let pair = {
17392        let mut result: Option<BracketMatch> = None;
17393
17394        for pair in buffer
17395            .all_bracket_ranges(range.clone())
17396            .filter(move |pair| {
17397                pair.open_range.start <= range.start && pair.close_range.end >= range.end
17398            })
17399        {
17400            let len = pair.close_range.end - pair.open_range.start;
17401
17402            if let Some(existing) = &result {
17403                let existing_len = existing.close_range.end - existing.open_range.start;
17404                if len > existing_len {
17405                    continue;
17406                }
17407            }
17408
17409            result = Some(pair);
17410        }
17411
17412        result
17413    };
17414    let Some(pair) = pair else {
17415        return false;
17416    };
17417    pair.newline_only
17418        && buffer
17419            .chars_for_range(pair.open_range.end..range.start)
17420            .chain(buffer.chars_for_range(range.end..pair.close_range.start))
17421            .all(|c| c.is_whitespace() && c != '\n')
17422}
17423
17424fn get_uncommitted_diff_for_buffer(
17425    project: &Entity<Project>,
17426    buffers: impl IntoIterator<Item = Entity<Buffer>>,
17427    buffer: Entity<MultiBuffer>,
17428    cx: &mut App,
17429) -> Task<()> {
17430    let mut tasks = Vec::new();
17431    project.update(cx, |project, cx| {
17432        for buffer in buffers {
17433            tasks.push(project.open_uncommitted_diff(buffer.clone(), cx))
17434        }
17435    });
17436    cx.spawn(async move |cx| {
17437        let diffs = future::join_all(tasks).await;
17438        buffer
17439            .update(cx, |buffer, cx| {
17440                for diff in diffs.into_iter().flatten() {
17441                    buffer.add_diff(diff, cx);
17442                }
17443            })
17444            .ok();
17445    })
17446}
17447
17448fn char_len_with_expanded_tabs(offset: usize, text: &str, tab_size: NonZeroU32) -> usize {
17449    let tab_size = tab_size.get() as usize;
17450    let mut width = offset;
17451
17452    for ch in text.chars() {
17453        width += if ch == '\t' {
17454            tab_size - (width % tab_size)
17455        } else {
17456            1
17457        };
17458    }
17459
17460    width - offset
17461}
17462
17463#[cfg(test)]
17464mod tests {
17465    use super::*;
17466
17467    #[test]
17468    fn test_string_size_with_expanded_tabs() {
17469        let nz = |val| NonZeroU32::new(val).unwrap();
17470        assert_eq!(char_len_with_expanded_tabs(0, "", nz(4)), 0);
17471        assert_eq!(char_len_with_expanded_tabs(0, "hello", nz(4)), 5);
17472        assert_eq!(char_len_with_expanded_tabs(0, "\thello", nz(4)), 9);
17473        assert_eq!(char_len_with_expanded_tabs(0, "abc\tab", nz(4)), 6);
17474        assert_eq!(char_len_with_expanded_tabs(0, "hello\t", nz(4)), 8);
17475        assert_eq!(char_len_with_expanded_tabs(0, "\t\t", nz(8)), 16);
17476        assert_eq!(char_len_with_expanded_tabs(0, "x\t", nz(8)), 8);
17477        assert_eq!(char_len_with_expanded_tabs(7, "x\t", nz(8)), 9);
17478    }
17479}
17480
17481/// Tokenizes a string into runs of text that should stick together, or that is whitespace.
17482struct WordBreakingTokenizer<'a> {
17483    input: &'a str,
17484}
17485
17486impl<'a> WordBreakingTokenizer<'a> {
17487    fn new(input: &'a str) -> Self {
17488        Self { input }
17489    }
17490}
17491
17492fn is_char_ideographic(ch: char) -> bool {
17493    use unicode_script::Script::*;
17494    use unicode_script::UnicodeScript;
17495    matches!(ch.script(), Han | Tangut | Yi)
17496}
17497
17498fn is_grapheme_ideographic(text: &str) -> bool {
17499    text.chars().any(is_char_ideographic)
17500}
17501
17502fn is_grapheme_whitespace(text: &str) -> bool {
17503    text.chars().any(|x| x.is_whitespace())
17504}
17505
17506fn should_stay_with_preceding_ideograph(text: &str) -> bool {
17507    text.chars().next().map_or(false, |ch| {
17508        matches!(ch, '。' | '、' | ',' | '?' | '!' | ':' | ';' | '…')
17509    })
17510}
17511
17512#[derive(PartialEq, Eq, Debug, Clone, Copy)]
17513enum WordBreakToken<'a> {
17514    Word { token: &'a str, grapheme_len: usize },
17515    InlineWhitespace { token: &'a str, grapheme_len: usize },
17516    Newline,
17517}
17518
17519impl<'a> Iterator for WordBreakingTokenizer<'a> {
17520    /// Yields a span, the count of graphemes in the token, and whether it was
17521    /// whitespace. Note that it also breaks at word boundaries.
17522    type Item = WordBreakToken<'a>;
17523
17524    fn next(&mut self) -> Option<Self::Item> {
17525        use unicode_segmentation::UnicodeSegmentation;
17526        if self.input.is_empty() {
17527            return None;
17528        }
17529
17530        let mut iter = self.input.graphemes(true).peekable();
17531        let mut offset = 0;
17532        let mut grapheme_len = 0;
17533        if let Some(first_grapheme) = iter.next() {
17534            let is_newline = first_grapheme == "\n";
17535            let is_whitespace = is_grapheme_whitespace(first_grapheme);
17536            offset += first_grapheme.len();
17537            grapheme_len += 1;
17538            if is_grapheme_ideographic(first_grapheme) && !is_whitespace {
17539                if let Some(grapheme) = iter.peek().copied() {
17540                    if should_stay_with_preceding_ideograph(grapheme) {
17541                        offset += grapheme.len();
17542                        grapheme_len += 1;
17543                    }
17544                }
17545            } else {
17546                let mut words = self.input[offset..].split_word_bound_indices().peekable();
17547                let mut next_word_bound = words.peek().copied();
17548                if next_word_bound.map_or(false, |(i, _)| i == 0) {
17549                    next_word_bound = words.next();
17550                }
17551                while let Some(grapheme) = iter.peek().copied() {
17552                    if next_word_bound.map_or(false, |(i, _)| i == offset) {
17553                        break;
17554                    };
17555                    if is_grapheme_whitespace(grapheme) != is_whitespace
17556                        || (grapheme == "\n") != is_newline
17557                    {
17558                        break;
17559                    };
17560                    offset += grapheme.len();
17561                    grapheme_len += 1;
17562                    iter.next();
17563                }
17564            }
17565            let token = &self.input[..offset];
17566            self.input = &self.input[offset..];
17567            if token == "\n" {
17568                Some(WordBreakToken::Newline)
17569            } else if is_whitespace {
17570                Some(WordBreakToken::InlineWhitespace {
17571                    token,
17572                    grapheme_len,
17573                })
17574            } else {
17575                Some(WordBreakToken::Word {
17576                    token,
17577                    grapheme_len,
17578                })
17579            }
17580        } else {
17581            None
17582        }
17583    }
17584}
17585
17586#[test]
17587fn test_word_breaking_tokenizer() {
17588    let tests: &[(&str, &[WordBreakToken<'static>])] = &[
17589        ("", &[]),
17590        ("  ", &[whitespace("  ", 2)]),
17591        ("Ʒ", &[word("Ʒ", 1)]),
17592        ("Ǽ", &[word("Ǽ", 1)]),
17593        ("", &[word("", 1)]),
17594        ("⋑⋑", &[word("⋑⋑", 2)]),
17595        (
17596            "原理,进而",
17597            &[word("", 1), word("理,", 2), word("", 1), word("", 1)],
17598        ),
17599        (
17600            "hello world",
17601            &[word("hello", 5), whitespace(" ", 1), word("world", 5)],
17602        ),
17603        (
17604            "hello, world",
17605            &[word("hello,", 6), whitespace(" ", 1), word("world", 5)],
17606        ),
17607        (
17608            "  hello world",
17609            &[
17610                whitespace("  ", 2),
17611                word("hello", 5),
17612                whitespace(" ", 1),
17613                word("world", 5),
17614            ],
17615        ),
17616        (
17617            "这是什么 \n 钢笔",
17618            &[
17619                word("", 1),
17620                word("", 1),
17621                word("", 1),
17622                word("", 1),
17623                whitespace(" ", 1),
17624                newline(),
17625                whitespace(" ", 1),
17626                word("", 1),
17627                word("", 1),
17628            ],
17629        ),
17630        (" mutton", &[whitespace("", 1), word("mutton", 6)]),
17631    ];
17632
17633    fn word(token: &'static str, grapheme_len: usize) -> WordBreakToken<'static> {
17634        WordBreakToken::Word {
17635            token,
17636            grapheme_len,
17637        }
17638    }
17639
17640    fn whitespace(token: &'static str, grapheme_len: usize) -> WordBreakToken<'static> {
17641        WordBreakToken::InlineWhitespace {
17642            token,
17643            grapheme_len,
17644        }
17645    }
17646
17647    fn newline() -> WordBreakToken<'static> {
17648        WordBreakToken::Newline
17649    }
17650
17651    for (input, result) in tests {
17652        assert_eq!(
17653            WordBreakingTokenizer::new(input)
17654                .collect::<Vec<_>>()
17655                .as_slice(),
17656            *result,
17657        );
17658    }
17659}
17660
17661fn wrap_with_prefix(
17662    line_prefix: String,
17663    unwrapped_text: String,
17664    wrap_column: usize,
17665    tab_size: NonZeroU32,
17666    preserve_existing_whitespace: bool,
17667) -> String {
17668    let line_prefix_len = char_len_with_expanded_tabs(0, &line_prefix, tab_size);
17669    let mut wrapped_text = String::new();
17670    let mut current_line = line_prefix.clone();
17671
17672    let tokenizer = WordBreakingTokenizer::new(&unwrapped_text);
17673    let mut current_line_len = line_prefix_len;
17674    let mut in_whitespace = false;
17675    for token in tokenizer {
17676        let have_preceding_whitespace = in_whitespace;
17677        match token {
17678            WordBreakToken::Word {
17679                token,
17680                grapheme_len,
17681            } => {
17682                in_whitespace = false;
17683                if current_line_len + grapheme_len > wrap_column
17684                    && current_line_len != line_prefix_len
17685                {
17686                    wrapped_text.push_str(current_line.trim_end());
17687                    wrapped_text.push('\n');
17688                    current_line.truncate(line_prefix.len());
17689                    current_line_len = line_prefix_len;
17690                }
17691                current_line.push_str(token);
17692                current_line_len += grapheme_len;
17693            }
17694            WordBreakToken::InlineWhitespace {
17695                mut token,
17696                mut grapheme_len,
17697            } => {
17698                in_whitespace = true;
17699                if have_preceding_whitespace && !preserve_existing_whitespace {
17700                    continue;
17701                }
17702                if !preserve_existing_whitespace {
17703                    token = " ";
17704                    grapheme_len = 1;
17705                }
17706                if current_line_len + grapheme_len > wrap_column {
17707                    wrapped_text.push_str(current_line.trim_end());
17708                    wrapped_text.push('\n');
17709                    current_line.truncate(line_prefix.len());
17710                    current_line_len = line_prefix_len;
17711                } else if current_line_len != line_prefix_len || preserve_existing_whitespace {
17712                    current_line.push_str(token);
17713                    current_line_len += grapheme_len;
17714                }
17715            }
17716            WordBreakToken::Newline => {
17717                in_whitespace = true;
17718                if preserve_existing_whitespace {
17719                    wrapped_text.push_str(current_line.trim_end());
17720                    wrapped_text.push('\n');
17721                    current_line.truncate(line_prefix.len());
17722                    current_line_len = line_prefix_len;
17723                } else if have_preceding_whitespace {
17724                    continue;
17725                } else if current_line_len + 1 > wrap_column && current_line_len != line_prefix_len
17726                {
17727                    wrapped_text.push_str(current_line.trim_end());
17728                    wrapped_text.push('\n');
17729                    current_line.truncate(line_prefix.len());
17730                    current_line_len = line_prefix_len;
17731                } else if current_line_len != line_prefix_len {
17732                    current_line.push(' ');
17733                    current_line_len += 1;
17734                }
17735            }
17736        }
17737    }
17738
17739    if !current_line.is_empty() {
17740        wrapped_text.push_str(&current_line);
17741    }
17742    wrapped_text
17743}
17744
17745#[test]
17746fn test_wrap_with_prefix() {
17747    assert_eq!(
17748        wrap_with_prefix(
17749            "# ".to_string(),
17750            "abcdefg".to_string(),
17751            4,
17752            NonZeroU32::new(4).unwrap(),
17753            false,
17754        ),
17755        "# abcdefg"
17756    );
17757    assert_eq!(
17758        wrap_with_prefix(
17759            "".to_string(),
17760            "\thello world".to_string(),
17761            8,
17762            NonZeroU32::new(4).unwrap(),
17763            false,
17764        ),
17765        "hello\nworld"
17766    );
17767    assert_eq!(
17768        wrap_with_prefix(
17769            "// ".to_string(),
17770            "xx \nyy zz aa bb cc".to_string(),
17771            12,
17772            NonZeroU32::new(4).unwrap(),
17773            false,
17774        ),
17775        "// xx yy zz\n// aa bb cc"
17776    );
17777    assert_eq!(
17778        wrap_with_prefix(
17779            String::new(),
17780            "这是什么 \n 钢笔".to_string(),
17781            3,
17782            NonZeroU32::new(4).unwrap(),
17783            false,
17784        ),
17785        "这是什\n么 钢\n"
17786    );
17787}
17788
17789pub trait CollaborationHub {
17790    fn collaborators<'a>(&self, cx: &'a App) -> &'a HashMap<PeerId, Collaborator>;
17791    fn user_participant_indices<'a>(&self, cx: &'a App) -> &'a HashMap<u64, ParticipantIndex>;
17792    fn user_names(&self, cx: &App) -> HashMap<u64, SharedString>;
17793}
17794
17795impl CollaborationHub for Entity<Project> {
17796    fn collaborators<'a>(&self, cx: &'a App) -> &'a HashMap<PeerId, Collaborator> {
17797        self.read(cx).collaborators()
17798    }
17799
17800    fn user_participant_indices<'a>(&self, cx: &'a App) -> &'a HashMap<u64, ParticipantIndex> {
17801        self.read(cx).user_store().read(cx).participant_indices()
17802    }
17803
17804    fn user_names(&self, cx: &App) -> HashMap<u64, SharedString> {
17805        let this = self.read(cx);
17806        let user_ids = this.collaborators().values().map(|c| c.user_id);
17807        this.user_store().read_with(cx, |user_store, cx| {
17808            user_store.participant_names(user_ids, cx)
17809        })
17810    }
17811}
17812
17813pub trait SemanticsProvider {
17814    fn hover(
17815        &self,
17816        buffer: &Entity<Buffer>,
17817        position: text::Anchor,
17818        cx: &mut App,
17819    ) -> Option<Task<Vec<project::Hover>>>;
17820
17821    fn inlay_hints(
17822        &self,
17823        buffer_handle: Entity<Buffer>,
17824        range: Range<text::Anchor>,
17825        cx: &mut App,
17826    ) -> Option<Task<anyhow::Result<Vec<InlayHint>>>>;
17827
17828    fn resolve_inlay_hint(
17829        &self,
17830        hint: InlayHint,
17831        buffer_handle: Entity<Buffer>,
17832        server_id: LanguageServerId,
17833        cx: &mut App,
17834    ) -> Option<Task<anyhow::Result<InlayHint>>>;
17835
17836    fn supports_inlay_hints(&self, buffer: &Entity<Buffer>, cx: &mut App) -> bool;
17837
17838    fn document_highlights(
17839        &self,
17840        buffer: &Entity<Buffer>,
17841        position: text::Anchor,
17842        cx: &mut App,
17843    ) -> Option<Task<Result<Vec<DocumentHighlight>>>>;
17844
17845    fn definitions(
17846        &self,
17847        buffer: &Entity<Buffer>,
17848        position: text::Anchor,
17849        kind: GotoDefinitionKind,
17850        cx: &mut App,
17851    ) -> Option<Task<Result<Vec<LocationLink>>>>;
17852
17853    fn range_for_rename(
17854        &self,
17855        buffer: &Entity<Buffer>,
17856        position: text::Anchor,
17857        cx: &mut App,
17858    ) -> Option<Task<Result<Option<Range<text::Anchor>>>>>;
17859
17860    fn perform_rename(
17861        &self,
17862        buffer: &Entity<Buffer>,
17863        position: text::Anchor,
17864        new_name: String,
17865        cx: &mut App,
17866    ) -> Option<Task<Result<ProjectTransaction>>>;
17867}
17868
17869pub trait CompletionProvider {
17870    fn completions(
17871        &self,
17872        buffer: &Entity<Buffer>,
17873        buffer_position: text::Anchor,
17874        trigger: CompletionContext,
17875        window: &mut Window,
17876        cx: &mut Context<Editor>,
17877    ) -> Task<Result<Option<Vec<Completion>>>>;
17878
17879    fn resolve_completions(
17880        &self,
17881        buffer: Entity<Buffer>,
17882        completion_indices: Vec<usize>,
17883        completions: Rc<RefCell<Box<[Completion]>>>,
17884        cx: &mut Context<Editor>,
17885    ) -> Task<Result<bool>>;
17886
17887    fn apply_additional_edits_for_completion(
17888        &self,
17889        _buffer: Entity<Buffer>,
17890        _completions: Rc<RefCell<Box<[Completion]>>>,
17891        _completion_index: usize,
17892        _push_to_history: bool,
17893        _cx: &mut Context<Editor>,
17894    ) -> Task<Result<Option<language::Transaction>>> {
17895        Task::ready(Ok(None))
17896    }
17897
17898    fn is_completion_trigger(
17899        &self,
17900        buffer: &Entity<Buffer>,
17901        position: language::Anchor,
17902        text: &str,
17903        trigger_in_words: bool,
17904        cx: &mut Context<Editor>,
17905    ) -> bool;
17906
17907    fn sort_completions(&self) -> bool {
17908        true
17909    }
17910}
17911
17912pub trait CodeActionProvider {
17913    fn id(&self) -> Arc<str>;
17914
17915    fn code_actions(
17916        &self,
17917        buffer: &Entity<Buffer>,
17918        range: Range<text::Anchor>,
17919        window: &mut Window,
17920        cx: &mut App,
17921    ) -> Task<Result<Vec<CodeAction>>>;
17922
17923    fn apply_code_action(
17924        &self,
17925        buffer_handle: Entity<Buffer>,
17926        action: CodeAction,
17927        excerpt_id: ExcerptId,
17928        push_to_history: bool,
17929        window: &mut Window,
17930        cx: &mut App,
17931    ) -> Task<Result<ProjectTransaction>>;
17932}
17933
17934impl CodeActionProvider for Entity<Project> {
17935    fn id(&self) -> Arc<str> {
17936        "project".into()
17937    }
17938
17939    fn code_actions(
17940        &self,
17941        buffer: &Entity<Buffer>,
17942        range: Range<text::Anchor>,
17943        _window: &mut Window,
17944        cx: &mut App,
17945    ) -> Task<Result<Vec<CodeAction>>> {
17946        self.update(cx, |project, cx| {
17947            let code_lens = project.code_lens(buffer, range.clone(), cx);
17948            let code_actions = project.code_actions(buffer, range, None, cx);
17949            cx.background_spawn(async move {
17950                let (code_lens, code_actions) = join(code_lens, code_actions).await;
17951                Ok(code_lens
17952                    .context("code lens fetch")?
17953                    .into_iter()
17954                    .chain(code_actions.context("code action fetch")?)
17955                    .collect())
17956            })
17957        })
17958    }
17959
17960    fn apply_code_action(
17961        &self,
17962        buffer_handle: Entity<Buffer>,
17963        action: CodeAction,
17964        _excerpt_id: ExcerptId,
17965        push_to_history: bool,
17966        _window: &mut Window,
17967        cx: &mut App,
17968    ) -> Task<Result<ProjectTransaction>> {
17969        self.update(cx, |project, cx| {
17970            project.apply_code_action(buffer_handle, action, push_to_history, cx)
17971        })
17972    }
17973}
17974
17975fn snippet_completions(
17976    project: &Project,
17977    buffer: &Entity<Buffer>,
17978    buffer_position: text::Anchor,
17979    cx: &mut App,
17980) -> Task<Result<Vec<Completion>>> {
17981    let language = buffer.read(cx).language_at(buffer_position);
17982    let language_name = language.as_ref().map(|language| language.lsp_id());
17983    let snippet_store = project.snippets().read(cx);
17984    let snippets = snippet_store.snippets_for(language_name, cx);
17985
17986    if snippets.is_empty() {
17987        return Task::ready(Ok(vec![]));
17988    }
17989    let snapshot = buffer.read(cx).text_snapshot();
17990    let chars: String = snapshot
17991        .reversed_chars_for_range(text::Anchor::MIN..buffer_position)
17992        .collect();
17993
17994    let scope = language.map(|language| language.default_scope());
17995    let executor = cx.background_executor().clone();
17996
17997    cx.background_spawn(async move {
17998        let classifier = CharClassifier::new(scope).for_completion(true);
17999        let mut last_word = chars
18000            .chars()
18001            .take_while(|c| classifier.is_word(*c))
18002            .collect::<String>();
18003        last_word = last_word.chars().rev().collect();
18004
18005        if last_word.is_empty() {
18006            return Ok(vec![]);
18007        }
18008
18009        let as_offset = text::ToOffset::to_offset(&buffer_position, &snapshot);
18010        let to_lsp = |point: &text::Anchor| {
18011            let end = text::ToPointUtf16::to_point_utf16(point, &snapshot);
18012            point_to_lsp(end)
18013        };
18014        let lsp_end = to_lsp(&buffer_position);
18015
18016        let candidates = snippets
18017            .iter()
18018            .enumerate()
18019            .flat_map(|(ix, snippet)| {
18020                snippet
18021                    .prefix
18022                    .iter()
18023                    .map(move |prefix| StringMatchCandidate::new(ix, &prefix))
18024            })
18025            .collect::<Vec<StringMatchCandidate>>();
18026
18027        let mut matches = fuzzy::match_strings(
18028            &candidates,
18029            &last_word,
18030            last_word.chars().any(|c| c.is_uppercase()),
18031            100,
18032            &Default::default(),
18033            executor,
18034        )
18035        .await;
18036
18037        // Remove all candidates where the query's start does not match the start of any word in the candidate
18038        if let Some(query_start) = last_word.chars().next() {
18039            matches.retain(|string_match| {
18040                split_words(&string_match.string).any(|word| {
18041                    // Check that the first codepoint of the word as lowercase matches the first
18042                    // codepoint of the query as lowercase
18043                    word.chars()
18044                        .flat_map(|codepoint| codepoint.to_lowercase())
18045                        .zip(query_start.to_lowercase())
18046                        .all(|(word_cp, query_cp)| word_cp == query_cp)
18047                })
18048            });
18049        }
18050
18051        let matched_strings = matches
18052            .into_iter()
18053            .map(|m| m.string)
18054            .collect::<HashSet<_>>();
18055
18056        let result: Vec<Completion> = snippets
18057            .into_iter()
18058            .filter_map(|snippet| {
18059                let matching_prefix = snippet
18060                    .prefix
18061                    .iter()
18062                    .find(|prefix| matched_strings.contains(*prefix))?;
18063                let start = as_offset - last_word.len();
18064                let start = snapshot.anchor_before(start);
18065                let range = start..buffer_position;
18066                let lsp_start = to_lsp(&start);
18067                let lsp_range = lsp::Range {
18068                    start: lsp_start,
18069                    end: lsp_end,
18070                };
18071                Some(Completion {
18072                    old_range: range,
18073                    new_text: snippet.body.clone(),
18074                    source: CompletionSource::Lsp {
18075                        server_id: LanguageServerId(usize::MAX),
18076                        resolved: true,
18077                        lsp_completion: Box::new(lsp::CompletionItem {
18078                            label: snippet.prefix.first().unwrap().clone(),
18079                            kind: Some(CompletionItemKind::SNIPPET),
18080                            label_details: snippet.description.as_ref().map(|description| {
18081                                lsp::CompletionItemLabelDetails {
18082                                    detail: Some(description.clone()),
18083                                    description: None,
18084                                }
18085                            }),
18086                            insert_text_format: Some(InsertTextFormat::SNIPPET),
18087                            text_edit: Some(lsp::CompletionTextEdit::InsertAndReplace(
18088                                lsp::InsertReplaceEdit {
18089                                    new_text: snippet.body.clone(),
18090                                    insert: lsp_range,
18091                                    replace: lsp_range,
18092                                },
18093                            )),
18094                            filter_text: Some(snippet.body.clone()),
18095                            sort_text: Some(char::MAX.to_string()),
18096                            ..lsp::CompletionItem::default()
18097                        }),
18098                        lsp_defaults: None,
18099                    },
18100                    label: CodeLabel {
18101                        text: matching_prefix.clone(),
18102                        runs: Vec::new(),
18103                        filter_range: 0..matching_prefix.len(),
18104                    },
18105                    documentation: snippet
18106                        .description
18107                        .clone()
18108                        .map(|description| CompletionDocumentation::SingleLine(description.into())),
18109                    confirm: None,
18110                })
18111            })
18112            .collect();
18113
18114        Ok(result)
18115    })
18116}
18117
18118impl CompletionProvider for Entity<Project> {
18119    fn completions(
18120        &self,
18121        buffer: &Entity<Buffer>,
18122        buffer_position: text::Anchor,
18123        options: CompletionContext,
18124        _window: &mut Window,
18125        cx: &mut Context<Editor>,
18126    ) -> Task<Result<Option<Vec<Completion>>>> {
18127        self.update(cx, |project, cx| {
18128            let snippets = snippet_completions(project, buffer, buffer_position, cx);
18129            let project_completions = project.completions(buffer, buffer_position, options, cx);
18130            cx.background_spawn(async move {
18131                let snippets_completions = snippets.await?;
18132                match project_completions.await? {
18133                    Some(mut completions) => {
18134                        completions.extend(snippets_completions);
18135                        Ok(Some(completions))
18136                    }
18137                    None => {
18138                        if snippets_completions.is_empty() {
18139                            Ok(None)
18140                        } else {
18141                            Ok(Some(snippets_completions))
18142                        }
18143                    }
18144                }
18145            })
18146        })
18147    }
18148
18149    fn resolve_completions(
18150        &self,
18151        buffer: Entity<Buffer>,
18152        completion_indices: Vec<usize>,
18153        completions: Rc<RefCell<Box<[Completion]>>>,
18154        cx: &mut Context<Editor>,
18155    ) -> Task<Result<bool>> {
18156        self.update(cx, |project, cx| {
18157            project.lsp_store().update(cx, |lsp_store, cx| {
18158                lsp_store.resolve_completions(buffer, completion_indices, completions, cx)
18159            })
18160        })
18161    }
18162
18163    fn apply_additional_edits_for_completion(
18164        &self,
18165        buffer: Entity<Buffer>,
18166        completions: Rc<RefCell<Box<[Completion]>>>,
18167        completion_index: usize,
18168        push_to_history: bool,
18169        cx: &mut Context<Editor>,
18170    ) -> Task<Result<Option<language::Transaction>>> {
18171        self.update(cx, |project, cx| {
18172            project.lsp_store().update(cx, |lsp_store, cx| {
18173                lsp_store.apply_additional_edits_for_completion(
18174                    buffer,
18175                    completions,
18176                    completion_index,
18177                    push_to_history,
18178                    cx,
18179                )
18180            })
18181        })
18182    }
18183
18184    fn is_completion_trigger(
18185        &self,
18186        buffer: &Entity<Buffer>,
18187        position: language::Anchor,
18188        text: &str,
18189        trigger_in_words: bool,
18190        cx: &mut Context<Editor>,
18191    ) -> bool {
18192        let mut chars = text.chars();
18193        let char = if let Some(char) = chars.next() {
18194            char
18195        } else {
18196            return false;
18197        };
18198        if chars.next().is_some() {
18199            return false;
18200        }
18201
18202        let buffer = buffer.read(cx);
18203        let snapshot = buffer.snapshot();
18204        if !snapshot.settings_at(position, cx).show_completions_on_input {
18205            return false;
18206        }
18207        let classifier = snapshot.char_classifier_at(position).for_completion(true);
18208        if trigger_in_words && classifier.is_word(char) {
18209            return true;
18210        }
18211
18212        buffer.completion_triggers().contains(text)
18213    }
18214}
18215
18216impl SemanticsProvider for Entity<Project> {
18217    fn hover(
18218        &self,
18219        buffer: &Entity<Buffer>,
18220        position: text::Anchor,
18221        cx: &mut App,
18222    ) -> Option<Task<Vec<project::Hover>>> {
18223        Some(self.update(cx, |project, cx| project.hover(buffer, position, cx)))
18224    }
18225
18226    fn document_highlights(
18227        &self,
18228        buffer: &Entity<Buffer>,
18229        position: text::Anchor,
18230        cx: &mut App,
18231    ) -> Option<Task<Result<Vec<DocumentHighlight>>>> {
18232        Some(self.update(cx, |project, cx| {
18233            project.document_highlights(buffer, position, cx)
18234        }))
18235    }
18236
18237    fn definitions(
18238        &self,
18239        buffer: &Entity<Buffer>,
18240        position: text::Anchor,
18241        kind: GotoDefinitionKind,
18242        cx: &mut App,
18243    ) -> Option<Task<Result<Vec<LocationLink>>>> {
18244        Some(self.update(cx, |project, cx| match kind {
18245            GotoDefinitionKind::Symbol => project.definition(&buffer, position, cx),
18246            GotoDefinitionKind::Declaration => project.declaration(&buffer, position, cx),
18247            GotoDefinitionKind::Type => project.type_definition(&buffer, position, cx),
18248            GotoDefinitionKind::Implementation => project.implementation(&buffer, position, cx),
18249        }))
18250    }
18251
18252    fn supports_inlay_hints(&self, buffer: &Entity<Buffer>, cx: &mut App) -> bool {
18253        // TODO: make this work for remote projects
18254        self.update(cx, |this, cx| {
18255            buffer.update(cx, |buffer, cx| {
18256                this.any_language_server_supports_inlay_hints(buffer, cx)
18257            })
18258        })
18259    }
18260
18261    fn inlay_hints(
18262        &self,
18263        buffer_handle: Entity<Buffer>,
18264        range: Range<text::Anchor>,
18265        cx: &mut App,
18266    ) -> Option<Task<anyhow::Result<Vec<InlayHint>>>> {
18267        Some(self.update(cx, |project, cx| {
18268            project.inlay_hints(buffer_handle, range, cx)
18269        }))
18270    }
18271
18272    fn resolve_inlay_hint(
18273        &self,
18274        hint: InlayHint,
18275        buffer_handle: Entity<Buffer>,
18276        server_id: LanguageServerId,
18277        cx: &mut App,
18278    ) -> Option<Task<anyhow::Result<InlayHint>>> {
18279        Some(self.update(cx, |project, cx| {
18280            project.resolve_inlay_hint(hint, buffer_handle, server_id, cx)
18281        }))
18282    }
18283
18284    fn range_for_rename(
18285        &self,
18286        buffer: &Entity<Buffer>,
18287        position: text::Anchor,
18288        cx: &mut App,
18289    ) -> Option<Task<Result<Option<Range<text::Anchor>>>>> {
18290        Some(self.update(cx, |project, cx| {
18291            let buffer = buffer.clone();
18292            let task = project.prepare_rename(buffer.clone(), position, cx);
18293            cx.spawn(async move |_, cx| {
18294                Ok(match task.await? {
18295                    PrepareRenameResponse::Success(range) => Some(range),
18296                    PrepareRenameResponse::InvalidPosition => None,
18297                    PrepareRenameResponse::OnlyUnpreparedRenameSupported => {
18298                        // Fallback on using TreeSitter info to determine identifier range
18299                        buffer.update(cx, |buffer, _| {
18300                            let snapshot = buffer.snapshot();
18301                            let (range, kind) = snapshot.surrounding_word(position);
18302                            if kind != Some(CharKind::Word) {
18303                                return None;
18304                            }
18305                            Some(
18306                                snapshot.anchor_before(range.start)
18307                                    ..snapshot.anchor_after(range.end),
18308                            )
18309                        })?
18310                    }
18311                })
18312            })
18313        }))
18314    }
18315
18316    fn perform_rename(
18317        &self,
18318        buffer: &Entity<Buffer>,
18319        position: text::Anchor,
18320        new_name: String,
18321        cx: &mut App,
18322    ) -> Option<Task<Result<ProjectTransaction>>> {
18323        Some(self.update(cx, |project, cx| {
18324            project.perform_rename(buffer.clone(), position, new_name, cx)
18325        }))
18326    }
18327}
18328
18329fn inlay_hint_settings(
18330    location: Anchor,
18331    snapshot: &MultiBufferSnapshot,
18332    cx: &mut Context<Editor>,
18333) -> InlayHintSettings {
18334    let file = snapshot.file_at(location);
18335    let language = snapshot.language_at(location).map(|l| l.name());
18336    language_settings(language, file, cx).inlay_hints
18337}
18338
18339fn consume_contiguous_rows(
18340    contiguous_row_selections: &mut Vec<Selection<Point>>,
18341    selection: &Selection<Point>,
18342    display_map: &DisplaySnapshot,
18343    selections: &mut Peekable<std::slice::Iter<Selection<Point>>>,
18344) -> (MultiBufferRow, MultiBufferRow) {
18345    contiguous_row_selections.push(selection.clone());
18346    let start_row = MultiBufferRow(selection.start.row);
18347    let mut end_row = ending_row(selection, display_map);
18348
18349    while let Some(next_selection) = selections.peek() {
18350        if next_selection.start.row <= end_row.0 {
18351            end_row = ending_row(next_selection, display_map);
18352            contiguous_row_selections.push(selections.next().unwrap().clone());
18353        } else {
18354            break;
18355        }
18356    }
18357    (start_row, end_row)
18358}
18359
18360fn ending_row(next_selection: &Selection<Point>, display_map: &DisplaySnapshot) -> MultiBufferRow {
18361    if next_selection.end.column > 0 || next_selection.is_empty() {
18362        MultiBufferRow(display_map.next_line_boundary(next_selection.end).0.row + 1)
18363    } else {
18364        MultiBufferRow(next_selection.end.row)
18365    }
18366}
18367
18368impl EditorSnapshot {
18369    pub fn remote_selections_in_range<'a>(
18370        &'a self,
18371        range: &'a Range<Anchor>,
18372        collaboration_hub: &dyn CollaborationHub,
18373        cx: &'a App,
18374    ) -> impl 'a + Iterator<Item = RemoteSelection> {
18375        let participant_names = collaboration_hub.user_names(cx);
18376        let participant_indices = collaboration_hub.user_participant_indices(cx);
18377        let collaborators_by_peer_id = collaboration_hub.collaborators(cx);
18378        let collaborators_by_replica_id = collaborators_by_peer_id
18379            .iter()
18380            .map(|(_, collaborator)| (collaborator.replica_id, collaborator))
18381            .collect::<HashMap<_, _>>();
18382        self.buffer_snapshot
18383            .selections_in_range(range, false)
18384            .filter_map(move |(replica_id, line_mode, cursor_shape, selection)| {
18385                let collaborator = collaborators_by_replica_id.get(&replica_id)?;
18386                let participant_index = participant_indices.get(&collaborator.user_id).copied();
18387                let user_name = participant_names.get(&collaborator.user_id).cloned();
18388                Some(RemoteSelection {
18389                    replica_id,
18390                    selection,
18391                    cursor_shape,
18392                    line_mode,
18393                    participant_index,
18394                    peer_id: collaborator.peer_id,
18395                    user_name,
18396                })
18397            })
18398    }
18399
18400    pub fn hunks_for_ranges(
18401        &self,
18402        ranges: impl IntoIterator<Item = Range<Point>>,
18403    ) -> Vec<MultiBufferDiffHunk> {
18404        let mut hunks = Vec::new();
18405        let mut processed_buffer_rows: HashMap<BufferId, HashSet<Range<text::Anchor>>> =
18406            HashMap::default();
18407        for query_range in ranges {
18408            let query_rows =
18409                MultiBufferRow(query_range.start.row)..MultiBufferRow(query_range.end.row + 1);
18410            for hunk in self.buffer_snapshot.diff_hunks_in_range(
18411                Point::new(query_rows.start.0, 0)..Point::new(query_rows.end.0, 0),
18412            ) {
18413                // Include deleted hunks that are adjacent to the query range, because
18414                // otherwise they would be missed.
18415                let mut intersects_range = hunk.row_range.overlaps(&query_rows);
18416                if hunk.status().is_deleted() {
18417                    intersects_range |= hunk.row_range.start == query_rows.end;
18418                    intersects_range |= hunk.row_range.end == query_rows.start;
18419                }
18420                if intersects_range {
18421                    if !processed_buffer_rows
18422                        .entry(hunk.buffer_id)
18423                        .or_default()
18424                        .insert(hunk.buffer_range.start..hunk.buffer_range.end)
18425                    {
18426                        continue;
18427                    }
18428                    hunks.push(hunk);
18429                }
18430            }
18431        }
18432
18433        hunks
18434    }
18435
18436    fn display_diff_hunks_for_rows<'a>(
18437        &'a self,
18438        display_rows: Range<DisplayRow>,
18439        folded_buffers: &'a HashSet<BufferId>,
18440    ) -> impl 'a + Iterator<Item = DisplayDiffHunk> {
18441        let buffer_start = DisplayPoint::new(display_rows.start, 0).to_point(self);
18442        let buffer_end = DisplayPoint::new(display_rows.end, 0).to_point(self);
18443
18444        self.buffer_snapshot
18445            .diff_hunks_in_range(buffer_start..buffer_end)
18446            .filter_map(|hunk| {
18447                if folded_buffers.contains(&hunk.buffer_id) {
18448                    return None;
18449                }
18450
18451                let hunk_start_point = Point::new(hunk.row_range.start.0, 0);
18452                let hunk_end_point = Point::new(hunk.row_range.end.0, 0);
18453
18454                let hunk_display_start = self.point_to_display_point(hunk_start_point, Bias::Left);
18455                let hunk_display_end = self.point_to_display_point(hunk_end_point, Bias::Right);
18456
18457                let display_hunk = if hunk_display_start.column() != 0 {
18458                    DisplayDiffHunk::Folded {
18459                        display_row: hunk_display_start.row(),
18460                    }
18461                } else {
18462                    let mut end_row = hunk_display_end.row();
18463                    if hunk_display_end.column() > 0 {
18464                        end_row.0 += 1;
18465                    }
18466                    let is_created_file = hunk.is_created_file();
18467                    DisplayDiffHunk::Unfolded {
18468                        status: hunk.status(),
18469                        diff_base_byte_range: hunk.diff_base_byte_range,
18470                        display_row_range: hunk_display_start.row()..end_row,
18471                        multi_buffer_range: Anchor::range_in_buffer(
18472                            hunk.excerpt_id,
18473                            hunk.buffer_id,
18474                            hunk.buffer_range,
18475                        ),
18476                        is_created_file,
18477                    }
18478                };
18479
18480                Some(display_hunk)
18481            })
18482    }
18483
18484    pub fn language_at<T: ToOffset>(&self, position: T) -> Option<&Arc<Language>> {
18485        self.display_snapshot.buffer_snapshot.language_at(position)
18486    }
18487
18488    pub fn is_focused(&self) -> bool {
18489        self.is_focused
18490    }
18491
18492    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
18493        self.placeholder_text.as_ref()
18494    }
18495
18496    pub fn scroll_position(&self) -> gpui::Point<f32> {
18497        self.scroll_anchor.scroll_position(&self.display_snapshot)
18498    }
18499
18500    fn gutter_dimensions(
18501        &self,
18502        font_id: FontId,
18503        font_size: Pixels,
18504        max_line_number_width: Pixels,
18505        cx: &App,
18506    ) -> Option<GutterDimensions> {
18507        if !self.show_gutter {
18508            return None;
18509        }
18510
18511        let descent = cx.text_system().descent(font_id, font_size);
18512        let em_width = cx.text_system().em_width(font_id, font_size).log_err()?;
18513        let em_advance = cx.text_system().em_advance(font_id, font_size).log_err()?;
18514
18515        let show_git_gutter = self.show_git_diff_gutter.unwrap_or_else(|| {
18516            matches!(
18517                ProjectSettings::get_global(cx).git.git_gutter,
18518                Some(GitGutterSetting::TrackedFiles)
18519            )
18520        });
18521        let gutter_settings = EditorSettings::get_global(cx).gutter;
18522        let show_line_numbers = self
18523            .show_line_numbers
18524            .unwrap_or(gutter_settings.line_numbers);
18525        let line_gutter_width = if show_line_numbers {
18526            // Avoid flicker-like gutter resizes when the line number gains another digit and only resize the gutter on files with N*10^5 lines.
18527            let min_width_for_number_on_gutter = em_advance * MIN_LINE_NUMBER_DIGITS as f32;
18528            max_line_number_width.max(min_width_for_number_on_gutter)
18529        } else {
18530            0.0.into()
18531        };
18532
18533        let show_code_actions = self
18534            .show_code_actions
18535            .unwrap_or(gutter_settings.code_actions);
18536
18537        let show_runnables = self.show_runnables.unwrap_or(gutter_settings.runnables);
18538        let show_breakpoints = self.show_breakpoints.unwrap_or(gutter_settings.breakpoints);
18539
18540        let git_blame_entries_width =
18541            self.git_blame_gutter_max_author_length
18542                .map(|max_author_length| {
18543                    const MAX_RELATIVE_TIMESTAMP: &str = "60 minutes ago";
18544
18545                    /// The number of characters to dedicate to gaps and margins.
18546                    const SPACING_WIDTH: usize = 4;
18547
18548                    let max_char_count = max_author_length
18549                        .min(GIT_BLAME_MAX_AUTHOR_CHARS_DISPLAYED)
18550                        + ::git::SHORT_SHA_LENGTH
18551                        + MAX_RELATIVE_TIMESTAMP.len()
18552                        + SPACING_WIDTH;
18553
18554                    em_advance * max_char_count
18555                });
18556
18557        let is_singleton = self.buffer_snapshot.is_singleton();
18558
18559        let mut left_padding = git_blame_entries_width.unwrap_or(Pixels::ZERO);
18560        left_padding += if !is_singleton {
18561            em_width * 4.0
18562        } else if show_code_actions || show_runnables || show_breakpoints {
18563            em_width * 3.0
18564        } else if show_git_gutter && show_line_numbers {
18565            em_width * 2.0
18566        } else if show_git_gutter || show_line_numbers {
18567            em_width
18568        } else {
18569            px(0.)
18570        };
18571
18572        let shows_folds = is_singleton && gutter_settings.folds;
18573
18574        let right_padding = if shows_folds && show_line_numbers {
18575            em_width * 4.0
18576        } else if shows_folds || (!is_singleton && show_line_numbers) {
18577            em_width * 3.0
18578        } else if show_line_numbers {
18579            em_width
18580        } else {
18581            px(0.)
18582        };
18583
18584        Some(GutterDimensions {
18585            left_padding,
18586            right_padding,
18587            width: line_gutter_width + left_padding + right_padding,
18588            margin: -descent,
18589            git_blame_entries_width,
18590        })
18591    }
18592
18593    pub fn render_crease_toggle(
18594        &self,
18595        buffer_row: MultiBufferRow,
18596        row_contains_cursor: bool,
18597        editor: Entity<Editor>,
18598        window: &mut Window,
18599        cx: &mut App,
18600    ) -> Option<AnyElement> {
18601        let folded = self.is_line_folded(buffer_row);
18602        let mut is_foldable = false;
18603
18604        if let Some(crease) = self
18605            .crease_snapshot
18606            .query_row(buffer_row, &self.buffer_snapshot)
18607        {
18608            is_foldable = true;
18609            match crease {
18610                Crease::Inline { render_toggle, .. } | Crease::Block { render_toggle, .. } => {
18611                    if let Some(render_toggle) = render_toggle {
18612                        let toggle_callback =
18613                            Arc::new(move |folded, window: &mut Window, cx: &mut App| {
18614                                if folded {
18615                                    editor.update(cx, |editor, cx| {
18616                                        editor.fold_at(&crate::FoldAt { buffer_row }, window, cx)
18617                                    });
18618                                } else {
18619                                    editor.update(cx, |editor, cx| {
18620                                        editor.unfold_at(
18621                                            &crate::UnfoldAt { buffer_row },
18622                                            window,
18623                                            cx,
18624                                        )
18625                                    });
18626                                }
18627                            });
18628                        return Some((render_toggle)(
18629                            buffer_row,
18630                            folded,
18631                            toggle_callback,
18632                            window,
18633                            cx,
18634                        ));
18635                    }
18636                }
18637            }
18638        }
18639
18640        is_foldable |= self.starts_indent(buffer_row);
18641
18642        if folded || (is_foldable && (row_contains_cursor || self.gutter_hovered)) {
18643            Some(
18644                Disclosure::new(("gutter_crease", buffer_row.0), !folded)
18645                    .toggle_state(folded)
18646                    .on_click(window.listener_for(&editor, move |this, _e, window, cx| {
18647                        if folded {
18648                            this.unfold_at(&UnfoldAt { buffer_row }, window, cx);
18649                        } else {
18650                            this.fold_at(&FoldAt { buffer_row }, window, cx);
18651                        }
18652                    }))
18653                    .into_any_element(),
18654            )
18655        } else {
18656            None
18657        }
18658    }
18659
18660    pub fn render_crease_trailer(
18661        &self,
18662        buffer_row: MultiBufferRow,
18663        window: &mut Window,
18664        cx: &mut App,
18665    ) -> Option<AnyElement> {
18666        let folded = self.is_line_folded(buffer_row);
18667        if let Crease::Inline { render_trailer, .. } = self
18668            .crease_snapshot
18669            .query_row(buffer_row, &self.buffer_snapshot)?
18670        {
18671            let render_trailer = render_trailer.as_ref()?;
18672            Some(render_trailer(buffer_row, folded, window, cx))
18673        } else {
18674            None
18675        }
18676    }
18677}
18678
18679impl Deref for EditorSnapshot {
18680    type Target = DisplaySnapshot;
18681
18682    fn deref(&self) -> &Self::Target {
18683        &self.display_snapshot
18684    }
18685}
18686
18687#[derive(Clone, Debug, PartialEq, Eq)]
18688pub enum EditorEvent {
18689    InputIgnored {
18690        text: Arc<str>,
18691    },
18692    InputHandled {
18693        utf16_range_to_replace: Option<Range<isize>>,
18694        text: Arc<str>,
18695    },
18696    ExcerptsAdded {
18697        buffer: Entity<Buffer>,
18698        predecessor: ExcerptId,
18699        excerpts: Vec<(ExcerptId, ExcerptRange<language::Anchor>)>,
18700    },
18701    ExcerptsRemoved {
18702        ids: Vec<ExcerptId>,
18703    },
18704    BufferFoldToggled {
18705        ids: Vec<ExcerptId>,
18706        folded: bool,
18707    },
18708    ExcerptsEdited {
18709        ids: Vec<ExcerptId>,
18710    },
18711    ExcerptsExpanded {
18712        ids: Vec<ExcerptId>,
18713    },
18714    BufferEdited,
18715    Edited {
18716        transaction_id: clock::Lamport,
18717    },
18718    Reparsed(BufferId),
18719    Focused,
18720    FocusedIn,
18721    Blurred,
18722    DirtyChanged,
18723    Saved,
18724    TitleChanged,
18725    DiffBaseChanged,
18726    SelectionsChanged {
18727        local: bool,
18728    },
18729    ScrollPositionChanged {
18730        local: bool,
18731        autoscroll: bool,
18732    },
18733    Closed,
18734    TransactionUndone {
18735        transaction_id: clock::Lamport,
18736    },
18737    TransactionBegun {
18738        transaction_id: clock::Lamport,
18739    },
18740    Reloaded,
18741    CursorShapeChanged,
18742    PushedToNavHistory {
18743        anchor: Anchor,
18744        is_deactivate: bool,
18745    },
18746}
18747
18748impl EventEmitter<EditorEvent> for Editor {}
18749
18750impl Focusable for Editor {
18751    fn focus_handle(&self, _cx: &App) -> FocusHandle {
18752        self.focus_handle.clone()
18753    }
18754}
18755
18756impl Render for Editor {
18757    fn render(&mut self, _: &mut Window, cx: &mut Context<'_, Self>) -> impl IntoElement {
18758        let settings = ThemeSettings::get_global(cx);
18759
18760        let mut text_style = match self.mode {
18761            EditorMode::SingleLine { .. } | EditorMode::AutoHeight { .. } => TextStyle {
18762                color: cx.theme().colors().editor_foreground,
18763                font_family: settings.ui_font.family.clone(),
18764                font_features: settings.ui_font.features.clone(),
18765                font_fallbacks: settings.ui_font.fallbacks.clone(),
18766                font_size: rems(0.875).into(),
18767                font_weight: settings.ui_font.weight,
18768                line_height: relative(settings.buffer_line_height.value()),
18769                ..Default::default()
18770            },
18771            EditorMode::Full => TextStyle {
18772                color: cx.theme().colors().editor_foreground,
18773                font_family: settings.buffer_font.family.clone(),
18774                font_features: settings.buffer_font.features.clone(),
18775                font_fallbacks: settings.buffer_font.fallbacks.clone(),
18776                font_size: settings.buffer_font_size(cx).into(),
18777                font_weight: settings.buffer_font.weight,
18778                line_height: relative(settings.buffer_line_height.value()),
18779                ..Default::default()
18780            },
18781        };
18782        if let Some(text_style_refinement) = &self.text_style_refinement {
18783            text_style.refine(text_style_refinement)
18784        }
18785
18786        let background = match self.mode {
18787            EditorMode::SingleLine { .. } => cx.theme().system().transparent,
18788            EditorMode::AutoHeight { max_lines: _ } => cx.theme().system().transparent,
18789            EditorMode::Full => cx.theme().colors().editor_background,
18790        };
18791
18792        EditorElement::new(
18793            &cx.entity(),
18794            EditorStyle {
18795                background,
18796                local_player: cx.theme().players().local(),
18797                text: text_style,
18798                scrollbar_width: EditorElement::SCROLLBAR_WIDTH,
18799                syntax: cx.theme().syntax().clone(),
18800                status: cx.theme().status().clone(),
18801                inlay_hints_style: make_inlay_hints_style(cx),
18802                inline_completion_styles: make_suggestion_styles(cx),
18803                unnecessary_code_fade: ThemeSettings::get_global(cx).unnecessary_code_fade,
18804            },
18805        )
18806    }
18807}
18808
18809impl EntityInputHandler for Editor {
18810    fn text_for_range(
18811        &mut self,
18812        range_utf16: Range<usize>,
18813        adjusted_range: &mut Option<Range<usize>>,
18814        _: &mut Window,
18815        cx: &mut Context<Self>,
18816    ) -> Option<String> {
18817        let snapshot = self.buffer.read(cx).read(cx);
18818        let start = snapshot.clip_offset_utf16(OffsetUtf16(range_utf16.start), Bias::Left);
18819        let end = snapshot.clip_offset_utf16(OffsetUtf16(range_utf16.end), Bias::Right);
18820        if (start.0..end.0) != range_utf16 {
18821            adjusted_range.replace(start.0..end.0);
18822        }
18823        Some(snapshot.text_for_range(start..end).collect())
18824    }
18825
18826    fn selected_text_range(
18827        &mut self,
18828        ignore_disabled_input: bool,
18829        _: &mut Window,
18830        cx: &mut Context<Self>,
18831    ) -> Option<UTF16Selection> {
18832        // Prevent the IME menu from appearing when holding down an alphabetic key
18833        // while input is disabled.
18834        if !ignore_disabled_input && !self.input_enabled {
18835            return None;
18836        }
18837
18838        let selection = self.selections.newest::<OffsetUtf16>(cx);
18839        let range = selection.range();
18840
18841        Some(UTF16Selection {
18842            range: range.start.0..range.end.0,
18843            reversed: selection.reversed,
18844        })
18845    }
18846
18847    fn marked_text_range(&self, _: &mut Window, cx: &mut Context<Self>) -> Option<Range<usize>> {
18848        let snapshot = self.buffer.read(cx).read(cx);
18849        let range = self.text_highlights::<InputComposition>(cx)?.1.first()?;
18850        Some(range.start.to_offset_utf16(&snapshot).0..range.end.to_offset_utf16(&snapshot).0)
18851    }
18852
18853    fn unmark_text(&mut self, _: &mut Window, cx: &mut Context<Self>) {
18854        self.clear_highlights::<InputComposition>(cx);
18855        self.ime_transaction.take();
18856    }
18857
18858    fn replace_text_in_range(
18859        &mut self,
18860        range_utf16: Option<Range<usize>>,
18861        text: &str,
18862        window: &mut Window,
18863        cx: &mut Context<Self>,
18864    ) {
18865        if !self.input_enabled {
18866            cx.emit(EditorEvent::InputIgnored { text: text.into() });
18867            return;
18868        }
18869
18870        self.transact(window, cx, |this, window, cx| {
18871            let new_selected_ranges = if let Some(range_utf16) = range_utf16 {
18872                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
18873                Some(this.selection_replacement_ranges(range_utf16, cx))
18874            } else {
18875                this.marked_text_ranges(cx)
18876            };
18877
18878            let range_to_replace = new_selected_ranges.as_ref().and_then(|ranges_to_replace| {
18879                let newest_selection_id = this.selections.newest_anchor().id;
18880                this.selections
18881                    .all::<OffsetUtf16>(cx)
18882                    .iter()
18883                    .zip(ranges_to_replace.iter())
18884                    .find_map(|(selection, range)| {
18885                        if selection.id == newest_selection_id {
18886                            Some(
18887                                (range.start.0 as isize - selection.head().0 as isize)
18888                                    ..(range.end.0 as isize - selection.head().0 as isize),
18889                            )
18890                        } else {
18891                            None
18892                        }
18893                    })
18894            });
18895
18896            cx.emit(EditorEvent::InputHandled {
18897                utf16_range_to_replace: range_to_replace,
18898                text: text.into(),
18899            });
18900
18901            if let Some(new_selected_ranges) = new_selected_ranges {
18902                this.change_selections(None, window, cx, |selections| {
18903                    selections.select_ranges(new_selected_ranges)
18904                });
18905                this.backspace(&Default::default(), window, cx);
18906            }
18907
18908            this.handle_input(text, window, cx);
18909        });
18910
18911        if let Some(transaction) = self.ime_transaction {
18912            self.buffer.update(cx, |buffer, cx| {
18913                buffer.group_until_transaction(transaction, cx);
18914            });
18915        }
18916
18917        self.unmark_text(window, cx);
18918    }
18919
18920    fn replace_and_mark_text_in_range(
18921        &mut self,
18922        range_utf16: Option<Range<usize>>,
18923        text: &str,
18924        new_selected_range_utf16: Option<Range<usize>>,
18925        window: &mut Window,
18926        cx: &mut Context<Self>,
18927    ) {
18928        if !self.input_enabled {
18929            return;
18930        }
18931
18932        let transaction = self.transact(window, cx, |this, window, cx| {
18933            let ranges_to_replace = if let Some(mut marked_ranges) = this.marked_text_ranges(cx) {
18934                let snapshot = this.buffer.read(cx).read(cx);
18935                if let Some(relative_range_utf16) = range_utf16.as_ref() {
18936                    for marked_range in &mut marked_ranges {
18937                        marked_range.end.0 = marked_range.start.0 + relative_range_utf16.end;
18938                        marked_range.start.0 += relative_range_utf16.start;
18939                        marked_range.start =
18940                            snapshot.clip_offset_utf16(marked_range.start, Bias::Left);
18941                        marked_range.end =
18942                            snapshot.clip_offset_utf16(marked_range.end, Bias::Right);
18943                    }
18944                }
18945                Some(marked_ranges)
18946            } else if let Some(range_utf16) = range_utf16 {
18947                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
18948                Some(this.selection_replacement_ranges(range_utf16, cx))
18949            } else {
18950                None
18951            };
18952
18953            let range_to_replace = ranges_to_replace.as_ref().and_then(|ranges_to_replace| {
18954                let newest_selection_id = this.selections.newest_anchor().id;
18955                this.selections
18956                    .all::<OffsetUtf16>(cx)
18957                    .iter()
18958                    .zip(ranges_to_replace.iter())
18959                    .find_map(|(selection, range)| {
18960                        if selection.id == newest_selection_id {
18961                            Some(
18962                                (range.start.0 as isize - selection.head().0 as isize)
18963                                    ..(range.end.0 as isize - selection.head().0 as isize),
18964                            )
18965                        } else {
18966                            None
18967                        }
18968                    })
18969            });
18970
18971            cx.emit(EditorEvent::InputHandled {
18972                utf16_range_to_replace: range_to_replace,
18973                text: text.into(),
18974            });
18975
18976            if let Some(ranges) = ranges_to_replace {
18977                this.change_selections(None, window, cx, |s| s.select_ranges(ranges));
18978            }
18979
18980            let marked_ranges = {
18981                let snapshot = this.buffer.read(cx).read(cx);
18982                this.selections
18983                    .disjoint_anchors()
18984                    .iter()
18985                    .map(|selection| {
18986                        selection.start.bias_left(&snapshot)..selection.end.bias_right(&snapshot)
18987                    })
18988                    .collect::<Vec<_>>()
18989            };
18990
18991            if text.is_empty() {
18992                this.unmark_text(window, cx);
18993            } else {
18994                this.highlight_text::<InputComposition>(
18995                    marked_ranges.clone(),
18996                    HighlightStyle {
18997                        underline: Some(UnderlineStyle {
18998                            thickness: px(1.),
18999                            color: None,
19000                            wavy: false,
19001                        }),
19002                        ..Default::default()
19003                    },
19004                    cx,
19005                );
19006            }
19007
19008            // Disable auto-closing when composing text (i.e. typing a `"` on a Brazilian keyboard)
19009            let use_autoclose = this.use_autoclose;
19010            let use_auto_surround = this.use_auto_surround;
19011            this.set_use_autoclose(false);
19012            this.set_use_auto_surround(false);
19013            this.handle_input(text, window, cx);
19014            this.set_use_autoclose(use_autoclose);
19015            this.set_use_auto_surround(use_auto_surround);
19016
19017            if let Some(new_selected_range) = new_selected_range_utf16 {
19018                let snapshot = this.buffer.read(cx).read(cx);
19019                let new_selected_ranges = marked_ranges
19020                    .into_iter()
19021                    .map(|marked_range| {
19022                        let insertion_start = marked_range.start.to_offset_utf16(&snapshot).0;
19023                        let new_start = OffsetUtf16(new_selected_range.start + insertion_start);
19024                        let new_end = OffsetUtf16(new_selected_range.end + insertion_start);
19025                        snapshot.clip_offset_utf16(new_start, Bias::Left)
19026                            ..snapshot.clip_offset_utf16(new_end, Bias::Right)
19027                    })
19028                    .collect::<Vec<_>>();
19029
19030                drop(snapshot);
19031                this.change_selections(None, window, cx, |selections| {
19032                    selections.select_ranges(new_selected_ranges)
19033                });
19034            }
19035        });
19036
19037        self.ime_transaction = self.ime_transaction.or(transaction);
19038        if let Some(transaction) = self.ime_transaction {
19039            self.buffer.update(cx, |buffer, cx| {
19040                buffer.group_until_transaction(transaction, cx);
19041            });
19042        }
19043
19044        if self.text_highlights::<InputComposition>(cx).is_none() {
19045            self.ime_transaction.take();
19046        }
19047    }
19048
19049    fn bounds_for_range(
19050        &mut self,
19051        range_utf16: Range<usize>,
19052        element_bounds: gpui::Bounds<Pixels>,
19053        window: &mut Window,
19054        cx: &mut Context<Self>,
19055    ) -> Option<gpui::Bounds<Pixels>> {
19056        let text_layout_details = self.text_layout_details(window);
19057        let gpui::Size {
19058            width: em_width,
19059            height: line_height,
19060        } = self.character_size(window);
19061
19062        let snapshot = self.snapshot(window, cx);
19063        let scroll_position = snapshot.scroll_position();
19064        let scroll_left = scroll_position.x * em_width;
19065
19066        let start = OffsetUtf16(range_utf16.start).to_display_point(&snapshot);
19067        let x = snapshot.x_for_display_point(start, &text_layout_details) - scroll_left
19068            + self.gutter_dimensions.width
19069            + self.gutter_dimensions.margin;
19070        let y = line_height * (start.row().as_f32() - scroll_position.y);
19071
19072        Some(Bounds {
19073            origin: element_bounds.origin + point(x, y),
19074            size: size(em_width, line_height),
19075        })
19076    }
19077
19078    fn character_index_for_point(
19079        &mut self,
19080        point: gpui::Point<Pixels>,
19081        _window: &mut Window,
19082        _cx: &mut Context<Self>,
19083    ) -> Option<usize> {
19084        let position_map = self.last_position_map.as_ref()?;
19085        if !position_map.text_hitbox.contains(&point) {
19086            return None;
19087        }
19088        let display_point = position_map.point_for_position(point).previous_valid;
19089        let anchor = position_map
19090            .snapshot
19091            .display_point_to_anchor(display_point, Bias::Left);
19092        let utf16_offset = anchor.to_offset_utf16(&position_map.snapshot.buffer_snapshot);
19093        Some(utf16_offset.0)
19094    }
19095}
19096
19097trait SelectionExt {
19098    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
19099    fn spanned_rows(
19100        &self,
19101        include_end_if_at_line_start: bool,
19102        map: &DisplaySnapshot,
19103    ) -> Range<MultiBufferRow>;
19104}
19105
19106impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
19107    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
19108        let start = self
19109            .start
19110            .to_point(&map.buffer_snapshot)
19111            .to_display_point(map);
19112        let end = self
19113            .end
19114            .to_point(&map.buffer_snapshot)
19115            .to_display_point(map);
19116        if self.reversed {
19117            end..start
19118        } else {
19119            start..end
19120        }
19121    }
19122
19123    fn spanned_rows(
19124        &self,
19125        include_end_if_at_line_start: bool,
19126        map: &DisplaySnapshot,
19127    ) -> Range<MultiBufferRow> {
19128        let start = self.start.to_point(&map.buffer_snapshot);
19129        let mut end = self.end.to_point(&map.buffer_snapshot);
19130        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
19131            end.row -= 1;
19132        }
19133
19134        let buffer_start = map.prev_line_boundary(start).0;
19135        let buffer_end = map.next_line_boundary(end).0;
19136        MultiBufferRow(buffer_start.row)..MultiBufferRow(buffer_end.row + 1)
19137    }
19138}
19139
19140impl<T: InvalidationRegion> InvalidationStack<T> {
19141    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
19142    where
19143        S: Clone + ToOffset,
19144    {
19145        while let Some(region) = self.last() {
19146            let all_selections_inside_invalidation_ranges =
19147                if selections.len() == region.ranges().len() {
19148                    selections
19149                        .iter()
19150                        .zip(region.ranges().iter().map(|r| r.to_offset(buffer)))
19151                        .all(|(selection, invalidation_range)| {
19152                            let head = selection.head().to_offset(buffer);
19153                            invalidation_range.start <= head && invalidation_range.end >= head
19154                        })
19155                } else {
19156                    false
19157                };
19158
19159            if all_selections_inside_invalidation_ranges {
19160                break;
19161            } else {
19162                self.pop();
19163            }
19164        }
19165    }
19166}
19167
19168impl<T> Default for InvalidationStack<T> {
19169    fn default() -> Self {
19170        Self(Default::default())
19171    }
19172}
19173
19174impl<T> Deref for InvalidationStack<T> {
19175    type Target = Vec<T>;
19176
19177    fn deref(&self) -> &Self::Target {
19178        &self.0
19179    }
19180}
19181
19182impl<T> DerefMut for InvalidationStack<T> {
19183    fn deref_mut(&mut self) -> &mut Self::Target {
19184        &mut self.0
19185    }
19186}
19187
19188impl InvalidationRegion for SnippetState {
19189    fn ranges(&self) -> &[Range<Anchor>] {
19190        &self.ranges[self.active_index]
19191    }
19192}
19193
19194pub fn diagnostic_block_renderer(
19195    diagnostic: Diagnostic,
19196    max_message_rows: Option<u8>,
19197    allow_closing: bool,
19198) -> RenderBlock {
19199    let (text_without_backticks, code_ranges) =
19200        highlight_diagnostic_message(&diagnostic, max_message_rows);
19201
19202    Arc::new(move |cx: &mut BlockContext| {
19203        let group_id: SharedString = cx.block_id.to_string().into();
19204
19205        let mut text_style = cx.window.text_style().clone();
19206        text_style.color = diagnostic_style(diagnostic.severity, cx.theme().status());
19207        let theme_settings = ThemeSettings::get_global(cx);
19208        text_style.font_family = theme_settings.buffer_font.family.clone();
19209        text_style.font_style = theme_settings.buffer_font.style;
19210        text_style.font_features = theme_settings.buffer_font.features.clone();
19211        text_style.font_weight = theme_settings.buffer_font.weight;
19212
19213        let multi_line_diagnostic = diagnostic.message.contains('\n');
19214
19215        let buttons = |diagnostic: &Diagnostic| {
19216            if multi_line_diagnostic {
19217                v_flex()
19218            } else {
19219                h_flex()
19220            }
19221            .when(allow_closing, |div| {
19222                div.children(diagnostic.is_primary.then(|| {
19223                    IconButton::new("close-block", IconName::XCircle)
19224                        .icon_color(Color::Muted)
19225                        .size(ButtonSize::Compact)
19226                        .style(ButtonStyle::Transparent)
19227                        .visible_on_hover(group_id.clone())
19228                        .on_click(move |_click, window, cx| {
19229                            window.dispatch_action(Box::new(Cancel), cx)
19230                        })
19231                        .tooltip(|window, cx| {
19232                            Tooltip::for_action("Close Diagnostics", &Cancel, window, cx)
19233                        })
19234                }))
19235            })
19236            .child(
19237                IconButton::new("copy-block", IconName::Copy)
19238                    .icon_color(Color::Muted)
19239                    .size(ButtonSize::Compact)
19240                    .style(ButtonStyle::Transparent)
19241                    .visible_on_hover(group_id.clone())
19242                    .on_click({
19243                        let message = diagnostic.message.clone();
19244                        move |_click, _, cx| {
19245                            cx.write_to_clipboard(ClipboardItem::new_string(message.clone()))
19246                        }
19247                    })
19248                    .tooltip(Tooltip::text("Copy diagnostic message")),
19249            )
19250        };
19251
19252        let icon_size = buttons(&diagnostic).into_any_element().layout_as_root(
19253            AvailableSpace::min_size(),
19254            cx.window,
19255            cx.app,
19256        );
19257
19258        h_flex()
19259            .id(cx.block_id)
19260            .group(group_id.clone())
19261            .relative()
19262            .size_full()
19263            .block_mouse_down()
19264            .pl(cx.gutter_dimensions.width)
19265            .w(cx.max_width - cx.gutter_dimensions.full_width())
19266            .child(
19267                div()
19268                    .flex()
19269                    .w(cx.anchor_x - cx.gutter_dimensions.width - icon_size.width)
19270                    .flex_shrink(),
19271            )
19272            .child(buttons(&diagnostic))
19273            .child(div().flex().flex_shrink_0().child(
19274                StyledText::new(text_without_backticks.clone()).with_default_highlights(
19275                    &text_style,
19276                    code_ranges.iter().map(|range| {
19277                        (
19278                            range.clone(),
19279                            HighlightStyle {
19280                                font_weight: Some(FontWeight::BOLD),
19281                                ..Default::default()
19282                            },
19283                        )
19284                    }),
19285                ),
19286            ))
19287            .into_any_element()
19288    })
19289}
19290
19291fn inline_completion_edit_text(
19292    current_snapshot: &BufferSnapshot,
19293    edits: &[(Range<Anchor>, String)],
19294    edit_preview: &EditPreview,
19295    include_deletions: bool,
19296    cx: &App,
19297) -> HighlightedText {
19298    let edits = edits
19299        .iter()
19300        .map(|(anchor, text)| {
19301            (
19302                anchor.start.text_anchor..anchor.end.text_anchor,
19303                text.clone(),
19304            )
19305        })
19306        .collect::<Vec<_>>();
19307
19308    edit_preview.highlight_edits(current_snapshot, &edits, include_deletions, cx)
19309}
19310
19311pub fn highlight_diagnostic_message(
19312    diagnostic: &Diagnostic,
19313    mut max_message_rows: Option<u8>,
19314) -> (SharedString, Vec<Range<usize>>) {
19315    let mut text_without_backticks = String::new();
19316    let mut code_ranges = Vec::new();
19317
19318    if let Some(source) = &diagnostic.source {
19319        text_without_backticks.push_str(source);
19320        code_ranges.push(0..source.len());
19321        text_without_backticks.push_str(": ");
19322    }
19323
19324    let mut prev_offset = 0;
19325    let mut in_code_block = false;
19326    let has_row_limit = max_message_rows.is_some();
19327    let mut newline_indices = diagnostic
19328        .message
19329        .match_indices('\n')
19330        .filter(|_| has_row_limit)
19331        .map(|(ix, _)| ix)
19332        .fuse()
19333        .peekable();
19334
19335    for (quote_ix, _) in diagnostic
19336        .message
19337        .match_indices('`')
19338        .chain([(diagnostic.message.len(), "")])
19339    {
19340        let mut first_newline_ix = None;
19341        let mut last_newline_ix = None;
19342        while let Some(newline_ix) = newline_indices.peek() {
19343            if *newline_ix < quote_ix {
19344                if first_newline_ix.is_none() {
19345                    first_newline_ix = Some(*newline_ix);
19346                }
19347                last_newline_ix = Some(*newline_ix);
19348
19349                if let Some(rows_left) = &mut max_message_rows {
19350                    if *rows_left == 0 {
19351                        break;
19352                    } else {
19353                        *rows_left -= 1;
19354                    }
19355                }
19356                let _ = newline_indices.next();
19357            } else {
19358                break;
19359            }
19360        }
19361        let prev_len = text_without_backticks.len();
19362        let new_text = &diagnostic.message[prev_offset..first_newline_ix.unwrap_or(quote_ix)];
19363        text_without_backticks.push_str(new_text);
19364        if in_code_block {
19365            code_ranges.push(prev_len..text_without_backticks.len());
19366        }
19367        prev_offset = last_newline_ix.unwrap_or(quote_ix) + 1;
19368        in_code_block = !in_code_block;
19369        if first_newline_ix.map_or(false, |newline_ix| newline_ix < quote_ix) {
19370            text_without_backticks.push_str("...");
19371            break;
19372        }
19373    }
19374
19375    (text_without_backticks.into(), code_ranges)
19376}
19377
19378fn diagnostic_style(severity: DiagnosticSeverity, colors: &StatusColors) -> Hsla {
19379    match severity {
19380        DiagnosticSeverity::ERROR => colors.error,
19381        DiagnosticSeverity::WARNING => colors.warning,
19382        DiagnosticSeverity::INFORMATION => colors.info,
19383        DiagnosticSeverity::HINT => colors.info,
19384        _ => colors.ignored,
19385    }
19386}
19387
19388pub fn styled_runs_for_code_label<'a>(
19389    label: &'a CodeLabel,
19390    syntax_theme: &'a theme::SyntaxTheme,
19391) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
19392    let fade_out = HighlightStyle {
19393        fade_out: Some(0.35),
19394        ..Default::default()
19395    };
19396
19397    let mut prev_end = label.filter_range.end;
19398    label
19399        .runs
19400        .iter()
19401        .enumerate()
19402        .flat_map(move |(ix, (range, highlight_id))| {
19403            let style = if let Some(style) = highlight_id.style(syntax_theme) {
19404                style
19405            } else {
19406                return Default::default();
19407            };
19408            let mut muted_style = style;
19409            muted_style.highlight(fade_out);
19410
19411            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
19412            if range.start >= label.filter_range.end {
19413                if range.start > prev_end {
19414                    runs.push((prev_end..range.start, fade_out));
19415                }
19416                runs.push((range.clone(), muted_style));
19417            } else if range.end <= label.filter_range.end {
19418                runs.push((range.clone(), style));
19419            } else {
19420                runs.push((range.start..label.filter_range.end, style));
19421                runs.push((label.filter_range.end..range.end, muted_style));
19422            }
19423            prev_end = cmp::max(prev_end, range.end);
19424
19425            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
19426                runs.push((prev_end..label.text.len(), fade_out));
19427            }
19428
19429            runs
19430        })
19431}
19432
19433pub(crate) fn split_words(text: &str) -> impl std::iter::Iterator<Item = &str> + '_ {
19434    let mut prev_index = 0;
19435    let mut prev_codepoint: Option<char> = None;
19436    text.char_indices()
19437        .chain([(text.len(), '\0')])
19438        .filter_map(move |(index, codepoint)| {
19439            let prev_codepoint = prev_codepoint.replace(codepoint)?;
19440            let is_boundary = index == text.len()
19441                || !prev_codepoint.is_uppercase() && codepoint.is_uppercase()
19442                || !prev_codepoint.is_alphanumeric() && codepoint.is_alphanumeric();
19443            if is_boundary {
19444                let chunk = &text[prev_index..index];
19445                prev_index = index;
19446                Some(chunk)
19447            } else {
19448                None
19449            }
19450        })
19451}
19452
19453pub trait RangeToAnchorExt: Sized {
19454    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor>;
19455
19456    fn to_display_points(self, snapshot: &EditorSnapshot) -> Range<DisplayPoint> {
19457        let anchor_range = self.to_anchors(&snapshot.buffer_snapshot);
19458        anchor_range.start.to_display_point(snapshot)..anchor_range.end.to_display_point(snapshot)
19459    }
19460}
19461
19462impl<T: ToOffset> RangeToAnchorExt for Range<T> {
19463    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor> {
19464        let start_offset = self.start.to_offset(snapshot);
19465        let end_offset = self.end.to_offset(snapshot);
19466        if start_offset == end_offset {
19467            snapshot.anchor_before(start_offset)..snapshot.anchor_before(end_offset)
19468        } else {
19469            snapshot.anchor_after(self.start)..snapshot.anchor_before(self.end)
19470        }
19471    }
19472}
19473
19474pub trait RowExt {
19475    fn as_f32(&self) -> f32;
19476
19477    fn next_row(&self) -> Self;
19478
19479    fn previous_row(&self) -> Self;
19480
19481    fn minus(&self, other: Self) -> u32;
19482}
19483
19484impl RowExt for DisplayRow {
19485    fn as_f32(&self) -> f32 {
19486        self.0 as f32
19487    }
19488
19489    fn next_row(&self) -> Self {
19490        Self(self.0 + 1)
19491    }
19492
19493    fn previous_row(&self) -> Self {
19494        Self(self.0.saturating_sub(1))
19495    }
19496
19497    fn minus(&self, other: Self) -> u32 {
19498        self.0 - other.0
19499    }
19500}
19501
19502impl RowExt for MultiBufferRow {
19503    fn as_f32(&self) -> f32 {
19504        self.0 as f32
19505    }
19506
19507    fn next_row(&self) -> Self {
19508        Self(self.0 + 1)
19509    }
19510
19511    fn previous_row(&self) -> Self {
19512        Self(self.0.saturating_sub(1))
19513    }
19514
19515    fn minus(&self, other: Self) -> u32 {
19516        self.0 - other.0
19517    }
19518}
19519
19520trait RowRangeExt {
19521    type Row;
19522
19523    fn len(&self) -> usize;
19524
19525    fn iter_rows(&self) -> impl DoubleEndedIterator<Item = Self::Row>;
19526}
19527
19528impl RowRangeExt for Range<MultiBufferRow> {
19529    type Row = MultiBufferRow;
19530
19531    fn len(&self) -> usize {
19532        (self.end.0 - self.start.0) as usize
19533    }
19534
19535    fn iter_rows(&self) -> impl DoubleEndedIterator<Item = MultiBufferRow> {
19536        (self.start.0..self.end.0).map(MultiBufferRow)
19537    }
19538}
19539
19540impl RowRangeExt for Range<DisplayRow> {
19541    type Row = DisplayRow;
19542
19543    fn len(&self) -> usize {
19544        (self.end.0 - self.start.0) as usize
19545    }
19546
19547    fn iter_rows(&self) -> impl DoubleEndedIterator<Item = DisplayRow> {
19548        (self.start.0..self.end.0).map(DisplayRow)
19549    }
19550}
19551
19552/// If select range has more than one line, we
19553/// just point the cursor to range.start.
19554fn collapse_multiline_range(range: Range<Point>) -> Range<Point> {
19555    if range.start.row == range.end.row {
19556        range
19557    } else {
19558        range.start..range.start
19559    }
19560}
19561pub struct KillRing(ClipboardItem);
19562impl Global for KillRing {}
19563
19564const UPDATE_DEBOUNCE: Duration = Duration::from_millis(50);
19565
19566struct BreakpointPromptEditor {
19567    pub(crate) prompt: Entity<Editor>,
19568    editor: WeakEntity<Editor>,
19569    breakpoint_anchor: Anchor,
19570    kind: BreakpointKind,
19571    block_ids: HashSet<CustomBlockId>,
19572    gutter_dimensions: Arc<Mutex<GutterDimensions>>,
19573    _subscriptions: Vec<Subscription>,
19574}
19575
19576impl BreakpointPromptEditor {
19577    const MAX_LINES: u8 = 4;
19578
19579    fn new(
19580        editor: WeakEntity<Editor>,
19581        breakpoint_anchor: Anchor,
19582        kind: BreakpointKind,
19583        window: &mut Window,
19584        cx: &mut Context<Self>,
19585    ) -> Self {
19586        let buffer = cx.new(|cx| {
19587            Buffer::local(
19588                kind.log_message()
19589                    .map(|msg| msg.to_string())
19590                    .unwrap_or_default(),
19591                cx,
19592            )
19593        });
19594        let buffer = cx.new(|cx| MultiBuffer::singleton(buffer, cx));
19595
19596        let prompt = cx.new(|cx| {
19597            let mut prompt = Editor::new(
19598                EditorMode::AutoHeight {
19599                    max_lines: Self::MAX_LINES as usize,
19600                },
19601                buffer,
19602                None,
19603                window,
19604                cx,
19605            );
19606            prompt.set_soft_wrap_mode(language::language_settings::SoftWrap::EditorWidth, cx);
19607            prompt.set_show_cursor_when_unfocused(false, cx);
19608            prompt.set_placeholder_text(
19609                "Message to log when breakpoint is hit. Expressions within {} are interpolated.",
19610                cx,
19611            );
19612
19613            prompt
19614        });
19615
19616        Self {
19617            prompt,
19618            editor,
19619            breakpoint_anchor,
19620            kind,
19621            gutter_dimensions: Arc::new(Mutex::new(GutterDimensions::default())),
19622            block_ids: Default::default(),
19623            _subscriptions: vec![],
19624        }
19625    }
19626
19627    pub(crate) fn add_block_ids(&mut self, block_ids: Vec<CustomBlockId>) {
19628        self.block_ids.extend(block_ids)
19629    }
19630
19631    fn confirm(&mut self, _: &menu::Confirm, window: &mut Window, cx: &mut Context<Self>) {
19632        if let Some(editor) = self.editor.upgrade() {
19633            let log_message = self
19634                .prompt
19635                .read(cx)
19636                .buffer
19637                .read(cx)
19638                .as_singleton()
19639                .expect("A multi buffer in breakpoint prompt isn't possible")
19640                .read(cx)
19641                .as_rope()
19642                .to_string();
19643
19644            editor.update(cx, |editor, cx| {
19645                editor.edit_breakpoint_at_anchor(
19646                    self.breakpoint_anchor,
19647                    self.kind.clone(),
19648                    BreakpointEditAction::EditLogMessage(log_message.into()),
19649                    cx,
19650                );
19651
19652                editor.remove_blocks(self.block_ids.clone(), None, cx);
19653                cx.focus_self(window);
19654            });
19655        }
19656    }
19657
19658    fn cancel(&mut self, _: &menu::Cancel, window: &mut Window, cx: &mut Context<Self>) {
19659        self.editor
19660            .update(cx, |editor, cx| {
19661                editor.remove_blocks(self.block_ids.clone(), None, cx);
19662                window.focus(&editor.focus_handle);
19663            })
19664            .log_err();
19665    }
19666
19667    fn render_prompt_editor(&self, cx: &mut Context<Self>) -> impl IntoElement {
19668        let settings = ThemeSettings::get_global(cx);
19669        let text_style = TextStyle {
19670            color: if self.prompt.read(cx).read_only(cx) {
19671                cx.theme().colors().text_disabled
19672            } else {
19673                cx.theme().colors().text
19674            },
19675            font_family: settings.buffer_font.family.clone(),
19676            font_fallbacks: settings.buffer_font.fallbacks.clone(),
19677            font_size: settings.buffer_font_size(cx).into(),
19678            font_weight: settings.buffer_font.weight,
19679            line_height: relative(settings.buffer_line_height.value()),
19680            ..Default::default()
19681        };
19682        EditorElement::new(
19683            &self.prompt,
19684            EditorStyle {
19685                background: cx.theme().colors().editor_background,
19686                local_player: cx.theme().players().local(),
19687                text: text_style,
19688                ..Default::default()
19689            },
19690        )
19691    }
19692}
19693
19694impl Render for BreakpointPromptEditor {
19695    fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
19696        let gutter_dimensions = *self.gutter_dimensions.lock();
19697        h_flex()
19698            .key_context("Editor")
19699            .bg(cx.theme().colors().editor_background)
19700            .border_y_1()
19701            .border_color(cx.theme().status().info_border)
19702            .size_full()
19703            .py(window.line_height() / 2.5)
19704            .on_action(cx.listener(Self::confirm))
19705            .on_action(cx.listener(Self::cancel))
19706            .child(h_flex().w(gutter_dimensions.full_width() + (gutter_dimensions.margin / 2.0)))
19707            .child(div().flex_1().child(self.render_prompt_editor(cx)))
19708    }
19709}
19710
19711impl Focusable for BreakpointPromptEditor {
19712    fn focus_handle(&self, cx: &App) -> FocusHandle {
19713        self.prompt.focus_handle(cx)
19714    }
19715}
19716
19717fn all_edits_insertions_or_deletions(
19718    edits: &Vec<(Range<Anchor>, String)>,
19719    snapshot: &MultiBufferSnapshot,
19720) -> bool {
19721    let mut all_insertions = true;
19722    let mut all_deletions = true;
19723
19724    for (range, new_text) in edits.iter() {
19725        let range_is_empty = range.to_offset(&snapshot).is_empty();
19726        let text_is_empty = new_text.is_empty();
19727
19728        if range_is_empty != text_is_empty {
19729            if range_is_empty {
19730                all_deletions = false;
19731            } else {
19732                all_insertions = false;
19733            }
19734        } else {
19735            return false;
19736        }
19737
19738        if !all_insertions && !all_deletions {
19739            return false;
19740        }
19741    }
19742    all_insertions || all_deletions
19743}
19744
19745struct MissingEditPredictionKeybindingTooltip;
19746
19747impl Render for MissingEditPredictionKeybindingTooltip {
19748    fn render(&mut self, window: &mut Window, cx: &mut Context<'_, Self>) -> impl IntoElement {
19749        ui::tooltip_container(window, cx, |container, _, cx| {
19750            container
19751                .flex_shrink_0()
19752                .max_w_80()
19753                .min_h(rems_from_px(124.))
19754                .justify_between()
19755                .child(
19756                    v_flex()
19757                        .flex_1()
19758                        .text_ui_sm(cx)
19759                        .child(Label::new("Conflict with Accept Keybinding"))
19760                        .child("Your keymap currently overrides the default accept keybinding. To continue, assign one keybinding for the `editor::AcceptEditPrediction` action.")
19761                )
19762                .child(
19763                    h_flex()
19764                        .pb_1()
19765                        .gap_1()
19766                        .items_end()
19767                        .w_full()
19768                        .child(Button::new("open-keymap", "Assign Keybinding").size(ButtonSize::Compact).on_click(|_ev, window, cx| {
19769                            window.dispatch_action(zed_actions::OpenKeymap.boxed_clone(), cx)
19770                        }))
19771                        .child(Button::new("see-docs", "See Docs").size(ButtonSize::Compact).on_click(|_ev, _window, cx| {
19772                            cx.open_url("https://zed.dev/docs/completions#edit-predictions-missing-keybinding");
19773                        })),
19774                )
19775        })
19776    }
19777}
19778
19779#[derive(Debug, Clone, Copy, PartialEq)]
19780pub struct LineHighlight {
19781    pub background: Background,
19782    pub border: Option<gpui::Hsla>,
19783}
19784
19785impl From<Hsla> for LineHighlight {
19786    fn from(hsla: Hsla) -> Self {
19787        Self {
19788            background: hsla.into(),
19789            border: None,
19790        }
19791    }
19792}
19793
19794impl From<Background> for LineHighlight {
19795    fn from(background: Background) -> Self {
19796        Self {
19797            background,
19798            border: None,
19799        }
19800    }
19801}