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 linked_editing_ranges;
   32mod lsp_ext;
   33mod mouse_context_menu;
   34pub mod movement;
   35mod persistence;
   36mod proposed_changes_editor;
   37mod rust_analyzer_ext;
   38pub mod scroll;
   39mod selections_collection;
   40pub mod tasks;
   41
   42#[cfg(test)]
   43mod editor_tests;
   44#[cfg(test)]
   45mod inline_completion_tests;
   46mod signature_help;
   47#[cfg(any(test, feature = "test-support"))]
   48pub mod test;
   49
   50pub(crate) use actions::*;
   51pub use actions::{AcceptEditPrediction, OpenExcerpts, OpenExcerptsSplit};
   52use aho_corasick::AhoCorasick;
   53use anyhow::{anyhow, Context as _, Result};
   54use blink_manager::BlinkManager;
   55use buffer_diff::{DiffHunkSecondaryStatus, DiffHunkStatus};
   56use client::{Collaborator, ParticipantIndex};
   57use clock::ReplicaId;
   58use collections::{BTreeMap, HashMap, HashSet, VecDeque};
   59use convert_case::{Case, Casing};
   60use display_map::*;
   61pub use display_map::{DisplayPoint, FoldPlaceholder};
   62pub use editor_settings::{
   63    CurrentLineHighlight, EditorSettings, ScrollBeyondLastLine, SearchSettings, ShowScrollbar,
   64};
   65pub use editor_settings_controls::*;
   66use element::{layout_line, AcceptEditPredictionBinding, LineWithInvisibles, PositionMap};
   67pub use element::{
   68    CursorLayout, EditorElement, HighlightedRange, HighlightedRangeLine, PointForPosition,
   69};
   70use futures::{
   71    future::{self, Shared},
   72    FutureExt,
   73};
   74use fuzzy::StringMatchCandidate;
   75
   76use ::git::{status::FileStatus, Restore};
   77use code_context_menus::{
   78    AvailableCodeAction, CodeActionContents, CodeActionsItem, CodeActionsMenu, CodeContextMenu,
   79    CompletionsMenu, ContextMenuOrigin,
   80};
   81use git::blame::GitBlame;
   82use gpui::{
   83    div, impl_actions, point, prelude::*, pulsating_between, px, relative, size, Action, Animation,
   84    AnimationExt, AnyElement, App, AsyncWindowContext, AvailableSpace, Background, Bounds,
   85    ClipboardEntry, ClipboardItem, Context, DispatchPhase, Edges, Entity, EntityInputHandler,
   86    EventEmitter, FocusHandle, FocusOutEvent, Focusable, FontId, FontWeight, Global,
   87    HighlightStyle, Hsla, KeyContext, Modifiers, MouseButton, MouseDownEvent, PaintQuad,
   88    ParentElement, Pixels, Render, SharedString, Size, Styled, StyledText, Subscription, Task,
   89    TextStyle, TextStyleRefinement, UTF16Selection, UnderlineStyle, UniformListScrollHandle,
   90    WeakEntity, WeakFocusHandle, Window,
   91};
   92use highlight_matching_bracket::refresh_matching_bracket_highlights;
   93use hover_popover::{hide_hover, HoverState};
   94use indent_guides::ActiveIndentGuidesState;
   95use inlay_hint_cache::{InlayHintCache, InlaySplice, InvalidationStrategy};
   96pub use inline_completion::Direction;
   97use inline_completion::{EditPredictionProvider, InlineCompletionProviderHandle};
   98pub use items::MAX_TAB_TITLE_LEN;
   99use itertools::Itertools;
  100use language::{
  101    language_settings::{
  102        self, all_language_settings, language_settings, InlayHintSettings, RewrapBehavior,
  103    },
  104    point_from_lsp, text_diff_with_options, AutoindentMode, BracketMatch, BracketPair, Buffer,
  105    Capability, CharKind, CodeLabel, CursorShape, Diagnostic, DiffOptions, EditPredictionsMode,
  106    EditPreview, HighlightedText, IndentKind, IndentSize, Language, OffsetRangeExt, Point,
  107    Selection, SelectionGoal, TextObject, TransactionId, TreeSitterOptions,
  108};
  109use language::{point_to_lsp, BufferRow, CharClassifier, Runnable, RunnableRange};
  110use linked_editing_ranges::refresh_linked_ranges;
  111use mouse_context_menu::MouseContextMenu;
  112use persistence::DB;
  113pub use proposed_changes_editor::{
  114    ProposedChangeLocation, ProposedChangesEditor, ProposedChangesEditorToolbar,
  115};
  116use smallvec::smallvec;
  117use std::iter::Peekable;
  118use task::{ResolvedTask, TaskTemplate, TaskVariables};
  119
  120use hover_links::{find_file, HoverLink, HoveredLinkState, InlayHighlight};
  121pub use lsp::CompletionContext;
  122use lsp::{
  123    CompletionItemKind, CompletionTriggerKind, DiagnosticSeverity, InsertTextFormat,
  124    LanguageServerId, LanguageServerName,
  125};
  126
  127use language::BufferSnapshot;
  128use movement::TextLayoutDetails;
  129pub use multi_buffer::{
  130    Anchor, AnchorRangeExt, ExcerptId, ExcerptRange, MultiBuffer, MultiBufferSnapshot, RowInfo,
  131    ToOffset, ToPoint,
  132};
  133use multi_buffer::{
  134    ExcerptInfo, ExpandExcerptDirection, MultiBufferDiffHunk, MultiBufferPoint, MultiBufferRow,
  135    MultiOrSingleBufferOffsetRange, ToOffsetUtf16,
  136};
  137use project::{
  138    lsp_store::{CompletionDocumentation, FormatTrigger, LspFormatTarget, OpenLspBufferHandle},
  139    project_settings::{GitGutterSetting, ProjectSettings},
  140    CodeAction, Completion, CompletionIntent, DocumentHighlight, InlayHint, Location, LocationLink,
  141    PrepareRenameResponse, Project, ProjectItem, ProjectTransaction, TaskSourceKind,
  142};
  143use rand::prelude::*;
  144use rpc::{proto::*, ErrorExt};
  145use scroll::{Autoscroll, OngoingScroll, ScrollAnchor, ScrollManager, ScrollbarAutoHide};
  146use selections_collection::{
  147    resolve_selections, MutableSelectionsCollection, SelectionsCollection,
  148};
  149use serde::{Deserialize, Serialize};
  150use settings::{update_settings_file, Settings, SettingsLocation, SettingsStore};
  151use smallvec::SmallVec;
  152use snippet::Snippet;
  153use std::{
  154    any::TypeId,
  155    borrow::Cow,
  156    cell::RefCell,
  157    cmp::{self, Ordering, Reverse},
  158    mem,
  159    num::NonZeroU32,
  160    ops::{ControlFlow, Deref, DerefMut, Not as _, Range, RangeInclusive},
  161    path::{Path, PathBuf},
  162    rc::Rc,
  163    sync::Arc,
  164    time::{Duration, Instant},
  165};
  166pub use sum_tree::Bias;
  167use sum_tree::TreeMap;
  168use text::{BufferId, OffsetUtf16, Rope};
  169use theme::{
  170    observe_buffer_font_size_adjustment, ActiveTheme, PlayerColor, StatusColors, SyntaxTheme,
  171    ThemeColors, ThemeSettings,
  172};
  173use ui::{
  174    h_flex, prelude::*, ButtonSize, ButtonStyle, Disclosure, IconButton, IconName, IconSize, Key,
  175    Tooltip,
  176};
  177use util::{defer, maybe, post_inc, RangeExt, ResultExt, TryFutureExt};
  178use workspace::{
  179    item::{ItemHandle, PreviewTabsSettings},
  180    ItemId, RestoreOnStartupBehavior,
  181};
  182use workspace::{
  183    notifications::{DetachAndPromptErr, NotificationId, NotifyTaskExt},
  184    WorkspaceSettings,
  185};
  186use workspace::{
  187    searchable::SearchEvent, ItemNavHistory, SplitDirection, ViewId, Workspace, WorkspaceId,
  188};
  189use workspace::{Item as WorkspaceItem, OpenInTerminal, OpenTerminal, TabBarSettings, Toast};
  190
  191use crate::hover_links::{find_url, find_url_from_range};
  192use crate::signature_help::{SignatureHelpHiddenBy, SignatureHelpState};
  193
  194pub const FILE_HEADER_HEIGHT: u32 = 2;
  195pub const MULTI_BUFFER_EXCERPT_HEADER_HEIGHT: u32 = 1;
  196pub const MULTI_BUFFER_EXCERPT_FOOTER_HEIGHT: u32 = 1;
  197pub const DEFAULT_MULTIBUFFER_CONTEXT: u32 = 2;
  198const CURSOR_BLINK_INTERVAL: Duration = Duration::from_millis(500);
  199const MAX_LINE_LEN: usize = 1024;
  200const MIN_NAVIGATION_HISTORY_ROW_DELTA: i64 = 10;
  201const MAX_SELECTION_HISTORY_LEN: usize = 1024;
  202pub(crate) const CURSORS_VISIBLE_FOR: Duration = Duration::from_millis(2000);
  203#[doc(hidden)]
  204pub const CODE_ACTIONS_DEBOUNCE_TIMEOUT: Duration = Duration::from_millis(250);
  205
  206pub(crate) const FORMAT_TIMEOUT: Duration = Duration::from_secs(5);
  207pub(crate) const SCROLL_CENTER_TOP_BOTTOM_DEBOUNCE_TIMEOUT: Duration = Duration::from_secs(1);
  208
  209pub(crate) const EDIT_PREDICTION_KEY_CONTEXT: &str = "edit_prediction";
  210pub(crate) const EDIT_PREDICTION_CONFLICT_KEY_CONTEXT: &str = "edit_prediction_conflict";
  211
  212const COLUMNAR_SELECTION_MODIFIERS: Modifiers = Modifiers {
  213    alt: true,
  214    shift: true,
  215    control: false,
  216    platform: false,
  217    function: false,
  218};
  219
  220#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
  221pub enum InlayId {
  222    InlineCompletion(usize),
  223    Hint(usize),
  224}
  225
  226impl InlayId {
  227    fn id(&self) -> usize {
  228        match self {
  229            Self::InlineCompletion(id) => *id,
  230            Self::Hint(id) => *id,
  231        }
  232    }
  233}
  234
  235enum DocumentHighlightRead {}
  236enum DocumentHighlightWrite {}
  237enum InputComposition {}
  238enum SelectedTextHighlight {}
  239
  240#[derive(Debug, Copy, Clone, PartialEq, Eq)]
  241pub enum Navigated {
  242    Yes,
  243    No,
  244}
  245
  246impl Navigated {
  247    pub fn from_bool(yes: bool) -> Navigated {
  248        if yes {
  249            Navigated::Yes
  250        } else {
  251            Navigated::No
  252        }
  253    }
  254}
  255
  256#[derive(Debug, Clone, PartialEq, Eq)]
  257enum DisplayDiffHunk {
  258    Folded {
  259        display_row: DisplayRow,
  260    },
  261    Unfolded {
  262        diff_base_byte_range: Range<usize>,
  263        display_row_range: Range<DisplayRow>,
  264        multi_buffer_range: Range<Anchor>,
  265        status: DiffHunkStatus,
  266    },
  267}
  268
  269pub fn init_settings(cx: &mut App) {
  270    EditorSettings::register(cx);
  271}
  272
  273pub fn init(cx: &mut App) {
  274    init_settings(cx);
  275
  276    workspace::register_project_item::<Editor>(cx);
  277    workspace::FollowableViewRegistry::register::<Editor>(cx);
  278    workspace::register_serializable_item::<Editor>(cx);
  279
  280    cx.observe_new(
  281        |workspace: &mut Workspace, _: Option<&mut Window>, _cx: &mut Context<Workspace>| {
  282            workspace.register_action(Editor::new_file);
  283            workspace.register_action(Editor::new_file_vertical);
  284            workspace.register_action(Editor::new_file_horizontal);
  285            workspace.register_action(Editor::cancel_language_server_work);
  286        },
  287    )
  288    .detach();
  289
  290    cx.on_action(move |_: &workspace::NewFile, cx| {
  291        let app_state = workspace::AppState::global(cx);
  292        if let Some(app_state) = app_state.upgrade() {
  293            workspace::open_new(
  294                Default::default(),
  295                app_state,
  296                cx,
  297                |workspace, window, cx| {
  298                    Editor::new_file(workspace, &Default::default(), window, cx)
  299                },
  300            )
  301            .detach();
  302        }
  303    });
  304    cx.on_action(move |_: &workspace::NewWindow, cx| {
  305        let app_state = workspace::AppState::global(cx);
  306        if let Some(app_state) = app_state.upgrade() {
  307            workspace::open_new(
  308                Default::default(),
  309                app_state,
  310                cx,
  311                |workspace, window, cx| {
  312                    cx.activate(true);
  313                    Editor::new_file(workspace, &Default::default(), window, cx)
  314                },
  315            )
  316            .detach();
  317        }
  318    });
  319}
  320
  321pub struct SearchWithinRange;
  322
  323trait InvalidationRegion {
  324    fn ranges(&self) -> &[Range<Anchor>];
  325}
  326
  327#[derive(Clone, Debug, PartialEq)]
  328pub enum SelectPhase {
  329    Begin {
  330        position: DisplayPoint,
  331        add: bool,
  332        click_count: usize,
  333    },
  334    BeginColumnar {
  335        position: DisplayPoint,
  336        reset: bool,
  337        goal_column: u32,
  338    },
  339    Extend {
  340        position: DisplayPoint,
  341        click_count: usize,
  342    },
  343    Update {
  344        position: DisplayPoint,
  345        goal_column: u32,
  346        scroll_delta: gpui::Point<f32>,
  347    },
  348    End,
  349}
  350
  351#[derive(Clone, Debug)]
  352pub enum SelectMode {
  353    Character,
  354    Word(Range<Anchor>),
  355    Line(Range<Anchor>),
  356    All,
  357}
  358
  359#[derive(Copy, Clone, PartialEq, Eq, Debug)]
  360pub enum EditorMode {
  361    SingleLine { auto_width: bool },
  362    AutoHeight { max_lines: usize },
  363    Full,
  364}
  365
  366#[derive(Copy, Clone, Debug)]
  367pub enum SoftWrap {
  368    /// Prefer not to wrap at all.
  369    ///
  370    /// Note: this is currently internal, as actually limited by [`crate::MAX_LINE_LEN`] until it wraps.
  371    /// The mode is used inside git diff hunks, where it's seems currently more useful to not wrap as much as possible.
  372    GitDiff,
  373    /// Prefer a single line generally, unless an overly long line is encountered.
  374    None,
  375    /// Soft wrap lines that exceed the editor width.
  376    EditorWidth,
  377    /// Soft wrap lines at the preferred line length.
  378    Column(u32),
  379    /// Soft wrap line at the preferred line length or the editor width (whichever is smaller).
  380    Bounded(u32),
  381}
  382
  383#[derive(Clone)]
  384pub struct EditorStyle {
  385    pub background: Hsla,
  386    pub local_player: PlayerColor,
  387    pub text: TextStyle,
  388    pub scrollbar_width: Pixels,
  389    pub syntax: Arc<SyntaxTheme>,
  390    pub status: StatusColors,
  391    pub inlay_hints_style: HighlightStyle,
  392    pub inline_completion_styles: InlineCompletionStyles,
  393    pub unnecessary_code_fade: f32,
  394}
  395
  396impl Default for EditorStyle {
  397    fn default() -> Self {
  398        Self {
  399            background: Hsla::default(),
  400            local_player: PlayerColor::default(),
  401            text: TextStyle::default(),
  402            scrollbar_width: Pixels::default(),
  403            syntax: Default::default(),
  404            // HACK: Status colors don't have a real default.
  405            // We should look into removing the status colors from the editor
  406            // style and retrieve them directly from the theme.
  407            status: StatusColors::dark(),
  408            inlay_hints_style: HighlightStyle::default(),
  409            inline_completion_styles: InlineCompletionStyles {
  410                insertion: HighlightStyle::default(),
  411                whitespace: HighlightStyle::default(),
  412            },
  413            unnecessary_code_fade: Default::default(),
  414        }
  415    }
  416}
  417
  418pub fn make_inlay_hints_style(cx: &mut App) -> HighlightStyle {
  419    let show_background = language_settings::language_settings(None, None, cx)
  420        .inlay_hints
  421        .show_background;
  422
  423    HighlightStyle {
  424        color: Some(cx.theme().status().hint),
  425        background_color: show_background.then(|| cx.theme().status().hint_background),
  426        ..HighlightStyle::default()
  427    }
  428}
  429
  430pub fn make_suggestion_styles(cx: &mut App) -> InlineCompletionStyles {
  431    InlineCompletionStyles {
  432        insertion: HighlightStyle {
  433            color: Some(cx.theme().status().predictive),
  434            ..HighlightStyle::default()
  435        },
  436        whitespace: HighlightStyle {
  437            background_color: Some(cx.theme().status().created_background),
  438            ..HighlightStyle::default()
  439        },
  440    }
  441}
  442
  443type CompletionId = usize;
  444
  445pub(crate) enum EditDisplayMode {
  446    TabAccept,
  447    DiffPopover,
  448    Inline,
  449}
  450
  451enum InlineCompletion {
  452    Edit {
  453        edits: Vec<(Range<Anchor>, String)>,
  454        edit_preview: Option<EditPreview>,
  455        display_mode: EditDisplayMode,
  456        snapshot: BufferSnapshot,
  457    },
  458    Move {
  459        target: Anchor,
  460        snapshot: BufferSnapshot,
  461    },
  462}
  463
  464struct InlineCompletionState {
  465    inlay_ids: Vec<InlayId>,
  466    completion: InlineCompletion,
  467    completion_id: Option<SharedString>,
  468    invalidation_range: Range<Anchor>,
  469}
  470
  471enum EditPredictionSettings {
  472    Disabled,
  473    Enabled {
  474        show_in_menu: bool,
  475        preview_requires_modifier: bool,
  476    },
  477}
  478
  479enum InlineCompletionHighlight {}
  480
  481#[derive(Debug, Clone)]
  482struct InlineDiagnostic {
  483    message: SharedString,
  484    group_id: usize,
  485    is_primary: bool,
  486    start: Point,
  487    severity: DiagnosticSeverity,
  488}
  489
  490pub enum MenuInlineCompletionsPolicy {
  491    Never,
  492    ByProvider,
  493}
  494
  495pub enum EditPredictionPreview {
  496    /// Modifier is not pressed
  497    Inactive { released_too_fast: bool },
  498    /// Modifier pressed
  499    Active {
  500        since: Instant,
  501        previous_scroll_position: Option<ScrollAnchor>,
  502    },
  503}
  504
  505impl EditPredictionPreview {
  506    pub fn released_too_fast(&self) -> bool {
  507        match self {
  508            EditPredictionPreview::Inactive { released_too_fast } => *released_too_fast,
  509            EditPredictionPreview::Active { .. } => false,
  510        }
  511    }
  512
  513    pub fn set_previous_scroll_position(&mut self, scroll_position: Option<ScrollAnchor>) {
  514        if let EditPredictionPreview::Active {
  515            previous_scroll_position,
  516            ..
  517        } = self
  518        {
  519            *previous_scroll_position = scroll_position;
  520        }
  521    }
  522}
  523
  524#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Debug, Default)]
  525struct EditorActionId(usize);
  526
  527impl EditorActionId {
  528    pub fn post_inc(&mut self) -> Self {
  529        let answer = self.0;
  530
  531        *self = Self(answer + 1);
  532
  533        Self(answer)
  534    }
  535}
  536
  537// type GetFieldEditorTheme = dyn Fn(&theme::Theme) -> theme::FieldEditor;
  538// type OverrideTextStyle = dyn Fn(&EditorStyle) -> Option<HighlightStyle>;
  539
  540type BackgroundHighlight = (fn(&ThemeColors) -> Hsla, Arc<[Range<Anchor>]>);
  541type GutterHighlight = (fn(&App) -> Hsla, Arc<[Range<Anchor>]>);
  542
  543#[derive(Default)]
  544struct ScrollbarMarkerState {
  545    scrollbar_size: Size<Pixels>,
  546    dirty: bool,
  547    markers: Arc<[PaintQuad]>,
  548    pending_refresh: Option<Task<Result<()>>>,
  549}
  550
  551impl ScrollbarMarkerState {
  552    fn should_refresh(&self, scrollbar_size: Size<Pixels>) -> bool {
  553        self.pending_refresh.is_none() && (self.scrollbar_size != scrollbar_size || self.dirty)
  554    }
  555}
  556
  557#[derive(Clone, Debug)]
  558struct RunnableTasks {
  559    templates: Vec<(TaskSourceKind, TaskTemplate)>,
  560    offset: multi_buffer::Anchor,
  561    // We need the column at which the task context evaluation should take place (when we're spawning it via gutter).
  562    column: u32,
  563    // Values of all named captures, including those starting with '_'
  564    extra_variables: HashMap<String, String>,
  565    // Full range of the tagged region. We use it to determine which `extra_variables` to grab for context resolution in e.g. a modal.
  566    context_range: Range<BufferOffset>,
  567}
  568
  569impl RunnableTasks {
  570    fn resolve<'a>(
  571        &'a self,
  572        cx: &'a task::TaskContext,
  573    ) -> impl Iterator<Item = (TaskSourceKind, ResolvedTask)> + 'a {
  574        self.templates.iter().filter_map(|(kind, template)| {
  575            template
  576                .resolve_task(&kind.to_id_base(), cx)
  577                .map(|task| (kind.clone(), task))
  578        })
  579    }
  580}
  581
  582#[derive(Clone)]
  583struct ResolvedTasks {
  584    templates: SmallVec<[(TaskSourceKind, ResolvedTask); 1]>,
  585    position: Anchor,
  586}
  587#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
  588struct BufferOffset(usize);
  589
  590// Addons allow storing per-editor state in other crates (e.g. Vim)
  591pub trait Addon: 'static {
  592    fn extend_key_context(&self, _: &mut KeyContext, _: &App) {}
  593
  594    fn render_buffer_header_controls(
  595        &self,
  596        _: &ExcerptInfo,
  597        _: &Window,
  598        _: &App,
  599    ) -> Option<AnyElement> {
  600        None
  601    }
  602
  603    fn to_any(&self) -> &dyn std::any::Any;
  604}
  605
  606#[derive(Debug, Copy, Clone, PartialEq, Eq)]
  607pub enum IsVimMode {
  608    Yes,
  609    No,
  610}
  611
  612/// Zed's primary implementation of text input, allowing users to edit a [`MultiBuffer`].
  613///
  614/// See the [module level documentation](self) for more information.
  615pub struct Editor {
  616    focus_handle: FocusHandle,
  617    last_focused_descendant: Option<WeakFocusHandle>,
  618    /// The text buffer being edited
  619    buffer: Entity<MultiBuffer>,
  620    /// Map of how text in the buffer should be displayed.
  621    /// Handles soft wraps, folds, fake inlay text insertions, etc.
  622    pub display_map: Entity<DisplayMap>,
  623    pub selections: SelectionsCollection,
  624    pub scroll_manager: ScrollManager,
  625    /// When inline assist editors are linked, they all render cursors because
  626    /// typing enters text into each of them, even the ones that aren't focused.
  627    pub(crate) show_cursor_when_unfocused: bool,
  628    columnar_selection_tail: Option<Anchor>,
  629    add_selections_state: Option<AddSelectionsState>,
  630    select_next_state: Option<SelectNextState>,
  631    select_prev_state: Option<SelectNextState>,
  632    selection_history: SelectionHistory,
  633    autoclose_regions: Vec<AutocloseRegion>,
  634    snippet_stack: InvalidationStack<SnippetState>,
  635    select_larger_syntax_node_stack: Vec<Box<[Selection<usize>]>>,
  636    ime_transaction: Option<TransactionId>,
  637    active_diagnostics: Option<ActiveDiagnosticGroup>,
  638    show_inline_diagnostics: bool,
  639    inline_diagnostics_update: Task<()>,
  640    inline_diagnostics_enabled: bool,
  641    inline_diagnostics: Vec<(Anchor, InlineDiagnostic)>,
  642    soft_wrap_mode_override: Option<language_settings::SoftWrap>,
  643
  644    // TODO: make this a access method
  645    pub project: Option<Entity<Project>>,
  646    semantics_provider: Option<Rc<dyn SemanticsProvider>>,
  647    completion_provider: Option<Box<dyn CompletionProvider>>,
  648    collaboration_hub: Option<Box<dyn CollaborationHub>>,
  649    blink_manager: Entity<BlinkManager>,
  650    show_cursor_names: bool,
  651    hovered_cursors: HashMap<HoveredCursor, Task<()>>,
  652    pub show_local_selections: bool,
  653    mode: EditorMode,
  654    show_breadcrumbs: bool,
  655    show_gutter: bool,
  656    show_scrollbars: bool,
  657    show_line_numbers: Option<bool>,
  658    use_relative_line_numbers: Option<bool>,
  659    show_git_diff_gutter: Option<bool>,
  660    show_code_actions: Option<bool>,
  661    show_runnables: Option<bool>,
  662    show_wrap_guides: Option<bool>,
  663    show_indent_guides: Option<bool>,
  664    placeholder_text: Option<Arc<str>>,
  665    highlight_order: usize,
  666    highlighted_rows: HashMap<TypeId, Vec<RowHighlight>>,
  667    background_highlights: TreeMap<TypeId, BackgroundHighlight>,
  668    gutter_highlights: TreeMap<TypeId, GutterHighlight>,
  669    scrollbar_marker_state: ScrollbarMarkerState,
  670    active_indent_guides_state: ActiveIndentGuidesState,
  671    nav_history: Option<ItemNavHistory>,
  672    context_menu: RefCell<Option<CodeContextMenu>>,
  673    mouse_context_menu: Option<MouseContextMenu>,
  674    completion_tasks: Vec<(CompletionId, Task<Option<()>>)>,
  675    signature_help_state: SignatureHelpState,
  676    auto_signature_help: Option<bool>,
  677    find_all_references_task_sources: Vec<Anchor>,
  678    next_completion_id: CompletionId,
  679    available_code_actions: Option<(Location, Rc<[AvailableCodeAction]>)>,
  680    code_actions_task: Option<Task<Result<()>>>,
  681    selection_highlight_task: Option<Task<()>>,
  682    document_highlights_task: Option<Task<()>>,
  683    linked_editing_range_task: Option<Task<Option<()>>>,
  684    linked_edit_ranges: linked_editing_ranges::LinkedEditingRanges,
  685    pending_rename: Option<RenameState>,
  686    searchable: bool,
  687    cursor_shape: CursorShape,
  688    current_line_highlight: Option<CurrentLineHighlight>,
  689    collapse_matches: bool,
  690    autoindent_mode: Option<AutoindentMode>,
  691    workspace: Option<(WeakEntity<Workspace>, Option<WorkspaceId>)>,
  692    input_enabled: bool,
  693    use_modal_editing: bool,
  694    read_only: bool,
  695    leader_peer_id: Option<PeerId>,
  696    remote_id: Option<ViewId>,
  697    hover_state: HoverState,
  698    pending_mouse_down: Option<Rc<RefCell<Option<MouseDownEvent>>>>,
  699    gutter_hovered: bool,
  700    hovered_link_state: Option<HoveredLinkState>,
  701    edit_prediction_provider: Option<RegisteredInlineCompletionProvider>,
  702    code_action_providers: Vec<Rc<dyn CodeActionProvider>>,
  703    active_inline_completion: Option<InlineCompletionState>,
  704    /// Used to prevent flickering as the user types while the menu is open
  705    stale_inline_completion_in_menu: Option<InlineCompletionState>,
  706    edit_prediction_settings: EditPredictionSettings,
  707    inline_completions_hidden_for_vim_mode: bool,
  708    show_inline_completions_override: Option<bool>,
  709    menu_inline_completions_policy: MenuInlineCompletionsPolicy,
  710    edit_prediction_preview: EditPredictionPreview,
  711    edit_prediction_indent_conflict: bool,
  712    edit_prediction_requires_modifier_in_indent_conflict: bool,
  713    inlay_hint_cache: InlayHintCache,
  714    next_inlay_id: usize,
  715    _subscriptions: Vec<Subscription>,
  716    pixel_position_of_newest_cursor: Option<gpui::Point<Pixels>>,
  717    gutter_dimensions: GutterDimensions,
  718    style: Option<EditorStyle>,
  719    text_style_refinement: Option<TextStyleRefinement>,
  720    next_editor_action_id: EditorActionId,
  721    editor_actions:
  722        Rc<RefCell<BTreeMap<EditorActionId, Box<dyn Fn(&mut Window, &mut Context<Self>)>>>>,
  723    use_autoclose: bool,
  724    use_auto_surround: bool,
  725    auto_replace_emoji_shortcode: bool,
  726    show_git_blame_gutter: bool,
  727    show_git_blame_inline: bool,
  728    show_git_blame_inline_delay_task: Option<Task<()>>,
  729    git_blame_inline_tooltip: Option<WeakEntity<crate::commit_tooltip::CommitTooltip>>,
  730    git_blame_inline_enabled: bool,
  731    serialize_dirty_buffers: bool,
  732    show_selection_menu: Option<bool>,
  733    blame: Option<Entity<GitBlame>>,
  734    blame_subscription: Option<Subscription>,
  735    custom_context_menu: Option<
  736        Box<
  737            dyn 'static
  738                + Fn(
  739                    &mut Self,
  740                    DisplayPoint,
  741                    &mut Window,
  742                    &mut Context<Self>,
  743                ) -> Option<Entity<ui::ContextMenu>>,
  744        >,
  745    >,
  746    last_bounds: Option<Bounds<Pixels>>,
  747    last_position_map: Option<Rc<PositionMap>>,
  748    expect_bounds_change: Option<Bounds<Pixels>>,
  749    tasks: BTreeMap<(BufferId, BufferRow), RunnableTasks>,
  750    tasks_update_task: Option<Task<()>>,
  751    in_project_search: bool,
  752    previous_search_ranges: Option<Arc<[Range<Anchor>]>>,
  753    breadcrumb_header: Option<String>,
  754    focused_block: Option<FocusedBlock>,
  755    next_scroll_position: NextScrollCursorCenterTopBottom,
  756    addons: HashMap<TypeId, Box<dyn Addon>>,
  757    registered_buffers: HashMap<BufferId, OpenLspBufferHandle>,
  758    load_diff_task: Option<Shared<Task<()>>>,
  759    selection_mark_mode: bool,
  760    toggle_fold_multiple_buffers: Task<()>,
  761    _scroll_cursor_center_top_bottom_task: Task<()>,
  762    serialize_selections: Task<()>,
  763}
  764
  765#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)]
  766enum NextScrollCursorCenterTopBottom {
  767    #[default]
  768    Center,
  769    Top,
  770    Bottom,
  771}
  772
  773impl NextScrollCursorCenterTopBottom {
  774    fn next(&self) -> Self {
  775        match self {
  776            Self::Center => Self::Top,
  777            Self::Top => Self::Bottom,
  778            Self::Bottom => Self::Center,
  779        }
  780    }
  781}
  782
  783#[derive(Clone)]
  784pub struct EditorSnapshot {
  785    pub mode: EditorMode,
  786    show_gutter: bool,
  787    show_line_numbers: Option<bool>,
  788    show_git_diff_gutter: Option<bool>,
  789    show_code_actions: Option<bool>,
  790    show_runnables: Option<bool>,
  791    git_blame_gutter_max_author_length: Option<usize>,
  792    pub display_snapshot: DisplaySnapshot,
  793    pub placeholder_text: Option<Arc<str>>,
  794    is_focused: bool,
  795    scroll_anchor: ScrollAnchor,
  796    ongoing_scroll: OngoingScroll,
  797    current_line_highlight: CurrentLineHighlight,
  798    gutter_hovered: bool,
  799}
  800
  801const GIT_BLAME_MAX_AUTHOR_CHARS_DISPLAYED: usize = 20;
  802
  803#[derive(Default, Debug, Clone, Copy)]
  804pub struct GutterDimensions {
  805    pub left_padding: Pixels,
  806    pub right_padding: Pixels,
  807    pub width: Pixels,
  808    pub margin: Pixels,
  809    pub git_blame_entries_width: Option<Pixels>,
  810}
  811
  812impl GutterDimensions {
  813    /// The full width of the space taken up by the gutter.
  814    pub fn full_width(&self) -> Pixels {
  815        self.margin + self.width
  816    }
  817
  818    /// The width of the space reserved for the fold indicators,
  819    /// use alongside 'justify_end' and `gutter_width` to
  820    /// right align content with the line numbers
  821    pub fn fold_area_width(&self) -> Pixels {
  822        self.margin + self.right_padding
  823    }
  824}
  825
  826#[derive(Debug)]
  827pub struct RemoteSelection {
  828    pub replica_id: ReplicaId,
  829    pub selection: Selection<Anchor>,
  830    pub cursor_shape: CursorShape,
  831    pub peer_id: PeerId,
  832    pub line_mode: bool,
  833    pub participant_index: Option<ParticipantIndex>,
  834    pub user_name: Option<SharedString>,
  835}
  836
  837#[derive(Clone, Debug)]
  838struct SelectionHistoryEntry {
  839    selections: Arc<[Selection<Anchor>]>,
  840    select_next_state: Option<SelectNextState>,
  841    select_prev_state: Option<SelectNextState>,
  842    add_selections_state: Option<AddSelectionsState>,
  843}
  844
  845enum SelectionHistoryMode {
  846    Normal,
  847    Undoing,
  848    Redoing,
  849}
  850
  851#[derive(Clone, PartialEq, Eq, Hash)]
  852struct HoveredCursor {
  853    replica_id: u16,
  854    selection_id: usize,
  855}
  856
  857impl Default for SelectionHistoryMode {
  858    fn default() -> Self {
  859        Self::Normal
  860    }
  861}
  862
  863#[derive(Default)]
  864struct SelectionHistory {
  865    #[allow(clippy::type_complexity)]
  866    selections_by_transaction:
  867        HashMap<TransactionId, (Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)>,
  868    mode: SelectionHistoryMode,
  869    undo_stack: VecDeque<SelectionHistoryEntry>,
  870    redo_stack: VecDeque<SelectionHistoryEntry>,
  871}
  872
  873impl SelectionHistory {
  874    fn insert_transaction(
  875        &mut self,
  876        transaction_id: TransactionId,
  877        selections: Arc<[Selection<Anchor>]>,
  878    ) {
  879        self.selections_by_transaction
  880            .insert(transaction_id, (selections, None));
  881    }
  882
  883    #[allow(clippy::type_complexity)]
  884    fn transaction(
  885        &self,
  886        transaction_id: TransactionId,
  887    ) -> Option<&(Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)> {
  888        self.selections_by_transaction.get(&transaction_id)
  889    }
  890
  891    #[allow(clippy::type_complexity)]
  892    fn transaction_mut(
  893        &mut self,
  894        transaction_id: TransactionId,
  895    ) -> Option<&mut (Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)> {
  896        self.selections_by_transaction.get_mut(&transaction_id)
  897    }
  898
  899    fn push(&mut self, entry: SelectionHistoryEntry) {
  900        if !entry.selections.is_empty() {
  901            match self.mode {
  902                SelectionHistoryMode::Normal => {
  903                    self.push_undo(entry);
  904                    self.redo_stack.clear();
  905                }
  906                SelectionHistoryMode::Undoing => self.push_redo(entry),
  907                SelectionHistoryMode::Redoing => self.push_undo(entry),
  908            }
  909        }
  910    }
  911
  912    fn push_undo(&mut self, entry: SelectionHistoryEntry) {
  913        if self
  914            .undo_stack
  915            .back()
  916            .map_or(true, |e| e.selections != entry.selections)
  917        {
  918            self.undo_stack.push_back(entry);
  919            if self.undo_stack.len() > MAX_SELECTION_HISTORY_LEN {
  920                self.undo_stack.pop_front();
  921            }
  922        }
  923    }
  924
  925    fn push_redo(&mut self, entry: SelectionHistoryEntry) {
  926        if self
  927            .redo_stack
  928            .back()
  929            .map_or(true, |e| e.selections != entry.selections)
  930        {
  931            self.redo_stack.push_back(entry);
  932            if self.redo_stack.len() > MAX_SELECTION_HISTORY_LEN {
  933                self.redo_stack.pop_front();
  934            }
  935        }
  936    }
  937}
  938
  939struct RowHighlight {
  940    index: usize,
  941    range: Range<Anchor>,
  942    color: Hsla,
  943    should_autoscroll: bool,
  944}
  945
  946#[derive(Clone, Debug)]
  947struct AddSelectionsState {
  948    above: bool,
  949    stack: Vec<usize>,
  950}
  951
  952#[derive(Clone)]
  953struct SelectNextState {
  954    query: AhoCorasick,
  955    wordwise: bool,
  956    done: bool,
  957}
  958
  959impl std::fmt::Debug for SelectNextState {
  960    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  961        f.debug_struct(std::any::type_name::<Self>())
  962            .field("wordwise", &self.wordwise)
  963            .field("done", &self.done)
  964            .finish()
  965    }
  966}
  967
  968#[derive(Debug)]
  969struct AutocloseRegion {
  970    selection_id: usize,
  971    range: Range<Anchor>,
  972    pair: BracketPair,
  973}
  974
  975#[derive(Debug)]
  976struct SnippetState {
  977    ranges: Vec<Vec<Range<Anchor>>>,
  978    active_index: usize,
  979    choices: Vec<Option<Vec<String>>>,
  980}
  981
  982#[doc(hidden)]
  983pub struct RenameState {
  984    pub range: Range<Anchor>,
  985    pub old_name: Arc<str>,
  986    pub editor: Entity<Editor>,
  987    block_id: CustomBlockId,
  988}
  989
  990struct InvalidationStack<T>(Vec<T>);
  991
  992struct RegisteredInlineCompletionProvider {
  993    provider: Arc<dyn InlineCompletionProviderHandle>,
  994    _subscription: Subscription,
  995}
  996
  997#[derive(Debug, PartialEq, Eq)]
  998struct ActiveDiagnosticGroup {
  999    primary_range: Range<Anchor>,
 1000    primary_message: String,
 1001    group_id: usize,
 1002    blocks: HashMap<CustomBlockId, Diagnostic>,
 1003    is_valid: bool,
 1004}
 1005
 1006#[derive(Serialize, Deserialize, Clone, Debug)]
 1007pub struct ClipboardSelection {
 1008    /// The number of bytes in this selection.
 1009    pub len: usize,
 1010    /// Whether this was a full-line selection.
 1011    pub is_entire_line: bool,
 1012    /// The column where this selection originally started.
 1013    pub start_column: u32,
 1014}
 1015
 1016#[derive(Debug)]
 1017pub(crate) struct NavigationData {
 1018    cursor_anchor: Anchor,
 1019    cursor_position: Point,
 1020    scroll_anchor: ScrollAnchor,
 1021    scroll_top_row: u32,
 1022}
 1023
 1024#[derive(Debug, Clone, Copy, PartialEq, Eq)]
 1025pub enum GotoDefinitionKind {
 1026    Symbol,
 1027    Declaration,
 1028    Type,
 1029    Implementation,
 1030}
 1031
 1032#[derive(Debug, Clone)]
 1033enum InlayHintRefreshReason {
 1034    ModifiersChanged(bool),
 1035    Toggle(bool),
 1036    SettingsChange(InlayHintSettings),
 1037    NewLinesShown,
 1038    BufferEdited(HashSet<Arc<Language>>),
 1039    RefreshRequested,
 1040    ExcerptsRemoved(Vec<ExcerptId>),
 1041}
 1042
 1043impl InlayHintRefreshReason {
 1044    fn description(&self) -> &'static str {
 1045        match self {
 1046            Self::ModifiersChanged(_) => "modifiers changed",
 1047            Self::Toggle(_) => "toggle",
 1048            Self::SettingsChange(_) => "settings change",
 1049            Self::NewLinesShown => "new lines shown",
 1050            Self::BufferEdited(_) => "buffer edited",
 1051            Self::RefreshRequested => "refresh requested",
 1052            Self::ExcerptsRemoved(_) => "excerpts removed",
 1053        }
 1054    }
 1055}
 1056
 1057pub enum FormatTarget {
 1058    Buffers,
 1059    Ranges(Vec<Range<MultiBufferPoint>>),
 1060}
 1061
 1062pub(crate) struct FocusedBlock {
 1063    id: BlockId,
 1064    focus_handle: WeakFocusHandle,
 1065}
 1066
 1067#[derive(Clone)]
 1068enum JumpData {
 1069    MultiBufferRow {
 1070        row: MultiBufferRow,
 1071        line_offset_from_top: u32,
 1072    },
 1073    MultiBufferPoint {
 1074        excerpt_id: ExcerptId,
 1075        position: Point,
 1076        anchor: text::Anchor,
 1077        line_offset_from_top: u32,
 1078    },
 1079}
 1080
 1081pub enum MultibufferSelectionMode {
 1082    First,
 1083    All,
 1084}
 1085
 1086impl Editor {
 1087    pub fn single_line(window: &mut Window, cx: &mut Context<Self>) -> Self {
 1088        let buffer = cx.new(|cx| Buffer::local("", cx));
 1089        let buffer = cx.new(|cx| MultiBuffer::singleton(buffer, cx));
 1090        Self::new(
 1091            EditorMode::SingleLine { auto_width: false },
 1092            buffer,
 1093            None,
 1094            false,
 1095            window,
 1096            cx,
 1097        )
 1098    }
 1099
 1100    pub fn multi_line(window: &mut Window, cx: &mut Context<Self>) -> Self {
 1101        let buffer = cx.new(|cx| Buffer::local("", cx));
 1102        let buffer = cx.new(|cx| MultiBuffer::singleton(buffer, cx));
 1103        Self::new(EditorMode::Full, buffer, None, false, window, cx)
 1104    }
 1105
 1106    pub fn auto_width(window: &mut Window, cx: &mut Context<Self>) -> Self {
 1107        let buffer = cx.new(|cx| Buffer::local("", cx));
 1108        let buffer = cx.new(|cx| MultiBuffer::singleton(buffer, cx));
 1109        Self::new(
 1110            EditorMode::SingleLine { auto_width: true },
 1111            buffer,
 1112            None,
 1113            false,
 1114            window,
 1115            cx,
 1116        )
 1117    }
 1118
 1119    pub fn auto_height(max_lines: usize, window: &mut Window, cx: &mut Context<Self>) -> Self {
 1120        let buffer = cx.new(|cx| Buffer::local("", cx));
 1121        let buffer = cx.new(|cx| MultiBuffer::singleton(buffer, cx));
 1122        Self::new(
 1123            EditorMode::AutoHeight { max_lines },
 1124            buffer,
 1125            None,
 1126            false,
 1127            window,
 1128            cx,
 1129        )
 1130    }
 1131
 1132    pub fn for_buffer(
 1133        buffer: Entity<Buffer>,
 1134        project: Option<Entity<Project>>,
 1135        window: &mut Window,
 1136        cx: &mut Context<Self>,
 1137    ) -> Self {
 1138        let buffer = cx.new(|cx| MultiBuffer::singleton(buffer, cx));
 1139        Self::new(EditorMode::Full, buffer, project, false, window, cx)
 1140    }
 1141
 1142    pub fn for_multibuffer(
 1143        buffer: Entity<MultiBuffer>,
 1144        project: Option<Entity<Project>>,
 1145        show_excerpt_controls: bool,
 1146        window: &mut Window,
 1147        cx: &mut Context<Self>,
 1148    ) -> Self {
 1149        Self::new(
 1150            EditorMode::Full,
 1151            buffer,
 1152            project,
 1153            show_excerpt_controls,
 1154            window,
 1155            cx,
 1156        )
 1157    }
 1158
 1159    pub fn clone(&self, window: &mut Window, cx: &mut Context<Self>) -> Self {
 1160        let show_excerpt_controls = self.display_map.read(cx).show_excerpt_controls();
 1161        let mut clone = Self::new(
 1162            self.mode,
 1163            self.buffer.clone(),
 1164            self.project.clone(),
 1165            show_excerpt_controls,
 1166            window,
 1167            cx,
 1168        );
 1169        self.display_map.update(cx, |display_map, cx| {
 1170            let snapshot = display_map.snapshot(cx);
 1171            clone.display_map.update(cx, |display_map, cx| {
 1172                display_map.set_state(&snapshot, cx);
 1173            });
 1174        });
 1175        clone.selections.clone_state(&self.selections);
 1176        clone.scroll_manager.clone_state(&self.scroll_manager);
 1177        clone.searchable = self.searchable;
 1178        clone
 1179    }
 1180
 1181    pub fn new(
 1182        mode: EditorMode,
 1183        buffer: Entity<MultiBuffer>,
 1184        project: Option<Entity<Project>>,
 1185        show_excerpt_controls: bool,
 1186        window: &mut Window,
 1187        cx: &mut Context<Self>,
 1188    ) -> Self {
 1189        let style = window.text_style();
 1190        let font_size = style.font_size.to_pixels(window.rem_size());
 1191        let editor = cx.entity().downgrade();
 1192        let fold_placeholder = FoldPlaceholder {
 1193            constrain_width: true,
 1194            render: Arc::new(move |fold_id, fold_range, cx| {
 1195                let editor = editor.clone();
 1196                div()
 1197                    .id(fold_id)
 1198                    .bg(cx.theme().colors().ghost_element_background)
 1199                    .hover(|style| style.bg(cx.theme().colors().ghost_element_hover))
 1200                    .active(|style| style.bg(cx.theme().colors().ghost_element_active))
 1201                    .rounded_sm()
 1202                    .size_full()
 1203                    .cursor_pointer()
 1204                    .child("")
 1205                    .on_mouse_down(MouseButton::Left, |_, _, cx| cx.stop_propagation())
 1206                    .on_click(move |_, _window, cx| {
 1207                        editor
 1208                            .update(cx, |editor, cx| {
 1209                                editor.unfold_ranges(
 1210                                    &[fold_range.start..fold_range.end],
 1211                                    true,
 1212                                    false,
 1213                                    cx,
 1214                                );
 1215                                cx.stop_propagation();
 1216                            })
 1217                            .ok();
 1218                    })
 1219                    .into_any()
 1220            }),
 1221            merge_adjacent: true,
 1222            ..Default::default()
 1223        };
 1224        let display_map = cx.new(|cx| {
 1225            DisplayMap::new(
 1226                buffer.clone(),
 1227                style.font(),
 1228                font_size,
 1229                None,
 1230                show_excerpt_controls,
 1231                FILE_HEADER_HEIGHT,
 1232                MULTI_BUFFER_EXCERPT_HEADER_HEIGHT,
 1233                MULTI_BUFFER_EXCERPT_FOOTER_HEIGHT,
 1234                fold_placeholder,
 1235                cx,
 1236            )
 1237        });
 1238
 1239        let selections = SelectionsCollection::new(display_map.clone(), buffer.clone());
 1240
 1241        let blink_manager = cx.new(|cx| BlinkManager::new(CURSOR_BLINK_INTERVAL, cx));
 1242
 1243        let soft_wrap_mode_override = matches!(mode, EditorMode::SingleLine { .. })
 1244            .then(|| language_settings::SoftWrap::None);
 1245
 1246        let mut project_subscriptions = Vec::new();
 1247        if mode == EditorMode::Full {
 1248            if let Some(project) = project.as_ref() {
 1249                if buffer.read(cx).is_singleton() {
 1250                    project_subscriptions.push(cx.observe_in(project, window, |_, _, _, cx| {
 1251                        cx.emit(EditorEvent::TitleChanged);
 1252                    }));
 1253                }
 1254                project_subscriptions.push(cx.subscribe_in(
 1255                    project,
 1256                    window,
 1257                    |editor, _, event, window, cx| {
 1258                        if let project::Event::RefreshInlayHints = event {
 1259                            editor
 1260                                .refresh_inlay_hints(InlayHintRefreshReason::RefreshRequested, cx);
 1261                        } else if let project::Event::SnippetEdit(id, snippet_edits) = event {
 1262                            if let Some(buffer) = editor.buffer.read(cx).buffer(*id) {
 1263                                let focus_handle = editor.focus_handle(cx);
 1264                                if focus_handle.is_focused(window) {
 1265                                    let snapshot = buffer.read(cx).snapshot();
 1266                                    for (range, snippet) in snippet_edits {
 1267                                        let editor_range =
 1268                                            language::range_from_lsp(*range).to_offset(&snapshot);
 1269                                        editor
 1270                                            .insert_snippet(
 1271                                                &[editor_range],
 1272                                                snippet.clone(),
 1273                                                window,
 1274                                                cx,
 1275                                            )
 1276                                            .ok();
 1277                                    }
 1278                                }
 1279                            }
 1280                        }
 1281                    },
 1282                ));
 1283                if let Some(task_inventory) = project
 1284                    .read(cx)
 1285                    .task_store()
 1286                    .read(cx)
 1287                    .task_inventory()
 1288                    .cloned()
 1289                {
 1290                    project_subscriptions.push(cx.observe_in(
 1291                        &task_inventory,
 1292                        window,
 1293                        |editor, _, window, cx| {
 1294                            editor.tasks_update_task = Some(editor.refresh_runnables(window, cx));
 1295                        },
 1296                    ));
 1297                }
 1298            }
 1299        }
 1300
 1301        let buffer_snapshot = buffer.read(cx).snapshot(cx);
 1302
 1303        let inlay_hint_settings =
 1304            inlay_hint_settings(selections.newest_anchor().head(), &buffer_snapshot, cx);
 1305        let focus_handle = cx.focus_handle();
 1306        cx.on_focus(&focus_handle, window, Self::handle_focus)
 1307            .detach();
 1308        cx.on_focus_in(&focus_handle, window, Self::handle_focus_in)
 1309            .detach();
 1310        cx.on_focus_out(&focus_handle, window, Self::handle_focus_out)
 1311            .detach();
 1312        cx.on_blur(&focus_handle, window, Self::handle_blur)
 1313            .detach();
 1314
 1315        let show_indent_guides = if matches!(mode, EditorMode::SingleLine { .. }) {
 1316            Some(false)
 1317        } else {
 1318            None
 1319        };
 1320
 1321        let mut code_action_providers = Vec::new();
 1322        let mut load_uncommitted_diff = None;
 1323        if let Some(project) = project.clone() {
 1324            load_uncommitted_diff = Some(
 1325                get_uncommitted_diff_for_buffer(
 1326                    &project,
 1327                    buffer.read(cx).all_buffers(),
 1328                    buffer.clone(),
 1329                    cx,
 1330                )
 1331                .shared(),
 1332            );
 1333            code_action_providers.push(Rc::new(project) as Rc<_>);
 1334        }
 1335
 1336        let mut this = Self {
 1337            focus_handle,
 1338            show_cursor_when_unfocused: false,
 1339            last_focused_descendant: None,
 1340            buffer: buffer.clone(),
 1341            display_map: display_map.clone(),
 1342            selections,
 1343            scroll_manager: ScrollManager::new(cx),
 1344            columnar_selection_tail: None,
 1345            add_selections_state: None,
 1346            select_next_state: None,
 1347            select_prev_state: None,
 1348            selection_history: Default::default(),
 1349            autoclose_regions: Default::default(),
 1350            snippet_stack: Default::default(),
 1351            select_larger_syntax_node_stack: Vec::new(),
 1352            ime_transaction: Default::default(),
 1353            active_diagnostics: None,
 1354            show_inline_diagnostics: ProjectSettings::get_global(cx).diagnostics.inline.enabled,
 1355            inline_diagnostics_update: Task::ready(()),
 1356            inline_diagnostics: Vec::new(),
 1357            soft_wrap_mode_override,
 1358            completion_provider: project.clone().map(|project| Box::new(project) as _),
 1359            semantics_provider: project.clone().map(|project| Rc::new(project) as _),
 1360            collaboration_hub: project.clone().map(|project| Box::new(project) as _),
 1361            project,
 1362            blink_manager: blink_manager.clone(),
 1363            show_local_selections: true,
 1364            show_scrollbars: true,
 1365            mode,
 1366            show_breadcrumbs: EditorSettings::get_global(cx).toolbar.breadcrumbs,
 1367            show_gutter: mode == EditorMode::Full,
 1368            show_line_numbers: None,
 1369            use_relative_line_numbers: None,
 1370            show_git_diff_gutter: None,
 1371            show_code_actions: None,
 1372            show_runnables: None,
 1373            show_wrap_guides: None,
 1374            show_indent_guides,
 1375            placeholder_text: None,
 1376            highlight_order: 0,
 1377            highlighted_rows: HashMap::default(),
 1378            background_highlights: Default::default(),
 1379            gutter_highlights: TreeMap::default(),
 1380            scrollbar_marker_state: ScrollbarMarkerState::default(),
 1381            active_indent_guides_state: ActiveIndentGuidesState::default(),
 1382            nav_history: None,
 1383            context_menu: RefCell::new(None),
 1384            mouse_context_menu: None,
 1385            completion_tasks: Default::default(),
 1386            signature_help_state: SignatureHelpState::default(),
 1387            auto_signature_help: None,
 1388            find_all_references_task_sources: Vec::new(),
 1389            next_completion_id: 0,
 1390            next_inlay_id: 0,
 1391            code_action_providers,
 1392            available_code_actions: Default::default(),
 1393            code_actions_task: Default::default(),
 1394            selection_highlight_task: Default::default(),
 1395            document_highlights_task: Default::default(),
 1396            linked_editing_range_task: Default::default(),
 1397            pending_rename: Default::default(),
 1398            searchable: true,
 1399            cursor_shape: EditorSettings::get_global(cx)
 1400                .cursor_shape
 1401                .unwrap_or_default(),
 1402            current_line_highlight: None,
 1403            autoindent_mode: Some(AutoindentMode::EachLine),
 1404            collapse_matches: false,
 1405            workspace: None,
 1406            input_enabled: true,
 1407            use_modal_editing: mode == EditorMode::Full,
 1408            read_only: false,
 1409            use_autoclose: true,
 1410            use_auto_surround: true,
 1411            auto_replace_emoji_shortcode: false,
 1412            leader_peer_id: None,
 1413            remote_id: None,
 1414            hover_state: Default::default(),
 1415            pending_mouse_down: None,
 1416            hovered_link_state: Default::default(),
 1417            edit_prediction_provider: None,
 1418            active_inline_completion: None,
 1419            stale_inline_completion_in_menu: None,
 1420            edit_prediction_preview: EditPredictionPreview::Inactive {
 1421                released_too_fast: false,
 1422            },
 1423            inline_diagnostics_enabled: mode == EditorMode::Full,
 1424            inlay_hint_cache: InlayHintCache::new(inlay_hint_settings),
 1425
 1426            gutter_hovered: false,
 1427            pixel_position_of_newest_cursor: None,
 1428            last_bounds: None,
 1429            last_position_map: None,
 1430            expect_bounds_change: None,
 1431            gutter_dimensions: GutterDimensions::default(),
 1432            style: None,
 1433            show_cursor_names: false,
 1434            hovered_cursors: Default::default(),
 1435            next_editor_action_id: EditorActionId::default(),
 1436            editor_actions: Rc::default(),
 1437            inline_completions_hidden_for_vim_mode: false,
 1438            show_inline_completions_override: None,
 1439            menu_inline_completions_policy: MenuInlineCompletionsPolicy::ByProvider,
 1440            edit_prediction_settings: EditPredictionSettings::Disabled,
 1441            edit_prediction_indent_conflict: false,
 1442            edit_prediction_requires_modifier_in_indent_conflict: true,
 1443            custom_context_menu: None,
 1444            show_git_blame_gutter: false,
 1445            show_git_blame_inline: false,
 1446            show_selection_menu: None,
 1447            show_git_blame_inline_delay_task: None,
 1448            git_blame_inline_tooltip: None,
 1449            git_blame_inline_enabled: ProjectSettings::get_global(cx).git.inline_blame_enabled(),
 1450            serialize_dirty_buffers: ProjectSettings::get_global(cx)
 1451                .session
 1452                .restore_unsaved_buffers,
 1453            blame: None,
 1454            blame_subscription: None,
 1455            tasks: Default::default(),
 1456            _subscriptions: vec![
 1457                cx.observe(&buffer, Self::on_buffer_changed),
 1458                cx.subscribe_in(&buffer, window, Self::on_buffer_event),
 1459                cx.observe_in(&display_map, window, Self::on_display_map_changed),
 1460                cx.observe(&blink_manager, |_, _, cx| cx.notify()),
 1461                cx.observe_global_in::<SettingsStore>(window, Self::settings_changed),
 1462                observe_buffer_font_size_adjustment(cx, |_, cx| cx.notify()),
 1463                cx.observe_window_activation(window, |editor, window, cx| {
 1464                    let active = window.is_window_active();
 1465                    editor.blink_manager.update(cx, |blink_manager, cx| {
 1466                        if active {
 1467                            blink_manager.enable(cx);
 1468                        } else {
 1469                            blink_manager.disable(cx);
 1470                        }
 1471                    });
 1472                }),
 1473            ],
 1474            tasks_update_task: None,
 1475            linked_edit_ranges: Default::default(),
 1476            in_project_search: false,
 1477            previous_search_ranges: None,
 1478            breadcrumb_header: None,
 1479            focused_block: None,
 1480            next_scroll_position: NextScrollCursorCenterTopBottom::default(),
 1481            addons: HashMap::default(),
 1482            registered_buffers: HashMap::default(),
 1483            _scroll_cursor_center_top_bottom_task: Task::ready(()),
 1484            selection_mark_mode: false,
 1485            toggle_fold_multiple_buffers: Task::ready(()),
 1486            serialize_selections: Task::ready(()),
 1487            text_style_refinement: None,
 1488            load_diff_task: load_uncommitted_diff,
 1489        };
 1490        this.tasks_update_task = Some(this.refresh_runnables(window, cx));
 1491        this._subscriptions.extend(project_subscriptions);
 1492
 1493        this.end_selection(window, cx);
 1494        this.scroll_manager.show_scrollbar(window, cx);
 1495
 1496        if mode == EditorMode::Full {
 1497            let should_auto_hide_scrollbars = cx.should_auto_hide_scrollbars();
 1498            cx.set_global(ScrollbarAutoHide(should_auto_hide_scrollbars));
 1499
 1500            if this.git_blame_inline_enabled {
 1501                this.git_blame_inline_enabled = true;
 1502                this.start_git_blame_inline(false, window, cx);
 1503            }
 1504
 1505            if let Some(buffer) = buffer.read(cx).as_singleton() {
 1506                if let Some(project) = this.project.as_ref() {
 1507                    let handle = project.update(cx, |project, cx| {
 1508                        project.register_buffer_with_language_servers(&buffer, cx)
 1509                    });
 1510                    this.registered_buffers
 1511                        .insert(buffer.read(cx).remote_id(), handle);
 1512                }
 1513            }
 1514        }
 1515
 1516        this.report_editor_event("Editor Opened", None, cx);
 1517        this
 1518    }
 1519
 1520    pub fn mouse_menu_is_focused(&self, window: &Window, cx: &App) -> bool {
 1521        self.mouse_context_menu
 1522            .as_ref()
 1523            .is_some_and(|menu| menu.context_menu.focus_handle(cx).is_focused(window))
 1524    }
 1525
 1526    fn key_context(&self, window: &Window, cx: &App) -> KeyContext {
 1527        self.key_context_internal(self.has_active_inline_completion(), window, cx)
 1528    }
 1529
 1530    fn key_context_internal(
 1531        &self,
 1532        has_active_edit_prediction: bool,
 1533        window: &Window,
 1534        cx: &App,
 1535    ) -> KeyContext {
 1536        let mut key_context = KeyContext::new_with_defaults();
 1537        key_context.add("Editor");
 1538        let mode = match self.mode {
 1539            EditorMode::SingleLine { .. } => "single_line",
 1540            EditorMode::AutoHeight { .. } => "auto_height",
 1541            EditorMode::Full => "full",
 1542        };
 1543
 1544        if EditorSettings::jupyter_enabled(cx) {
 1545            key_context.add("jupyter");
 1546        }
 1547
 1548        key_context.set("mode", mode);
 1549        if self.pending_rename.is_some() {
 1550            key_context.add("renaming");
 1551        }
 1552
 1553        match self.context_menu.borrow().as_ref() {
 1554            Some(CodeContextMenu::Completions(_)) => {
 1555                key_context.add("menu");
 1556                key_context.add("showing_completions");
 1557            }
 1558            Some(CodeContextMenu::CodeActions(_)) => {
 1559                key_context.add("menu");
 1560                key_context.add("showing_code_actions")
 1561            }
 1562            None => {}
 1563        }
 1564
 1565        // Disable vim contexts when a sub-editor (e.g. rename/inline assistant) is focused.
 1566        if !self.focus_handle(cx).contains_focused(window, cx)
 1567            || (self.is_focused(window) || self.mouse_menu_is_focused(window, cx))
 1568        {
 1569            for addon in self.addons.values() {
 1570                addon.extend_key_context(&mut key_context, cx)
 1571            }
 1572        }
 1573
 1574        if let Some(extension) = self
 1575            .buffer
 1576            .read(cx)
 1577            .as_singleton()
 1578            .and_then(|buffer| buffer.read(cx).file()?.path().extension()?.to_str())
 1579        {
 1580            key_context.set("extension", extension.to_string());
 1581        }
 1582
 1583        if has_active_edit_prediction {
 1584            if self.edit_prediction_in_conflict() {
 1585                key_context.add(EDIT_PREDICTION_CONFLICT_KEY_CONTEXT);
 1586            } else {
 1587                key_context.add(EDIT_PREDICTION_KEY_CONTEXT);
 1588                key_context.add("copilot_suggestion");
 1589            }
 1590        }
 1591
 1592        if self.selection_mark_mode {
 1593            key_context.add("selection_mode");
 1594        }
 1595
 1596        key_context
 1597    }
 1598
 1599    pub fn edit_prediction_in_conflict(&self) -> bool {
 1600        if !self.show_edit_predictions_in_menu() {
 1601            return false;
 1602        }
 1603
 1604        let showing_completions = self
 1605            .context_menu
 1606            .borrow()
 1607            .as_ref()
 1608            .map_or(false, |context| {
 1609                matches!(context, CodeContextMenu::Completions(_))
 1610            });
 1611
 1612        showing_completions
 1613            || self.edit_prediction_requires_modifier()
 1614            // Require modifier key when the cursor is on leading whitespace, to allow `tab`
 1615            // bindings to insert tab characters.
 1616            || (self.edit_prediction_requires_modifier_in_indent_conflict && self.edit_prediction_indent_conflict)
 1617    }
 1618
 1619    pub fn accept_edit_prediction_keybind(
 1620        &self,
 1621        window: &Window,
 1622        cx: &App,
 1623    ) -> AcceptEditPredictionBinding {
 1624        let key_context = self.key_context_internal(true, window, cx);
 1625        let in_conflict = self.edit_prediction_in_conflict();
 1626
 1627        AcceptEditPredictionBinding(
 1628            window
 1629                .bindings_for_action_in_context(&AcceptEditPrediction, key_context)
 1630                .into_iter()
 1631                .filter(|binding| {
 1632                    !in_conflict
 1633                        || binding
 1634                            .keystrokes()
 1635                            .first()
 1636                            .map_or(false, |keystroke| keystroke.modifiers.modified())
 1637                })
 1638                .rev()
 1639                .min_by_key(|binding| {
 1640                    binding
 1641                        .keystrokes()
 1642                        .first()
 1643                        .map_or(u8::MAX, |k| k.modifiers.number_of_modifiers())
 1644                }),
 1645        )
 1646    }
 1647
 1648    pub fn new_file(
 1649        workspace: &mut Workspace,
 1650        _: &workspace::NewFile,
 1651        window: &mut Window,
 1652        cx: &mut Context<Workspace>,
 1653    ) {
 1654        Self::new_in_workspace(workspace, window, cx).detach_and_prompt_err(
 1655            "Failed to create buffer",
 1656            window,
 1657            cx,
 1658            |e, _, _| match e.error_code() {
 1659                ErrorCode::RemoteUpgradeRequired => Some(format!(
 1660                "The remote instance of Zed does not support this yet. It must be upgraded to {}",
 1661                e.error_tag("required").unwrap_or("the latest version")
 1662            )),
 1663                _ => None,
 1664            },
 1665        );
 1666    }
 1667
 1668    pub fn new_in_workspace(
 1669        workspace: &mut Workspace,
 1670        window: &mut Window,
 1671        cx: &mut Context<Workspace>,
 1672    ) -> Task<Result<Entity<Editor>>> {
 1673        let project = workspace.project().clone();
 1674        let create = project.update(cx, |project, cx| project.create_buffer(cx));
 1675
 1676        cx.spawn_in(window, |workspace, mut cx| async move {
 1677            let buffer = create.await?;
 1678            workspace.update_in(&mut cx, |workspace, window, cx| {
 1679                let editor =
 1680                    cx.new(|cx| Editor::for_buffer(buffer, Some(project.clone()), window, cx));
 1681                workspace.add_item_to_active_pane(Box::new(editor.clone()), None, true, window, cx);
 1682                editor
 1683            })
 1684        })
 1685    }
 1686
 1687    fn new_file_vertical(
 1688        workspace: &mut Workspace,
 1689        _: &workspace::NewFileSplitVertical,
 1690        window: &mut Window,
 1691        cx: &mut Context<Workspace>,
 1692    ) {
 1693        Self::new_file_in_direction(workspace, SplitDirection::vertical(cx), window, cx)
 1694    }
 1695
 1696    fn new_file_horizontal(
 1697        workspace: &mut Workspace,
 1698        _: &workspace::NewFileSplitHorizontal,
 1699        window: &mut Window,
 1700        cx: &mut Context<Workspace>,
 1701    ) {
 1702        Self::new_file_in_direction(workspace, SplitDirection::horizontal(cx), window, cx)
 1703    }
 1704
 1705    fn new_file_in_direction(
 1706        workspace: &mut Workspace,
 1707        direction: SplitDirection,
 1708        window: &mut Window,
 1709        cx: &mut Context<Workspace>,
 1710    ) {
 1711        let project = workspace.project().clone();
 1712        let create = project.update(cx, |project, cx| project.create_buffer(cx));
 1713
 1714        cx.spawn_in(window, |workspace, mut cx| async move {
 1715            let buffer = create.await?;
 1716            workspace.update_in(&mut cx, move |workspace, window, cx| {
 1717                workspace.split_item(
 1718                    direction,
 1719                    Box::new(
 1720                        cx.new(|cx| Editor::for_buffer(buffer, Some(project.clone()), window, cx)),
 1721                    ),
 1722                    window,
 1723                    cx,
 1724                )
 1725            })?;
 1726            anyhow::Ok(())
 1727        })
 1728        .detach_and_prompt_err("Failed to create buffer", window, cx, |e, _, _| {
 1729            match e.error_code() {
 1730                ErrorCode::RemoteUpgradeRequired => Some(format!(
 1731                "The remote instance of Zed does not support this yet. It must be upgraded to {}",
 1732                e.error_tag("required").unwrap_or("the latest version")
 1733            )),
 1734                _ => None,
 1735            }
 1736        });
 1737    }
 1738
 1739    pub fn leader_peer_id(&self) -> Option<PeerId> {
 1740        self.leader_peer_id
 1741    }
 1742
 1743    pub fn buffer(&self) -> &Entity<MultiBuffer> {
 1744        &self.buffer
 1745    }
 1746
 1747    pub fn workspace(&self) -> Option<Entity<Workspace>> {
 1748        self.workspace.as_ref()?.0.upgrade()
 1749    }
 1750
 1751    pub fn title<'a>(&self, cx: &'a App) -> Cow<'a, str> {
 1752        self.buffer().read(cx).title(cx)
 1753    }
 1754
 1755    pub fn snapshot(&self, window: &mut Window, cx: &mut App) -> EditorSnapshot {
 1756        let git_blame_gutter_max_author_length = self
 1757            .render_git_blame_gutter(cx)
 1758            .then(|| {
 1759                if let Some(blame) = self.blame.as_ref() {
 1760                    let max_author_length =
 1761                        blame.update(cx, |blame, cx| blame.max_author_length(cx));
 1762                    Some(max_author_length)
 1763                } else {
 1764                    None
 1765                }
 1766            })
 1767            .flatten();
 1768
 1769        EditorSnapshot {
 1770            mode: self.mode,
 1771            show_gutter: self.show_gutter,
 1772            show_line_numbers: self.show_line_numbers,
 1773            show_git_diff_gutter: self.show_git_diff_gutter,
 1774            show_code_actions: self.show_code_actions,
 1775            show_runnables: self.show_runnables,
 1776            git_blame_gutter_max_author_length,
 1777            display_snapshot: self.display_map.update(cx, |map, cx| map.snapshot(cx)),
 1778            scroll_anchor: self.scroll_manager.anchor(),
 1779            ongoing_scroll: self.scroll_manager.ongoing_scroll(),
 1780            placeholder_text: self.placeholder_text.clone(),
 1781            is_focused: self.focus_handle.is_focused(window),
 1782            current_line_highlight: self
 1783                .current_line_highlight
 1784                .unwrap_or_else(|| EditorSettings::get_global(cx).current_line_highlight),
 1785            gutter_hovered: self.gutter_hovered,
 1786        }
 1787    }
 1788
 1789    pub fn language_at<T: ToOffset>(&self, point: T, cx: &App) -> Option<Arc<Language>> {
 1790        self.buffer.read(cx).language_at(point, cx)
 1791    }
 1792
 1793    pub fn file_at<T: ToOffset>(&self, point: T, cx: &App) -> Option<Arc<dyn language::File>> {
 1794        self.buffer.read(cx).read(cx).file_at(point).cloned()
 1795    }
 1796
 1797    pub fn active_excerpt(
 1798        &self,
 1799        cx: &App,
 1800    ) -> Option<(ExcerptId, Entity<Buffer>, Range<text::Anchor>)> {
 1801        self.buffer
 1802            .read(cx)
 1803            .excerpt_containing(self.selections.newest_anchor().head(), cx)
 1804    }
 1805
 1806    pub fn mode(&self) -> EditorMode {
 1807        self.mode
 1808    }
 1809
 1810    pub fn collaboration_hub(&self) -> Option<&dyn CollaborationHub> {
 1811        self.collaboration_hub.as_deref()
 1812    }
 1813
 1814    pub fn set_collaboration_hub(&mut self, hub: Box<dyn CollaborationHub>) {
 1815        self.collaboration_hub = Some(hub);
 1816    }
 1817
 1818    pub fn set_in_project_search(&mut self, in_project_search: bool) {
 1819        self.in_project_search = in_project_search;
 1820    }
 1821
 1822    pub fn set_custom_context_menu(
 1823        &mut self,
 1824        f: impl 'static
 1825            + Fn(
 1826                &mut Self,
 1827                DisplayPoint,
 1828                &mut Window,
 1829                &mut Context<Self>,
 1830            ) -> Option<Entity<ui::ContextMenu>>,
 1831    ) {
 1832        self.custom_context_menu = Some(Box::new(f))
 1833    }
 1834
 1835    pub fn set_completion_provider(&mut self, provider: Option<Box<dyn CompletionProvider>>) {
 1836        self.completion_provider = provider;
 1837    }
 1838
 1839    pub fn semantics_provider(&self) -> Option<Rc<dyn SemanticsProvider>> {
 1840        self.semantics_provider.clone()
 1841    }
 1842
 1843    pub fn set_semantics_provider(&mut self, provider: Option<Rc<dyn SemanticsProvider>>) {
 1844        self.semantics_provider = provider;
 1845    }
 1846
 1847    pub fn set_edit_prediction_provider<T>(
 1848        &mut self,
 1849        provider: Option<Entity<T>>,
 1850        window: &mut Window,
 1851        cx: &mut Context<Self>,
 1852    ) where
 1853        T: EditPredictionProvider,
 1854    {
 1855        self.edit_prediction_provider =
 1856            provider.map(|provider| RegisteredInlineCompletionProvider {
 1857                _subscription: cx.observe_in(&provider, window, |this, _, window, cx| {
 1858                    if this.focus_handle.is_focused(window) {
 1859                        this.update_visible_inline_completion(window, cx);
 1860                    }
 1861                }),
 1862                provider: Arc::new(provider),
 1863            });
 1864        self.update_edit_prediction_settings(cx);
 1865        self.refresh_inline_completion(false, false, window, cx);
 1866    }
 1867
 1868    pub fn placeholder_text(&self) -> Option<&str> {
 1869        self.placeholder_text.as_deref()
 1870    }
 1871
 1872    pub fn set_placeholder_text(
 1873        &mut self,
 1874        placeholder_text: impl Into<Arc<str>>,
 1875        cx: &mut Context<Self>,
 1876    ) {
 1877        let placeholder_text = Some(placeholder_text.into());
 1878        if self.placeholder_text != placeholder_text {
 1879            self.placeholder_text = placeholder_text;
 1880            cx.notify();
 1881        }
 1882    }
 1883
 1884    pub fn set_cursor_shape(&mut self, cursor_shape: CursorShape, cx: &mut Context<Self>) {
 1885        self.cursor_shape = cursor_shape;
 1886
 1887        // Disrupt blink for immediate user feedback that the cursor shape has changed
 1888        self.blink_manager.update(cx, BlinkManager::show_cursor);
 1889
 1890        cx.notify();
 1891    }
 1892
 1893    pub fn set_current_line_highlight(
 1894        &mut self,
 1895        current_line_highlight: Option<CurrentLineHighlight>,
 1896    ) {
 1897        self.current_line_highlight = current_line_highlight;
 1898    }
 1899
 1900    pub fn set_collapse_matches(&mut self, collapse_matches: bool) {
 1901        self.collapse_matches = collapse_matches;
 1902    }
 1903
 1904    fn register_buffers_with_language_servers(&mut self, cx: &mut Context<Self>) {
 1905        let buffers = self.buffer.read(cx).all_buffers();
 1906        let Some(project) = self.project.as_ref() else {
 1907            return;
 1908        };
 1909        project.update(cx, |project, cx| {
 1910            for buffer in buffers {
 1911                self.registered_buffers
 1912                    .entry(buffer.read(cx).remote_id())
 1913                    .or_insert_with(|| project.register_buffer_with_language_servers(&buffer, cx));
 1914            }
 1915        })
 1916    }
 1917
 1918    pub fn range_for_match<T: std::marker::Copy>(&self, range: &Range<T>) -> Range<T> {
 1919        if self.collapse_matches {
 1920            return range.start..range.start;
 1921        }
 1922        range.clone()
 1923    }
 1924
 1925    pub fn set_clip_at_line_ends(&mut self, clip: bool, cx: &mut Context<Self>) {
 1926        if self.display_map.read(cx).clip_at_line_ends != clip {
 1927            self.display_map
 1928                .update(cx, |map, _| map.clip_at_line_ends = clip);
 1929        }
 1930    }
 1931
 1932    pub fn set_input_enabled(&mut self, input_enabled: bool) {
 1933        self.input_enabled = input_enabled;
 1934    }
 1935
 1936    pub fn set_inline_completions_hidden_for_vim_mode(
 1937        &mut self,
 1938        hidden: bool,
 1939        window: &mut Window,
 1940        cx: &mut Context<Self>,
 1941    ) {
 1942        if hidden != self.inline_completions_hidden_for_vim_mode {
 1943            self.inline_completions_hidden_for_vim_mode = hidden;
 1944            if hidden {
 1945                self.update_visible_inline_completion(window, cx);
 1946            } else {
 1947                self.refresh_inline_completion(true, false, window, cx);
 1948            }
 1949        }
 1950    }
 1951
 1952    pub fn set_menu_inline_completions_policy(&mut self, value: MenuInlineCompletionsPolicy) {
 1953        self.menu_inline_completions_policy = value;
 1954    }
 1955
 1956    pub fn set_autoindent(&mut self, autoindent: bool) {
 1957        if autoindent {
 1958            self.autoindent_mode = Some(AutoindentMode::EachLine);
 1959        } else {
 1960            self.autoindent_mode = None;
 1961        }
 1962    }
 1963
 1964    pub fn read_only(&self, cx: &App) -> bool {
 1965        self.read_only || self.buffer.read(cx).read_only()
 1966    }
 1967
 1968    pub fn set_read_only(&mut self, read_only: bool) {
 1969        self.read_only = read_only;
 1970    }
 1971
 1972    pub fn set_use_autoclose(&mut self, autoclose: bool) {
 1973        self.use_autoclose = autoclose;
 1974    }
 1975
 1976    pub fn set_use_auto_surround(&mut self, auto_surround: bool) {
 1977        self.use_auto_surround = auto_surround;
 1978    }
 1979
 1980    pub fn set_auto_replace_emoji_shortcode(&mut self, auto_replace: bool) {
 1981        self.auto_replace_emoji_shortcode = auto_replace;
 1982    }
 1983
 1984    pub fn toggle_edit_predictions(
 1985        &mut self,
 1986        _: &ToggleEditPrediction,
 1987        window: &mut Window,
 1988        cx: &mut Context<Self>,
 1989    ) {
 1990        if self.show_inline_completions_override.is_some() {
 1991            self.set_show_edit_predictions(None, window, cx);
 1992        } else {
 1993            let show_edit_predictions = !self.edit_predictions_enabled();
 1994            self.set_show_edit_predictions(Some(show_edit_predictions), window, cx);
 1995        }
 1996    }
 1997
 1998    pub fn set_show_edit_predictions(
 1999        &mut self,
 2000        show_edit_predictions: Option<bool>,
 2001        window: &mut Window,
 2002        cx: &mut Context<Self>,
 2003    ) {
 2004        self.show_inline_completions_override = show_edit_predictions;
 2005        self.update_edit_prediction_settings(cx);
 2006
 2007        if let Some(false) = show_edit_predictions {
 2008            self.discard_inline_completion(false, cx);
 2009        } else {
 2010            self.refresh_inline_completion(false, true, window, cx);
 2011        }
 2012    }
 2013
 2014    fn inline_completions_disabled_in_scope(
 2015        &self,
 2016        buffer: &Entity<Buffer>,
 2017        buffer_position: language::Anchor,
 2018        cx: &App,
 2019    ) -> bool {
 2020        let snapshot = buffer.read(cx).snapshot();
 2021        let settings = snapshot.settings_at(buffer_position, cx);
 2022
 2023        let Some(scope) = snapshot.language_scope_at(buffer_position) else {
 2024            return false;
 2025        };
 2026
 2027        scope.override_name().map_or(false, |scope_name| {
 2028            settings
 2029                .edit_predictions_disabled_in
 2030                .iter()
 2031                .any(|s| s == scope_name)
 2032        })
 2033    }
 2034
 2035    pub fn set_use_modal_editing(&mut self, to: bool) {
 2036        self.use_modal_editing = to;
 2037    }
 2038
 2039    pub fn use_modal_editing(&self) -> bool {
 2040        self.use_modal_editing
 2041    }
 2042
 2043    fn selections_did_change(
 2044        &mut self,
 2045        local: bool,
 2046        old_cursor_position: &Anchor,
 2047        show_completions: bool,
 2048        window: &mut Window,
 2049        cx: &mut Context<Self>,
 2050    ) {
 2051        window.invalidate_character_coordinates();
 2052
 2053        // Copy selections to primary selection buffer
 2054        #[cfg(any(target_os = "linux", target_os = "freebsd"))]
 2055        if local {
 2056            let selections = self.selections.all::<usize>(cx);
 2057            let buffer_handle = self.buffer.read(cx).read(cx);
 2058
 2059            let mut text = String::new();
 2060            for (index, selection) in selections.iter().enumerate() {
 2061                let text_for_selection = buffer_handle
 2062                    .text_for_range(selection.start..selection.end)
 2063                    .collect::<String>();
 2064
 2065                text.push_str(&text_for_selection);
 2066                if index != selections.len() - 1 {
 2067                    text.push('\n');
 2068                }
 2069            }
 2070
 2071            if !text.is_empty() {
 2072                cx.write_to_primary(ClipboardItem::new_string(text));
 2073            }
 2074        }
 2075
 2076        if self.focus_handle.is_focused(window) && self.leader_peer_id.is_none() {
 2077            self.buffer.update(cx, |buffer, cx| {
 2078                buffer.set_active_selections(
 2079                    &self.selections.disjoint_anchors(),
 2080                    self.selections.line_mode,
 2081                    self.cursor_shape,
 2082                    cx,
 2083                )
 2084            });
 2085        }
 2086        let display_map = self
 2087            .display_map
 2088            .update(cx, |display_map, cx| display_map.snapshot(cx));
 2089        let buffer = &display_map.buffer_snapshot;
 2090        self.add_selections_state = None;
 2091        self.select_next_state = None;
 2092        self.select_prev_state = None;
 2093        self.select_larger_syntax_node_stack.clear();
 2094        self.invalidate_autoclose_regions(&self.selections.disjoint_anchors(), buffer);
 2095        self.snippet_stack
 2096            .invalidate(&self.selections.disjoint_anchors(), buffer);
 2097        self.take_rename(false, window, cx);
 2098
 2099        let new_cursor_position = self.selections.newest_anchor().head();
 2100
 2101        self.push_to_nav_history(
 2102            *old_cursor_position,
 2103            Some(new_cursor_position.to_point(buffer)),
 2104            cx,
 2105        );
 2106
 2107        if local {
 2108            let new_cursor_position = self.selections.newest_anchor().head();
 2109            let mut context_menu = self.context_menu.borrow_mut();
 2110            let completion_menu = match context_menu.as_ref() {
 2111                Some(CodeContextMenu::Completions(menu)) => Some(menu),
 2112                _ => {
 2113                    *context_menu = None;
 2114                    None
 2115                }
 2116            };
 2117            if let Some(buffer_id) = new_cursor_position.buffer_id {
 2118                if !self.registered_buffers.contains_key(&buffer_id) {
 2119                    if let Some(project) = self.project.as_ref() {
 2120                        project.update(cx, |project, cx| {
 2121                            let Some(buffer) = self.buffer.read(cx).buffer(buffer_id) else {
 2122                                return;
 2123                            };
 2124                            self.registered_buffers.insert(
 2125                                buffer_id,
 2126                                project.register_buffer_with_language_servers(&buffer, cx),
 2127                            );
 2128                        })
 2129                    }
 2130                }
 2131            }
 2132
 2133            if let Some(completion_menu) = completion_menu {
 2134                let cursor_position = new_cursor_position.to_offset(buffer);
 2135                let (word_range, kind) =
 2136                    buffer.surrounding_word(completion_menu.initial_position, true);
 2137                if kind == Some(CharKind::Word)
 2138                    && word_range.to_inclusive().contains(&cursor_position)
 2139                {
 2140                    let mut completion_menu = completion_menu.clone();
 2141                    drop(context_menu);
 2142
 2143                    let query = Self::completion_query(buffer, cursor_position);
 2144                    cx.spawn(move |this, mut cx| async move {
 2145                        completion_menu
 2146                            .filter(query.as_deref(), cx.background_executor().clone())
 2147                            .await;
 2148
 2149                        this.update(&mut cx, |this, cx| {
 2150                            let mut context_menu = this.context_menu.borrow_mut();
 2151                            let Some(CodeContextMenu::Completions(menu)) = context_menu.as_ref()
 2152                            else {
 2153                                return;
 2154                            };
 2155
 2156                            if menu.id > completion_menu.id {
 2157                                return;
 2158                            }
 2159
 2160                            *context_menu = Some(CodeContextMenu::Completions(completion_menu));
 2161                            drop(context_menu);
 2162                            cx.notify();
 2163                        })
 2164                    })
 2165                    .detach();
 2166
 2167                    if show_completions {
 2168                        self.show_completions(&ShowCompletions { trigger: None }, window, cx);
 2169                    }
 2170                } else {
 2171                    drop(context_menu);
 2172                    self.hide_context_menu(window, cx);
 2173                }
 2174            } else {
 2175                drop(context_menu);
 2176            }
 2177
 2178            hide_hover(self, cx);
 2179
 2180            if old_cursor_position.to_display_point(&display_map).row()
 2181                != new_cursor_position.to_display_point(&display_map).row()
 2182            {
 2183                self.available_code_actions.take();
 2184            }
 2185            self.refresh_code_actions(window, cx);
 2186            self.refresh_document_highlights(cx);
 2187            self.refresh_selected_text_highlights(window, cx);
 2188            refresh_matching_bracket_highlights(self, window, cx);
 2189            self.update_visible_inline_completion(window, cx);
 2190            self.edit_prediction_requires_modifier_in_indent_conflict = true;
 2191            linked_editing_ranges::refresh_linked_ranges(self, window, cx);
 2192            if self.git_blame_inline_enabled {
 2193                self.start_inline_blame_timer(window, cx);
 2194            }
 2195        }
 2196
 2197        self.blink_manager.update(cx, BlinkManager::pause_blinking);
 2198        cx.emit(EditorEvent::SelectionsChanged { local });
 2199
 2200        let selections = &self.selections.disjoint;
 2201        if selections.len() == 1 {
 2202            cx.emit(SearchEvent::ActiveMatchChanged)
 2203        }
 2204        if local
 2205            && self.is_singleton(cx)
 2206            && WorkspaceSettings::get(None, cx).restore_on_startup != RestoreOnStartupBehavior::None
 2207        {
 2208            if let Some(workspace_id) = self.workspace.as_ref().and_then(|workspace| workspace.1) {
 2209                let background_executor = cx.background_executor().clone();
 2210                let editor_id = cx.entity().entity_id().as_u64() as ItemId;
 2211                let snapshot = self.buffer().read(cx).snapshot(cx);
 2212                let selections = selections.clone();
 2213                self.serialize_selections = cx.background_spawn(async move {
 2214                    background_executor.timer(Duration::from_millis(100)).await;
 2215                    let selections = selections
 2216                        .iter()
 2217                        .map(|selection| {
 2218                            (
 2219                                selection.start.to_offset(&snapshot),
 2220                                selection.end.to_offset(&snapshot),
 2221                            )
 2222                        })
 2223                        .collect();
 2224                    DB.save_editor_selections(editor_id, workspace_id, selections)
 2225                        .await
 2226                        .with_context(|| format!("persisting editor selections for editor {editor_id}, workspace {workspace_id:?}"))
 2227                        .log_err();
 2228                });
 2229            }
 2230        }
 2231
 2232        cx.notify();
 2233    }
 2234
 2235    pub fn change_selections<R>(
 2236        &mut self,
 2237        autoscroll: Option<Autoscroll>,
 2238        window: &mut Window,
 2239        cx: &mut Context<Self>,
 2240        change: impl FnOnce(&mut MutableSelectionsCollection<'_>) -> R,
 2241    ) -> R {
 2242        self.change_selections_inner(autoscroll, true, window, cx, change)
 2243    }
 2244
 2245    fn change_selections_inner<R>(
 2246        &mut self,
 2247        autoscroll: Option<Autoscroll>,
 2248        request_completions: bool,
 2249        window: &mut Window,
 2250        cx: &mut Context<Self>,
 2251        change: impl FnOnce(&mut MutableSelectionsCollection<'_>) -> R,
 2252    ) -> R {
 2253        let old_cursor_position = self.selections.newest_anchor().head();
 2254        self.push_to_selection_history();
 2255
 2256        let (changed, result) = self.selections.change_with(cx, change);
 2257
 2258        if changed {
 2259            if let Some(autoscroll) = autoscroll {
 2260                self.request_autoscroll(autoscroll, cx);
 2261            }
 2262            self.selections_did_change(true, &old_cursor_position, request_completions, window, cx);
 2263
 2264            if self.should_open_signature_help_automatically(
 2265                &old_cursor_position,
 2266                self.signature_help_state.backspace_pressed(),
 2267                cx,
 2268            ) {
 2269                self.show_signature_help(&ShowSignatureHelp, window, cx);
 2270            }
 2271            self.signature_help_state.set_backspace_pressed(false);
 2272        }
 2273
 2274        result
 2275    }
 2276
 2277    pub fn edit<I, S, T>(&mut self, edits: I, cx: &mut Context<Self>)
 2278    where
 2279        I: IntoIterator<Item = (Range<S>, T)>,
 2280        S: ToOffset,
 2281        T: Into<Arc<str>>,
 2282    {
 2283        if self.read_only(cx) {
 2284            return;
 2285        }
 2286
 2287        self.buffer
 2288            .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
 2289    }
 2290
 2291    pub fn edit_with_autoindent<I, S, T>(&mut self, edits: I, cx: &mut Context<Self>)
 2292    where
 2293        I: IntoIterator<Item = (Range<S>, T)>,
 2294        S: ToOffset,
 2295        T: Into<Arc<str>>,
 2296    {
 2297        if self.read_only(cx) {
 2298            return;
 2299        }
 2300
 2301        self.buffer.update(cx, |buffer, cx| {
 2302            buffer.edit(edits, self.autoindent_mode.clone(), cx)
 2303        });
 2304    }
 2305
 2306    pub fn edit_with_block_indent<I, S, T>(
 2307        &mut self,
 2308        edits: I,
 2309        original_start_columns: Vec<u32>,
 2310        cx: &mut Context<Self>,
 2311    ) where
 2312        I: IntoIterator<Item = (Range<S>, T)>,
 2313        S: ToOffset,
 2314        T: Into<Arc<str>>,
 2315    {
 2316        if self.read_only(cx) {
 2317            return;
 2318        }
 2319
 2320        self.buffer.update(cx, |buffer, cx| {
 2321            buffer.edit(
 2322                edits,
 2323                Some(AutoindentMode::Block {
 2324                    original_start_columns,
 2325                }),
 2326                cx,
 2327            )
 2328        });
 2329    }
 2330
 2331    fn select(&mut self, phase: SelectPhase, window: &mut Window, cx: &mut Context<Self>) {
 2332        self.hide_context_menu(window, cx);
 2333
 2334        match phase {
 2335            SelectPhase::Begin {
 2336                position,
 2337                add,
 2338                click_count,
 2339            } => self.begin_selection(position, add, click_count, window, cx),
 2340            SelectPhase::BeginColumnar {
 2341                position,
 2342                goal_column,
 2343                reset,
 2344            } => self.begin_columnar_selection(position, goal_column, reset, window, cx),
 2345            SelectPhase::Extend {
 2346                position,
 2347                click_count,
 2348            } => self.extend_selection(position, click_count, window, cx),
 2349            SelectPhase::Update {
 2350                position,
 2351                goal_column,
 2352                scroll_delta,
 2353            } => self.update_selection(position, goal_column, scroll_delta, window, cx),
 2354            SelectPhase::End => self.end_selection(window, cx),
 2355        }
 2356    }
 2357
 2358    fn extend_selection(
 2359        &mut self,
 2360        position: DisplayPoint,
 2361        click_count: usize,
 2362        window: &mut Window,
 2363        cx: &mut Context<Self>,
 2364    ) {
 2365        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 2366        let tail = self.selections.newest::<usize>(cx).tail();
 2367        self.begin_selection(position, false, click_count, window, cx);
 2368
 2369        let position = position.to_offset(&display_map, Bias::Left);
 2370        let tail_anchor = display_map.buffer_snapshot.anchor_before(tail);
 2371
 2372        let mut pending_selection = self
 2373            .selections
 2374            .pending_anchor()
 2375            .expect("extend_selection not called with pending selection");
 2376        if position >= tail {
 2377            pending_selection.start = tail_anchor;
 2378        } else {
 2379            pending_selection.end = tail_anchor;
 2380            pending_selection.reversed = true;
 2381        }
 2382
 2383        let mut pending_mode = self.selections.pending_mode().unwrap();
 2384        match &mut pending_mode {
 2385            SelectMode::Word(range) | SelectMode::Line(range) => *range = tail_anchor..tail_anchor,
 2386            _ => {}
 2387        }
 2388
 2389        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 2390            s.set_pending(pending_selection, pending_mode)
 2391        });
 2392    }
 2393
 2394    fn begin_selection(
 2395        &mut self,
 2396        position: DisplayPoint,
 2397        add: bool,
 2398        click_count: usize,
 2399        window: &mut Window,
 2400        cx: &mut Context<Self>,
 2401    ) {
 2402        if !self.focus_handle.is_focused(window) {
 2403            self.last_focused_descendant = None;
 2404            window.focus(&self.focus_handle);
 2405        }
 2406
 2407        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 2408        let buffer = &display_map.buffer_snapshot;
 2409        let newest_selection = self.selections.newest_anchor().clone();
 2410        let position = display_map.clip_point(position, Bias::Left);
 2411
 2412        let start;
 2413        let end;
 2414        let mode;
 2415        let mut auto_scroll;
 2416        match click_count {
 2417            1 => {
 2418                start = buffer.anchor_before(position.to_point(&display_map));
 2419                end = start;
 2420                mode = SelectMode::Character;
 2421                auto_scroll = true;
 2422            }
 2423            2 => {
 2424                let range = movement::surrounding_word(&display_map, position);
 2425                start = buffer.anchor_before(range.start.to_point(&display_map));
 2426                end = buffer.anchor_before(range.end.to_point(&display_map));
 2427                mode = SelectMode::Word(start..end);
 2428                auto_scroll = true;
 2429            }
 2430            3 => {
 2431                let position = display_map
 2432                    .clip_point(position, Bias::Left)
 2433                    .to_point(&display_map);
 2434                let line_start = display_map.prev_line_boundary(position).0;
 2435                let next_line_start = buffer.clip_point(
 2436                    display_map.next_line_boundary(position).0 + Point::new(1, 0),
 2437                    Bias::Left,
 2438                );
 2439                start = buffer.anchor_before(line_start);
 2440                end = buffer.anchor_before(next_line_start);
 2441                mode = SelectMode::Line(start..end);
 2442                auto_scroll = true;
 2443            }
 2444            _ => {
 2445                start = buffer.anchor_before(0);
 2446                end = buffer.anchor_before(buffer.len());
 2447                mode = SelectMode::All;
 2448                auto_scroll = false;
 2449            }
 2450        }
 2451        auto_scroll &= EditorSettings::get_global(cx).autoscroll_on_clicks;
 2452
 2453        let point_to_delete: Option<usize> = {
 2454            let selected_points: Vec<Selection<Point>> =
 2455                self.selections.disjoint_in_range(start..end, cx);
 2456
 2457            if !add || click_count > 1 {
 2458                None
 2459            } else if !selected_points.is_empty() {
 2460                Some(selected_points[0].id)
 2461            } else {
 2462                let clicked_point_already_selected =
 2463                    self.selections.disjoint.iter().find(|selection| {
 2464                        selection.start.to_point(buffer) == start.to_point(buffer)
 2465                            || selection.end.to_point(buffer) == end.to_point(buffer)
 2466                    });
 2467
 2468                clicked_point_already_selected.map(|selection| selection.id)
 2469            }
 2470        };
 2471
 2472        let selections_count = self.selections.count();
 2473
 2474        self.change_selections(auto_scroll.then(Autoscroll::newest), window, cx, |s| {
 2475            if let Some(point_to_delete) = point_to_delete {
 2476                s.delete(point_to_delete);
 2477
 2478                if selections_count == 1 {
 2479                    s.set_pending_anchor_range(start..end, mode);
 2480                }
 2481            } else {
 2482                if !add {
 2483                    s.clear_disjoint();
 2484                } else if click_count > 1 {
 2485                    s.delete(newest_selection.id)
 2486                }
 2487
 2488                s.set_pending_anchor_range(start..end, mode);
 2489            }
 2490        });
 2491    }
 2492
 2493    fn begin_columnar_selection(
 2494        &mut self,
 2495        position: DisplayPoint,
 2496        goal_column: u32,
 2497        reset: bool,
 2498        window: &mut Window,
 2499        cx: &mut Context<Self>,
 2500    ) {
 2501        if !self.focus_handle.is_focused(window) {
 2502            self.last_focused_descendant = None;
 2503            window.focus(&self.focus_handle);
 2504        }
 2505
 2506        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 2507
 2508        if reset {
 2509            let pointer_position = display_map
 2510                .buffer_snapshot
 2511                .anchor_before(position.to_point(&display_map));
 2512
 2513            self.change_selections(Some(Autoscroll::newest()), window, cx, |s| {
 2514                s.clear_disjoint();
 2515                s.set_pending_anchor_range(
 2516                    pointer_position..pointer_position,
 2517                    SelectMode::Character,
 2518                );
 2519            });
 2520        }
 2521
 2522        let tail = self.selections.newest::<Point>(cx).tail();
 2523        self.columnar_selection_tail = Some(display_map.buffer_snapshot.anchor_before(tail));
 2524
 2525        if !reset {
 2526            self.select_columns(
 2527                tail.to_display_point(&display_map),
 2528                position,
 2529                goal_column,
 2530                &display_map,
 2531                window,
 2532                cx,
 2533            );
 2534        }
 2535    }
 2536
 2537    fn update_selection(
 2538        &mut self,
 2539        position: DisplayPoint,
 2540        goal_column: u32,
 2541        scroll_delta: gpui::Point<f32>,
 2542        window: &mut Window,
 2543        cx: &mut Context<Self>,
 2544    ) {
 2545        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 2546
 2547        if let Some(tail) = self.columnar_selection_tail.as_ref() {
 2548            let tail = tail.to_display_point(&display_map);
 2549            self.select_columns(tail, position, goal_column, &display_map, window, cx);
 2550        } else if let Some(mut pending) = self.selections.pending_anchor() {
 2551            let buffer = self.buffer.read(cx).snapshot(cx);
 2552            let head;
 2553            let tail;
 2554            let mode = self.selections.pending_mode().unwrap();
 2555            match &mode {
 2556                SelectMode::Character => {
 2557                    head = position.to_point(&display_map);
 2558                    tail = pending.tail().to_point(&buffer);
 2559                }
 2560                SelectMode::Word(original_range) => {
 2561                    let original_display_range = original_range.start.to_display_point(&display_map)
 2562                        ..original_range.end.to_display_point(&display_map);
 2563                    let original_buffer_range = original_display_range.start.to_point(&display_map)
 2564                        ..original_display_range.end.to_point(&display_map);
 2565                    if movement::is_inside_word(&display_map, position)
 2566                        || original_display_range.contains(&position)
 2567                    {
 2568                        let word_range = movement::surrounding_word(&display_map, position);
 2569                        if word_range.start < original_display_range.start {
 2570                            head = word_range.start.to_point(&display_map);
 2571                        } else {
 2572                            head = word_range.end.to_point(&display_map);
 2573                        }
 2574                    } else {
 2575                        head = position.to_point(&display_map);
 2576                    }
 2577
 2578                    if head <= original_buffer_range.start {
 2579                        tail = original_buffer_range.end;
 2580                    } else {
 2581                        tail = original_buffer_range.start;
 2582                    }
 2583                }
 2584                SelectMode::Line(original_range) => {
 2585                    let original_range = original_range.to_point(&display_map.buffer_snapshot);
 2586
 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
 2596                    if line_start < original_range.start {
 2597                        head = line_start
 2598                    } else {
 2599                        head = next_line_start
 2600                    }
 2601
 2602                    if head <= original_range.start {
 2603                        tail = original_range.end;
 2604                    } else {
 2605                        tail = original_range.start;
 2606                    }
 2607                }
 2608                SelectMode::All => {
 2609                    return;
 2610                }
 2611            };
 2612
 2613            if head < tail {
 2614                pending.start = buffer.anchor_before(head);
 2615                pending.end = buffer.anchor_before(tail);
 2616                pending.reversed = true;
 2617            } else {
 2618                pending.start = buffer.anchor_before(tail);
 2619                pending.end = buffer.anchor_before(head);
 2620                pending.reversed = false;
 2621            }
 2622
 2623            self.change_selections(None, window, cx, |s| {
 2624                s.set_pending(pending, mode);
 2625            });
 2626        } else {
 2627            log::error!("update_selection dispatched with no pending selection");
 2628            return;
 2629        }
 2630
 2631        self.apply_scroll_delta(scroll_delta, window, cx);
 2632        cx.notify();
 2633    }
 2634
 2635    fn end_selection(&mut self, window: &mut Window, cx: &mut Context<Self>) {
 2636        self.columnar_selection_tail.take();
 2637        if self.selections.pending_anchor().is_some() {
 2638            let selections = self.selections.all::<usize>(cx);
 2639            self.change_selections(None, window, cx, |s| {
 2640                s.select(selections);
 2641                s.clear_pending();
 2642            });
 2643        }
 2644    }
 2645
 2646    fn select_columns(
 2647        &mut self,
 2648        tail: DisplayPoint,
 2649        head: DisplayPoint,
 2650        goal_column: u32,
 2651        display_map: &DisplaySnapshot,
 2652        window: &mut Window,
 2653        cx: &mut Context<Self>,
 2654    ) {
 2655        let start_row = cmp::min(tail.row(), head.row());
 2656        let end_row = cmp::max(tail.row(), head.row());
 2657        let start_column = cmp::min(tail.column(), goal_column);
 2658        let end_column = cmp::max(tail.column(), goal_column);
 2659        let reversed = start_column < tail.column();
 2660
 2661        let selection_ranges = (start_row.0..=end_row.0)
 2662            .map(DisplayRow)
 2663            .filter_map(|row| {
 2664                if start_column <= display_map.line_len(row) && !display_map.is_block_line(row) {
 2665                    let start = display_map
 2666                        .clip_point(DisplayPoint::new(row, start_column), Bias::Left)
 2667                        .to_point(display_map);
 2668                    let end = display_map
 2669                        .clip_point(DisplayPoint::new(row, end_column), Bias::Right)
 2670                        .to_point(display_map);
 2671                    if reversed {
 2672                        Some(end..start)
 2673                    } else {
 2674                        Some(start..end)
 2675                    }
 2676                } else {
 2677                    None
 2678                }
 2679            })
 2680            .collect::<Vec<_>>();
 2681
 2682        self.change_selections(None, window, cx, |s| {
 2683            s.select_ranges(selection_ranges);
 2684        });
 2685        cx.notify();
 2686    }
 2687
 2688    pub fn has_pending_nonempty_selection(&self) -> bool {
 2689        let pending_nonempty_selection = match self.selections.pending_anchor() {
 2690            Some(Selection { start, end, .. }) => start != end,
 2691            None => false,
 2692        };
 2693
 2694        pending_nonempty_selection
 2695            || (self.columnar_selection_tail.is_some() && self.selections.disjoint.len() > 1)
 2696    }
 2697
 2698    pub fn has_pending_selection(&self) -> bool {
 2699        self.selections.pending_anchor().is_some() || self.columnar_selection_tail.is_some()
 2700    }
 2701
 2702    pub fn cancel(&mut self, _: &Cancel, window: &mut Window, cx: &mut Context<Self>) {
 2703        self.selection_mark_mode = false;
 2704
 2705        if self.clear_expanded_diff_hunks(cx) {
 2706            cx.notify();
 2707            return;
 2708        }
 2709        if self.dismiss_menus_and_popups(true, window, cx) {
 2710            return;
 2711        }
 2712
 2713        if self.mode == EditorMode::Full
 2714            && self.change_selections(Some(Autoscroll::fit()), window, cx, |s| s.try_cancel())
 2715        {
 2716            return;
 2717        }
 2718
 2719        cx.propagate();
 2720    }
 2721
 2722    pub fn dismiss_menus_and_popups(
 2723        &mut self,
 2724        is_user_requested: bool,
 2725        window: &mut Window,
 2726        cx: &mut Context<Self>,
 2727    ) -> bool {
 2728        if self.take_rename(false, window, cx).is_some() {
 2729            return true;
 2730        }
 2731
 2732        if hide_hover(self, cx) {
 2733            return true;
 2734        }
 2735
 2736        if self.hide_signature_help(cx, SignatureHelpHiddenBy::Escape) {
 2737            return true;
 2738        }
 2739
 2740        if self.hide_context_menu(window, cx).is_some() {
 2741            return true;
 2742        }
 2743
 2744        if self.mouse_context_menu.take().is_some() {
 2745            return true;
 2746        }
 2747
 2748        if is_user_requested && self.discard_inline_completion(true, cx) {
 2749            return true;
 2750        }
 2751
 2752        if self.snippet_stack.pop().is_some() {
 2753            return true;
 2754        }
 2755
 2756        if self.mode == EditorMode::Full && self.active_diagnostics.is_some() {
 2757            self.dismiss_diagnostics(cx);
 2758            return true;
 2759        }
 2760
 2761        false
 2762    }
 2763
 2764    fn linked_editing_ranges_for(
 2765        &self,
 2766        selection: Range<text::Anchor>,
 2767        cx: &App,
 2768    ) -> Option<HashMap<Entity<Buffer>, Vec<Range<text::Anchor>>>> {
 2769        if self.linked_edit_ranges.is_empty() {
 2770            return None;
 2771        }
 2772        let ((base_range, linked_ranges), buffer_snapshot, buffer) =
 2773            selection.end.buffer_id.and_then(|end_buffer_id| {
 2774                if selection.start.buffer_id != Some(end_buffer_id) {
 2775                    return None;
 2776                }
 2777                let buffer = self.buffer.read(cx).buffer(end_buffer_id)?;
 2778                let snapshot = buffer.read(cx).snapshot();
 2779                self.linked_edit_ranges
 2780                    .get(end_buffer_id, selection.start..selection.end, &snapshot)
 2781                    .map(|ranges| (ranges, snapshot, buffer))
 2782            })?;
 2783        use text::ToOffset as TO;
 2784        // find offset from the start of current range to current cursor position
 2785        let start_byte_offset = TO::to_offset(&base_range.start, &buffer_snapshot);
 2786
 2787        let start_offset = TO::to_offset(&selection.start, &buffer_snapshot);
 2788        let start_difference = start_offset - start_byte_offset;
 2789        let end_offset = TO::to_offset(&selection.end, &buffer_snapshot);
 2790        let end_difference = end_offset - start_byte_offset;
 2791        // Current range has associated linked ranges.
 2792        let mut linked_edits = HashMap::<_, Vec<_>>::default();
 2793        for range in linked_ranges.iter() {
 2794            let start_offset = TO::to_offset(&range.start, &buffer_snapshot);
 2795            let end_offset = start_offset + end_difference;
 2796            let start_offset = start_offset + start_difference;
 2797            if start_offset > buffer_snapshot.len() || end_offset > buffer_snapshot.len() {
 2798                continue;
 2799            }
 2800            if self.selections.disjoint_anchor_ranges().any(|s| {
 2801                if s.start.buffer_id != selection.start.buffer_id
 2802                    || s.end.buffer_id != selection.end.buffer_id
 2803                {
 2804                    return false;
 2805                }
 2806                TO::to_offset(&s.start.text_anchor, &buffer_snapshot) <= end_offset
 2807                    && TO::to_offset(&s.end.text_anchor, &buffer_snapshot) >= start_offset
 2808            }) {
 2809                continue;
 2810            }
 2811            let start = buffer_snapshot.anchor_after(start_offset);
 2812            let end = buffer_snapshot.anchor_after(end_offset);
 2813            linked_edits
 2814                .entry(buffer.clone())
 2815                .or_default()
 2816                .push(start..end);
 2817        }
 2818        Some(linked_edits)
 2819    }
 2820
 2821    pub fn handle_input(&mut self, text: &str, window: &mut Window, cx: &mut Context<Self>) {
 2822        let text: Arc<str> = text.into();
 2823
 2824        if self.read_only(cx) {
 2825            return;
 2826        }
 2827
 2828        let selections = self.selections.all_adjusted(cx);
 2829        let mut bracket_inserted = false;
 2830        let mut edits = Vec::new();
 2831        let mut linked_edits = HashMap::<_, Vec<_>>::default();
 2832        let mut new_selections = Vec::with_capacity(selections.len());
 2833        let mut new_autoclose_regions = Vec::new();
 2834        let snapshot = self.buffer.read(cx).read(cx);
 2835
 2836        for (selection, autoclose_region) in
 2837            self.selections_with_autoclose_regions(selections, &snapshot)
 2838        {
 2839            if let Some(scope) = snapshot.language_scope_at(selection.head()) {
 2840                // Determine if the inserted text matches the opening or closing
 2841                // bracket of any of this language's bracket pairs.
 2842                let mut bracket_pair = None;
 2843                let mut is_bracket_pair_start = false;
 2844                let mut is_bracket_pair_end = false;
 2845                if !text.is_empty() {
 2846                    // `text` can be empty when a user is using IME (e.g. Chinese Wubi Simplified)
 2847                    //  and they are removing the character that triggered IME popup.
 2848                    for (pair, enabled) in scope.brackets() {
 2849                        if !pair.close && !pair.surround {
 2850                            continue;
 2851                        }
 2852
 2853                        if enabled && pair.start.ends_with(text.as_ref()) {
 2854                            let prefix_len = pair.start.len() - text.len();
 2855                            let preceding_text_matches_prefix = prefix_len == 0
 2856                                || (selection.start.column >= (prefix_len as u32)
 2857                                    && snapshot.contains_str_at(
 2858                                        Point::new(
 2859                                            selection.start.row,
 2860                                            selection.start.column - (prefix_len as u32),
 2861                                        ),
 2862                                        &pair.start[..prefix_len],
 2863                                    ));
 2864                            if preceding_text_matches_prefix {
 2865                                bracket_pair = Some(pair.clone());
 2866                                is_bracket_pair_start = true;
 2867                                break;
 2868                            }
 2869                        }
 2870                        if pair.end.as_str() == text.as_ref() {
 2871                            bracket_pair = Some(pair.clone());
 2872                            is_bracket_pair_end = true;
 2873                            break;
 2874                        }
 2875                    }
 2876                }
 2877
 2878                if let Some(bracket_pair) = bracket_pair {
 2879                    let snapshot_settings = snapshot.settings_at(selection.start, cx);
 2880                    let autoclose = self.use_autoclose && snapshot_settings.use_autoclose;
 2881                    let auto_surround =
 2882                        self.use_auto_surround && snapshot_settings.use_auto_surround;
 2883                    if selection.is_empty() {
 2884                        if is_bracket_pair_start {
 2885                            // If the inserted text is a suffix of an opening bracket and the
 2886                            // selection is preceded by the rest of the opening bracket, then
 2887                            // insert the closing bracket.
 2888                            let following_text_allows_autoclose = snapshot
 2889                                .chars_at(selection.start)
 2890                                .next()
 2891                                .map_or(true, |c| scope.should_autoclose_before(c));
 2892
 2893                            let is_closing_quote = if bracket_pair.end == bracket_pair.start
 2894                                && bracket_pair.start.len() == 1
 2895                            {
 2896                                let target = bracket_pair.start.chars().next().unwrap();
 2897                                let current_line_count = snapshot
 2898                                    .reversed_chars_at(selection.start)
 2899                                    .take_while(|&c| c != '\n')
 2900                                    .filter(|&c| c == target)
 2901                                    .count();
 2902                                current_line_count % 2 == 1
 2903                            } else {
 2904                                false
 2905                            };
 2906
 2907                            if autoclose
 2908                                && bracket_pair.close
 2909                                && following_text_allows_autoclose
 2910                                && !is_closing_quote
 2911                            {
 2912                                let anchor = snapshot.anchor_before(selection.end);
 2913                                new_selections.push((selection.map(|_| anchor), text.len()));
 2914                                new_autoclose_regions.push((
 2915                                    anchor,
 2916                                    text.len(),
 2917                                    selection.id,
 2918                                    bracket_pair.clone(),
 2919                                ));
 2920                                edits.push((
 2921                                    selection.range(),
 2922                                    format!("{}{}", text, bracket_pair.end).into(),
 2923                                ));
 2924                                bracket_inserted = true;
 2925                                continue;
 2926                            }
 2927                        }
 2928
 2929                        if let Some(region) = autoclose_region {
 2930                            // If the selection is followed by an auto-inserted closing bracket,
 2931                            // then don't insert that closing bracket again; just move the selection
 2932                            // past the closing bracket.
 2933                            let should_skip = selection.end == region.range.end.to_point(&snapshot)
 2934                                && text.as_ref() == region.pair.end.as_str();
 2935                            if should_skip {
 2936                                let anchor = snapshot.anchor_after(selection.end);
 2937                                new_selections
 2938                                    .push((selection.map(|_| anchor), region.pair.end.len()));
 2939                                continue;
 2940                            }
 2941                        }
 2942
 2943                        let always_treat_brackets_as_autoclosed = snapshot
 2944                            .settings_at(selection.start, cx)
 2945                            .always_treat_brackets_as_autoclosed;
 2946                        if always_treat_brackets_as_autoclosed
 2947                            && is_bracket_pair_end
 2948                            && snapshot.contains_str_at(selection.end, text.as_ref())
 2949                        {
 2950                            // Otherwise, when `always_treat_brackets_as_autoclosed` is set to `true
 2951                            // and the inserted text is a closing bracket and the selection is followed
 2952                            // by the closing bracket then move the selection past the closing bracket.
 2953                            let anchor = snapshot.anchor_after(selection.end);
 2954                            new_selections.push((selection.map(|_| anchor), text.len()));
 2955                            continue;
 2956                        }
 2957                    }
 2958                    // If an opening bracket is 1 character long and is typed while
 2959                    // text is selected, then surround that text with the bracket pair.
 2960                    else if auto_surround
 2961                        && bracket_pair.surround
 2962                        && is_bracket_pair_start
 2963                        && bracket_pair.start.chars().count() == 1
 2964                    {
 2965                        edits.push((selection.start..selection.start, text.clone()));
 2966                        edits.push((
 2967                            selection.end..selection.end,
 2968                            bracket_pair.end.as_str().into(),
 2969                        ));
 2970                        bracket_inserted = true;
 2971                        new_selections.push((
 2972                            Selection {
 2973                                id: selection.id,
 2974                                start: snapshot.anchor_after(selection.start),
 2975                                end: snapshot.anchor_before(selection.end),
 2976                                reversed: selection.reversed,
 2977                                goal: selection.goal,
 2978                            },
 2979                            0,
 2980                        ));
 2981                        continue;
 2982                    }
 2983                }
 2984            }
 2985
 2986            if self.auto_replace_emoji_shortcode
 2987                && selection.is_empty()
 2988                && text.as_ref().ends_with(':')
 2989            {
 2990                if let Some(possible_emoji_short_code) =
 2991                    Self::find_possible_emoji_shortcode_at_position(&snapshot, selection.start)
 2992                {
 2993                    if !possible_emoji_short_code.is_empty() {
 2994                        if let Some(emoji) = emojis::get_by_shortcode(&possible_emoji_short_code) {
 2995                            let emoji_shortcode_start = Point::new(
 2996                                selection.start.row,
 2997                                selection.start.column - possible_emoji_short_code.len() as u32 - 1,
 2998                            );
 2999
 3000                            // Remove shortcode from buffer
 3001                            edits.push((
 3002                                emoji_shortcode_start..selection.start,
 3003                                "".to_string().into(),
 3004                            ));
 3005                            new_selections.push((
 3006                                Selection {
 3007                                    id: selection.id,
 3008                                    start: snapshot.anchor_after(emoji_shortcode_start),
 3009                                    end: snapshot.anchor_before(selection.start),
 3010                                    reversed: selection.reversed,
 3011                                    goal: selection.goal,
 3012                                },
 3013                                0,
 3014                            ));
 3015
 3016                            // Insert emoji
 3017                            let selection_start_anchor = snapshot.anchor_after(selection.start);
 3018                            new_selections.push((selection.map(|_| selection_start_anchor), 0));
 3019                            edits.push((selection.start..selection.end, emoji.to_string().into()));
 3020
 3021                            continue;
 3022                        }
 3023                    }
 3024                }
 3025            }
 3026
 3027            // If not handling any auto-close operation, then just replace the selected
 3028            // text with the given input and move the selection to the end of the
 3029            // newly inserted text.
 3030            let anchor = snapshot.anchor_after(selection.end);
 3031            if !self.linked_edit_ranges.is_empty() {
 3032                let start_anchor = snapshot.anchor_before(selection.start);
 3033
 3034                let is_word_char = text.chars().next().map_or(true, |char| {
 3035                    let classifier = snapshot.char_classifier_at(start_anchor.to_offset(&snapshot));
 3036                    classifier.is_word(char)
 3037                });
 3038
 3039                if is_word_char {
 3040                    if let Some(ranges) = self
 3041                        .linked_editing_ranges_for(start_anchor.text_anchor..anchor.text_anchor, cx)
 3042                    {
 3043                        for (buffer, edits) in ranges {
 3044                            linked_edits
 3045                                .entry(buffer.clone())
 3046                                .or_default()
 3047                                .extend(edits.into_iter().map(|range| (range, text.clone())));
 3048                        }
 3049                    }
 3050                }
 3051            }
 3052
 3053            new_selections.push((selection.map(|_| anchor), 0));
 3054            edits.push((selection.start..selection.end, text.clone()));
 3055        }
 3056
 3057        drop(snapshot);
 3058
 3059        self.transact(window, cx, |this, window, cx| {
 3060            this.buffer.update(cx, |buffer, cx| {
 3061                buffer.edit(edits, this.autoindent_mode.clone(), cx);
 3062            });
 3063            for (buffer, edits) in linked_edits {
 3064                buffer.update(cx, |buffer, cx| {
 3065                    let snapshot = buffer.snapshot();
 3066                    let edits = edits
 3067                        .into_iter()
 3068                        .map(|(range, text)| {
 3069                            use text::ToPoint as TP;
 3070                            let end_point = TP::to_point(&range.end, &snapshot);
 3071                            let start_point = TP::to_point(&range.start, &snapshot);
 3072                            (start_point..end_point, text)
 3073                        })
 3074                        .sorted_by_key(|(range, _)| range.start)
 3075                        .collect::<Vec<_>>();
 3076                    buffer.edit(edits, None, cx);
 3077                })
 3078            }
 3079            let new_anchor_selections = new_selections.iter().map(|e| &e.0);
 3080            let new_selection_deltas = new_selections.iter().map(|e| e.1);
 3081            let map = this.display_map.update(cx, |map, cx| map.snapshot(cx));
 3082            let new_selections = resolve_selections::<usize, _>(new_anchor_selections, &map)
 3083                .zip(new_selection_deltas)
 3084                .map(|(selection, delta)| Selection {
 3085                    id: selection.id,
 3086                    start: selection.start + delta,
 3087                    end: selection.end + delta,
 3088                    reversed: selection.reversed,
 3089                    goal: SelectionGoal::None,
 3090                })
 3091                .collect::<Vec<_>>();
 3092
 3093            let mut i = 0;
 3094            for (position, delta, selection_id, pair) in new_autoclose_regions {
 3095                let position = position.to_offset(&map.buffer_snapshot) + delta;
 3096                let start = map.buffer_snapshot.anchor_before(position);
 3097                let end = map.buffer_snapshot.anchor_after(position);
 3098                while let Some(existing_state) = this.autoclose_regions.get(i) {
 3099                    match existing_state.range.start.cmp(&start, &map.buffer_snapshot) {
 3100                        Ordering::Less => i += 1,
 3101                        Ordering::Greater => break,
 3102                        Ordering::Equal => {
 3103                            match end.cmp(&existing_state.range.end, &map.buffer_snapshot) {
 3104                                Ordering::Less => i += 1,
 3105                                Ordering::Equal => break,
 3106                                Ordering::Greater => break,
 3107                            }
 3108                        }
 3109                    }
 3110                }
 3111                this.autoclose_regions.insert(
 3112                    i,
 3113                    AutocloseRegion {
 3114                        selection_id,
 3115                        range: start..end,
 3116                        pair,
 3117                    },
 3118                );
 3119            }
 3120
 3121            let had_active_inline_completion = this.has_active_inline_completion();
 3122            this.change_selections_inner(Some(Autoscroll::fit()), false, window, cx, |s| {
 3123                s.select(new_selections)
 3124            });
 3125
 3126            if !bracket_inserted {
 3127                if let Some(on_type_format_task) =
 3128                    this.trigger_on_type_formatting(text.to_string(), window, cx)
 3129                {
 3130                    on_type_format_task.detach_and_log_err(cx);
 3131                }
 3132            }
 3133
 3134            let editor_settings = EditorSettings::get_global(cx);
 3135            if bracket_inserted
 3136                && (editor_settings.auto_signature_help
 3137                    || editor_settings.show_signature_help_after_edits)
 3138            {
 3139                this.show_signature_help(&ShowSignatureHelp, window, cx);
 3140            }
 3141
 3142            let trigger_in_words =
 3143                this.show_edit_predictions_in_menu() || !had_active_inline_completion;
 3144            this.trigger_completion_on_input(&text, trigger_in_words, window, cx);
 3145            linked_editing_ranges::refresh_linked_ranges(this, window, cx);
 3146            this.refresh_inline_completion(true, false, window, cx);
 3147        });
 3148    }
 3149
 3150    fn find_possible_emoji_shortcode_at_position(
 3151        snapshot: &MultiBufferSnapshot,
 3152        position: Point,
 3153    ) -> Option<String> {
 3154        let mut chars = Vec::new();
 3155        let mut found_colon = false;
 3156        for char in snapshot.reversed_chars_at(position).take(100) {
 3157            // Found a possible emoji shortcode in the middle of the buffer
 3158            if found_colon {
 3159                if char.is_whitespace() {
 3160                    chars.reverse();
 3161                    return Some(chars.iter().collect());
 3162                }
 3163                // If the previous character is not a whitespace, we are in the middle of a word
 3164                // and we only want to complete the shortcode if the word is made up of other emojis
 3165                let mut containing_word = String::new();
 3166                for ch in snapshot
 3167                    .reversed_chars_at(position)
 3168                    .skip(chars.len() + 1)
 3169                    .take(100)
 3170                {
 3171                    if ch.is_whitespace() {
 3172                        break;
 3173                    }
 3174                    containing_word.push(ch);
 3175                }
 3176                let containing_word = containing_word.chars().rev().collect::<String>();
 3177                if util::word_consists_of_emojis(containing_word.as_str()) {
 3178                    chars.reverse();
 3179                    return Some(chars.iter().collect());
 3180                }
 3181            }
 3182
 3183            if char.is_whitespace() || !char.is_ascii() {
 3184                return None;
 3185            }
 3186            if char == ':' {
 3187                found_colon = true;
 3188            } else {
 3189                chars.push(char);
 3190            }
 3191        }
 3192        // Found a possible emoji shortcode at the beginning of the buffer
 3193        chars.reverse();
 3194        Some(chars.iter().collect())
 3195    }
 3196
 3197    pub fn newline(&mut self, _: &Newline, window: &mut Window, cx: &mut Context<Self>) {
 3198        self.transact(window, cx, |this, window, cx| {
 3199            let (edits, selection_fixup_info): (Vec<_>, Vec<_>) = {
 3200                let selections = this.selections.all::<usize>(cx);
 3201                let multi_buffer = this.buffer.read(cx);
 3202                let buffer = multi_buffer.snapshot(cx);
 3203                selections
 3204                    .iter()
 3205                    .map(|selection| {
 3206                        let start_point = selection.start.to_point(&buffer);
 3207                        let mut indent =
 3208                            buffer.indent_size_for_line(MultiBufferRow(start_point.row));
 3209                        indent.len = cmp::min(indent.len, start_point.column);
 3210                        let start = selection.start;
 3211                        let end = selection.end;
 3212                        let selection_is_empty = start == end;
 3213                        let language_scope = buffer.language_scope_at(start);
 3214                        let (comment_delimiter, insert_extra_newline) = if let Some(language) =
 3215                            &language_scope
 3216                        {
 3217                            let insert_extra_newline =
 3218                                insert_extra_newline_brackets(&buffer, start..end, language)
 3219                                    || insert_extra_newline_tree_sitter(&buffer, start..end);
 3220
 3221                            // Comment extension on newline is allowed only for cursor selections
 3222                            let comment_delimiter = maybe!({
 3223                                if !selection_is_empty {
 3224                                    return None;
 3225                                }
 3226
 3227                                if !multi_buffer.settings_at(0, cx).extend_comment_on_newline {
 3228                                    return None;
 3229                                }
 3230
 3231                                let delimiters = language.line_comment_prefixes();
 3232                                let max_len_of_delimiter =
 3233                                    delimiters.iter().map(|delimiter| delimiter.len()).max()?;
 3234                                let (snapshot, range) =
 3235                                    buffer.buffer_line_for_row(MultiBufferRow(start_point.row))?;
 3236
 3237                                let mut index_of_first_non_whitespace = 0;
 3238                                let comment_candidate = snapshot
 3239                                    .chars_for_range(range)
 3240                                    .skip_while(|c| {
 3241                                        let should_skip = c.is_whitespace();
 3242                                        if should_skip {
 3243                                            index_of_first_non_whitespace += 1;
 3244                                        }
 3245                                        should_skip
 3246                                    })
 3247                                    .take(max_len_of_delimiter)
 3248                                    .collect::<String>();
 3249                                let comment_prefix = delimiters.iter().find(|comment_prefix| {
 3250                                    comment_candidate.starts_with(comment_prefix.as_ref())
 3251                                })?;
 3252                                let cursor_is_placed_after_comment_marker =
 3253                                    index_of_first_non_whitespace + comment_prefix.len()
 3254                                        <= start_point.column as usize;
 3255                                if cursor_is_placed_after_comment_marker {
 3256                                    Some(comment_prefix.clone())
 3257                                } else {
 3258                                    None
 3259                                }
 3260                            });
 3261                            (comment_delimiter, insert_extra_newline)
 3262                        } else {
 3263                            (None, false)
 3264                        };
 3265
 3266                        let capacity_for_delimiter = comment_delimiter
 3267                            .as_deref()
 3268                            .map(str::len)
 3269                            .unwrap_or_default();
 3270                        let mut new_text =
 3271                            String::with_capacity(1 + capacity_for_delimiter + indent.len as usize);
 3272                        new_text.push('\n');
 3273                        new_text.extend(indent.chars());
 3274                        if let Some(delimiter) = &comment_delimiter {
 3275                            new_text.push_str(delimiter);
 3276                        }
 3277                        if insert_extra_newline {
 3278                            new_text = new_text.repeat(2);
 3279                        }
 3280
 3281                        let anchor = buffer.anchor_after(end);
 3282                        let new_selection = selection.map(|_| anchor);
 3283                        (
 3284                            (start..end, new_text),
 3285                            (insert_extra_newline, new_selection),
 3286                        )
 3287                    })
 3288                    .unzip()
 3289            };
 3290
 3291            this.edit_with_autoindent(edits, cx);
 3292            let buffer = this.buffer.read(cx).snapshot(cx);
 3293            let new_selections = selection_fixup_info
 3294                .into_iter()
 3295                .map(|(extra_newline_inserted, new_selection)| {
 3296                    let mut cursor = new_selection.end.to_point(&buffer);
 3297                    if extra_newline_inserted {
 3298                        cursor.row -= 1;
 3299                        cursor.column = buffer.line_len(MultiBufferRow(cursor.row));
 3300                    }
 3301                    new_selection.map(|_| cursor)
 3302                })
 3303                .collect();
 3304
 3305            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 3306                s.select(new_selections)
 3307            });
 3308            this.refresh_inline_completion(true, false, window, cx);
 3309        });
 3310    }
 3311
 3312    pub fn newline_above(&mut self, _: &NewlineAbove, window: &mut Window, cx: &mut Context<Self>) {
 3313        let buffer = self.buffer.read(cx);
 3314        let snapshot = buffer.snapshot(cx);
 3315
 3316        let mut edits = Vec::new();
 3317        let mut rows = Vec::new();
 3318
 3319        for (rows_inserted, selection) in self.selections.all_adjusted(cx).into_iter().enumerate() {
 3320            let cursor = selection.head();
 3321            let row = cursor.row;
 3322
 3323            let start_of_line = snapshot.clip_point(Point::new(row, 0), Bias::Left);
 3324
 3325            let newline = "\n".to_string();
 3326            edits.push((start_of_line..start_of_line, newline));
 3327
 3328            rows.push(row + rows_inserted as u32);
 3329        }
 3330
 3331        self.transact(window, cx, |editor, window, cx| {
 3332            editor.edit(edits, cx);
 3333
 3334            editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 3335                let mut index = 0;
 3336                s.move_cursors_with(|map, _, _| {
 3337                    let row = rows[index];
 3338                    index += 1;
 3339
 3340                    let point = Point::new(row, 0);
 3341                    let boundary = map.next_line_boundary(point).1;
 3342                    let clipped = map.clip_point(boundary, Bias::Left);
 3343
 3344                    (clipped, SelectionGoal::None)
 3345                });
 3346            });
 3347
 3348            let mut indent_edits = Vec::new();
 3349            let multibuffer_snapshot = editor.buffer.read(cx).snapshot(cx);
 3350            for row in rows {
 3351                let indents = multibuffer_snapshot.suggested_indents(row..row + 1, cx);
 3352                for (row, indent) in indents {
 3353                    if indent.len == 0 {
 3354                        continue;
 3355                    }
 3356
 3357                    let text = match indent.kind {
 3358                        IndentKind::Space => " ".repeat(indent.len as usize),
 3359                        IndentKind::Tab => "\t".repeat(indent.len as usize),
 3360                    };
 3361                    let point = Point::new(row.0, 0);
 3362                    indent_edits.push((point..point, text));
 3363                }
 3364            }
 3365            editor.edit(indent_edits, cx);
 3366        });
 3367    }
 3368
 3369    pub fn newline_below(&mut self, _: &NewlineBelow, window: &mut Window, cx: &mut Context<Self>) {
 3370        let buffer = self.buffer.read(cx);
 3371        let snapshot = buffer.snapshot(cx);
 3372
 3373        let mut edits = Vec::new();
 3374        let mut rows = Vec::new();
 3375        let mut rows_inserted = 0;
 3376
 3377        for selection in self.selections.all_adjusted(cx) {
 3378            let cursor = selection.head();
 3379            let row = cursor.row;
 3380
 3381            let point = Point::new(row + 1, 0);
 3382            let start_of_line = snapshot.clip_point(point, Bias::Left);
 3383
 3384            let newline = "\n".to_string();
 3385            edits.push((start_of_line..start_of_line, newline));
 3386
 3387            rows_inserted += 1;
 3388            rows.push(row + rows_inserted);
 3389        }
 3390
 3391        self.transact(window, cx, |editor, window, cx| {
 3392            editor.edit(edits, cx);
 3393
 3394            editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 3395                let mut index = 0;
 3396                s.move_cursors_with(|map, _, _| {
 3397                    let row = rows[index];
 3398                    index += 1;
 3399
 3400                    let point = Point::new(row, 0);
 3401                    let boundary = map.next_line_boundary(point).1;
 3402                    let clipped = map.clip_point(boundary, Bias::Left);
 3403
 3404                    (clipped, SelectionGoal::None)
 3405                });
 3406            });
 3407
 3408            let mut indent_edits = Vec::new();
 3409            let multibuffer_snapshot = editor.buffer.read(cx).snapshot(cx);
 3410            for row in rows {
 3411                let indents = multibuffer_snapshot.suggested_indents(row..row + 1, cx);
 3412                for (row, indent) in indents {
 3413                    if indent.len == 0 {
 3414                        continue;
 3415                    }
 3416
 3417                    let text = match indent.kind {
 3418                        IndentKind::Space => " ".repeat(indent.len as usize),
 3419                        IndentKind::Tab => "\t".repeat(indent.len as usize),
 3420                    };
 3421                    let point = Point::new(row.0, 0);
 3422                    indent_edits.push((point..point, text));
 3423                }
 3424            }
 3425            editor.edit(indent_edits, cx);
 3426        });
 3427    }
 3428
 3429    pub fn insert(&mut self, text: &str, window: &mut Window, cx: &mut Context<Self>) {
 3430        let autoindent = text.is_empty().not().then(|| AutoindentMode::Block {
 3431            original_start_columns: Vec::new(),
 3432        });
 3433        self.insert_with_autoindent_mode(text, autoindent, window, cx);
 3434    }
 3435
 3436    fn insert_with_autoindent_mode(
 3437        &mut self,
 3438        text: &str,
 3439        autoindent_mode: Option<AutoindentMode>,
 3440        window: &mut Window,
 3441        cx: &mut Context<Self>,
 3442    ) {
 3443        if self.read_only(cx) {
 3444            return;
 3445        }
 3446
 3447        let text: Arc<str> = text.into();
 3448        self.transact(window, cx, |this, window, cx| {
 3449            let old_selections = this.selections.all_adjusted(cx);
 3450            let selection_anchors = this.buffer.update(cx, |buffer, cx| {
 3451                let anchors = {
 3452                    let snapshot = buffer.read(cx);
 3453                    old_selections
 3454                        .iter()
 3455                        .map(|s| {
 3456                            let anchor = snapshot.anchor_after(s.head());
 3457                            s.map(|_| anchor)
 3458                        })
 3459                        .collect::<Vec<_>>()
 3460                };
 3461                buffer.edit(
 3462                    old_selections
 3463                        .iter()
 3464                        .map(|s| (s.start..s.end, text.clone())),
 3465                    autoindent_mode,
 3466                    cx,
 3467                );
 3468                anchors
 3469            });
 3470
 3471            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 3472                s.select_anchors(selection_anchors);
 3473            });
 3474
 3475            cx.notify();
 3476        });
 3477    }
 3478
 3479    fn trigger_completion_on_input(
 3480        &mut self,
 3481        text: &str,
 3482        trigger_in_words: bool,
 3483        window: &mut Window,
 3484        cx: &mut Context<Self>,
 3485    ) {
 3486        if self.is_completion_trigger(text, trigger_in_words, cx) {
 3487            self.show_completions(
 3488                &ShowCompletions {
 3489                    trigger: Some(text.to_owned()).filter(|x| !x.is_empty()),
 3490                },
 3491                window,
 3492                cx,
 3493            );
 3494        } else {
 3495            self.hide_context_menu(window, cx);
 3496        }
 3497    }
 3498
 3499    fn is_completion_trigger(
 3500        &self,
 3501        text: &str,
 3502        trigger_in_words: bool,
 3503        cx: &mut Context<Self>,
 3504    ) -> bool {
 3505        let position = self.selections.newest_anchor().head();
 3506        let multibuffer = self.buffer.read(cx);
 3507        let Some(buffer) = position
 3508            .buffer_id
 3509            .and_then(|buffer_id| multibuffer.buffer(buffer_id).clone())
 3510        else {
 3511            return false;
 3512        };
 3513
 3514        if let Some(completion_provider) = &self.completion_provider {
 3515            completion_provider.is_completion_trigger(
 3516                &buffer,
 3517                position.text_anchor,
 3518                text,
 3519                trigger_in_words,
 3520                cx,
 3521            )
 3522        } else {
 3523            false
 3524        }
 3525    }
 3526
 3527    /// If any empty selections is touching the start of its innermost containing autoclose
 3528    /// region, expand it to select the brackets.
 3529    fn select_autoclose_pair(&mut self, window: &mut Window, cx: &mut Context<Self>) {
 3530        let selections = self.selections.all::<usize>(cx);
 3531        let buffer = self.buffer.read(cx).read(cx);
 3532        let new_selections = self
 3533            .selections_with_autoclose_regions(selections, &buffer)
 3534            .map(|(mut selection, region)| {
 3535                if !selection.is_empty() {
 3536                    return selection;
 3537                }
 3538
 3539                if let Some(region) = region {
 3540                    let mut range = region.range.to_offset(&buffer);
 3541                    if selection.start == range.start && range.start >= region.pair.start.len() {
 3542                        range.start -= region.pair.start.len();
 3543                        if buffer.contains_str_at(range.start, &region.pair.start)
 3544                            && buffer.contains_str_at(range.end, &region.pair.end)
 3545                        {
 3546                            range.end += region.pair.end.len();
 3547                            selection.start = range.start;
 3548                            selection.end = range.end;
 3549
 3550                            return selection;
 3551                        }
 3552                    }
 3553                }
 3554
 3555                let always_treat_brackets_as_autoclosed = buffer
 3556                    .settings_at(selection.start, cx)
 3557                    .always_treat_brackets_as_autoclosed;
 3558
 3559                if !always_treat_brackets_as_autoclosed {
 3560                    return selection;
 3561                }
 3562
 3563                if let Some(scope) = buffer.language_scope_at(selection.start) {
 3564                    for (pair, enabled) in scope.brackets() {
 3565                        if !enabled || !pair.close {
 3566                            continue;
 3567                        }
 3568
 3569                        if buffer.contains_str_at(selection.start, &pair.end) {
 3570                            let pair_start_len = pair.start.len();
 3571                            if buffer.contains_str_at(
 3572                                selection.start.saturating_sub(pair_start_len),
 3573                                &pair.start,
 3574                            ) {
 3575                                selection.start -= pair_start_len;
 3576                                selection.end += pair.end.len();
 3577
 3578                                return selection;
 3579                            }
 3580                        }
 3581                    }
 3582                }
 3583
 3584                selection
 3585            })
 3586            .collect();
 3587
 3588        drop(buffer);
 3589        self.change_selections(None, window, cx, |selections| {
 3590            selections.select(new_selections)
 3591        });
 3592    }
 3593
 3594    /// Iterate the given selections, and for each one, find the smallest surrounding
 3595    /// autoclose region. This uses the ordering of the selections and the autoclose
 3596    /// regions to avoid repeated comparisons.
 3597    fn selections_with_autoclose_regions<'a, D: ToOffset + Clone>(
 3598        &'a self,
 3599        selections: impl IntoIterator<Item = Selection<D>>,
 3600        buffer: &'a MultiBufferSnapshot,
 3601    ) -> impl Iterator<Item = (Selection<D>, Option<&'a AutocloseRegion>)> {
 3602        let mut i = 0;
 3603        let mut regions = self.autoclose_regions.as_slice();
 3604        selections.into_iter().map(move |selection| {
 3605            let range = selection.start.to_offset(buffer)..selection.end.to_offset(buffer);
 3606
 3607            let mut enclosing = None;
 3608            while let Some(pair_state) = regions.get(i) {
 3609                if pair_state.range.end.to_offset(buffer) < range.start {
 3610                    regions = &regions[i + 1..];
 3611                    i = 0;
 3612                } else if pair_state.range.start.to_offset(buffer) > range.end {
 3613                    break;
 3614                } else {
 3615                    if pair_state.selection_id == selection.id {
 3616                        enclosing = Some(pair_state);
 3617                    }
 3618                    i += 1;
 3619                }
 3620            }
 3621
 3622            (selection, enclosing)
 3623        })
 3624    }
 3625
 3626    /// Remove any autoclose regions that no longer contain their selection.
 3627    fn invalidate_autoclose_regions(
 3628        &mut self,
 3629        mut selections: &[Selection<Anchor>],
 3630        buffer: &MultiBufferSnapshot,
 3631    ) {
 3632        self.autoclose_regions.retain(|state| {
 3633            let mut i = 0;
 3634            while let Some(selection) = selections.get(i) {
 3635                if selection.end.cmp(&state.range.start, buffer).is_lt() {
 3636                    selections = &selections[1..];
 3637                    continue;
 3638                }
 3639                if selection.start.cmp(&state.range.end, buffer).is_gt() {
 3640                    break;
 3641                }
 3642                if selection.id == state.selection_id {
 3643                    return true;
 3644                } else {
 3645                    i += 1;
 3646                }
 3647            }
 3648            false
 3649        });
 3650    }
 3651
 3652    fn completion_query(buffer: &MultiBufferSnapshot, position: impl ToOffset) -> Option<String> {
 3653        let offset = position.to_offset(buffer);
 3654        let (word_range, kind) = buffer.surrounding_word(offset, true);
 3655        if offset > word_range.start && kind == Some(CharKind::Word) {
 3656            Some(
 3657                buffer
 3658                    .text_for_range(word_range.start..offset)
 3659                    .collect::<String>(),
 3660            )
 3661        } else {
 3662            None
 3663        }
 3664    }
 3665
 3666    pub fn toggle_inlay_hints(
 3667        &mut self,
 3668        _: &ToggleInlayHints,
 3669        _: &mut Window,
 3670        cx: &mut Context<Self>,
 3671    ) {
 3672        self.refresh_inlay_hints(
 3673            InlayHintRefreshReason::Toggle(!self.inlay_hints_enabled()),
 3674            cx,
 3675        );
 3676    }
 3677
 3678    pub fn inlay_hints_enabled(&self) -> bool {
 3679        self.inlay_hint_cache.enabled
 3680    }
 3681
 3682    fn refresh_inlay_hints(&mut self, reason: InlayHintRefreshReason, cx: &mut Context<Self>) {
 3683        if self.semantics_provider.is_none() || self.mode != EditorMode::Full {
 3684            return;
 3685        }
 3686
 3687        let reason_description = reason.description();
 3688        let ignore_debounce = matches!(
 3689            reason,
 3690            InlayHintRefreshReason::SettingsChange(_)
 3691                | InlayHintRefreshReason::Toggle(_)
 3692                | InlayHintRefreshReason::ExcerptsRemoved(_)
 3693        );
 3694        let (invalidate_cache, required_languages) = match reason {
 3695            InlayHintRefreshReason::ModifiersChanged(enabled) => {
 3696                match self.inlay_hint_cache.modifiers_override(enabled) {
 3697                    Some(enabled) => {
 3698                        if enabled {
 3699                            (InvalidationStrategy::RefreshRequested, None)
 3700                        } else {
 3701                            self.splice_inlays(
 3702                                &self
 3703                                    .visible_inlay_hints(cx)
 3704                                    .iter()
 3705                                    .map(|inlay| inlay.id)
 3706                                    .collect::<Vec<InlayId>>(),
 3707                                Vec::new(),
 3708                                cx,
 3709                            );
 3710                            return;
 3711                        }
 3712                    }
 3713                    None => return,
 3714                }
 3715            }
 3716            InlayHintRefreshReason::Toggle(enabled) => {
 3717                if self.inlay_hint_cache.toggle(enabled) {
 3718                    if enabled {
 3719                        (InvalidationStrategy::RefreshRequested, None)
 3720                    } else {
 3721                        self.splice_inlays(
 3722                            &self
 3723                                .visible_inlay_hints(cx)
 3724                                .iter()
 3725                                .map(|inlay| inlay.id)
 3726                                .collect::<Vec<InlayId>>(),
 3727                            Vec::new(),
 3728                            cx,
 3729                        );
 3730                        return;
 3731                    }
 3732                } else {
 3733                    return;
 3734                }
 3735            }
 3736            InlayHintRefreshReason::SettingsChange(new_settings) => {
 3737                match self.inlay_hint_cache.update_settings(
 3738                    &self.buffer,
 3739                    new_settings,
 3740                    self.visible_inlay_hints(cx),
 3741                    cx,
 3742                ) {
 3743                    ControlFlow::Break(Some(InlaySplice {
 3744                        to_remove,
 3745                        to_insert,
 3746                    })) => {
 3747                        self.splice_inlays(&to_remove, to_insert, cx);
 3748                        return;
 3749                    }
 3750                    ControlFlow::Break(None) => return,
 3751                    ControlFlow::Continue(()) => (InvalidationStrategy::RefreshRequested, None),
 3752                }
 3753            }
 3754            InlayHintRefreshReason::ExcerptsRemoved(excerpts_removed) => {
 3755                if let Some(InlaySplice {
 3756                    to_remove,
 3757                    to_insert,
 3758                }) = self.inlay_hint_cache.remove_excerpts(excerpts_removed)
 3759                {
 3760                    self.splice_inlays(&to_remove, to_insert, cx);
 3761                }
 3762                return;
 3763            }
 3764            InlayHintRefreshReason::NewLinesShown => (InvalidationStrategy::None, None),
 3765            InlayHintRefreshReason::BufferEdited(buffer_languages) => {
 3766                (InvalidationStrategy::BufferEdited, Some(buffer_languages))
 3767            }
 3768            InlayHintRefreshReason::RefreshRequested => {
 3769                (InvalidationStrategy::RefreshRequested, None)
 3770            }
 3771        };
 3772
 3773        if let Some(InlaySplice {
 3774            to_remove,
 3775            to_insert,
 3776        }) = self.inlay_hint_cache.spawn_hint_refresh(
 3777            reason_description,
 3778            self.excerpts_for_inlay_hints_query(required_languages.as_ref(), cx),
 3779            invalidate_cache,
 3780            ignore_debounce,
 3781            cx,
 3782        ) {
 3783            self.splice_inlays(&to_remove, to_insert, cx);
 3784        }
 3785    }
 3786
 3787    fn visible_inlay_hints(&self, cx: &Context<Editor>) -> Vec<Inlay> {
 3788        self.display_map
 3789            .read(cx)
 3790            .current_inlays()
 3791            .filter(move |inlay| matches!(inlay.id, InlayId::Hint(_)))
 3792            .cloned()
 3793            .collect()
 3794    }
 3795
 3796    pub fn excerpts_for_inlay_hints_query(
 3797        &self,
 3798        restrict_to_languages: Option<&HashSet<Arc<Language>>>,
 3799        cx: &mut Context<Editor>,
 3800    ) -> HashMap<ExcerptId, (Entity<Buffer>, clock::Global, Range<usize>)> {
 3801        let Some(project) = self.project.as_ref() else {
 3802            return HashMap::default();
 3803        };
 3804        let project = project.read(cx);
 3805        let multi_buffer = self.buffer().read(cx);
 3806        let multi_buffer_snapshot = multi_buffer.snapshot(cx);
 3807        let multi_buffer_visible_start = self
 3808            .scroll_manager
 3809            .anchor()
 3810            .anchor
 3811            .to_point(&multi_buffer_snapshot);
 3812        let multi_buffer_visible_end = multi_buffer_snapshot.clip_point(
 3813            multi_buffer_visible_start
 3814                + Point::new(self.visible_line_count().unwrap_or(0.).ceil() as u32, 0),
 3815            Bias::Left,
 3816        );
 3817        let multi_buffer_visible_range = multi_buffer_visible_start..multi_buffer_visible_end;
 3818        multi_buffer_snapshot
 3819            .range_to_buffer_ranges(multi_buffer_visible_range)
 3820            .into_iter()
 3821            .filter(|(_, excerpt_visible_range, _)| !excerpt_visible_range.is_empty())
 3822            .filter_map(|(buffer, excerpt_visible_range, excerpt_id)| {
 3823                let buffer_file = project::File::from_dyn(buffer.file())?;
 3824                let buffer_worktree = project.worktree_for_id(buffer_file.worktree_id(cx), cx)?;
 3825                let worktree_entry = buffer_worktree
 3826                    .read(cx)
 3827                    .entry_for_id(buffer_file.project_entry_id(cx)?)?;
 3828                if worktree_entry.is_ignored {
 3829                    return None;
 3830                }
 3831
 3832                let language = buffer.language()?;
 3833                if let Some(restrict_to_languages) = restrict_to_languages {
 3834                    if !restrict_to_languages.contains(language) {
 3835                        return None;
 3836                    }
 3837                }
 3838                Some((
 3839                    excerpt_id,
 3840                    (
 3841                        multi_buffer.buffer(buffer.remote_id()).unwrap(),
 3842                        buffer.version().clone(),
 3843                        excerpt_visible_range,
 3844                    ),
 3845                ))
 3846            })
 3847            .collect()
 3848    }
 3849
 3850    pub fn text_layout_details(&self, window: &mut Window) -> TextLayoutDetails {
 3851        TextLayoutDetails {
 3852            text_system: window.text_system().clone(),
 3853            editor_style: self.style.clone().unwrap(),
 3854            rem_size: window.rem_size(),
 3855            scroll_anchor: self.scroll_manager.anchor(),
 3856            visible_rows: self.visible_line_count(),
 3857            vertical_scroll_margin: self.scroll_manager.vertical_scroll_margin,
 3858        }
 3859    }
 3860
 3861    pub fn splice_inlays(
 3862        &self,
 3863        to_remove: &[InlayId],
 3864        to_insert: Vec<Inlay>,
 3865        cx: &mut Context<Self>,
 3866    ) {
 3867        self.display_map.update(cx, |display_map, cx| {
 3868            display_map.splice_inlays(to_remove, to_insert, cx)
 3869        });
 3870        cx.notify();
 3871    }
 3872
 3873    fn trigger_on_type_formatting(
 3874        &self,
 3875        input: String,
 3876        window: &mut Window,
 3877        cx: &mut Context<Self>,
 3878    ) -> Option<Task<Result<()>>> {
 3879        if input.len() != 1 {
 3880            return None;
 3881        }
 3882
 3883        let project = self.project.as_ref()?;
 3884        let position = self.selections.newest_anchor().head();
 3885        let (buffer, buffer_position) = self
 3886            .buffer
 3887            .read(cx)
 3888            .text_anchor_for_position(position, cx)?;
 3889
 3890        let settings = language_settings::language_settings(
 3891            buffer
 3892                .read(cx)
 3893                .language_at(buffer_position)
 3894                .map(|l| l.name()),
 3895            buffer.read(cx).file(),
 3896            cx,
 3897        );
 3898        if !settings.use_on_type_format {
 3899            return None;
 3900        }
 3901
 3902        // OnTypeFormatting returns a list of edits, no need to pass them between Zed instances,
 3903        // hence we do LSP request & edit on host side only — add formats to host's history.
 3904        let push_to_lsp_host_history = true;
 3905        // If this is not the host, append its history with new edits.
 3906        let push_to_client_history = project.read(cx).is_via_collab();
 3907
 3908        let on_type_formatting = project.update(cx, |project, cx| {
 3909            project.on_type_format(
 3910                buffer.clone(),
 3911                buffer_position,
 3912                input,
 3913                push_to_lsp_host_history,
 3914                cx,
 3915            )
 3916        });
 3917        Some(cx.spawn_in(window, |editor, mut cx| async move {
 3918            if let Some(transaction) = on_type_formatting.await? {
 3919                if push_to_client_history {
 3920                    buffer
 3921                        .update(&mut cx, |buffer, _| {
 3922                            buffer.push_transaction(transaction, Instant::now());
 3923                        })
 3924                        .ok();
 3925                }
 3926                editor.update(&mut cx, |editor, cx| {
 3927                    editor.refresh_document_highlights(cx);
 3928                })?;
 3929            }
 3930            Ok(())
 3931        }))
 3932    }
 3933
 3934    pub fn show_completions(
 3935        &mut self,
 3936        options: &ShowCompletions,
 3937        window: &mut Window,
 3938        cx: &mut Context<Self>,
 3939    ) {
 3940        if self.pending_rename.is_some() {
 3941            return;
 3942        }
 3943
 3944        let Some(provider) = self.completion_provider.as_ref() else {
 3945            return;
 3946        };
 3947
 3948        if !self.snippet_stack.is_empty() && self.context_menu.borrow().as_ref().is_some() {
 3949            return;
 3950        }
 3951
 3952        let position = self.selections.newest_anchor().head();
 3953        if position.diff_base_anchor.is_some() {
 3954            return;
 3955        }
 3956        let (buffer, buffer_position) =
 3957            if let Some(output) = self.buffer.read(cx).text_anchor_for_position(position, cx) {
 3958                output
 3959            } else {
 3960                return;
 3961            };
 3962        let show_completion_documentation = buffer
 3963            .read(cx)
 3964            .snapshot()
 3965            .settings_at(buffer_position, cx)
 3966            .show_completion_documentation;
 3967
 3968        let query = Self::completion_query(&self.buffer.read(cx).read(cx), position);
 3969
 3970        let trigger_kind = match &options.trigger {
 3971            Some(trigger) if buffer.read(cx).completion_triggers().contains(trigger) => {
 3972                CompletionTriggerKind::TRIGGER_CHARACTER
 3973            }
 3974            _ => CompletionTriggerKind::INVOKED,
 3975        };
 3976        let completion_context = CompletionContext {
 3977            trigger_character: options.trigger.as_ref().and_then(|trigger| {
 3978                if trigger_kind == CompletionTriggerKind::TRIGGER_CHARACTER {
 3979                    Some(String::from(trigger))
 3980                } else {
 3981                    None
 3982                }
 3983            }),
 3984            trigger_kind,
 3985        };
 3986        let completions =
 3987            provider.completions(&buffer, buffer_position, completion_context, window, cx);
 3988        let sort_completions = provider.sort_completions();
 3989
 3990        let id = post_inc(&mut self.next_completion_id);
 3991        let task = cx.spawn_in(window, |editor, mut cx| {
 3992            async move {
 3993                editor.update(&mut cx, |this, _| {
 3994                    this.completion_tasks.retain(|(task_id, _)| *task_id >= id);
 3995                })?;
 3996                let completions = completions.await.log_err();
 3997                let menu = if let Some(completions) = completions {
 3998                    let mut menu = CompletionsMenu::new(
 3999                        id,
 4000                        sort_completions,
 4001                        show_completion_documentation,
 4002                        position,
 4003                        buffer.clone(),
 4004                        completions.into(),
 4005                    );
 4006
 4007                    menu.filter(query.as_deref(), cx.background_executor().clone())
 4008                        .await;
 4009
 4010                    menu.visible().then_some(menu)
 4011                } else {
 4012                    None
 4013                };
 4014
 4015                editor.update_in(&mut cx, |editor, window, cx| {
 4016                    match editor.context_menu.borrow().as_ref() {
 4017                        None => {}
 4018                        Some(CodeContextMenu::Completions(prev_menu)) => {
 4019                            if prev_menu.id > id {
 4020                                return;
 4021                            }
 4022                        }
 4023                        _ => return,
 4024                    }
 4025
 4026                    if editor.focus_handle.is_focused(window) && menu.is_some() {
 4027                        let mut menu = menu.unwrap();
 4028                        menu.resolve_visible_completions(editor.completion_provider.as_deref(), cx);
 4029
 4030                        *editor.context_menu.borrow_mut() =
 4031                            Some(CodeContextMenu::Completions(menu));
 4032
 4033                        if editor.show_edit_predictions_in_menu() {
 4034                            editor.update_visible_inline_completion(window, cx);
 4035                        } else {
 4036                            editor.discard_inline_completion(false, cx);
 4037                        }
 4038
 4039                        cx.notify();
 4040                    } else if editor.completion_tasks.len() <= 1 {
 4041                        // If there are no more completion tasks and the last menu was
 4042                        // empty, we should hide it.
 4043                        let was_hidden = editor.hide_context_menu(window, cx).is_none();
 4044                        // If it was already hidden and we don't show inline
 4045                        // completions in the menu, we should also show the
 4046                        // inline-completion when available.
 4047                        if was_hidden && editor.show_edit_predictions_in_menu() {
 4048                            editor.update_visible_inline_completion(window, cx);
 4049                        }
 4050                    }
 4051                })?;
 4052
 4053                Ok::<_, anyhow::Error>(())
 4054            }
 4055            .log_err()
 4056        });
 4057
 4058        self.completion_tasks.push((id, task));
 4059    }
 4060
 4061    pub fn confirm_completion(
 4062        &mut self,
 4063        action: &ConfirmCompletion,
 4064        window: &mut Window,
 4065        cx: &mut Context<Self>,
 4066    ) -> Option<Task<Result<()>>> {
 4067        self.do_completion(action.item_ix, CompletionIntent::Complete, window, cx)
 4068    }
 4069
 4070    pub fn compose_completion(
 4071        &mut self,
 4072        action: &ComposeCompletion,
 4073        window: &mut Window,
 4074        cx: &mut Context<Self>,
 4075    ) -> Option<Task<Result<()>>> {
 4076        self.do_completion(action.item_ix, CompletionIntent::Compose, window, cx)
 4077    }
 4078
 4079    fn do_completion(
 4080        &mut self,
 4081        item_ix: Option<usize>,
 4082        intent: CompletionIntent,
 4083        window: &mut Window,
 4084        cx: &mut Context<Editor>,
 4085    ) -> Option<Task<std::result::Result<(), anyhow::Error>>> {
 4086        use language::ToOffset as _;
 4087
 4088        let completions_menu =
 4089            if let CodeContextMenu::Completions(menu) = self.hide_context_menu(window, cx)? {
 4090                menu
 4091            } else {
 4092                return None;
 4093            };
 4094
 4095        let entries = completions_menu.entries.borrow();
 4096        let mat = entries.get(item_ix.unwrap_or(completions_menu.selected_item))?;
 4097        if self.show_edit_predictions_in_menu() {
 4098            self.discard_inline_completion(true, cx);
 4099        }
 4100        let candidate_id = mat.candidate_id;
 4101        drop(entries);
 4102
 4103        let buffer_handle = completions_menu.buffer;
 4104        let completion = completions_menu
 4105            .completions
 4106            .borrow()
 4107            .get(candidate_id)?
 4108            .clone();
 4109        cx.stop_propagation();
 4110
 4111        let snippet;
 4112        let text;
 4113
 4114        if completion.is_snippet() {
 4115            snippet = Some(Snippet::parse(&completion.new_text).log_err()?);
 4116            text = snippet.as_ref().unwrap().text.clone();
 4117        } else {
 4118            snippet = None;
 4119            text = completion.new_text.clone();
 4120        };
 4121        let selections = self.selections.all::<usize>(cx);
 4122        let buffer = buffer_handle.read(cx);
 4123        let old_range = completion.old_range.to_offset(buffer);
 4124        let old_text = buffer.text_for_range(old_range.clone()).collect::<String>();
 4125
 4126        let newest_selection = self.selections.newest_anchor();
 4127        if newest_selection.start.buffer_id != Some(buffer_handle.read(cx).remote_id()) {
 4128            return None;
 4129        }
 4130
 4131        let lookbehind = newest_selection
 4132            .start
 4133            .text_anchor
 4134            .to_offset(buffer)
 4135            .saturating_sub(old_range.start);
 4136        let lookahead = old_range
 4137            .end
 4138            .saturating_sub(newest_selection.end.text_anchor.to_offset(buffer));
 4139        let mut common_prefix_len = old_text
 4140            .bytes()
 4141            .zip(text.bytes())
 4142            .take_while(|(a, b)| a == b)
 4143            .count();
 4144
 4145        let snapshot = self.buffer.read(cx).snapshot(cx);
 4146        let mut range_to_replace: Option<Range<isize>> = None;
 4147        let mut ranges = Vec::new();
 4148        let mut linked_edits = HashMap::<_, Vec<_>>::default();
 4149        for selection in &selections {
 4150            if snapshot.contains_str_at(selection.start.saturating_sub(lookbehind), &old_text) {
 4151                let start = selection.start.saturating_sub(lookbehind);
 4152                let end = selection.end + lookahead;
 4153                if selection.id == newest_selection.id {
 4154                    range_to_replace = Some(
 4155                        ((start + common_prefix_len) as isize - selection.start as isize)
 4156                            ..(end as isize - selection.start as isize),
 4157                    );
 4158                }
 4159                ranges.push(start + common_prefix_len..end);
 4160            } else {
 4161                common_prefix_len = 0;
 4162                ranges.clear();
 4163                ranges.extend(selections.iter().map(|s| {
 4164                    if s.id == newest_selection.id {
 4165                        range_to_replace = Some(
 4166                            old_range.start.to_offset_utf16(&snapshot).0 as isize
 4167                                - selection.start as isize
 4168                                ..old_range.end.to_offset_utf16(&snapshot).0 as isize
 4169                                    - selection.start as isize,
 4170                        );
 4171                        old_range.clone()
 4172                    } else {
 4173                        s.start..s.end
 4174                    }
 4175                }));
 4176                break;
 4177            }
 4178            if !self.linked_edit_ranges.is_empty() {
 4179                let start_anchor = snapshot.anchor_before(selection.head());
 4180                let end_anchor = snapshot.anchor_after(selection.tail());
 4181                if let Some(ranges) = self
 4182                    .linked_editing_ranges_for(start_anchor.text_anchor..end_anchor.text_anchor, cx)
 4183                {
 4184                    for (buffer, edits) in ranges {
 4185                        linked_edits.entry(buffer.clone()).or_default().extend(
 4186                            edits
 4187                                .into_iter()
 4188                                .map(|range| (range, text[common_prefix_len..].to_owned())),
 4189                        );
 4190                    }
 4191                }
 4192            }
 4193        }
 4194        let text = &text[common_prefix_len..];
 4195
 4196        cx.emit(EditorEvent::InputHandled {
 4197            utf16_range_to_replace: range_to_replace,
 4198            text: text.into(),
 4199        });
 4200
 4201        self.transact(window, cx, |this, window, cx| {
 4202            if let Some(mut snippet) = snippet {
 4203                snippet.text = text.to_string();
 4204                for tabstop in snippet
 4205                    .tabstops
 4206                    .iter_mut()
 4207                    .flat_map(|tabstop| tabstop.ranges.iter_mut())
 4208                {
 4209                    tabstop.start -= common_prefix_len as isize;
 4210                    tabstop.end -= common_prefix_len as isize;
 4211                }
 4212
 4213                this.insert_snippet(&ranges, snippet, window, cx).log_err();
 4214            } else {
 4215                this.buffer.update(cx, |buffer, cx| {
 4216                    buffer.edit(
 4217                        ranges.iter().map(|range| (range.clone(), text)),
 4218                        this.autoindent_mode.clone(),
 4219                        cx,
 4220                    );
 4221                });
 4222            }
 4223            for (buffer, edits) in linked_edits {
 4224                buffer.update(cx, |buffer, cx| {
 4225                    let snapshot = buffer.snapshot();
 4226                    let edits = edits
 4227                        .into_iter()
 4228                        .map(|(range, text)| {
 4229                            use text::ToPoint as TP;
 4230                            let end_point = TP::to_point(&range.end, &snapshot);
 4231                            let start_point = TP::to_point(&range.start, &snapshot);
 4232                            (start_point..end_point, text)
 4233                        })
 4234                        .sorted_by_key(|(range, _)| range.start)
 4235                        .collect::<Vec<_>>();
 4236                    buffer.edit(edits, None, cx);
 4237                })
 4238            }
 4239
 4240            this.refresh_inline_completion(true, false, window, cx);
 4241        });
 4242
 4243        let show_new_completions_on_confirm = completion
 4244            .confirm
 4245            .as_ref()
 4246            .map_or(false, |confirm| confirm(intent, window, cx));
 4247        if show_new_completions_on_confirm {
 4248            self.show_completions(&ShowCompletions { trigger: None }, window, cx);
 4249        }
 4250
 4251        let provider = self.completion_provider.as_ref()?;
 4252        drop(completion);
 4253        let apply_edits = provider.apply_additional_edits_for_completion(
 4254            buffer_handle,
 4255            completions_menu.completions.clone(),
 4256            candidate_id,
 4257            true,
 4258            cx,
 4259        );
 4260
 4261        let editor_settings = EditorSettings::get_global(cx);
 4262        if editor_settings.show_signature_help_after_edits || editor_settings.auto_signature_help {
 4263            // After the code completion is finished, users often want to know what signatures are needed.
 4264            // so we should automatically call signature_help
 4265            self.show_signature_help(&ShowSignatureHelp, window, cx);
 4266        }
 4267
 4268        Some(cx.foreground_executor().spawn(async move {
 4269            apply_edits.await?;
 4270            Ok(())
 4271        }))
 4272    }
 4273
 4274    pub fn toggle_code_actions(
 4275        &mut self,
 4276        action: &ToggleCodeActions,
 4277        window: &mut Window,
 4278        cx: &mut Context<Self>,
 4279    ) {
 4280        let mut context_menu = self.context_menu.borrow_mut();
 4281        if let Some(CodeContextMenu::CodeActions(code_actions)) = context_menu.as_ref() {
 4282            if code_actions.deployed_from_indicator == action.deployed_from_indicator {
 4283                // Toggle if we're selecting the same one
 4284                *context_menu = None;
 4285                cx.notify();
 4286                return;
 4287            } else {
 4288                // Otherwise, clear it and start a new one
 4289                *context_menu = None;
 4290                cx.notify();
 4291            }
 4292        }
 4293        drop(context_menu);
 4294        let snapshot = self.snapshot(window, cx);
 4295        let deployed_from_indicator = action.deployed_from_indicator;
 4296        let mut task = self.code_actions_task.take();
 4297        let action = action.clone();
 4298        cx.spawn_in(window, |editor, mut cx| async move {
 4299            while let Some(prev_task) = task {
 4300                prev_task.await.log_err();
 4301                task = editor.update(&mut cx, |this, _| this.code_actions_task.take())?;
 4302            }
 4303
 4304            let spawned_test_task = editor.update_in(&mut cx, |editor, window, cx| {
 4305                if editor.focus_handle.is_focused(window) {
 4306                    let multibuffer_point = action
 4307                        .deployed_from_indicator
 4308                        .map(|row| DisplayPoint::new(row, 0).to_point(&snapshot))
 4309                        .unwrap_or_else(|| editor.selections.newest::<Point>(cx).head());
 4310                    let (buffer, buffer_row) = snapshot
 4311                        .buffer_snapshot
 4312                        .buffer_line_for_row(MultiBufferRow(multibuffer_point.row))
 4313                        .and_then(|(buffer_snapshot, range)| {
 4314                            editor
 4315                                .buffer
 4316                                .read(cx)
 4317                                .buffer(buffer_snapshot.remote_id())
 4318                                .map(|buffer| (buffer, range.start.row))
 4319                        })?;
 4320                    let (_, code_actions) = editor
 4321                        .available_code_actions
 4322                        .clone()
 4323                        .and_then(|(location, code_actions)| {
 4324                            let snapshot = location.buffer.read(cx).snapshot();
 4325                            let point_range = location.range.to_point(&snapshot);
 4326                            let point_range = point_range.start.row..=point_range.end.row;
 4327                            if point_range.contains(&buffer_row) {
 4328                                Some((location, code_actions))
 4329                            } else {
 4330                                None
 4331                            }
 4332                        })
 4333                        .unzip();
 4334                    let buffer_id = buffer.read(cx).remote_id();
 4335                    let tasks = editor
 4336                        .tasks
 4337                        .get(&(buffer_id, buffer_row))
 4338                        .map(|t| Arc::new(t.to_owned()));
 4339                    if tasks.is_none() && code_actions.is_none() {
 4340                        return None;
 4341                    }
 4342
 4343                    editor.completion_tasks.clear();
 4344                    editor.discard_inline_completion(false, cx);
 4345                    let task_context =
 4346                        tasks
 4347                            .as_ref()
 4348                            .zip(editor.project.clone())
 4349                            .map(|(tasks, project)| {
 4350                                Self::build_tasks_context(&project, &buffer, buffer_row, tasks, cx)
 4351                            });
 4352
 4353                    Some(cx.spawn_in(window, |editor, mut cx| async move {
 4354                        let task_context = match task_context {
 4355                            Some(task_context) => task_context.await,
 4356                            None => None,
 4357                        };
 4358                        let resolved_tasks =
 4359                            tasks.zip(task_context).map(|(tasks, task_context)| {
 4360                                Rc::new(ResolvedTasks {
 4361                                    templates: tasks.resolve(&task_context).collect(),
 4362                                    position: snapshot.buffer_snapshot.anchor_before(Point::new(
 4363                                        multibuffer_point.row,
 4364                                        tasks.column,
 4365                                    )),
 4366                                })
 4367                            });
 4368                        let spawn_straight_away = resolved_tasks
 4369                            .as_ref()
 4370                            .map_or(false, |tasks| tasks.templates.len() == 1)
 4371                            && code_actions
 4372                                .as_ref()
 4373                                .map_or(true, |actions| actions.is_empty());
 4374                        if let Ok(task) = editor.update_in(&mut cx, |editor, window, cx| {
 4375                            *editor.context_menu.borrow_mut() =
 4376                                Some(CodeContextMenu::CodeActions(CodeActionsMenu {
 4377                                    buffer,
 4378                                    actions: CodeActionContents {
 4379                                        tasks: resolved_tasks,
 4380                                        actions: code_actions,
 4381                                    },
 4382                                    selected_item: Default::default(),
 4383                                    scroll_handle: UniformListScrollHandle::default(),
 4384                                    deployed_from_indicator,
 4385                                }));
 4386                            if spawn_straight_away {
 4387                                if let Some(task) = editor.confirm_code_action(
 4388                                    &ConfirmCodeAction { item_ix: Some(0) },
 4389                                    window,
 4390                                    cx,
 4391                                ) {
 4392                                    cx.notify();
 4393                                    return task;
 4394                                }
 4395                            }
 4396                            cx.notify();
 4397                            Task::ready(Ok(()))
 4398                        }) {
 4399                            task.await
 4400                        } else {
 4401                            Ok(())
 4402                        }
 4403                    }))
 4404                } else {
 4405                    Some(Task::ready(Ok(())))
 4406                }
 4407            })?;
 4408            if let Some(task) = spawned_test_task {
 4409                task.await?;
 4410            }
 4411
 4412            Ok::<_, anyhow::Error>(())
 4413        })
 4414        .detach_and_log_err(cx);
 4415    }
 4416
 4417    pub fn confirm_code_action(
 4418        &mut self,
 4419        action: &ConfirmCodeAction,
 4420        window: &mut Window,
 4421        cx: &mut Context<Self>,
 4422    ) -> Option<Task<Result<()>>> {
 4423        let actions_menu =
 4424            if let CodeContextMenu::CodeActions(menu) = self.hide_context_menu(window, cx)? {
 4425                menu
 4426            } else {
 4427                return None;
 4428            };
 4429        let action_ix = action.item_ix.unwrap_or(actions_menu.selected_item);
 4430        let action = actions_menu.actions.get(action_ix)?;
 4431        let title = action.label();
 4432        let buffer = actions_menu.buffer;
 4433        let workspace = self.workspace()?;
 4434
 4435        match action {
 4436            CodeActionsItem::Task(task_source_kind, resolved_task) => {
 4437                workspace.update(cx, |workspace, cx| {
 4438                    workspace::tasks::schedule_resolved_task(
 4439                        workspace,
 4440                        task_source_kind,
 4441                        resolved_task,
 4442                        false,
 4443                        cx,
 4444                    );
 4445
 4446                    Some(Task::ready(Ok(())))
 4447                })
 4448            }
 4449            CodeActionsItem::CodeAction {
 4450                excerpt_id,
 4451                action,
 4452                provider,
 4453            } => {
 4454                let apply_code_action =
 4455                    provider.apply_code_action(buffer, action, excerpt_id, true, window, cx);
 4456                let workspace = workspace.downgrade();
 4457                Some(cx.spawn_in(window, |editor, cx| async move {
 4458                    let project_transaction = apply_code_action.await?;
 4459                    Self::open_project_transaction(
 4460                        &editor,
 4461                        workspace,
 4462                        project_transaction,
 4463                        title,
 4464                        cx,
 4465                    )
 4466                    .await
 4467                }))
 4468            }
 4469        }
 4470    }
 4471
 4472    pub async fn open_project_transaction(
 4473        this: &WeakEntity<Editor>,
 4474        workspace: WeakEntity<Workspace>,
 4475        transaction: ProjectTransaction,
 4476        title: String,
 4477        mut cx: AsyncWindowContext,
 4478    ) -> Result<()> {
 4479        let mut entries = transaction.0.into_iter().collect::<Vec<_>>();
 4480        cx.update(|_, cx| {
 4481            entries.sort_unstable_by_key(|(buffer, _)| {
 4482                buffer.read(cx).file().map(|f| f.path().clone())
 4483            });
 4484        })?;
 4485
 4486        // If the project transaction's edits are all contained within this editor, then
 4487        // avoid opening a new editor to display them.
 4488
 4489        if let Some((buffer, transaction)) = entries.first() {
 4490            if entries.len() == 1 {
 4491                let excerpt = this.update(&mut cx, |editor, cx| {
 4492                    editor
 4493                        .buffer()
 4494                        .read(cx)
 4495                        .excerpt_containing(editor.selections.newest_anchor().head(), cx)
 4496                })?;
 4497                if let Some((_, excerpted_buffer, excerpt_range)) = excerpt {
 4498                    if excerpted_buffer == *buffer {
 4499                        let all_edits_within_excerpt = buffer.read_with(&cx, |buffer, _| {
 4500                            let excerpt_range = excerpt_range.to_offset(buffer);
 4501                            buffer
 4502                                .edited_ranges_for_transaction::<usize>(transaction)
 4503                                .all(|range| {
 4504                                    excerpt_range.start <= range.start
 4505                                        && excerpt_range.end >= range.end
 4506                                })
 4507                        })?;
 4508
 4509                        if all_edits_within_excerpt {
 4510                            return Ok(());
 4511                        }
 4512                    }
 4513                }
 4514            }
 4515        } else {
 4516            return Ok(());
 4517        }
 4518
 4519        let mut ranges_to_highlight = Vec::new();
 4520        let excerpt_buffer = cx.new(|cx| {
 4521            let mut multibuffer = MultiBuffer::new(Capability::ReadWrite).with_title(title);
 4522            for (buffer_handle, transaction) in &entries {
 4523                let buffer = buffer_handle.read(cx);
 4524                ranges_to_highlight.extend(
 4525                    multibuffer.push_excerpts_with_context_lines(
 4526                        buffer_handle.clone(),
 4527                        buffer
 4528                            .edited_ranges_for_transaction::<usize>(transaction)
 4529                            .collect(),
 4530                        DEFAULT_MULTIBUFFER_CONTEXT,
 4531                        cx,
 4532                    ),
 4533                );
 4534            }
 4535            multibuffer.push_transaction(entries.iter().map(|(b, t)| (b, t)), cx);
 4536            multibuffer
 4537        })?;
 4538
 4539        workspace.update_in(&mut cx, |workspace, window, cx| {
 4540            let project = workspace.project().clone();
 4541            let editor = cx
 4542                .new(|cx| Editor::for_multibuffer(excerpt_buffer, Some(project), true, window, cx));
 4543            workspace.add_item_to_active_pane(Box::new(editor.clone()), None, true, window, cx);
 4544            editor.update(cx, |editor, cx| {
 4545                editor.highlight_background::<Self>(
 4546                    &ranges_to_highlight,
 4547                    |theme| theme.editor_highlighted_line_background,
 4548                    cx,
 4549                );
 4550            });
 4551        })?;
 4552
 4553        Ok(())
 4554    }
 4555
 4556    pub fn clear_code_action_providers(&mut self) {
 4557        self.code_action_providers.clear();
 4558        self.available_code_actions.take();
 4559    }
 4560
 4561    pub fn add_code_action_provider(
 4562        &mut self,
 4563        provider: Rc<dyn CodeActionProvider>,
 4564        window: &mut Window,
 4565        cx: &mut Context<Self>,
 4566    ) {
 4567        if self
 4568            .code_action_providers
 4569            .iter()
 4570            .any(|existing_provider| existing_provider.id() == provider.id())
 4571        {
 4572            return;
 4573        }
 4574
 4575        self.code_action_providers.push(provider);
 4576        self.refresh_code_actions(window, cx);
 4577    }
 4578
 4579    pub fn remove_code_action_provider(
 4580        &mut self,
 4581        id: Arc<str>,
 4582        window: &mut Window,
 4583        cx: &mut Context<Self>,
 4584    ) {
 4585        self.code_action_providers
 4586            .retain(|provider| provider.id() != id);
 4587        self.refresh_code_actions(window, cx);
 4588    }
 4589
 4590    fn refresh_code_actions(&mut self, window: &mut Window, cx: &mut Context<Self>) -> Option<()> {
 4591        let buffer = self.buffer.read(cx);
 4592        let newest_selection = self.selections.newest_anchor().clone();
 4593        if newest_selection.head().diff_base_anchor.is_some() {
 4594            return None;
 4595        }
 4596        let (start_buffer, start) = buffer.text_anchor_for_position(newest_selection.start, cx)?;
 4597        let (end_buffer, end) = buffer.text_anchor_for_position(newest_selection.end, cx)?;
 4598        if start_buffer != end_buffer {
 4599            return None;
 4600        }
 4601
 4602        self.code_actions_task = Some(cx.spawn_in(window, |this, mut cx| async move {
 4603            cx.background_executor()
 4604                .timer(CODE_ACTIONS_DEBOUNCE_TIMEOUT)
 4605                .await;
 4606
 4607            let (providers, tasks) = this.update_in(&mut cx, |this, window, cx| {
 4608                let providers = this.code_action_providers.clone();
 4609                let tasks = this
 4610                    .code_action_providers
 4611                    .iter()
 4612                    .map(|provider| provider.code_actions(&start_buffer, start..end, window, cx))
 4613                    .collect::<Vec<_>>();
 4614                (providers, tasks)
 4615            })?;
 4616
 4617            let mut actions = Vec::new();
 4618            for (provider, provider_actions) in
 4619                providers.into_iter().zip(future::join_all(tasks).await)
 4620            {
 4621                if let Some(provider_actions) = provider_actions.log_err() {
 4622                    actions.extend(provider_actions.into_iter().map(|action| {
 4623                        AvailableCodeAction {
 4624                            excerpt_id: newest_selection.start.excerpt_id,
 4625                            action,
 4626                            provider: provider.clone(),
 4627                        }
 4628                    }));
 4629                }
 4630            }
 4631
 4632            this.update(&mut cx, |this, cx| {
 4633                this.available_code_actions = if actions.is_empty() {
 4634                    None
 4635                } else {
 4636                    Some((
 4637                        Location {
 4638                            buffer: start_buffer,
 4639                            range: start..end,
 4640                        },
 4641                        actions.into(),
 4642                    ))
 4643                };
 4644                cx.notify();
 4645            })
 4646        }));
 4647        None
 4648    }
 4649
 4650    fn start_inline_blame_timer(&mut self, window: &mut Window, cx: &mut Context<Self>) {
 4651        if let Some(delay) = ProjectSettings::get_global(cx).git.inline_blame_delay() {
 4652            self.show_git_blame_inline = false;
 4653
 4654            self.show_git_blame_inline_delay_task =
 4655                Some(cx.spawn_in(window, |this, mut cx| async move {
 4656                    cx.background_executor().timer(delay).await;
 4657
 4658                    this.update(&mut cx, |this, cx| {
 4659                        this.show_git_blame_inline = true;
 4660                        cx.notify();
 4661                    })
 4662                    .log_err();
 4663                }));
 4664        }
 4665    }
 4666
 4667    fn refresh_document_highlights(&mut self, cx: &mut Context<Self>) -> Option<()> {
 4668        if self.pending_rename.is_some() {
 4669            return None;
 4670        }
 4671
 4672        let provider = self.semantics_provider.clone()?;
 4673        let buffer = self.buffer.read(cx);
 4674        let newest_selection = self.selections.newest_anchor().clone();
 4675        let cursor_position = newest_selection.head();
 4676        let (cursor_buffer, cursor_buffer_position) =
 4677            buffer.text_anchor_for_position(cursor_position, cx)?;
 4678        let (tail_buffer, _) = buffer.text_anchor_for_position(newest_selection.tail(), cx)?;
 4679        if cursor_buffer != tail_buffer {
 4680            return None;
 4681        }
 4682        let debounce = EditorSettings::get_global(cx).lsp_highlight_debounce;
 4683        self.document_highlights_task = Some(cx.spawn(|this, mut cx| async move {
 4684            cx.background_executor()
 4685                .timer(Duration::from_millis(debounce))
 4686                .await;
 4687
 4688            let highlights = if let Some(highlights) = cx
 4689                .update(|cx| {
 4690                    provider.document_highlights(&cursor_buffer, cursor_buffer_position, cx)
 4691                })
 4692                .ok()
 4693                .flatten()
 4694            {
 4695                highlights.await.log_err()
 4696            } else {
 4697                None
 4698            };
 4699
 4700            if let Some(highlights) = highlights {
 4701                this.update(&mut cx, |this, cx| {
 4702                    if this.pending_rename.is_some() {
 4703                        return;
 4704                    }
 4705
 4706                    let buffer_id = cursor_position.buffer_id;
 4707                    let buffer = this.buffer.read(cx);
 4708                    if !buffer
 4709                        .text_anchor_for_position(cursor_position, cx)
 4710                        .map_or(false, |(buffer, _)| buffer == cursor_buffer)
 4711                    {
 4712                        return;
 4713                    }
 4714
 4715                    let cursor_buffer_snapshot = cursor_buffer.read(cx);
 4716                    let mut write_ranges = Vec::new();
 4717                    let mut read_ranges = Vec::new();
 4718                    for highlight in highlights {
 4719                        for (excerpt_id, excerpt_range) in
 4720                            buffer.excerpts_for_buffer(cursor_buffer.read(cx).remote_id(), cx)
 4721                        {
 4722                            let start = highlight
 4723                                .range
 4724                                .start
 4725                                .max(&excerpt_range.context.start, cursor_buffer_snapshot);
 4726                            let end = highlight
 4727                                .range
 4728                                .end
 4729                                .min(&excerpt_range.context.end, cursor_buffer_snapshot);
 4730                            if start.cmp(&end, cursor_buffer_snapshot).is_ge() {
 4731                                continue;
 4732                            }
 4733
 4734                            let range = Anchor {
 4735                                buffer_id,
 4736                                excerpt_id,
 4737                                text_anchor: start,
 4738                                diff_base_anchor: None,
 4739                            }..Anchor {
 4740                                buffer_id,
 4741                                excerpt_id,
 4742                                text_anchor: end,
 4743                                diff_base_anchor: None,
 4744                            };
 4745                            if highlight.kind == lsp::DocumentHighlightKind::WRITE {
 4746                                write_ranges.push(range);
 4747                            } else {
 4748                                read_ranges.push(range);
 4749                            }
 4750                        }
 4751                    }
 4752
 4753                    this.highlight_background::<DocumentHighlightRead>(
 4754                        &read_ranges,
 4755                        |theme| theme.editor_document_highlight_read_background,
 4756                        cx,
 4757                    );
 4758                    this.highlight_background::<DocumentHighlightWrite>(
 4759                        &write_ranges,
 4760                        |theme| theme.editor_document_highlight_write_background,
 4761                        cx,
 4762                    );
 4763                    cx.notify();
 4764                })
 4765                .log_err();
 4766            }
 4767        }));
 4768        None
 4769    }
 4770
 4771    pub fn refresh_selected_text_highlights(
 4772        &mut self,
 4773        window: &mut Window,
 4774        cx: &mut Context<Editor>,
 4775    ) {
 4776        self.selection_highlight_task.take();
 4777        if !EditorSettings::get_global(cx).selection_highlight {
 4778            self.clear_background_highlights::<SelectedTextHighlight>(cx);
 4779            return;
 4780        }
 4781        if self.selections.count() != 1 || self.selections.line_mode {
 4782            self.clear_background_highlights::<SelectedTextHighlight>(cx);
 4783            return;
 4784        }
 4785        let selection = self.selections.newest::<Point>(cx);
 4786        if selection.is_empty() || selection.start.row != selection.end.row {
 4787            self.clear_background_highlights::<SelectedTextHighlight>(cx);
 4788            return;
 4789        }
 4790        let debounce = EditorSettings::get_global(cx).selection_highlight_debounce;
 4791        self.selection_highlight_task = Some(cx.spawn_in(window, |editor, mut cx| async move {
 4792            cx.background_executor()
 4793                .timer(Duration::from_millis(debounce))
 4794                .await;
 4795            let Some(Some(matches_task)) = editor
 4796                .update_in(&mut cx, |editor, _, cx| {
 4797                    if editor.selections.count() != 1 || editor.selections.line_mode {
 4798                        editor.clear_background_highlights::<SelectedTextHighlight>(cx);
 4799                        return None;
 4800                    }
 4801                    let selection = editor.selections.newest::<Point>(cx);
 4802                    if selection.is_empty() || selection.start.row != selection.end.row {
 4803                        editor.clear_background_highlights::<SelectedTextHighlight>(cx);
 4804                        return None;
 4805                    }
 4806                    let buffer = editor.buffer().read(cx).snapshot(cx);
 4807                    let query = buffer.text_for_range(selection.range()).collect::<String>();
 4808                    if query.trim().is_empty() {
 4809                        editor.clear_background_highlights::<SelectedTextHighlight>(cx);
 4810                        return None;
 4811                    }
 4812                    Some(cx.background_spawn(async move {
 4813                        let mut ranges = Vec::new();
 4814                        let selection_anchors = selection.range().to_anchors(&buffer);
 4815                        for range in [buffer.anchor_before(0)..buffer.anchor_after(buffer.len())] {
 4816                            for (search_buffer, search_range, excerpt_id) in
 4817                                buffer.range_to_buffer_ranges(range)
 4818                            {
 4819                                ranges.extend(
 4820                                    project::search::SearchQuery::text(
 4821                                        query.clone(),
 4822                                        false,
 4823                                        false,
 4824                                        false,
 4825                                        Default::default(),
 4826                                        Default::default(),
 4827                                        None,
 4828                                    )
 4829                                    .unwrap()
 4830                                    .search(search_buffer, Some(search_range.clone()))
 4831                                    .await
 4832                                    .into_iter()
 4833                                    .filter_map(
 4834                                        |match_range| {
 4835                                            let start = search_buffer.anchor_after(
 4836                                                search_range.start + match_range.start,
 4837                                            );
 4838                                            let end = search_buffer.anchor_before(
 4839                                                search_range.start + match_range.end,
 4840                                            );
 4841                                            let range = Anchor::range_in_buffer(
 4842                                                excerpt_id,
 4843                                                search_buffer.remote_id(),
 4844                                                start..end,
 4845                                            );
 4846                                            (range != selection_anchors).then_some(range)
 4847                                        },
 4848                                    ),
 4849                                );
 4850                            }
 4851                        }
 4852                        ranges
 4853                    }))
 4854                })
 4855                .log_err()
 4856            else {
 4857                return;
 4858            };
 4859            let matches = matches_task.await;
 4860            editor
 4861                .update_in(&mut cx, |editor, _, cx| {
 4862                    editor.clear_background_highlights::<SelectedTextHighlight>(cx);
 4863                    if !matches.is_empty() {
 4864                        editor.highlight_background::<SelectedTextHighlight>(
 4865                            &matches,
 4866                            |theme| theme.editor_document_highlight_bracket_background,
 4867                            cx,
 4868                        )
 4869                    }
 4870                })
 4871                .log_err();
 4872        }));
 4873    }
 4874
 4875    pub fn refresh_inline_completion(
 4876        &mut self,
 4877        debounce: bool,
 4878        user_requested: bool,
 4879        window: &mut Window,
 4880        cx: &mut Context<Self>,
 4881    ) -> Option<()> {
 4882        let provider = self.edit_prediction_provider()?;
 4883        let cursor = self.selections.newest_anchor().head();
 4884        let (buffer, cursor_buffer_position) =
 4885            self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
 4886
 4887        if !self.edit_predictions_enabled_in_buffer(&buffer, cursor_buffer_position, cx) {
 4888            self.discard_inline_completion(false, cx);
 4889            return None;
 4890        }
 4891
 4892        if !user_requested
 4893            && (!self.should_show_edit_predictions()
 4894                || !self.is_focused(window)
 4895                || buffer.read(cx).is_empty())
 4896        {
 4897            self.discard_inline_completion(false, cx);
 4898            return None;
 4899        }
 4900
 4901        self.update_visible_inline_completion(window, cx);
 4902        provider.refresh(
 4903            self.project.clone(),
 4904            buffer,
 4905            cursor_buffer_position,
 4906            debounce,
 4907            cx,
 4908        );
 4909        Some(())
 4910    }
 4911
 4912    fn show_edit_predictions_in_menu(&self) -> bool {
 4913        match self.edit_prediction_settings {
 4914            EditPredictionSettings::Disabled => false,
 4915            EditPredictionSettings::Enabled { show_in_menu, .. } => show_in_menu,
 4916        }
 4917    }
 4918
 4919    pub fn edit_predictions_enabled(&self) -> bool {
 4920        match self.edit_prediction_settings {
 4921            EditPredictionSettings::Disabled => false,
 4922            EditPredictionSettings::Enabled { .. } => true,
 4923        }
 4924    }
 4925
 4926    fn edit_prediction_requires_modifier(&self) -> bool {
 4927        match self.edit_prediction_settings {
 4928            EditPredictionSettings::Disabled => false,
 4929            EditPredictionSettings::Enabled {
 4930                preview_requires_modifier,
 4931                ..
 4932            } => preview_requires_modifier,
 4933        }
 4934    }
 4935
 4936    pub fn update_edit_prediction_settings(&mut self, cx: &mut Context<Self>) {
 4937        if self.edit_prediction_provider.is_none() {
 4938            self.edit_prediction_settings = EditPredictionSettings::Disabled;
 4939        } else {
 4940            let selection = self.selections.newest_anchor();
 4941            let cursor = selection.head();
 4942
 4943            if let Some((buffer, cursor_buffer_position)) =
 4944                self.buffer.read(cx).text_anchor_for_position(cursor, cx)
 4945            {
 4946                self.edit_prediction_settings =
 4947                    self.edit_prediction_settings_at_position(&buffer, cursor_buffer_position, cx);
 4948            }
 4949        }
 4950    }
 4951
 4952    fn edit_prediction_settings_at_position(
 4953        &self,
 4954        buffer: &Entity<Buffer>,
 4955        buffer_position: language::Anchor,
 4956        cx: &App,
 4957    ) -> EditPredictionSettings {
 4958        if self.mode != EditorMode::Full
 4959            || !self.show_inline_completions_override.unwrap_or(true)
 4960            || self.inline_completions_disabled_in_scope(buffer, buffer_position, cx)
 4961        {
 4962            return EditPredictionSettings::Disabled;
 4963        }
 4964
 4965        let buffer = buffer.read(cx);
 4966
 4967        let file = buffer.file();
 4968
 4969        if !language_settings(buffer.language().map(|l| l.name()), file, cx).show_edit_predictions {
 4970            return EditPredictionSettings::Disabled;
 4971        };
 4972
 4973        let by_provider = matches!(
 4974            self.menu_inline_completions_policy,
 4975            MenuInlineCompletionsPolicy::ByProvider
 4976        );
 4977
 4978        let show_in_menu = by_provider
 4979            && self
 4980                .edit_prediction_provider
 4981                .as_ref()
 4982                .map_or(false, |provider| {
 4983                    provider.provider.show_completions_in_menu()
 4984                });
 4985
 4986        let preview_requires_modifier =
 4987            all_language_settings(file, cx).edit_predictions_mode() == EditPredictionsMode::Subtle;
 4988
 4989        EditPredictionSettings::Enabled {
 4990            show_in_menu,
 4991            preview_requires_modifier,
 4992        }
 4993    }
 4994
 4995    fn should_show_edit_predictions(&self) -> bool {
 4996        self.snippet_stack.is_empty() && self.edit_predictions_enabled()
 4997    }
 4998
 4999    pub fn edit_prediction_preview_is_active(&self) -> bool {
 5000        matches!(
 5001            self.edit_prediction_preview,
 5002            EditPredictionPreview::Active { .. }
 5003        )
 5004    }
 5005
 5006    pub fn edit_predictions_enabled_at_cursor(&self, cx: &App) -> bool {
 5007        let cursor = self.selections.newest_anchor().head();
 5008        if let Some((buffer, cursor_position)) =
 5009            self.buffer.read(cx).text_anchor_for_position(cursor, cx)
 5010        {
 5011            self.edit_predictions_enabled_in_buffer(&buffer, cursor_position, cx)
 5012        } else {
 5013            false
 5014        }
 5015    }
 5016
 5017    fn edit_predictions_enabled_in_buffer(
 5018        &self,
 5019        buffer: &Entity<Buffer>,
 5020        buffer_position: language::Anchor,
 5021        cx: &App,
 5022    ) -> bool {
 5023        maybe!({
 5024            let provider = self.edit_prediction_provider()?;
 5025            if !provider.is_enabled(&buffer, buffer_position, cx) {
 5026                return Some(false);
 5027            }
 5028            let buffer = buffer.read(cx);
 5029            let Some(file) = buffer.file() else {
 5030                return Some(true);
 5031            };
 5032            let settings = all_language_settings(Some(file), cx);
 5033            Some(settings.edit_predictions_enabled_for_file(file, cx))
 5034        })
 5035        .unwrap_or(false)
 5036    }
 5037
 5038    fn cycle_inline_completion(
 5039        &mut self,
 5040        direction: Direction,
 5041        window: &mut Window,
 5042        cx: &mut Context<Self>,
 5043    ) -> Option<()> {
 5044        let provider = self.edit_prediction_provider()?;
 5045        let cursor = self.selections.newest_anchor().head();
 5046        let (buffer, cursor_buffer_position) =
 5047            self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
 5048        if self.inline_completions_hidden_for_vim_mode || !self.should_show_edit_predictions() {
 5049            return None;
 5050        }
 5051
 5052        provider.cycle(buffer, cursor_buffer_position, direction, cx);
 5053        self.update_visible_inline_completion(window, cx);
 5054
 5055        Some(())
 5056    }
 5057
 5058    pub fn show_inline_completion(
 5059        &mut self,
 5060        _: &ShowEditPrediction,
 5061        window: &mut Window,
 5062        cx: &mut Context<Self>,
 5063    ) {
 5064        if !self.has_active_inline_completion() {
 5065            self.refresh_inline_completion(false, true, window, cx);
 5066            return;
 5067        }
 5068
 5069        self.update_visible_inline_completion(window, cx);
 5070    }
 5071
 5072    pub fn display_cursor_names(
 5073        &mut self,
 5074        _: &DisplayCursorNames,
 5075        window: &mut Window,
 5076        cx: &mut Context<Self>,
 5077    ) {
 5078        self.show_cursor_names(window, cx);
 5079    }
 5080
 5081    fn show_cursor_names(&mut self, window: &mut Window, cx: &mut Context<Self>) {
 5082        self.show_cursor_names = true;
 5083        cx.notify();
 5084        cx.spawn_in(window, |this, mut cx| async move {
 5085            cx.background_executor().timer(CURSORS_VISIBLE_FOR).await;
 5086            this.update(&mut cx, |this, cx| {
 5087                this.show_cursor_names = false;
 5088                cx.notify()
 5089            })
 5090            .ok()
 5091        })
 5092        .detach();
 5093    }
 5094
 5095    pub fn next_edit_prediction(
 5096        &mut self,
 5097        _: &NextEditPrediction,
 5098        window: &mut Window,
 5099        cx: &mut Context<Self>,
 5100    ) {
 5101        if self.has_active_inline_completion() {
 5102            self.cycle_inline_completion(Direction::Next, window, cx);
 5103        } else {
 5104            let is_copilot_disabled = self
 5105                .refresh_inline_completion(false, true, window, cx)
 5106                .is_none();
 5107            if is_copilot_disabled {
 5108                cx.propagate();
 5109            }
 5110        }
 5111    }
 5112
 5113    pub fn previous_edit_prediction(
 5114        &mut self,
 5115        _: &PreviousEditPrediction,
 5116        window: &mut Window,
 5117        cx: &mut Context<Self>,
 5118    ) {
 5119        if self.has_active_inline_completion() {
 5120            self.cycle_inline_completion(Direction::Prev, window, cx);
 5121        } else {
 5122            let is_copilot_disabled = self
 5123                .refresh_inline_completion(false, true, window, cx)
 5124                .is_none();
 5125            if is_copilot_disabled {
 5126                cx.propagate();
 5127            }
 5128        }
 5129    }
 5130
 5131    pub fn accept_edit_prediction(
 5132        &mut self,
 5133        _: &AcceptEditPrediction,
 5134        window: &mut Window,
 5135        cx: &mut Context<Self>,
 5136    ) {
 5137        if self.show_edit_predictions_in_menu() {
 5138            self.hide_context_menu(window, cx);
 5139        }
 5140
 5141        let Some(active_inline_completion) = self.active_inline_completion.as_ref() else {
 5142            return;
 5143        };
 5144
 5145        self.report_inline_completion_event(
 5146            active_inline_completion.completion_id.clone(),
 5147            true,
 5148            cx,
 5149        );
 5150
 5151        match &active_inline_completion.completion {
 5152            InlineCompletion::Move { target, .. } => {
 5153                let target = *target;
 5154
 5155                if let Some(position_map) = &self.last_position_map {
 5156                    if position_map
 5157                        .visible_row_range
 5158                        .contains(&target.to_display_point(&position_map.snapshot).row())
 5159                        || !self.edit_prediction_requires_modifier()
 5160                    {
 5161                        self.unfold_ranges(&[target..target], true, false, cx);
 5162                        // Note that this is also done in vim's handler of the Tab action.
 5163                        self.change_selections(
 5164                            Some(Autoscroll::newest()),
 5165                            window,
 5166                            cx,
 5167                            |selections| {
 5168                                selections.select_anchor_ranges([target..target]);
 5169                            },
 5170                        );
 5171                        self.clear_row_highlights::<EditPredictionPreview>();
 5172
 5173                        self.edit_prediction_preview
 5174                            .set_previous_scroll_position(None);
 5175                    } else {
 5176                        self.edit_prediction_preview
 5177                            .set_previous_scroll_position(Some(
 5178                                position_map.snapshot.scroll_anchor,
 5179                            ));
 5180
 5181                        self.highlight_rows::<EditPredictionPreview>(
 5182                            target..target,
 5183                            cx.theme().colors().editor_highlighted_line_background,
 5184                            true,
 5185                            cx,
 5186                        );
 5187                        self.request_autoscroll(Autoscroll::fit(), cx);
 5188                    }
 5189                }
 5190            }
 5191            InlineCompletion::Edit { edits, .. } => {
 5192                if let Some(provider) = self.edit_prediction_provider() {
 5193                    provider.accept(cx);
 5194                }
 5195
 5196                let snapshot = self.buffer.read(cx).snapshot(cx);
 5197                let last_edit_end = edits.last().unwrap().0.end.bias_right(&snapshot);
 5198
 5199                self.buffer.update(cx, |buffer, cx| {
 5200                    buffer.edit(edits.iter().cloned(), None, cx)
 5201                });
 5202
 5203                self.change_selections(None, window, cx, |s| {
 5204                    s.select_anchor_ranges([last_edit_end..last_edit_end])
 5205                });
 5206
 5207                self.update_visible_inline_completion(window, cx);
 5208                if self.active_inline_completion.is_none() {
 5209                    self.refresh_inline_completion(true, true, window, cx);
 5210                }
 5211
 5212                cx.notify();
 5213            }
 5214        }
 5215
 5216        self.edit_prediction_requires_modifier_in_indent_conflict = false;
 5217    }
 5218
 5219    pub fn accept_partial_inline_completion(
 5220        &mut self,
 5221        _: &AcceptPartialEditPrediction,
 5222        window: &mut Window,
 5223        cx: &mut Context<Self>,
 5224    ) {
 5225        let Some(active_inline_completion) = self.active_inline_completion.as_ref() else {
 5226            return;
 5227        };
 5228        if self.selections.count() != 1 {
 5229            return;
 5230        }
 5231
 5232        self.report_inline_completion_event(
 5233            active_inline_completion.completion_id.clone(),
 5234            true,
 5235            cx,
 5236        );
 5237
 5238        match &active_inline_completion.completion {
 5239            InlineCompletion::Move { target, .. } => {
 5240                let target = *target;
 5241                self.change_selections(Some(Autoscroll::newest()), window, cx, |selections| {
 5242                    selections.select_anchor_ranges([target..target]);
 5243                });
 5244            }
 5245            InlineCompletion::Edit { edits, .. } => {
 5246                // Find an insertion that starts at the cursor position.
 5247                let snapshot = self.buffer.read(cx).snapshot(cx);
 5248                let cursor_offset = self.selections.newest::<usize>(cx).head();
 5249                let insertion = edits.iter().find_map(|(range, text)| {
 5250                    let range = range.to_offset(&snapshot);
 5251                    if range.is_empty() && range.start == cursor_offset {
 5252                        Some(text)
 5253                    } else {
 5254                        None
 5255                    }
 5256                });
 5257
 5258                if let Some(text) = insertion {
 5259                    let mut partial_completion = text
 5260                        .chars()
 5261                        .by_ref()
 5262                        .take_while(|c| c.is_alphabetic())
 5263                        .collect::<String>();
 5264                    if partial_completion.is_empty() {
 5265                        partial_completion = text
 5266                            .chars()
 5267                            .by_ref()
 5268                            .take_while(|c| c.is_whitespace() || !c.is_alphabetic())
 5269                            .collect::<String>();
 5270                    }
 5271
 5272                    cx.emit(EditorEvent::InputHandled {
 5273                        utf16_range_to_replace: None,
 5274                        text: partial_completion.clone().into(),
 5275                    });
 5276
 5277                    self.insert_with_autoindent_mode(&partial_completion, None, window, cx);
 5278
 5279                    self.refresh_inline_completion(true, true, window, cx);
 5280                    cx.notify();
 5281                } else {
 5282                    self.accept_edit_prediction(&Default::default(), window, cx);
 5283                }
 5284            }
 5285        }
 5286    }
 5287
 5288    fn discard_inline_completion(
 5289        &mut self,
 5290        should_report_inline_completion_event: bool,
 5291        cx: &mut Context<Self>,
 5292    ) -> bool {
 5293        if should_report_inline_completion_event {
 5294            let completion_id = self
 5295                .active_inline_completion
 5296                .as_ref()
 5297                .and_then(|active_completion| active_completion.completion_id.clone());
 5298
 5299            self.report_inline_completion_event(completion_id, false, cx);
 5300        }
 5301
 5302        if let Some(provider) = self.edit_prediction_provider() {
 5303            provider.discard(cx);
 5304        }
 5305
 5306        self.take_active_inline_completion(cx)
 5307    }
 5308
 5309    fn report_inline_completion_event(&self, id: Option<SharedString>, accepted: bool, cx: &App) {
 5310        let Some(provider) = self.edit_prediction_provider() else {
 5311            return;
 5312        };
 5313
 5314        let Some((_, buffer, _)) = self
 5315            .buffer
 5316            .read(cx)
 5317            .excerpt_containing(self.selections.newest_anchor().head(), cx)
 5318        else {
 5319            return;
 5320        };
 5321
 5322        let extension = buffer
 5323            .read(cx)
 5324            .file()
 5325            .and_then(|file| Some(file.path().extension()?.to_string_lossy().to_string()));
 5326
 5327        let event_type = match accepted {
 5328            true => "Edit Prediction Accepted",
 5329            false => "Edit Prediction Discarded",
 5330        };
 5331        telemetry::event!(
 5332            event_type,
 5333            provider = provider.name(),
 5334            prediction_id = id,
 5335            suggestion_accepted = accepted,
 5336            file_extension = extension,
 5337        );
 5338    }
 5339
 5340    pub fn has_active_inline_completion(&self) -> bool {
 5341        self.active_inline_completion.is_some()
 5342    }
 5343
 5344    fn take_active_inline_completion(&mut self, cx: &mut Context<Self>) -> bool {
 5345        let Some(active_inline_completion) = self.active_inline_completion.take() else {
 5346            return false;
 5347        };
 5348
 5349        self.splice_inlays(&active_inline_completion.inlay_ids, Default::default(), cx);
 5350        self.clear_highlights::<InlineCompletionHighlight>(cx);
 5351        self.stale_inline_completion_in_menu = Some(active_inline_completion);
 5352        true
 5353    }
 5354
 5355    /// Returns true when we're displaying the edit prediction popover below the cursor
 5356    /// like we are not previewing and the LSP autocomplete menu is visible
 5357    /// or we are in `when_holding_modifier` mode.
 5358    pub fn edit_prediction_visible_in_cursor_popover(&self, has_completion: bool) -> bool {
 5359        if self.edit_prediction_preview_is_active()
 5360            || !self.show_edit_predictions_in_menu()
 5361            || !self.edit_predictions_enabled()
 5362        {
 5363            return false;
 5364        }
 5365
 5366        if self.has_visible_completions_menu() {
 5367            return true;
 5368        }
 5369
 5370        has_completion && self.edit_prediction_requires_modifier()
 5371    }
 5372
 5373    fn handle_modifiers_changed(
 5374        &mut self,
 5375        modifiers: Modifiers,
 5376        position_map: &PositionMap,
 5377        window: &mut Window,
 5378        cx: &mut Context<Self>,
 5379    ) {
 5380        if self.show_edit_predictions_in_menu() {
 5381            self.update_edit_prediction_preview(&modifiers, window, cx);
 5382        }
 5383
 5384        self.update_selection_mode(&modifiers, position_map, window, cx);
 5385
 5386        let mouse_position = window.mouse_position();
 5387        if !position_map.text_hitbox.is_hovered(window) {
 5388            return;
 5389        }
 5390
 5391        self.update_hovered_link(
 5392            position_map.point_for_position(mouse_position),
 5393            &position_map.snapshot,
 5394            modifiers,
 5395            window,
 5396            cx,
 5397        )
 5398    }
 5399
 5400    fn update_selection_mode(
 5401        &mut self,
 5402        modifiers: &Modifiers,
 5403        position_map: &PositionMap,
 5404        window: &mut Window,
 5405        cx: &mut Context<Self>,
 5406    ) {
 5407        if modifiers != &COLUMNAR_SELECTION_MODIFIERS || self.selections.pending.is_none() {
 5408            return;
 5409        }
 5410
 5411        let mouse_position = window.mouse_position();
 5412        let point_for_position = position_map.point_for_position(mouse_position);
 5413        let position = point_for_position.previous_valid;
 5414
 5415        self.select(
 5416            SelectPhase::BeginColumnar {
 5417                position,
 5418                reset: false,
 5419                goal_column: point_for_position.exact_unclipped.column(),
 5420            },
 5421            window,
 5422            cx,
 5423        );
 5424    }
 5425
 5426    fn update_edit_prediction_preview(
 5427        &mut self,
 5428        modifiers: &Modifiers,
 5429        window: &mut Window,
 5430        cx: &mut Context<Self>,
 5431    ) {
 5432        let accept_keybind = self.accept_edit_prediction_keybind(window, cx);
 5433        let Some(accept_keystroke) = accept_keybind.keystroke() else {
 5434            return;
 5435        };
 5436
 5437        if &accept_keystroke.modifiers == modifiers && accept_keystroke.modifiers.modified() {
 5438            if matches!(
 5439                self.edit_prediction_preview,
 5440                EditPredictionPreview::Inactive { .. }
 5441            ) {
 5442                self.edit_prediction_preview = EditPredictionPreview::Active {
 5443                    previous_scroll_position: None,
 5444                    since: Instant::now(),
 5445                };
 5446
 5447                self.update_visible_inline_completion(window, cx);
 5448                cx.notify();
 5449            }
 5450        } else if let EditPredictionPreview::Active {
 5451            previous_scroll_position,
 5452            since,
 5453        } = self.edit_prediction_preview
 5454        {
 5455            if let (Some(previous_scroll_position), Some(position_map)) =
 5456                (previous_scroll_position, self.last_position_map.as_ref())
 5457            {
 5458                self.set_scroll_position(
 5459                    previous_scroll_position
 5460                        .scroll_position(&position_map.snapshot.display_snapshot),
 5461                    window,
 5462                    cx,
 5463                );
 5464            }
 5465
 5466            self.edit_prediction_preview = EditPredictionPreview::Inactive {
 5467                released_too_fast: since.elapsed() < Duration::from_millis(200),
 5468            };
 5469            self.clear_row_highlights::<EditPredictionPreview>();
 5470            self.update_visible_inline_completion(window, cx);
 5471            cx.notify();
 5472        }
 5473    }
 5474
 5475    fn update_visible_inline_completion(
 5476        &mut self,
 5477        _window: &mut Window,
 5478        cx: &mut Context<Self>,
 5479    ) -> Option<()> {
 5480        let selection = self.selections.newest_anchor();
 5481        let cursor = selection.head();
 5482        let multibuffer = self.buffer.read(cx).snapshot(cx);
 5483        let offset_selection = selection.map(|endpoint| endpoint.to_offset(&multibuffer));
 5484        let excerpt_id = cursor.excerpt_id;
 5485
 5486        let show_in_menu = self.show_edit_predictions_in_menu();
 5487        let completions_menu_has_precedence = !show_in_menu
 5488            && (self.context_menu.borrow().is_some()
 5489                || (!self.completion_tasks.is_empty() && !self.has_active_inline_completion()));
 5490
 5491        if completions_menu_has_precedence
 5492            || !offset_selection.is_empty()
 5493            || self
 5494                .active_inline_completion
 5495                .as_ref()
 5496                .map_or(false, |completion| {
 5497                    let invalidation_range = completion.invalidation_range.to_offset(&multibuffer);
 5498                    let invalidation_range = invalidation_range.start..=invalidation_range.end;
 5499                    !invalidation_range.contains(&offset_selection.head())
 5500                })
 5501        {
 5502            self.discard_inline_completion(false, cx);
 5503            return None;
 5504        }
 5505
 5506        self.take_active_inline_completion(cx);
 5507        let Some(provider) = self.edit_prediction_provider() else {
 5508            self.edit_prediction_settings = EditPredictionSettings::Disabled;
 5509            return None;
 5510        };
 5511
 5512        let (buffer, cursor_buffer_position) =
 5513            self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
 5514
 5515        self.edit_prediction_settings =
 5516            self.edit_prediction_settings_at_position(&buffer, cursor_buffer_position, cx);
 5517
 5518        self.edit_prediction_indent_conflict = multibuffer.is_line_whitespace_upto(cursor);
 5519
 5520        if self.edit_prediction_indent_conflict {
 5521            let cursor_point = cursor.to_point(&multibuffer);
 5522
 5523            let indents = multibuffer.suggested_indents(cursor_point.row..cursor_point.row + 1, cx);
 5524
 5525            if let Some((_, indent)) = indents.iter().next() {
 5526                if indent.len == cursor_point.column {
 5527                    self.edit_prediction_indent_conflict = false;
 5528                }
 5529            }
 5530        }
 5531
 5532        let inline_completion = provider.suggest(&buffer, cursor_buffer_position, cx)?;
 5533        let edits = inline_completion
 5534            .edits
 5535            .into_iter()
 5536            .flat_map(|(range, new_text)| {
 5537                let start = multibuffer.anchor_in_excerpt(excerpt_id, range.start)?;
 5538                let end = multibuffer.anchor_in_excerpt(excerpt_id, range.end)?;
 5539                Some((start..end, new_text))
 5540            })
 5541            .collect::<Vec<_>>();
 5542        if edits.is_empty() {
 5543            return None;
 5544        }
 5545
 5546        let first_edit_start = edits.first().unwrap().0.start;
 5547        let first_edit_start_point = first_edit_start.to_point(&multibuffer);
 5548        let edit_start_row = first_edit_start_point.row.saturating_sub(2);
 5549
 5550        let last_edit_end = edits.last().unwrap().0.end;
 5551        let last_edit_end_point = last_edit_end.to_point(&multibuffer);
 5552        let edit_end_row = cmp::min(multibuffer.max_point().row, last_edit_end_point.row + 2);
 5553
 5554        let cursor_row = cursor.to_point(&multibuffer).row;
 5555
 5556        let snapshot = multibuffer.buffer_for_excerpt(excerpt_id).cloned()?;
 5557
 5558        let mut inlay_ids = Vec::new();
 5559        let invalidation_row_range;
 5560        let move_invalidation_row_range = if cursor_row < edit_start_row {
 5561            Some(cursor_row..edit_end_row)
 5562        } else if cursor_row > edit_end_row {
 5563            Some(edit_start_row..cursor_row)
 5564        } else {
 5565            None
 5566        };
 5567        let is_move =
 5568            move_invalidation_row_range.is_some() || self.inline_completions_hidden_for_vim_mode;
 5569        let completion = if is_move {
 5570            invalidation_row_range =
 5571                move_invalidation_row_range.unwrap_or(edit_start_row..edit_end_row);
 5572            let target = first_edit_start;
 5573            InlineCompletion::Move { target, snapshot }
 5574        } else {
 5575            let show_completions_in_buffer = !self.edit_prediction_visible_in_cursor_popover(true)
 5576                && !self.inline_completions_hidden_for_vim_mode;
 5577
 5578            if show_completions_in_buffer {
 5579                if edits
 5580                    .iter()
 5581                    .all(|(range, _)| range.to_offset(&multibuffer).is_empty())
 5582                {
 5583                    let mut inlays = Vec::new();
 5584                    for (range, new_text) in &edits {
 5585                        let inlay = Inlay::inline_completion(
 5586                            post_inc(&mut self.next_inlay_id),
 5587                            range.start,
 5588                            new_text.as_str(),
 5589                        );
 5590                        inlay_ids.push(inlay.id);
 5591                        inlays.push(inlay);
 5592                    }
 5593
 5594                    self.splice_inlays(&[], inlays, cx);
 5595                } else {
 5596                    let background_color = cx.theme().status().deleted_background;
 5597                    self.highlight_text::<InlineCompletionHighlight>(
 5598                        edits.iter().map(|(range, _)| range.clone()).collect(),
 5599                        HighlightStyle {
 5600                            background_color: Some(background_color),
 5601                            ..Default::default()
 5602                        },
 5603                        cx,
 5604                    );
 5605                }
 5606            }
 5607
 5608            invalidation_row_range = edit_start_row..edit_end_row;
 5609
 5610            let display_mode = if all_edits_insertions_or_deletions(&edits, &multibuffer) {
 5611                if provider.show_tab_accept_marker() {
 5612                    EditDisplayMode::TabAccept
 5613                } else {
 5614                    EditDisplayMode::Inline
 5615                }
 5616            } else {
 5617                EditDisplayMode::DiffPopover
 5618            };
 5619
 5620            InlineCompletion::Edit {
 5621                edits,
 5622                edit_preview: inline_completion.edit_preview,
 5623                display_mode,
 5624                snapshot,
 5625            }
 5626        };
 5627
 5628        let invalidation_range = multibuffer
 5629            .anchor_before(Point::new(invalidation_row_range.start, 0))
 5630            ..multibuffer.anchor_after(Point::new(
 5631                invalidation_row_range.end,
 5632                multibuffer.line_len(MultiBufferRow(invalidation_row_range.end)),
 5633            ));
 5634
 5635        self.stale_inline_completion_in_menu = None;
 5636        self.active_inline_completion = Some(InlineCompletionState {
 5637            inlay_ids,
 5638            completion,
 5639            completion_id: inline_completion.id,
 5640            invalidation_range,
 5641        });
 5642
 5643        cx.notify();
 5644
 5645        Some(())
 5646    }
 5647
 5648    pub fn edit_prediction_provider(&self) -> Option<Arc<dyn InlineCompletionProviderHandle>> {
 5649        Some(self.edit_prediction_provider.as_ref()?.provider.clone())
 5650    }
 5651
 5652    fn render_code_actions_indicator(
 5653        &self,
 5654        _style: &EditorStyle,
 5655        row: DisplayRow,
 5656        is_active: bool,
 5657        cx: &mut Context<Self>,
 5658    ) -> Option<IconButton> {
 5659        if self.available_code_actions.is_some() {
 5660            Some(
 5661                IconButton::new("code_actions_indicator", ui::IconName::Bolt)
 5662                    .shape(ui::IconButtonShape::Square)
 5663                    .icon_size(IconSize::XSmall)
 5664                    .icon_color(Color::Muted)
 5665                    .toggle_state(is_active)
 5666                    .tooltip({
 5667                        let focus_handle = self.focus_handle.clone();
 5668                        move |window, cx| {
 5669                            Tooltip::for_action_in(
 5670                                "Toggle Code Actions",
 5671                                &ToggleCodeActions {
 5672                                    deployed_from_indicator: None,
 5673                                },
 5674                                &focus_handle,
 5675                                window,
 5676                                cx,
 5677                            )
 5678                        }
 5679                    })
 5680                    .on_click(cx.listener(move |editor, _e, window, cx| {
 5681                        window.focus(&editor.focus_handle(cx));
 5682                        editor.toggle_code_actions(
 5683                            &ToggleCodeActions {
 5684                                deployed_from_indicator: Some(row),
 5685                            },
 5686                            window,
 5687                            cx,
 5688                        );
 5689                    })),
 5690            )
 5691        } else {
 5692            None
 5693        }
 5694    }
 5695
 5696    fn clear_tasks(&mut self) {
 5697        self.tasks.clear()
 5698    }
 5699
 5700    fn insert_tasks(&mut self, key: (BufferId, BufferRow), value: RunnableTasks) {
 5701        if self.tasks.insert(key, value).is_some() {
 5702            // This case should hopefully be rare, but just in case...
 5703            log::error!("multiple different run targets found on a single line, only the last target will be rendered")
 5704        }
 5705    }
 5706
 5707    fn build_tasks_context(
 5708        project: &Entity<Project>,
 5709        buffer: &Entity<Buffer>,
 5710        buffer_row: u32,
 5711        tasks: &Arc<RunnableTasks>,
 5712        cx: &mut Context<Self>,
 5713    ) -> Task<Option<task::TaskContext>> {
 5714        let position = Point::new(buffer_row, tasks.column);
 5715        let range_start = buffer.read(cx).anchor_at(position, Bias::Right);
 5716        let location = Location {
 5717            buffer: buffer.clone(),
 5718            range: range_start..range_start,
 5719        };
 5720        // Fill in the environmental variables from the tree-sitter captures
 5721        let mut captured_task_variables = TaskVariables::default();
 5722        for (capture_name, value) in tasks.extra_variables.clone() {
 5723            captured_task_variables.insert(
 5724                task::VariableName::Custom(capture_name.into()),
 5725                value.clone(),
 5726            );
 5727        }
 5728        project.update(cx, |project, cx| {
 5729            project.task_store().update(cx, |task_store, cx| {
 5730                task_store.task_context_for_location(captured_task_variables, location, cx)
 5731            })
 5732        })
 5733    }
 5734
 5735    pub fn spawn_nearest_task(
 5736        &mut self,
 5737        action: &SpawnNearestTask,
 5738        window: &mut Window,
 5739        cx: &mut Context<Self>,
 5740    ) {
 5741        let Some((workspace, _)) = self.workspace.clone() else {
 5742            return;
 5743        };
 5744        let Some(project) = self.project.clone() else {
 5745            return;
 5746        };
 5747
 5748        // Try to find a closest, enclosing node using tree-sitter that has a
 5749        // task
 5750        let Some((buffer, buffer_row, tasks)) = self
 5751            .find_enclosing_node_task(cx)
 5752            // Or find the task that's closest in row-distance.
 5753            .or_else(|| self.find_closest_task(cx))
 5754        else {
 5755            return;
 5756        };
 5757
 5758        let reveal_strategy = action.reveal;
 5759        let task_context = Self::build_tasks_context(&project, &buffer, buffer_row, &tasks, cx);
 5760        cx.spawn_in(window, |_, mut cx| async move {
 5761            let context = task_context.await?;
 5762            let (task_source_kind, mut resolved_task) = tasks.resolve(&context).next()?;
 5763
 5764            let resolved = resolved_task.resolved.as_mut()?;
 5765            resolved.reveal = reveal_strategy;
 5766
 5767            workspace
 5768                .update(&mut cx, |workspace, cx| {
 5769                    workspace::tasks::schedule_resolved_task(
 5770                        workspace,
 5771                        task_source_kind,
 5772                        resolved_task,
 5773                        false,
 5774                        cx,
 5775                    );
 5776                })
 5777                .ok()
 5778        })
 5779        .detach();
 5780    }
 5781
 5782    fn find_closest_task(
 5783        &mut self,
 5784        cx: &mut Context<Self>,
 5785    ) -> Option<(Entity<Buffer>, u32, Arc<RunnableTasks>)> {
 5786        let cursor_row = self.selections.newest_adjusted(cx).head().row;
 5787
 5788        let ((buffer_id, row), tasks) = self
 5789            .tasks
 5790            .iter()
 5791            .min_by_key(|((_, row), _)| cursor_row.abs_diff(*row))?;
 5792
 5793        let buffer = self.buffer.read(cx).buffer(*buffer_id)?;
 5794        let tasks = Arc::new(tasks.to_owned());
 5795        Some((buffer, *row, tasks))
 5796    }
 5797
 5798    fn find_enclosing_node_task(
 5799        &mut self,
 5800        cx: &mut Context<Self>,
 5801    ) -> Option<(Entity<Buffer>, u32, Arc<RunnableTasks>)> {
 5802        let snapshot = self.buffer.read(cx).snapshot(cx);
 5803        let offset = self.selections.newest::<usize>(cx).head();
 5804        let excerpt = snapshot.excerpt_containing(offset..offset)?;
 5805        let buffer_id = excerpt.buffer().remote_id();
 5806
 5807        let layer = excerpt.buffer().syntax_layer_at(offset)?;
 5808        let mut cursor = layer.node().walk();
 5809
 5810        while cursor.goto_first_child_for_byte(offset).is_some() {
 5811            if cursor.node().end_byte() == offset {
 5812                cursor.goto_next_sibling();
 5813            }
 5814        }
 5815
 5816        // Ascend to the smallest ancestor that contains the range and has a task.
 5817        loop {
 5818            let node = cursor.node();
 5819            let node_range = node.byte_range();
 5820            let symbol_start_row = excerpt.buffer().offset_to_point(node.start_byte()).row;
 5821
 5822            // Check if this node contains our offset
 5823            if node_range.start <= offset && node_range.end >= offset {
 5824                // If it contains offset, check for task
 5825                if let Some(tasks) = self.tasks.get(&(buffer_id, symbol_start_row)) {
 5826                    let buffer = self.buffer.read(cx).buffer(buffer_id)?;
 5827                    return Some((buffer, symbol_start_row, Arc::new(tasks.to_owned())));
 5828                }
 5829            }
 5830
 5831            if !cursor.goto_parent() {
 5832                break;
 5833            }
 5834        }
 5835        None
 5836    }
 5837
 5838    fn render_run_indicator(
 5839        &self,
 5840        _style: &EditorStyle,
 5841        is_active: bool,
 5842        row: DisplayRow,
 5843        cx: &mut Context<Self>,
 5844    ) -> IconButton {
 5845        IconButton::new(("run_indicator", row.0 as usize), ui::IconName::Play)
 5846            .shape(ui::IconButtonShape::Square)
 5847            .icon_size(IconSize::XSmall)
 5848            .icon_color(Color::Muted)
 5849            .toggle_state(is_active)
 5850            .on_click(cx.listener(move |editor, _e, window, cx| {
 5851                window.focus(&editor.focus_handle(cx));
 5852                editor.toggle_code_actions(
 5853                    &ToggleCodeActions {
 5854                        deployed_from_indicator: Some(row),
 5855                    },
 5856                    window,
 5857                    cx,
 5858                );
 5859            }))
 5860    }
 5861
 5862    pub fn context_menu_visible(&self) -> bool {
 5863        !self.edit_prediction_preview_is_active()
 5864            && self
 5865                .context_menu
 5866                .borrow()
 5867                .as_ref()
 5868                .map_or(false, |menu| menu.visible())
 5869    }
 5870
 5871    fn context_menu_origin(&self) -> Option<ContextMenuOrigin> {
 5872        self.context_menu
 5873            .borrow()
 5874            .as_ref()
 5875            .map(|menu| menu.origin())
 5876    }
 5877
 5878    const EDIT_PREDICTION_POPOVER_PADDING_X: Pixels = Pixels(24.);
 5879    const EDIT_PREDICTION_POPOVER_PADDING_Y: Pixels = Pixels(2.);
 5880
 5881    #[allow(clippy::too_many_arguments)]
 5882    fn render_edit_prediction_popover(
 5883        &mut self,
 5884        text_bounds: &Bounds<Pixels>,
 5885        content_origin: gpui::Point<Pixels>,
 5886        editor_snapshot: &EditorSnapshot,
 5887        visible_row_range: Range<DisplayRow>,
 5888        scroll_top: f32,
 5889        scroll_bottom: f32,
 5890        line_layouts: &[LineWithInvisibles],
 5891        line_height: Pixels,
 5892        scroll_pixel_position: gpui::Point<Pixels>,
 5893        newest_selection_head: Option<DisplayPoint>,
 5894        editor_width: Pixels,
 5895        style: &EditorStyle,
 5896        window: &mut Window,
 5897        cx: &mut App,
 5898    ) -> Option<(AnyElement, gpui::Point<Pixels>)> {
 5899        let active_inline_completion = self.active_inline_completion.as_ref()?;
 5900
 5901        if self.edit_prediction_visible_in_cursor_popover(true) {
 5902            return None;
 5903        }
 5904
 5905        match &active_inline_completion.completion {
 5906            InlineCompletion::Move { target, .. } => {
 5907                let target_display_point = target.to_display_point(editor_snapshot);
 5908
 5909                if self.edit_prediction_requires_modifier() {
 5910                    if !self.edit_prediction_preview_is_active() {
 5911                        return None;
 5912                    }
 5913
 5914                    self.render_edit_prediction_modifier_jump_popover(
 5915                        text_bounds,
 5916                        content_origin,
 5917                        visible_row_range,
 5918                        line_layouts,
 5919                        line_height,
 5920                        scroll_pixel_position,
 5921                        newest_selection_head,
 5922                        target_display_point,
 5923                        window,
 5924                        cx,
 5925                    )
 5926                } else {
 5927                    self.render_edit_prediction_eager_jump_popover(
 5928                        text_bounds,
 5929                        content_origin,
 5930                        editor_snapshot,
 5931                        visible_row_range,
 5932                        scroll_top,
 5933                        scroll_bottom,
 5934                        line_height,
 5935                        scroll_pixel_position,
 5936                        target_display_point,
 5937                        editor_width,
 5938                        window,
 5939                        cx,
 5940                    )
 5941                }
 5942            }
 5943            InlineCompletion::Edit {
 5944                display_mode: EditDisplayMode::Inline,
 5945                ..
 5946            } => None,
 5947            InlineCompletion::Edit {
 5948                display_mode: EditDisplayMode::TabAccept,
 5949                edits,
 5950                ..
 5951            } => {
 5952                let range = &edits.first()?.0;
 5953                let target_display_point = range.end.to_display_point(editor_snapshot);
 5954
 5955                self.render_edit_prediction_end_of_line_popover(
 5956                    "Accept",
 5957                    editor_snapshot,
 5958                    visible_row_range,
 5959                    target_display_point,
 5960                    line_height,
 5961                    scroll_pixel_position,
 5962                    content_origin,
 5963                    editor_width,
 5964                    window,
 5965                    cx,
 5966                )
 5967            }
 5968            InlineCompletion::Edit {
 5969                edits,
 5970                edit_preview,
 5971                display_mode: EditDisplayMode::DiffPopover,
 5972                snapshot,
 5973            } => self.render_edit_prediction_diff_popover(
 5974                text_bounds,
 5975                content_origin,
 5976                editor_snapshot,
 5977                visible_row_range,
 5978                line_layouts,
 5979                line_height,
 5980                scroll_pixel_position,
 5981                newest_selection_head,
 5982                editor_width,
 5983                style,
 5984                edits,
 5985                edit_preview,
 5986                snapshot,
 5987                window,
 5988                cx,
 5989            ),
 5990        }
 5991    }
 5992
 5993    #[allow(clippy::too_many_arguments)]
 5994    fn render_edit_prediction_modifier_jump_popover(
 5995        &mut self,
 5996        text_bounds: &Bounds<Pixels>,
 5997        content_origin: gpui::Point<Pixels>,
 5998        visible_row_range: Range<DisplayRow>,
 5999        line_layouts: &[LineWithInvisibles],
 6000        line_height: Pixels,
 6001        scroll_pixel_position: gpui::Point<Pixels>,
 6002        newest_selection_head: Option<DisplayPoint>,
 6003        target_display_point: DisplayPoint,
 6004        window: &mut Window,
 6005        cx: &mut App,
 6006    ) -> Option<(AnyElement, gpui::Point<Pixels>)> {
 6007        let scrolled_content_origin =
 6008            content_origin - gpui::Point::new(scroll_pixel_position.x, Pixels(0.0));
 6009
 6010        const SCROLL_PADDING_Y: Pixels = px(12.);
 6011
 6012        if target_display_point.row() < visible_row_range.start {
 6013            return self.render_edit_prediction_scroll_popover(
 6014                |_| SCROLL_PADDING_Y,
 6015                IconName::ArrowUp,
 6016                visible_row_range,
 6017                line_layouts,
 6018                newest_selection_head,
 6019                scrolled_content_origin,
 6020                window,
 6021                cx,
 6022            );
 6023        } else if target_display_point.row() >= visible_row_range.end {
 6024            return self.render_edit_prediction_scroll_popover(
 6025                |size| text_bounds.size.height - size.height - SCROLL_PADDING_Y,
 6026                IconName::ArrowDown,
 6027                visible_row_range,
 6028                line_layouts,
 6029                newest_selection_head,
 6030                scrolled_content_origin,
 6031                window,
 6032                cx,
 6033            );
 6034        }
 6035
 6036        const POLE_WIDTH: Pixels = px(2.);
 6037
 6038        let line_layout =
 6039            line_layouts.get(target_display_point.row().minus(visible_row_range.start) as usize)?;
 6040        let target_column = target_display_point.column() as usize;
 6041
 6042        let target_x = line_layout.x_for_index(target_column);
 6043        let target_y =
 6044            (target_display_point.row().as_f32() * line_height) - scroll_pixel_position.y;
 6045
 6046        let flag_on_right = target_x < text_bounds.size.width / 2.;
 6047
 6048        let mut border_color = Self::edit_prediction_callout_popover_border_color(cx);
 6049        border_color.l += 0.001;
 6050
 6051        let mut element = v_flex()
 6052            .items_end()
 6053            .when(flag_on_right, |el| el.items_start())
 6054            .child(if flag_on_right {
 6055                self.render_edit_prediction_line_popover("Jump", None, window, cx)?
 6056                    .rounded_bl(px(0.))
 6057                    .rounded_tl(px(0.))
 6058                    .border_l_2()
 6059                    .border_color(border_color)
 6060            } else {
 6061                self.render_edit_prediction_line_popover("Jump", None, window, cx)?
 6062                    .rounded_br(px(0.))
 6063                    .rounded_tr(px(0.))
 6064                    .border_r_2()
 6065                    .border_color(border_color)
 6066            })
 6067            .child(div().w(POLE_WIDTH).bg(border_color).h(line_height))
 6068            .into_any();
 6069
 6070        let size = element.layout_as_root(AvailableSpace::min_size(), window, cx);
 6071
 6072        let mut origin = scrolled_content_origin + point(target_x, target_y)
 6073            - point(
 6074                if flag_on_right {
 6075                    POLE_WIDTH
 6076                } else {
 6077                    size.width - POLE_WIDTH
 6078                },
 6079                size.height - line_height,
 6080            );
 6081
 6082        origin.x = origin.x.max(content_origin.x);
 6083
 6084        element.prepaint_at(origin, window, cx);
 6085
 6086        Some((element, origin))
 6087    }
 6088
 6089    #[allow(clippy::too_many_arguments)]
 6090    fn render_edit_prediction_scroll_popover(
 6091        &mut self,
 6092        to_y: impl Fn(Size<Pixels>) -> Pixels,
 6093        scroll_icon: IconName,
 6094        visible_row_range: Range<DisplayRow>,
 6095        line_layouts: &[LineWithInvisibles],
 6096        newest_selection_head: Option<DisplayPoint>,
 6097        scrolled_content_origin: gpui::Point<Pixels>,
 6098        window: &mut Window,
 6099        cx: &mut App,
 6100    ) -> Option<(AnyElement, gpui::Point<Pixels>)> {
 6101        let mut element = self
 6102            .render_edit_prediction_line_popover("Scroll", Some(scroll_icon), window, cx)?
 6103            .into_any();
 6104
 6105        let size = element.layout_as_root(AvailableSpace::min_size(), window, cx);
 6106
 6107        let cursor = newest_selection_head?;
 6108        let cursor_row_layout =
 6109            line_layouts.get(cursor.row().minus(visible_row_range.start) as usize)?;
 6110        let cursor_column = cursor.column() as usize;
 6111
 6112        let cursor_character_x = cursor_row_layout.x_for_index(cursor_column);
 6113
 6114        let origin = scrolled_content_origin + point(cursor_character_x, to_y(size));
 6115
 6116        element.prepaint_at(origin, window, cx);
 6117        Some((element, origin))
 6118    }
 6119
 6120    #[allow(clippy::too_many_arguments)]
 6121    fn render_edit_prediction_eager_jump_popover(
 6122        &mut self,
 6123        text_bounds: &Bounds<Pixels>,
 6124        content_origin: gpui::Point<Pixels>,
 6125        editor_snapshot: &EditorSnapshot,
 6126        visible_row_range: Range<DisplayRow>,
 6127        scroll_top: f32,
 6128        scroll_bottom: f32,
 6129        line_height: Pixels,
 6130        scroll_pixel_position: gpui::Point<Pixels>,
 6131        target_display_point: DisplayPoint,
 6132        editor_width: Pixels,
 6133        window: &mut Window,
 6134        cx: &mut App,
 6135    ) -> Option<(AnyElement, gpui::Point<Pixels>)> {
 6136        if target_display_point.row().as_f32() < scroll_top {
 6137            let mut element = self
 6138                .render_edit_prediction_line_popover(
 6139                    "Jump to Edit",
 6140                    Some(IconName::ArrowUp),
 6141                    window,
 6142                    cx,
 6143                )?
 6144                .into_any();
 6145
 6146            let size = element.layout_as_root(AvailableSpace::min_size(), window, cx);
 6147            let offset = point(
 6148                (text_bounds.size.width - size.width) / 2.,
 6149                Self::EDIT_PREDICTION_POPOVER_PADDING_Y,
 6150            );
 6151
 6152            let origin = text_bounds.origin + offset;
 6153            element.prepaint_at(origin, window, cx);
 6154            Some((element, origin))
 6155        } else if (target_display_point.row().as_f32() + 1.) > scroll_bottom {
 6156            let mut element = self
 6157                .render_edit_prediction_line_popover(
 6158                    "Jump to Edit",
 6159                    Some(IconName::ArrowDown),
 6160                    window,
 6161                    cx,
 6162                )?
 6163                .into_any();
 6164
 6165            let size = element.layout_as_root(AvailableSpace::min_size(), window, cx);
 6166            let offset = point(
 6167                (text_bounds.size.width - size.width) / 2.,
 6168                text_bounds.size.height - size.height - Self::EDIT_PREDICTION_POPOVER_PADDING_Y,
 6169            );
 6170
 6171            let origin = text_bounds.origin + offset;
 6172            element.prepaint_at(origin, window, cx);
 6173            Some((element, origin))
 6174        } else {
 6175            self.render_edit_prediction_end_of_line_popover(
 6176                "Jump to Edit",
 6177                editor_snapshot,
 6178                visible_row_range,
 6179                target_display_point,
 6180                line_height,
 6181                scroll_pixel_position,
 6182                content_origin,
 6183                editor_width,
 6184                window,
 6185                cx,
 6186            )
 6187        }
 6188    }
 6189
 6190    #[allow(clippy::too_many_arguments)]
 6191    fn render_edit_prediction_end_of_line_popover(
 6192        self: &mut Editor,
 6193        label: &'static str,
 6194        editor_snapshot: &EditorSnapshot,
 6195        visible_row_range: Range<DisplayRow>,
 6196        target_display_point: DisplayPoint,
 6197        line_height: Pixels,
 6198        scroll_pixel_position: gpui::Point<Pixels>,
 6199        content_origin: gpui::Point<Pixels>,
 6200        editor_width: Pixels,
 6201        window: &mut Window,
 6202        cx: &mut App,
 6203    ) -> Option<(AnyElement, gpui::Point<Pixels>)> {
 6204        let target_line_end = DisplayPoint::new(
 6205            target_display_point.row(),
 6206            editor_snapshot.line_len(target_display_point.row()),
 6207        );
 6208
 6209        let mut element = self
 6210            .render_edit_prediction_line_popover(label, None, window, cx)?
 6211            .into_any();
 6212
 6213        let size = element.layout_as_root(AvailableSpace::min_size(), window, cx);
 6214
 6215        let line_origin = self.display_to_pixel_point(target_line_end, editor_snapshot, window)?;
 6216
 6217        let start_point = content_origin - point(scroll_pixel_position.x, Pixels::ZERO);
 6218        let mut origin = start_point
 6219            + line_origin
 6220            + point(Self::EDIT_PREDICTION_POPOVER_PADDING_X, Pixels::ZERO);
 6221        origin.x = origin.x.max(content_origin.x);
 6222
 6223        let max_x = content_origin.x + editor_width - size.width;
 6224
 6225        if origin.x > max_x {
 6226            let offset = line_height + Self::EDIT_PREDICTION_POPOVER_PADDING_Y;
 6227
 6228            let icon = if visible_row_range.contains(&(target_display_point.row() + 2)) {
 6229                origin.y += offset;
 6230                IconName::ArrowUp
 6231            } else {
 6232                origin.y -= offset;
 6233                IconName::ArrowDown
 6234            };
 6235
 6236            element = self
 6237                .render_edit_prediction_line_popover(label, Some(icon), window, cx)?
 6238                .into_any();
 6239
 6240            let size = element.layout_as_root(AvailableSpace::min_size(), window, cx);
 6241
 6242            origin.x = content_origin.x + editor_width - size.width - px(2.);
 6243        }
 6244
 6245        element.prepaint_at(origin, window, cx);
 6246        Some((element, origin))
 6247    }
 6248
 6249    #[allow(clippy::too_many_arguments)]
 6250    fn render_edit_prediction_diff_popover(
 6251        self: &Editor,
 6252        text_bounds: &Bounds<Pixels>,
 6253        content_origin: gpui::Point<Pixels>,
 6254        editor_snapshot: &EditorSnapshot,
 6255        visible_row_range: Range<DisplayRow>,
 6256        line_layouts: &[LineWithInvisibles],
 6257        line_height: Pixels,
 6258        scroll_pixel_position: gpui::Point<Pixels>,
 6259        newest_selection_head: Option<DisplayPoint>,
 6260        editor_width: Pixels,
 6261        style: &EditorStyle,
 6262        edits: &Vec<(Range<Anchor>, String)>,
 6263        edit_preview: &Option<language::EditPreview>,
 6264        snapshot: &language::BufferSnapshot,
 6265        window: &mut Window,
 6266        cx: &mut App,
 6267    ) -> Option<(AnyElement, gpui::Point<Pixels>)> {
 6268        let edit_start = edits
 6269            .first()
 6270            .unwrap()
 6271            .0
 6272            .start
 6273            .to_display_point(editor_snapshot);
 6274        let edit_end = edits
 6275            .last()
 6276            .unwrap()
 6277            .0
 6278            .end
 6279            .to_display_point(editor_snapshot);
 6280
 6281        let is_visible = visible_row_range.contains(&edit_start.row())
 6282            || visible_row_range.contains(&edit_end.row());
 6283        if !is_visible {
 6284            return None;
 6285        }
 6286
 6287        let highlighted_edits =
 6288            crate::inline_completion_edit_text(&snapshot, edits, edit_preview.as_ref()?, false, cx);
 6289
 6290        let styled_text = highlighted_edits.to_styled_text(&style.text);
 6291        let line_count = highlighted_edits.text.lines().count();
 6292
 6293        const BORDER_WIDTH: Pixels = px(1.);
 6294
 6295        let mut element = h_flex()
 6296            .items_start()
 6297            .child(
 6298                h_flex()
 6299                    .bg(cx.theme().colors().editor_background)
 6300                    .border(BORDER_WIDTH)
 6301                    .shadow_sm()
 6302                    .border_color(cx.theme().colors().border)
 6303                    .rounded_l_lg()
 6304                    .when(line_count > 1, |el| el.rounded_br_lg())
 6305                    .pr_1()
 6306                    .child(styled_text),
 6307            )
 6308            .child(
 6309                h_flex()
 6310                    .h(line_height + BORDER_WIDTH * px(2.))
 6311                    .px_1p5()
 6312                    .gap_1()
 6313                    // Workaround: For some reason, there's a gap if we don't do this
 6314                    .ml(-BORDER_WIDTH)
 6315                    .shadow(smallvec![gpui::BoxShadow {
 6316                        color: gpui::black().opacity(0.05),
 6317                        offset: point(px(1.), px(1.)),
 6318                        blur_radius: px(2.),
 6319                        spread_radius: px(0.),
 6320                    }])
 6321                    .bg(Editor::edit_prediction_line_popover_bg_color(cx))
 6322                    .border(BORDER_WIDTH)
 6323                    .border_color(cx.theme().colors().border)
 6324                    .rounded_r_lg()
 6325                    .children(self.render_edit_prediction_accept_keybind(window, cx)),
 6326            )
 6327            .into_any();
 6328
 6329        let longest_row =
 6330            editor_snapshot.longest_row_in_range(edit_start.row()..edit_end.row() + 1);
 6331        let longest_line_width = if visible_row_range.contains(&longest_row) {
 6332            line_layouts[(longest_row.0 - visible_row_range.start.0) as usize].width
 6333        } else {
 6334            layout_line(
 6335                longest_row,
 6336                editor_snapshot,
 6337                style,
 6338                editor_width,
 6339                |_| false,
 6340                window,
 6341                cx,
 6342            )
 6343            .width
 6344        };
 6345
 6346        let viewport_bounds =
 6347            Bounds::new(Default::default(), window.viewport_size()).extend(Edges {
 6348                right: -EditorElement::SCROLLBAR_WIDTH,
 6349                ..Default::default()
 6350            });
 6351
 6352        let x_after_longest =
 6353            text_bounds.origin.x + longest_line_width + Self::EDIT_PREDICTION_POPOVER_PADDING_X
 6354                - scroll_pixel_position.x;
 6355
 6356        let element_bounds = element.layout_as_root(AvailableSpace::min_size(), window, cx);
 6357
 6358        // Fully visible if it can be displayed within the window (allow overlapping other
 6359        // panes). However, this is only allowed if the popover starts within text_bounds.
 6360        let can_position_to_the_right = x_after_longest < text_bounds.right()
 6361            && x_after_longest + element_bounds.width < viewport_bounds.right();
 6362
 6363        let mut origin = if can_position_to_the_right {
 6364            point(
 6365                x_after_longest,
 6366                text_bounds.origin.y + edit_start.row().as_f32() * line_height
 6367                    - scroll_pixel_position.y,
 6368            )
 6369        } else {
 6370            let cursor_row = newest_selection_head.map(|head| head.row());
 6371            let above_edit = edit_start
 6372                .row()
 6373                .0
 6374                .checked_sub(line_count as u32)
 6375                .map(DisplayRow);
 6376            let below_edit = Some(edit_end.row() + 1);
 6377            let above_cursor =
 6378                cursor_row.and_then(|row| row.0.checked_sub(line_count as u32).map(DisplayRow));
 6379            let below_cursor = cursor_row.map(|cursor_row| cursor_row + 1);
 6380
 6381            // Place the edit popover adjacent to the edit if there is a location
 6382            // available that is onscreen and does not obscure the cursor. Otherwise,
 6383            // place it adjacent to the cursor.
 6384            let row_target = [above_edit, below_edit, above_cursor, below_cursor]
 6385                .into_iter()
 6386                .flatten()
 6387                .find(|&start_row| {
 6388                    let end_row = start_row + line_count as u32;
 6389                    visible_row_range.contains(&start_row)
 6390                        && visible_row_range.contains(&end_row)
 6391                        && cursor_row.map_or(true, |cursor_row| {
 6392                            !((start_row..end_row).contains(&cursor_row))
 6393                        })
 6394                })?;
 6395
 6396            content_origin
 6397                + point(
 6398                    -scroll_pixel_position.x,
 6399                    row_target.as_f32() * line_height - scroll_pixel_position.y,
 6400                )
 6401        };
 6402
 6403        origin.x -= BORDER_WIDTH;
 6404
 6405        window.defer_draw(element, origin, 1);
 6406
 6407        // Do not return an element, since it will already be drawn due to defer_draw.
 6408        None
 6409    }
 6410
 6411    fn edit_prediction_cursor_popover_height(&self) -> Pixels {
 6412        px(30.)
 6413    }
 6414
 6415    fn current_user_player_color(&self, cx: &mut App) -> PlayerColor {
 6416        if self.read_only(cx) {
 6417            cx.theme().players().read_only()
 6418        } else {
 6419            self.style.as_ref().unwrap().local_player
 6420        }
 6421    }
 6422
 6423    fn render_edit_prediction_accept_keybind(&self, window: &mut Window, cx: &App) -> Option<Div> {
 6424        let accept_binding = self.accept_edit_prediction_keybind(window, cx);
 6425        let accept_keystroke = accept_binding.keystroke()?;
 6426
 6427        let is_platform_style_mac = PlatformStyle::platform() == PlatformStyle::Mac;
 6428
 6429        let modifiers_color = if accept_keystroke.modifiers == window.modifiers() {
 6430            Color::Accent
 6431        } else {
 6432            Color::Muted
 6433        };
 6434
 6435        h_flex()
 6436            .px_0p5()
 6437            .when(is_platform_style_mac, |parent| parent.gap_0p5())
 6438            .font(theme::ThemeSettings::get_global(cx).buffer_font.clone())
 6439            .text_size(TextSize::XSmall.rems(cx))
 6440            .child(h_flex().children(ui::render_modifiers(
 6441                &accept_keystroke.modifiers,
 6442                PlatformStyle::platform(),
 6443                Some(modifiers_color),
 6444                Some(IconSize::XSmall.rems().into()),
 6445                true,
 6446            )))
 6447            .when(is_platform_style_mac, |parent| {
 6448                parent.child(accept_keystroke.key.clone())
 6449            })
 6450            .when(!is_platform_style_mac, |parent| {
 6451                parent.child(
 6452                    Key::new(
 6453                        util::capitalize(&accept_keystroke.key),
 6454                        Some(Color::Default),
 6455                    )
 6456                    .size(Some(IconSize::XSmall.rems().into())),
 6457                )
 6458            })
 6459            .into()
 6460    }
 6461
 6462    fn render_edit_prediction_line_popover(
 6463        &self,
 6464        label: impl Into<SharedString>,
 6465        icon: Option<IconName>,
 6466        window: &mut Window,
 6467        cx: &App,
 6468    ) -> Option<Div> {
 6469        let padding_right = if icon.is_some() { px(4.) } else { px(8.) };
 6470
 6471        let result = h_flex()
 6472            .py_0p5()
 6473            .pl_1()
 6474            .pr(padding_right)
 6475            .gap_1()
 6476            .rounded(px(6.))
 6477            .border_1()
 6478            .bg(Self::edit_prediction_line_popover_bg_color(cx))
 6479            .border_color(Self::edit_prediction_callout_popover_border_color(cx))
 6480            .shadow_sm()
 6481            .children(self.render_edit_prediction_accept_keybind(window, cx))
 6482            .child(Label::new(label).size(LabelSize::Small))
 6483            .when_some(icon, |element, icon| {
 6484                element.child(
 6485                    div()
 6486                        .mt(px(1.5))
 6487                        .child(Icon::new(icon).size(IconSize::Small)),
 6488                )
 6489            });
 6490
 6491        Some(result)
 6492    }
 6493
 6494    fn edit_prediction_line_popover_bg_color(cx: &App) -> Hsla {
 6495        let accent_color = cx.theme().colors().text_accent;
 6496        let editor_bg_color = cx.theme().colors().editor_background;
 6497        editor_bg_color.blend(accent_color.opacity(0.1))
 6498    }
 6499
 6500    fn edit_prediction_callout_popover_border_color(cx: &App) -> Hsla {
 6501        let accent_color = cx.theme().colors().text_accent;
 6502        let editor_bg_color = cx.theme().colors().editor_background;
 6503        editor_bg_color.blend(accent_color.opacity(0.6))
 6504    }
 6505
 6506    #[allow(clippy::too_many_arguments)]
 6507    fn render_edit_prediction_cursor_popover(
 6508        &self,
 6509        min_width: Pixels,
 6510        max_width: Pixels,
 6511        cursor_point: Point,
 6512        style: &EditorStyle,
 6513        accept_keystroke: Option<&gpui::Keystroke>,
 6514        _window: &Window,
 6515        cx: &mut Context<Editor>,
 6516    ) -> Option<AnyElement> {
 6517        let provider = self.edit_prediction_provider.as_ref()?;
 6518
 6519        if provider.provider.needs_terms_acceptance(cx) {
 6520            return Some(
 6521                h_flex()
 6522                    .min_w(min_width)
 6523                    .flex_1()
 6524                    .px_2()
 6525                    .py_1()
 6526                    .gap_3()
 6527                    .elevation_2(cx)
 6528                    .hover(|style| style.bg(cx.theme().colors().element_hover))
 6529                    .id("accept-terms")
 6530                    .cursor_pointer()
 6531                    .on_mouse_down(MouseButton::Left, |_, window, _| window.prevent_default())
 6532                    .on_click(cx.listener(|this, _event, window, cx| {
 6533                        cx.stop_propagation();
 6534                        this.report_editor_event("Edit Prediction Provider ToS Clicked", None, cx);
 6535                        window.dispatch_action(
 6536                            zed_actions::OpenZedPredictOnboarding.boxed_clone(),
 6537                            cx,
 6538                        );
 6539                    }))
 6540                    .child(
 6541                        h_flex()
 6542                            .flex_1()
 6543                            .gap_2()
 6544                            .child(Icon::new(IconName::ZedPredict))
 6545                            .child(Label::new("Accept Terms of Service"))
 6546                            .child(div().w_full())
 6547                            .child(
 6548                                Icon::new(IconName::ArrowUpRight)
 6549                                    .color(Color::Muted)
 6550                                    .size(IconSize::Small),
 6551                            )
 6552                            .into_any_element(),
 6553                    )
 6554                    .into_any(),
 6555            );
 6556        }
 6557
 6558        let is_refreshing = provider.provider.is_refreshing(cx);
 6559
 6560        fn pending_completion_container() -> Div {
 6561            h_flex()
 6562                .h_full()
 6563                .flex_1()
 6564                .gap_2()
 6565                .child(Icon::new(IconName::ZedPredict))
 6566        }
 6567
 6568        let completion = match &self.active_inline_completion {
 6569            Some(prediction) => {
 6570                if !self.has_visible_completions_menu() {
 6571                    const RADIUS: Pixels = px(6.);
 6572                    const BORDER_WIDTH: Pixels = px(1.);
 6573
 6574                    return Some(
 6575                        h_flex()
 6576                            .elevation_2(cx)
 6577                            .border(BORDER_WIDTH)
 6578                            .border_color(cx.theme().colors().border)
 6579                            .rounded(RADIUS)
 6580                            .rounded_tl(px(0.))
 6581                            .overflow_hidden()
 6582                            .child(div().px_1p5().child(match &prediction.completion {
 6583                                InlineCompletion::Move { target, snapshot } => {
 6584                                    use text::ToPoint as _;
 6585                                    if target.text_anchor.to_point(&snapshot).row > cursor_point.row
 6586                                    {
 6587                                        Icon::new(IconName::ZedPredictDown)
 6588                                    } else {
 6589                                        Icon::new(IconName::ZedPredictUp)
 6590                                    }
 6591                                }
 6592                                InlineCompletion::Edit { .. } => Icon::new(IconName::ZedPredict),
 6593                            }))
 6594                            .child(
 6595                                h_flex()
 6596                                    .gap_1()
 6597                                    .py_1()
 6598                                    .px_2()
 6599                                    .rounded_r(RADIUS - BORDER_WIDTH)
 6600                                    .border_l_1()
 6601                                    .border_color(cx.theme().colors().border)
 6602                                    .bg(Self::edit_prediction_line_popover_bg_color(cx))
 6603                                    .when(self.edit_prediction_preview.released_too_fast(), |el| {
 6604                                        el.child(
 6605                                            Label::new("Hold")
 6606                                                .size(LabelSize::Small)
 6607                                                .line_height_style(LineHeightStyle::UiLabel),
 6608                                        )
 6609                                    })
 6610                                    .child(h_flex().children(ui::render_modifiers(
 6611                                        &accept_keystroke?.modifiers,
 6612                                        PlatformStyle::platform(),
 6613                                        Some(Color::Default),
 6614                                        Some(IconSize::XSmall.rems().into()),
 6615                                        false,
 6616                                    ))),
 6617                            )
 6618                            .into_any(),
 6619                    );
 6620                }
 6621
 6622                self.render_edit_prediction_cursor_popover_preview(
 6623                    prediction,
 6624                    cursor_point,
 6625                    style,
 6626                    cx,
 6627                )?
 6628            }
 6629
 6630            None if is_refreshing => match &self.stale_inline_completion_in_menu {
 6631                Some(stale_completion) => self.render_edit_prediction_cursor_popover_preview(
 6632                    stale_completion,
 6633                    cursor_point,
 6634                    style,
 6635                    cx,
 6636                )?,
 6637
 6638                None => {
 6639                    pending_completion_container().child(Label::new("...").size(LabelSize::Small))
 6640                }
 6641            },
 6642
 6643            None => pending_completion_container().child(Label::new("No Prediction")),
 6644        };
 6645
 6646        let completion = if is_refreshing {
 6647            completion
 6648                .with_animation(
 6649                    "loading-completion",
 6650                    Animation::new(Duration::from_secs(2))
 6651                        .repeat()
 6652                        .with_easing(pulsating_between(0.4, 0.8)),
 6653                    |label, delta| label.opacity(delta),
 6654                )
 6655                .into_any_element()
 6656        } else {
 6657            completion.into_any_element()
 6658        };
 6659
 6660        let has_completion = self.active_inline_completion.is_some();
 6661
 6662        let is_platform_style_mac = PlatformStyle::platform() == PlatformStyle::Mac;
 6663        Some(
 6664            h_flex()
 6665                .min_w(min_width)
 6666                .max_w(max_width)
 6667                .flex_1()
 6668                .elevation_2(cx)
 6669                .border_color(cx.theme().colors().border)
 6670                .child(
 6671                    div()
 6672                        .flex_1()
 6673                        .py_1()
 6674                        .px_2()
 6675                        .overflow_hidden()
 6676                        .child(completion),
 6677                )
 6678                .when_some(accept_keystroke, |el, accept_keystroke| {
 6679                    if !accept_keystroke.modifiers.modified() {
 6680                        return el;
 6681                    }
 6682
 6683                    el.child(
 6684                        h_flex()
 6685                            .h_full()
 6686                            .border_l_1()
 6687                            .rounded_r_lg()
 6688                            .border_color(cx.theme().colors().border)
 6689                            .bg(Self::edit_prediction_line_popover_bg_color(cx))
 6690                            .gap_1()
 6691                            .py_1()
 6692                            .px_2()
 6693                            .child(
 6694                                h_flex()
 6695                                    .font(theme::ThemeSettings::get_global(cx).buffer_font.clone())
 6696                                    .when(is_platform_style_mac, |parent| parent.gap_1())
 6697                                    .child(h_flex().children(ui::render_modifiers(
 6698                                        &accept_keystroke.modifiers,
 6699                                        PlatformStyle::platform(),
 6700                                        Some(if !has_completion {
 6701                                            Color::Muted
 6702                                        } else {
 6703                                            Color::Default
 6704                                        }),
 6705                                        None,
 6706                                        false,
 6707                                    ))),
 6708                            )
 6709                            .child(Label::new("Preview").into_any_element())
 6710                            .opacity(if has_completion { 1.0 } else { 0.4 }),
 6711                    )
 6712                })
 6713                .into_any(),
 6714        )
 6715    }
 6716
 6717    fn render_edit_prediction_cursor_popover_preview(
 6718        &self,
 6719        completion: &InlineCompletionState,
 6720        cursor_point: Point,
 6721        style: &EditorStyle,
 6722        cx: &mut Context<Editor>,
 6723    ) -> Option<Div> {
 6724        use text::ToPoint as _;
 6725
 6726        fn render_relative_row_jump(
 6727            prefix: impl Into<String>,
 6728            current_row: u32,
 6729            target_row: u32,
 6730        ) -> Div {
 6731            let (row_diff, arrow) = if target_row < current_row {
 6732                (current_row - target_row, IconName::ArrowUp)
 6733            } else {
 6734                (target_row - current_row, IconName::ArrowDown)
 6735            };
 6736
 6737            h_flex()
 6738                .child(
 6739                    Label::new(format!("{}{}", prefix.into(), row_diff))
 6740                        .color(Color::Muted)
 6741                        .size(LabelSize::Small),
 6742                )
 6743                .child(Icon::new(arrow).color(Color::Muted).size(IconSize::Small))
 6744        }
 6745
 6746        match &completion.completion {
 6747            InlineCompletion::Move {
 6748                target, snapshot, ..
 6749            } => Some(
 6750                h_flex()
 6751                    .px_2()
 6752                    .gap_2()
 6753                    .flex_1()
 6754                    .child(
 6755                        if target.text_anchor.to_point(&snapshot).row > cursor_point.row {
 6756                            Icon::new(IconName::ZedPredictDown)
 6757                        } else {
 6758                            Icon::new(IconName::ZedPredictUp)
 6759                        },
 6760                    )
 6761                    .child(Label::new("Jump to Edit")),
 6762            ),
 6763
 6764            InlineCompletion::Edit {
 6765                edits,
 6766                edit_preview,
 6767                snapshot,
 6768                display_mode: _,
 6769            } => {
 6770                let first_edit_row = edits.first()?.0.start.text_anchor.to_point(&snapshot).row;
 6771
 6772                let (highlighted_edits, has_more_lines) = crate::inline_completion_edit_text(
 6773                    &snapshot,
 6774                    &edits,
 6775                    edit_preview.as_ref()?,
 6776                    true,
 6777                    cx,
 6778                )
 6779                .first_line_preview();
 6780
 6781                let styled_text = gpui::StyledText::new(highlighted_edits.text)
 6782                    .with_highlights(&style.text, highlighted_edits.highlights);
 6783
 6784                let preview = h_flex()
 6785                    .gap_1()
 6786                    .min_w_16()
 6787                    .child(styled_text)
 6788                    .when(has_more_lines, |parent| parent.child(""));
 6789
 6790                let left = if first_edit_row != cursor_point.row {
 6791                    render_relative_row_jump("", cursor_point.row, first_edit_row)
 6792                        .into_any_element()
 6793                } else {
 6794                    Icon::new(IconName::ZedPredict).into_any_element()
 6795                };
 6796
 6797                Some(
 6798                    h_flex()
 6799                        .h_full()
 6800                        .flex_1()
 6801                        .gap_2()
 6802                        .pr_1()
 6803                        .overflow_x_hidden()
 6804                        .font(theme::ThemeSettings::get_global(cx).buffer_font.clone())
 6805                        .child(left)
 6806                        .child(preview),
 6807                )
 6808            }
 6809        }
 6810    }
 6811
 6812    fn render_context_menu(
 6813        &self,
 6814        style: &EditorStyle,
 6815        max_height_in_lines: u32,
 6816        y_flipped: bool,
 6817        window: &mut Window,
 6818        cx: &mut Context<Editor>,
 6819    ) -> Option<AnyElement> {
 6820        let menu = self.context_menu.borrow();
 6821        let menu = menu.as_ref()?;
 6822        if !menu.visible() {
 6823            return None;
 6824        };
 6825        Some(menu.render(style, max_height_in_lines, y_flipped, window, cx))
 6826    }
 6827
 6828    fn render_context_menu_aside(
 6829        &mut self,
 6830        max_size: Size<Pixels>,
 6831        window: &mut Window,
 6832        cx: &mut Context<Editor>,
 6833    ) -> Option<AnyElement> {
 6834        self.context_menu.borrow_mut().as_mut().and_then(|menu| {
 6835            if menu.visible() {
 6836                menu.render_aside(self, max_size, window, cx)
 6837            } else {
 6838                None
 6839            }
 6840        })
 6841    }
 6842
 6843    fn hide_context_menu(
 6844        &mut self,
 6845        window: &mut Window,
 6846        cx: &mut Context<Self>,
 6847    ) -> Option<CodeContextMenu> {
 6848        cx.notify();
 6849        self.completion_tasks.clear();
 6850        let context_menu = self.context_menu.borrow_mut().take();
 6851        self.stale_inline_completion_in_menu.take();
 6852        self.update_visible_inline_completion(window, cx);
 6853        context_menu
 6854    }
 6855
 6856    fn show_snippet_choices(
 6857        &mut self,
 6858        choices: &Vec<String>,
 6859        selection: Range<Anchor>,
 6860        cx: &mut Context<Self>,
 6861    ) {
 6862        if selection.start.buffer_id.is_none() {
 6863            return;
 6864        }
 6865        let buffer_id = selection.start.buffer_id.unwrap();
 6866        let buffer = self.buffer().read(cx).buffer(buffer_id);
 6867        let id = post_inc(&mut self.next_completion_id);
 6868
 6869        if let Some(buffer) = buffer {
 6870            *self.context_menu.borrow_mut() = Some(CodeContextMenu::Completions(
 6871                CompletionsMenu::new_snippet_choices(id, true, choices, selection, buffer),
 6872            ));
 6873        }
 6874    }
 6875
 6876    pub fn insert_snippet(
 6877        &mut self,
 6878        insertion_ranges: &[Range<usize>],
 6879        snippet: Snippet,
 6880        window: &mut Window,
 6881        cx: &mut Context<Self>,
 6882    ) -> Result<()> {
 6883        struct Tabstop<T> {
 6884            is_end_tabstop: bool,
 6885            ranges: Vec<Range<T>>,
 6886            choices: Option<Vec<String>>,
 6887        }
 6888
 6889        let tabstops = self.buffer.update(cx, |buffer, cx| {
 6890            let snippet_text: Arc<str> = snippet.text.clone().into();
 6891            buffer.edit(
 6892                insertion_ranges
 6893                    .iter()
 6894                    .cloned()
 6895                    .map(|range| (range, snippet_text.clone())),
 6896                Some(AutoindentMode::EachLine),
 6897                cx,
 6898            );
 6899
 6900            let snapshot = &*buffer.read(cx);
 6901            let snippet = &snippet;
 6902            snippet
 6903                .tabstops
 6904                .iter()
 6905                .map(|tabstop| {
 6906                    let is_end_tabstop = tabstop.ranges.first().map_or(false, |tabstop| {
 6907                        tabstop.is_empty() && tabstop.start == snippet.text.len() as isize
 6908                    });
 6909                    let mut tabstop_ranges = tabstop
 6910                        .ranges
 6911                        .iter()
 6912                        .flat_map(|tabstop_range| {
 6913                            let mut delta = 0_isize;
 6914                            insertion_ranges.iter().map(move |insertion_range| {
 6915                                let insertion_start = insertion_range.start as isize + delta;
 6916                                delta +=
 6917                                    snippet.text.len() as isize - insertion_range.len() as isize;
 6918
 6919                                let start = ((insertion_start + tabstop_range.start) as usize)
 6920                                    .min(snapshot.len());
 6921                                let end = ((insertion_start + tabstop_range.end) as usize)
 6922                                    .min(snapshot.len());
 6923                                snapshot.anchor_before(start)..snapshot.anchor_after(end)
 6924                            })
 6925                        })
 6926                        .collect::<Vec<_>>();
 6927                    tabstop_ranges.sort_unstable_by(|a, b| a.start.cmp(&b.start, snapshot));
 6928
 6929                    Tabstop {
 6930                        is_end_tabstop,
 6931                        ranges: tabstop_ranges,
 6932                        choices: tabstop.choices.clone(),
 6933                    }
 6934                })
 6935                .collect::<Vec<_>>()
 6936        });
 6937        if let Some(tabstop) = tabstops.first() {
 6938            self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 6939                s.select_ranges(tabstop.ranges.iter().cloned());
 6940            });
 6941
 6942            if let Some(choices) = &tabstop.choices {
 6943                if let Some(selection) = tabstop.ranges.first() {
 6944                    self.show_snippet_choices(choices, selection.clone(), cx)
 6945                }
 6946            }
 6947
 6948            // If we're already at the last tabstop and it's at the end of the snippet,
 6949            // we're done, we don't need to keep the state around.
 6950            if !tabstop.is_end_tabstop {
 6951                let choices = tabstops
 6952                    .iter()
 6953                    .map(|tabstop| tabstop.choices.clone())
 6954                    .collect();
 6955
 6956                let ranges = tabstops
 6957                    .into_iter()
 6958                    .map(|tabstop| tabstop.ranges)
 6959                    .collect::<Vec<_>>();
 6960
 6961                self.snippet_stack.push(SnippetState {
 6962                    active_index: 0,
 6963                    ranges,
 6964                    choices,
 6965                });
 6966            }
 6967
 6968            // Check whether the just-entered snippet ends with an auto-closable bracket.
 6969            if self.autoclose_regions.is_empty() {
 6970                let snapshot = self.buffer.read(cx).snapshot(cx);
 6971                for selection in &mut self.selections.all::<Point>(cx) {
 6972                    let selection_head = selection.head();
 6973                    let Some(scope) = snapshot.language_scope_at(selection_head) else {
 6974                        continue;
 6975                    };
 6976
 6977                    let mut bracket_pair = None;
 6978                    let next_chars = snapshot.chars_at(selection_head).collect::<String>();
 6979                    let prev_chars = snapshot
 6980                        .reversed_chars_at(selection_head)
 6981                        .collect::<String>();
 6982                    for (pair, enabled) in scope.brackets() {
 6983                        if enabled
 6984                            && pair.close
 6985                            && prev_chars.starts_with(pair.start.as_str())
 6986                            && next_chars.starts_with(pair.end.as_str())
 6987                        {
 6988                            bracket_pair = Some(pair.clone());
 6989                            break;
 6990                        }
 6991                    }
 6992                    if let Some(pair) = bracket_pair {
 6993                        let start = snapshot.anchor_after(selection_head);
 6994                        let end = snapshot.anchor_after(selection_head);
 6995                        self.autoclose_regions.push(AutocloseRegion {
 6996                            selection_id: selection.id,
 6997                            range: start..end,
 6998                            pair,
 6999                        });
 7000                    }
 7001                }
 7002            }
 7003        }
 7004        Ok(())
 7005    }
 7006
 7007    pub fn move_to_next_snippet_tabstop(
 7008        &mut self,
 7009        window: &mut Window,
 7010        cx: &mut Context<Self>,
 7011    ) -> bool {
 7012        self.move_to_snippet_tabstop(Bias::Right, window, cx)
 7013    }
 7014
 7015    pub fn move_to_prev_snippet_tabstop(
 7016        &mut self,
 7017        window: &mut Window,
 7018        cx: &mut Context<Self>,
 7019    ) -> bool {
 7020        self.move_to_snippet_tabstop(Bias::Left, window, cx)
 7021    }
 7022
 7023    pub fn move_to_snippet_tabstop(
 7024        &mut self,
 7025        bias: Bias,
 7026        window: &mut Window,
 7027        cx: &mut Context<Self>,
 7028    ) -> bool {
 7029        if let Some(mut snippet) = self.snippet_stack.pop() {
 7030            match bias {
 7031                Bias::Left => {
 7032                    if snippet.active_index > 0 {
 7033                        snippet.active_index -= 1;
 7034                    } else {
 7035                        self.snippet_stack.push(snippet);
 7036                        return false;
 7037                    }
 7038                }
 7039                Bias::Right => {
 7040                    if snippet.active_index + 1 < snippet.ranges.len() {
 7041                        snippet.active_index += 1;
 7042                    } else {
 7043                        self.snippet_stack.push(snippet);
 7044                        return false;
 7045                    }
 7046                }
 7047            }
 7048            if let Some(current_ranges) = snippet.ranges.get(snippet.active_index) {
 7049                self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 7050                    s.select_anchor_ranges(current_ranges.iter().cloned())
 7051                });
 7052
 7053                if let Some(choices) = &snippet.choices[snippet.active_index] {
 7054                    if let Some(selection) = current_ranges.first() {
 7055                        self.show_snippet_choices(&choices, selection.clone(), cx);
 7056                    }
 7057                }
 7058
 7059                // If snippet state is not at the last tabstop, push it back on the stack
 7060                if snippet.active_index + 1 < snippet.ranges.len() {
 7061                    self.snippet_stack.push(snippet);
 7062                }
 7063                return true;
 7064            }
 7065        }
 7066
 7067        false
 7068    }
 7069
 7070    pub fn clear(&mut self, window: &mut Window, cx: &mut Context<Self>) {
 7071        self.transact(window, cx, |this, window, cx| {
 7072            this.select_all(&SelectAll, window, cx);
 7073            this.insert("", window, cx);
 7074        });
 7075    }
 7076
 7077    pub fn backspace(&mut self, _: &Backspace, window: &mut Window, cx: &mut Context<Self>) {
 7078        self.transact(window, cx, |this, window, cx| {
 7079            this.select_autoclose_pair(window, cx);
 7080            let mut linked_ranges = HashMap::<_, Vec<_>>::default();
 7081            if !this.linked_edit_ranges.is_empty() {
 7082                let selections = this.selections.all::<MultiBufferPoint>(cx);
 7083                let snapshot = this.buffer.read(cx).snapshot(cx);
 7084
 7085                for selection in selections.iter() {
 7086                    let selection_start = snapshot.anchor_before(selection.start).text_anchor;
 7087                    let selection_end = snapshot.anchor_after(selection.end).text_anchor;
 7088                    if selection_start.buffer_id != selection_end.buffer_id {
 7089                        continue;
 7090                    }
 7091                    if let Some(ranges) =
 7092                        this.linked_editing_ranges_for(selection_start..selection_end, cx)
 7093                    {
 7094                        for (buffer, entries) in ranges {
 7095                            linked_ranges.entry(buffer).or_default().extend(entries);
 7096                        }
 7097                    }
 7098                }
 7099            }
 7100
 7101            let mut selections = this.selections.all::<MultiBufferPoint>(cx);
 7102            if !this.selections.line_mode {
 7103                let display_map = this.display_map.update(cx, |map, cx| map.snapshot(cx));
 7104                for selection in &mut selections {
 7105                    if selection.is_empty() {
 7106                        let old_head = selection.head();
 7107                        let mut new_head =
 7108                            movement::left(&display_map, old_head.to_display_point(&display_map))
 7109                                .to_point(&display_map);
 7110                        if let Some((buffer, line_buffer_range)) = display_map
 7111                            .buffer_snapshot
 7112                            .buffer_line_for_row(MultiBufferRow(old_head.row))
 7113                        {
 7114                            let indent_size =
 7115                                buffer.indent_size_for_line(line_buffer_range.start.row);
 7116                            let indent_len = match indent_size.kind {
 7117                                IndentKind::Space => {
 7118                                    buffer.settings_at(line_buffer_range.start, cx).tab_size
 7119                                }
 7120                                IndentKind::Tab => NonZeroU32::new(1).unwrap(),
 7121                            };
 7122                            if old_head.column <= indent_size.len && old_head.column > 0 {
 7123                                let indent_len = indent_len.get();
 7124                                new_head = cmp::min(
 7125                                    new_head,
 7126                                    MultiBufferPoint::new(
 7127                                        old_head.row,
 7128                                        ((old_head.column - 1) / indent_len) * indent_len,
 7129                                    ),
 7130                                );
 7131                            }
 7132                        }
 7133
 7134                        selection.set_head(new_head, SelectionGoal::None);
 7135                    }
 7136                }
 7137            }
 7138
 7139            this.signature_help_state.set_backspace_pressed(true);
 7140            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 7141                s.select(selections)
 7142            });
 7143            this.insert("", window, cx);
 7144            let empty_str: Arc<str> = Arc::from("");
 7145            for (buffer, edits) in linked_ranges {
 7146                let snapshot = buffer.read(cx).snapshot();
 7147                use text::ToPoint as TP;
 7148
 7149                let edits = edits
 7150                    .into_iter()
 7151                    .map(|range| {
 7152                        let end_point = TP::to_point(&range.end, &snapshot);
 7153                        let mut start_point = TP::to_point(&range.start, &snapshot);
 7154
 7155                        if end_point == start_point {
 7156                            let offset = text::ToOffset::to_offset(&range.start, &snapshot)
 7157                                .saturating_sub(1);
 7158                            start_point =
 7159                                snapshot.clip_point(TP::to_point(&offset, &snapshot), Bias::Left);
 7160                        };
 7161
 7162                        (start_point..end_point, empty_str.clone())
 7163                    })
 7164                    .sorted_by_key(|(range, _)| range.start)
 7165                    .collect::<Vec<_>>();
 7166                buffer.update(cx, |this, cx| {
 7167                    this.edit(edits, None, cx);
 7168                })
 7169            }
 7170            this.refresh_inline_completion(true, false, window, cx);
 7171            linked_editing_ranges::refresh_linked_ranges(this, window, cx);
 7172        });
 7173    }
 7174
 7175    pub fn delete(&mut self, _: &Delete, window: &mut Window, cx: &mut Context<Self>) {
 7176        self.transact(window, cx, |this, window, cx| {
 7177            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 7178                let line_mode = s.line_mode;
 7179                s.move_with(|map, selection| {
 7180                    if selection.is_empty() && !line_mode {
 7181                        let cursor = movement::right(map, selection.head());
 7182                        selection.end = cursor;
 7183                        selection.reversed = true;
 7184                        selection.goal = SelectionGoal::None;
 7185                    }
 7186                })
 7187            });
 7188            this.insert("", window, cx);
 7189            this.refresh_inline_completion(true, false, window, cx);
 7190        });
 7191    }
 7192
 7193    pub fn tab_prev(&mut self, _: &TabPrev, window: &mut Window, cx: &mut Context<Self>) {
 7194        if self.move_to_prev_snippet_tabstop(window, cx) {
 7195            return;
 7196        }
 7197
 7198        self.outdent(&Outdent, window, cx);
 7199    }
 7200
 7201    pub fn tab(&mut self, _: &Tab, window: &mut Window, cx: &mut Context<Self>) {
 7202        if self.move_to_next_snippet_tabstop(window, cx) || self.read_only(cx) {
 7203            return;
 7204        }
 7205
 7206        let mut selections = self.selections.all_adjusted(cx);
 7207        let buffer = self.buffer.read(cx);
 7208        let snapshot = buffer.snapshot(cx);
 7209        let rows_iter = selections.iter().map(|s| s.head().row);
 7210        let suggested_indents = snapshot.suggested_indents(rows_iter, cx);
 7211
 7212        let mut edits = Vec::new();
 7213        let mut prev_edited_row = 0;
 7214        let mut row_delta = 0;
 7215        for selection in &mut selections {
 7216            if selection.start.row != prev_edited_row {
 7217                row_delta = 0;
 7218            }
 7219            prev_edited_row = selection.end.row;
 7220
 7221            // If the selection is non-empty, then increase the indentation of the selected lines.
 7222            if !selection.is_empty() {
 7223                row_delta =
 7224                    Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
 7225                continue;
 7226            }
 7227
 7228            // If the selection is empty and the cursor is in the leading whitespace before the
 7229            // suggested indentation, then auto-indent the line.
 7230            let cursor = selection.head();
 7231            let current_indent = snapshot.indent_size_for_line(MultiBufferRow(cursor.row));
 7232            if let Some(suggested_indent) =
 7233                suggested_indents.get(&MultiBufferRow(cursor.row)).copied()
 7234            {
 7235                if cursor.column < suggested_indent.len
 7236                    && cursor.column <= current_indent.len
 7237                    && current_indent.len <= suggested_indent.len
 7238                {
 7239                    selection.start = Point::new(cursor.row, suggested_indent.len);
 7240                    selection.end = selection.start;
 7241                    if row_delta == 0 {
 7242                        edits.extend(Buffer::edit_for_indent_size_adjustment(
 7243                            cursor.row,
 7244                            current_indent,
 7245                            suggested_indent,
 7246                        ));
 7247                        row_delta = suggested_indent.len - current_indent.len;
 7248                    }
 7249                    continue;
 7250                }
 7251            }
 7252
 7253            // Otherwise, insert a hard or soft tab.
 7254            let settings = buffer.settings_at(cursor, cx);
 7255            let tab_size = if settings.hard_tabs {
 7256                IndentSize::tab()
 7257            } else {
 7258                let tab_size = settings.tab_size.get();
 7259                let char_column = snapshot
 7260                    .text_for_range(Point::new(cursor.row, 0)..cursor)
 7261                    .flat_map(str::chars)
 7262                    .count()
 7263                    + row_delta as usize;
 7264                let chars_to_next_tab_stop = tab_size - (char_column as u32 % tab_size);
 7265                IndentSize::spaces(chars_to_next_tab_stop)
 7266            };
 7267            selection.start = Point::new(cursor.row, cursor.column + row_delta + tab_size.len);
 7268            selection.end = selection.start;
 7269            edits.push((cursor..cursor, tab_size.chars().collect::<String>()));
 7270            row_delta += tab_size.len;
 7271        }
 7272
 7273        self.transact(window, cx, |this, window, cx| {
 7274            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
 7275            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 7276                s.select(selections)
 7277            });
 7278            this.refresh_inline_completion(true, false, window, cx);
 7279        });
 7280    }
 7281
 7282    pub fn indent(&mut self, _: &Indent, window: &mut Window, cx: &mut Context<Self>) {
 7283        if self.read_only(cx) {
 7284            return;
 7285        }
 7286        let mut selections = self.selections.all::<Point>(cx);
 7287        let mut prev_edited_row = 0;
 7288        let mut row_delta = 0;
 7289        let mut edits = Vec::new();
 7290        let buffer = self.buffer.read(cx);
 7291        let snapshot = buffer.snapshot(cx);
 7292        for selection in &mut selections {
 7293            if selection.start.row != prev_edited_row {
 7294                row_delta = 0;
 7295            }
 7296            prev_edited_row = selection.end.row;
 7297
 7298            row_delta =
 7299                Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
 7300        }
 7301
 7302        self.transact(window, cx, |this, window, cx| {
 7303            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
 7304            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 7305                s.select(selections)
 7306            });
 7307        });
 7308    }
 7309
 7310    fn indent_selection(
 7311        buffer: &MultiBuffer,
 7312        snapshot: &MultiBufferSnapshot,
 7313        selection: &mut Selection<Point>,
 7314        edits: &mut Vec<(Range<Point>, String)>,
 7315        delta_for_start_row: u32,
 7316        cx: &App,
 7317    ) -> u32 {
 7318        let settings = buffer.settings_at(selection.start, cx);
 7319        let tab_size = settings.tab_size.get();
 7320        let indent_kind = if settings.hard_tabs {
 7321            IndentKind::Tab
 7322        } else {
 7323            IndentKind::Space
 7324        };
 7325        let mut start_row = selection.start.row;
 7326        let mut end_row = selection.end.row + 1;
 7327
 7328        // If a selection ends at the beginning of a line, don't indent
 7329        // that last line.
 7330        if selection.end.column == 0 && selection.end.row > selection.start.row {
 7331            end_row -= 1;
 7332        }
 7333
 7334        // Avoid re-indenting a row that has already been indented by a
 7335        // previous selection, but still update this selection's column
 7336        // to reflect that indentation.
 7337        if delta_for_start_row > 0 {
 7338            start_row += 1;
 7339            selection.start.column += delta_for_start_row;
 7340            if selection.end.row == selection.start.row {
 7341                selection.end.column += delta_for_start_row;
 7342            }
 7343        }
 7344
 7345        let mut delta_for_end_row = 0;
 7346        let has_multiple_rows = start_row + 1 != end_row;
 7347        for row in start_row..end_row {
 7348            let current_indent = snapshot.indent_size_for_line(MultiBufferRow(row));
 7349            let indent_delta = match (current_indent.kind, indent_kind) {
 7350                (IndentKind::Space, IndentKind::Space) => {
 7351                    let columns_to_next_tab_stop = tab_size - (current_indent.len % tab_size);
 7352                    IndentSize::spaces(columns_to_next_tab_stop)
 7353                }
 7354                (IndentKind::Tab, IndentKind::Space) => IndentSize::spaces(tab_size),
 7355                (_, IndentKind::Tab) => IndentSize::tab(),
 7356            };
 7357
 7358            let start = if has_multiple_rows || current_indent.len < selection.start.column {
 7359                0
 7360            } else {
 7361                selection.start.column
 7362            };
 7363            let row_start = Point::new(row, start);
 7364            edits.push((
 7365                row_start..row_start,
 7366                indent_delta.chars().collect::<String>(),
 7367            ));
 7368
 7369            // Update this selection's endpoints to reflect the indentation.
 7370            if row == selection.start.row {
 7371                selection.start.column += indent_delta.len;
 7372            }
 7373            if row == selection.end.row {
 7374                selection.end.column += indent_delta.len;
 7375                delta_for_end_row = indent_delta.len;
 7376            }
 7377        }
 7378
 7379        if selection.start.row == selection.end.row {
 7380            delta_for_start_row + delta_for_end_row
 7381        } else {
 7382            delta_for_end_row
 7383        }
 7384    }
 7385
 7386    pub fn outdent(&mut self, _: &Outdent, window: &mut Window, cx: &mut Context<Self>) {
 7387        if self.read_only(cx) {
 7388            return;
 7389        }
 7390        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 7391        let selections = self.selections.all::<Point>(cx);
 7392        let mut deletion_ranges = Vec::new();
 7393        let mut last_outdent = None;
 7394        {
 7395            let buffer = self.buffer.read(cx);
 7396            let snapshot = buffer.snapshot(cx);
 7397            for selection in &selections {
 7398                let settings = buffer.settings_at(selection.start, cx);
 7399                let tab_size = settings.tab_size.get();
 7400                let mut rows = selection.spanned_rows(false, &display_map);
 7401
 7402                // Avoid re-outdenting a row that has already been outdented by a
 7403                // previous selection.
 7404                if let Some(last_row) = last_outdent {
 7405                    if last_row == rows.start {
 7406                        rows.start = rows.start.next_row();
 7407                    }
 7408                }
 7409                let has_multiple_rows = rows.len() > 1;
 7410                for row in rows.iter_rows() {
 7411                    let indent_size = snapshot.indent_size_for_line(row);
 7412                    if indent_size.len > 0 {
 7413                        let deletion_len = match indent_size.kind {
 7414                            IndentKind::Space => {
 7415                                let columns_to_prev_tab_stop = indent_size.len % tab_size;
 7416                                if columns_to_prev_tab_stop == 0 {
 7417                                    tab_size
 7418                                } else {
 7419                                    columns_to_prev_tab_stop
 7420                                }
 7421                            }
 7422                            IndentKind::Tab => 1,
 7423                        };
 7424                        let start = if has_multiple_rows
 7425                            || deletion_len > selection.start.column
 7426                            || indent_size.len < selection.start.column
 7427                        {
 7428                            0
 7429                        } else {
 7430                            selection.start.column - deletion_len
 7431                        };
 7432                        deletion_ranges.push(
 7433                            Point::new(row.0, start)..Point::new(row.0, start + deletion_len),
 7434                        );
 7435                        last_outdent = Some(row);
 7436                    }
 7437                }
 7438            }
 7439        }
 7440
 7441        self.transact(window, cx, |this, window, cx| {
 7442            this.buffer.update(cx, |buffer, cx| {
 7443                let empty_str: Arc<str> = Arc::default();
 7444                buffer.edit(
 7445                    deletion_ranges
 7446                        .into_iter()
 7447                        .map(|range| (range, empty_str.clone())),
 7448                    None,
 7449                    cx,
 7450                );
 7451            });
 7452            let selections = this.selections.all::<usize>(cx);
 7453            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 7454                s.select(selections)
 7455            });
 7456        });
 7457    }
 7458
 7459    pub fn autoindent(&mut self, _: &AutoIndent, window: &mut Window, cx: &mut Context<Self>) {
 7460        if self.read_only(cx) {
 7461            return;
 7462        }
 7463        let selections = self
 7464            .selections
 7465            .all::<usize>(cx)
 7466            .into_iter()
 7467            .map(|s| s.range());
 7468
 7469        self.transact(window, cx, |this, window, cx| {
 7470            this.buffer.update(cx, |buffer, cx| {
 7471                buffer.autoindent_ranges(selections, cx);
 7472            });
 7473            let selections = this.selections.all::<usize>(cx);
 7474            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 7475                s.select(selections)
 7476            });
 7477        });
 7478    }
 7479
 7480    pub fn delete_line(&mut self, _: &DeleteLine, window: &mut Window, cx: &mut Context<Self>) {
 7481        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 7482        let selections = self.selections.all::<Point>(cx);
 7483
 7484        let mut new_cursors = Vec::new();
 7485        let mut edit_ranges = Vec::new();
 7486        let mut selections = selections.iter().peekable();
 7487        while let Some(selection) = selections.next() {
 7488            let mut rows = selection.spanned_rows(false, &display_map);
 7489            let goal_display_column = selection.head().to_display_point(&display_map).column();
 7490
 7491            // Accumulate contiguous regions of rows that we want to delete.
 7492            while let Some(next_selection) = selections.peek() {
 7493                let next_rows = next_selection.spanned_rows(false, &display_map);
 7494                if next_rows.start <= rows.end {
 7495                    rows.end = next_rows.end;
 7496                    selections.next().unwrap();
 7497                } else {
 7498                    break;
 7499                }
 7500            }
 7501
 7502            let buffer = &display_map.buffer_snapshot;
 7503            let mut edit_start = Point::new(rows.start.0, 0).to_offset(buffer);
 7504            let edit_end;
 7505            let cursor_buffer_row;
 7506            if buffer.max_point().row >= rows.end.0 {
 7507                // If there's a line after the range, delete the \n from the end of the row range
 7508                // and position the cursor on the next line.
 7509                edit_end = Point::new(rows.end.0, 0).to_offset(buffer);
 7510                cursor_buffer_row = rows.end;
 7511            } else {
 7512                // If there isn't a line after the range, delete the \n from the line before the
 7513                // start of the row range and position the cursor there.
 7514                edit_start = edit_start.saturating_sub(1);
 7515                edit_end = buffer.len();
 7516                cursor_buffer_row = rows.start.previous_row();
 7517            }
 7518
 7519            let mut cursor = Point::new(cursor_buffer_row.0, 0).to_display_point(&display_map);
 7520            *cursor.column_mut() =
 7521                cmp::min(goal_display_column, display_map.line_len(cursor.row()));
 7522
 7523            new_cursors.push((
 7524                selection.id,
 7525                buffer.anchor_after(cursor.to_point(&display_map)),
 7526            ));
 7527            edit_ranges.push(edit_start..edit_end);
 7528        }
 7529
 7530        self.transact(window, cx, |this, window, cx| {
 7531            let buffer = this.buffer.update(cx, |buffer, cx| {
 7532                let empty_str: Arc<str> = Arc::default();
 7533                buffer.edit(
 7534                    edit_ranges
 7535                        .into_iter()
 7536                        .map(|range| (range, empty_str.clone())),
 7537                    None,
 7538                    cx,
 7539                );
 7540                buffer.snapshot(cx)
 7541            });
 7542            let new_selections = new_cursors
 7543                .into_iter()
 7544                .map(|(id, cursor)| {
 7545                    let cursor = cursor.to_point(&buffer);
 7546                    Selection {
 7547                        id,
 7548                        start: cursor,
 7549                        end: cursor,
 7550                        reversed: false,
 7551                        goal: SelectionGoal::None,
 7552                    }
 7553                })
 7554                .collect();
 7555
 7556            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 7557                s.select(new_selections);
 7558            });
 7559        });
 7560    }
 7561
 7562    pub fn join_lines_impl(
 7563        &mut self,
 7564        insert_whitespace: bool,
 7565        window: &mut Window,
 7566        cx: &mut Context<Self>,
 7567    ) {
 7568        if self.read_only(cx) {
 7569            return;
 7570        }
 7571        let mut row_ranges = Vec::<Range<MultiBufferRow>>::new();
 7572        for selection in self.selections.all::<Point>(cx) {
 7573            let start = MultiBufferRow(selection.start.row);
 7574            // Treat single line selections as if they include the next line. Otherwise this action
 7575            // would do nothing for single line selections individual cursors.
 7576            let end = if selection.start.row == selection.end.row {
 7577                MultiBufferRow(selection.start.row + 1)
 7578            } else {
 7579                MultiBufferRow(selection.end.row)
 7580            };
 7581
 7582            if let Some(last_row_range) = row_ranges.last_mut() {
 7583                if start <= last_row_range.end {
 7584                    last_row_range.end = end;
 7585                    continue;
 7586                }
 7587            }
 7588            row_ranges.push(start..end);
 7589        }
 7590
 7591        let snapshot = self.buffer.read(cx).snapshot(cx);
 7592        let mut cursor_positions = Vec::new();
 7593        for row_range in &row_ranges {
 7594            let anchor = snapshot.anchor_before(Point::new(
 7595                row_range.end.previous_row().0,
 7596                snapshot.line_len(row_range.end.previous_row()),
 7597            ));
 7598            cursor_positions.push(anchor..anchor);
 7599        }
 7600
 7601        self.transact(window, cx, |this, window, cx| {
 7602            for row_range in row_ranges.into_iter().rev() {
 7603                for row in row_range.iter_rows().rev() {
 7604                    let end_of_line = Point::new(row.0, snapshot.line_len(row));
 7605                    let next_line_row = row.next_row();
 7606                    let indent = snapshot.indent_size_for_line(next_line_row);
 7607                    let start_of_next_line = Point::new(next_line_row.0, indent.len);
 7608
 7609                    let replace =
 7610                        if snapshot.line_len(next_line_row) > indent.len && insert_whitespace {
 7611                            " "
 7612                        } else {
 7613                            ""
 7614                        };
 7615
 7616                    this.buffer.update(cx, |buffer, cx| {
 7617                        buffer.edit([(end_of_line..start_of_next_line, replace)], None, cx)
 7618                    });
 7619                }
 7620            }
 7621
 7622            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 7623                s.select_anchor_ranges(cursor_positions)
 7624            });
 7625        });
 7626    }
 7627
 7628    pub fn join_lines(&mut self, _: &JoinLines, window: &mut Window, cx: &mut Context<Self>) {
 7629        self.join_lines_impl(true, window, cx);
 7630    }
 7631
 7632    pub fn sort_lines_case_sensitive(
 7633        &mut self,
 7634        _: &SortLinesCaseSensitive,
 7635        window: &mut Window,
 7636        cx: &mut Context<Self>,
 7637    ) {
 7638        self.manipulate_lines(window, cx, |lines| lines.sort())
 7639    }
 7640
 7641    pub fn sort_lines_case_insensitive(
 7642        &mut self,
 7643        _: &SortLinesCaseInsensitive,
 7644        window: &mut Window,
 7645        cx: &mut Context<Self>,
 7646    ) {
 7647        self.manipulate_lines(window, cx, |lines| {
 7648            lines.sort_by_key(|line| line.to_lowercase())
 7649        })
 7650    }
 7651
 7652    pub fn unique_lines_case_insensitive(
 7653        &mut self,
 7654        _: &UniqueLinesCaseInsensitive,
 7655        window: &mut Window,
 7656        cx: &mut Context<Self>,
 7657    ) {
 7658        self.manipulate_lines(window, cx, |lines| {
 7659            let mut seen = HashSet::default();
 7660            lines.retain(|line| seen.insert(line.to_lowercase()));
 7661        })
 7662    }
 7663
 7664    pub fn unique_lines_case_sensitive(
 7665        &mut self,
 7666        _: &UniqueLinesCaseSensitive,
 7667        window: &mut Window,
 7668        cx: &mut Context<Self>,
 7669    ) {
 7670        self.manipulate_lines(window, cx, |lines| {
 7671            let mut seen = HashSet::default();
 7672            lines.retain(|line| seen.insert(*line));
 7673        })
 7674    }
 7675
 7676    pub fn reload_file(&mut self, _: &ReloadFile, window: &mut Window, cx: &mut Context<Self>) {
 7677        let Some(project) = self.project.clone() else {
 7678            return;
 7679        };
 7680        self.reload(project, window, cx)
 7681            .detach_and_notify_err(window, cx);
 7682    }
 7683
 7684    pub fn restore_file(
 7685        &mut self,
 7686        _: &::git::RestoreFile,
 7687        window: &mut Window,
 7688        cx: &mut Context<Self>,
 7689    ) {
 7690        let mut buffer_ids = HashSet::default();
 7691        let snapshot = self.buffer().read(cx).snapshot(cx);
 7692        for selection in self.selections.all::<usize>(cx) {
 7693            buffer_ids.extend(snapshot.buffer_ids_for_range(selection.range()))
 7694        }
 7695
 7696        let buffer = self.buffer().read(cx);
 7697        let ranges = buffer_ids
 7698            .into_iter()
 7699            .flat_map(|buffer_id| buffer.excerpt_ranges_for_buffer(buffer_id, cx))
 7700            .collect::<Vec<_>>();
 7701
 7702        self.restore_hunks_in_ranges(ranges, window, cx);
 7703    }
 7704
 7705    pub fn git_restore(&mut self, _: &Restore, window: &mut Window, cx: &mut Context<Self>) {
 7706        let selections = self
 7707            .selections
 7708            .all(cx)
 7709            .into_iter()
 7710            .map(|s| s.range())
 7711            .collect();
 7712        self.restore_hunks_in_ranges(selections, window, cx);
 7713    }
 7714
 7715    fn restore_hunks_in_ranges(
 7716        &mut self,
 7717        ranges: Vec<Range<Point>>,
 7718        window: &mut Window,
 7719        cx: &mut Context<Editor>,
 7720    ) {
 7721        let mut revert_changes = HashMap::default();
 7722        let snapshot = self.buffer.read(cx).snapshot(cx);
 7723        let Some(project) = &self.project else {
 7724            return;
 7725        };
 7726
 7727        let chunk_by = self
 7728            .snapshot(window, cx)
 7729            .hunks_for_ranges(ranges.into_iter())
 7730            .into_iter()
 7731            .chunk_by(|hunk| hunk.buffer_id);
 7732        for (buffer_id, hunks) in &chunk_by {
 7733            let hunks = hunks.collect::<Vec<_>>();
 7734            for hunk in &hunks {
 7735                self.prepare_restore_change(&mut revert_changes, hunk, cx);
 7736            }
 7737            Self::do_stage_or_unstage(
 7738                project,
 7739                false,
 7740                buffer_id,
 7741                hunks.into_iter(),
 7742                &snapshot,
 7743                window,
 7744                cx,
 7745            );
 7746        }
 7747        drop(chunk_by);
 7748        if !revert_changes.is_empty() {
 7749            self.transact(window, cx, |editor, window, cx| {
 7750                editor.restore(revert_changes, window, cx);
 7751            });
 7752        }
 7753    }
 7754
 7755    pub fn open_active_item_in_terminal(
 7756        &mut self,
 7757        _: &OpenInTerminal,
 7758        window: &mut Window,
 7759        cx: &mut Context<Self>,
 7760    ) {
 7761        if let Some(working_directory) = self.active_excerpt(cx).and_then(|(_, buffer, _)| {
 7762            let project_path = buffer.read(cx).project_path(cx)?;
 7763            let project = self.project.as_ref()?.read(cx);
 7764            let entry = project.entry_for_path(&project_path, cx)?;
 7765            let parent = match &entry.canonical_path {
 7766                Some(canonical_path) => canonical_path.to_path_buf(),
 7767                None => project.absolute_path(&project_path, cx)?,
 7768            }
 7769            .parent()?
 7770            .to_path_buf();
 7771            Some(parent)
 7772        }) {
 7773            window.dispatch_action(OpenTerminal { working_directory }.boxed_clone(), cx);
 7774        }
 7775    }
 7776
 7777    pub fn prepare_restore_change(
 7778        &self,
 7779        revert_changes: &mut HashMap<BufferId, Vec<(Range<text::Anchor>, Rope)>>,
 7780        hunk: &MultiBufferDiffHunk,
 7781        cx: &mut App,
 7782    ) -> Option<()> {
 7783        let buffer = self.buffer.read(cx);
 7784        let diff = buffer.diff_for(hunk.buffer_id)?;
 7785        let buffer = buffer.buffer(hunk.buffer_id)?;
 7786        let buffer = buffer.read(cx);
 7787        let original_text = diff
 7788            .read(cx)
 7789            .base_text()
 7790            .as_ref()?
 7791            .as_rope()
 7792            .slice(hunk.diff_base_byte_range.clone());
 7793        let buffer_snapshot = buffer.snapshot();
 7794        let buffer_revert_changes = revert_changes.entry(buffer.remote_id()).or_default();
 7795        if let Err(i) = buffer_revert_changes.binary_search_by(|probe| {
 7796            probe
 7797                .0
 7798                .start
 7799                .cmp(&hunk.buffer_range.start, &buffer_snapshot)
 7800                .then(probe.0.end.cmp(&hunk.buffer_range.end, &buffer_snapshot))
 7801        }) {
 7802            buffer_revert_changes.insert(i, (hunk.buffer_range.clone(), original_text));
 7803            Some(())
 7804        } else {
 7805            None
 7806        }
 7807    }
 7808
 7809    pub fn reverse_lines(&mut self, _: &ReverseLines, window: &mut Window, cx: &mut Context<Self>) {
 7810        self.manipulate_lines(window, cx, |lines| lines.reverse())
 7811    }
 7812
 7813    pub fn shuffle_lines(&mut self, _: &ShuffleLines, window: &mut Window, cx: &mut Context<Self>) {
 7814        self.manipulate_lines(window, cx, |lines| lines.shuffle(&mut thread_rng()))
 7815    }
 7816
 7817    fn manipulate_lines<Fn>(
 7818        &mut self,
 7819        window: &mut Window,
 7820        cx: &mut Context<Self>,
 7821        mut callback: Fn,
 7822    ) where
 7823        Fn: FnMut(&mut Vec<&str>),
 7824    {
 7825        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 7826        let buffer = self.buffer.read(cx).snapshot(cx);
 7827
 7828        let mut edits = Vec::new();
 7829
 7830        let selections = self.selections.all::<Point>(cx);
 7831        let mut selections = selections.iter().peekable();
 7832        let mut contiguous_row_selections = Vec::new();
 7833        let mut new_selections = Vec::new();
 7834        let mut added_lines = 0;
 7835        let mut removed_lines = 0;
 7836
 7837        while let Some(selection) = selections.next() {
 7838            let (start_row, end_row) = consume_contiguous_rows(
 7839                &mut contiguous_row_selections,
 7840                selection,
 7841                &display_map,
 7842                &mut selections,
 7843            );
 7844
 7845            let start_point = Point::new(start_row.0, 0);
 7846            let end_point = Point::new(
 7847                end_row.previous_row().0,
 7848                buffer.line_len(end_row.previous_row()),
 7849            );
 7850            let text = buffer
 7851                .text_for_range(start_point..end_point)
 7852                .collect::<String>();
 7853
 7854            let mut lines = text.split('\n').collect_vec();
 7855
 7856            let lines_before = lines.len();
 7857            callback(&mut lines);
 7858            let lines_after = lines.len();
 7859
 7860            edits.push((start_point..end_point, lines.join("\n")));
 7861
 7862            // Selections must change based on added and removed line count
 7863            let start_row =
 7864                MultiBufferRow(start_point.row + added_lines as u32 - removed_lines as u32);
 7865            let end_row = MultiBufferRow(start_row.0 + lines_after.saturating_sub(1) as u32);
 7866            new_selections.push(Selection {
 7867                id: selection.id,
 7868                start: start_row,
 7869                end: end_row,
 7870                goal: SelectionGoal::None,
 7871                reversed: selection.reversed,
 7872            });
 7873
 7874            if lines_after > lines_before {
 7875                added_lines += lines_after - lines_before;
 7876            } else if lines_before > lines_after {
 7877                removed_lines += lines_before - lines_after;
 7878            }
 7879        }
 7880
 7881        self.transact(window, cx, |this, window, cx| {
 7882            let buffer = this.buffer.update(cx, |buffer, cx| {
 7883                buffer.edit(edits, None, cx);
 7884                buffer.snapshot(cx)
 7885            });
 7886
 7887            // Recalculate offsets on newly edited buffer
 7888            let new_selections = new_selections
 7889                .iter()
 7890                .map(|s| {
 7891                    let start_point = Point::new(s.start.0, 0);
 7892                    let end_point = Point::new(s.end.0, buffer.line_len(s.end));
 7893                    Selection {
 7894                        id: s.id,
 7895                        start: buffer.point_to_offset(start_point),
 7896                        end: buffer.point_to_offset(end_point),
 7897                        goal: s.goal,
 7898                        reversed: s.reversed,
 7899                    }
 7900                })
 7901                .collect();
 7902
 7903            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 7904                s.select(new_selections);
 7905            });
 7906
 7907            this.request_autoscroll(Autoscroll::fit(), cx);
 7908        });
 7909    }
 7910
 7911    pub fn convert_to_upper_case(
 7912        &mut self,
 7913        _: &ConvertToUpperCase,
 7914        window: &mut Window,
 7915        cx: &mut Context<Self>,
 7916    ) {
 7917        self.manipulate_text(window, cx, |text| text.to_uppercase())
 7918    }
 7919
 7920    pub fn convert_to_lower_case(
 7921        &mut self,
 7922        _: &ConvertToLowerCase,
 7923        window: &mut Window,
 7924        cx: &mut Context<Self>,
 7925    ) {
 7926        self.manipulate_text(window, cx, |text| text.to_lowercase())
 7927    }
 7928
 7929    pub fn convert_to_title_case(
 7930        &mut self,
 7931        _: &ConvertToTitleCase,
 7932        window: &mut Window,
 7933        cx: &mut Context<Self>,
 7934    ) {
 7935        self.manipulate_text(window, cx, |text| {
 7936            text.split('\n')
 7937                .map(|line| line.to_case(Case::Title))
 7938                .join("\n")
 7939        })
 7940    }
 7941
 7942    pub fn convert_to_snake_case(
 7943        &mut self,
 7944        _: &ConvertToSnakeCase,
 7945        window: &mut Window,
 7946        cx: &mut Context<Self>,
 7947    ) {
 7948        self.manipulate_text(window, cx, |text| text.to_case(Case::Snake))
 7949    }
 7950
 7951    pub fn convert_to_kebab_case(
 7952        &mut self,
 7953        _: &ConvertToKebabCase,
 7954        window: &mut Window,
 7955        cx: &mut Context<Self>,
 7956    ) {
 7957        self.manipulate_text(window, cx, |text| text.to_case(Case::Kebab))
 7958    }
 7959
 7960    pub fn convert_to_upper_camel_case(
 7961        &mut self,
 7962        _: &ConvertToUpperCamelCase,
 7963        window: &mut Window,
 7964        cx: &mut Context<Self>,
 7965    ) {
 7966        self.manipulate_text(window, cx, |text| {
 7967            text.split('\n')
 7968                .map(|line| line.to_case(Case::UpperCamel))
 7969                .join("\n")
 7970        })
 7971    }
 7972
 7973    pub fn convert_to_lower_camel_case(
 7974        &mut self,
 7975        _: &ConvertToLowerCamelCase,
 7976        window: &mut Window,
 7977        cx: &mut Context<Self>,
 7978    ) {
 7979        self.manipulate_text(window, cx, |text| text.to_case(Case::Camel))
 7980    }
 7981
 7982    pub fn convert_to_opposite_case(
 7983        &mut self,
 7984        _: &ConvertToOppositeCase,
 7985        window: &mut Window,
 7986        cx: &mut Context<Self>,
 7987    ) {
 7988        self.manipulate_text(window, cx, |text| {
 7989            text.chars()
 7990                .fold(String::with_capacity(text.len()), |mut t, c| {
 7991                    if c.is_uppercase() {
 7992                        t.extend(c.to_lowercase());
 7993                    } else {
 7994                        t.extend(c.to_uppercase());
 7995                    }
 7996                    t
 7997                })
 7998        })
 7999    }
 8000
 8001    fn manipulate_text<Fn>(&mut self, window: &mut Window, cx: &mut Context<Self>, mut callback: Fn)
 8002    where
 8003        Fn: FnMut(&str) -> String,
 8004    {
 8005        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8006        let buffer = self.buffer.read(cx).snapshot(cx);
 8007
 8008        let mut new_selections = Vec::new();
 8009        let mut edits = Vec::new();
 8010        let mut selection_adjustment = 0i32;
 8011
 8012        for selection in self.selections.all::<usize>(cx) {
 8013            let selection_is_empty = selection.is_empty();
 8014
 8015            let (start, end) = if selection_is_empty {
 8016                let word_range = movement::surrounding_word(
 8017                    &display_map,
 8018                    selection.start.to_display_point(&display_map),
 8019                );
 8020                let start = word_range.start.to_offset(&display_map, Bias::Left);
 8021                let end = word_range.end.to_offset(&display_map, Bias::Left);
 8022                (start, end)
 8023            } else {
 8024                (selection.start, selection.end)
 8025            };
 8026
 8027            let text = buffer.text_for_range(start..end).collect::<String>();
 8028            let old_length = text.len() as i32;
 8029            let text = callback(&text);
 8030
 8031            new_selections.push(Selection {
 8032                start: (start as i32 - selection_adjustment) as usize,
 8033                end: ((start + text.len()) as i32 - selection_adjustment) as usize,
 8034                goal: SelectionGoal::None,
 8035                ..selection
 8036            });
 8037
 8038            selection_adjustment += old_length - text.len() as i32;
 8039
 8040            edits.push((start..end, text));
 8041        }
 8042
 8043        self.transact(window, cx, |this, window, cx| {
 8044            this.buffer.update(cx, |buffer, cx| {
 8045                buffer.edit(edits, None, cx);
 8046            });
 8047
 8048            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8049                s.select(new_selections);
 8050            });
 8051
 8052            this.request_autoscroll(Autoscroll::fit(), cx);
 8053        });
 8054    }
 8055
 8056    pub fn duplicate(
 8057        &mut self,
 8058        upwards: bool,
 8059        whole_lines: bool,
 8060        window: &mut Window,
 8061        cx: &mut Context<Self>,
 8062    ) {
 8063        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8064        let buffer = &display_map.buffer_snapshot;
 8065        let selections = self.selections.all::<Point>(cx);
 8066
 8067        let mut edits = Vec::new();
 8068        let mut selections_iter = selections.iter().peekable();
 8069        while let Some(selection) = selections_iter.next() {
 8070            let mut rows = selection.spanned_rows(false, &display_map);
 8071            // duplicate line-wise
 8072            if whole_lines || selection.start == selection.end {
 8073                // Avoid duplicating the same lines twice.
 8074                while let Some(next_selection) = selections_iter.peek() {
 8075                    let next_rows = next_selection.spanned_rows(false, &display_map);
 8076                    if next_rows.start < rows.end {
 8077                        rows.end = next_rows.end;
 8078                        selections_iter.next().unwrap();
 8079                    } else {
 8080                        break;
 8081                    }
 8082                }
 8083
 8084                // Copy the text from the selected row region and splice it either at the start
 8085                // or end of the region.
 8086                let start = Point::new(rows.start.0, 0);
 8087                let end = Point::new(
 8088                    rows.end.previous_row().0,
 8089                    buffer.line_len(rows.end.previous_row()),
 8090                );
 8091                let text = buffer
 8092                    .text_for_range(start..end)
 8093                    .chain(Some("\n"))
 8094                    .collect::<String>();
 8095                let insert_location = if upwards {
 8096                    Point::new(rows.end.0, 0)
 8097                } else {
 8098                    start
 8099                };
 8100                edits.push((insert_location..insert_location, text));
 8101            } else {
 8102                // duplicate character-wise
 8103                let start = selection.start;
 8104                let end = selection.end;
 8105                let text = buffer.text_for_range(start..end).collect::<String>();
 8106                edits.push((selection.end..selection.end, text));
 8107            }
 8108        }
 8109
 8110        self.transact(window, cx, |this, _, cx| {
 8111            this.buffer.update(cx, |buffer, cx| {
 8112                buffer.edit(edits, None, cx);
 8113            });
 8114
 8115            this.request_autoscroll(Autoscroll::fit(), cx);
 8116        });
 8117    }
 8118
 8119    pub fn duplicate_line_up(
 8120        &mut self,
 8121        _: &DuplicateLineUp,
 8122        window: &mut Window,
 8123        cx: &mut Context<Self>,
 8124    ) {
 8125        self.duplicate(true, true, window, cx);
 8126    }
 8127
 8128    pub fn duplicate_line_down(
 8129        &mut self,
 8130        _: &DuplicateLineDown,
 8131        window: &mut Window,
 8132        cx: &mut Context<Self>,
 8133    ) {
 8134        self.duplicate(false, true, window, cx);
 8135    }
 8136
 8137    pub fn duplicate_selection(
 8138        &mut self,
 8139        _: &DuplicateSelection,
 8140        window: &mut Window,
 8141        cx: &mut Context<Self>,
 8142    ) {
 8143        self.duplicate(false, false, window, cx);
 8144    }
 8145
 8146    pub fn move_line_up(&mut self, _: &MoveLineUp, window: &mut Window, cx: &mut Context<Self>) {
 8147        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8148        let buffer = self.buffer.read(cx).snapshot(cx);
 8149
 8150        let mut edits = Vec::new();
 8151        let mut unfold_ranges = Vec::new();
 8152        let mut refold_creases = Vec::new();
 8153
 8154        let selections = self.selections.all::<Point>(cx);
 8155        let mut selections = selections.iter().peekable();
 8156        let mut contiguous_row_selections = Vec::new();
 8157        let mut new_selections = Vec::new();
 8158
 8159        while let Some(selection) = selections.next() {
 8160            // Find all the selections that span a contiguous row range
 8161            let (start_row, end_row) = consume_contiguous_rows(
 8162                &mut contiguous_row_selections,
 8163                selection,
 8164                &display_map,
 8165                &mut selections,
 8166            );
 8167
 8168            // Move the text spanned by the row range to be before the line preceding the row range
 8169            if start_row.0 > 0 {
 8170                let range_to_move = Point::new(
 8171                    start_row.previous_row().0,
 8172                    buffer.line_len(start_row.previous_row()),
 8173                )
 8174                    ..Point::new(
 8175                        end_row.previous_row().0,
 8176                        buffer.line_len(end_row.previous_row()),
 8177                    );
 8178                let insertion_point = display_map
 8179                    .prev_line_boundary(Point::new(start_row.previous_row().0, 0))
 8180                    .0;
 8181
 8182                // Don't move lines across excerpts
 8183                if buffer
 8184                    .excerpt_containing(insertion_point..range_to_move.end)
 8185                    .is_some()
 8186                {
 8187                    let text = buffer
 8188                        .text_for_range(range_to_move.clone())
 8189                        .flat_map(|s| s.chars())
 8190                        .skip(1)
 8191                        .chain(['\n'])
 8192                        .collect::<String>();
 8193
 8194                    edits.push((
 8195                        buffer.anchor_after(range_to_move.start)
 8196                            ..buffer.anchor_before(range_to_move.end),
 8197                        String::new(),
 8198                    ));
 8199                    let insertion_anchor = buffer.anchor_after(insertion_point);
 8200                    edits.push((insertion_anchor..insertion_anchor, text));
 8201
 8202                    let row_delta = range_to_move.start.row - insertion_point.row + 1;
 8203
 8204                    // Move selections up
 8205                    new_selections.extend(contiguous_row_selections.drain(..).map(
 8206                        |mut selection| {
 8207                            selection.start.row -= row_delta;
 8208                            selection.end.row -= row_delta;
 8209                            selection
 8210                        },
 8211                    ));
 8212
 8213                    // Move folds up
 8214                    unfold_ranges.push(range_to_move.clone());
 8215                    for fold in display_map.folds_in_range(
 8216                        buffer.anchor_before(range_to_move.start)
 8217                            ..buffer.anchor_after(range_to_move.end),
 8218                    ) {
 8219                        let mut start = fold.range.start.to_point(&buffer);
 8220                        let mut end = fold.range.end.to_point(&buffer);
 8221                        start.row -= row_delta;
 8222                        end.row -= row_delta;
 8223                        refold_creases.push(Crease::simple(start..end, fold.placeholder.clone()));
 8224                    }
 8225                }
 8226            }
 8227
 8228            // If we didn't move line(s), preserve the existing selections
 8229            new_selections.append(&mut contiguous_row_selections);
 8230        }
 8231
 8232        self.transact(window, cx, |this, window, cx| {
 8233            this.unfold_ranges(&unfold_ranges, true, true, cx);
 8234            this.buffer.update(cx, |buffer, cx| {
 8235                for (range, text) in edits {
 8236                    buffer.edit([(range, text)], None, cx);
 8237                }
 8238            });
 8239            this.fold_creases(refold_creases, true, window, cx);
 8240            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8241                s.select(new_selections);
 8242            })
 8243        });
 8244    }
 8245
 8246    pub fn move_line_down(
 8247        &mut self,
 8248        _: &MoveLineDown,
 8249        window: &mut Window,
 8250        cx: &mut Context<Self>,
 8251    ) {
 8252        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8253        let buffer = self.buffer.read(cx).snapshot(cx);
 8254
 8255        let mut edits = Vec::new();
 8256        let mut unfold_ranges = Vec::new();
 8257        let mut refold_creases = Vec::new();
 8258
 8259        let selections = self.selections.all::<Point>(cx);
 8260        let mut selections = selections.iter().peekable();
 8261        let mut contiguous_row_selections = Vec::new();
 8262        let mut new_selections = Vec::new();
 8263
 8264        while let Some(selection) = selections.next() {
 8265            // Find all the selections that span a contiguous row range
 8266            let (start_row, end_row) = consume_contiguous_rows(
 8267                &mut contiguous_row_selections,
 8268                selection,
 8269                &display_map,
 8270                &mut selections,
 8271            );
 8272
 8273            // Move the text spanned by the row range to be after the last line of the row range
 8274            if end_row.0 <= buffer.max_point().row {
 8275                let range_to_move =
 8276                    MultiBufferPoint::new(start_row.0, 0)..MultiBufferPoint::new(end_row.0, 0);
 8277                let insertion_point = display_map
 8278                    .next_line_boundary(MultiBufferPoint::new(end_row.0, 0))
 8279                    .0;
 8280
 8281                // Don't move lines across excerpt boundaries
 8282                if buffer
 8283                    .excerpt_containing(range_to_move.start..insertion_point)
 8284                    .is_some()
 8285                {
 8286                    let mut text = String::from("\n");
 8287                    text.extend(buffer.text_for_range(range_to_move.clone()));
 8288                    text.pop(); // Drop trailing newline
 8289                    edits.push((
 8290                        buffer.anchor_after(range_to_move.start)
 8291                            ..buffer.anchor_before(range_to_move.end),
 8292                        String::new(),
 8293                    ));
 8294                    let insertion_anchor = buffer.anchor_after(insertion_point);
 8295                    edits.push((insertion_anchor..insertion_anchor, text));
 8296
 8297                    let row_delta = insertion_point.row - range_to_move.end.row + 1;
 8298
 8299                    // Move selections down
 8300                    new_selections.extend(contiguous_row_selections.drain(..).map(
 8301                        |mut selection| {
 8302                            selection.start.row += row_delta;
 8303                            selection.end.row += row_delta;
 8304                            selection
 8305                        },
 8306                    ));
 8307
 8308                    // Move folds down
 8309                    unfold_ranges.push(range_to_move.clone());
 8310                    for fold in display_map.folds_in_range(
 8311                        buffer.anchor_before(range_to_move.start)
 8312                            ..buffer.anchor_after(range_to_move.end),
 8313                    ) {
 8314                        let mut start = fold.range.start.to_point(&buffer);
 8315                        let mut end = fold.range.end.to_point(&buffer);
 8316                        start.row += row_delta;
 8317                        end.row += row_delta;
 8318                        refold_creases.push(Crease::simple(start..end, fold.placeholder.clone()));
 8319                    }
 8320                }
 8321            }
 8322
 8323            // If we didn't move line(s), preserve the existing selections
 8324            new_selections.append(&mut contiguous_row_selections);
 8325        }
 8326
 8327        self.transact(window, cx, |this, window, cx| {
 8328            this.unfold_ranges(&unfold_ranges, true, true, cx);
 8329            this.buffer.update(cx, |buffer, cx| {
 8330                for (range, text) in edits {
 8331                    buffer.edit([(range, text)], None, cx);
 8332                }
 8333            });
 8334            this.fold_creases(refold_creases, true, window, cx);
 8335            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8336                s.select(new_selections)
 8337            });
 8338        });
 8339    }
 8340
 8341    pub fn transpose(&mut self, _: &Transpose, window: &mut Window, cx: &mut Context<Self>) {
 8342        let text_layout_details = &self.text_layout_details(window);
 8343        self.transact(window, cx, |this, window, cx| {
 8344            let edits = this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8345                let mut edits: Vec<(Range<usize>, String)> = Default::default();
 8346                let line_mode = s.line_mode;
 8347                s.move_with(|display_map, selection| {
 8348                    if !selection.is_empty() || line_mode {
 8349                        return;
 8350                    }
 8351
 8352                    let mut head = selection.head();
 8353                    let mut transpose_offset = head.to_offset(display_map, Bias::Right);
 8354                    if head.column() == display_map.line_len(head.row()) {
 8355                        transpose_offset = display_map
 8356                            .buffer_snapshot
 8357                            .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
 8358                    }
 8359
 8360                    if transpose_offset == 0 {
 8361                        return;
 8362                    }
 8363
 8364                    *head.column_mut() += 1;
 8365                    head = display_map.clip_point(head, Bias::Right);
 8366                    let goal = SelectionGoal::HorizontalPosition(
 8367                        display_map
 8368                            .x_for_display_point(head, text_layout_details)
 8369                            .into(),
 8370                    );
 8371                    selection.collapse_to(head, goal);
 8372
 8373                    let transpose_start = display_map
 8374                        .buffer_snapshot
 8375                        .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
 8376                    if edits.last().map_or(true, |e| e.0.end <= transpose_start) {
 8377                        let transpose_end = display_map
 8378                            .buffer_snapshot
 8379                            .clip_offset(transpose_offset + 1, Bias::Right);
 8380                        if let Some(ch) =
 8381                            display_map.buffer_snapshot.chars_at(transpose_start).next()
 8382                        {
 8383                            edits.push((transpose_start..transpose_offset, String::new()));
 8384                            edits.push((transpose_end..transpose_end, ch.to_string()));
 8385                        }
 8386                    }
 8387                });
 8388                edits
 8389            });
 8390            this.buffer
 8391                .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
 8392            let selections = this.selections.all::<usize>(cx);
 8393            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8394                s.select(selections);
 8395            });
 8396        });
 8397    }
 8398
 8399    pub fn rewrap(&mut self, _: &Rewrap, _: &mut Window, cx: &mut Context<Self>) {
 8400        self.rewrap_impl(IsVimMode::No, cx)
 8401    }
 8402
 8403    pub fn rewrap_impl(&mut self, is_vim_mode: IsVimMode, cx: &mut Context<Self>) {
 8404        let buffer = self.buffer.read(cx).snapshot(cx);
 8405        let selections = self.selections.all::<Point>(cx);
 8406        let mut selections = selections.iter().peekable();
 8407
 8408        let mut edits = Vec::new();
 8409        let mut rewrapped_row_ranges = Vec::<RangeInclusive<u32>>::new();
 8410
 8411        while let Some(selection) = selections.next() {
 8412            let mut start_row = selection.start.row;
 8413            let mut end_row = selection.end.row;
 8414
 8415            // Skip selections that overlap with a range that has already been rewrapped.
 8416            let selection_range = start_row..end_row;
 8417            if rewrapped_row_ranges
 8418                .iter()
 8419                .any(|range| range.overlaps(&selection_range))
 8420            {
 8421                continue;
 8422            }
 8423
 8424            let tab_size = buffer.settings_at(selection.head(), cx).tab_size;
 8425
 8426            // Since not all lines in the selection may be at the same indent
 8427            // level, choose the indent size that is the most common between all
 8428            // of the lines.
 8429            //
 8430            // If there is a tie, we use the deepest indent.
 8431            let (indent_size, indent_end) = {
 8432                let mut indent_size_occurrences = HashMap::default();
 8433                let mut rows_by_indent_size = HashMap::<IndentSize, Vec<u32>>::default();
 8434
 8435                for row in start_row..=end_row {
 8436                    let indent = buffer.indent_size_for_line(MultiBufferRow(row));
 8437                    rows_by_indent_size.entry(indent).or_default().push(row);
 8438                    *indent_size_occurrences.entry(indent).or_insert(0) += 1;
 8439                }
 8440
 8441                let indent_size = indent_size_occurrences
 8442                    .into_iter()
 8443                    .max_by_key(|(indent, count)| (*count, indent.len_with_expanded_tabs(tab_size)))
 8444                    .map(|(indent, _)| indent)
 8445                    .unwrap_or_default();
 8446                let row = rows_by_indent_size[&indent_size][0];
 8447                let indent_end = Point::new(row, indent_size.len);
 8448
 8449                (indent_size, indent_end)
 8450            };
 8451
 8452            let mut line_prefix = indent_size.chars().collect::<String>();
 8453
 8454            let mut inside_comment = false;
 8455            if let Some(comment_prefix) =
 8456                buffer
 8457                    .language_scope_at(selection.head())
 8458                    .and_then(|language| {
 8459                        language
 8460                            .line_comment_prefixes()
 8461                            .iter()
 8462                            .find(|prefix| buffer.contains_str_at(indent_end, prefix))
 8463                            .cloned()
 8464                    })
 8465            {
 8466                line_prefix.push_str(&comment_prefix);
 8467                inside_comment = true;
 8468            }
 8469
 8470            let language_settings = buffer.settings_at(selection.head(), cx);
 8471            let allow_rewrap_based_on_language = match language_settings.allow_rewrap {
 8472                RewrapBehavior::InComments => inside_comment,
 8473                RewrapBehavior::InSelections => !selection.is_empty(),
 8474                RewrapBehavior::Anywhere => true,
 8475            };
 8476
 8477            let should_rewrap = is_vim_mode == IsVimMode::Yes || allow_rewrap_based_on_language;
 8478            if !should_rewrap {
 8479                continue;
 8480            }
 8481
 8482            if selection.is_empty() {
 8483                'expand_upwards: while start_row > 0 {
 8484                    let prev_row = start_row - 1;
 8485                    if buffer.contains_str_at(Point::new(prev_row, 0), &line_prefix)
 8486                        && buffer.line_len(MultiBufferRow(prev_row)) as usize > line_prefix.len()
 8487                    {
 8488                        start_row = prev_row;
 8489                    } else {
 8490                        break 'expand_upwards;
 8491                    }
 8492                }
 8493
 8494                'expand_downwards: while end_row < buffer.max_point().row {
 8495                    let next_row = end_row + 1;
 8496                    if buffer.contains_str_at(Point::new(next_row, 0), &line_prefix)
 8497                        && buffer.line_len(MultiBufferRow(next_row)) as usize > line_prefix.len()
 8498                    {
 8499                        end_row = next_row;
 8500                    } else {
 8501                        break 'expand_downwards;
 8502                    }
 8503                }
 8504            }
 8505
 8506            let start = Point::new(start_row, 0);
 8507            let start_offset = start.to_offset(&buffer);
 8508            let end = Point::new(end_row, buffer.line_len(MultiBufferRow(end_row)));
 8509            let selection_text = buffer.text_for_range(start..end).collect::<String>();
 8510            let Some(lines_without_prefixes) = selection_text
 8511                .lines()
 8512                .map(|line| {
 8513                    line.strip_prefix(&line_prefix)
 8514                        .or_else(|| line.trim_start().strip_prefix(&line_prefix.trim_start()))
 8515                        .ok_or_else(|| {
 8516                            anyhow!("line did not start with prefix {line_prefix:?}: {line:?}")
 8517                        })
 8518                })
 8519                .collect::<Result<Vec<_>, _>>()
 8520                .log_err()
 8521            else {
 8522                continue;
 8523            };
 8524
 8525            let wrap_column = buffer
 8526                .settings_at(Point::new(start_row, 0), cx)
 8527                .preferred_line_length as usize;
 8528            let wrapped_text = wrap_with_prefix(
 8529                line_prefix,
 8530                lines_without_prefixes.join(" "),
 8531                wrap_column,
 8532                tab_size,
 8533            );
 8534
 8535            // TODO: should always use char-based diff while still supporting cursor behavior that
 8536            // matches vim.
 8537            let mut diff_options = DiffOptions::default();
 8538            if is_vim_mode == IsVimMode::Yes {
 8539                diff_options.max_word_diff_len = 0;
 8540                diff_options.max_word_diff_line_count = 0;
 8541            } else {
 8542                diff_options.max_word_diff_len = usize::MAX;
 8543                diff_options.max_word_diff_line_count = usize::MAX;
 8544            }
 8545
 8546            for (old_range, new_text) in
 8547                text_diff_with_options(&selection_text, &wrapped_text, diff_options)
 8548            {
 8549                let edit_start = buffer.anchor_after(start_offset + old_range.start);
 8550                let edit_end = buffer.anchor_after(start_offset + old_range.end);
 8551                edits.push((edit_start..edit_end, new_text));
 8552            }
 8553
 8554            rewrapped_row_ranges.push(start_row..=end_row);
 8555        }
 8556
 8557        self.buffer
 8558            .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
 8559    }
 8560
 8561    pub fn cut_common(&mut self, window: &mut Window, cx: &mut Context<Self>) -> ClipboardItem {
 8562        let mut text = String::new();
 8563        let buffer = self.buffer.read(cx).snapshot(cx);
 8564        let mut selections = self.selections.all::<Point>(cx);
 8565        let mut clipboard_selections = Vec::with_capacity(selections.len());
 8566        {
 8567            let max_point = buffer.max_point();
 8568            let mut is_first = true;
 8569            for selection in &mut selections {
 8570                let is_entire_line = selection.is_empty() || self.selections.line_mode;
 8571                if is_entire_line {
 8572                    selection.start = Point::new(selection.start.row, 0);
 8573                    if !selection.is_empty() && selection.end.column == 0 {
 8574                        selection.end = cmp::min(max_point, selection.end);
 8575                    } else {
 8576                        selection.end = cmp::min(max_point, Point::new(selection.end.row + 1, 0));
 8577                    }
 8578                    selection.goal = SelectionGoal::None;
 8579                }
 8580                if is_first {
 8581                    is_first = false;
 8582                } else {
 8583                    text += "\n";
 8584                }
 8585                let mut len = 0;
 8586                for chunk in buffer.text_for_range(selection.start..selection.end) {
 8587                    text.push_str(chunk);
 8588                    len += chunk.len();
 8589                }
 8590                clipboard_selections.push(ClipboardSelection {
 8591                    len,
 8592                    is_entire_line,
 8593                    start_column: selection.start.column,
 8594                });
 8595            }
 8596        }
 8597
 8598        self.transact(window, cx, |this, window, cx| {
 8599            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8600                s.select(selections);
 8601            });
 8602            this.insert("", window, cx);
 8603        });
 8604        ClipboardItem::new_string_with_json_metadata(text, clipboard_selections)
 8605    }
 8606
 8607    pub fn cut(&mut self, _: &Cut, window: &mut Window, cx: &mut Context<Self>) {
 8608        let item = self.cut_common(window, cx);
 8609        cx.write_to_clipboard(item);
 8610    }
 8611
 8612    pub fn kill_ring_cut(&mut self, _: &KillRingCut, window: &mut Window, cx: &mut Context<Self>) {
 8613        self.change_selections(None, window, cx, |s| {
 8614            s.move_with(|snapshot, sel| {
 8615                if sel.is_empty() {
 8616                    sel.end = DisplayPoint::new(sel.end.row(), snapshot.line_len(sel.end.row()))
 8617                }
 8618            });
 8619        });
 8620        let item = self.cut_common(window, cx);
 8621        cx.set_global(KillRing(item))
 8622    }
 8623
 8624    pub fn kill_ring_yank(
 8625        &mut self,
 8626        _: &KillRingYank,
 8627        window: &mut Window,
 8628        cx: &mut Context<Self>,
 8629    ) {
 8630        let (text, metadata) = if let Some(KillRing(item)) = cx.try_global() {
 8631            if let Some(ClipboardEntry::String(kill_ring)) = item.entries().first() {
 8632                (kill_ring.text().to_string(), kill_ring.metadata_json())
 8633            } else {
 8634                return;
 8635            }
 8636        } else {
 8637            return;
 8638        };
 8639        self.do_paste(&text, metadata, false, window, cx);
 8640    }
 8641
 8642    pub fn copy(&mut self, _: &Copy, _: &mut Window, cx: &mut Context<Self>) {
 8643        let selections = self.selections.all::<Point>(cx);
 8644        let buffer = self.buffer.read(cx).read(cx);
 8645        let mut text = String::new();
 8646
 8647        let mut clipboard_selections = Vec::with_capacity(selections.len());
 8648        {
 8649            let max_point = buffer.max_point();
 8650            let mut is_first = true;
 8651            for selection in selections.iter() {
 8652                let mut start = selection.start;
 8653                let mut end = selection.end;
 8654                let is_entire_line = selection.is_empty() || self.selections.line_mode;
 8655                if is_entire_line {
 8656                    start = Point::new(start.row, 0);
 8657                    end = cmp::min(max_point, Point::new(end.row + 1, 0));
 8658                }
 8659                if is_first {
 8660                    is_first = false;
 8661                } else {
 8662                    text += "\n";
 8663                }
 8664                let mut len = 0;
 8665                for chunk in buffer.text_for_range(start..end) {
 8666                    text.push_str(chunk);
 8667                    len += chunk.len();
 8668                }
 8669                clipboard_selections.push(ClipboardSelection {
 8670                    len,
 8671                    is_entire_line,
 8672                    start_column: start.column,
 8673                });
 8674            }
 8675        }
 8676
 8677        cx.write_to_clipboard(ClipboardItem::new_string_with_json_metadata(
 8678            text,
 8679            clipboard_selections,
 8680        ));
 8681    }
 8682
 8683    pub fn do_paste(
 8684        &mut self,
 8685        text: &String,
 8686        clipboard_selections: Option<Vec<ClipboardSelection>>,
 8687        handle_entire_lines: bool,
 8688        window: &mut Window,
 8689        cx: &mut Context<Self>,
 8690    ) {
 8691        if self.read_only(cx) {
 8692            return;
 8693        }
 8694
 8695        let clipboard_text = Cow::Borrowed(text);
 8696
 8697        self.transact(window, cx, |this, window, cx| {
 8698            if let Some(mut clipboard_selections) = clipboard_selections {
 8699                let old_selections = this.selections.all::<usize>(cx);
 8700                let all_selections_were_entire_line =
 8701                    clipboard_selections.iter().all(|s| s.is_entire_line);
 8702                let first_selection_start_column =
 8703                    clipboard_selections.first().map(|s| s.start_column);
 8704                if clipboard_selections.len() != old_selections.len() {
 8705                    clipboard_selections.drain(..);
 8706                }
 8707                let cursor_offset = this.selections.last::<usize>(cx).head();
 8708                let mut auto_indent_on_paste = true;
 8709
 8710                this.buffer.update(cx, |buffer, cx| {
 8711                    let snapshot = buffer.read(cx);
 8712                    auto_indent_on_paste =
 8713                        snapshot.settings_at(cursor_offset, cx).auto_indent_on_paste;
 8714
 8715                    let mut start_offset = 0;
 8716                    let mut edits = Vec::new();
 8717                    let mut original_start_columns = Vec::new();
 8718                    for (ix, selection) in old_selections.iter().enumerate() {
 8719                        let to_insert;
 8720                        let entire_line;
 8721                        let original_start_column;
 8722                        if let Some(clipboard_selection) = clipboard_selections.get(ix) {
 8723                            let end_offset = start_offset + clipboard_selection.len;
 8724                            to_insert = &clipboard_text[start_offset..end_offset];
 8725                            entire_line = clipboard_selection.is_entire_line;
 8726                            start_offset = end_offset + 1;
 8727                            original_start_column = Some(clipboard_selection.start_column);
 8728                        } else {
 8729                            to_insert = clipboard_text.as_str();
 8730                            entire_line = all_selections_were_entire_line;
 8731                            original_start_column = first_selection_start_column
 8732                        }
 8733
 8734                        // If the corresponding selection was empty when this slice of the
 8735                        // clipboard text was written, then the entire line containing the
 8736                        // selection was copied. If this selection is also currently empty,
 8737                        // then paste the line before the current line of the buffer.
 8738                        let range = if selection.is_empty() && handle_entire_lines && entire_line {
 8739                            let column = selection.start.to_point(&snapshot).column as usize;
 8740                            let line_start = selection.start - column;
 8741                            line_start..line_start
 8742                        } else {
 8743                            selection.range()
 8744                        };
 8745
 8746                        edits.push((range, to_insert));
 8747                        original_start_columns.extend(original_start_column);
 8748                    }
 8749                    drop(snapshot);
 8750
 8751                    buffer.edit(
 8752                        edits,
 8753                        if auto_indent_on_paste {
 8754                            Some(AutoindentMode::Block {
 8755                                original_start_columns,
 8756                            })
 8757                        } else {
 8758                            None
 8759                        },
 8760                        cx,
 8761                    );
 8762                });
 8763
 8764                let selections = this.selections.all::<usize>(cx);
 8765                this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8766                    s.select(selections)
 8767                });
 8768            } else {
 8769                this.insert(&clipboard_text, window, cx);
 8770            }
 8771        });
 8772    }
 8773
 8774    pub fn paste(&mut self, _: &Paste, window: &mut Window, cx: &mut Context<Self>) {
 8775        if let Some(item) = cx.read_from_clipboard() {
 8776            let entries = item.entries();
 8777
 8778            match entries.first() {
 8779                // For now, we only support applying metadata if there's one string. In the future, we can incorporate all the selections
 8780                // of all the pasted entries.
 8781                Some(ClipboardEntry::String(clipboard_string)) if entries.len() == 1 => self
 8782                    .do_paste(
 8783                        clipboard_string.text(),
 8784                        clipboard_string.metadata_json::<Vec<ClipboardSelection>>(),
 8785                        true,
 8786                        window,
 8787                        cx,
 8788                    ),
 8789                _ => self.do_paste(&item.text().unwrap_or_default(), None, true, window, cx),
 8790            }
 8791        }
 8792    }
 8793
 8794    pub fn undo(&mut self, _: &Undo, window: &mut Window, cx: &mut Context<Self>) {
 8795        if self.read_only(cx) {
 8796            return;
 8797        }
 8798
 8799        if let Some(transaction_id) = self.buffer.update(cx, |buffer, cx| buffer.undo(cx)) {
 8800            if let Some((selections, _)) =
 8801                self.selection_history.transaction(transaction_id).cloned()
 8802            {
 8803                self.change_selections(None, window, cx, |s| {
 8804                    s.select_anchors(selections.to_vec());
 8805                });
 8806            } else {
 8807                log::error!(
 8808                    "No entry in selection_history found for undo. \
 8809                     This may correspond to a bug where undo does not update the selection. \
 8810                     If this is occurring, please add details to \
 8811                     https://github.com/zed-industries/zed/issues/22692"
 8812                );
 8813            }
 8814            self.request_autoscroll(Autoscroll::fit(), cx);
 8815            self.unmark_text(window, cx);
 8816            self.refresh_inline_completion(true, false, window, cx);
 8817            cx.emit(EditorEvent::Edited { transaction_id });
 8818            cx.emit(EditorEvent::TransactionUndone { transaction_id });
 8819        }
 8820    }
 8821
 8822    pub fn redo(&mut self, _: &Redo, window: &mut Window, cx: &mut Context<Self>) {
 8823        if self.read_only(cx) {
 8824            return;
 8825        }
 8826
 8827        if let Some(transaction_id) = self.buffer.update(cx, |buffer, cx| buffer.redo(cx)) {
 8828            if let Some((_, Some(selections))) =
 8829                self.selection_history.transaction(transaction_id).cloned()
 8830            {
 8831                self.change_selections(None, window, cx, |s| {
 8832                    s.select_anchors(selections.to_vec());
 8833                });
 8834            } else {
 8835                log::error!(
 8836                    "No entry in selection_history found for redo. \
 8837                     This may correspond to a bug where undo does not update the selection. \
 8838                     If this is occurring, please add details to \
 8839                     https://github.com/zed-industries/zed/issues/22692"
 8840                );
 8841            }
 8842            self.request_autoscroll(Autoscroll::fit(), cx);
 8843            self.unmark_text(window, cx);
 8844            self.refresh_inline_completion(true, false, window, cx);
 8845            cx.emit(EditorEvent::Edited { transaction_id });
 8846        }
 8847    }
 8848
 8849    pub fn finalize_last_transaction(&mut self, cx: &mut Context<Self>) {
 8850        self.buffer
 8851            .update(cx, |buffer, cx| buffer.finalize_last_transaction(cx));
 8852    }
 8853
 8854    pub fn group_until_transaction(&mut self, tx_id: TransactionId, cx: &mut Context<Self>) {
 8855        self.buffer
 8856            .update(cx, |buffer, cx| buffer.group_until_transaction(tx_id, cx));
 8857    }
 8858
 8859    pub fn move_left(&mut self, _: &MoveLeft, window: &mut Window, cx: &mut Context<Self>) {
 8860        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8861            let line_mode = s.line_mode;
 8862            s.move_with(|map, selection| {
 8863                let cursor = if selection.is_empty() && !line_mode {
 8864                    movement::left(map, selection.start)
 8865                } else {
 8866                    selection.start
 8867                };
 8868                selection.collapse_to(cursor, SelectionGoal::None);
 8869            });
 8870        })
 8871    }
 8872
 8873    pub fn select_left(&mut self, _: &SelectLeft, window: &mut Window, cx: &mut Context<Self>) {
 8874        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8875            s.move_heads_with(|map, head, _| (movement::left(map, head), SelectionGoal::None));
 8876        })
 8877    }
 8878
 8879    pub fn move_right(&mut self, _: &MoveRight, window: &mut Window, cx: &mut Context<Self>) {
 8880        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8881            let line_mode = s.line_mode;
 8882            s.move_with(|map, selection| {
 8883                let cursor = if selection.is_empty() && !line_mode {
 8884                    movement::right(map, selection.end)
 8885                } else {
 8886                    selection.end
 8887                };
 8888                selection.collapse_to(cursor, SelectionGoal::None)
 8889            });
 8890        })
 8891    }
 8892
 8893    pub fn select_right(&mut self, _: &SelectRight, window: &mut Window, cx: &mut Context<Self>) {
 8894        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8895            s.move_heads_with(|map, head, _| (movement::right(map, head), SelectionGoal::None));
 8896        })
 8897    }
 8898
 8899    pub fn move_up(&mut self, _: &MoveUp, window: &mut Window, cx: &mut Context<Self>) {
 8900        if self.take_rename(true, window, cx).is_some() {
 8901            return;
 8902        }
 8903
 8904        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 8905            cx.propagate();
 8906            return;
 8907        }
 8908
 8909        let text_layout_details = &self.text_layout_details(window);
 8910        let selection_count = self.selections.count();
 8911        let first_selection = self.selections.first_anchor();
 8912
 8913        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8914            let line_mode = s.line_mode;
 8915            s.move_with(|map, selection| {
 8916                if !selection.is_empty() && !line_mode {
 8917                    selection.goal = SelectionGoal::None;
 8918                }
 8919                let (cursor, goal) = movement::up(
 8920                    map,
 8921                    selection.start,
 8922                    selection.goal,
 8923                    false,
 8924                    text_layout_details,
 8925                );
 8926                selection.collapse_to(cursor, goal);
 8927            });
 8928        });
 8929
 8930        if selection_count == 1 && first_selection.range() == self.selections.first_anchor().range()
 8931        {
 8932            cx.propagate();
 8933        }
 8934    }
 8935
 8936    pub fn move_up_by_lines(
 8937        &mut self,
 8938        action: &MoveUpByLines,
 8939        window: &mut Window,
 8940        cx: &mut Context<Self>,
 8941    ) {
 8942        if self.take_rename(true, window, cx).is_some() {
 8943            return;
 8944        }
 8945
 8946        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 8947            cx.propagate();
 8948            return;
 8949        }
 8950
 8951        let text_layout_details = &self.text_layout_details(window);
 8952
 8953        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8954            let line_mode = s.line_mode;
 8955            s.move_with(|map, selection| {
 8956                if !selection.is_empty() && !line_mode {
 8957                    selection.goal = SelectionGoal::None;
 8958                }
 8959                let (cursor, goal) = movement::up_by_rows(
 8960                    map,
 8961                    selection.start,
 8962                    action.lines,
 8963                    selection.goal,
 8964                    false,
 8965                    text_layout_details,
 8966                );
 8967                selection.collapse_to(cursor, goal);
 8968            });
 8969        })
 8970    }
 8971
 8972    pub fn move_down_by_lines(
 8973        &mut self,
 8974        action: &MoveDownByLines,
 8975        window: &mut Window,
 8976        cx: &mut Context<Self>,
 8977    ) {
 8978        if self.take_rename(true, window, cx).is_some() {
 8979            return;
 8980        }
 8981
 8982        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 8983            cx.propagate();
 8984            return;
 8985        }
 8986
 8987        let text_layout_details = &self.text_layout_details(window);
 8988
 8989        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8990            let line_mode = s.line_mode;
 8991            s.move_with(|map, selection| {
 8992                if !selection.is_empty() && !line_mode {
 8993                    selection.goal = SelectionGoal::None;
 8994                }
 8995                let (cursor, goal) = movement::down_by_rows(
 8996                    map,
 8997                    selection.start,
 8998                    action.lines,
 8999                    selection.goal,
 9000                    false,
 9001                    text_layout_details,
 9002                );
 9003                selection.collapse_to(cursor, goal);
 9004            });
 9005        })
 9006    }
 9007
 9008    pub fn select_down_by_lines(
 9009        &mut self,
 9010        action: &SelectDownByLines,
 9011        window: &mut Window,
 9012        cx: &mut Context<Self>,
 9013    ) {
 9014        let text_layout_details = &self.text_layout_details(window);
 9015        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9016            s.move_heads_with(|map, head, goal| {
 9017                movement::down_by_rows(map, head, action.lines, goal, false, text_layout_details)
 9018            })
 9019        })
 9020    }
 9021
 9022    pub fn select_up_by_lines(
 9023        &mut self,
 9024        action: &SelectUpByLines,
 9025        window: &mut Window,
 9026        cx: &mut Context<Self>,
 9027    ) {
 9028        let text_layout_details = &self.text_layout_details(window);
 9029        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9030            s.move_heads_with(|map, head, goal| {
 9031                movement::up_by_rows(map, head, action.lines, goal, false, text_layout_details)
 9032            })
 9033        })
 9034    }
 9035
 9036    pub fn select_page_up(
 9037        &mut self,
 9038        _: &SelectPageUp,
 9039        window: &mut Window,
 9040        cx: &mut Context<Self>,
 9041    ) {
 9042        let Some(row_count) = self.visible_row_count() else {
 9043            return;
 9044        };
 9045
 9046        let text_layout_details = &self.text_layout_details(window);
 9047
 9048        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9049            s.move_heads_with(|map, head, goal| {
 9050                movement::up_by_rows(map, head, row_count, goal, false, text_layout_details)
 9051            })
 9052        })
 9053    }
 9054
 9055    pub fn move_page_up(
 9056        &mut self,
 9057        action: &MovePageUp,
 9058        window: &mut Window,
 9059        cx: &mut Context<Self>,
 9060    ) {
 9061        if self.take_rename(true, window, cx).is_some() {
 9062            return;
 9063        }
 9064
 9065        if self
 9066            .context_menu
 9067            .borrow_mut()
 9068            .as_mut()
 9069            .map(|menu| menu.select_first(self.completion_provider.as_deref(), cx))
 9070            .unwrap_or(false)
 9071        {
 9072            return;
 9073        }
 9074
 9075        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 9076            cx.propagate();
 9077            return;
 9078        }
 9079
 9080        let Some(row_count) = self.visible_row_count() else {
 9081            return;
 9082        };
 9083
 9084        let autoscroll = if action.center_cursor {
 9085            Autoscroll::center()
 9086        } else {
 9087            Autoscroll::fit()
 9088        };
 9089
 9090        let text_layout_details = &self.text_layout_details(window);
 9091
 9092        self.change_selections(Some(autoscroll), window, cx, |s| {
 9093            let line_mode = s.line_mode;
 9094            s.move_with(|map, selection| {
 9095                if !selection.is_empty() && !line_mode {
 9096                    selection.goal = SelectionGoal::None;
 9097                }
 9098                let (cursor, goal) = movement::up_by_rows(
 9099                    map,
 9100                    selection.end,
 9101                    row_count,
 9102                    selection.goal,
 9103                    false,
 9104                    text_layout_details,
 9105                );
 9106                selection.collapse_to(cursor, goal);
 9107            });
 9108        });
 9109    }
 9110
 9111    pub fn select_up(&mut self, _: &SelectUp, window: &mut Window, cx: &mut Context<Self>) {
 9112        let text_layout_details = &self.text_layout_details(window);
 9113        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9114            s.move_heads_with(|map, head, goal| {
 9115                movement::up(map, head, goal, false, text_layout_details)
 9116            })
 9117        })
 9118    }
 9119
 9120    pub fn move_down(&mut self, _: &MoveDown, window: &mut Window, cx: &mut Context<Self>) {
 9121        self.take_rename(true, window, cx);
 9122
 9123        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 9124            cx.propagate();
 9125            return;
 9126        }
 9127
 9128        let text_layout_details = &self.text_layout_details(window);
 9129        let selection_count = self.selections.count();
 9130        let first_selection = self.selections.first_anchor();
 9131
 9132        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9133            let line_mode = s.line_mode;
 9134            s.move_with(|map, selection| {
 9135                if !selection.is_empty() && !line_mode {
 9136                    selection.goal = SelectionGoal::None;
 9137                }
 9138                let (cursor, goal) = movement::down(
 9139                    map,
 9140                    selection.end,
 9141                    selection.goal,
 9142                    false,
 9143                    text_layout_details,
 9144                );
 9145                selection.collapse_to(cursor, goal);
 9146            });
 9147        });
 9148
 9149        if selection_count == 1 && first_selection.range() == self.selections.first_anchor().range()
 9150        {
 9151            cx.propagate();
 9152        }
 9153    }
 9154
 9155    pub fn select_page_down(
 9156        &mut self,
 9157        _: &SelectPageDown,
 9158        window: &mut Window,
 9159        cx: &mut Context<Self>,
 9160    ) {
 9161        let Some(row_count) = self.visible_row_count() else {
 9162            return;
 9163        };
 9164
 9165        let text_layout_details = &self.text_layout_details(window);
 9166
 9167        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9168            s.move_heads_with(|map, head, goal| {
 9169                movement::down_by_rows(map, head, row_count, goal, false, text_layout_details)
 9170            })
 9171        })
 9172    }
 9173
 9174    pub fn move_page_down(
 9175        &mut self,
 9176        action: &MovePageDown,
 9177        window: &mut Window,
 9178        cx: &mut Context<Self>,
 9179    ) {
 9180        if self.take_rename(true, window, cx).is_some() {
 9181            return;
 9182        }
 9183
 9184        if self
 9185            .context_menu
 9186            .borrow_mut()
 9187            .as_mut()
 9188            .map(|menu| menu.select_last(self.completion_provider.as_deref(), cx))
 9189            .unwrap_or(false)
 9190        {
 9191            return;
 9192        }
 9193
 9194        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 9195            cx.propagate();
 9196            return;
 9197        }
 9198
 9199        let Some(row_count) = self.visible_row_count() else {
 9200            return;
 9201        };
 9202
 9203        let autoscroll = if action.center_cursor {
 9204            Autoscroll::center()
 9205        } else {
 9206            Autoscroll::fit()
 9207        };
 9208
 9209        let text_layout_details = &self.text_layout_details(window);
 9210        self.change_selections(Some(autoscroll), window, cx, |s| {
 9211            let line_mode = s.line_mode;
 9212            s.move_with(|map, selection| {
 9213                if !selection.is_empty() && !line_mode {
 9214                    selection.goal = SelectionGoal::None;
 9215                }
 9216                let (cursor, goal) = movement::down_by_rows(
 9217                    map,
 9218                    selection.end,
 9219                    row_count,
 9220                    selection.goal,
 9221                    false,
 9222                    text_layout_details,
 9223                );
 9224                selection.collapse_to(cursor, goal);
 9225            });
 9226        });
 9227    }
 9228
 9229    pub fn select_down(&mut self, _: &SelectDown, window: &mut Window, cx: &mut Context<Self>) {
 9230        let text_layout_details = &self.text_layout_details(window);
 9231        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9232            s.move_heads_with(|map, head, goal| {
 9233                movement::down(map, head, goal, false, text_layout_details)
 9234            })
 9235        });
 9236    }
 9237
 9238    pub fn context_menu_first(
 9239        &mut self,
 9240        _: &ContextMenuFirst,
 9241        _window: &mut Window,
 9242        cx: &mut Context<Self>,
 9243    ) {
 9244        if let Some(context_menu) = self.context_menu.borrow_mut().as_mut() {
 9245            context_menu.select_first(self.completion_provider.as_deref(), cx);
 9246        }
 9247    }
 9248
 9249    pub fn context_menu_prev(
 9250        &mut self,
 9251        _: &ContextMenuPrev,
 9252        _window: &mut Window,
 9253        cx: &mut Context<Self>,
 9254    ) {
 9255        if let Some(context_menu) = self.context_menu.borrow_mut().as_mut() {
 9256            context_menu.select_prev(self.completion_provider.as_deref(), cx);
 9257        }
 9258    }
 9259
 9260    pub fn context_menu_next(
 9261        &mut self,
 9262        _: &ContextMenuNext,
 9263        _window: &mut Window,
 9264        cx: &mut Context<Self>,
 9265    ) {
 9266        if let Some(context_menu) = self.context_menu.borrow_mut().as_mut() {
 9267            context_menu.select_next(self.completion_provider.as_deref(), cx);
 9268        }
 9269    }
 9270
 9271    pub fn context_menu_last(
 9272        &mut self,
 9273        _: &ContextMenuLast,
 9274        _window: &mut Window,
 9275        cx: &mut Context<Self>,
 9276    ) {
 9277        if let Some(context_menu) = self.context_menu.borrow_mut().as_mut() {
 9278            context_menu.select_last(self.completion_provider.as_deref(), cx);
 9279        }
 9280    }
 9281
 9282    pub fn move_to_previous_word_start(
 9283        &mut self,
 9284        _: &MoveToPreviousWordStart,
 9285        window: &mut Window,
 9286        cx: &mut Context<Self>,
 9287    ) {
 9288        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9289            s.move_cursors_with(|map, head, _| {
 9290                (
 9291                    movement::previous_word_start(map, head),
 9292                    SelectionGoal::None,
 9293                )
 9294            });
 9295        })
 9296    }
 9297
 9298    pub fn move_to_previous_subword_start(
 9299        &mut self,
 9300        _: &MoveToPreviousSubwordStart,
 9301        window: &mut Window,
 9302        cx: &mut Context<Self>,
 9303    ) {
 9304        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9305            s.move_cursors_with(|map, head, _| {
 9306                (
 9307                    movement::previous_subword_start(map, head),
 9308                    SelectionGoal::None,
 9309                )
 9310            });
 9311        })
 9312    }
 9313
 9314    pub fn select_to_previous_word_start(
 9315        &mut self,
 9316        _: &SelectToPreviousWordStart,
 9317        window: &mut Window,
 9318        cx: &mut Context<Self>,
 9319    ) {
 9320        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9321            s.move_heads_with(|map, head, _| {
 9322                (
 9323                    movement::previous_word_start(map, head),
 9324                    SelectionGoal::None,
 9325                )
 9326            });
 9327        })
 9328    }
 9329
 9330    pub fn select_to_previous_subword_start(
 9331        &mut self,
 9332        _: &SelectToPreviousSubwordStart,
 9333        window: &mut Window,
 9334        cx: &mut Context<Self>,
 9335    ) {
 9336        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9337            s.move_heads_with(|map, head, _| {
 9338                (
 9339                    movement::previous_subword_start(map, head),
 9340                    SelectionGoal::None,
 9341                )
 9342            });
 9343        })
 9344    }
 9345
 9346    pub fn delete_to_previous_word_start(
 9347        &mut self,
 9348        action: &DeleteToPreviousWordStart,
 9349        window: &mut Window,
 9350        cx: &mut Context<Self>,
 9351    ) {
 9352        self.transact(window, cx, |this, window, cx| {
 9353            this.select_autoclose_pair(window, cx);
 9354            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9355                let line_mode = s.line_mode;
 9356                s.move_with(|map, selection| {
 9357                    if selection.is_empty() && !line_mode {
 9358                        let cursor = if action.ignore_newlines {
 9359                            movement::previous_word_start(map, selection.head())
 9360                        } else {
 9361                            movement::previous_word_start_or_newline(map, selection.head())
 9362                        };
 9363                        selection.set_head(cursor, SelectionGoal::None);
 9364                    }
 9365                });
 9366            });
 9367            this.insert("", window, cx);
 9368        });
 9369    }
 9370
 9371    pub fn delete_to_previous_subword_start(
 9372        &mut self,
 9373        _: &DeleteToPreviousSubwordStart,
 9374        window: &mut Window,
 9375        cx: &mut Context<Self>,
 9376    ) {
 9377        self.transact(window, cx, |this, window, cx| {
 9378            this.select_autoclose_pair(window, cx);
 9379            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9380                let line_mode = s.line_mode;
 9381                s.move_with(|map, selection| {
 9382                    if selection.is_empty() && !line_mode {
 9383                        let cursor = movement::previous_subword_start(map, selection.head());
 9384                        selection.set_head(cursor, SelectionGoal::None);
 9385                    }
 9386                });
 9387            });
 9388            this.insert("", window, cx);
 9389        });
 9390    }
 9391
 9392    pub fn move_to_next_word_end(
 9393        &mut self,
 9394        _: &MoveToNextWordEnd,
 9395        window: &mut Window,
 9396        cx: &mut Context<Self>,
 9397    ) {
 9398        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9399            s.move_cursors_with(|map, head, _| {
 9400                (movement::next_word_end(map, head), SelectionGoal::None)
 9401            });
 9402        })
 9403    }
 9404
 9405    pub fn move_to_next_subword_end(
 9406        &mut self,
 9407        _: &MoveToNextSubwordEnd,
 9408        window: &mut Window,
 9409        cx: &mut Context<Self>,
 9410    ) {
 9411        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9412            s.move_cursors_with(|map, head, _| {
 9413                (movement::next_subword_end(map, head), SelectionGoal::None)
 9414            });
 9415        })
 9416    }
 9417
 9418    pub fn select_to_next_word_end(
 9419        &mut self,
 9420        _: &SelectToNextWordEnd,
 9421        window: &mut Window,
 9422        cx: &mut Context<Self>,
 9423    ) {
 9424        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9425            s.move_heads_with(|map, head, _| {
 9426                (movement::next_word_end(map, head), SelectionGoal::None)
 9427            });
 9428        })
 9429    }
 9430
 9431    pub fn select_to_next_subword_end(
 9432        &mut self,
 9433        _: &SelectToNextSubwordEnd,
 9434        window: &mut Window,
 9435        cx: &mut Context<Self>,
 9436    ) {
 9437        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9438            s.move_heads_with(|map, head, _| {
 9439                (movement::next_subword_end(map, head), SelectionGoal::None)
 9440            });
 9441        })
 9442    }
 9443
 9444    pub fn delete_to_next_word_end(
 9445        &mut self,
 9446        action: &DeleteToNextWordEnd,
 9447        window: &mut Window,
 9448        cx: &mut Context<Self>,
 9449    ) {
 9450        self.transact(window, cx, |this, window, cx| {
 9451            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9452                let line_mode = s.line_mode;
 9453                s.move_with(|map, selection| {
 9454                    if selection.is_empty() && !line_mode {
 9455                        let cursor = if action.ignore_newlines {
 9456                            movement::next_word_end(map, selection.head())
 9457                        } else {
 9458                            movement::next_word_end_or_newline(map, selection.head())
 9459                        };
 9460                        selection.set_head(cursor, SelectionGoal::None);
 9461                    }
 9462                });
 9463            });
 9464            this.insert("", window, cx);
 9465        });
 9466    }
 9467
 9468    pub fn delete_to_next_subword_end(
 9469        &mut self,
 9470        _: &DeleteToNextSubwordEnd,
 9471        window: &mut Window,
 9472        cx: &mut Context<Self>,
 9473    ) {
 9474        self.transact(window, cx, |this, window, cx| {
 9475            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9476                s.move_with(|map, selection| {
 9477                    if selection.is_empty() {
 9478                        let cursor = movement::next_subword_end(map, selection.head());
 9479                        selection.set_head(cursor, SelectionGoal::None);
 9480                    }
 9481                });
 9482            });
 9483            this.insert("", window, cx);
 9484        });
 9485    }
 9486
 9487    pub fn move_to_beginning_of_line(
 9488        &mut self,
 9489        action: &MoveToBeginningOfLine,
 9490        window: &mut Window,
 9491        cx: &mut Context<Self>,
 9492    ) {
 9493        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9494            s.move_cursors_with(|map, head, _| {
 9495                (
 9496                    movement::indented_line_beginning(
 9497                        map,
 9498                        head,
 9499                        action.stop_at_soft_wraps,
 9500                        action.stop_at_indent,
 9501                    ),
 9502                    SelectionGoal::None,
 9503                )
 9504            });
 9505        })
 9506    }
 9507
 9508    pub fn select_to_beginning_of_line(
 9509        &mut self,
 9510        action: &SelectToBeginningOfLine,
 9511        window: &mut Window,
 9512        cx: &mut Context<Self>,
 9513    ) {
 9514        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9515            s.move_heads_with(|map, head, _| {
 9516                (
 9517                    movement::indented_line_beginning(
 9518                        map,
 9519                        head,
 9520                        action.stop_at_soft_wraps,
 9521                        action.stop_at_indent,
 9522                    ),
 9523                    SelectionGoal::None,
 9524                )
 9525            });
 9526        });
 9527    }
 9528
 9529    pub fn delete_to_beginning_of_line(
 9530        &mut self,
 9531        _: &DeleteToBeginningOfLine,
 9532        window: &mut Window,
 9533        cx: &mut Context<Self>,
 9534    ) {
 9535        self.transact(window, cx, |this, window, cx| {
 9536            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9537                s.move_with(|_, selection| {
 9538                    selection.reversed = true;
 9539                });
 9540            });
 9541
 9542            this.select_to_beginning_of_line(
 9543                &SelectToBeginningOfLine {
 9544                    stop_at_soft_wraps: false,
 9545                    stop_at_indent: false,
 9546                },
 9547                window,
 9548                cx,
 9549            );
 9550            this.backspace(&Backspace, window, cx);
 9551        });
 9552    }
 9553
 9554    pub fn move_to_end_of_line(
 9555        &mut self,
 9556        action: &MoveToEndOfLine,
 9557        window: &mut Window,
 9558        cx: &mut Context<Self>,
 9559    ) {
 9560        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9561            s.move_cursors_with(|map, head, _| {
 9562                (
 9563                    movement::line_end(map, head, action.stop_at_soft_wraps),
 9564                    SelectionGoal::None,
 9565                )
 9566            });
 9567        })
 9568    }
 9569
 9570    pub fn select_to_end_of_line(
 9571        &mut self,
 9572        action: &SelectToEndOfLine,
 9573        window: &mut Window,
 9574        cx: &mut Context<Self>,
 9575    ) {
 9576        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9577            s.move_heads_with(|map, head, _| {
 9578                (
 9579                    movement::line_end(map, head, action.stop_at_soft_wraps),
 9580                    SelectionGoal::None,
 9581                )
 9582            });
 9583        })
 9584    }
 9585
 9586    pub fn delete_to_end_of_line(
 9587        &mut self,
 9588        _: &DeleteToEndOfLine,
 9589        window: &mut Window,
 9590        cx: &mut Context<Self>,
 9591    ) {
 9592        self.transact(window, cx, |this, window, cx| {
 9593            this.select_to_end_of_line(
 9594                &SelectToEndOfLine {
 9595                    stop_at_soft_wraps: false,
 9596                },
 9597                window,
 9598                cx,
 9599            );
 9600            this.delete(&Delete, window, cx);
 9601        });
 9602    }
 9603
 9604    pub fn cut_to_end_of_line(
 9605        &mut self,
 9606        _: &CutToEndOfLine,
 9607        window: &mut Window,
 9608        cx: &mut Context<Self>,
 9609    ) {
 9610        self.transact(window, cx, |this, window, cx| {
 9611            this.select_to_end_of_line(
 9612                &SelectToEndOfLine {
 9613                    stop_at_soft_wraps: false,
 9614                },
 9615                window,
 9616                cx,
 9617            );
 9618            this.cut(&Cut, window, cx);
 9619        });
 9620    }
 9621
 9622    pub fn move_to_start_of_paragraph(
 9623        &mut self,
 9624        _: &MoveToStartOfParagraph,
 9625        window: &mut Window,
 9626        cx: &mut Context<Self>,
 9627    ) {
 9628        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 9629            cx.propagate();
 9630            return;
 9631        }
 9632
 9633        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9634            s.move_with(|map, selection| {
 9635                selection.collapse_to(
 9636                    movement::start_of_paragraph(map, selection.head(), 1),
 9637                    SelectionGoal::None,
 9638                )
 9639            });
 9640        })
 9641    }
 9642
 9643    pub fn move_to_end_of_paragraph(
 9644        &mut self,
 9645        _: &MoveToEndOfParagraph,
 9646        window: &mut Window,
 9647        cx: &mut Context<Self>,
 9648    ) {
 9649        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 9650            cx.propagate();
 9651            return;
 9652        }
 9653
 9654        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9655            s.move_with(|map, selection| {
 9656                selection.collapse_to(
 9657                    movement::end_of_paragraph(map, selection.head(), 1),
 9658                    SelectionGoal::None,
 9659                )
 9660            });
 9661        })
 9662    }
 9663
 9664    pub fn select_to_start_of_paragraph(
 9665        &mut self,
 9666        _: &SelectToStartOfParagraph,
 9667        window: &mut Window,
 9668        cx: &mut Context<Self>,
 9669    ) {
 9670        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 9671            cx.propagate();
 9672            return;
 9673        }
 9674
 9675        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9676            s.move_heads_with(|map, head, _| {
 9677                (
 9678                    movement::start_of_paragraph(map, head, 1),
 9679                    SelectionGoal::None,
 9680                )
 9681            });
 9682        })
 9683    }
 9684
 9685    pub fn select_to_end_of_paragraph(
 9686        &mut self,
 9687        _: &SelectToEndOfParagraph,
 9688        window: &mut Window,
 9689        cx: &mut Context<Self>,
 9690    ) {
 9691        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 9692            cx.propagate();
 9693            return;
 9694        }
 9695
 9696        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9697            s.move_heads_with(|map, head, _| {
 9698                (
 9699                    movement::end_of_paragraph(map, head, 1),
 9700                    SelectionGoal::None,
 9701                )
 9702            });
 9703        })
 9704    }
 9705
 9706    pub fn move_to_start_of_excerpt(
 9707        &mut self,
 9708        _: &MoveToStartOfExcerpt,
 9709        window: &mut Window,
 9710        cx: &mut Context<Self>,
 9711    ) {
 9712        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 9713            cx.propagate();
 9714            return;
 9715        }
 9716
 9717        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9718            s.move_with(|map, selection| {
 9719                selection.collapse_to(
 9720                    movement::start_of_excerpt(
 9721                        map,
 9722                        selection.head(),
 9723                        workspace::searchable::Direction::Prev,
 9724                    ),
 9725                    SelectionGoal::None,
 9726                )
 9727            });
 9728        })
 9729    }
 9730
 9731    pub fn move_to_end_of_excerpt(
 9732        &mut self,
 9733        _: &MoveToEndOfExcerpt,
 9734        window: &mut Window,
 9735        cx: &mut Context<Self>,
 9736    ) {
 9737        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 9738            cx.propagate();
 9739            return;
 9740        }
 9741
 9742        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9743            s.move_with(|map, selection| {
 9744                selection.collapse_to(
 9745                    movement::end_of_excerpt(
 9746                        map,
 9747                        selection.head(),
 9748                        workspace::searchable::Direction::Next,
 9749                    ),
 9750                    SelectionGoal::None,
 9751                )
 9752            });
 9753        })
 9754    }
 9755
 9756    pub fn select_to_start_of_excerpt(
 9757        &mut self,
 9758        _: &SelectToStartOfExcerpt,
 9759        window: &mut Window,
 9760        cx: &mut Context<Self>,
 9761    ) {
 9762        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 9763            cx.propagate();
 9764            return;
 9765        }
 9766
 9767        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9768            s.move_heads_with(|map, head, _| {
 9769                (
 9770                    movement::start_of_excerpt(map, head, workspace::searchable::Direction::Prev),
 9771                    SelectionGoal::None,
 9772                )
 9773            });
 9774        })
 9775    }
 9776
 9777    pub fn select_to_end_of_excerpt(
 9778        &mut self,
 9779        _: &SelectToEndOfExcerpt,
 9780        window: &mut Window,
 9781        cx: &mut Context<Self>,
 9782    ) {
 9783        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 9784            cx.propagate();
 9785            return;
 9786        }
 9787
 9788        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9789            s.move_heads_with(|map, head, _| {
 9790                (
 9791                    movement::end_of_excerpt(map, head, workspace::searchable::Direction::Next),
 9792                    SelectionGoal::None,
 9793                )
 9794            });
 9795        })
 9796    }
 9797
 9798    pub fn move_to_beginning(
 9799        &mut self,
 9800        _: &MoveToBeginning,
 9801        window: &mut Window,
 9802        cx: &mut Context<Self>,
 9803    ) {
 9804        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 9805            cx.propagate();
 9806            return;
 9807        }
 9808
 9809        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9810            s.select_ranges(vec![0..0]);
 9811        });
 9812    }
 9813
 9814    pub fn select_to_beginning(
 9815        &mut self,
 9816        _: &SelectToBeginning,
 9817        window: &mut Window,
 9818        cx: &mut Context<Self>,
 9819    ) {
 9820        let mut selection = self.selections.last::<Point>(cx);
 9821        selection.set_head(Point::zero(), SelectionGoal::None);
 9822
 9823        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9824            s.select(vec![selection]);
 9825        });
 9826    }
 9827
 9828    pub fn move_to_end(&mut self, _: &MoveToEnd, window: &mut Window, cx: &mut Context<Self>) {
 9829        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 9830            cx.propagate();
 9831            return;
 9832        }
 9833
 9834        let cursor = self.buffer.read(cx).read(cx).len();
 9835        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9836            s.select_ranges(vec![cursor..cursor])
 9837        });
 9838    }
 9839
 9840    pub fn set_nav_history(&mut self, nav_history: Option<ItemNavHistory>) {
 9841        self.nav_history = nav_history;
 9842    }
 9843
 9844    pub fn nav_history(&self) -> Option<&ItemNavHistory> {
 9845        self.nav_history.as_ref()
 9846    }
 9847
 9848    fn push_to_nav_history(
 9849        &mut self,
 9850        cursor_anchor: Anchor,
 9851        new_position: Option<Point>,
 9852        cx: &mut Context<Self>,
 9853    ) {
 9854        if let Some(nav_history) = self.nav_history.as_mut() {
 9855            let buffer = self.buffer.read(cx).read(cx);
 9856            let cursor_position = cursor_anchor.to_point(&buffer);
 9857            let scroll_state = self.scroll_manager.anchor();
 9858            let scroll_top_row = scroll_state.top_row(&buffer);
 9859            drop(buffer);
 9860
 9861            if let Some(new_position) = new_position {
 9862                let row_delta = (new_position.row as i64 - cursor_position.row as i64).abs();
 9863                if row_delta < MIN_NAVIGATION_HISTORY_ROW_DELTA {
 9864                    return;
 9865                }
 9866            }
 9867
 9868            nav_history.push(
 9869                Some(NavigationData {
 9870                    cursor_anchor,
 9871                    cursor_position,
 9872                    scroll_anchor: scroll_state,
 9873                    scroll_top_row,
 9874                }),
 9875                cx,
 9876            );
 9877        }
 9878    }
 9879
 9880    pub fn select_to_end(&mut self, _: &SelectToEnd, window: &mut Window, cx: &mut Context<Self>) {
 9881        let buffer = self.buffer.read(cx).snapshot(cx);
 9882        let mut selection = self.selections.first::<usize>(cx);
 9883        selection.set_head(buffer.len(), SelectionGoal::None);
 9884        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9885            s.select(vec![selection]);
 9886        });
 9887    }
 9888
 9889    pub fn select_all(&mut self, _: &SelectAll, window: &mut Window, cx: &mut Context<Self>) {
 9890        let end = self.buffer.read(cx).read(cx).len();
 9891        self.change_selections(None, window, cx, |s| {
 9892            s.select_ranges(vec![0..end]);
 9893        });
 9894    }
 9895
 9896    pub fn select_line(&mut self, _: &SelectLine, window: &mut Window, cx: &mut Context<Self>) {
 9897        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 9898        let mut selections = self.selections.all::<Point>(cx);
 9899        let max_point = display_map.buffer_snapshot.max_point();
 9900        for selection in &mut selections {
 9901            let rows = selection.spanned_rows(true, &display_map);
 9902            selection.start = Point::new(rows.start.0, 0);
 9903            selection.end = cmp::min(max_point, Point::new(rows.end.0, 0));
 9904            selection.reversed = false;
 9905        }
 9906        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9907            s.select(selections);
 9908        });
 9909    }
 9910
 9911    pub fn split_selection_into_lines(
 9912        &mut self,
 9913        _: &SplitSelectionIntoLines,
 9914        window: &mut Window,
 9915        cx: &mut Context<Self>,
 9916    ) {
 9917        let selections = self
 9918            .selections
 9919            .all::<Point>(cx)
 9920            .into_iter()
 9921            .map(|selection| selection.start..selection.end)
 9922            .collect::<Vec<_>>();
 9923        self.unfold_ranges(&selections, true, true, cx);
 9924
 9925        let mut new_selection_ranges = Vec::new();
 9926        {
 9927            let buffer = self.buffer.read(cx).read(cx);
 9928            for selection in selections {
 9929                for row in selection.start.row..selection.end.row {
 9930                    let cursor = Point::new(row, buffer.line_len(MultiBufferRow(row)));
 9931                    new_selection_ranges.push(cursor..cursor);
 9932                }
 9933
 9934                let is_multiline_selection = selection.start.row != selection.end.row;
 9935                // Don't insert last one if it's a multi-line selection ending at the start of a line,
 9936                // so this action feels more ergonomic when paired with other selection operations
 9937                let should_skip_last = is_multiline_selection && selection.end.column == 0;
 9938                if !should_skip_last {
 9939                    new_selection_ranges.push(selection.end..selection.end);
 9940                }
 9941            }
 9942        }
 9943        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9944            s.select_ranges(new_selection_ranges);
 9945        });
 9946    }
 9947
 9948    pub fn add_selection_above(
 9949        &mut self,
 9950        _: &AddSelectionAbove,
 9951        window: &mut Window,
 9952        cx: &mut Context<Self>,
 9953    ) {
 9954        self.add_selection(true, window, cx);
 9955    }
 9956
 9957    pub fn add_selection_below(
 9958        &mut self,
 9959        _: &AddSelectionBelow,
 9960        window: &mut Window,
 9961        cx: &mut Context<Self>,
 9962    ) {
 9963        self.add_selection(false, window, cx);
 9964    }
 9965
 9966    fn add_selection(&mut self, above: bool, window: &mut Window, cx: &mut Context<Self>) {
 9967        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 9968        let mut selections = self.selections.all::<Point>(cx);
 9969        let text_layout_details = self.text_layout_details(window);
 9970        let mut state = self.add_selections_state.take().unwrap_or_else(|| {
 9971            let oldest_selection = selections.iter().min_by_key(|s| s.id).unwrap().clone();
 9972            let range = oldest_selection.display_range(&display_map).sorted();
 9973
 9974            let start_x = display_map.x_for_display_point(range.start, &text_layout_details);
 9975            let end_x = display_map.x_for_display_point(range.end, &text_layout_details);
 9976            let positions = start_x.min(end_x)..start_x.max(end_x);
 9977
 9978            selections.clear();
 9979            let mut stack = Vec::new();
 9980            for row in range.start.row().0..=range.end.row().0 {
 9981                if let Some(selection) = self.selections.build_columnar_selection(
 9982                    &display_map,
 9983                    DisplayRow(row),
 9984                    &positions,
 9985                    oldest_selection.reversed,
 9986                    &text_layout_details,
 9987                ) {
 9988                    stack.push(selection.id);
 9989                    selections.push(selection);
 9990                }
 9991            }
 9992
 9993            if above {
 9994                stack.reverse();
 9995            }
 9996
 9997            AddSelectionsState { above, stack }
 9998        });
 9999
10000        let last_added_selection = *state.stack.last().unwrap();
10001        let mut new_selections = Vec::new();
10002        if above == state.above {
10003            let end_row = if above {
10004                DisplayRow(0)
10005            } else {
10006                display_map.max_point().row()
10007            };
10008
10009            'outer: for selection in selections {
10010                if selection.id == last_added_selection {
10011                    let range = selection.display_range(&display_map).sorted();
10012                    debug_assert_eq!(range.start.row(), range.end.row());
10013                    let mut row = range.start.row();
10014                    let positions =
10015                        if let SelectionGoal::HorizontalRange { start, end } = selection.goal {
10016                            px(start)..px(end)
10017                        } else {
10018                            let start_x =
10019                                display_map.x_for_display_point(range.start, &text_layout_details);
10020                            let end_x =
10021                                display_map.x_for_display_point(range.end, &text_layout_details);
10022                            start_x.min(end_x)..start_x.max(end_x)
10023                        };
10024
10025                    while row != end_row {
10026                        if above {
10027                            row.0 -= 1;
10028                        } else {
10029                            row.0 += 1;
10030                        }
10031
10032                        if let Some(new_selection) = self.selections.build_columnar_selection(
10033                            &display_map,
10034                            row,
10035                            &positions,
10036                            selection.reversed,
10037                            &text_layout_details,
10038                        ) {
10039                            state.stack.push(new_selection.id);
10040                            if above {
10041                                new_selections.push(new_selection);
10042                                new_selections.push(selection);
10043                            } else {
10044                                new_selections.push(selection);
10045                                new_selections.push(new_selection);
10046                            }
10047
10048                            continue 'outer;
10049                        }
10050                    }
10051                }
10052
10053                new_selections.push(selection);
10054            }
10055        } else {
10056            new_selections = selections;
10057            new_selections.retain(|s| s.id != last_added_selection);
10058            state.stack.pop();
10059        }
10060
10061        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10062            s.select(new_selections);
10063        });
10064        if state.stack.len() > 1 {
10065            self.add_selections_state = Some(state);
10066        }
10067    }
10068
10069    pub fn select_next_match_internal(
10070        &mut self,
10071        display_map: &DisplaySnapshot,
10072        replace_newest: bool,
10073        autoscroll: Option<Autoscroll>,
10074        window: &mut Window,
10075        cx: &mut Context<Self>,
10076    ) -> Result<()> {
10077        fn select_next_match_ranges(
10078            this: &mut Editor,
10079            range: Range<usize>,
10080            replace_newest: bool,
10081            auto_scroll: Option<Autoscroll>,
10082            window: &mut Window,
10083            cx: &mut Context<Editor>,
10084        ) {
10085            this.unfold_ranges(&[range.clone()], false, true, cx);
10086            this.change_selections(auto_scroll, window, cx, |s| {
10087                if replace_newest {
10088                    s.delete(s.newest_anchor().id);
10089                }
10090                s.insert_range(range.clone());
10091            });
10092        }
10093
10094        let buffer = &display_map.buffer_snapshot;
10095        let mut selections = self.selections.all::<usize>(cx);
10096        if let Some(mut select_next_state) = self.select_next_state.take() {
10097            let query = &select_next_state.query;
10098            if !select_next_state.done {
10099                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
10100                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
10101                let mut next_selected_range = None;
10102
10103                let bytes_after_last_selection =
10104                    buffer.bytes_in_range(last_selection.end..buffer.len());
10105                let bytes_before_first_selection = buffer.bytes_in_range(0..first_selection.start);
10106                let query_matches = query
10107                    .stream_find_iter(bytes_after_last_selection)
10108                    .map(|result| (last_selection.end, result))
10109                    .chain(
10110                        query
10111                            .stream_find_iter(bytes_before_first_selection)
10112                            .map(|result| (0, result)),
10113                    );
10114
10115                for (start_offset, query_match) in query_matches {
10116                    let query_match = query_match.unwrap(); // can only fail due to I/O
10117                    let offset_range =
10118                        start_offset + query_match.start()..start_offset + query_match.end();
10119                    let display_range = offset_range.start.to_display_point(display_map)
10120                        ..offset_range.end.to_display_point(display_map);
10121
10122                    if !select_next_state.wordwise
10123                        || (!movement::is_inside_word(display_map, display_range.start)
10124                            && !movement::is_inside_word(display_map, display_range.end))
10125                    {
10126                        // TODO: This is n^2, because we might check all the selections
10127                        if !selections
10128                            .iter()
10129                            .any(|selection| selection.range().overlaps(&offset_range))
10130                        {
10131                            next_selected_range = Some(offset_range);
10132                            break;
10133                        }
10134                    }
10135                }
10136
10137                if let Some(next_selected_range) = next_selected_range {
10138                    select_next_match_ranges(
10139                        self,
10140                        next_selected_range,
10141                        replace_newest,
10142                        autoscroll,
10143                        window,
10144                        cx,
10145                    );
10146                } else {
10147                    select_next_state.done = true;
10148                }
10149            }
10150
10151            self.select_next_state = Some(select_next_state);
10152        } else {
10153            let mut only_carets = true;
10154            let mut same_text_selected = true;
10155            let mut selected_text = None;
10156
10157            let mut selections_iter = selections.iter().peekable();
10158            while let Some(selection) = selections_iter.next() {
10159                if selection.start != selection.end {
10160                    only_carets = false;
10161                }
10162
10163                if same_text_selected {
10164                    if selected_text.is_none() {
10165                        selected_text =
10166                            Some(buffer.text_for_range(selection.range()).collect::<String>());
10167                    }
10168
10169                    if let Some(next_selection) = selections_iter.peek() {
10170                        if next_selection.range().len() == selection.range().len() {
10171                            let next_selected_text = buffer
10172                                .text_for_range(next_selection.range())
10173                                .collect::<String>();
10174                            if Some(next_selected_text) != selected_text {
10175                                same_text_selected = false;
10176                                selected_text = None;
10177                            }
10178                        } else {
10179                            same_text_selected = false;
10180                            selected_text = None;
10181                        }
10182                    }
10183                }
10184            }
10185
10186            if only_carets {
10187                for selection in &mut selections {
10188                    let word_range = movement::surrounding_word(
10189                        display_map,
10190                        selection.start.to_display_point(display_map),
10191                    );
10192                    selection.start = word_range.start.to_offset(display_map, Bias::Left);
10193                    selection.end = word_range.end.to_offset(display_map, Bias::Left);
10194                    selection.goal = SelectionGoal::None;
10195                    selection.reversed = false;
10196                    select_next_match_ranges(
10197                        self,
10198                        selection.start..selection.end,
10199                        replace_newest,
10200                        autoscroll,
10201                        window,
10202                        cx,
10203                    );
10204                }
10205
10206                if selections.len() == 1 {
10207                    let selection = selections
10208                        .last()
10209                        .expect("ensured that there's only one selection");
10210                    let query = buffer
10211                        .text_for_range(selection.start..selection.end)
10212                        .collect::<String>();
10213                    let is_empty = query.is_empty();
10214                    let select_state = SelectNextState {
10215                        query: AhoCorasick::new(&[query])?,
10216                        wordwise: true,
10217                        done: is_empty,
10218                    };
10219                    self.select_next_state = Some(select_state);
10220                } else {
10221                    self.select_next_state = None;
10222                }
10223            } else if let Some(selected_text) = selected_text {
10224                self.select_next_state = Some(SelectNextState {
10225                    query: AhoCorasick::new(&[selected_text])?,
10226                    wordwise: false,
10227                    done: false,
10228                });
10229                self.select_next_match_internal(
10230                    display_map,
10231                    replace_newest,
10232                    autoscroll,
10233                    window,
10234                    cx,
10235                )?;
10236            }
10237        }
10238        Ok(())
10239    }
10240
10241    pub fn select_all_matches(
10242        &mut self,
10243        _action: &SelectAllMatches,
10244        window: &mut Window,
10245        cx: &mut Context<Self>,
10246    ) -> Result<()> {
10247        self.push_to_selection_history();
10248        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
10249
10250        self.select_next_match_internal(&display_map, false, None, window, cx)?;
10251        let Some(select_next_state) = self.select_next_state.as_mut() else {
10252            return Ok(());
10253        };
10254        if select_next_state.done {
10255            return Ok(());
10256        }
10257
10258        let mut new_selections = self.selections.all::<usize>(cx);
10259
10260        let buffer = &display_map.buffer_snapshot;
10261        let query_matches = select_next_state
10262            .query
10263            .stream_find_iter(buffer.bytes_in_range(0..buffer.len()));
10264
10265        for query_match in query_matches {
10266            let query_match = query_match.unwrap(); // can only fail due to I/O
10267            let offset_range = query_match.start()..query_match.end();
10268            let display_range = offset_range.start.to_display_point(&display_map)
10269                ..offset_range.end.to_display_point(&display_map);
10270
10271            if !select_next_state.wordwise
10272                || (!movement::is_inside_word(&display_map, display_range.start)
10273                    && !movement::is_inside_word(&display_map, display_range.end))
10274            {
10275                self.selections.change_with(cx, |selections| {
10276                    new_selections.push(Selection {
10277                        id: selections.new_selection_id(),
10278                        start: offset_range.start,
10279                        end: offset_range.end,
10280                        reversed: false,
10281                        goal: SelectionGoal::None,
10282                    });
10283                });
10284            }
10285        }
10286
10287        new_selections.sort_by_key(|selection| selection.start);
10288        let mut ix = 0;
10289        while ix + 1 < new_selections.len() {
10290            let current_selection = &new_selections[ix];
10291            let next_selection = &new_selections[ix + 1];
10292            if current_selection.range().overlaps(&next_selection.range()) {
10293                if current_selection.id < next_selection.id {
10294                    new_selections.remove(ix + 1);
10295                } else {
10296                    new_selections.remove(ix);
10297                }
10298            } else {
10299                ix += 1;
10300            }
10301        }
10302
10303        let reversed = self.selections.oldest::<usize>(cx).reversed;
10304
10305        for selection in new_selections.iter_mut() {
10306            selection.reversed = reversed;
10307        }
10308
10309        select_next_state.done = true;
10310        self.unfold_ranges(
10311            &new_selections
10312                .iter()
10313                .map(|selection| selection.range())
10314                .collect::<Vec<_>>(),
10315            false,
10316            false,
10317            cx,
10318        );
10319        self.change_selections(Some(Autoscroll::fit()), window, cx, |selections| {
10320            selections.select(new_selections)
10321        });
10322
10323        Ok(())
10324    }
10325
10326    pub fn select_next(
10327        &mut self,
10328        action: &SelectNext,
10329        window: &mut Window,
10330        cx: &mut Context<Self>,
10331    ) -> Result<()> {
10332        self.push_to_selection_history();
10333        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
10334        self.select_next_match_internal(
10335            &display_map,
10336            action.replace_newest,
10337            Some(Autoscroll::newest()),
10338            window,
10339            cx,
10340        )?;
10341        Ok(())
10342    }
10343
10344    pub fn select_previous(
10345        &mut self,
10346        action: &SelectPrevious,
10347        window: &mut Window,
10348        cx: &mut Context<Self>,
10349    ) -> Result<()> {
10350        self.push_to_selection_history();
10351        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
10352        let buffer = &display_map.buffer_snapshot;
10353        let mut selections = self.selections.all::<usize>(cx);
10354        if let Some(mut select_prev_state) = self.select_prev_state.take() {
10355            let query = &select_prev_state.query;
10356            if !select_prev_state.done {
10357                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
10358                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
10359                let mut next_selected_range = None;
10360                // When we're iterating matches backwards, the oldest match will actually be the furthest one in the buffer.
10361                let bytes_before_last_selection =
10362                    buffer.reversed_bytes_in_range(0..last_selection.start);
10363                let bytes_after_first_selection =
10364                    buffer.reversed_bytes_in_range(first_selection.end..buffer.len());
10365                let query_matches = query
10366                    .stream_find_iter(bytes_before_last_selection)
10367                    .map(|result| (last_selection.start, result))
10368                    .chain(
10369                        query
10370                            .stream_find_iter(bytes_after_first_selection)
10371                            .map(|result| (buffer.len(), result)),
10372                    );
10373                for (end_offset, query_match) in query_matches {
10374                    let query_match = query_match.unwrap(); // can only fail due to I/O
10375                    let offset_range =
10376                        end_offset - query_match.end()..end_offset - query_match.start();
10377                    let display_range = offset_range.start.to_display_point(&display_map)
10378                        ..offset_range.end.to_display_point(&display_map);
10379
10380                    if !select_prev_state.wordwise
10381                        || (!movement::is_inside_word(&display_map, display_range.start)
10382                            && !movement::is_inside_word(&display_map, display_range.end))
10383                    {
10384                        next_selected_range = Some(offset_range);
10385                        break;
10386                    }
10387                }
10388
10389                if let Some(next_selected_range) = next_selected_range {
10390                    self.unfold_ranges(&[next_selected_range.clone()], false, true, cx);
10391                    self.change_selections(Some(Autoscroll::newest()), window, cx, |s| {
10392                        if action.replace_newest {
10393                            s.delete(s.newest_anchor().id);
10394                        }
10395                        s.insert_range(next_selected_range);
10396                    });
10397                } else {
10398                    select_prev_state.done = true;
10399                }
10400            }
10401
10402            self.select_prev_state = Some(select_prev_state);
10403        } else {
10404            let mut only_carets = true;
10405            let mut same_text_selected = true;
10406            let mut selected_text = None;
10407
10408            let mut selections_iter = selections.iter().peekable();
10409            while let Some(selection) = selections_iter.next() {
10410                if selection.start != selection.end {
10411                    only_carets = false;
10412                }
10413
10414                if same_text_selected {
10415                    if selected_text.is_none() {
10416                        selected_text =
10417                            Some(buffer.text_for_range(selection.range()).collect::<String>());
10418                    }
10419
10420                    if let Some(next_selection) = selections_iter.peek() {
10421                        if next_selection.range().len() == selection.range().len() {
10422                            let next_selected_text = buffer
10423                                .text_for_range(next_selection.range())
10424                                .collect::<String>();
10425                            if Some(next_selected_text) != selected_text {
10426                                same_text_selected = false;
10427                                selected_text = None;
10428                            }
10429                        } else {
10430                            same_text_selected = false;
10431                            selected_text = None;
10432                        }
10433                    }
10434                }
10435            }
10436
10437            if only_carets {
10438                for selection in &mut selections {
10439                    let word_range = movement::surrounding_word(
10440                        &display_map,
10441                        selection.start.to_display_point(&display_map),
10442                    );
10443                    selection.start = word_range.start.to_offset(&display_map, Bias::Left);
10444                    selection.end = word_range.end.to_offset(&display_map, Bias::Left);
10445                    selection.goal = SelectionGoal::None;
10446                    selection.reversed = false;
10447                }
10448                if selections.len() == 1 {
10449                    let selection = selections
10450                        .last()
10451                        .expect("ensured that there's only one selection");
10452                    let query = buffer
10453                        .text_for_range(selection.start..selection.end)
10454                        .collect::<String>();
10455                    let is_empty = query.is_empty();
10456                    let select_state = SelectNextState {
10457                        query: AhoCorasick::new(&[query.chars().rev().collect::<String>()])?,
10458                        wordwise: true,
10459                        done: is_empty,
10460                    };
10461                    self.select_prev_state = Some(select_state);
10462                } else {
10463                    self.select_prev_state = None;
10464                }
10465
10466                self.unfold_ranges(
10467                    &selections.iter().map(|s| s.range()).collect::<Vec<_>>(),
10468                    false,
10469                    true,
10470                    cx,
10471                );
10472                self.change_selections(Some(Autoscroll::newest()), window, cx, |s| {
10473                    s.select(selections);
10474                });
10475            } else if let Some(selected_text) = selected_text {
10476                self.select_prev_state = Some(SelectNextState {
10477                    query: AhoCorasick::new(&[selected_text.chars().rev().collect::<String>()])?,
10478                    wordwise: false,
10479                    done: false,
10480                });
10481                self.select_previous(action, window, cx)?;
10482            }
10483        }
10484        Ok(())
10485    }
10486
10487    pub fn toggle_comments(
10488        &mut self,
10489        action: &ToggleComments,
10490        window: &mut Window,
10491        cx: &mut Context<Self>,
10492    ) {
10493        if self.read_only(cx) {
10494            return;
10495        }
10496        let text_layout_details = &self.text_layout_details(window);
10497        self.transact(window, cx, |this, window, cx| {
10498            let mut selections = this.selections.all::<MultiBufferPoint>(cx);
10499            let mut edits = Vec::new();
10500            let mut selection_edit_ranges = Vec::new();
10501            let mut last_toggled_row = None;
10502            let snapshot = this.buffer.read(cx).read(cx);
10503            let empty_str: Arc<str> = Arc::default();
10504            let mut suffixes_inserted = Vec::new();
10505            let ignore_indent = action.ignore_indent;
10506
10507            fn comment_prefix_range(
10508                snapshot: &MultiBufferSnapshot,
10509                row: MultiBufferRow,
10510                comment_prefix: &str,
10511                comment_prefix_whitespace: &str,
10512                ignore_indent: bool,
10513            ) -> Range<Point> {
10514                let indent_size = if ignore_indent {
10515                    0
10516                } else {
10517                    snapshot.indent_size_for_line(row).len
10518                };
10519
10520                let start = Point::new(row.0, indent_size);
10521
10522                let mut line_bytes = snapshot
10523                    .bytes_in_range(start..snapshot.max_point())
10524                    .flatten()
10525                    .copied();
10526
10527                // If this line currently begins with the line comment prefix, then record
10528                // the range containing the prefix.
10529                if line_bytes
10530                    .by_ref()
10531                    .take(comment_prefix.len())
10532                    .eq(comment_prefix.bytes())
10533                {
10534                    // Include any whitespace that matches the comment prefix.
10535                    let matching_whitespace_len = line_bytes
10536                        .zip(comment_prefix_whitespace.bytes())
10537                        .take_while(|(a, b)| a == b)
10538                        .count() as u32;
10539                    let end = Point::new(
10540                        start.row,
10541                        start.column + comment_prefix.len() as u32 + matching_whitespace_len,
10542                    );
10543                    start..end
10544                } else {
10545                    start..start
10546                }
10547            }
10548
10549            fn comment_suffix_range(
10550                snapshot: &MultiBufferSnapshot,
10551                row: MultiBufferRow,
10552                comment_suffix: &str,
10553                comment_suffix_has_leading_space: bool,
10554            ) -> Range<Point> {
10555                let end = Point::new(row.0, snapshot.line_len(row));
10556                let suffix_start_column = end.column.saturating_sub(comment_suffix.len() as u32);
10557
10558                let mut line_end_bytes = snapshot
10559                    .bytes_in_range(Point::new(end.row, suffix_start_column.saturating_sub(1))..end)
10560                    .flatten()
10561                    .copied();
10562
10563                let leading_space_len = if suffix_start_column > 0
10564                    && line_end_bytes.next() == Some(b' ')
10565                    && comment_suffix_has_leading_space
10566                {
10567                    1
10568                } else {
10569                    0
10570                };
10571
10572                // If this line currently begins with the line comment prefix, then record
10573                // the range containing the prefix.
10574                if line_end_bytes.by_ref().eq(comment_suffix.bytes()) {
10575                    let start = Point::new(end.row, suffix_start_column - leading_space_len);
10576                    start..end
10577                } else {
10578                    end..end
10579                }
10580            }
10581
10582            // TODO: Handle selections that cross excerpts
10583            for selection in &mut selections {
10584                let start_column = snapshot
10585                    .indent_size_for_line(MultiBufferRow(selection.start.row))
10586                    .len;
10587                let language = if let Some(language) =
10588                    snapshot.language_scope_at(Point::new(selection.start.row, start_column))
10589                {
10590                    language
10591                } else {
10592                    continue;
10593                };
10594
10595                selection_edit_ranges.clear();
10596
10597                // If multiple selections contain a given row, avoid processing that
10598                // row more than once.
10599                let mut start_row = MultiBufferRow(selection.start.row);
10600                if last_toggled_row == Some(start_row) {
10601                    start_row = start_row.next_row();
10602                }
10603                let end_row =
10604                    if selection.end.row > selection.start.row && selection.end.column == 0 {
10605                        MultiBufferRow(selection.end.row - 1)
10606                    } else {
10607                        MultiBufferRow(selection.end.row)
10608                    };
10609                last_toggled_row = Some(end_row);
10610
10611                if start_row > end_row {
10612                    continue;
10613                }
10614
10615                // If the language has line comments, toggle those.
10616                let mut full_comment_prefixes = language.line_comment_prefixes().to_vec();
10617
10618                // If ignore_indent is set, trim spaces from the right side of all full_comment_prefixes
10619                if ignore_indent {
10620                    full_comment_prefixes = full_comment_prefixes
10621                        .into_iter()
10622                        .map(|s| Arc::from(s.trim_end()))
10623                        .collect();
10624                }
10625
10626                if !full_comment_prefixes.is_empty() {
10627                    let first_prefix = full_comment_prefixes
10628                        .first()
10629                        .expect("prefixes is non-empty");
10630                    let prefix_trimmed_lengths = full_comment_prefixes
10631                        .iter()
10632                        .map(|p| p.trim_end_matches(' ').len())
10633                        .collect::<SmallVec<[usize; 4]>>();
10634
10635                    let mut all_selection_lines_are_comments = true;
10636
10637                    for row in start_row.0..=end_row.0 {
10638                        let row = MultiBufferRow(row);
10639                        if start_row < end_row && snapshot.is_line_blank(row) {
10640                            continue;
10641                        }
10642
10643                        let prefix_range = full_comment_prefixes
10644                            .iter()
10645                            .zip(prefix_trimmed_lengths.iter().copied())
10646                            .map(|(prefix, trimmed_prefix_len)| {
10647                                comment_prefix_range(
10648                                    snapshot.deref(),
10649                                    row,
10650                                    &prefix[..trimmed_prefix_len],
10651                                    &prefix[trimmed_prefix_len..],
10652                                    ignore_indent,
10653                                )
10654                            })
10655                            .max_by_key(|range| range.end.column - range.start.column)
10656                            .expect("prefixes is non-empty");
10657
10658                        if prefix_range.is_empty() {
10659                            all_selection_lines_are_comments = false;
10660                        }
10661
10662                        selection_edit_ranges.push(prefix_range);
10663                    }
10664
10665                    if all_selection_lines_are_comments {
10666                        edits.extend(
10667                            selection_edit_ranges
10668                                .iter()
10669                                .cloned()
10670                                .map(|range| (range, empty_str.clone())),
10671                        );
10672                    } else {
10673                        let min_column = selection_edit_ranges
10674                            .iter()
10675                            .map(|range| range.start.column)
10676                            .min()
10677                            .unwrap_or(0);
10678                        edits.extend(selection_edit_ranges.iter().map(|range| {
10679                            let position = Point::new(range.start.row, min_column);
10680                            (position..position, first_prefix.clone())
10681                        }));
10682                    }
10683                } else if let Some((full_comment_prefix, comment_suffix)) =
10684                    language.block_comment_delimiters()
10685                {
10686                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
10687                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
10688                    let prefix_range = comment_prefix_range(
10689                        snapshot.deref(),
10690                        start_row,
10691                        comment_prefix,
10692                        comment_prefix_whitespace,
10693                        ignore_indent,
10694                    );
10695                    let suffix_range = comment_suffix_range(
10696                        snapshot.deref(),
10697                        end_row,
10698                        comment_suffix.trim_start_matches(' '),
10699                        comment_suffix.starts_with(' '),
10700                    );
10701
10702                    if prefix_range.is_empty() || suffix_range.is_empty() {
10703                        edits.push((
10704                            prefix_range.start..prefix_range.start,
10705                            full_comment_prefix.clone(),
10706                        ));
10707                        edits.push((suffix_range.end..suffix_range.end, comment_suffix.clone()));
10708                        suffixes_inserted.push((end_row, comment_suffix.len()));
10709                    } else {
10710                        edits.push((prefix_range, empty_str.clone()));
10711                        edits.push((suffix_range, empty_str.clone()));
10712                    }
10713                } else {
10714                    continue;
10715                }
10716            }
10717
10718            drop(snapshot);
10719            this.buffer.update(cx, |buffer, cx| {
10720                buffer.edit(edits, None, cx);
10721            });
10722
10723            // Adjust selections so that they end before any comment suffixes that
10724            // were inserted.
10725            let mut suffixes_inserted = suffixes_inserted.into_iter().peekable();
10726            let mut selections = this.selections.all::<Point>(cx);
10727            let snapshot = this.buffer.read(cx).read(cx);
10728            for selection in &mut selections {
10729                while let Some((row, suffix_len)) = suffixes_inserted.peek().copied() {
10730                    match row.cmp(&MultiBufferRow(selection.end.row)) {
10731                        Ordering::Less => {
10732                            suffixes_inserted.next();
10733                            continue;
10734                        }
10735                        Ordering::Greater => break,
10736                        Ordering::Equal => {
10737                            if selection.end.column == snapshot.line_len(row) {
10738                                if selection.is_empty() {
10739                                    selection.start.column -= suffix_len as u32;
10740                                }
10741                                selection.end.column -= suffix_len as u32;
10742                            }
10743                            break;
10744                        }
10745                    }
10746                }
10747            }
10748
10749            drop(snapshot);
10750            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10751                s.select(selections)
10752            });
10753
10754            let selections = this.selections.all::<Point>(cx);
10755            let selections_on_single_row = selections.windows(2).all(|selections| {
10756                selections[0].start.row == selections[1].start.row
10757                    && selections[0].end.row == selections[1].end.row
10758                    && selections[0].start.row == selections[0].end.row
10759            });
10760            let selections_selecting = selections
10761                .iter()
10762                .any(|selection| selection.start != selection.end);
10763            let advance_downwards = action.advance_downwards
10764                && selections_on_single_row
10765                && !selections_selecting
10766                && !matches!(this.mode, EditorMode::SingleLine { .. });
10767
10768            if advance_downwards {
10769                let snapshot = this.buffer.read(cx).snapshot(cx);
10770
10771                this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10772                    s.move_cursors_with(|display_snapshot, display_point, _| {
10773                        let mut point = display_point.to_point(display_snapshot);
10774                        point.row += 1;
10775                        point = snapshot.clip_point(point, Bias::Left);
10776                        let display_point = point.to_display_point(display_snapshot);
10777                        let goal = SelectionGoal::HorizontalPosition(
10778                            display_snapshot
10779                                .x_for_display_point(display_point, text_layout_details)
10780                                .into(),
10781                        );
10782                        (display_point, goal)
10783                    })
10784                });
10785            }
10786        });
10787    }
10788
10789    pub fn select_enclosing_symbol(
10790        &mut self,
10791        _: &SelectEnclosingSymbol,
10792        window: &mut Window,
10793        cx: &mut Context<Self>,
10794    ) {
10795        let buffer = self.buffer.read(cx).snapshot(cx);
10796        let old_selections = self.selections.all::<usize>(cx).into_boxed_slice();
10797
10798        fn update_selection(
10799            selection: &Selection<usize>,
10800            buffer_snap: &MultiBufferSnapshot,
10801        ) -> Option<Selection<usize>> {
10802            let cursor = selection.head();
10803            let (_buffer_id, symbols) = buffer_snap.symbols_containing(cursor, None)?;
10804            for symbol in symbols.iter().rev() {
10805                let start = symbol.range.start.to_offset(buffer_snap);
10806                let end = symbol.range.end.to_offset(buffer_snap);
10807                let new_range = start..end;
10808                if start < selection.start || end > selection.end {
10809                    return Some(Selection {
10810                        id: selection.id,
10811                        start: new_range.start,
10812                        end: new_range.end,
10813                        goal: SelectionGoal::None,
10814                        reversed: selection.reversed,
10815                    });
10816                }
10817            }
10818            None
10819        }
10820
10821        let mut selected_larger_symbol = false;
10822        let new_selections = old_selections
10823            .iter()
10824            .map(|selection| match update_selection(selection, &buffer) {
10825                Some(new_selection) => {
10826                    if new_selection.range() != selection.range() {
10827                        selected_larger_symbol = true;
10828                    }
10829                    new_selection
10830                }
10831                None => selection.clone(),
10832            })
10833            .collect::<Vec<_>>();
10834
10835        if selected_larger_symbol {
10836            self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10837                s.select(new_selections);
10838            });
10839        }
10840    }
10841
10842    pub fn select_larger_syntax_node(
10843        &mut self,
10844        _: &SelectLargerSyntaxNode,
10845        window: &mut Window,
10846        cx: &mut Context<Self>,
10847    ) {
10848        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
10849        let buffer = self.buffer.read(cx).snapshot(cx);
10850        let old_selections = self.selections.all::<usize>(cx).into_boxed_slice();
10851
10852        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
10853        let mut selected_larger_node = false;
10854        let new_selections = old_selections
10855            .iter()
10856            .map(|selection| {
10857                let old_range = selection.start..selection.end;
10858                let mut new_range = old_range.clone();
10859                let mut new_node = None;
10860                while let Some((node, containing_range)) = buffer.syntax_ancestor(new_range.clone())
10861                {
10862                    new_node = Some(node);
10863                    new_range = match containing_range {
10864                        MultiOrSingleBufferOffsetRange::Single(_) => break,
10865                        MultiOrSingleBufferOffsetRange::Multi(range) => range,
10866                    };
10867                    if !display_map.intersects_fold(new_range.start)
10868                        && !display_map.intersects_fold(new_range.end)
10869                    {
10870                        break;
10871                    }
10872                }
10873
10874                if let Some(node) = new_node {
10875                    // Log the ancestor, to support using this action as a way to explore TreeSitter
10876                    // nodes. Parent and grandparent are also logged because this operation will not
10877                    // visit nodes that have the same range as their parent.
10878                    log::info!("Node: {node:?}");
10879                    let parent = node.parent();
10880                    log::info!("Parent: {parent:?}");
10881                    let grandparent = parent.and_then(|x| x.parent());
10882                    log::info!("Grandparent: {grandparent:?}");
10883                }
10884
10885                selected_larger_node |= new_range != old_range;
10886                Selection {
10887                    id: selection.id,
10888                    start: new_range.start,
10889                    end: new_range.end,
10890                    goal: SelectionGoal::None,
10891                    reversed: selection.reversed,
10892                }
10893            })
10894            .collect::<Vec<_>>();
10895
10896        if selected_larger_node {
10897            stack.push(old_selections);
10898            self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10899                s.select(new_selections);
10900            });
10901        }
10902        self.select_larger_syntax_node_stack = stack;
10903    }
10904
10905    pub fn select_smaller_syntax_node(
10906        &mut self,
10907        _: &SelectSmallerSyntaxNode,
10908        window: &mut Window,
10909        cx: &mut Context<Self>,
10910    ) {
10911        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
10912        if let Some(selections) = stack.pop() {
10913            self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10914                s.select(selections.to_vec());
10915            });
10916        }
10917        self.select_larger_syntax_node_stack = stack;
10918    }
10919
10920    fn refresh_runnables(&mut self, window: &mut Window, cx: &mut Context<Self>) -> Task<()> {
10921        if !EditorSettings::get_global(cx).gutter.runnables {
10922            self.clear_tasks();
10923            return Task::ready(());
10924        }
10925        let project = self.project.as_ref().map(Entity::downgrade);
10926        cx.spawn_in(window, |this, mut cx| async move {
10927            cx.background_executor().timer(UPDATE_DEBOUNCE).await;
10928            let Some(project) = project.and_then(|p| p.upgrade()) else {
10929                return;
10930            };
10931            let Ok(display_snapshot) = this.update(&mut cx, |this, cx| {
10932                this.display_map.update(cx, |map, cx| map.snapshot(cx))
10933            }) else {
10934                return;
10935            };
10936
10937            let hide_runnables = project
10938                .update(&mut cx, |project, cx| {
10939                    // Do not display any test indicators in non-dev server remote projects.
10940                    project.is_via_collab() && project.ssh_connection_string(cx).is_none()
10941                })
10942                .unwrap_or(true);
10943            if hide_runnables {
10944                return;
10945            }
10946            let new_rows =
10947                cx.background_spawn({
10948                    let snapshot = display_snapshot.clone();
10949                    async move {
10950                        Self::fetch_runnable_ranges(&snapshot, Anchor::min()..Anchor::max())
10951                    }
10952                })
10953                    .await;
10954
10955            let rows = Self::runnable_rows(project, display_snapshot, new_rows, cx.clone());
10956            this.update(&mut cx, |this, _| {
10957                this.clear_tasks();
10958                for (key, value) in rows {
10959                    this.insert_tasks(key, value);
10960                }
10961            })
10962            .ok();
10963        })
10964    }
10965    fn fetch_runnable_ranges(
10966        snapshot: &DisplaySnapshot,
10967        range: Range<Anchor>,
10968    ) -> Vec<language::RunnableRange> {
10969        snapshot.buffer_snapshot.runnable_ranges(range).collect()
10970    }
10971
10972    fn runnable_rows(
10973        project: Entity<Project>,
10974        snapshot: DisplaySnapshot,
10975        runnable_ranges: Vec<RunnableRange>,
10976        mut cx: AsyncWindowContext,
10977    ) -> Vec<((BufferId, u32), RunnableTasks)> {
10978        runnable_ranges
10979            .into_iter()
10980            .filter_map(|mut runnable| {
10981                let tasks = cx
10982                    .update(|_, cx| Self::templates_with_tags(&project, &mut runnable.runnable, cx))
10983                    .ok()?;
10984                if tasks.is_empty() {
10985                    return None;
10986                }
10987
10988                let point = runnable.run_range.start.to_point(&snapshot.buffer_snapshot);
10989
10990                let row = snapshot
10991                    .buffer_snapshot
10992                    .buffer_line_for_row(MultiBufferRow(point.row))?
10993                    .1
10994                    .start
10995                    .row;
10996
10997                let context_range =
10998                    BufferOffset(runnable.full_range.start)..BufferOffset(runnable.full_range.end);
10999                Some((
11000                    (runnable.buffer_id, row),
11001                    RunnableTasks {
11002                        templates: tasks,
11003                        offset: snapshot
11004                            .buffer_snapshot
11005                            .anchor_before(runnable.run_range.start),
11006                        context_range,
11007                        column: point.column,
11008                        extra_variables: runnable.extra_captures,
11009                    },
11010                ))
11011            })
11012            .collect()
11013    }
11014
11015    fn templates_with_tags(
11016        project: &Entity<Project>,
11017        runnable: &mut Runnable,
11018        cx: &mut App,
11019    ) -> Vec<(TaskSourceKind, TaskTemplate)> {
11020        let (inventory, worktree_id, file) = project.read_with(cx, |project, cx| {
11021            let (worktree_id, file) = project
11022                .buffer_for_id(runnable.buffer, cx)
11023                .and_then(|buffer| buffer.read(cx).file())
11024                .map(|file| (file.worktree_id(cx), file.clone()))
11025                .unzip();
11026
11027            (
11028                project.task_store().read(cx).task_inventory().cloned(),
11029                worktree_id,
11030                file,
11031            )
11032        });
11033
11034        let tags = mem::take(&mut runnable.tags);
11035        let mut tags: Vec<_> = tags
11036            .into_iter()
11037            .flat_map(|tag| {
11038                let tag = tag.0.clone();
11039                inventory
11040                    .as_ref()
11041                    .into_iter()
11042                    .flat_map(|inventory| {
11043                        inventory.read(cx).list_tasks(
11044                            file.clone(),
11045                            Some(runnable.language.clone()),
11046                            worktree_id,
11047                            cx,
11048                        )
11049                    })
11050                    .filter(move |(_, template)| {
11051                        template.tags.iter().any(|source_tag| source_tag == &tag)
11052                    })
11053            })
11054            .sorted_by_key(|(kind, _)| kind.to_owned())
11055            .collect();
11056        if let Some((leading_tag_source, _)) = tags.first() {
11057            // Strongest source wins; if we have worktree tag binding, prefer that to
11058            // global and language bindings;
11059            // if we have a global binding, prefer that to language binding.
11060            let first_mismatch = tags
11061                .iter()
11062                .position(|(tag_source, _)| tag_source != leading_tag_source);
11063            if let Some(index) = first_mismatch {
11064                tags.truncate(index);
11065            }
11066        }
11067
11068        tags
11069    }
11070
11071    pub fn move_to_enclosing_bracket(
11072        &mut self,
11073        _: &MoveToEnclosingBracket,
11074        window: &mut Window,
11075        cx: &mut Context<Self>,
11076    ) {
11077        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
11078            s.move_offsets_with(|snapshot, selection| {
11079                let Some(enclosing_bracket_ranges) =
11080                    snapshot.enclosing_bracket_ranges(selection.start..selection.end)
11081                else {
11082                    return;
11083                };
11084
11085                let mut best_length = usize::MAX;
11086                let mut best_inside = false;
11087                let mut best_in_bracket_range = false;
11088                let mut best_destination = None;
11089                for (open, close) in enclosing_bracket_ranges {
11090                    let close = close.to_inclusive();
11091                    let length = close.end() - open.start;
11092                    let inside = selection.start >= open.end && selection.end <= *close.start();
11093                    let in_bracket_range = open.to_inclusive().contains(&selection.head())
11094                        || close.contains(&selection.head());
11095
11096                    // If best is next to a bracket and current isn't, skip
11097                    if !in_bracket_range && best_in_bracket_range {
11098                        continue;
11099                    }
11100
11101                    // Prefer smaller lengths unless best is inside and current isn't
11102                    if length > best_length && (best_inside || !inside) {
11103                        continue;
11104                    }
11105
11106                    best_length = length;
11107                    best_inside = inside;
11108                    best_in_bracket_range = in_bracket_range;
11109                    best_destination = Some(
11110                        if close.contains(&selection.start) && close.contains(&selection.end) {
11111                            if inside {
11112                                open.end
11113                            } else {
11114                                open.start
11115                            }
11116                        } else if inside {
11117                            *close.start()
11118                        } else {
11119                            *close.end()
11120                        },
11121                    );
11122                }
11123
11124                if let Some(destination) = best_destination {
11125                    selection.collapse_to(destination, SelectionGoal::None);
11126                }
11127            })
11128        });
11129    }
11130
11131    pub fn undo_selection(
11132        &mut self,
11133        _: &UndoSelection,
11134        window: &mut Window,
11135        cx: &mut Context<Self>,
11136    ) {
11137        self.end_selection(window, cx);
11138        self.selection_history.mode = SelectionHistoryMode::Undoing;
11139        if let Some(entry) = self.selection_history.undo_stack.pop_back() {
11140            self.change_selections(None, window, cx, |s| {
11141                s.select_anchors(entry.selections.to_vec())
11142            });
11143            self.select_next_state = entry.select_next_state;
11144            self.select_prev_state = entry.select_prev_state;
11145            self.add_selections_state = entry.add_selections_state;
11146            self.request_autoscroll(Autoscroll::newest(), cx);
11147        }
11148        self.selection_history.mode = SelectionHistoryMode::Normal;
11149    }
11150
11151    pub fn redo_selection(
11152        &mut self,
11153        _: &RedoSelection,
11154        window: &mut Window,
11155        cx: &mut Context<Self>,
11156    ) {
11157        self.end_selection(window, cx);
11158        self.selection_history.mode = SelectionHistoryMode::Redoing;
11159        if let Some(entry) = self.selection_history.redo_stack.pop_back() {
11160            self.change_selections(None, window, cx, |s| {
11161                s.select_anchors(entry.selections.to_vec())
11162            });
11163            self.select_next_state = entry.select_next_state;
11164            self.select_prev_state = entry.select_prev_state;
11165            self.add_selections_state = entry.add_selections_state;
11166            self.request_autoscroll(Autoscroll::newest(), cx);
11167        }
11168        self.selection_history.mode = SelectionHistoryMode::Normal;
11169    }
11170
11171    pub fn expand_excerpts(
11172        &mut self,
11173        action: &ExpandExcerpts,
11174        _: &mut Window,
11175        cx: &mut Context<Self>,
11176    ) {
11177        self.expand_excerpts_for_direction(action.lines, ExpandExcerptDirection::UpAndDown, cx)
11178    }
11179
11180    pub fn expand_excerpts_down(
11181        &mut self,
11182        action: &ExpandExcerptsDown,
11183        _: &mut Window,
11184        cx: &mut Context<Self>,
11185    ) {
11186        self.expand_excerpts_for_direction(action.lines, ExpandExcerptDirection::Down, cx)
11187    }
11188
11189    pub fn expand_excerpts_up(
11190        &mut self,
11191        action: &ExpandExcerptsUp,
11192        _: &mut Window,
11193        cx: &mut Context<Self>,
11194    ) {
11195        self.expand_excerpts_for_direction(action.lines, ExpandExcerptDirection::Up, cx)
11196    }
11197
11198    pub fn expand_excerpts_for_direction(
11199        &mut self,
11200        lines: u32,
11201        direction: ExpandExcerptDirection,
11202
11203        cx: &mut Context<Self>,
11204    ) {
11205        let selections = self.selections.disjoint_anchors();
11206
11207        let lines = if lines == 0 {
11208            EditorSettings::get_global(cx).expand_excerpt_lines
11209        } else {
11210            lines
11211        };
11212
11213        self.buffer.update(cx, |buffer, cx| {
11214            let snapshot = buffer.snapshot(cx);
11215            let mut excerpt_ids = selections
11216                .iter()
11217                .flat_map(|selection| snapshot.excerpt_ids_for_range(selection.range()))
11218                .collect::<Vec<_>>();
11219            excerpt_ids.sort();
11220            excerpt_ids.dedup();
11221            buffer.expand_excerpts(excerpt_ids, lines, direction, cx)
11222        })
11223    }
11224
11225    pub fn expand_excerpt(
11226        &mut self,
11227        excerpt: ExcerptId,
11228        direction: ExpandExcerptDirection,
11229        cx: &mut Context<Self>,
11230    ) {
11231        let lines = EditorSettings::get_global(cx).expand_excerpt_lines;
11232        self.buffer.update(cx, |buffer, cx| {
11233            buffer.expand_excerpts([excerpt], lines, direction, cx)
11234        })
11235    }
11236
11237    pub fn go_to_singleton_buffer_point(
11238        &mut self,
11239        point: Point,
11240        window: &mut Window,
11241        cx: &mut Context<Self>,
11242    ) {
11243        self.go_to_singleton_buffer_range(point..point, window, cx);
11244    }
11245
11246    pub fn go_to_singleton_buffer_range(
11247        &mut self,
11248        range: Range<Point>,
11249        window: &mut Window,
11250        cx: &mut Context<Self>,
11251    ) {
11252        let multibuffer = self.buffer().read(cx);
11253        let Some(buffer) = multibuffer.as_singleton() else {
11254            return;
11255        };
11256        let Some(start) = multibuffer.buffer_point_to_anchor(&buffer, range.start, cx) else {
11257            return;
11258        };
11259        let Some(end) = multibuffer.buffer_point_to_anchor(&buffer, range.end, cx) else {
11260            return;
11261        };
11262        self.change_selections(Some(Autoscroll::center()), window, cx, |s| {
11263            s.select_anchor_ranges([start..end])
11264        });
11265    }
11266
11267    fn go_to_diagnostic(
11268        &mut self,
11269        _: &GoToDiagnostic,
11270        window: &mut Window,
11271        cx: &mut Context<Self>,
11272    ) {
11273        self.go_to_diagnostic_impl(Direction::Next, window, cx)
11274    }
11275
11276    fn go_to_prev_diagnostic(
11277        &mut self,
11278        _: &GoToPrevDiagnostic,
11279        window: &mut Window,
11280        cx: &mut Context<Self>,
11281    ) {
11282        self.go_to_diagnostic_impl(Direction::Prev, window, cx)
11283    }
11284
11285    pub fn go_to_diagnostic_impl(
11286        &mut self,
11287        direction: Direction,
11288        window: &mut Window,
11289        cx: &mut Context<Self>,
11290    ) {
11291        let buffer = self.buffer.read(cx).snapshot(cx);
11292        let selection = self.selections.newest::<usize>(cx);
11293
11294        // If there is an active Diagnostic Popover jump to its diagnostic instead.
11295        if direction == Direction::Next {
11296            if let Some(popover) = self.hover_state.diagnostic_popover.as_ref() {
11297                let Some(buffer_id) = popover.local_diagnostic.range.start.buffer_id else {
11298                    return;
11299                };
11300                self.activate_diagnostics(
11301                    buffer_id,
11302                    popover.local_diagnostic.diagnostic.group_id,
11303                    window,
11304                    cx,
11305                );
11306                if let Some(active_diagnostics) = self.active_diagnostics.as_ref() {
11307                    let primary_range_start = active_diagnostics.primary_range.start;
11308                    self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
11309                        let mut new_selection = s.newest_anchor().clone();
11310                        new_selection.collapse_to(primary_range_start, SelectionGoal::None);
11311                        s.select_anchors(vec![new_selection.clone()]);
11312                    });
11313                    self.refresh_inline_completion(false, true, window, cx);
11314                }
11315                return;
11316            }
11317        }
11318
11319        let active_group_id = self
11320            .active_diagnostics
11321            .as_ref()
11322            .map(|active_group| active_group.group_id);
11323        let active_primary_range = self.active_diagnostics.as_ref().map(|active_diagnostics| {
11324            active_diagnostics
11325                .primary_range
11326                .to_offset(&buffer)
11327                .to_inclusive()
11328        });
11329        let search_start = if let Some(active_primary_range) = active_primary_range.as_ref() {
11330            if active_primary_range.contains(&selection.head()) {
11331                *active_primary_range.start()
11332            } else {
11333                selection.head()
11334            }
11335        } else {
11336            selection.head()
11337        };
11338
11339        let snapshot = self.snapshot(window, cx);
11340        let primary_diagnostics_before = buffer
11341            .diagnostics_in_range::<usize>(0..search_start)
11342            .filter(|entry| entry.diagnostic.is_primary)
11343            .filter(|entry| entry.range.start != entry.range.end)
11344            .filter(|entry| entry.diagnostic.severity <= DiagnosticSeverity::WARNING)
11345            .filter(|entry| !snapshot.intersects_fold(entry.range.start))
11346            .collect::<Vec<_>>();
11347        let last_same_group_diagnostic_before = active_group_id.and_then(|active_group_id| {
11348            primary_diagnostics_before
11349                .iter()
11350                .position(|entry| entry.diagnostic.group_id == active_group_id)
11351        });
11352
11353        let primary_diagnostics_after = buffer
11354            .diagnostics_in_range::<usize>(search_start..buffer.len())
11355            .filter(|entry| entry.diagnostic.is_primary)
11356            .filter(|entry| entry.range.start != entry.range.end)
11357            .filter(|entry| entry.diagnostic.severity <= DiagnosticSeverity::WARNING)
11358            .filter(|diagnostic| !snapshot.intersects_fold(diagnostic.range.start))
11359            .collect::<Vec<_>>();
11360        let last_same_group_diagnostic_after = active_group_id.and_then(|active_group_id| {
11361            primary_diagnostics_after
11362                .iter()
11363                .enumerate()
11364                .rev()
11365                .find_map(|(i, entry)| {
11366                    if entry.diagnostic.group_id == active_group_id {
11367                        Some(i)
11368                    } else {
11369                        None
11370                    }
11371                })
11372        });
11373
11374        let next_primary_diagnostic = match direction {
11375            Direction::Prev => primary_diagnostics_before
11376                .iter()
11377                .take(last_same_group_diagnostic_before.unwrap_or(usize::MAX))
11378                .rev()
11379                .next(),
11380            Direction::Next => primary_diagnostics_after
11381                .iter()
11382                .skip(
11383                    last_same_group_diagnostic_after
11384                        .map(|index| index + 1)
11385                        .unwrap_or(0),
11386                )
11387                .next(),
11388        };
11389
11390        // Cycle around to the start of the buffer, potentially moving back to the start of
11391        // the currently active diagnostic.
11392        let cycle_around = || match direction {
11393            Direction::Prev => primary_diagnostics_after
11394                .iter()
11395                .rev()
11396                .chain(primary_diagnostics_before.iter().rev())
11397                .next(),
11398            Direction::Next => primary_diagnostics_before
11399                .iter()
11400                .chain(primary_diagnostics_after.iter())
11401                .next(),
11402        };
11403
11404        if let Some((primary_range, group_id)) = next_primary_diagnostic
11405            .or_else(cycle_around)
11406            .map(|entry| (&entry.range, entry.diagnostic.group_id))
11407        {
11408            let Some(buffer_id) = buffer.anchor_after(primary_range.start).buffer_id else {
11409                return;
11410            };
11411            self.activate_diagnostics(buffer_id, group_id, window, cx);
11412            if self.active_diagnostics.is_some() {
11413                self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
11414                    s.select(vec![Selection {
11415                        id: selection.id,
11416                        start: primary_range.start,
11417                        end: primary_range.start,
11418                        reversed: false,
11419                        goal: SelectionGoal::None,
11420                    }]);
11421                });
11422                self.refresh_inline_completion(false, true, window, cx);
11423            }
11424        }
11425    }
11426
11427    fn go_to_next_hunk(&mut self, _: &GoToHunk, window: &mut Window, cx: &mut Context<Self>) {
11428        let snapshot = self.snapshot(window, cx);
11429        let selection = self.selections.newest::<Point>(cx);
11430        self.go_to_hunk_after_position(&snapshot, selection.head(), window, cx);
11431    }
11432
11433    fn go_to_hunk_after_position(
11434        &mut self,
11435        snapshot: &EditorSnapshot,
11436        position: Point,
11437        window: &mut Window,
11438        cx: &mut Context<Editor>,
11439    ) -> Option<MultiBufferDiffHunk> {
11440        let mut hunk = snapshot
11441            .buffer_snapshot
11442            .diff_hunks_in_range(position..snapshot.buffer_snapshot.max_point())
11443            .find(|hunk| hunk.row_range.start.0 > position.row);
11444        if hunk.is_none() {
11445            hunk = snapshot
11446                .buffer_snapshot
11447                .diff_hunks_in_range(Point::zero()..position)
11448                .find(|hunk| hunk.row_range.end.0 < position.row)
11449        }
11450        if let Some(hunk) = &hunk {
11451            let destination = Point::new(hunk.row_range.start.0, 0);
11452            self.unfold_ranges(&[destination..destination], false, false, cx);
11453            self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
11454                s.select_ranges(vec![destination..destination]);
11455            });
11456        }
11457
11458        hunk
11459    }
11460
11461    fn go_to_prev_hunk(&mut self, _: &GoToPrevHunk, window: &mut Window, cx: &mut Context<Self>) {
11462        let snapshot = self.snapshot(window, cx);
11463        let selection = self.selections.newest::<Point>(cx);
11464        self.go_to_hunk_before_position(&snapshot, selection.head(), window, cx);
11465    }
11466
11467    fn go_to_hunk_before_position(
11468        &mut self,
11469        snapshot: &EditorSnapshot,
11470        position: Point,
11471        window: &mut Window,
11472        cx: &mut Context<Editor>,
11473    ) -> Option<MultiBufferDiffHunk> {
11474        let mut hunk = snapshot.buffer_snapshot.diff_hunk_before(position);
11475        if hunk.is_none() {
11476            hunk = snapshot.buffer_snapshot.diff_hunk_before(Point::MAX);
11477        }
11478        if let Some(hunk) = &hunk {
11479            let destination = Point::new(hunk.row_range.start.0, 0);
11480            self.unfold_ranges(&[destination..destination], false, false, cx);
11481            self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
11482                s.select_ranges(vec![destination..destination]);
11483            });
11484        }
11485
11486        hunk
11487    }
11488
11489    pub fn go_to_definition(
11490        &mut self,
11491        _: &GoToDefinition,
11492        window: &mut Window,
11493        cx: &mut Context<Self>,
11494    ) -> Task<Result<Navigated>> {
11495        let definition =
11496            self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, false, window, cx);
11497        cx.spawn_in(window, |editor, mut cx| async move {
11498            if definition.await? == Navigated::Yes {
11499                return Ok(Navigated::Yes);
11500            }
11501            match editor.update_in(&mut cx, |editor, window, cx| {
11502                editor.find_all_references(&FindAllReferences, window, cx)
11503            })? {
11504                Some(references) => references.await,
11505                None => Ok(Navigated::No),
11506            }
11507        })
11508    }
11509
11510    pub fn go_to_declaration(
11511        &mut self,
11512        _: &GoToDeclaration,
11513        window: &mut Window,
11514        cx: &mut Context<Self>,
11515    ) -> Task<Result<Navigated>> {
11516        self.go_to_definition_of_kind(GotoDefinitionKind::Declaration, false, window, cx)
11517    }
11518
11519    pub fn go_to_declaration_split(
11520        &mut self,
11521        _: &GoToDeclaration,
11522        window: &mut Window,
11523        cx: &mut Context<Self>,
11524    ) -> Task<Result<Navigated>> {
11525        self.go_to_definition_of_kind(GotoDefinitionKind::Declaration, true, window, cx)
11526    }
11527
11528    pub fn go_to_implementation(
11529        &mut self,
11530        _: &GoToImplementation,
11531        window: &mut Window,
11532        cx: &mut Context<Self>,
11533    ) -> Task<Result<Navigated>> {
11534        self.go_to_definition_of_kind(GotoDefinitionKind::Implementation, false, window, cx)
11535    }
11536
11537    pub fn go_to_implementation_split(
11538        &mut self,
11539        _: &GoToImplementationSplit,
11540        window: &mut Window,
11541        cx: &mut Context<Self>,
11542    ) -> Task<Result<Navigated>> {
11543        self.go_to_definition_of_kind(GotoDefinitionKind::Implementation, true, window, cx)
11544    }
11545
11546    pub fn go_to_type_definition(
11547        &mut self,
11548        _: &GoToTypeDefinition,
11549        window: &mut Window,
11550        cx: &mut Context<Self>,
11551    ) -> Task<Result<Navigated>> {
11552        self.go_to_definition_of_kind(GotoDefinitionKind::Type, false, window, cx)
11553    }
11554
11555    pub fn go_to_definition_split(
11556        &mut self,
11557        _: &GoToDefinitionSplit,
11558        window: &mut Window,
11559        cx: &mut Context<Self>,
11560    ) -> Task<Result<Navigated>> {
11561        self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, true, window, cx)
11562    }
11563
11564    pub fn go_to_type_definition_split(
11565        &mut self,
11566        _: &GoToTypeDefinitionSplit,
11567        window: &mut Window,
11568        cx: &mut Context<Self>,
11569    ) -> Task<Result<Navigated>> {
11570        self.go_to_definition_of_kind(GotoDefinitionKind::Type, true, window, cx)
11571    }
11572
11573    fn go_to_definition_of_kind(
11574        &mut self,
11575        kind: GotoDefinitionKind,
11576        split: bool,
11577        window: &mut Window,
11578        cx: &mut Context<Self>,
11579    ) -> Task<Result<Navigated>> {
11580        let Some(provider) = self.semantics_provider.clone() else {
11581            return Task::ready(Ok(Navigated::No));
11582        };
11583        let head = self.selections.newest::<usize>(cx).head();
11584        let buffer = self.buffer.read(cx);
11585        let (buffer, head) = if let Some(text_anchor) = buffer.text_anchor_for_position(head, cx) {
11586            text_anchor
11587        } else {
11588            return Task::ready(Ok(Navigated::No));
11589        };
11590
11591        let Some(definitions) = provider.definitions(&buffer, head, kind, cx) else {
11592            return Task::ready(Ok(Navigated::No));
11593        };
11594
11595        cx.spawn_in(window, |editor, mut cx| async move {
11596            let definitions = definitions.await?;
11597            let navigated = editor
11598                .update_in(&mut cx, |editor, window, cx| {
11599                    editor.navigate_to_hover_links(
11600                        Some(kind),
11601                        definitions
11602                            .into_iter()
11603                            .filter(|location| {
11604                                hover_links::exclude_link_to_position(&buffer, &head, location, cx)
11605                            })
11606                            .map(HoverLink::Text)
11607                            .collect::<Vec<_>>(),
11608                        split,
11609                        window,
11610                        cx,
11611                    )
11612                })?
11613                .await?;
11614            anyhow::Ok(navigated)
11615        })
11616    }
11617
11618    pub fn open_url(&mut self, _: &OpenUrl, window: &mut Window, cx: &mut Context<Self>) {
11619        let selection = self.selections.newest_anchor();
11620        let head = selection.head();
11621        let tail = selection.tail();
11622
11623        let Some((buffer, start_position)) =
11624            self.buffer.read(cx).text_anchor_for_position(head, cx)
11625        else {
11626            return;
11627        };
11628
11629        let end_position = if head != tail {
11630            let Some((_, pos)) = self.buffer.read(cx).text_anchor_for_position(tail, cx) else {
11631                return;
11632            };
11633            Some(pos)
11634        } else {
11635            None
11636        };
11637
11638        let url_finder = cx.spawn_in(window, |editor, mut cx| async move {
11639            let url = if let Some(end_pos) = end_position {
11640                find_url_from_range(&buffer, start_position..end_pos, cx.clone())
11641            } else {
11642                find_url(&buffer, start_position, cx.clone()).map(|(_, url)| url)
11643            };
11644
11645            if let Some(url) = url {
11646                editor.update(&mut cx, |_, cx| {
11647                    cx.open_url(&url);
11648                })
11649            } else {
11650                Ok(())
11651            }
11652        });
11653
11654        url_finder.detach();
11655    }
11656
11657    pub fn open_selected_filename(
11658        &mut self,
11659        _: &OpenSelectedFilename,
11660        window: &mut Window,
11661        cx: &mut Context<Self>,
11662    ) {
11663        let Some(workspace) = self.workspace() else {
11664            return;
11665        };
11666
11667        let position = self.selections.newest_anchor().head();
11668
11669        let Some((buffer, buffer_position)) =
11670            self.buffer.read(cx).text_anchor_for_position(position, cx)
11671        else {
11672            return;
11673        };
11674
11675        let project = self.project.clone();
11676
11677        cx.spawn_in(window, |_, mut cx| async move {
11678            let result = find_file(&buffer, project, buffer_position, &mut cx).await;
11679
11680            if let Some((_, path)) = result {
11681                workspace
11682                    .update_in(&mut cx, |workspace, window, cx| {
11683                        workspace.open_resolved_path(path, window, cx)
11684                    })?
11685                    .await?;
11686            }
11687            anyhow::Ok(())
11688        })
11689        .detach();
11690    }
11691
11692    pub(crate) fn navigate_to_hover_links(
11693        &mut self,
11694        kind: Option<GotoDefinitionKind>,
11695        mut definitions: Vec<HoverLink>,
11696        split: bool,
11697        window: &mut Window,
11698        cx: &mut Context<Editor>,
11699    ) -> Task<Result<Navigated>> {
11700        // If there is one definition, just open it directly
11701        if definitions.len() == 1 {
11702            let definition = definitions.pop().unwrap();
11703
11704            enum TargetTaskResult {
11705                Location(Option<Location>),
11706                AlreadyNavigated,
11707            }
11708
11709            let target_task = match definition {
11710                HoverLink::Text(link) => {
11711                    Task::ready(anyhow::Ok(TargetTaskResult::Location(Some(link.target))))
11712                }
11713                HoverLink::InlayHint(lsp_location, server_id) => {
11714                    let computation =
11715                        self.compute_target_location(lsp_location, server_id, window, cx);
11716                    cx.background_spawn(async move {
11717                        let location = computation.await?;
11718                        Ok(TargetTaskResult::Location(location))
11719                    })
11720                }
11721                HoverLink::Url(url) => {
11722                    cx.open_url(&url);
11723                    Task::ready(Ok(TargetTaskResult::AlreadyNavigated))
11724                }
11725                HoverLink::File(path) => {
11726                    if let Some(workspace) = self.workspace() {
11727                        cx.spawn_in(window, |_, mut cx| async move {
11728                            workspace
11729                                .update_in(&mut cx, |workspace, window, cx| {
11730                                    workspace.open_resolved_path(path, window, cx)
11731                                })?
11732                                .await
11733                                .map(|_| TargetTaskResult::AlreadyNavigated)
11734                        })
11735                    } else {
11736                        Task::ready(Ok(TargetTaskResult::Location(None)))
11737                    }
11738                }
11739            };
11740            cx.spawn_in(window, |editor, mut cx| async move {
11741                let target = match target_task.await.context("target resolution task")? {
11742                    TargetTaskResult::AlreadyNavigated => return Ok(Navigated::Yes),
11743                    TargetTaskResult::Location(None) => return Ok(Navigated::No),
11744                    TargetTaskResult::Location(Some(target)) => target,
11745                };
11746
11747                editor.update_in(&mut cx, |editor, window, cx| {
11748                    let Some(workspace) = editor.workspace() else {
11749                        return Navigated::No;
11750                    };
11751                    let pane = workspace.read(cx).active_pane().clone();
11752
11753                    let range = target.range.to_point(target.buffer.read(cx));
11754                    let range = editor.range_for_match(&range);
11755                    let range = collapse_multiline_range(range);
11756
11757                    if !split
11758                        && Some(&target.buffer) == editor.buffer.read(cx).as_singleton().as_ref()
11759                    {
11760                        editor.go_to_singleton_buffer_range(range.clone(), window, cx);
11761                    } else {
11762                        window.defer(cx, move |window, cx| {
11763                            let target_editor: Entity<Self> =
11764                                workspace.update(cx, |workspace, cx| {
11765                                    let pane = if split {
11766                                        workspace.adjacent_pane(window, cx)
11767                                    } else {
11768                                        workspace.active_pane().clone()
11769                                    };
11770
11771                                    workspace.open_project_item(
11772                                        pane,
11773                                        target.buffer.clone(),
11774                                        true,
11775                                        true,
11776                                        window,
11777                                        cx,
11778                                    )
11779                                });
11780                            target_editor.update(cx, |target_editor, cx| {
11781                                // When selecting a definition in a different buffer, disable the nav history
11782                                // to avoid creating a history entry at the previous cursor location.
11783                                pane.update(cx, |pane, _| pane.disable_history());
11784                                target_editor.go_to_singleton_buffer_range(range, window, cx);
11785                                pane.update(cx, |pane, _| pane.enable_history());
11786                            });
11787                        });
11788                    }
11789                    Navigated::Yes
11790                })
11791            })
11792        } else if !definitions.is_empty() {
11793            cx.spawn_in(window, |editor, mut cx| async move {
11794                let (title, location_tasks, workspace) = editor
11795                    .update_in(&mut cx, |editor, window, cx| {
11796                        let tab_kind = match kind {
11797                            Some(GotoDefinitionKind::Implementation) => "Implementations",
11798                            _ => "Definitions",
11799                        };
11800                        let title = definitions
11801                            .iter()
11802                            .find_map(|definition| match definition {
11803                                HoverLink::Text(link) => link.origin.as_ref().map(|origin| {
11804                                    let buffer = origin.buffer.read(cx);
11805                                    format!(
11806                                        "{} for {}",
11807                                        tab_kind,
11808                                        buffer
11809                                            .text_for_range(origin.range.clone())
11810                                            .collect::<String>()
11811                                    )
11812                                }),
11813                                HoverLink::InlayHint(_, _) => None,
11814                                HoverLink::Url(_) => None,
11815                                HoverLink::File(_) => None,
11816                            })
11817                            .unwrap_or(tab_kind.to_string());
11818                        let location_tasks = definitions
11819                            .into_iter()
11820                            .map(|definition| match definition {
11821                                HoverLink::Text(link) => Task::ready(Ok(Some(link.target))),
11822                                HoverLink::InlayHint(lsp_location, server_id) => editor
11823                                    .compute_target_location(lsp_location, server_id, window, cx),
11824                                HoverLink::Url(_) => Task::ready(Ok(None)),
11825                                HoverLink::File(_) => Task::ready(Ok(None)),
11826                            })
11827                            .collect::<Vec<_>>();
11828                        (title, location_tasks, editor.workspace().clone())
11829                    })
11830                    .context("location tasks preparation")?;
11831
11832                let locations = future::join_all(location_tasks)
11833                    .await
11834                    .into_iter()
11835                    .filter_map(|location| location.transpose())
11836                    .collect::<Result<_>>()
11837                    .context("location tasks")?;
11838
11839                let Some(workspace) = workspace else {
11840                    return Ok(Navigated::No);
11841                };
11842                let opened = workspace
11843                    .update_in(&mut cx, |workspace, window, cx| {
11844                        Self::open_locations_in_multibuffer(
11845                            workspace,
11846                            locations,
11847                            title,
11848                            split,
11849                            MultibufferSelectionMode::First,
11850                            window,
11851                            cx,
11852                        )
11853                    })
11854                    .ok();
11855
11856                anyhow::Ok(Navigated::from_bool(opened.is_some()))
11857            })
11858        } else {
11859            Task::ready(Ok(Navigated::No))
11860        }
11861    }
11862
11863    fn compute_target_location(
11864        &self,
11865        lsp_location: lsp::Location,
11866        server_id: LanguageServerId,
11867        window: &mut Window,
11868        cx: &mut Context<Self>,
11869    ) -> Task<anyhow::Result<Option<Location>>> {
11870        let Some(project) = self.project.clone() else {
11871            return Task::ready(Ok(None));
11872        };
11873
11874        cx.spawn_in(window, move |editor, mut cx| async move {
11875            let location_task = editor.update(&mut cx, |_, cx| {
11876                project.update(cx, |project, cx| {
11877                    let language_server_name = project
11878                        .language_server_statuses(cx)
11879                        .find(|(id, _)| server_id == *id)
11880                        .map(|(_, status)| LanguageServerName::from(status.name.as_str()));
11881                    language_server_name.map(|language_server_name| {
11882                        project.open_local_buffer_via_lsp(
11883                            lsp_location.uri.clone(),
11884                            server_id,
11885                            language_server_name,
11886                            cx,
11887                        )
11888                    })
11889                })
11890            })?;
11891            let location = match location_task {
11892                Some(task) => Some({
11893                    let target_buffer_handle = task.await.context("open local buffer")?;
11894                    let range = target_buffer_handle.update(&mut cx, |target_buffer, _| {
11895                        let target_start = target_buffer
11896                            .clip_point_utf16(point_from_lsp(lsp_location.range.start), Bias::Left);
11897                        let target_end = target_buffer
11898                            .clip_point_utf16(point_from_lsp(lsp_location.range.end), Bias::Left);
11899                        target_buffer.anchor_after(target_start)
11900                            ..target_buffer.anchor_before(target_end)
11901                    })?;
11902                    Location {
11903                        buffer: target_buffer_handle,
11904                        range,
11905                    }
11906                }),
11907                None => None,
11908            };
11909            Ok(location)
11910        })
11911    }
11912
11913    pub fn find_all_references(
11914        &mut self,
11915        _: &FindAllReferences,
11916        window: &mut Window,
11917        cx: &mut Context<Self>,
11918    ) -> Option<Task<Result<Navigated>>> {
11919        let selection = self.selections.newest::<usize>(cx);
11920        let multi_buffer = self.buffer.read(cx);
11921        let head = selection.head();
11922
11923        let multi_buffer_snapshot = multi_buffer.snapshot(cx);
11924        let head_anchor = multi_buffer_snapshot.anchor_at(
11925            head,
11926            if head < selection.tail() {
11927                Bias::Right
11928            } else {
11929                Bias::Left
11930            },
11931        );
11932
11933        match self
11934            .find_all_references_task_sources
11935            .binary_search_by(|anchor| anchor.cmp(&head_anchor, &multi_buffer_snapshot))
11936        {
11937            Ok(_) => {
11938                log::info!(
11939                    "Ignoring repeated FindAllReferences invocation with the position of already running task"
11940                );
11941                return None;
11942            }
11943            Err(i) => {
11944                self.find_all_references_task_sources.insert(i, head_anchor);
11945            }
11946        }
11947
11948        let (buffer, head) = multi_buffer.text_anchor_for_position(head, cx)?;
11949        let workspace = self.workspace()?;
11950        let project = workspace.read(cx).project().clone();
11951        let references = project.update(cx, |project, cx| project.references(&buffer, head, cx));
11952        Some(cx.spawn_in(window, |editor, mut cx| async move {
11953            let _cleanup = defer({
11954                let mut cx = cx.clone();
11955                move || {
11956                    let _ = editor.update(&mut cx, |editor, _| {
11957                        if let Ok(i) =
11958                            editor
11959                                .find_all_references_task_sources
11960                                .binary_search_by(|anchor| {
11961                                    anchor.cmp(&head_anchor, &multi_buffer_snapshot)
11962                                })
11963                        {
11964                            editor.find_all_references_task_sources.remove(i);
11965                        }
11966                    });
11967                }
11968            });
11969
11970            let locations = references.await?;
11971            if locations.is_empty() {
11972                return anyhow::Ok(Navigated::No);
11973            }
11974
11975            workspace.update_in(&mut cx, |workspace, window, cx| {
11976                let title = locations
11977                    .first()
11978                    .as_ref()
11979                    .map(|location| {
11980                        let buffer = location.buffer.read(cx);
11981                        format!(
11982                            "References to `{}`",
11983                            buffer
11984                                .text_for_range(location.range.clone())
11985                                .collect::<String>()
11986                        )
11987                    })
11988                    .unwrap();
11989                Self::open_locations_in_multibuffer(
11990                    workspace,
11991                    locations,
11992                    title,
11993                    false,
11994                    MultibufferSelectionMode::First,
11995                    window,
11996                    cx,
11997                );
11998                Navigated::Yes
11999            })
12000        }))
12001    }
12002
12003    /// Opens a multibuffer with the given project locations in it
12004    pub fn open_locations_in_multibuffer(
12005        workspace: &mut Workspace,
12006        mut locations: Vec<Location>,
12007        title: String,
12008        split: bool,
12009        multibuffer_selection_mode: MultibufferSelectionMode,
12010        window: &mut Window,
12011        cx: &mut Context<Workspace>,
12012    ) {
12013        // If there are multiple definitions, open them in a multibuffer
12014        locations.sort_by_key(|location| location.buffer.read(cx).remote_id());
12015        let mut locations = locations.into_iter().peekable();
12016        let mut ranges = Vec::new();
12017        let capability = workspace.project().read(cx).capability();
12018
12019        let excerpt_buffer = cx.new(|cx| {
12020            let mut multibuffer = MultiBuffer::new(capability);
12021            while let Some(location) = locations.next() {
12022                let buffer = location.buffer.read(cx);
12023                let mut ranges_for_buffer = Vec::new();
12024                let range = location.range.to_offset(buffer);
12025                ranges_for_buffer.push(range.clone());
12026
12027                while let Some(next_location) = locations.peek() {
12028                    if next_location.buffer == location.buffer {
12029                        ranges_for_buffer.push(next_location.range.to_offset(buffer));
12030                        locations.next();
12031                    } else {
12032                        break;
12033                    }
12034                }
12035
12036                ranges_for_buffer.sort_by_key(|range| (range.start, Reverse(range.end)));
12037                ranges.extend(multibuffer.push_excerpts_with_context_lines(
12038                    location.buffer.clone(),
12039                    ranges_for_buffer,
12040                    DEFAULT_MULTIBUFFER_CONTEXT,
12041                    cx,
12042                ))
12043            }
12044
12045            multibuffer.with_title(title)
12046        });
12047
12048        let editor = cx.new(|cx| {
12049            Editor::for_multibuffer(
12050                excerpt_buffer,
12051                Some(workspace.project().clone()),
12052                true,
12053                window,
12054                cx,
12055            )
12056        });
12057        editor.update(cx, |editor, cx| {
12058            match multibuffer_selection_mode {
12059                MultibufferSelectionMode::First => {
12060                    if let Some(first_range) = ranges.first() {
12061                        editor.change_selections(None, window, cx, |selections| {
12062                            selections.clear_disjoint();
12063                            selections.select_anchor_ranges(std::iter::once(first_range.clone()));
12064                        });
12065                    }
12066                    editor.highlight_background::<Self>(
12067                        &ranges,
12068                        |theme| theme.editor_highlighted_line_background,
12069                        cx,
12070                    );
12071                }
12072                MultibufferSelectionMode::All => {
12073                    editor.change_selections(None, window, cx, |selections| {
12074                        selections.clear_disjoint();
12075                        selections.select_anchor_ranges(ranges);
12076                    });
12077                }
12078            }
12079            editor.register_buffers_with_language_servers(cx);
12080        });
12081
12082        let item = Box::new(editor);
12083        let item_id = item.item_id();
12084
12085        if split {
12086            workspace.split_item(SplitDirection::Right, item.clone(), window, cx);
12087        } else {
12088            let destination_index = workspace.active_pane().update(cx, |pane, cx| {
12089                if PreviewTabsSettings::get_global(cx).enable_preview_from_code_navigation {
12090                    pane.close_current_preview_item(window, cx)
12091                } else {
12092                    None
12093                }
12094            });
12095            workspace.add_item_to_active_pane(item.clone(), destination_index, true, window, cx);
12096        }
12097        workspace.active_pane().update(cx, |pane, cx| {
12098            pane.set_preview_item_id(Some(item_id), cx);
12099        });
12100    }
12101
12102    pub fn rename(
12103        &mut self,
12104        _: &Rename,
12105        window: &mut Window,
12106        cx: &mut Context<Self>,
12107    ) -> Option<Task<Result<()>>> {
12108        use language::ToOffset as _;
12109
12110        let provider = self.semantics_provider.clone()?;
12111        let selection = self.selections.newest_anchor().clone();
12112        let (cursor_buffer, cursor_buffer_position) = self
12113            .buffer
12114            .read(cx)
12115            .text_anchor_for_position(selection.head(), cx)?;
12116        let (tail_buffer, cursor_buffer_position_end) = self
12117            .buffer
12118            .read(cx)
12119            .text_anchor_for_position(selection.tail(), cx)?;
12120        if tail_buffer != cursor_buffer {
12121            return None;
12122        }
12123
12124        let snapshot = cursor_buffer.read(cx).snapshot();
12125        let cursor_buffer_offset = cursor_buffer_position.to_offset(&snapshot);
12126        let cursor_buffer_offset_end = cursor_buffer_position_end.to_offset(&snapshot);
12127        let prepare_rename = provider
12128            .range_for_rename(&cursor_buffer, cursor_buffer_position, cx)
12129            .unwrap_or_else(|| Task::ready(Ok(None)));
12130        drop(snapshot);
12131
12132        Some(cx.spawn_in(window, |this, mut cx| async move {
12133            let rename_range = if let Some(range) = prepare_rename.await? {
12134                Some(range)
12135            } else {
12136                this.update(&mut cx, |this, cx| {
12137                    let buffer = this.buffer.read(cx).snapshot(cx);
12138                    let mut buffer_highlights = this
12139                        .document_highlights_for_position(selection.head(), &buffer)
12140                        .filter(|highlight| {
12141                            highlight.start.excerpt_id == selection.head().excerpt_id
12142                                && highlight.end.excerpt_id == selection.head().excerpt_id
12143                        });
12144                    buffer_highlights
12145                        .next()
12146                        .map(|highlight| highlight.start.text_anchor..highlight.end.text_anchor)
12147                })?
12148            };
12149            if let Some(rename_range) = rename_range {
12150                this.update_in(&mut cx, |this, window, cx| {
12151                    let snapshot = cursor_buffer.read(cx).snapshot();
12152                    let rename_buffer_range = rename_range.to_offset(&snapshot);
12153                    let cursor_offset_in_rename_range =
12154                        cursor_buffer_offset.saturating_sub(rename_buffer_range.start);
12155                    let cursor_offset_in_rename_range_end =
12156                        cursor_buffer_offset_end.saturating_sub(rename_buffer_range.start);
12157
12158                    this.take_rename(false, window, cx);
12159                    let buffer = this.buffer.read(cx).read(cx);
12160                    let cursor_offset = selection.head().to_offset(&buffer);
12161                    let rename_start = cursor_offset.saturating_sub(cursor_offset_in_rename_range);
12162                    let rename_end = rename_start + rename_buffer_range.len();
12163                    let range = buffer.anchor_before(rename_start)..buffer.anchor_after(rename_end);
12164                    let mut old_highlight_id = None;
12165                    let old_name: Arc<str> = buffer
12166                        .chunks(rename_start..rename_end, true)
12167                        .map(|chunk| {
12168                            if old_highlight_id.is_none() {
12169                                old_highlight_id = chunk.syntax_highlight_id;
12170                            }
12171                            chunk.text
12172                        })
12173                        .collect::<String>()
12174                        .into();
12175
12176                    drop(buffer);
12177
12178                    // Position the selection in the rename editor so that it matches the current selection.
12179                    this.show_local_selections = false;
12180                    let rename_editor = cx.new(|cx| {
12181                        let mut editor = Editor::single_line(window, cx);
12182                        editor.buffer.update(cx, |buffer, cx| {
12183                            buffer.edit([(0..0, old_name.clone())], None, cx)
12184                        });
12185                        let rename_selection_range = match cursor_offset_in_rename_range
12186                            .cmp(&cursor_offset_in_rename_range_end)
12187                        {
12188                            Ordering::Equal => {
12189                                editor.select_all(&SelectAll, window, cx);
12190                                return editor;
12191                            }
12192                            Ordering::Less => {
12193                                cursor_offset_in_rename_range..cursor_offset_in_rename_range_end
12194                            }
12195                            Ordering::Greater => {
12196                                cursor_offset_in_rename_range_end..cursor_offset_in_rename_range
12197                            }
12198                        };
12199                        if rename_selection_range.end > old_name.len() {
12200                            editor.select_all(&SelectAll, window, cx);
12201                        } else {
12202                            editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
12203                                s.select_ranges([rename_selection_range]);
12204                            });
12205                        }
12206                        editor
12207                    });
12208                    cx.subscribe(&rename_editor, |_, _, e: &EditorEvent, cx| {
12209                        if e == &EditorEvent::Focused {
12210                            cx.emit(EditorEvent::FocusedIn)
12211                        }
12212                    })
12213                    .detach();
12214
12215                    let write_highlights =
12216                        this.clear_background_highlights::<DocumentHighlightWrite>(cx);
12217                    let read_highlights =
12218                        this.clear_background_highlights::<DocumentHighlightRead>(cx);
12219                    let ranges = write_highlights
12220                        .iter()
12221                        .flat_map(|(_, ranges)| ranges.iter())
12222                        .chain(read_highlights.iter().flat_map(|(_, ranges)| ranges.iter()))
12223                        .cloned()
12224                        .collect();
12225
12226                    this.highlight_text::<Rename>(
12227                        ranges,
12228                        HighlightStyle {
12229                            fade_out: Some(0.6),
12230                            ..Default::default()
12231                        },
12232                        cx,
12233                    );
12234                    let rename_focus_handle = rename_editor.focus_handle(cx);
12235                    window.focus(&rename_focus_handle);
12236                    let block_id = this.insert_blocks(
12237                        [BlockProperties {
12238                            style: BlockStyle::Flex,
12239                            placement: BlockPlacement::Below(range.start),
12240                            height: 1,
12241                            render: Arc::new({
12242                                let rename_editor = rename_editor.clone();
12243                                move |cx: &mut BlockContext| {
12244                                    let mut text_style = cx.editor_style.text.clone();
12245                                    if let Some(highlight_style) = old_highlight_id
12246                                        .and_then(|h| h.style(&cx.editor_style.syntax))
12247                                    {
12248                                        text_style = text_style.highlight(highlight_style);
12249                                    }
12250                                    div()
12251                                        .block_mouse_down()
12252                                        .pl(cx.anchor_x)
12253                                        .child(EditorElement::new(
12254                                            &rename_editor,
12255                                            EditorStyle {
12256                                                background: cx.theme().system().transparent,
12257                                                local_player: cx.editor_style.local_player,
12258                                                text: text_style,
12259                                                scrollbar_width: cx.editor_style.scrollbar_width,
12260                                                syntax: cx.editor_style.syntax.clone(),
12261                                                status: cx.editor_style.status.clone(),
12262                                                inlay_hints_style: HighlightStyle {
12263                                                    font_weight: Some(FontWeight::BOLD),
12264                                                    ..make_inlay_hints_style(cx.app)
12265                                                },
12266                                                inline_completion_styles: make_suggestion_styles(
12267                                                    cx.app,
12268                                                ),
12269                                                ..EditorStyle::default()
12270                                            },
12271                                        ))
12272                                        .into_any_element()
12273                                }
12274                            }),
12275                            priority: 0,
12276                        }],
12277                        Some(Autoscroll::fit()),
12278                        cx,
12279                    )[0];
12280                    this.pending_rename = Some(RenameState {
12281                        range,
12282                        old_name,
12283                        editor: rename_editor,
12284                        block_id,
12285                    });
12286                })?;
12287            }
12288
12289            Ok(())
12290        }))
12291    }
12292
12293    pub fn confirm_rename(
12294        &mut self,
12295        _: &ConfirmRename,
12296        window: &mut Window,
12297        cx: &mut Context<Self>,
12298    ) -> Option<Task<Result<()>>> {
12299        let rename = self.take_rename(false, window, cx)?;
12300        let workspace = self.workspace()?.downgrade();
12301        let (buffer, start) = self
12302            .buffer
12303            .read(cx)
12304            .text_anchor_for_position(rename.range.start, cx)?;
12305        let (end_buffer, _) = self
12306            .buffer
12307            .read(cx)
12308            .text_anchor_for_position(rename.range.end, cx)?;
12309        if buffer != end_buffer {
12310            return None;
12311        }
12312
12313        let old_name = rename.old_name;
12314        let new_name = rename.editor.read(cx).text(cx);
12315
12316        let rename = self.semantics_provider.as_ref()?.perform_rename(
12317            &buffer,
12318            start,
12319            new_name.clone(),
12320            cx,
12321        )?;
12322
12323        Some(cx.spawn_in(window, |editor, mut cx| async move {
12324            let project_transaction = rename.await?;
12325            Self::open_project_transaction(
12326                &editor,
12327                workspace,
12328                project_transaction,
12329                format!("Rename: {}{}", old_name, new_name),
12330                cx.clone(),
12331            )
12332            .await?;
12333
12334            editor.update(&mut cx, |editor, cx| {
12335                editor.refresh_document_highlights(cx);
12336            })?;
12337            Ok(())
12338        }))
12339    }
12340
12341    fn take_rename(
12342        &mut self,
12343        moving_cursor: bool,
12344        window: &mut Window,
12345        cx: &mut Context<Self>,
12346    ) -> Option<RenameState> {
12347        let rename = self.pending_rename.take()?;
12348        if rename.editor.focus_handle(cx).is_focused(window) {
12349            window.focus(&self.focus_handle);
12350        }
12351
12352        self.remove_blocks(
12353            [rename.block_id].into_iter().collect(),
12354            Some(Autoscroll::fit()),
12355            cx,
12356        );
12357        self.clear_highlights::<Rename>(cx);
12358        self.show_local_selections = true;
12359
12360        if moving_cursor {
12361            let cursor_in_rename_editor = rename.editor.update(cx, |editor, cx| {
12362                editor.selections.newest::<usize>(cx).head()
12363            });
12364
12365            // Update the selection to match the position of the selection inside
12366            // the rename editor.
12367            let snapshot = self.buffer.read(cx).read(cx);
12368            let rename_range = rename.range.to_offset(&snapshot);
12369            let cursor_in_editor = snapshot
12370                .clip_offset(rename_range.start + cursor_in_rename_editor, Bias::Left)
12371                .min(rename_range.end);
12372            drop(snapshot);
12373
12374            self.change_selections(None, window, cx, |s| {
12375                s.select_ranges(vec![cursor_in_editor..cursor_in_editor])
12376            });
12377        } else {
12378            self.refresh_document_highlights(cx);
12379        }
12380
12381        Some(rename)
12382    }
12383
12384    pub fn pending_rename(&self) -> Option<&RenameState> {
12385        self.pending_rename.as_ref()
12386    }
12387
12388    fn format(
12389        &mut self,
12390        _: &Format,
12391        window: &mut Window,
12392        cx: &mut Context<Self>,
12393    ) -> Option<Task<Result<()>>> {
12394        let project = match &self.project {
12395            Some(project) => project.clone(),
12396            None => return None,
12397        };
12398
12399        Some(self.perform_format(
12400            project,
12401            FormatTrigger::Manual,
12402            FormatTarget::Buffers,
12403            window,
12404            cx,
12405        ))
12406    }
12407
12408    fn format_selections(
12409        &mut self,
12410        _: &FormatSelections,
12411        window: &mut Window,
12412        cx: &mut Context<Self>,
12413    ) -> Option<Task<Result<()>>> {
12414        let project = match &self.project {
12415            Some(project) => project.clone(),
12416            None => return None,
12417        };
12418
12419        let ranges = self
12420            .selections
12421            .all_adjusted(cx)
12422            .into_iter()
12423            .map(|selection| selection.range())
12424            .collect_vec();
12425
12426        Some(self.perform_format(
12427            project,
12428            FormatTrigger::Manual,
12429            FormatTarget::Ranges(ranges),
12430            window,
12431            cx,
12432        ))
12433    }
12434
12435    fn perform_format(
12436        &mut self,
12437        project: Entity<Project>,
12438        trigger: FormatTrigger,
12439        target: FormatTarget,
12440        window: &mut Window,
12441        cx: &mut Context<Self>,
12442    ) -> Task<Result<()>> {
12443        let buffer = self.buffer.clone();
12444        let (buffers, target) = match target {
12445            FormatTarget::Buffers => {
12446                let mut buffers = buffer.read(cx).all_buffers();
12447                if trigger == FormatTrigger::Save {
12448                    buffers.retain(|buffer| buffer.read(cx).is_dirty());
12449                }
12450                (buffers, LspFormatTarget::Buffers)
12451            }
12452            FormatTarget::Ranges(selection_ranges) => {
12453                let multi_buffer = buffer.read(cx);
12454                let snapshot = multi_buffer.read(cx);
12455                let mut buffers = HashSet::default();
12456                let mut buffer_id_to_ranges: BTreeMap<BufferId, Vec<Range<text::Anchor>>> =
12457                    BTreeMap::new();
12458                for selection_range in selection_ranges {
12459                    for (buffer, buffer_range, _) in
12460                        snapshot.range_to_buffer_ranges(selection_range)
12461                    {
12462                        let buffer_id = buffer.remote_id();
12463                        let start = buffer.anchor_before(buffer_range.start);
12464                        let end = buffer.anchor_after(buffer_range.end);
12465                        buffers.insert(multi_buffer.buffer(buffer_id).unwrap());
12466                        buffer_id_to_ranges
12467                            .entry(buffer_id)
12468                            .and_modify(|buffer_ranges| buffer_ranges.push(start..end))
12469                            .or_insert_with(|| vec![start..end]);
12470                    }
12471                }
12472                (buffers, LspFormatTarget::Ranges(buffer_id_to_ranges))
12473            }
12474        };
12475
12476        let mut timeout = cx.background_executor().timer(FORMAT_TIMEOUT).fuse();
12477        let format = project.update(cx, |project, cx| {
12478            project.format(buffers, target, true, trigger, cx)
12479        });
12480
12481        cx.spawn_in(window, |_, mut cx| async move {
12482            let transaction = futures::select_biased! {
12483                () = timeout => {
12484                    log::warn!("timed out waiting for formatting");
12485                    None
12486                }
12487                transaction = format.log_err().fuse() => transaction,
12488            };
12489
12490            buffer
12491                .update(&mut cx, |buffer, cx| {
12492                    if let Some(transaction) = transaction {
12493                        if !buffer.is_singleton() {
12494                            buffer.push_transaction(&transaction.0, cx);
12495                        }
12496                    }
12497
12498                    cx.notify();
12499                })
12500                .ok();
12501
12502            Ok(())
12503        })
12504    }
12505
12506    fn restart_language_server(
12507        &mut self,
12508        _: &RestartLanguageServer,
12509        _: &mut Window,
12510        cx: &mut Context<Self>,
12511    ) {
12512        if let Some(project) = self.project.clone() {
12513            self.buffer.update(cx, |multi_buffer, cx| {
12514                project.update(cx, |project, cx| {
12515                    project.restart_language_servers_for_buffers(
12516                        multi_buffer.all_buffers().into_iter().collect(),
12517                        cx,
12518                    );
12519                });
12520            })
12521        }
12522    }
12523
12524    fn cancel_language_server_work(
12525        workspace: &mut Workspace,
12526        _: &actions::CancelLanguageServerWork,
12527        _: &mut Window,
12528        cx: &mut Context<Workspace>,
12529    ) {
12530        let project = workspace.project();
12531        let buffers = workspace
12532            .active_item(cx)
12533            .and_then(|item| item.act_as::<Editor>(cx))
12534            .map_or(HashSet::default(), |editor| {
12535                editor.read(cx).buffer.read(cx).all_buffers()
12536            });
12537        project.update(cx, |project, cx| {
12538            project.cancel_language_server_work_for_buffers(buffers, cx);
12539        });
12540    }
12541
12542    fn show_character_palette(
12543        &mut self,
12544        _: &ShowCharacterPalette,
12545        window: &mut Window,
12546        _: &mut Context<Self>,
12547    ) {
12548        window.show_character_palette();
12549    }
12550
12551    fn refresh_active_diagnostics(&mut self, cx: &mut Context<Editor>) {
12552        if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
12553            let buffer = self.buffer.read(cx).snapshot(cx);
12554            let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
12555            let primary_range_end = active_diagnostics.primary_range.end.to_offset(&buffer);
12556            let is_valid = buffer
12557                .diagnostics_in_range::<usize>(primary_range_start..primary_range_end)
12558                .any(|entry| {
12559                    entry.diagnostic.is_primary
12560                        && !entry.range.is_empty()
12561                        && entry.range.start == primary_range_start
12562                        && entry.diagnostic.message == active_diagnostics.primary_message
12563                });
12564
12565            if is_valid != active_diagnostics.is_valid {
12566                active_diagnostics.is_valid = is_valid;
12567                if is_valid {
12568                    let mut new_styles = HashMap::default();
12569                    for (block_id, diagnostic) in &active_diagnostics.blocks {
12570                        new_styles.insert(
12571                            *block_id,
12572                            diagnostic_block_renderer(diagnostic.clone(), None, true),
12573                        );
12574                    }
12575                    self.display_map.update(cx, |display_map, _cx| {
12576                        display_map.replace_blocks(new_styles);
12577                    });
12578                } else {
12579                    self.dismiss_diagnostics(cx);
12580                }
12581            }
12582        }
12583    }
12584
12585    fn activate_diagnostics(
12586        &mut self,
12587        buffer_id: BufferId,
12588        group_id: usize,
12589        window: &mut Window,
12590        cx: &mut Context<Self>,
12591    ) {
12592        self.dismiss_diagnostics(cx);
12593        let snapshot = self.snapshot(window, cx);
12594        self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
12595            let buffer = self.buffer.read(cx).snapshot(cx);
12596
12597            let mut primary_range = None;
12598            let mut primary_message = None;
12599            let diagnostic_group = buffer
12600                .diagnostic_group(buffer_id, group_id)
12601                .filter_map(|entry| {
12602                    let start = entry.range.start;
12603                    let end = entry.range.end;
12604                    if snapshot.is_line_folded(MultiBufferRow(start.row))
12605                        && (start.row == end.row
12606                            || snapshot.is_line_folded(MultiBufferRow(end.row)))
12607                    {
12608                        return None;
12609                    }
12610                    if entry.diagnostic.is_primary {
12611                        primary_range = Some(entry.range.clone());
12612                        primary_message = Some(entry.diagnostic.message.clone());
12613                    }
12614                    Some(entry)
12615                })
12616                .collect::<Vec<_>>();
12617            let primary_range = primary_range?;
12618            let primary_message = primary_message?;
12619
12620            let blocks = display_map
12621                .insert_blocks(
12622                    diagnostic_group.iter().map(|entry| {
12623                        let diagnostic = entry.diagnostic.clone();
12624                        let message_height = diagnostic.message.matches('\n').count() as u32 + 1;
12625                        BlockProperties {
12626                            style: BlockStyle::Fixed,
12627                            placement: BlockPlacement::Below(
12628                                buffer.anchor_after(entry.range.start),
12629                            ),
12630                            height: message_height,
12631                            render: diagnostic_block_renderer(diagnostic, None, true),
12632                            priority: 0,
12633                        }
12634                    }),
12635                    cx,
12636                )
12637                .into_iter()
12638                .zip(diagnostic_group.into_iter().map(|entry| entry.diagnostic))
12639                .collect();
12640
12641            Some(ActiveDiagnosticGroup {
12642                primary_range: buffer.anchor_before(primary_range.start)
12643                    ..buffer.anchor_after(primary_range.end),
12644                primary_message,
12645                group_id,
12646                blocks,
12647                is_valid: true,
12648            })
12649        });
12650    }
12651
12652    fn dismiss_diagnostics(&mut self, cx: &mut Context<Self>) {
12653        if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
12654            self.display_map.update(cx, |display_map, cx| {
12655                display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx);
12656            });
12657            cx.notify();
12658        }
12659    }
12660
12661    /// Disable inline diagnostics rendering for this editor.
12662    pub fn disable_inline_diagnostics(&mut self) {
12663        self.inline_diagnostics_enabled = false;
12664        self.inline_diagnostics_update = Task::ready(());
12665        self.inline_diagnostics.clear();
12666    }
12667
12668    pub fn inline_diagnostics_enabled(&self) -> bool {
12669        self.inline_diagnostics_enabled
12670    }
12671
12672    pub fn show_inline_diagnostics(&self) -> bool {
12673        self.show_inline_diagnostics
12674    }
12675
12676    pub fn toggle_inline_diagnostics(
12677        &mut self,
12678        _: &ToggleInlineDiagnostics,
12679        window: &mut Window,
12680        cx: &mut Context<'_, Editor>,
12681    ) {
12682        self.show_inline_diagnostics = !self.show_inline_diagnostics;
12683        self.refresh_inline_diagnostics(false, window, cx);
12684    }
12685
12686    fn refresh_inline_diagnostics(
12687        &mut self,
12688        debounce: bool,
12689        window: &mut Window,
12690        cx: &mut Context<Self>,
12691    ) {
12692        if !self.inline_diagnostics_enabled || !self.show_inline_diagnostics {
12693            self.inline_diagnostics_update = Task::ready(());
12694            self.inline_diagnostics.clear();
12695            return;
12696        }
12697
12698        let debounce_ms = ProjectSettings::get_global(cx)
12699            .diagnostics
12700            .inline
12701            .update_debounce_ms;
12702        let debounce = if debounce && debounce_ms > 0 {
12703            Some(Duration::from_millis(debounce_ms))
12704        } else {
12705            None
12706        };
12707        self.inline_diagnostics_update = cx.spawn_in(window, |editor, mut cx| async move {
12708            if let Some(debounce) = debounce {
12709                cx.background_executor().timer(debounce).await;
12710            }
12711            let Some(snapshot) = editor
12712                .update(&mut cx, |editor, cx| editor.buffer().read(cx).snapshot(cx))
12713                .ok()
12714            else {
12715                return;
12716            };
12717
12718            let new_inline_diagnostics = cx
12719                .background_spawn(async move {
12720                    let mut inline_diagnostics = Vec::<(Anchor, InlineDiagnostic)>::new();
12721                    for diagnostic_entry in snapshot.diagnostics_in_range(0..snapshot.len()) {
12722                        let message = diagnostic_entry
12723                            .diagnostic
12724                            .message
12725                            .split_once('\n')
12726                            .map(|(line, _)| line)
12727                            .map(SharedString::new)
12728                            .unwrap_or_else(|| {
12729                                SharedString::from(diagnostic_entry.diagnostic.message)
12730                            });
12731                        let start_anchor = snapshot.anchor_before(diagnostic_entry.range.start);
12732                        let (Ok(i) | Err(i)) = inline_diagnostics
12733                            .binary_search_by(|(probe, _)| probe.cmp(&start_anchor, &snapshot));
12734                        inline_diagnostics.insert(
12735                            i,
12736                            (
12737                                start_anchor,
12738                                InlineDiagnostic {
12739                                    message,
12740                                    group_id: diagnostic_entry.diagnostic.group_id,
12741                                    start: diagnostic_entry.range.start.to_point(&snapshot),
12742                                    is_primary: diagnostic_entry.diagnostic.is_primary,
12743                                    severity: diagnostic_entry.diagnostic.severity,
12744                                },
12745                            ),
12746                        );
12747                    }
12748                    inline_diagnostics
12749                })
12750                .await;
12751
12752            editor
12753                .update(&mut cx, |editor, cx| {
12754                    editor.inline_diagnostics = new_inline_diagnostics;
12755                    cx.notify();
12756                })
12757                .ok();
12758        });
12759    }
12760
12761    pub fn set_selections_from_remote(
12762        &mut self,
12763        selections: Vec<Selection<Anchor>>,
12764        pending_selection: Option<Selection<Anchor>>,
12765        window: &mut Window,
12766        cx: &mut Context<Self>,
12767    ) {
12768        let old_cursor_position = self.selections.newest_anchor().head();
12769        self.selections.change_with(cx, |s| {
12770            s.select_anchors(selections);
12771            if let Some(pending_selection) = pending_selection {
12772                s.set_pending(pending_selection, SelectMode::Character);
12773            } else {
12774                s.clear_pending();
12775            }
12776        });
12777        self.selections_did_change(false, &old_cursor_position, true, window, cx);
12778    }
12779
12780    fn push_to_selection_history(&mut self) {
12781        self.selection_history.push(SelectionHistoryEntry {
12782            selections: self.selections.disjoint_anchors(),
12783            select_next_state: self.select_next_state.clone(),
12784            select_prev_state: self.select_prev_state.clone(),
12785            add_selections_state: self.add_selections_state.clone(),
12786        });
12787    }
12788
12789    pub fn transact(
12790        &mut self,
12791        window: &mut Window,
12792        cx: &mut Context<Self>,
12793        update: impl FnOnce(&mut Self, &mut Window, &mut Context<Self>),
12794    ) -> Option<TransactionId> {
12795        self.start_transaction_at(Instant::now(), window, cx);
12796        update(self, window, cx);
12797        self.end_transaction_at(Instant::now(), cx)
12798    }
12799
12800    pub fn start_transaction_at(
12801        &mut self,
12802        now: Instant,
12803        window: &mut Window,
12804        cx: &mut Context<Self>,
12805    ) {
12806        self.end_selection(window, cx);
12807        if let Some(tx_id) = self
12808            .buffer
12809            .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx))
12810        {
12811            self.selection_history
12812                .insert_transaction(tx_id, self.selections.disjoint_anchors());
12813            cx.emit(EditorEvent::TransactionBegun {
12814                transaction_id: tx_id,
12815            })
12816        }
12817    }
12818
12819    pub fn end_transaction_at(
12820        &mut self,
12821        now: Instant,
12822        cx: &mut Context<Self>,
12823    ) -> Option<TransactionId> {
12824        if let Some(transaction_id) = self
12825            .buffer
12826            .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
12827        {
12828            if let Some((_, end_selections)) =
12829                self.selection_history.transaction_mut(transaction_id)
12830            {
12831                *end_selections = Some(self.selections.disjoint_anchors());
12832            } else {
12833                log::error!("unexpectedly ended a transaction that wasn't started by this editor");
12834            }
12835
12836            cx.emit(EditorEvent::Edited { transaction_id });
12837            Some(transaction_id)
12838        } else {
12839            None
12840        }
12841    }
12842
12843    pub fn set_mark(&mut self, _: &actions::SetMark, window: &mut Window, cx: &mut Context<Self>) {
12844        if self.selection_mark_mode {
12845            self.change_selections(None, window, cx, |s| {
12846                s.move_with(|_, sel| {
12847                    sel.collapse_to(sel.head(), SelectionGoal::None);
12848                });
12849            })
12850        }
12851        self.selection_mark_mode = true;
12852        cx.notify();
12853    }
12854
12855    pub fn swap_selection_ends(
12856        &mut self,
12857        _: &actions::SwapSelectionEnds,
12858        window: &mut Window,
12859        cx: &mut Context<Self>,
12860    ) {
12861        self.change_selections(None, window, cx, |s| {
12862            s.move_with(|_, sel| {
12863                if sel.start != sel.end {
12864                    sel.reversed = !sel.reversed
12865                }
12866            });
12867        });
12868        self.request_autoscroll(Autoscroll::newest(), cx);
12869        cx.notify();
12870    }
12871
12872    pub fn toggle_fold(
12873        &mut self,
12874        _: &actions::ToggleFold,
12875        window: &mut Window,
12876        cx: &mut Context<Self>,
12877    ) {
12878        if self.is_singleton(cx) {
12879            let selection = self.selections.newest::<Point>(cx);
12880
12881            let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
12882            let range = if selection.is_empty() {
12883                let point = selection.head().to_display_point(&display_map);
12884                let start = DisplayPoint::new(point.row(), 0).to_point(&display_map);
12885                let end = DisplayPoint::new(point.row(), display_map.line_len(point.row()))
12886                    .to_point(&display_map);
12887                start..end
12888            } else {
12889                selection.range()
12890            };
12891            if display_map.folds_in_range(range).next().is_some() {
12892                self.unfold_lines(&Default::default(), window, cx)
12893            } else {
12894                self.fold(&Default::default(), window, cx)
12895            }
12896        } else {
12897            let multi_buffer_snapshot = self.buffer.read(cx).snapshot(cx);
12898            let buffer_ids: HashSet<_> = multi_buffer_snapshot
12899                .ranges_to_buffer_ranges(self.selections.disjoint_anchor_ranges())
12900                .map(|(snapshot, _, _)| snapshot.remote_id())
12901                .collect();
12902
12903            for buffer_id in buffer_ids {
12904                if self.is_buffer_folded(buffer_id, cx) {
12905                    self.unfold_buffer(buffer_id, cx);
12906                } else {
12907                    self.fold_buffer(buffer_id, cx);
12908                }
12909            }
12910        }
12911    }
12912
12913    pub fn toggle_fold_recursive(
12914        &mut self,
12915        _: &actions::ToggleFoldRecursive,
12916        window: &mut Window,
12917        cx: &mut Context<Self>,
12918    ) {
12919        let selection = self.selections.newest::<Point>(cx);
12920
12921        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
12922        let range = if selection.is_empty() {
12923            let point = selection.head().to_display_point(&display_map);
12924            let start = DisplayPoint::new(point.row(), 0).to_point(&display_map);
12925            let end = DisplayPoint::new(point.row(), display_map.line_len(point.row()))
12926                .to_point(&display_map);
12927            start..end
12928        } else {
12929            selection.range()
12930        };
12931        if display_map.folds_in_range(range).next().is_some() {
12932            self.unfold_recursive(&Default::default(), window, cx)
12933        } else {
12934            self.fold_recursive(&Default::default(), window, cx)
12935        }
12936    }
12937
12938    pub fn fold(&mut self, _: &actions::Fold, window: &mut Window, cx: &mut Context<Self>) {
12939        if self.is_singleton(cx) {
12940            let mut to_fold = Vec::new();
12941            let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
12942            let selections = self.selections.all_adjusted(cx);
12943
12944            for selection in selections {
12945                let range = selection.range().sorted();
12946                let buffer_start_row = range.start.row;
12947
12948                if range.start.row != range.end.row {
12949                    let mut found = false;
12950                    let mut row = range.start.row;
12951                    while row <= range.end.row {
12952                        if let Some(crease) = display_map.crease_for_buffer_row(MultiBufferRow(row))
12953                        {
12954                            found = true;
12955                            row = crease.range().end.row + 1;
12956                            to_fold.push(crease);
12957                        } else {
12958                            row += 1
12959                        }
12960                    }
12961                    if found {
12962                        continue;
12963                    }
12964                }
12965
12966                for row in (0..=range.start.row).rev() {
12967                    if let Some(crease) = display_map.crease_for_buffer_row(MultiBufferRow(row)) {
12968                        if crease.range().end.row >= buffer_start_row {
12969                            to_fold.push(crease);
12970                            if row <= range.start.row {
12971                                break;
12972                            }
12973                        }
12974                    }
12975                }
12976            }
12977
12978            self.fold_creases(to_fold, true, window, cx);
12979        } else {
12980            let multi_buffer_snapshot = self.buffer.read(cx).snapshot(cx);
12981
12982            let buffer_ids: HashSet<_> = multi_buffer_snapshot
12983                .ranges_to_buffer_ranges(self.selections.disjoint_anchor_ranges())
12984                .map(|(snapshot, _, _)| snapshot.remote_id())
12985                .collect();
12986            for buffer_id in buffer_ids {
12987                self.fold_buffer(buffer_id, cx);
12988            }
12989        }
12990    }
12991
12992    fn fold_at_level(
12993        &mut self,
12994        fold_at: &FoldAtLevel,
12995        window: &mut Window,
12996        cx: &mut Context<Self>,
12997    ) {
12998        if !self.buffer.read(cx).is_singleton() {
12999            return;
13000        }
13001
13002        let fold_at_level = fold_at.0;
13003        let snapshot = self.buffer.read(cx).snapshot(cx);
13004        let mut to_fold = Vec::new();
13005        let mut stack = vec![(0, snapshot.max_row().0, 1)];
13006
13007        while let Some((mut start_row, end_row, current_level)) = stack.pop() {
13008            while start_row < end_row {
13009                match self
13010                    .snapshot(window, cx)
13011                    .crease_for_buffer_row(MultiBufferRow(start_row))
13012                {
13013                    Some(crease) => {
13014                        let nested_start_row = crease.range().start.row + 1;
13015                        let nested_end_row = crease.range().end.row;
13016
13017                        if current_level < fold_at_level {
13018                            stack.push((nested_start_row, nested_end_row, current_level + 1));
13019                        } else if current_level == fold_at_level {
13020                            to_fold.push(crease);
13021                        }
13022
13023                        start_row = nested_end_row + 1;
13024                    }
13025                    None => start_row += 1,
13026                }
13027            }
13028        }
13029
13030        self.fold_creases(to_fold, true, window, cx);
13031    }
13032
13033    pub fn fold_all(&mut self, _: &actions::FoldAll, window: &mut Window, cx: &mut Context<Self>) {
13034        if self.buffer.read(cx).is_singleton() {
13035            let mut fold_ranges = Vec::new();
13036            let snapshot = self.buffer.read(cx).snapshot(cx);
13037
13038            for row in 0..snapshot.max_row().0 {
13039                if let Some(foldable_range) = self
13040                    .snapshot(window, cx)
13041                    .crease_for_buffer_row(MultiBufferRow(row))
13042                {
13043                    fold_ranges.push(foldable_range);
13044                }
13045            }
13046
13047            self.fold_creases(fold_ranges, true, window, cx);
13048        } else {
13049            self.toggle_fold_multiple_buffers = cx.spawn_in(window, |editor, mut cx| async move {
13050                editor
13051                    .update_in(&mut cx, |editor, _, cx| {
13052                        for buffer_id in editor.buffer.read(cx).excerpt_buffer_ids() {
13053                            editor.fold_buffer(buffer_id, cx);
13054                        }
13055                    })
13056                    .ok();
13057            });
13058        }
13059    }
13060
13061    pub fn fold_function_bodies(
13062        &mut self,
13063        _: &actions::FoldFunctionBodies,
13064        window: &mut Window,
13065        cx: &mut Context<Self>,
13066    ) {
13067        let snapshot = self.buffer.read(cx).snapshot(cx);
13068
13069        let ranges = snapshot
13070            .text_object_ranges(0..snapshot.len(), TreeSitterOptions::default())
13071            .filter_map(|(range, obj)| (obj == TextObject::InsideFunction).then_some(range))
13072            .collect::<Vec<_>>();
13073
13074        let creases = ranges
13075            .into_iter()
13076            .map(|range| Crease::simple(range, self.display_map.read(cx).fold_placeholder.clone()))
13077            .collect();
13078
13079        self.fold_creases(creases, true, window, cx);
13080    }
13081
13082    pub fn fold_recursive(
13083        &mut self,
13084        _: &actions::FoldRecursive,
13085        window: &mut Window,
13086        cx: &mut Context<Self>,
13087    ) {
13088        let mut to_fold = Vec::new();
13089        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
13090        let selections = self.selections.all_adjusted(cx);
13091
13092        for selection in selections {
13093            let range = selection.range().sorted();
13094            let buffer_start_row = range.start.row;
13095
13096            if range.start.row != range.end.row {
13097                let mut found = false;
13098                for row in range.start.row..=range.end.row {
13099                    if let Some(crease) = display_map.crease_for_buffer_row(MultiBufferRow(row)) {
13100                        found = true;
13101                        to_fold.push(crease);
13102                    }
13103                }
13104                if found {
13105                    continue;
13106                }
13107            }
13108
13109            for row in (0..=range.start.row).rev() {
13110                if let Some(crease) = display_map.crease_for_buffer_row(MultiBufferRow(row)) {
13111                    if crease.range().end.row >= buffer_start_row {
13112                        to_fold.push(crease);
13113                    } else {
13114                        break;
13115                    }
13116                }
13117            }
13118        }
13119
13120        self.fold_creases(to_fold, true, window, cx);
13121    }
13122
13123    pub fn fold_at(&mut self, fold_at: &FoldAt, window: &mut Window, cx: &mut Context<Self>) {
13124        let buffer_row = fold_at.buffer_row;
13125        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
13126
13127        if let Some(crease) = display_map.crease_for_buffer_row(buffer_row) {
13128            let autoscroll = self
13129                .selections
13130                .all::<Point>(cx)
13131                .iter()
13132                .any(|selection| crease.range().overlaps(&selection.range()));
13133
13134            self.fold_creases(vec![crease], autoscroll, window, cx);
13135        }
13136    }
13137
13138    pub fn unfold_lines(&mut self, _: &UnfoldLines, _window: &mut Window, cx: &mut Context<Self>) {
13139        if self.is_singleton(cx) {
13140            let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
13141            let buffer = &display_map.buffer_snapshot;
13142            let selections = self.selections.all::<Point>(cx);
13143            let ranges = selections
13144                .iter()
13145                .map(|s| {
13146                    let range = s.display_range(&display_map).sorted();
13147                    let mut start = range.start.to_point(&display_map);
13148                    let mut end = range.end.to_point(&display_map);
13149                    start.column = 0;
13150                    end.column = buffer.line_len(MultiBufferRow(end.row));
13151                    start..end
13152                })
13153                .collect::<Vec<_>>();
13154
13155            self.unfold_ranges(&ranges, true, true, cx);
13156        } else {
13157            let multi_buffer_snapshot = self.buffer.read(cx).snapshot(cx);
13158            let buffer_ids: HashSet<_> = multi_buffer_snapshot
13159                .ranges_to_buffer_ranges(self.selections.disjoint_anchor_ranges())
13160                .map(|(snapshot, _, _)| snapshot.remote_id())
13161                .collect();
13162            for buffer_id in buffer_ids {
13163                self.unfold_buffer(buffer_id, cx);
13164            }
13165        }
13166    }
13167
13168    pub fn unfold_recursive(
13169        &mut self,
13170        _: &UnfoldRecursive,
13171        _window: &mut Window,
13172        cx: &mut Context<Self>,
13173    ) {
13174        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
13175        let selections = self.selections.all::<Point>(cx);
13176        let ranges = selections
13177            .iter()
13178            .map(|s| {
13179                let mut range = s.display_range(&display_map).sorted();
13180                *range.start.column_mut() = 0;
13181                *range.end.column_mut() = display_map.line_len(range.end.row());
13182                let start = range.start.to_point(&display_map);
13183                let end = range.end.to_point(&display_map);
13184                start..end
13185            })
13186            .collect::<Vec<_>>();
13187
13188        self.unfold_ranges(&ranges, true, true, cx);
13189    }
13190
13191    pub fn unfold_at(
13192        &mut self,
13193        unfold_at: &UnfoldAt,
13194        _window: &mut Window,
13195        cx: &mut Context<Self>,
13196    ) {
13197        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
13198
13199        let intersection_range = Point::new(unfold_at.buffer_row.0, 0)
13200            ..Point::new(
13201                unfold_at.buffer_row.0,
13202                display_map.buffer_snapshot.line_len(unfold_at.buffer_row),
13203            );
13204
13205        let autoscroll = self
13206            .selections
13207            .all::<Point>(cx)
13208            .iter()
13209            .any(|selection| RangeExt::overlaps(&selection.range(), &intersection_range));
13210
13211        self.unfold_ranges(&[intersection_range], true, autoscroll, cx);
13212    }
13213
13214    pub fn unfold_all(
13215        &mut self,
13216        _: &actions::UnfoldAll,
13217        _window: &mut Window,
13218        cx: &mut Context<Self>,
13219    ) {
13220        if self.buffer.read(cx).is_singleton() {
13221            let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
13222            self.unfold_ranges(&[0..display_map.buffer_snapshot.len()], true, true, cx);
13223        } else {
13224            self.toggle_fold_multiple_buffers = cx.spawn(|editor, mut cx| async move {
13225                editor
13226                    .update(&mut cx, |editor, cx| {
13227                        for buffer_id in editor.buffer.read(cx).excerpt_buffer_ids() {
13228                            editor.unfold_buffer(buffer_id, cx);
13229                        }
13230                    })
13231                    .ok();
13232            });
13233        }
13234    }
13235
13236    pub fn fold_selected_ranges(
13237        &mut self,
13238        _: &FoldSelectedRanges,
13239        window: &mut Window,
13240        cx: &mut Context<Self>,
13241    ) {
13242        let selections = self.selections.all::<Point>(cx);
13243        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
13244        let line_mode = self.selections.line_mode;
13245        let ranges = selections
13246            .into_iter()
13247            .map(|s| {
13248                if line_mode {
13249                    let start = Point::new(s.start.row, 0);
13250                    let end = Point::new(
13251                        s.end.row,
13252                        display_map
13253                            .buffer_snapshot
13254                            .line_len(MultiBufferRow(s.end.row)),
13255                    );
13256                    Crease::simple(start..end, display_map.fold_placeholder.clone())
13257                } else {
13258                    Crease::simple(s.start..s.end, display_map.fold_placeholder.clone())
13259                }
13260            })
13261            .collect::<Vec<_>>();
13262        self.fold_creases(ranges, true, window, cx);
13263    }
13264
13265    pub fn fold_ranges<T: ToOffset + Clone>(
13266        &mut self,
13267        ranges: Vec<Range<T>>,
13268        auto_scroll: bool,
13269        window: &mut Window,
13270        cx: &mut Context<Self>,
13271    ) {
13272        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
13273        let ranges = ranges
13274            .into_iter()
13275            .map(|r| Crease::simple(r, display_map.fold_placeholder.clone()))
13276            .collect::<Vec<_>>();
13277        self.fold_creases(ranges, auto_scroll, window, cx);
13278    }
13279
13280    pub fn fold_creases<T: ToOffset + Clone>(
13281        &mut self,
13282        creases: Vec<Crease<T>>,
13283        auto_scroll: bool,
13284        window: &mut Window,
13285        cx: &mut Context<Self>,
13286    ) {
13287        if creases.is_empty() {
13288            return;
13289        }
13290
13291        let mut buffers_affected = HashSet::default();
13292        let multi_buffer = self.buffer().read(cx);
13293        for crease in &creases {
13294            if let Some((_, buffer, _)) =
13295                multi_buffer.excerpt_containing(crease.range().start.clone(), cx)
13296            {
13297                buffers_affected.insert(buffer.read(cx).remote_id());
13298            };
13299        }
13300
13301        self.display_map.update(cx, |map, cx| map.fold(creases, cx));
13302
13303        if auto_scroll {
13304            self.request_autoscroll(Autoscroll::fit(), cx);
13305        }
13306
13307        cx.notify();
13308
13309        if let Some(active_diagnostics) = self.active_diagnostics.take() {
13310            // Clear diagnostics block when folding a range that contains it.
13311            let snapshot = self.snapshot(window, cx);
13312            if snapshot.intersects_fold(active_diagnostics.primary_range.start) {
13313                drop(snapshot);
13314                self.active_diagnostics = Some(active_diagnostics);
13315                self.dismiss_diagnostics(cx);
13316            } else {
13317                self.active_diagnostics = Some(active_diagnostics);
13318            }
13319        }
13320
13321        self.scrollbar_marker_state.dirty = true;
13322    }
13323
13324    /// Removes any folds whose ranges intersect any of the given ranges.
13325    pub fn unfold_ranges<T: ToOffset + Clone>(
13326        &mut self,
13327        ranges: &[Range<T>],
13328        inclusive: bool,
13329        auto_scroll: bool,
13330        cx: &mut Context<Self>,
13331    ) {
13332        self.remove_folds_with(ranges, auto_scroll, cx, |map, cx| {
13333            map.unfold_intersecting(ranges.iter().cloned(), inclusive, cx)
13334        });
13335    }
13336
13337    pub fn fold_buffer(&mut self, buffer_id: BufferId, cx: &mut Context<Self>) {
13338        if self.buffer().read(cx).is_singleton() || self.is_buffer_folded(buffer_id, cx) {
13339            return;
13340        }
13341        let folded_excerpts = self.buffer().read(cx).excerpts_for_buffer(buffer_id, cx);
13342        self.display_map.update(cx, |display_map, cx| {
13343            display_map.fold_buffers([buffer_id], cx)
13344        });
13345        cx.emit(EditorEvent::BufferFoldToggled {
13346            ids: folded_excerpts.iter().map(|&(id, _)| id).collect(),
13347            folded: true,
13348        });
13349        cx.notify();
13350    }
13351
13352    pub fn unfold_buffer(&mut self, buffer_id: BufferId, cx: &mut Context<Self>) {
13353        if self.buffer().read(cx).is_singleton() || !self.is_buffer_folded(buffer_id, cx) {
13354            return;
13355        }
13356        let unfolded_excerpts = self.buffer().read(cx).excerpts_for_buffer(buffer_id, cx);
13357        self.display_map.update(cx, |display_map, cx| {
13358            display_map.unfold_buffers([buffer_id], cx);
13359        });
13360        cx.emit(EditorEvent::BufferFoldToggled {
13361            ids: unfolded_excerpts.iter().map(|&(id, _)| id).collect(),
13362            folded: false,
13363        });
13364        cx.notify();
13365    }
13366
13367    pub fn is_buffer_folded(&self, buffer: BufferId, cx: &App) -> bool {
13368        self.display_map.read(cx).is_buffer_folded(buffer)
13369    }
13370
13371    pub fn folded_buffers<'a>(&self, cx: &'a App) -> &'a HashSet<BufferId> {
13372        self.display_map.read(cx).folded_buffers()
13373    }
13374
13375    /// Removes any folds with the given ranges.
13376    pub fn remove_folds_with_type<T: ToOffset + Clone>(
13377        &mut self,
13378        ranges: &[Range<T>],
13379        type_id: TypeId,
13380        auto_scroll: bool,
13381        cx: &mut Context<Self>,
13382    ) {
13383        self.remove_folds_with(ranges, auto_scroll, cx, |map, cx| {
13384            map.remove_folds_with_type(ranges.iter().cloned(), type_id, cx)
13385        });
13386    }
13387
13388    fn remove_folds_with<T: ToOffset + Clone>(
13389        &mut self,
13390        ranges: &[Range<T>],
13391        auto_scroll: bool,
13392        cx: &mut Context<Self>,
13393        update: impl FnOnce(&mut DisplayMap, &mut Context<DisplayMap>),
13394    ) {
13395        if ranges.is_empty() {
13396            return;
13397        }
13398
13399        let mut buffers_affected = HashSet::default();
13400        let multi_buffer = self.buffer().read(cx);
13401        for range in ranges {
13402            if let Some((_, buffer, _)) = multi_buffer.excerpt_containing(range.start.clone(), cx) {
13403                buffers_affected.insert(buffer.read(cx).remote_id());
13404            };
13405        }
13406
13407        self.display_map.update(cx, update);
13408
13409        if auto_scroll {
13410            self.request_autoscroll(Autoscroll::fit(), cx);
13411        }
13412
13413        cx.notify();
13414        self.scrollbar_marker_state.dirty = true;
13415        self.active_indent_guides_state.dirty = true;
13416    }
13417
13418    pub fn default_fold_placeholder(&self, cx: &App) -> FoldPlaceholder {
13419        self.display_map.read(cx).fold_placeholder.clone()
13420    }
13421
13422    pub fn set_expand_all_diff_hunks(&mut self, cx: &mut App) {
13423        self.buffer.update(cx, |buffer, cx| {
13424            buffer.set_all_diff_hunks_expanded(cx);
13425        });
13426    }
13427
13428    pub fn expand_all_diff_hunks(
13429        &mut self,
13430        _: &ExpandAllDiffHunks,
13431        _window: &mut Window,
13432        cx: &mut Context<Self>,
13433    ) {
13434        self.buffer.update(cx, |buffer, cx| {
13435            buffer.expand_diff_hunks(vec![Anchor::min()..Anchor::max()], cx)
13436        });
13437    }
13438
13439    pub fn toggle_selected_diff_hunks(
13440        &mut self,
13441        _: &ToggleSelectedDiffHunks,
13442        _window: &mut Window,
13443        cx: &mut Context<Self>,
13444    ) {
13445        let ranges: Vec<_> = self.selections.disjoint.iter().map(|s| s.range()).collect();
13446        self.toggle_diff_hunks_in_ranges(ranges, cx);
13447    }
13448
13449    pub fn diff_hunks_in_ranges<'a>(
13450        &'a self,
13451        ranges: &'a [Range<Anchor>],
13452        buffer: &'a MultiBufferSnapshot,
13453    ) -> impl 'a + Iterator<Item = MultiBufferDiffHunk> {
13454        ranges.iter().flat_map(move |range| {
13455            let end_excerpt_id = range.end.excerpt_id;
13456            let range = range.to_point(buffer);
13457            let mut peek_end = range.end;
13458            if range.end.row < buffer.max_row().0 {
13459                peek_end = Point::new(range.end.row + 1, 0);
13460            }
13461            buffer
13462                .diff_hunks_in_range(range.start..peek_end)
13463                .filter(move |hunk| hunk.excerpt_id.cmp(&end_excerpt_id, buffer).is_le())
13464        })
13465    }
13466
13467    pub fn has_stageable_diff_hunks_in_ranges(
13468        &self,
13469        ranges: &[Range<Anchor>],
13470        snapshot: &MultiBufferSnapshot,
13471    ) -> bool {
13472        let mut hunks = self.diff_hunks_in_ranges(ranges, &snapshot);
13473        hunks.any(|hunk| hunk.secondary_status != DiffHunkSecondaryStatus::None)
13474    }
13475
13476    pub fn toggle_staged_selected_diff_hunks(
13477        &mut self,
13478        _: &::git::ToggleStaged,
13479        window: &mut Window,
13480        cx: &mut Context<Self>,
13481    ) {
13482        let snapshot = self.buffer.read(cx).snapshot(cx);
13483        let ranges: Vec<_> = self.selections.disjoint.iter().map(|s| s.range()).collect();
13484        let stage = self.has_stageable_diff_hunks_in_ranges(&ranges, &snapshot);
13485        self.stage_or_unstage_diff_hunks(stage, &ranges, window, cx);
13486    }
13487
13488    pub fn stage_and_next(
13489        &mut self,
13490        _: &::git::StageAndNext,
13491        window: &mut Window,
13492        cx: &mut Context<Self>,
13493    ) {
13494        self.do_stage_or_unstage_and_next(true, window, cx);
13495    }
13496
13497    pub fn unstage_and_next(
13498        &mut self,
13499        _: &::git::UnstageAndNext,
13500        window: &mut Window,
13501        cx: &mut Context<Self>,
13502    ) {
13503        self.do_stage_or_unstage_and_next(false, window, cx);
13504    }
13505
13506    pub fn stage_or_unstage_diff_hunks(
13507        &mut self,
13508        stage: bool,
13509        ranges: &[Range<Anchor>],
13510        window: &mut Window,
13511        cx: &mut Context<Self>,
13512    ) {
13513        let snapshot = self.buffer.read(cx).snapshot(cx);
13514        let Some(project) = &self.project else {
13515            return;
13516        };
13517
13518        let chunk_by = self
13519            .diff_hunks_in_ranges(&ranges, &snapshot)
13520            .chunk_by(|hunk| hunk.buffer_id);
13521        for (buffer_id, hunks) in &chunk_by {
13522            Self::do_stage_or_unstage(project, stage, buffer_id, hunks, &snapshot, window, cx);
13523        }
13524    }
13525
13526    fn do_stage_or_unstage_and_next(
13527        &mut self,
13528        stage: bool,
13529        window: &mut Window,
13530        cx: &mut Context<Self>,
13531    ) {
13532        let mut ranges = self.selections.disjoint_anchor_ranges().collect::<Vec<_>>();
13533        if ranges.iter().any(|range| range.start != range.end) {
13534            self.stage_or_unstage_diff_hunks(stage, &ranges[..], window, cx);
13535            return;
13536        }
13537
13538        if !self.buffer().read(cx).is_singleton() {
13539            if let Some((excerpt_id, buffer, range)) = self.active_excerpt(cx) {
13540                if buffer.read(cx).is_empty() {
13541                    let buffer = buffer.read(cx);
13542                    let Some(file) = buffer.file() else {
13543                        return;
13544                    };
13545                    let project_path = project::ProjectPath {
13546                        worktree_id: file.worktree_id(cx),
13547                        path: file.path().clone(),
13548                    };
13549                    let Some(project) = self.project.as_ref() else {
13550                        return;
13551                    };
13552                    let project = project.read(cx);
13553
13554                    let Some(repo) = project.git_store().read(cx).active_repository() else {
13555                        return;
13556                    };
13557
13558                    repo.update(cx, |repo, cx| {
13559                        let Some(repo_path) = repo.project_path_to_repo_path(&project_path) else {
13560                            return;
13561                        };
13562                        let Some(status) = repo.repository_entry.status_for_path(&repo_path) else {
13563                            return;
13564                        };
13565                        if stage && status.status == FileStatus::Untracked {
13566                            repo.stage_entries(vec![repo_path], cx)
13567                                .detach_and_log_err(cx);
13568                            return;
13569                        }
13570                    })
13571                }
13572                ranges = vec![multi_buffer::Anchor::range_in_buffer(
13573                    excerpt_id,
13574                    buffer.read(cx).remote_id(),
13575                    range,
13576                )];
13577                self.stage_or_unstage_diff_hunks(stage, &ranges[..], window, cx);
13578                let snapshot = self.buffer().read(cx).snapshot(cx);
13579                let mut point = ranges.last().unwrap().end.to_point(&snapshot);
13580                if point.row < snapshot.max_row().0 {
13581                    point.row += 1;
13582                    point.column = 0;
13583                    point = snapshot.clip_point(point, Bias::Right);
13584                    self.change_selections(Some(Autoscroll::top_relative(6)), window, cx, |s| {
13585                        s.select_ranges([point..point]);
13586                    })
13587                }
13588                return;
13589            }
13590        }
13591        self.stage_or_unstage_diff_hunks(stage, &ranges[..], window, cx);
13592        self.go_to_next_hunk(&Default::default(), window, cx);
13593    }
13594
13595    fn do_stage_or_unstage(
13596        project: &Entity<Project>,
13597        stage: bool,
13598        buffer_id: BufferId,
13599        hunks: impl Iterator<Item = MultiBufferDiffHunk>,
13600        snapshot: &MultiBufferSnapshot,
13601        window: &mut Window,
13602        cx: &mut App,
13603    ) {
13604        let Some(buffer) = project.read(cx).buffer_for_id(buffer_id, cx) else {
13605            log::debug!("no buffer for id");
13606            return;
13607        };
13608        let buffer_snapshot = buffer.read(cx).snapshot();
13609        let file_exists = buffer_snapshot
13610            .file()
13611            .is_some_and(|file| file.disk_state().exists());
13612        let Some((repo, path)) = project
13613            .read(cx)
13614            .repository_and_path_for_buffer_id(buffer_id, cx)
13615        else {
13616            log::debug!("no git repo for buffer id");
13617            return;
13618        };
13619        let Some(diff) = snapshot.diff_for_buffer_id(buffer_id) else {
13620            log::debug!("no diff for buffer id");
13621            return;
13622        };
13623
13624        let new_index_text = if !stage && diff.is_single_insertion || stage && !file_exists {
13625            log::debug!("removing from index");
13626            None
13627        } else {
13628            diff.new_secondary_text_for_stage_or_unstage(
13629                stage,
13630                hunks.filter_map(|hunk| {
13631                    if stage && hunk.secondary_status == DiffHunkSecondaryStatus::None {
13632                        return None;
13633                    } else if !stage
13634                        && hunk.secondary_status == DiffHunkSecondaryStatus::HasSecondaryHunk
13635                    {
13636                        return None;
13637                    }
13638                    Some((hunk.buffer_range.clone(), hunk.diff_base_byte_range.clone()))
13639                }),
13640                &buffer_snapshot,
13641                cx,
13642            )
13643        };
13644        if file_exists {
13645            let buffer_store = project.read(cx).buffer_store().clone();
13646            buffer_store
13647                .update(cx, |buffer_store, cx| buffer_store.save_buffer(buffer, cx))
13648                .detach_and_log_err(cx);
13649        }
13650        let recv = repo
13651            .read(cx)
13652            .set_index_text(&path, new_index_text.map(|rope| rope.to_string()));
13653
13654        cx.background_spawn(async move { recv.await? })
13655            .detach_and_notify_err(window, cx);
13656    }
13657
13658    pub fn expand_selected_diff_hunks(&mut self, cx: &mut Context<Self>) {
13659        let ranges: Vec<_> = self.selections.disjoint.iter().map(|s| s.range()).collect();
13660        self.buffer
13661            .update(cx, |buffer, cx| buffer.expand_diff_hunks(ranges, cx))
13662    }
13663
13664    pub fn clear_expanded_diff_hunks(&mut self, cx: &mut Context<Self>) -> bool {
13665        self.buffer.update(cx, |buffer, cx| {
13666            let ranges = vec![Anchor::min()..Anchor::max()];
13667            if !buffer.all_diff_hunks_expanded()
13668                && buffer.has_expanded_diff_hunks_in_ranges(&ranges, cx)
13669            {
13670                buffer.collapse_diff_hunks(ranges, cx);
13671                true
13672            } else {
13673                false
13674            }
13675        })
13676    }
13677
13678    fn toggle_diff_hunks_in_ranges(
13679        &mut self,
13680        ranges: Vec<Range<Anchor>>,
13681        cx: &mut Context<'_, Editor>,
13682    ) {
13683        self.buffer.update(cx, |buffer, cx| {
13684            let expand = !buffer.has_expanded_diff_hunks_in_ranges(&ranges, cx);
13685            buffer.expand_or_collapse_diff_hunks(ranges, expand, cx);
13686        })
13687    }
13688
13689    fn toggle_single_diff_hunk(&mut self, range: Range<Anchor>, cx: &mut Context<Self>) {
13690        self.buffer.update(cx, |buffer, cx| {
13691            let snapshot = buffer.snapshot(cx);
13692            let excerpt_id = range.end.excerpt_id;
13693            let point_range = range.to_point(&snapshot);
13694            let expand = !buffer.single_hunk_is_expanded(range, cx);
13695            buffer.expand_or_collapse_diff_hunks_inner([(point_range, excerpt_id)], expand, cx);
13696        })
13697    }
13698
13699    pub(crate) fn apply_all_diff_hunks(
13700        &mut self,
13701        _: &ApplyAllDiffHunks,
13702        window: &mut Window,
13703        cx: &mut Context<Self>,
13704    ) {
13705        let buffers = self.buffer.read(cx).all_buffers();
13706        for branch_buffer in buffers {
13707            branch_buffer.update(cx, |branch_buffer, cx| {
13708                branch_buffer.merge_into_base(Vec::new(), cx);
13709            });
13710        }
13711
13712        if let Some(project) = self.project.clone() {
13713            self.save(true, project, window, cx).detach_and_log_err(cx);
13714        }
13715    }
13716
13717    pub(crate) fn apply_selected_diff_hunks(
13718        &mut self,
13719        _: &ApplyDiffHunk,
13720        window: &mut Window,
13721        cx: &mut Context<Self>,
13722    ) {
13723        let snapshot = self.snapshot(window, cx);
13724        let hunks = snapshot.hunks_for_ranges(self.selections.ranges(cx).into_iter());
13725        let mut ranges_by_buffer = HashMap::default();
13726        self.transact(window, cx, |editor, _window, cx| {
13727            for hunk in hunks {
13728                if let Some(buffer) = editor.buffer.read(cx).buffer(hunk.buffer_id) {
13729                    ranges_by_buffer
13730                        .entry(buffer.clone())
13731                        .or_insert_with(Vec::new)
13732                        .push(hunk.buffer_range.to_offset(buffer.read(cx)));
13733                }
13734            }
13735
13736            for (buffer, ranges) in ranges_by_buffer {
13737                buffer.update(cx, |buffer, cx| {
13738                    buffer.merge_into_base(ranges, cx);
13739                });
13740            }
13741        });
13742
13743        if let Some(project) = self.project.clone() {
13744            self.save(true, project, window, cx).detach_and_log_err(cx);
13745        }
13746    }
13747
13748    pub fn set_gutter_hovered(&mut self, hovered: bool, cx: &mut Context<Self>) {
13749        if hovered != self.gutter_hovered {
13750            self.gutter_hovered = hovered;
13751            cx.notify();
13752        }
13753    }
13754
13755    pub fn insert_blocks(
13756        &mut self,
13757        blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
13758        autoscroll: Option<Autoscroll>,
13759        cx: &mut Context<Self>,
13760    ) -> Vec<CustomBlockId> {
13761        let blocks = self
13762            .display_map
13763            .update(cx, |display_map, cx| display_map.insert_blocks(blocks, cx));
13764        if let Some(autoscroll) = autoscroll {
13765            self.request_autoscroll(autoscroll, cx);
13766        }
13767        cx.notify();
13768        blocks
13769    }
13770
13771    pub fn resize_blocks(
13772        &mut self,
13773        heights: HashMap<CustomBlockId, u32>,
13774        autoscroll: Option<Autoscroll>,
13775        cx: &mut Context<Self>,
13776    ) {
13777        self.display_map
13778            .update(cx, |display_map, cx| display_map.resize_blocks(heights, cx));
13779        if let Some(autoscroll) = autoscroll {
13780            self.request_autoscroll(autoscroll, cx);
13781        }
13782        cx.notify();
13783    }
13784
13785    pub fn replace_blocks(
13786        &mut self,
13787        renderers: HashMap<CustomBlockId, RenderBlock>,
13788        autoscroll: Option<Autoscroll>,
13789        cx: &mut Context<Self>,
13790    ) {
13791        self.display_map
13792            .update(cx, |display_map, _cx| display_map.replace_blocks(renderers));
13793        if let Some(autoscroll) = autoscroll {
13794            self.request_autoscroll(autoscroll, cx);
13795        }
13796        cx.notify();
13797    }
13798
13799    pub fn remove_blocks(
13800        &mut self,
13801        block_ids: HashSet<CustomBlockId>,
13802        autoscroll: Option<Autoscroll>,
13803        cx: &mut Context<Self>,
13804    ) {
13805        self.display_map.update(cx, |display_map, cx| {
13806            display_map.remove_blocks(block_ids, cx)
13807        });
13808        if let Some(autoscroll) = autoscroll {
13809            self.request_autoscroll(autoscroll, cx);
13810        }
13811        cx.notify();
13812    }
13813
13814    pub fn row_for_block(
13815        &self,
13816        block_id: CustomBlockId,
13817        cx: &mut Context<Self>,
13818    ) -> Option<DisplayRow> {
13819        self.display_map
13820            .update(cx, |map, cx| map.row_for_block(block_id, cx))
13821    }
13822
13823    pub(crate) fn set_focused_block(&mut self, focused_block: FocusedBlock) {
13824        self.focused_block = Some(focused_block);
13825    }
13826
13827    pub(crate) fn take_focused_block(&mut self) -> Option<FocusedBlock> {
13828        self.focused_block.take()
13829    }
13830
13831    pub fn insert_creases(
13832        &mut self,
13833        creases: impl IntoIterator<Item = Crease<Anchor>>,
13834        cx: &mut Context<Self>,
13835    ) -> Vec<CreaseId> {
13836        self.display_map
13837            .update(cx, |map, cx| map.insert_creases(creases, cx))
13838    }
13839
13840    pub fn remove_creases(
13841        &mut self,
13842        ids: impl IntoIterator<Item = CreaseId>,
13843        cx: &mut Context<Self>,
13844    ) {
13845        self.display_map
13846            .update(cx, |map, cx| map.remove_creases(ids, cx));
13847    }
13848
13849    pub fn longest_row(&self, cx: &mut App) -> DisplayRow {
13850        self.display_map
13851            .update(cx, |map, cx| map.snapshot(cx))
13852            .longest_row()
13853    }
13854
13855    pub fn max_point(&self, cx: &mut App) -> DisplayPoint {
13856        self.display_map
13857            .update(cx, |map, cx| map.snapshot(cx))
13858            .max_point()
13859    }
13860
13861    pub fn text(&self, cx: &App) -> String {
13862        self.buffer.read(cx).read(cx).text()
13863    }
13864
13865    pub fn is_empty(&self, cx: &App) -> bool {
13866        self.buffer.read(cx).read(cx).is_empty()
13867    }
13868
13869    pub fn text_option(&self, cx: &App) -> Option<String> {
13870        let text = self.text(cx);
13871        let text = text.trim();
13872
13873        if text.is_empty() {
13874            return None;
13875        }
13876
13877        Some(text.to_string())
13878    }
13879
13880    pub fn set_text(
13881        &mut self,
13882        text: impl Into<Arc<str>>,
13883        window: &mut Window,
13884        cx: &mut Context<Self>,
13885    ) {
13886        self.transact(window, cx, |this, _, cx| {
13887            this.buffer
13888                .read(cx)
13889                .as_singleton()
13890                .expect("you can only call set_text on editors for singleton buffers")
13891                .update(cx, |buffer, cx| buffer.set_text(text, cx));
13892        });
13893    }
13894
13895    pub fn display_text(&self, cx: &mut App) -> String {
13896        self.display_map
13897            .update(cx, |map, cx| map.snapshot(cx))
13898            .text()
13899    }
13900
13901    pub fn wrap_guides(&self, cx: &App) -> SmallVec<[(usize, bool); 2]> {
13902        let mut wrap_guides = smallvec::smallvec![];
13903
13904        if self.show_wrap_guides == Some(false) {
13905            return wrap_guides;
13906        }
13907
13908        let settings = self.buffer.read(cx).settings_at(0, cx);
13909        if settings.show_wrap_guides {
13910            if let SoftWrap::Column(soft_wrap) = self.soft_wrap_mode(cx) {
13911                wrap_guides.push((soft_wrap as usize, true));
13912            } else if let SoftWrap::Bounded(soft_wrap) = self.soft_wrap_mode(cx) {
13913                wrap_guides.push((soft_wrap as usize, true));
13914            }
13915            wrap_guides.extend(settings.wrap_guides.iter().map(|guide| (*guide, false)))
13916        }
13917
13918        wrap_guides
13919    }
13920
13921    pub fn soft_wrap_mode(&self, cx: &App) -> SoftWrap {
13922        let settings = self.buffer.read(cx).settings_at(0, cx);
13923        let mode = self.soft_wrap_mode_override.unwrap_or(settings.soft_wrap);
13924        match mode {
13925            language_settings::SoftWrap::PreferLine | language_settings::SoftWrap::None => {
13926                SoftWrap::None
13927            }
13928            language_settings::SoftWrap::EditorWidth => SoftWrap::EditorWidth,
13929            language_settings::SoftWrap::PreferredLineLength => {
13930                SoftWrap::Column(settings.preferred_line_length)
13931            }
13932            language_settings::SoftWrap::Bounded => {
13933                SoftWrap::Bounded(settings.preferred_line_length)
13934            }
13935        }
13936    }
13937
13938    pub fn set_soft_wrap_mode(
13939        &mut self,
13940        mode: language_settings::SoftWrap,
13941
13942        cx: &mut Context<Self>,
13943    ) {
13944        self.soft_wrap_mode_override = Some(mode);
13945        cx.notify();
13946    }
13947
13948    pub fn set_text_style_refinement(&mut self, style: TextStyleRefinement) {
13949        self.text_style_refinement = Some(style);
13950    }
13951
13952    /// called by the Element so we know what style we were most recently rendered with.
13953    pub(crate) fn set_style(
13954        &mut self,
13955        style: EditorStyle,
13956        window: &mut Window,
13957        cx: &mut Context<Self>,
13958    ) {
13959        let rem_size = window.rem_size();
13960        self.display_map.update(cx, |map, cx| {
13961            map.set_font(
13962                style.text.font(),
13963                style.text.font_size.to_pixels(rem_size),
13964                cx,
13965            )
13966        });
13967        self.style = Some(style);
13968    }
13969
13970    pub fn style(&self) -> Option<&EditorStyle> {
13971        self.style.as_ref()
13972    }
13973
13974    // Called by the element. This method is not designed to be called outside of the editor
13975    // element's layout code because it does not notify when rewrapping is computed synchronously.
13976    pub(crate) fn set_wrap_width(&self, width: Option<Pixels>, cx: &mut App) -> bool {
13977        self.display_map
13978            .update(cx, |map, cx| map.set_wrap_width(width, cx))
13979    }
13980
13981    pub fn set_soft_wrap(&mut self) {
13982        self.soft_wrap_mode_override = Some(language_settings::SoftWrap::EditorWidth)
13983    }
13984
13985    pub fn toggle_soft_wrap(&mut self, _: &ToggleSoftWrap, _: &mut Window, cx: &mut Context<Self>) {
13986        if self.soft_wrap_mode_override.is_some() {
13987            self.soft_wrap_mode_override.take();
13988        } else {
13989            let soft_wrap = match self.soft_wrap_mode(cx) {
13990                SoftWrap::GitDiff => return,
13991                SoftWrap::None => language_settings::SoftWrap::EditorWidth,
13992                SoftWrap::EditorWidth | SoftWrap::Column(_) | SoftWrap::Bounded(_) => {
13993                    language_settings::SoftWrap::None
13994                }
13995            };
13996            self.soft_wrap_mode_override = Some(soft_wrap);
13997        }
13998        cx.notify();
13999    }
14000
14001    pub fn toggle_tab_bar(&mut self, _: &ToggleTabBar, _: &mut Window, cx: &mut Context<Self>) {
14002        let Some(workspace) = self.workspace() else {
14003            return;
14004        };
14005        let fs = workspace.read(cx).app_state().fs.clone();
14006        let current_show = TabBarSettings::get_global(cx).show;
14007        update_settings_file::<TabBarSettings>(fs, cx, move |setting, _| {
14008            setting.show = Some(!current_show);
14009        });
14010    }
14011
14012    pub fn toggle_indent_guides(
14013        &mut self,
14014        _: &ToggleIndentGuides,
14015        _: &mut Window,
14016        cx: &mut Context<Self>,
14017    ) {
14018        let currently_enabled = self.should_show_indent_guides().unwrap_or_else(|| {
14019            self.buffer
14020                .read(cx)
14021                .settings_at(0, cx)
14022                .indent_guides
14023                .enabled
14024        });
14025        self.show_indent_guides = Some(!currently_enabled);
14026        cx.notify();
14027    }
14028
14029    fn should_show_indent_guides(&self) -> Option<bool> {
14030        self.show_indent_guides
14031    }
14032
14033    pub fn toggle_line_numbers(
14034        &mut self,
14035        _: &ToggleLineNumbers,
14036        _: &mut Window,
14037        cx: &mut Context<Self>,
14038    ) {
14039        let mut editor_settings = EditorSettings::get_global(cx).clone();
14040        editor_settings.gutter.line_numbers = !editor_settings.gutter.line_numbers;
14041        EditorSettings::override_global(editor_settings, cx);
14042    }
14043
14044    pub fn should_use_relative_line_numbers(&self, cx: &mut App) -> bool {
14045        self.use_relative_line_numbers
14046            .unwrap_or(EditorSettings::get_global(cx).relative_line_numbers)
14047    }
14048
14049    pub fn toggle_relative_line_numbers(
14050        &mut self,
14051        _: &ToggleRelativeLineNumbers,
14052        _: &mut Window,
14053        cx: &mut Context<Self>,
14054    ) {
14055        let is_relative = self.should_use_relative_line_numbers(cx);
14056        self.set_relative_line_number(Some(!is_relative), cx)
14057    }
14058
14059    pub fn set_relative_line_number(&mut self, is_relative: Option<bool>, cx: &mut Context<Self>) {
14060        self.use_relative_line_numbers = is_relative;
14061        cx.notify();
14062    }
14063
14064    pub fn set_show_gutter(&mut self, show_gutter: bool, cx: &mut Context<Self>) {
14065        self.show_gutter = show_gutter;
14066        cx.notify();
14067    }
14068
14069    pub fn set_show_scrollbars(&mut self, show_scrollbars: bool, cx: &mut Context<Self>) {
14070        self.show_scrollbars = show_scrollbars;
14071        cx.notify();
14072    }
14073
14074    pub fn set_show_line_numbers(&mut self, show_line_numbers: bool, cx: &mut Context<Self>) {
14075        self.show_line_numbers = Some(show_line_numbers);
14076        cx.notify();
14077    }
14078
14079    pub fn set_show_git_diff_gutter(&mut self, show_git_diff_gutter: bool, cx: &mut Context<Self>) {
14080        self.show_git_diff_gutter = Some(show_git_diff_gutter);
14081        cx.notify();
14082    }
14083
14084    pub fn set_show_code_actions(&mut self, show_code_actions: bool, cx: &mut Context<Self>) {
14085        self.show_code_actions = Some(show_code_actions);
14086        cx.notify();
14087    }
14088
14089    pub fn set_show_runnables(&mut self, show_runnables: bool, cx: &mut Context<Self>) {
14090        self.show_runnables = Some(show_runnables);
14091        cx.notify();
14092    }
14093
14094    pub fn set_masked(&mut self, masked: bool, cx: &mut Context<Self>) {
14095        if self.display_map.read(cx).masked != masked {
14096            self.display_map.update(cx, |map, _| map.masked = masked);
14097        }
14098        cx.notify()
14099    }
14100
14101    pub fn set_show_wrap_guides(&mut self, show_wrap_guides: bool, cx: &mut Context<Self>) {
14102        self.show_wrap_guides = Some(show_wrap_guides);
14103        cx.notify();
14104    }
14105
14106    pub fn set_show_indent_guides(&mut self, show_indent_guides: bool, cx: &mut Context<Self>) {
14107        self.show_indent_guides = Some(show_indent_guides);
14108        cx.notify();
14109    }
14110
14111    pub fn working_directory(&self, cx: &App) -> Option<PathBuf> {
14112        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
14113            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
14114                if let Some(dir) = file.abs_path(cx).parent() {
14115                    return Some(dir.to_owned());
14116                }
14117            }
14118
14119            if let Some(project_path) = buffer.read(cx).project_path(cx) {
14120                return Some(project_path.path.to_path_buf());
14121            }
14122        }
14123
14124        None
14125    }
14126
14127    fn target_file<'a>(&self, cx: &'a App) -> Option<&'a dyn language::LocalFile> {
14128        self.active_excerpt(cx)?
14129            .1
14130            .read(cx)
14131            .file()
14132            .and_then(|f| f.as_local())
14133    }
14134
14135    pub fn target_file_abs_path(&self, cx: &mut Context<Self>) -> Option<PathBuf> {
14136        self.active_excerpt(cx).and_then(|(_, buffer, _)| {
14137            let buffer = buffer.read(cx);
14138            if let Some(project_path) = buffer.project_path(cx) {
14139                let project = self.project.as_ref()?.read(cx);
14140                project.absolute_path(&project_path, cx)
14141            } else {
14142                buffer
14143                    .file()
14144                    .and_then(|file| file.as_local().map(|file| file.abs_path(cx)))
14145            }
14146        })
14147    }
14148
14149    fn target_file_path(&self, cx: &mut Context<Self>) -> Option<PathBuf> {
14150        self.active_excerpt(cx).and_then(|(_, buffer, _)| {
14151            let project_path = buffer.read(cx).project_path(cx)?;
14152            let project = self.project.as_ref()?.read(cx);
14153            let entry = project.entry_for_path(&project_path, cx)?;
14154            let path = entry.path.to_path_buf();
14155            Some(path)
14156        })
14157    }
14158
14159    pub fn reveal_in_finder(
14160        &mut self,
14161        _: &RevealInFileManager,
14162        _window: &mut Window,
14163        cx: &mut Context<Self>,
14164    ) {
14165        if let Some(target) = self.target_file(cx) {
14166            cx.reveal_path(&target.abs_path(cx));
14167        }
14168    }
14169
14170    pub fn copy_path(
14171        &mut self,
14172        _: &zed_actions::workspace::CopyPath,
14173        _window: &mut Window,
14174        cx: &mut Context<Self>,
14175    ) {
14176        if let Some(path) = self.target_file_abs_path(cx) {
14177            if let Some(path) = path.to_str() {
14178                cx.write_to_clipboard(ClipboardItem::new_string(path.to_string()));
14179            }
14180        }
14181    }
14182
14183    pub fn copy_relative_path(
14184        &mut self,
14185        _: &zed_actions::workspace::CopyRelativePath,
14186        _window: &mut Window,
14187        cx: &mut Context<Self>,
14188    ) {
14189        if let Some(path) = self.target_file_path(cx) {
14190            if let Some(path) = path.to_str() {
14191                cx.write_to_clipboard(ClipboardItem::new_string(path.to_string()));
14192            }
14193        }
14194    }
14195
14196    pub fn copy_file_name_without_extension(
14197        &mut self,
14198        _: &CopyFileNameWithoutExtension,
14199        _: &mut Window,
14200        cx: &mut Context<Self>,
14201    ) {
14202        if let Some(file) = self.target_file(cx) {
14203            if let Some(file_stem) = file.path().file_stem() {
14204                if let Some(name) = file_stem.to_str() {
14205                    cx.write_to_clipboard(ClipboardItem::new_string(name.to_string()));
14206                }
14207            }
14208        }
14209    }
14210
14211    pub fn copy_file_name(&mut self, _: &CopyFileName, _: &mut Window, cx: &mut Context<Self>) {
14212        if let Some(file) = self.target_file(cx) {
14213            if let Some(file_name) = file.path().file_name() {
14214                if let Some(name) = file_name.to_str() {
14215                    cx.write_to_clipboard(ClipboardItem::new_string(name.to_string()));
14216                }
14217            }
14218        }
14219    }
14220
14221    pub fn toggle_git_blame(
14222        &mut self,
14223        _: &ToggleGitBlame,
14224        window: &mut Window,
14225        cx: &mut Context<Self>,
14226    ) {
14227        self.show_git_blame_gutter = !self.show_git_blame_gutter;
14228
14229        if self.show_git_blame_gutter && !self.has_blame_entries(cx) {
14230            self.start_git_blame(true, window, cx);
14231        }
14232
14233        cx.notify();
14234    }
14235
14236    pub fn toggle_git_blame_inline(
14237        &mut self,
14238        _: &ToggleGitBlameInline,
14239        window: &mut Window,
14240        cx: &mut Context<Self>,
14241    ) {
14242        self.toggle_git_blame_inline_internal(true, window, cx);
14243        cx.notify();
14244    }
14245
14246    pub fn git_blame_inline_enabled(&self) -> bool {
14247        self.git_blame_inline_enabled
14248    }
14249
14250    pub fn toggle_selection_menu(
14251        &mut self,
14252        _: &ToggleSelectionMenu,
14253        _: &mut Window,
14254        cx: &mut Context<Self>,
14255    ) {
14256        self.show_selection_menu = self
14257            .show_selection_menu
14258            .map(|show_selections_menu| !show_selections_menu)
14259            .or_else(|| Some(!EditorSettings::get_global(cx).toolbar.selections_menu));
14260
14261        cx.notify();
14262    }
14263
14264    pub fn selection_menu_enabled(&self, cx: &App) -> bool {
14265        self.show_selection_menu
14266            .unwrap_or_else(|| EditorSettings::get_global(cx).toolbar.selections_menu)
14267    }
14268
14269    fn start_git_blame(
14270        &mut self,
14271        user_triggered: bool,
14272        window: &mut Window,
14273        cx: &mut Context<Self>,
14274    ) {
14275        if let Some(project) = self.project.as_ref() {
14276            let Some(buffer) = self.buffer().read(cx).as_singleton() else {
14277                return;
14278            };
14279
14280            if buffer.read(cx).file().is_none() {
14281                return;
14282            }
14283
14284            let focused = self.focus_handle(cx).contains_focused(window, cx);
14285
14286            let project = project.clone();
14287            let blame = cx.new(|cx| GitBlame::new(buffer, project, user_triggered, focused, cx));
14288            self.blame_subscription =
14289                Some(cx.observe_in(&blame, window, |_, _, _, cx| cx.notify()));
14290            self.blame = Some(blame);
14291        }
14292    }
14293
14294    fn toggle_git_blame_inline_internal(
14295        &mut self,
14296        user_triggered: bool,
14297        window: &mut Window,
14298        cx: &mut Context<Self>,
14299    ) {
14300        if self.git_blame_inline_enabled {
14301            self.git_blame_inline_enabled = false;
14302            self.show_git_blame_inline = false;
14303            self.show_git_blame_inline_delay_task.take();
14304        } else {
14305            self.git_blame_inline_enabled = true;
14306            self.start_git_blame_inline(user_triggered, window, cx);
14307        }
14308
14309        cx.notify();
14310    }
14311
14312    fn start_git_blame_inline(
14313        &mut self,
14314        user_triggered: bool,
14315        window: &mut Window,
14316        cx: &mut Context<Self>,
14317    ) {
14318        self.start_git_blame(user_triggered, window, cx);
14319
14320        if ProjectSettings::get_global(cx)
14321            .git
14322            .inline_blame_delay()
14323            .is_some()
14324        {
14325            self.start_inline_blame_timer(window, cx);
14326        } else {
14327            self.show_git_blame_inline = true
14328        }
14329    }
14330
14331    pub fn blame(&self) -> Option<&Entity<GitBlame>> {
14332        self.blame.as_ref()
14333    }
14334
14335    pub fn show_git_blame_gutter(&self) -> bool {
14336        self.show_git_blame_gutter
14337    }
14338
14339    pub fn render_git_blame_gutter(&self, cx: &App) -> bool {
14340        self.show_git_blame_gutter && self.has_blame_entries(cx)
14341    }
14342
14343    pub fn render_git_blame_inline(&self, window: &Window, cx: &App) -> bool {
14344        self.show_git_blame_inline
14345            && (self.focus_handle.is_focused(window)
14346                || self
14347                    .git_blame_inline_tooltip
14348                    .as_ref()
14349                    .and_then(|t| t.upgrade())
14350                    .is_some())
14351            && !self.newest_selection_head_on_empty_line(cx)
14352            && self.has_blame_entries(cx)
14353    }
14354
14355    fn has_blame_entries(&self, cx: &App) -> bool {
14356        self.blame()
14357            .map_or(false, |blame| blame.read(cx).has_generated_entries())
14358    }
14359
14360    fn newest_selection_head_on_empty_line(&self, cx: &App) -> bool {
14361        let cursor_anchor = self.selections.newest_anchor().head();
14362
14363        let snapshot = self.buffer.read(cx).snapshot(cx);
14364        let buffer_row = MultiBufferRow(cursor_anchor.to_point(&snapshot).row);
14365
14366        snapshot.line_len(buffer_row) == 0
14367    }
14368
14369    fn get_permalink_to_line(&self, cx: &mut Context<Self>) -> Task<Result<url::Url>> {
14370        let buffer_and_selection = maybe!({
14371            let selection = self.selections.newest::<Point>(cx);
14372            let selection_range = selection.range();
14373
14374            let multi_buffer = self.buffer().read(cx);
14375            let multi_buffer_snapshot = multi_buffer.snapshot(cx);
14376            let buffer_ranges = multi_buffer_snapshot.range_to_buffer_ranges(selection_range);
14377
14378            let (buffer, range, _) = if selection.reversed {
14379                buffer_ranges.first()
14380            } else {
14381                buffer_ranges.last()
14382            }?;
14383
14384            let selection = text::ToPoint::to_point(&range.start, &buffer).row
14385                ..text::ToPoint::to_point(&range.end, &buffer).row;
14386            Some((
14387                multi_buffer.buffer(buffer.remote_id()).unwrap().clone(),
14388                selection,
14389            ))
14390        });
14391
14392        let Some((buffer, selection)) = buffer_and_selection else {
14393            return Task::ready(Err(anyhow!("failed to determine buffer and selection")));
14394        };
14395
14396        let Some(project) = self.project.as_ref() else {
14397            return Task::ready(Err(anyhow!("editor does not have project")));
14398        };
14399
14400        project.update(cx, |project, cx| {
14401            project.get_permalink_to_line(&buffer, selection, cx)
14402        })
14403    }
14404
14405    pub fn copy_permalink_to_line(
14406        &mut self,
14407        _: &CopyPermalinkToLine,
14408        window: &mut Window,
14409        cx: &mut Context<Self>,
14410    ) {
14411        let permalink_task = self.get_permalink_to_line(cx);
14412        let workspace = self.workspace();
14413
14414        cx.spawn_in(window, |_, mut cx| async move {
14415            match permalink_task.await {
14416                Ok(permalink) => {
14417                    cx.update(|_, cx| {
14418                        cx.write_to_clipboard(ClipboardItem::new_string(permalink.to_string()));
14419                    })
14420                    .ok();
14421                }
14422                Err(err) => {
14423                    let message = format!("Failed to copy permalink: {err}");
14424
14425                    Err::<(), anyhow::Error>(err).log_err();
14426
14427                    if let Some(workspace) = workspace {
14428                        workspace
14429                            .update_in(&mut cx, |workspace, _, cx| {
14430                                struct CopyPermalinkToLine;
14431
14432                                workspace.show_toast(
14433                                    Toast::new(
14434                                        NotificationId::unique::<CopyPermalinkToLine>(),
14435                                        message,
14436                                    ),
14437                                    cx,
14438                                )
14439                            })
14440                            .ok();
14441                    }
14442                }
14443            }
14444        })
14445        .detach();
14446    }
14447
14448    pub fn copy_file_location(
14449        &mut self,
14450        _: &CopyFileLocation,
14451        _: &mut Window,
14452        cx: &mut Context<Self>,
14453    ) {
14454        let selection = self.selections.newest::<Point>(cx).start.row + 1;
14455        if let Some(file) = self.target_file(cx) {
14456            if let Some(path) = file.path().to_str() {
14457                cx.write_to_clipboard(ClipboardItem::new_string(format!("{path}:{selection}")));
14458            }
14459        }
14460    }
14461
14462    pub fn open_permalink_to_line(
14463        &mut self,
14464        _: &OpenPermalinkToLine,
14465        window: &mut Window,
14466        cx: &mut Context<Self>,
14467    ) {
14468        let permalink_task = self.get_permalink_to_line(cx);
14469        let workspace = self.workspace();
14470
14471        cx.spawn_in(window, |_, mut cx| async move {
14472            match permalink_task.await {
14473                Ok(permalink) => {
14474                    cx.update(|_, cx| {
14475                        cx.open_url(permalink.as_ref());
14476                    })
14477                    .ok();
14478                }
14479                Err(err) => {
14480                    let message = format!("Failed to open permalink: {err}");
14481
14482                    Err::<(), anyhow::Error>(err).log_err();
14483
14484                    if let Some(workspace) = workspace {
14485                        workspace
14486                            .update(&mut cx, |workspace, cx| {
14487                                struct OpenPermalinkToLine;
14488
14489                                workspace.show_toast(
14490                                    Toast::new(
14491                                        NotificationId::unique::<OpenPermalinkToLine>(),
14492                                        message,
14493                                    ),
14494                                    cx,
14495                                )
14496                            })
14497                            .ok();
14498                    }
14499                }
14500            }
14501        })
14502        .detach();
14503    }
14504
14505    pub fn insert_uuid_v4(
14506        &mut self,
14507        _: &InsertUuidV4,
14508        window: &mut Window,
14509        cx: &mut Context<Self>,
14510    ) {
14511        self.insert_uuid(UuidVersion::V4, window, cx);
14512    }
14513
14514    pub fn insert_uuid_v7(
14515        &mut self,
14516        _: &InsertUuidV7,
14517        window: &mut Window,
14518        cx: &mut Context<Self>,
14519    ) {
14520        self.insert_uuid(UuidVersion::V7, window, cx);
14521    }
14522
14523    fn insert_uuid(&mut self, version: UuidVersion, window: &mut Window, cx: &mut Context<Self>) {
14524        self.transact(window, cx, |this, window, cx| {
14525            let edits = this
14526                .selections
14527                .all::<Point>(cx)
14528                .into_iter()
14529                .map(|selection| {
14530                    let uuid = match version {
14531                        UuidVersion::V4 => uuid::Uuid::new_v4(),
14532                        UuidVersion::V7 => uuid::Uuid::now_v7(),
14533                    };
14534
14535                    (selection.range(), uuid.to_string())
14536                });
14537            this.edit(edits, cx);
14538            this.refresh_inline_completion(true, false, window, cx);
14539        });
14540    }
14541
14542    pub fn open_selections_in_multibuffer(
14543        &mut self,
14544        _: &OpenSelectionsInMultibuffer,
14545        window: &mut Window,
14546        cx: &mut Context<Self>,
14547    ) {
14548        let multibuffer = self.buffer.read(cx);
14549
14550        let Some(buffer) = multibuffer.as_singleton() else {
14551            return;
14552        };
14553
14554        let Some(workspace) = self.workspace() else {
14555            return;
14556        };
14557
14558        let locations = self
14559            .selections
14560            .disjoint_anchors()
14561            .iter()
14562            .map(|range| Location {
14563                buffer: buffer.clone(),
14564                range: range.start.text_anchor..range.end.text_anchor,
14565            })
14566            .collect::<Vec<_>>();
14567
14568        let title = multibuffer.title(cx).to_string();
14569
14570        cx.spawn_in(window, |_, mut cx| async move {
14571            workspace.update_in(&mut cx, |workspace, window, cx| {
14572                Self::open_locations_in_multibuffer(
14573                    workspace,
14574                    locations,
14575                    format!("Selections for '{title}'"),
14576                    false,
14577                    MultibufferSelectionMode::All,
14578                    window,
14579                    cx,
14580                );
14581            })
14582        })
14583        .detach();
14584    }
14585
14586    /// Adds a row highlight for the given range. If a row has multiple highlights, the
14587    /// last highlight added will be used.
14588    ///
14589    /// If the range ends at the beginning of a line, then that line will not be highlighted.
14590    pub fn highlight_rows<T: 'static>(
14591        &mut self,
14592        range: Range<Anchor>,
14593        color: Hsla,
14594        should_autoscroll: bool,
14595        cx: &mut Context<Self>,
14596    ) {
14597        let snapshot = self.buffer().read(cx).snapshot(cx);
14598        let row_highlights = self.highlighted_rows.entry(TypeId::of::<T>()).or_default();
14599        let ix = row_highlights.binary_search_by(|highlight| {
14600            Ordering::Equal
14601                .then_with(|| highlight.range.start.cmp(&range.start, &snapshot))
14602                .then_with(|| highlight.range.end.cmp(&range.end, &snapshot))
14603        });
14604
14605        if let Err(mut ix) = ix {
14606            let index = post_inc(&mut self.highlight_order);
14607
14608            // If this range intersects with the preceding highlight, then merge it with
14609            // the preceding highlight. Otherwise insert a new highlight.
14610            let mut merged = false;
14611            if ix > 0 {
14612                let prev_highlight = &mut row_highlights[ix - 1];
14613                if prev_highlight
14614                    .range
14615                    .end
14616                    .cmp(&range.start, &snapshot)
14617                    .is_ge()
14618                {
14619                    ix -= 1;
14620                    if prev_highlight.range.end.cmp(&range.end, &snapshot).is_lt() {
14621                        prev_highlight.range.end = range.end;
14622                    }
14623                    merged = true;
14624                    prev_highlight.index = index;
14625                    prev_highlight.color = color;
14626                    prev_highlight.should_autoscroll = should_autoscroll;
14627                }
14628            }
14629
14630            if !merged {
14631                row_highlights.insert(
14632                    ix,
14633                    RowHighlight {
14634                        range: range.clone(),
14635                        index,
14636                        color,
14637                        should_autoscroll,
14638                    },
14639                );
14640            }
14641
14642            // If any of the following highlights intersect with this one, merge them.
14643            while let Some(next_highlight) = row_highlights.get(ix + 1) {
14644                let highlight = &row_highlights[ix];
14645                if next_highlight
14646                    .range
14647                    .start
14648                    .cmp(&highlight.range.end, &snapshot)
14649                    .is_le()
14650                {
14651                    if next_highlight
14652                        .range
14653                        .end
14654                        .cmp(&highlight.range.end, &snapshot)
14655                        .is_gt()
14656                    {
14657                        row_highlights[ix].range.end = next_highlight.range.end;
14658                    }
14659                    row_highlights.remove(ix + 1);
14660                } else {
14661                    break;
14662                }
14663            }
14664        }
14665    }
14666
14667    /// Remove any highlighted row ranges of the given type that intersect the
14668    /// given ranges.
14669    pub fn remove_highlighted_rows<T: 'static>(
14670        &mut self,
14671        ranges_to_remove: Vec<Range<Anchor>>,
14672        cx: &mut Context<Self>,
14673    ) {
14674        let snapshot = self.buffer().read(cx).snapshot(cx);
14675        let row_highlights = self.highlighted_rows.entry(TypeId::of::<T>()).or_default();
14676        let mut ranges_to_remove = ranges_to_remove.iter().peekable();
14677        row_highlights.retain(|highlight| {
14678            while let Some(range_to_remove) = ranges_to_remove.peek() {
14679                match range_to_remove.end.cmp(&highlight.range.start, &snapshot) {
14680                    Ordering::Less | Ordering::Equal => {
14681                        ranges_to_remove.next();
14682                    }
14683                    Ordering::Greater => {
14684                        match range_to_remove.start.cmp(&highlight.range.end, &snapshot) {
14685                            Ordering::Less | Ordering::Equal => {
14686                                return false;
14687                            }
14688                            Ordering::Greater => break,
14689                        }
14690                    }
14691                }
14692            }
14693
14694            true
14695        })
14696    }
14697
14698    /// Clear all anchor ranges for a certain highlight context type, so no corresponding rows will be highlighted.
14699    pub fn clear_row_highlights<T: 'static>(&mut self) {
14700        self.highlighted_rows.remove(&TypeId::of::<T>());
14701    }
14702
14703    /// For a highlight given context type, gets all anchor ranges that will be used for row highlighting.
14704    pub fn highlighted_rows<T: 'static>(&self) -> impl '_ + Iterator<Item = (Range<Anchor>, Hsla)> {
14705        self.highlighted_rows
14706            .get(&TypeId::of::<T>())
14707            .map_or(&[] as &[_], |vec| vec.as_slice())
14708            .iter()
14709            .map(|highlight| (highlight.range.clone(), highlight.color))
14710    }
14711
14712    /// Merges all anchor ranges for all context types ever set, picking the last highlight added in case of a row conflict.
14713    /// Returns a map of display rows that are highlighted and their corresponding highlight color.
14714    /// Allows to ignore certain kinds of highlights.
14715    pub fn highlighted_display_rows(
14716        &self,
14717        window: &mut Window,
14718        cx: &mut App,
14719    ) -> BTreeMap<DisplayRow, Background> {
14720        let snapshot = self.snapshot(window, cx);
14721        let mut used_highlight_orders = HashMap::default();
14722        self.highlighted_rows
14723            .iter()
14724            .flat_map(|(_, highlighted_rows)| highlighted_rows.iter())
14725            .fold(
14726                BTreeMap::<DisplayRow, Background>::new(),
14727                |mut unique_rows, highlight| {
14728                    let start = highlight.range.start.to_display_point(&snapshot);
14729                    let end = highlight.range.end.to_display_point(&snapshot);
14730                    let start_row = start.row().0;
14731                    let end_row = if highlight.range.end.text_anchor != text::Anchor::MAX
14732                        && end.column() == 0
14733                    {
14734                        end.row().0.saturating_sub(1)
14735                    } else {
14736                        end.row().0
14737                    };
14738                    for row in start_row..=end_row {
14739                        let used_index =
14740                            used_highlight_orders.entry(row).or_insert(highlight.index);
14741                        if highlight.index >= *used_index {
14742                            *used_index = highlight.index;
14743                            unique_rows.insert(DisplayRow(row), highlight.color.into());
14744                        }
14745                    }
14746                    unique_rows
14747                },
14748            )
14749    }
14750
14751    pub fn highlighted_display_row_for_autoscroll(
14752        &self,
14753        snapshot: &DisplaySnapshot,
14754    ) -> Option<DisplayRow> {
14755        self.highlighted_rows
14756            .values()
14757            .flat_map(|highlighted_rows| highlighted_rows.iter())
14758            .filter_map(|highlight| {
14759                if highlight.should_autoscroll {
14760                    Some(highlight.range.start.to_display_point(snapshot).row())
14761                } else {
14762                    None
14763                }
14764            })
14765            .min()
14766    }
14767
14768    pub fn set_search_within_ranges(&mut self, ranges: &[Range<Anchor>], cx: &mut Context<Self>) {
14769        self.highlight_background::<SearchWithinRange>(
14770            ranges,
14771            |colors| colors.editor_document_highlight_read_background,
14772            cx,
14773        )
14774    }
14775
14776    pub fn set_breadcrumb_header(&mut self, new_header: String) {
14777        self.breadcrumb_header = Some(new_header);
14778    }
14779
14780    pub fn clear_search_within_ranges(&mut self, cx: &mut Context<Self>) {
14781        self.clear_background_highlights::<SearchWithinRange>(cx);
14782    }
14783
14784    pub fn highlight_background<T: 'static>(
14785        &mut self,
14786        ranges: &[Range<Anchor>],
14787        color_fetcher: fn(&ThemeColors) -> Hsla,
14788        cx: &mut Context<Self>,
14789    ) {
14790        self.background_highlights
14791            .insert(TypeId::of::<T>(), (color_fetcher, Arc::from(ranges)));
14792        self.scrollbar_marker_state.dirty = true;
14793        cx.notify();
14794    }
14795
14796    pub fn clear_background_highlights<T: 'static>(
14797        &mut self,
14798        cx: &mut Context<Self>,
14799    ) -> Option<BackgroundHighlight> {
14800        let text_highlights = self.background_highlights.remove(&TypeId::of::<T>())?;
14801        if !text_highlights.1.is_empty() {
14802            self.scrollbar_marker_state.dirty = true;
14803            cx.notify();
14804        }
14805        Some(text_highlights)
14806    }
14807
14808    pub fn highlight_gutter<T: 'static>(
14809        &mut self,
14810        ranges: &[Range<Anchor>],
14811        color_fetcher: fn(&App) -> Hsla,
14812        cx: &mut Context<Self>,
14813    ) {
14814        self.gutter_highlights
14815            .insert(TypeId::of::<T>(), (color_fetcher, Arc::from(ranges)));
14816        cx.notify();
14817    }
14818
14819    pub fn clear_gutter_highlights<T: 'static>(
14820        &mut self,
14821        cx: &mut Context<Self>,
14822    ) -> Option<GutterHighlight> {
14823        cx.notify();
14824        self.gutter_highlights.remove(&TypeId::of::<T>())
14825    }
14826
14827    #[cfg(feature = "test-support")]
14828    pub fn all_text_background_highlights(
14829        &self,
14830        window: &mut Window,
14831        cx: &mut Context<Self>,
14832    ) -> Vec<(Range<DisplayPoint>, Hsla)> {
14833        let snapshot = self.snapshot(window, cx);
14834        let buffer = &snapshot.buffer_snapshot;
14835        let start = buffer.anchor_before(0);
14836        let end = buffer.anchor_after(buffer.len());
14837        let theme = cx.theme().colors();
14838        self.background_highlights_in_range(start..end, &snapshot, theme)
14839    }
14840
14841    #[cfg(feature = "test-support")]
14842    pub fn search_background_highlights(&mut self, cx: &mut Context<Self>) -> Vec<Range<Point>> {
14843        let snapshot = self.buffer().read(cx).snapshot(cx);
14844
14845        let highlights = self
14846            .background_highlights
14847            .get(&TypeId::of::<items::BufferSearchHighlights>());
14848
14849        if let Some((_color, ranges)) = highlights {
14850            ranges
14851                .iter()
14852                .map(|range| range.start.to_point(&snapshot)..range.end.to_point(&snapshot))
14853                .collect_vec()
14854        } else {
14855            vec![]
14856        }
14857    }
14858
14859    fn document_highlights_for_position<'a>(
14860        &'a self,
14861        position: Anchor,
14862        buffer: &'a MultiBufferSnapshot,
14863    ) -> impl 'a + Iterator<Item = &'a Range<Anchor>> {
14864        let read_highlights = self
14865            .background_highlights
14866            .get(&TypeId::of::<DocumentHighlightRead>())
14867            .map(|h| &h.1);
14868        let write_highlights = self
14869            .background_highlights
14870            .get(&TypeId::of::<DocumentHighlightWrite>())
14871            .map(|h| &h.1);
14872        let left_position = position.bias_left(buffer);
14873        let right_position = position.bias_right(buffer);
14874        read_highlights
14875            .into_iter()
14876            .chain(write_highlights)
14877            .flat_map(move |ranges| {
14878                let start_ix = match ranges.binary_search_by(|probe| {
14879                    let cmp = probe.end.cmp(&left_position, buffer);
14880                    if cmp.is_ge() {
14881                        Ordering::Greater
14882                    } else {
14883                        Ordering::Less
14884                    }
14885                }) {
14886                    Ok(i) | Err(i) => i,
14887                };
14888
14889                ranges[start_ix..]
14890                    .iter()
14891                    .take_while(move |range| range.start.cmp(&right_position, buffer).is_le())
14892            })
14893    }
14894
14895    pub fn has_background_highlights<T: 'static>(&self) -> bool {
14896        self.background_highlights
14897            .get(&TypeId::of::<T>())
14898            .map_or(false, |(_, highlights)| !highlights.is_empty())
14899    }
14900
14901    pub fn background_highlights_in_range(
14902        &self,
14903        search_range: Range<Anchor>,
14904        display_snapshot: &DisplaySnapshot,
14905        theme: &ThemeColors,
14906    ) -> Vec<(Range<DisplayPoint>, Hsla)> {
14907        let mut results = Vec::new();
14908        for (color_fetcher, ranges) in self.background_highlights.values() {
14909            let color = color_fetcher(theme);
14910            let start_ix = match ranges.binary_search_by(|probe| {
14911                let cmp = probe
14912                    .end
14913                    .cmp(&search_range.start, &display_snapshot.buffer_snapshot);
14914                if cmp.is_gt() {
14915                    Ordering::Greater
14916                } else {
14917                    Ordering::Less
14918                }
14919            }) {
14920                Ok(i) | Err(i) => i,
14921            };
14922            for range in &ranges[start_ix..] {
14923                if range
14924                    .start
14925                    .cmp(&search_range.end, &display_snapshot.buffer_snapshot)
14926                    .is_ge()
14927                {
14928                    break;
14929                }
14930
14931                let start = range.start.to_display_point(display_snapshot);
14932                let end = range.end.to_display_point(display_snapshot);
14933                results.push((start..end, color))
14934            }
14935        }
14936        results
14937    }
14938
14939    pub fn background_highlight_row_ranges<T: 'static>(
14940        &self,
14941        search_range: Range<Anchor>,
14942        display_snapshot: &DisplaySnapshot,
14943        count: usize,
14944    ) -> Vec<RangeInclusive<DisplayPoint>> {
14945        let mut results = Vec::new();
14946        let Some((_, ranges)) = self.background_highlights.get(&TypeId::of::<T>()) else {
14947            return vec![];
14948        };
14949
14950        let start_ix = match ranges.binary_search_by(|probe| {
14951            let cmp = probe
14952                .end
14953                .cmp(&search_range.start, &display_snapshot.buffer_snapshot);
14954            if cmp.is_gt() {
14955                Ordering::Greater
14956            } else {
14957                Ordering::Less
14958            }
14959        }) {
14960            Ok(i) | Err(i) => i,
14961        };
14962        let mut push_region = |start: Option<Point>, end: Option<Point>| {
14963            if let (Some(start_display), Some(end_display)) = (start, end) {
14964                results.push(
14965                    start_display.to_display_point(display_snapshot)
14966                        ..=end_display.to_display_point(display_snapshot),
14967                );
14968            }
14969        };
14970        let mut start_row: Option<Point> = None;
14971        let mut end_row: Option<Point> = None;
14972        if ranges.len() > count {
14973            return Vec::new();
14974        }
14975        for range in &ranges[start_ix..] {
14976            if range
14977                .start
14978                .cmp(&search_range.end, &display_snapshot.buffer_snapshot)
14979                .is_ge()
14980            {
14981                break;
14982            }
14983            let end = range.end.to_point(&display_snapshot.buffer_snapshot);
14984            if let Some(current_row) = &end_row {
14985                if end.row == current_row.row {
14986                    continue;
14987                }
14988            }
14989            let start = range.start.to_point(&display_snapshot.buffer_snapshot);
14990            if start_row.is_none() {
14991                assert_eq!(end_row, None);
14992                start_row = Some(start);
14993                end_row = Some(end);
14994                continue;
14995            }
14996            if let Some(current_end) = end_row.as_mut() {
14997                if start.row > current_end.row + 1 {
14998                    push_region(start_row, end_row);
14999                    start_row = Some(start);
15000                    end_row = Some(end);
15001                } else {
15002                    // Merge two hunks.
15003                    *current_end = end;
15004                }
15005            } else {
15006                unreachable!();
15007            }
15008        }
15009        // We might still have a hunk that was not rendered (if there was a search hit on the last line)
15010        push_region(start_row, end_row);
15011        results
15012    }
15013
15014    pub fn gutter_highlights_in_range(
15015        &self,
15016        search_range: Range<Anchor>,
15017        display_snapshot: &DisplaySnapshot,
15018        cx: &App,
15019    ) -> Vec<(Range<DisplayPoint>, Hsla)> {
15020        let mut results = Vec::new();
15021        for (color_fetcher, ranges) in self.gutter_highlights.values() {
15022            let color = color_fetcher(cx);
15023            let start_ix = match ranges.binary_search_by(|probe| {
15024                let cmp = probe
15025                    .end
15026                    .cmp(&search_range.start, &display_snapshot.buffer_snapshot);
15027                if cmp.is_gt() {
15028                    Ordering::Greater
15029                } else {
15030                    Ordering::Less
15031                }
15032            }) {
15033                Ok(i) | Err(i) => i,
15034            };
15035            for range in &ranges[start_ix..] {
15036                if range
15037                    .start
15038                    .cmp(&search_range.end, &display_snapshot.buffer_snapshot)
15039                    .is_ge()
15040                {
15041                    break;
15042                }
15043
15044                let start = range.start.to_display_point(display_snapshot);
15045                let end = range.end.to_display_point(display_snapshot);
15046                results.push((start..end, color))
15047            }
15048        }
15049        results
15050    }
15051
15052    /// Get the text ranges corresponding to the redaction query
15053    pub fn redacted_ranges(
15054        &self,
15055        search_range: Range<Anchor>,
15056        display_snapshot: &DisplaySnapshot,
15057        cx: &App,
15058    ) -> Vec<Range<DisplayPoint>> {
15059        display_snapshot
15060            .buffer_snapshot
15061            .redacted_ranges(search_range, |file| {
15062                if let Some(file) = file {
15063                    file.is_private()
15064                        && EditorSettings::get(
15065                            Some(SettingsLocation {
15066                                worktree_id: file.worktree_id(cx),
15067                                path: file.path().as_ref(),
15068                            }),
15069                            cx,
15070                        )
15071                        .redact_private_values
15072                } else {
15073                    false
15074                }
15075            })
15076            .map(|range| {
15077                range.start.to_display_point(display_snapshot)
15078                    ..range.end.to_display_point(display_snapshot)
15079            })
15080            .collect()
15081    }
15082
15083    pub fn highlight_text<T: 'static>(
15084        &mut self,
15085        ranges: Vec<Range<Anchor>>,
15086        style: HighlightStyle,
15087        cx: &mut Context<Self>,
15088    ) {
15089        self.display_map.update(cx, |map, _| {
15090            map.highlight_text(TypeId::of::<T>(), ranges, style)
15091        });
15092        cx.notify();
15093    }
15094
15095    pub(crate) fn highlight_inlays<T: 'static>(
15096        &mut self,
15097        highlights: Vec<InlayHighlight>,
15098        style: HighlightStyle,
15099        cx: &mut Context<Self>,
15100    ) {
15101        self.display_map.update(cx, |map, _| {
15102            map.highlight_inlays(TypeId::of::<T>(), highlights, style)
15103        });
15104        cx.notify();
15105    }
15106
15107    pub fn text_highlights<'a, T: 'static>(
15108        &'a self,
15109        cx: &'a App,
15110    ) -> Option<(HighlightStyle, &'a [Range<Anchor>])> {
15111        self.display_map.read(cx).text_highlights(TypeId::of::<T>())
15112    }
15113
15114    pub fn clear_highlights<T: 'static>(&mut self, cx: &mut Context<Self>) {
15115        let cleared = self
15116            .display_map
15117            .update(cx, |map, _| map.clear_highlights(TypeId::of::<T>()));
15118        if cleared {
15119            cx.notify();
15120        }
15121    }
15122
15123    pub fn show_local_cursors(&self, window: &mut Window, cx: &mut App) -> bool {
15124        (self.read_only(cx) || self.blink_manager.read(cx).visible())
15125            && self.focus_handle.is_focused(window)
15126    }
15127
15128    pub fn set_show_cursor_when_unfocused(&mut self, is_enabled: bool, cx: &mut Context<Self>) {
15129        self.show_cursor_when_unfocused = is_enabled;
15130        cx.notify();
15131    }
15132
15133    fn on_buffer_changed(&mut self, _: Entity<MultiBuffer>, cx: &mut Context<Self>) {
15134        cx.notify();
15135    }
15136
15137    fn on_buffer_event(
15138        &mut self,
15139        multibuffer: &Entity<MultiBuffer>,
15140        event: &multi_buffer::Event,
15141        window: &mut Window,
15142        cx: &mut Context<Self>,
15143    ) {
15144        match event {
15145            multi_buffer::Event::Edited {
15146                singleton_buffer_edited,
15147                edited_buffer: buffer_edited,
15148            } => {
15149                self.scrollbar_marker_state.dirty = true;
15150                self.active_indent_guides_state.dirty = true;
15151                self.refresh_active_diagnostics(cx);
15152                self.refresh_code_actions(window, cx);
15153                if self.has_active_inline_completion() {
15154                    self.update_visible_inline_completion(window, cx);
15155                }
15156                if let Some(buffer) = buffer_edited {
15157                    let buffer_id = buffer.read(cx).remote_id();
15158                    if !self.registered_buffers.contains_key(&buffer_id) {
15159                        if let Some(project) = self.project.as_ref() {
15160                            project.update(cx, |project, cx| {
15161                                self.registered_buffers.insert(
15162                                    buffer_id,
15163                                    project.register_buffer_with_language_servers(&buffer, cx),
15164                                );
15165                            })
15166                        }
15167                    }
15168                }
15169                cx.emit(EditorEvent::BufferEdited);
15170                cx.emit(SearchEvent::MatchesInvalidated);
15171                if *singleton_buffer_edited {
15172                    if let Some(project) = &self.project {
15173                        #[allow(clippy::mutable_key_type)]
15174                        let languages_affected = multibuffer.update(cx, |multibuffer, cx| {
15175                            multibuffer
15176                                .all_buffers()
15177                                .into_iter()
15178                                .filter_map(|buffer| {
15179                                    buffer.update(cx, |buffer, cx| {
15180                                        let language = buffer.language()?;
15181                                        let should_discard = project.update(cx, |project, cx| {
15182                                            project.is_local()
15183                                                && !project.has_language_servers_for(buffer, cx)
15184                                        });
15185                                        should_discard.not().then_some(language.clone())
15186                                    })
15187                                })
15188                                .collect::<HashSet<_>>()
15189                        });
15190                        if !languages_affected.is_empty() {
15191                            self.refresh_inlay_hints(
15192                                InlayHintRefreshReason::BufferEdited(languages_affected),
15193                                cx,
15194                            );
15195                        }
15196                    }
15197                }
15198
15199                let Some(project) = &self.project else { return };
15200                let (telemetry, is_via_ssh) = {
15201                    let project = project.read(cx);
15202                    let telemetry = project.client().telemetry().clone();
15203                    let is_via_ssh = project.is_via_ssh();
15204                    (telemetry, is_via_ssh)
15205                };
15206                refresh_linked_ranges(self, window, cx);
15207                telemetry.log_edit_event("editor", is_via_ssh);
15208            }
15209            multi_buffer::Event::ExcerptsAdded {
15210                buffer,
15211                predecessor,
15212                excerpts,
15213            } => {
15214                self.tasks_update_task = Some(self.refresh_runnables(window, cx));
15215                let buffer_id = buffer.read(cx).remote_id();
15216                if self.buffer.read(cx).diff_for(buffer_id).is_none() {
15217                    if let Some(project) = &self.project {
15218                        get_uncommitted_diff_for_buffer(
15219                            project,
15220                            [buffer.clone()],
15221                            self.buffer.clone(),
15222                            cx,
15223                        )
15224                        .detach();
15225                    }
15226                }
15227                cx.emit(EditorEvent::ExcerptsAdded {
15228                    buffer: buffer.clone(),
15229                    predecessor: *predecessor,
15230                    excerpts: excerpts.clone(),
15231                });
15232                self.refresh_inlay_hints(InlayHintRefreshReason::NewLinesShown, cx);
15233            }
15234            multi_buffer::Event::ExcerptsRemoved { ids } => {
15235                self.refresh_inlay_hints(InlayHintRefreshReason::ExcerptsRemoved(ids.clone()), cx);
15236                let buffer = self.buffer.read(cx);
15237                self.registered_buffers
15238                    .retain(|buffer_id, _| buffer.buffer(*buffer_id).is_some());
15239                cx.emit(EditorEvent::ExcerptsRemoved { ids: ids.clone() })
15240            }
15241            multi_buffer::Event::ExcerptsEdited {
15242                excerpt_ids,
15243                buffer_ids,
15244            } => {
15245                self.display_map.update(cx, |map, cx| {
15246                    map.unfold_buffers(buffer_ids.iter().copied(), cx)
15247                });
15248                cx.emit(EditorEvent::ExcerptsEdited {
15249                    ids: excerpt_ids.clone(),
15250                })
15251            }
15252            multi_buffer::Event::ExcerptsExpanded { ids } => {
15253                self.refresh_inlay_hints(InlayHintRefreshReason::NewLinesShown, cx);
15254                cx.emit(EditorEvent::ExcerptsExpanded { ids: ids.clone() })
15255            }
15256            multi_buffer::Event::Reparsed(buffer_id) => {
15257                self.tasks_update_task = Some(self.refresh_runnables(window, cx));
15258
15259                cx.emit(EditorEvent::Reparsed(*buffer_id));
15260            }
15261            multi_buffer::Event::DiffHunksToggled => {
15262                self.tasks_update_task = Some(self.refresh_runnables(window, cx));
15263            }
15264            multi_buffer::Event::LanguageChanged(buffer_id) => {
15265                linked_editing_ranges::refresh_linked_ranges(self, window, cx);
15266                cx.emit(EditorEvent::Reparsed(*buffer_id));
15267                cx.notify();
15268            }
15269            multi_buffer::Event::DirtyChanged => cx.emit(EditorEvent::DirtyChanged),
15270            multi_buffer::Event::Saved => cx.emit(EditorEvent::Saved),
15271            multi_buffer::Event::FileHandleChanged | multi_buffer::Event::Reloaded => {
15272                cx.emit(EditorEvent::TitleChanged)
15273            }
15274            // multi_buffer::Event::DiffBaseChanged => {
15275            //     self.scrollbar_marker_state.dirty = true;
15276            //     cx.emit(EditorEvent::DiffBaseChanged);
15277            //     cx.notify();
15278            // }
15279            multi_buffer::Event::Closed => cx.emit(EditorEvent::Closed),
15280            multi_buffer::Event::DiagnosticsUpdated => {
15281                self.refresh_active_diagnostics(cx);
15282                self.refresh_inline_diagnostics(true, window, cx);
15283                self.scrollbar_marker_state.dirty = true;
15284                cx.notify();
15285            }
15286            _ => {}
15287        };
15288    }
15289
15290    fn on_display_map_changed(
15291        &mut self,
15292        _: Entity<DisplayMap>,
15293        _: &mut Window,
15294        cx: &mut Context<Self>,
15295    ) {
15296        cx.notify();
15297    }
15298
15299    fn settings_changed(&mut self, window: &mut Window, cx: &mut Context<Self>) {
15300        self.tasks_update_task = Some(self.refresh_runnables(window, cx));
15301        self.update_edit_prediction_settings(cx);
15302        self.refresh_inline_completion(true, false, window, cx);
15303        self.refresh_inlay_hints(
15304            InlayHintRefreshReason::SettingsChange(inlay_hint_settings(
15305                self.selections.newest_anchor().head(),
15306                &self.buffer.read(cx).snapshot(cx),
15307                cx,
15308            )),
15309            cx,
15310        );
15311
15312        let old_cursor_shape = self.cursor_shape;
15313
15314        {
15315            let editor_settings = EditorSettings::get_global(cx);
15316            self.scroll_manager.vertical_scroll_margin = editor_settings.vertical_scroll_margin;
15317            self.show_breadcrumbs = editor_settings.toolbar.breadcrumbs;
15318            self.cursor_shape = editor_settings.cursor_shape.unwrap_or_default();
15319        }
15320
15321        if old_cursor_shape != self.cursor_shape {
15322            cx.emit(EditorEvent::CursorShapeChanged);
15323        }
15324
15325        let project_settings = ProjectSettings::get_global(cx);
15326        self.serialize_dirty_buffers = project_settings.session.restore_unsaved_buffers;
15327
15328        if self.mode == EditorMode::Full {
15329            let show_inline_diagnostics = project_settings.diagnostics.inline.enabled;
15330            let inline_blame_enabled = project_settings.git.inline_blame_enabled();
15331            if self.show_inline_diagnostics != show_inline_diagnostics {
15332                self.show_inline_diagnostics = show_inline_diagnostics;
15333                self.refresh_inline_diagnostics(false, window, cx);
15334            }
15335
15336            if self.git_blame_inline_enabled != inline_blame_enabled {
15337                self.toggle_git_blame_inline_internal(false, window, cx);
15338            }
15339        }
15340
15341        cx.notify();
15342    }
15343
15344    pub fn set_searchable(&mut self, searchable: bool) {
15345        self.searchable = searchable;
15346    }
15347
15348    pub fn searchable(&self) -> bool {
15349        self.searchable
15350    }
15351
15352    fn open_proposed_changes_editor(
15353        &mut self,
15354        _: &OpenProposedChangesEditor,
15355        window: &mut Window,
15356        cx: &mut Context<Self>,
15357    ) {
15358        let Some(workspace) = self.workspace() else {
15359            cx.propagate();
15360            return;
15361        };
15362
15363        let selections = self.selections.all::<usize>(cx);
15364        let multi_buffer = self.buffer.read(cx);
15365        let multi_buffer_snapshot = multi_buffer.snapshot(cx);
15366        let mut new_selections_by_buffer = HashMap::default();
15367        for selection in selections {
15368            for (buffer, range, _) in
15369                multi_buffer_snapshot.range_to_buffer_ranges(selection.start..selection.end)
15370            {
15371                let mut range = range.to_point(buffer);
15372                range.start.column = 0;
15373                range.end.column = buffer.line_len(range.end.row);
15374                new_selections_by_buffer
15375                    .entry(multi_buffer.buffer(buffer.remote_id()).unwrap())
15376                    .or_insert(Vec::new())
15377                    .push(range)
15378            }
15379        }
15380
15381        let proposed_changes_buffers = new_selections_by_buffer
15382            .into_iter()
15383            .map(|(buffer, ranges)| ProposedChangeLocation { buffer, ranges })
15384            .collect::<Vec<_>>();
15385        let proposed_changes_editor = cx.new(|cx| {
15386            ProposedChangesEditor::new(
15387                "Proposed changes",
15388                proposed_changes_buffers,
15389                self.project.clone(),
15390                window,
15391                cx,
15392            )
15393        });
15394
15395        window.defer(cx, move |window, cx| {
15396            workspace.update(cx, |workspace, cx| {
15397                workspace.active_pane().update(cx, |pane, cx| {
15398                    pane.add_item(
15399                        Box::new(proposed_changes_editor),
15400                        true,
15401                        true,
15402                        None,
15403                        window,
15404                        cx,
15405                    );
15406                });
15407            });
15408        });
15409    }
15410
15411    pub fn open_excerpts_in_split(
15412        &mut self,
15413        _: &OpenExcerptsSplit,
15414        window: &mut Window,
15415        cx: &mut Context<Self>,
15416    ) {
15417        self.open_excerpts_common(None, true, window, cx)
15418    }
15419
15420    pub fn open_excerpts(&mut self, _: &OpenExcerpts, window: &mut Window, cx: &mut Context<Self>) {
15421        self.open_excerpts_common(None, false, window, cx)
15422    }
15423
15424    fn open_excerpts_common(
15425        &mut self,
15426        jump_data: Option<JumpData>,
15427        split: bool,
15428        window: &mut Window,
15429        cx: &mut Context<Self>,
15430    ) {
15431        let Some(workspace) = self.workspace() else {
15432            cx.propagate();
15433            return;
15434        };
15435
15436        if self.buffer.read(cx).is_singleton() {
15437            cx.propagate();
15438            return;
15439        }
15440
15441        let mut new_selections_by_buffer = HashMap::default();
15442        match &jump_data {
15443            Some(JumpData::MultiBufferPoint {
15444                excerpt_id,
15445                position,
15446                anchor,
15447                line_offset_from_top,
15448            }) => {
15449                let multi_buffer_snapshot = self.buffer.read(cx).snapshot(cx);
15450                if let Some(buffer) = multi_buffer_snapshot
15451                    .buffer_id_for_excerpt(*excerpt_id)
15452                    .and_then(|buffer_id| self.buffer.read(cx).buffer(buffer_id))
15453                {
15454                    let buffer_snapshot = buffer.read(cx).snapshot();
15455                    let jump_to_point = if buffer_snapshot.can_resolve(anchor) {
15456                        language::ToPoint::to_point(anchor, &buffer_snapshot)
15457                    } else {
15458                        buffer_snapshot.clip_point(*position, Bias::Left)
15459                    };
15460                    let jump_to_offset = buffer_snapshot.point_to_offset(jump_to_point);
15461                    new_selections_by_buffer.insert(
15462                        buffer,
15463                        (
15464                            vec![jump_to_offset..jump_to_offset],
15465                            Some(*line_offset_from_top),
15466                        ),
15467                    );
15468                }
15469            }
15470            Some(JumpData::MultiBufferRow {
15471                row,
15472                line_offset_from_top,
15473            }) => {
15474                let point = MultiBufferPoint::new(row.0, 0);
15475                if let Some((buffer, buffer_point, _)) =
15476                    self.buffer.read(cx).point_to_buffer_point(point, cx)
15477                {
15478                    let buffer_offset = buffer.read(cx).point_to_offset(buffer_point);
15479                    new_selections_by_buffer
15480                        .entry(buffer)
15481                        .or_insert((Vec::new(), Some(*line_offset_from_top)))
15482                        .0
15483                        .push(buffer_offset..buffer_offset)
15484                }
15485            }
15486            None => {
15487                let selections = self.selections.all::<usize>(cx);
15488                let multi_buffer = self.buffer.read(cx);
15489                for selection in selections {
15490                    for (snapshot, range, _, anchor) in multi_buffer
15491                        .snapshot(cx)
15492                        .range_to_buffer_ranges_with_deleted_hunks(selection.range())
15493                    {
15494                        if let Some(anchor) = anchor {
15495                            // selection is in a deleted hunk
15496                            let Some(buffer_id) = anchor.buffer_id else {
15497                                continue;
15498                            };
15499                            let Some(buffer_handle) = multi_buffer.buffer(buffer_id) else {
15500                                continue;
15501                            };
15502                            let offset = text::ToOffset::to_offset(
15503                                &anchor.text_anchor,
15504                                &buffer_handle.read(cx).snapshot(),
15505                            );
15506                            let range = offset..offset;
15507                            new_selections_by_buffer
15508                                .entry(buffer_handle)
15509                                .or_insert((Vec::new(), None))
15510                                .0
15511                                .push(range)
15512                        } else {
15513                            let Some(buffer_handle) = multi_buffer.buffer(snapshot.remote_id())
15514                            else {
15515                                continue;
15516                            };
15517                            new_selections_by_buffer
15518                                .entry(buffer_handle)
15519                                .or_insert((Vec::new(), None))
15520                                .0
15521                                .push(range)
15522                        }
15523                    }
15524                }
15525            }
15526        }
15527
15528        if new_selections_by_buffer.is_empty() {
15529            return;
15530        }
15531
15532        // We defer the pane interaction because we ourselves are a workspace item
15533        // and activating a new item causes the pane to call a method on us reentrantly,
15534        // which panics if we're on the stack.
15535        window.defer(cx, move |window, cx| {
15536            workspace.update(cx, |workspace, cx| {
15537                let pane = if split {
15538                    workspace.adjacent_pane(window, cx)
15539                } else {
15540                    workspace.active_pane().clone()
15541                };
15542
15543                for (buffer, (ranges, scroll_offset)) in new_selections_by_buffer {
15544                    let editor = buffer
15545                        .read(cx)
15546                        .file()
15547                        .is_none()
15548                        .then(|| {
15549                            // Handle file-less buffers separately: those are not really the project items, so won't have a project path or entity id,
15550                            // so `workspace.open_project_item` will never find them, always opening a new editor.
15551                            // Instead, we try to activate the existing editor in the pane first.
15552                            let (editor, pane_item_index) =
15553                                pane.read(cx).items().enumerate().find_map(|(i, item)| {
15554                                    let editor = item.downcast::<Editor>()?;
15555                                    let singleton_buffer =
15556                                        editor.read(cx).buffer().read(cx).as_singleton()?;
15557                                    if singleton_buffer == buffer {
15558                                        Some((editor, i))
15559                                    } else {
15560                                        None
15561                                    }
15562                                })?;
15563                            pane.update(cx, |pane, cx| {
15564                                pane.activate_item(pane_item_index, true, true, window, cx)
15565                            });
15566                            Some(editor)
15567                        })
15568                        .flatten()
15569                        .unwrap_or_else(|| {
15570                            workspace.open_project_item::<Self>(
15571                                pane.clone(),
15572                                buffer,
15573                                true,
15574                                true,
15575                                window,
15576                                cx,
15577                            )
15578                        });
15579
15580                    editor.update(cx, |editor, cx| {
15581                        let autoscroll = match scroll_offset {
15582                            Some(scroll_offset) => Autoscroll::top_relative(scroll_offset as usize),
15583                            None => Autoscroll::newest(),
15584                        };
15585                        let nav_history = editor.nav_history.take();
15586                        editor.change_selections(Some(autoscroll), window, cx, |s| {
15587                            s.select_ranges(ranges);
15588                        });
15589                        editor.nav_history = nav_history;
15590                    });
15591                }
15592            })
15593        });
15594    }
15595
15596    fn marked_text_ranges(&self, cx: &App) -> Option<Vec<Range<OffsetUtf16>>> {
15597        let snapshot = self.buffer.read(cx).read(cx);
15598        let (_, ranges) = self.text_highlights::<InputComposition>(cx)?;
15599        Some(
15600            ranges
15601                .iter()
15602                .map(move |range| {
15603                    range.start.to_offset_utf16(&snapshot)..range.end.to_offset_utf16(&snapshot)
15604                })
15605                .collect(),
15606        )
15607    }
15608
15609    fn selection_replacement_ranges(
15610        &self,
15611        range: Range<OffsetUtf16>,
15612        cx: &mut App,
15613    ) -> Vec<Range<OffsetUtf16>> {
15614        let selections = self.selections.all::<OffsetUtf16>(cx);
15615        let newest_selection = selections
15616            .iter()
15617            .max_by_key(|selection| selection.id)
15618            .unwrap();
15619        let start_delta = range.start.0 as isize - newest_selection.start.0 as isize;
15620        let end_delta = range.end.0 as isize - newest_selection.end.0 as isize;
15621        let snapshot = self.buffer.read(cx).read(cx);
15622        selections
15623            .into_iter()
15624            .map(|mut selection| {
15625                selection.start.0 =
15626                    (selection.start.0 as isize).saturating_add(start_delta) as usize;
15627                selection.end.0 = (selection.end.0 as isize).saturating_add(end_delta) as usize;
15628                snapshot.clip_offset_utf16(selection.start, Bias::Left)
15629                    ..snapshot.clip_offset_utf16(selection.end, Bias::Right)
15630            })
15631            .collect()
15632    }
15633
15634    fn report_editor_event(
15635        &self,
15636        event_type: &'static str,
15637        file_extension: Option<String>,
15638        cx: &App,
15639    ) {
15640        if cfg!(any(test, feature = "test-support")) {
15641            return;
15642        }
15643
15644        let Some(project) = &self.project else { return };
15645
15646        // If None, we are in a file without an extension
15647        let file = self
15648            .buffer
15649            .read(cx)
15650            .as_singleton()
15651            .and_then(|b| b.read(cx).file());
15652        let file_extension = file_extension.or(file
15653            .as_ref()
15654            .and_then(|file| Path::new(file.file_name(cx)).extension())
15655            .and_then(|e| e.to_str())
15656            .map(|a| a.to_string()));
15657
15658        let vim_mode = cx
15659            .global::<SettingsStore>()
15660            .raw_user_settings()
15661            .get("vim_mode")
15662            == Some(&serde_json::Value::Bool(true));
15663
15664        let edit_predictions_provider = all_language_settings(file, cx).edit_predictions.provider;
15665        let copilot_enabled = edit_predictions_provider
15666            == language::language_settings::EditPredictionProvider::Copilot;
15667        let copilot_enabled_for_language = self
15668            .buffer
15669            .read(cx)
15670            .settings_at(0, cx)
15671            .show_edit_predictions;
15672
15673        let project = project.read(cx);
15674        telemetry::event!(
15675            event_type,
15676            file_extension,
15677            vim_mode,
15678            copilot_enabled,
15679            copilot_enabled_for_language,
15680            edit_predictions_provider,
15681            is_via_ssh = project.is_via_ssh(),
15682        );
15683    }
15684
15685    /// Copy the highlighted chunks to the clipboard as JSON. The format is an array of lines,
15686    /// with each line being an array of {text, highlight} objects.
15687    fn copy_highlight_json(
15688        &mut self,
15689        _: &CopyHighlightJson,
15690        window: &mut Window,
15691        cx: &mut Context<Self>,
15692    ) {
15693        #[derive(Serialize)]
15694        struct Chunk<'a> {
15695            text: String,
15696            highlight: Option<&'a str>,
15697        }
15698
15699        let snapshot = self.buffer.read(cx).snapshot(cx);
15700        let range = self
15701            .selected_text_range(false, window, cx)
15702            .and_then(|selection| {
15703                if selection.range.is_empty() {
15704                    None
15705                } else {
15706                    Some(selection.range)
15707                }
15708            })
15709            .unwrap_or_else(|| 0..snapshot.len());
15710
15711        let chunks = snapshot.chunks(range, true);
15712        let mut lines = Vec::new();
15713        let mut line: VecDeque<Chunk> = VecDeque::new();
15714
15715        let Some(style) = self.style.as_ref() else {
15716            return;
15717        };
15718
15719        for chunk in chunks {
15720            let highlight = chunk
15721                .syntax_highlight_id
15722                .and_then(|id| id.name(&style.syntax));
15723            let mut chunk_lines = chunk.text.split('\n').peekable();
15724            while let Some(text) = chunk_lines.next() {
15725                let mut merged_with_last_token = false;
15726                if let Some(last_token) = line.back_mut() {
15727                    if last_token.highlight == highlight {
15728                        last_token.text.push_str(text);
15729                        merged_with_last_token = true;
15730                    }
15731                }
15732
15733                if !merged_with_last_token {
15734                    line.push_back(Chunk {
15735                        text: text.into(),
15736                        highlight,
15737                    });
15738                }
15739
15740                if chunk_lines.peek().is_some() {
15741                    if line.len() > 1 && line.front().unwrap().text.is_empty() {
15742                        line.pop_front();
15743                    }
15744                    if line.len() > 1 && line.back().unwrap().text.is_empty() {
15745                        line.pop_back();
15746                    }
15747
15748                    lines.push(mem::take(&mut line));
15749                }
15750            }
15751        }
15752
15753        let Some(lines) = serde_json::to_string_pretty(&lines).log_err() else {
15754            return;
15755        };
15756        cx.write_to_clipboard(ClipboardItem::new_string(lines));
15757    }
15758
15759    pub fn open_context_menu(
15760        &mut self,
15761        _: &OpenContextMenu,
15762        window: &mut Window,
15763        cx: &mut Context<Self>,
15764    ) {
15765        self.request_autoscroll(Autoscroll::newest(), cx);
15766        let position = self.selections.newest_display(cx).start;
15767        mouse_context_menu::deploy_context_menu(self, None, position, window, cx);
15768    }
15769
15770    pub fn inlay_hint_cache(&self) -> &InlayHintCache {
15771        &self.inlay_hint_cache
15772    }
15773
15774    pub fn replay_insert_event(
15775        &mut self,
15776        text: &str,
15777        relative_utf16_range: Option<Range<isize>>,
15778        window: &mut Window,
15779        cx: &mut Context<Self>,
15780    ) {
15781        if !self.input_enabled {
15782            cx.emit(EditorEvent::InputIgnored { text: text.into() });
15783            return;
15784        }
15785        if let Some(relative_utf16_range) = relative_utf16_range {
15786            let selections = self.selections.all::<OffsetUtf16>(cx);
15787            self.change_selections(None, window, cx, |s| {
15788                let new_ranges = selections.into_iter().map(|range| {
15789                    let start = OffsetUtf16(
15790                        range
15791                            .head()
15792                            .0
15793                            .saturating_add_signed(relative_utf16_range.start),
15794                    );
15795                    let end = OffsetUtf16(
15796                        range
15797                            .head()
15798                            .0
15799                            .saturating_add_signed(relative_utf16_range.end),
15800                    );
15801                    start..end
15802                });
15803                s.select_ranges(new_ranges);
15804            });
15805        }
15806
15807        self.handle_input(text, window, cx);
15808    }
15809
15810    pub fn supports_inlay_hints(&self, cx: &mut App) -> bool {
15811        let Some(provider) = self.semantics_provider.as_ref() else {
15812            return false;
15813        };
15814
15815        let mut supports = false;
15816        self.buffer().update(cx, |this, cx| {
15817            this.for_each_buffer(|buffer| {
15818                supports |= provider.supports_inlay_hints(buffer, cx);
15819            });
15820        });
15821
15822        supports
15823    }
15824
15825    pub fn is_focused(&self, window: &Window) -> bool {
15826        self.focus_handle.is_focused(window)
15827    }
15828
15829    fn handle_focus(&mut self, window: &mut Window, cx: &mut Context<Self>) {
15830        cx.emit(EditorEvent::Focused);
15831
15832        if let Some(descendant) = self
15833            .last_focused_descendant
15834            .take()
15835            .and_then(|descendant| descendant.upgrade())
15836        {
15837            window.focus(&descendant);
15838        } else {
15839            if let Some(blame) = self.blame.as_ref() {
15840                blame.update(cx, GitBlame::focus)
15841            }
15842
15843            self.blink_manager.update(cx, BlinkManager::enable);
15844            self.show_cursor_names(window, cx);
15845            self.buffer.update(cx, |buffer, cx| {
15846                buffer.finalize_last_transaction(cx);
15847                if self.leader_peer_id.is_none() {
15848                    buffer.set_active_selections(
15849                        &self.selections.disjoint_anchors(),
15850                        self.selections.line_mode,
15851                        self.cursor_shape,
15852                        cx,
15853                    );
15854                }
15855            });
15856        }
15857    }
15858
15859    fn handle_focus_in(&mut self, _: &mut Window, cx: &mut Context<Self>) {
15860        cx.emit(EditorEvent::FocusedIn)
15861    }
15862
15863    fn handle_focus_out(
15864        &mut self,
15865        event: FocusOutEvent,
15866        _window: &mut Window,
15867        cx: &mut Context<Self>,
15868    ) {
15869        if event.blurred != self.focus_handle {
15870            self.last_focused_descendant = Some(event.blurred);
15871        }
15872        self.refresh_inlay_hints(InlayHintRefreshReason::ModifiersChanged(false), cx);
15873    }
15874
15875    pub fn handle_blur(&mut self, window: &mut Window, cx: &mut Context<Self>) {
15876        self.blink_manager.update(cx, BlinkManager::disable);
15877        self.buffer
15878            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
15879
15880        if let Some(blame) = self.blame.as_ref() {
15881            blame.update(cx, GitBlame::blur)
15882        }
15883        if !self.hover_state.focused(window, cx) {
15884            hide_hover(self, cx);
15885        }
15886        if !self
15887            .context_menu
15888            .borrow()
15889            .as_ref()
15890            .is_some_and(|context_menu| context_menu.focused(window, cx))
15891        {
15892            self.hide_context_menu(window, cx);
15893        }
15894        self.discard_inline_completion(false, cx);
15895        cx.emit(EditorEvent::Blurred);
15896        cx.notify();
15897    }
15898
15899    pub fn register_action<A: Action>(
15900        &mut self,
15901        listener: impl Fn(&A, &mut Window, &mut App) + 'static,
15902    ) -> Subscription {
15903        let id = self.next_editor_action_id.post_inc();
15904        let listener = Arc::new(listener);
15905        self.editor_actions.borrow_mut().insert(
15906            id,
15907            Box::new(move |window, _| {
15908                let listener = listener.clone();
15909                window.on_action(TypeId::of::<A>(), move |action, phase, window, cx| {
15910                    let action = action.downcast_ref().unwrap();
15911                    if phase == DispatchPhase::Bubble {
15912                        listener(action, window, cx)
15913                    }
15914                })
15915            }),
15916        );
15917
15918        let editor_actions = self.editor_actions.clone();
15919        Subscription::new(move || {
15920            editor_actions.borrow_mut().remove(&id);
15921        })
15922    }
15923
15924    pub fn file_header_size(&self) -> u32 {
15925        FILE_HEADER_HEIGHT
15926    }
15927
15928    pub fn restore(
15929        &mut self,
15930        revert_changes: HashMap<BufferId, Vec<(Range<text::Anchor>, Rope)>>,
15931        window: &mut Window,
15932        cx: &mut Context<Self>,
15933    ) {
15934        let workspace = self.workspace();
15935        let project = self.project.as_ref();
15936        let save_tasks = self.buffer().update(cx, |multi_buffer, cx| {
15937            let mut tasks = Vec::new();
15938            for (buffer_id, changes) in revert_changes {
15939                if let Some(buffer) = multi_buffer.buffer(buffer_id) {
15940                    buffer.update(cx, |buffer, cx| {
15941                        buffer.edit(
15942                            changes.into_iter().map(|(range, text)| {
15943                                (range, text.to_string().map(Arc::<str>::from))
15944                            }),
15945                            None,
15946                            cx,
15947                        );
15948                    });
15949
15950                    if let Some(project) =
15951                        project.filter(|_| multi_buffer.all_diff_hunks_expanded())
15952                    {
15953                        project.update(cx, |project, cx| {
15954                            tasks.push((buffer.clone(), project.save_buffer(buffer, cx)));
15955                        })
15956                    }
15957                }
15958            }
15959            tasks
15960        });
15961        cx.spawn_in(window, |_, mut cx| async move {
15962            for (buffer, task) in save_tasks {
15963                let result = task.await;
15964                if result.is_err() {
15965                    let Some(path) = buffer
15966                        .read_with(&cx, |buffer, cx| buffer.project_path(cx))
15967                        .ok()
15968                    else {
15969                        continue;
15970                    };
15971                    if let Some((workspace, path)) = workspace.as_ref().zip(path) {
15972                        let Some(task) = cx
15973                            .update_window_entity(&workspace, |workspace, window, cx| {
15974                                workspace
15975                                    .open_path_preview(path, None, false, false, false, window, cx)
15976                            })
15977                            .ok()
15978                        else {
15979                            continue;
15980                        };
15981                        task.await.log_err();
15982                    }
15983                }
15984            }
15985        })
15986        .detach();
15987        self.change_selections(None, window, cx, |selections| selections.refresh());
15988    }
15989
15990    pub fn to_pixel_point(
15991        &self,
15992        source: multi_buffer::Anchor,
15993        editor_snapshot: &EditorSnapshot,
15994        window: &mut Window,
15995    ) -> Option<gpui::Point<Pixels>> {
15996        let source_point = source.to_display_point(editor_snapshot);
15997        self.display_to_pixel_point(source_point, editor_snapshot, window)
15998    }
15999
16000    pub fn display_to_pixel_point(
16001        &self,
16002        source: DisplayPoint,
16003        editor_snapshot: &EditorSnapshot,
16004        window: &mut Window,
16005    ) -> Option<gpui::Point<Pixels>> {
16006        let line_height = self.style()?.text.line_height_in_pixels(window.rem_size());
16007        let text_layout_details = self.text_layout_details(window);
16008        let scroll_top = text_layout_details
16009            .scroll_anchor
16010            .scroll_position(editor_snapshot)
16011            .y;
16012
16013        if source.row().as_f32() < scroll_top.floor() {
16014            return None;
16015        }
16016        let source_x = editor_snapshot.x_for_display_point(source, &text_layout_details);
16017        let source_y = line_height * (source.row().as_f32() - scroll_top);
16018        Some(gpui::Point::new(source_x, source_y))
16019    }
16020
16021    pub fn has_visible_completions_menu(&self) -> bool {
16022        !self.edit_prediction_preview_is_active()
16023            && self.context_menu.borrow().as_ref().map_or(false, |menu| {
16024                menu.visible() && matches!(menu, CodeContextMenu::Completions(_))
16025            })
16026    }
16027
16028    pub fn register_addon<T: Addon>(&mut self, instance: T) {
16029        self.addons
16030            .insert(std::any::TypeId::of::<T>(), Box::new(instance));
16031    }
16032
16033    pub fn unregister_addon<T: Addon>(&mut self) {
16034        self.addons.remove(&std::any::TypeId::of::<T>());
16035    }
16036
16037    pub fn addon<T: Addon>(&self) -> Option<&T> {
16038        let type_id = std::any::TypeId::of::<T>();
16039        self.addons
16040            .get(&type_id)
16041            .and_then(|item| item.to_any().downcast_ref::<T>())
16042    }
16043
16044    fn character_size(&self, window: &mut Window) -> gpui::Size<Pixels> {
16045        let text_layout_details = self.text_layout_details(window);
16046        let style = &text_layout_details.editor_style;
16047        let font_id = window.text_system().resolve_font(&style.text.font());
16048        let font_size = style.text.font_size.to_pixels(window.rem_size());
16049        let line_height = style.text.line_height_in_pixels(window.rem_size());
16050        let em_width = window.text_system().em_width(font_id, font_size).unwrap();
16051
16052        gpui::Size::new(em_width, line_height)
16053    }
16054
16055    pub fn wait_for_diff_to_load(&self) -> Option<Shared<Task<()>>> {
16056        self.load_diff_task.clone()
16057    }
16058
16059    fn read_selections_from_db(
16060        &mut self,
16061        item_id: u64,
16062        workspace_id: WorkspaceId,
16063        window: &mut Window,
16064        cx: &mut Context<Editor>,
16065    ) {
16066        if !self.is_singleton(cx)
16067            || WorkspaceSettings::get(None, cx).restore_on_startup == RestoreOnStartupBehavior::None
16068        {
16069            return;
16070        }
16071        let Some(selections) = DB.get_editor_selections(item_id, workspace_id).log_err() else {
16072            return;
16073        };
16074        if selections.is_empty() {
16075            return;
16076        }
16077
16078        let snapshot = self.buffer.read(cx).snapshot(cx);
16079        self.change_selections(None, window, cx, |s| {
16080            s.select_ranges(selections.into_iter().map(|(start, end)| {
16081                snapshot.clip_offset(start, Bias::Left)..snapshot.clip_offset(end, Bias::Right)
16082            }));
16083        });
16084    }
16085}
16086
16087fn insert_extra_newline_brackets(
16088    buffer: &MultiBufferSnapshot,
16089    range: Range<usize>,
16090    language: &language::LanguageScope,
16091) -> bool {
16092    let leading_whitespace_len = buffer
16093        .reversed_chars_at(range.start)
16094        .take_while(|c| c.is_whitespace() && *c != '\n')
16095        .map(|c| c.len_utf8())
16096        .sum::<usize>();
16097    let trailing_whitespace_len = buffer
16098        .chars_at(range.end)
16099        .take_while(|c| c.is_whitespace() && *c != '\n')
16100        .map(|c| c.len_utf8())
16101        .sum::<usize>();
16102    let range = range.start - leading_whitespace_len..range.end + trailing_whitespace_len;
16103
16104    language.brackets().any(|(pair, enabled)| {
16105        let pair_start = pair.start.trim_end();
16106        let pair_end = pair.end.trim_start();
16107
16108        enabled
16109            && pair.newline
16110            && buffer.contains_str_at(range.end, pair_end)
16111            && buffer.contains_str_at(range.start.saturating_sub(pair_start.len()), pair_start)
16112    })
16113}
16114
16115fn insert_extra_newline_tree_sitter(buffer: &MultiBufferSnapshot, range: Range<usize>) -> bool {
16116    let (buffer, range) = match buffer.range_to_buffer_ranges(range).as_slice() {
16117        [(buffer, range, _)] => (*buffer, range.clone()),
16118        _ => return false,
16119    };
16120    let pair = {
16121        let mut result: Option<BracketMatch> = None;
16122
16123        for pair in buffer
16124            .all_bracket_ranges(range.clone())
16125            .filter(move |pair| {
16126                pair.open_range.start <= range.start && pair.close_range.end >= range.end
16127            })
16128        {
16129            let len = pair.close_range.end - pair.open_range.start;
16130
16131            if let Some(existing) = &result {
16132                let existing_len = existing.close_range.end - existing.open_range.start;
16133                if len > existing_len {
16134                    continue;
16135                }
16136            }
16137
16138            result = Some(pair);
16139        }
16140
16141        result
16142    };
16143    let Some(pair) = pair else {
16144        return false;
16145    };
16146    pair.newline_only
16147        && buffer
16148            .chars_for_range(pair.open_range.end..range.start)
16149            .chain(buffer.chars_for_range(range.end..pair.close_range.start))
16150            .all(|c| c.is_whitespace() && c != '\n')
16151}
16152
16153fn get_uncommitted_diff_for_buffer(
16154    project: &Entity<Project>,
16155    buffers: impl IntoIterator<Item = Entity<Buffer>>,
16156    buffer: Entity<MultiBuffer>,
16157    cx: &mut App,
16158) -> Task<()> {
16159    let mut tasks = Vec::new();
16160    project.update(cx, |project, cx| {
16161        for buffer in buffers {
16162            tasks.push(project.open_uncommitted_diff(buffer.clone(), cx))
16163        }
16164    });
16165    cx.spawn(|mut cx| async move {
16166        let diffs = futures::future::join_all(tasks).await;
16167        buffer
16168            .update(&mut cx, |buffer, cx| {
16169                for diff in diffs.into_iter().flatten() {
16170                    buffer.add_diff(diff, cx);
16171                }
16172            })
16173            .ok();
16174    })
16175}
16176
16177fn char_len_with_expanded_tabs(offset: usize, text: &str, tab_size: NonZeroU32) -> usize {
16178    let tab_size = tab_size.get() as usize;
16179    let mut width = offset;
16180
16181    for ch in text.chars() {
16182        width += if ch == '\t' {
16183            tab_size - (width % tab_size)
16184        } else {
16185            1
16186        };
16187    }
16188
16189    width - offset
16190}
16191
16192#[cfg(test)]
16193mod tests {
16194    use super::*;
16195
16196    #[test]
16197    fn test_string_size_with_expanded_tabs() {
16198        let nz = |val| NonZeroU32::new(val).unwrap();
16199        assert_eq!(char_len_with_expanded_tabs(0, "", nz(4)), 0);
16200        assert_eq!(char_len_with_expanded_tabs(0, "hello", nz(4)), 5);
16201        assert_eq!(char_len_with_expanded_tabs(0, "\thello", nz(4)), 9);
16202        assert_eq!(char_len_with_expanded_tabs(0, "abc\tab", nz(4)), 6);
16203        assert_eq!(char_len_with_expanded_tabs(0, "hello\t", nz(4)), 8);
16204        assert_eq!(char_len_with_expanded_tabs(0, "\t\t", nz(8)), 16);
16205        assert_eq!(char_len_with_expanded_tabs(0, "x\t", nz(8)), 8);
16206        assert_eq!(char_len_with_expanded_tabs(7, "x\t", nz(8)), 9);
16207    }
16208}
16209
16210/// Tokenizes a string into runs of text that should stick together, or that is whitespace.
16211struct WordBreakingTokenizer<'a> {
16212    input: &'a str,
16213}
16214
16215impl<'a> WordBreakingTokenizer<'a> {
16216    fn new(input: &'a str) -> Self {
16217        Self { input }
16218    }
16219}
16220
16221fn is_char_ideographic(ch: char) -> bool {
16222    use unicode_script::Script::*;
16223    use unicode_script::UnicodeScript;
16224    matches!(ch.script(), Han | Tangut | Yi)
16225}
16226
16227fn is_grapheme_ideographic(text: &str) -> bool {
16228    text.chars().any(is_char_ideographic)
16229}
16230
16231fn is_grapheme_whitespace(text: &str) -> bool {
16232    text.chars().any(|x| x.is_whitespace())
16233}
16234
16235fn should_stay_with_preceding_ideograph(text: &str) -> bool {
16236    text.chars().next().map_or(false, |ch| {
16237        matches!(ch, '。' | '、' | ',' | '?' | '!' | ':' | ';' | '…')
16238    })
16239}
16240
16241#[derive(PartialEq, Eq, Debug, Clone, Copy)]
16242struct WordBreakToken<'a> {
16243    token: &'a str,
16244    grapheme_len: usize,
16245    is_whitespace: bool,
16246}
16247
16248impl<'a> Iterator for WordBreakingTokenizer<'a> {
16249    /// Yields a span, the count of graphemes in the token, and whether it was
16250    /// whitespace. Note that it also breaks at word boundaries.
16251    type Item = WordBreakToken<'a>;
16252
16253    fn next(&mut self) -> Option<Self::Item> {
16254        use unicode_segmentation::UnicodeSegmentation;
16255        if self.input.is_empty() {
16256            return None;
16257        }
16258
16259        let mut iter = self.input.graphemes(true).peekable();
16260        let mut offset = 0;
16261        let mut graphemes = 0;
16262        if let Some(first_grapheme) = iter.next() {
16263            let is_whitespace = is_grapheme_whitespace(first_grapheme);
16264            offset += first_grapheme.len();
16265            graphemes += 1;
16266            if is_grapheme_ideographic(first_grapheme) && !is_whitespace {
16267                if let Some(grapheme) = iter.peek().copied() {
16268                    if should_stay_with_preceding_ideograph(grapheme) {
16269                        offset += grapheme.len();
16270                        graphemes += 1;
16271                    }
16272                }
16273            } else {
16274                let mut words = self.input[offset..].split_word_bound_indices().peekable();
16275                let mut next_word_bound = words.peek().copied();
16276                if next_word_bound.map_or(false, |(i, _)| i == 0) {
16277                    next_word_bound = words.next();
16278                }
16279                while let Some(grapheme) = iter.peek().copied() {
16280                    if next_word_bound.map_or(false, |(i, _)| i == offset) {
16281                        break;
16282                    };
16283                    if is_grapheme_whitespace(grapheme) != is_whitespace {
16284                        break;
16285                    };
16286                    offset += grapheme.len();
16287                    graphemes += 1;
16288                    iter.next();
16289                }
16290            }
16291            let token = &self.input[..offset];
16292            self.input = &self.input[offset..];
16293            if is_whitespace {
16294                Some(WordBreakToken {
16295                    token: " ",
16296                    grapheme_len: 1,
16297                    is_whitespace: true,
16298                })
16299            } else {
16300                Some(WordBreakToken {
16301                    token,
16302                    grapheme_len: graphemes,
16303                    is_whitespace: false,
16304                })
16305            }
16306        } else {
16307            None
16308        }
16309    }
16310}
16311
16312#[test]
16313fn test_word_breaking_tokenizer() {
16314    let tests: &[(&str, &[(&str, usize, bool)])] = &[
16315        ("", &[]),
16316        ("  ", &[(" ", 1, true)]),
16317        ("Ʒ", &[("Ʒ", 1, false)]),
16318        ("Ǽ", &[("Ǽ", 1, false)]),
16319        ("", &[("", 1, false)]),
16320        ("⋑⋑", &[("⋑⋑", 2, false)]),
16321        (
16322            "原理,进而",
16323            &[
16324                ("", 1, false),
16325                ("理,", 2, false),
16326                ("", 1, false),
16327                ("", 1, false),
16328            ],
16329        ),
16330        (
16331            "hello world",
16332            &[("hello", 5, false), (" ", 1, true), ("world", 5, false)],
16333        ),
16334        (
16335            "hello, world",
16336            &[("hello,", 6, false), (" ", 1, true), ("world", 5, false)],
16337        ),
16338        (
16339            "  hello world",
16340            &[
16341                (" ", 1, true),
16342                ("hello", 5, false),
16343                (" ", 1, true),
16344                ("world", 5, false),
16345            ],
16346        ),
16347        (
16348            "这是什么 \n 钢笔",
16349            &[
16350                ("", 1, false),
16351                ("", 1, false),
16352                ("", 1, false),
16353                ("", 1, false),
16354                (" ", 1, true),
16355                ("", 1, false),
16356                ("", 1, false),
16357            ],
16358        ),
16359        (" mutton", &[(" ", 1, true), ("mutton", 6, false)]),
16360    ];
16361
16362    for (input, result) in tests {
16363        assert_eq!(
16364            WordBreakingTokenizer::new(input).collect::<Vec<_>>(),
16365            result
16366                .iter()
16367                .copied()
16368                .map(|(token, grapheme_len, is_whitespace)| WordBreakToken {
16369                    token,
16370                    grapheme_len,
16371                    is_whitespace,
16372                })
16373                .collect::<Vec<_>>()
16374        );
16375    }
16376}
16377
16378fn wrap_with_prefix(
16379    line_prefix: String,
16380    unwrapped_text: String,
16381    wrap_column: usize,
16382    tab_size: NonZeroU32,
16383) -> String {
16384    let line_prefix_len = char_len_with_expanded_tabs(0, &line_prefix, tab_size);
16385    let mut wrapped_text = String::new();
16386    let mut current_line = line_prefix.clone();
16387
16388    let tokenizer = WordBreakingTokenizer::new(&unwrapped_text);
16389    let mut current_line_len = line_prefix_len;
16390    for WordBreakToken {
16391        token,
16392        grapheme_len,
16393        is_whitespace,
16394    } in tokenizer
16395    {
16396        if current_line_len + grapheme_len > wrap_column && current_line_len != line_prefix_len {
16397            wrapped_text.push_str(current_line.trim_end());
16398            wrapped_text.push('\n');
16399            current_line.truncate(line_prefix.len());
16400            current_line_len = line_prefix_len;
16401            if !is_whitespace {
16402                current_line.push_str(token);
16403                current_line_len += grapheme_len;
16404            }
16405        } else if !is_whitespace {
16406            current_line.push_str(token);
16407            current_line_len += grapheme_len;
16408        } else if current_line_len != line_prefix_len {
16409            current_line.push(' ');
16410            current_line_len += 1;
16411        }
16412    }
16413
16414    if !current_line.is_empty() {
16415        wrapped_text.push_str(&current_line);
16416    }
16417    wrapped_text
16418}
16419
16420#[test]
16421fn test_wrap_with_prefix() {
16422    assert_eq!(
16423        wrap_with_prefix(
16424            "# ".to_string(),
16425            "abcdefg".to_string(),
16426            4,
16427            NonZeroU32::new(4).unwrap()
16428        ),
16429        "# abcdefg"
16430    );
16431    assert_eq!(
16432        wrap_with_prefix(
16433            "".to_string(),
16434            "\thello world".to_string(),
16435            8,
16436            NonZeroU32::new(4).unwrap()
16437        ),
16438        "hello\nworld"
16439    );
16440    assert_eq!(
16441        wrap_with_prefix(
16442            "// ".to_string(),
16443            "xx \nyy zz aa bb cc".to_string(),
16444            12,
16445            NonZeroU32::new(4).unwrap()
16446        ),
16447        "// xx yy zz\n// aa bb cc"
16448    );
16449    assert_eq!(
16450        wrap_with_prefix(
16451            String::new(),
16452            "这是什么 \n 钢笔".to_string(),
16453            3,
16454            NonZeroU32::new(4).unwrap()
16455        ),
16456        "这是什\n么 钢\n"
16457    );
16458}
16459
16460pub trait CollaborationHub {
16461    fn collaborators<'a>(&self, cx: &'a App) -> &'a HashMap<PeerId, Collaborator>;
16462    fn user_participant_indices<'a>(&self, cx: &'a App) -> &'a HashMap<u64, ParticipantIndex>;
16463    fn user_names(&self, cx: &App) -> HashMap<u64, SharedString>;
16464}
16465
16466impl CollaborationHub for Entity<Project> {
16467    fn collaborators<'a>(&self, cx: &'a App) -> &'a HashMap<PeerId, Collaborator> {
16468        self.read(cx).collaborators()
16469    }
16470
16471    fn user_participant_indices<'a>(&self, cx: &'a App) -> &'a HashMap<u64, ParticipantIndex> {
16472        self.read(cx).user_store().read(cx).participant_indices()
16473    }
16474
16475    fn user_names(&self, cx: &App) -> HashMap<u64, SharedString> {
16476        let this = self.read(cx);
16477        let user_ids = this.collaborators().values().map(|c| c.user_id);
16478        this.user_store().read_with(cx, |user_store, cx| {
16479            user_store.participant_names(user_ids, cx)
16480        })
16481    }
16482}
16483
16484pub trait SemanticsProvider {
16485    fn hover(
16486        &self,
16487        buffer: &Entity<Buffer>,
16488        position: text::Anchor,
16489        cx: &mut App,
16490    ) -> Option<Task<Vec<project::Hover>>>;
16491
16492    fn inlay_hints(
16493        &self,
16494        buffer_handle: Entity<Buffer>,
16495        range: Range<text::Anchor>,
16496        cx: &mut App,
16497    ) -> Option<Task<anyhow::Result<Vec<InlayHint>>>>;
16498
16499    fn resolve_inlay_hint(
16500        &self,
16501        hint: InlayHint,
16502        buffer_handle: Entity<Buffer>,
16503        server_id: LanguageServerId,
16504        cx: &mut App,
16505    ) -> Option<Task<anyhow::Result<InlayHint>>>;
16506
16507    fn supports_inlay_hints(&self, buffer: &Entity<Buffer>, cx: &mut App) -> bool;
16508
16509    fn document_highlights(
16510        &self,
16511        buffer: &Entity<Buffer>,
16512        position: text::Anchor,
16513        cx: &mut App,
16514    ) -> Option<Task<Result<Vec<DocumentHighlight>>>>;
16515
16516    fn definitions(
16517        &self,
16518        buffer: &Entity<Buffer>,
16519        position: text::Anchor,
16520        kind: GotoDefinitionKind,
16521        cx: &mut App,
16522    ) -> Option<Task<Result<Vec<LocationLink>>>>;
16523
16524    fn range_for_rename(
16525        &self,
16526        buffer: &Entity<Buffer>,
16527        position: text::Anchor,
16528        cx: &mut App,
16529    ) -> Option<Task<Result<Option<Range<text::Anchor>>>>>;
16530
16531    fn perform_rename(
16532        &self,
16533        buffer: &Entity<Buffer>,
16534        position: text::Anchor,
16535        new_name: String,
16536        cx: &mut App,
16537    ) -> Option<Task<Result<ProjectTransaction>>>;
16538}
16539
16540pub trait CompletionProvider {
16541    fn completions(
16542        &self,
16543        buffer: &Entity<Buffer>,
16544        buffer_position: text::Anchor,
16545        trigger: CompletionContext,
16546        window: &mut Window,
16547        cx: &mut Context<Editor>,
16548    ) -> Task<Result<Vec<Completion>>>;
16549
16550    fn resolve_completions(
16551        &self,
16552        buffer: Entity<Buffer>,
16553        completion_indices: Vec<usize>,
16554        completions: Rc<RefCell<Box<[Completion]>>>,
16555        cx: &mut Context<Editor>,
16556    ) -> Task<Result<bool>>;
16557
16558    fn apply_additional_edits_for_completion(
16559        &self,
16560        _buffer: Entity<Buffer>,
16561        _completions: Rc<RefCell<Box<[Completion]>>>,
16562        _completion_index: usize,
16563        _push_to_history: bool,
16564        _cx: &mut Context<Editor>,
16565    ) -> Task<Result<Option<language::Transaction>>> {
16566        Task::ready(Ok(None))
16567    }
16568
16569    fn is_completion_trigger(
16570        &self,
16571        buffer: &Entity<Buffer>,
16572        position: language::Anchor,
16573        text: &str,
16574        trigger_in_words: bool,
16575        cx: &mut Context<Editor>,
16576    ) -> bool;
16577
16578    fn sort_completions(&self) -> bool {
16579        true
16580    }
16581}
16582
16583pub trait CodeActionProvider {
16584    fn id(&self) -> Arc<str>;
16585
16586    fn code_actions(
16587        &self,
16588        buffer: &Entity<Buffer>,
16589        range: Range<text::Anchor>,
16590        window: &mut Window,
16591        cx: &mut App,
16592    ) -> Task<Result<Vec<CodeAction>>>;
16593
16594    fn apply_code_action(
16595        &self,
16596        buffer_handle: Entity<Buffer>,
16597        action: CodeAction,
16598        excerpt_id: ExcerptId,
16599        push_to_history: bool,
16600        window: &mut Window,
16601        cx: &mut App,
16602    ) -> Task<Result<ProjectTransaction>>;
16603}
16604
16605impl CodeActionProvider for Entity<Project> {
16606    fn id(&self) -> Arc<str> {
16607        "project".into()
16608    }
16609
16610    fn code_actions(
16611        &self,
16612        buffer: &Entity<Buffer>,
16613        range: Range<text::Anchor>,
16614        _window: &mut Window,
16615        cx: &mut App,
16616    ) -> Task<Result<Vec<CodeAction>>> {
16617        self.update(cx, |project, cx| {
16618            project.code_actions(buffer, range, None, cx)
16619        })
16620    }
16621
16622    fn apply_code_action(
16623        &self,
16624        buffer_handle: Entity<Buffer>,
16625        action: CodeAction,
16626        _excerpt_id: ExcerptId,
16627        push_to_history: bool,
16628        _window: &mut Window,
16629        cx: &mut App,
16630    ) -> Task<Result<ProjectTransaction>> {
16631        self.update(cx, |project, cx| {
16632            project.apply_code_action(buffer_handle, action, push_to_history, cx)
16633        })
16634    }
16635}
16636
16637fn snippet_completions(
16638    project: &Project,
16639    buffer: &Entity<Buffer>,
16640    buffer_position: text::Anchor,
16641    cx: &mut App,
16642) -> Task<Result<Vec<Completion>>> {
16643    let language = buffer.read(cx).language_at(buffer_position);
16644    let language_name = language.as_ref().map(|language| language.lsp_id());
16645    let snippet_store = project.snippets().read(cx);
16646    let snippets = snippet_store.snippets_for(language_name, cx);
16647
16648    if snippets.is_empty() {
16649        return Task::ready(Ok(vec![]));
16650    }
16651    let snapshot = buffer.read(cx).text_snapshot();
16652    let chars: String = snapshot
16653        .reversed_chars_for_range(text::Anchor::MIN..buffer_position)
16654        .collect();
16655
16656    let scope = language.map(|language| language.default_scope());
16657    let executor = cx.background_executor().clone();
16658
16659    cx.background_spawn(async move {
16660        let classifier = CharClassifier::new(scope).for_completion(true);
16661        let mut last_word = chars
16662            .chars()
16663            .take_while(|c| classifier.is_word(*c))
16664            .collect::<String>();
16665        last_word = last_word.chars().rev().collect();
16666
16667        if last_word.is_empty() {
16668            return Ok(vec![]);
16669        }
16670
16671        let as_offset = text::ToOffset::to_offset(&buffer_position, &snapshot);
16672        let to_lsp = |point: &text::Anchor| {
16673            let end = text::ToPointUtf16::to_point_utf16(point, &snapshot);
16674            point_to_lsp(end)
16675        };
16676        let lsp_end = to_lsp(&buffer_position);
16677
16678        let candidates = snippets
16679            .iter()
16680            .enumerate()
16681            .flat_map(|(ix, snippet)| {
16682                snippet
16683                    .prefix
16684                    .iter()
16685                    .map(move |prefix| StringMatchCandidate::new(ix, &prefix))
16686            })
16687            .collect::<Vec<StringMatchCandidate>>();
16688
16689        let mut matches = fuzzy::match_strings(
16690            &candidates,
16691            &last_word,
16692            last_word.chars().any(|c| c.is_uppercase()),
16693            100,
16694            &Default::default(),
16695            executor,
16696        )
16697        .await;
16698
16699        // Remove all candidates where the query's start does not match the start of any word in the candidate
16700        if let Some(query_start) = last_word.chars().next() {
16701            matches.retain(|string_match| {
16702                split_words(&string_match.string).any(|word| {
16703                    // Check that the first codepoint of the word as lowercase matches the first
16704                    // codepoint of the query as lowercase
16705                    word.chars()
16706                        .flat_map(|codepoint| codepoint.to_lowercase())
16707                        .zip(query_start.to_lowercase())
16708                        .all(|(word_cp, query_cp)| word_cp == query_cp)
16709                })
16710            });
16711        }
16712
16713        let matched_strings = matches
16714            .into_iter()
16715            .map(|m| m.string)
16716            .collect::<HashSet<_>>();
16717
16718        let result: Vec<Completion> = snippets
16719            .into_iter()
16720            .filter_map(|snippet| {
16721                let matching_prefix = snippet
16722                    .prefix
16723                    .iter()
16724                    .find(|prefix| matched_strings.contains(*prefix))?;
16725                let start = as_offset - last_word.len();
16726                let start = snapshot.anchor_before(start);
16727                let range = start..buffer_position;
16728                let lsp_start = to_lsp(&start);
16729                let lsp_range = lsp::Range {
16730                    start: lsp_start,
16731                    end: lsp_end,
16732                };
16733                Some(Completion {
16734                    old_range: range,
16735                    new_text: snippet.body.clone(),
16736                    resolved: false,
16737                    label: CodeLabel {
16738                        text: matching_prefix.clone(),
16739                        runs: vec![],
16740                        filter_range: 0..matching_prefix.len(),
16741                    },
16742                    server_id: LanguageServerId(usize::MAX),
16743                    documentation: snippet
16744                        .description
16745                        .clone()
16746                        .map(|description| CompletionDocumentation::SingleLine(description.into())),
16747                    lsp_completion: lsp::CompletionItem {
16748                        label: snippet.prefix.first().unwrap().clone(),
16749                        kind: Some(CompletionItemKind::SNIPPET),
16750                        label_details: snippet.description.as_ref().map(|description| {
16751                            lsp::CompletionItemLabelDetails {
16752                                detail: Some(description.clone()),
16753                                description: None,
16754                            }
16755                        }),
16756                        insert_text_format: Some(InsertTextFormat::SNIPPET),
16757                        text_edit: Some(lsp::CompletionTextEdit::InsertAndReplace(
16758                            lsp::InsertReplaceEdit {
16759                                new_text: snippet.body.clone(),
16760                                insert: lsp_range,
16761                                replace: lsp_range,
16762                            },
16763                        )),
16764                        filter_text: Some(snippet.body.clone()),
16765                        sort_text: Some(char::MAX.to_string()),
16766                        ..Default::default()
16767                    },
16768                    confirm: None,
16769                })
16770            })
16771            .collect();
16772
16773        Ok(result)
16774    })
16775}
16776
16777impl CompletionProvider for Entity<Project> {
16778    fn completions(
16779        &self,
16780        buffer: &Entity<Buffer>,
16781        buffer_position: text::Anchor,
16782        options: CompletionContext,
16783        _window: &mut Window,
16784        cx: &mut Context<Editor>,
16785    ) -> Task<Result<Vec<Completion>>> {
16786        self.update(cx, |project, cx| {
16787            let snippets = snippet_completions(project, buffer, buffer_position, cx);
16788            let project_completions = project.completions(buffer, buffer_position, options, cx);
16789            cx.background_spawn(async move {
16790                let mut completions = project_completions.await?;
16791                let snippets_completions = snippets.await?;
16792                completions.extend(snippets_completions);
16793                Ok(completions)
16794            })
16795        })
16796    }
16797
16798    fn resolve_completions(
16799        &self,
16800        buffer: Entity<Buffer>,
16801        completion_indices: Vec<usize>,
16802        completions: Rc<RefCell<Box<[Completion]>>>,
16803        cx: &mut Context<Editor>,
16804    ) -> Task<Result<bool>> {
16805        self.update(cx, |project, cx| {
16806            project.lsp_store().update(cx, |lsp_store, cx| {
16807                lsp_store.resolve_completions(buffer, completion_indices, completions, cx)
16808            })
16809        })
16810    }
16811
16812    fn apply_additional_edits_for_completion(
16813        &self,
16814        buffer: Entity<Buffer>,
16815        completions: Rc<RefCell<Box<[Completion]>>>,
16816        completion_index: usize,
16817        push_to_history: bool,
16818        cx: &mut Context<Editor>,
16819    ) -> Task<Result<Option<language::Transaction>>> {
16820        self.update(cx, |project, cx| {
16821            project.lsp_store().update(cx, |lsp_store, cx| {
16822                lsp_store.apply_additional_edits_for_completion(
16823                    buffer,
16824                    completions,
16825                    completion_index,
16826                    push_to_history,
16827                    cx,
16828                )
16829            })
16830        })
16831    }
16832
16833    fn is_completion_trigger(
16834        &self,
16835        buffer: &Entity<Buffer>,
16836        position: language::Anchor,
16837        text: &str,
16838        trigger_in_words: bool,
16839        cx: &mut Context<Editor>,
16840    ) -> bool {
16841        let mut chars = text.chars();
16842        let char = if let Some(char) = chars.next() {
16843            char
16844        } else {
16845            return false;
16846        };
16847        if chars.next().is_some() {
16848            return false;
16849        }
16850
16851        let buffer = buffer.read(cx);
16852        let snapshot = buffer.snapshot();
16853        if !snapshot.settings_at(position, cx).show_completions_on_input {
16854            return false;
16855        }
16856        let classifier = snapshot.char_classifier_at(position).for_completion(true);
16857        if trigger_in_words && classifier.is_word(char) {
16858            return true;
16859        }
16860
16861        buffer.completion_triggers().contains(text)
16862    }
16863}
16864
16865impl SemanticsProvider for Entity<Project> {
16866    fn hover(
16867        &self,
16868        buffer: &Entity<Buffer>,
16869        position: text::Anchor,
16870        cx: &mut App,
16871    ) -> Option<Task<Vec<project::Hover>>> {
16872        Some(self.update(cx, |project, cx| project.hover(buffer, position, cx)))
16873    }
16874
16875    fn document_highlights(
16876        &self,
16877        buffer: &Entity<Buffer>,
16878        position: text::Anchor,
16879        cx: &mut App,
16880    ) -> Option<Task<Result<Vec<DocumentHighlight>>>> {
16881        Some(self.update(cx, |project, cx| {
16882            project.document_highlights(buffer, position, cx)
16883        }))
16884    }
16885
16886    fn definitions(
16887        &self,
16888        buffer: &Entity<Buffer>,
16889        position: text::Anchor,
16890        kind: GotoDefinitionKind,
16891        cx: &mut App,
16892    ) -> Option<Task<Result<Vec<LocationLink>>>> {
16893        Some(self.update(cx, |project, cx| match kind {
16894            GotoDefinitionKind::Symbol => project.definition(&buffer, position, cx),
16895            GotoDefinitionKind::Declaration => project.declaration(&buffer, position, cx),
16896            GotoDefinitionKind::Type => project.type_definition(&buffer, position, cx),
16897            GotoDefinitionKind::Implementation => project.implementation(&buffer, position, cx),
16898        }))
16899    }
16900
16901    fn supports_inlay_hints(&self, buffer: &Entity<Buffer>, cx: &mut App) -> bool {
16902        // TODO: make this work for remote projects
16903        self.update(cx, |this, cx| {
16904            buffer.update(cx, |buffer, cx| {
16905                this.any_language_server_supports_inlay_hints(buffer, cx)
16906            })
16907        })
16908    }
16909
16910    fn inlay_hints(
16911        &self,
16912        buffer_handle: Entity<Buffer>,
16913        range: Range<text::Anchor>,
16914        cx: &mut App,
16915    ) -> Option<Task<anyhow::Result<Vec<InlayHint>>>> {
16916        Some(self.update(cx, |project, cx| {
16917            project.inlay_hints(buffer_handle, range, cx)
16918        }))
16919    }
16920
16921    fn resolve_inlay_hint(
16922        &self,
16923        hint: InlayHint,
16924        buffer_handle: Entity<Buffer>,
16925        server_id: LanguageServerId,
16926        cx: &mut App,
16927    ) -> Option<Task<anyhow::Result<InlayHint>>> {
16928        Some(self.update(cx, |project, cx| {
16929            project.resolve_inlay_hint(hint, buffer_handle, server_id, cx)
16930        }))
16931    }
16932
16933    fn range_for_rename(
16934        &self,
16935        buffer: &Entity<Buffer>,
16936        position: text::Anchor,
16937        cx: &mut App,
16938    ) -> Option<Task<Result<Option<Range<text::Anchor>>>>> {
16939        Some(self.update(cx, |project, cx| {
16940            let buffer = buffer.clone();
16941            let task = project.prepare_rename(buffer.clone(), position, cx);
16942            cx.spawn(|_, mut cx| async move {
16943                Ok(match task.await? {
16944                    PrepareRenameResponse::Success(range) => Some(range),
16945                    PrepareRenameResponse::InvalidPosition => None,
16946                    PrepareRenameResponse::OnlyUnpreparedRenameSupported => {
16947                        // Fallback on using TreeSitter info to determine identifier range
16948                        buffer.update(&mut cx, |buffer, _| {
16949                            let snapshot = buffer.snapshot();
16950                            let (range, kind) = snapshot.surrounding_word(position);
16951                            if kind != Some(CharKind::Word) {
16952                                return None;
16953                            }
16954                            Some(
16955                                snapshot.anchor_before(range.start)
16956                                    ..snapshot.anchor_after(range.end),
16957                            )
16958                        })?
16959                    }
16960                })
16961            })
16962        }))
16963    }
16964
16965    fn perform_rename(
16966        &self,
16967        buffer: &Entity<Buffer>,
16968        position: text::Anchor,
16969        new_name: String,
16970        cx: &mut App,
16971    ) -> Option<Task<Result<ProjectTransaction>>> {
16972        Some(self.update(cx, |project, cx| {
16973            project.perform_rename(buffer.clone(), position, new_name, cx)
16974        }))
16975    }
16976}
16977
16978fn inlay_hint_settings(
16979    location: Anchor,
16980    snapshot: &MultiBufferSnapshot,
16981    cx: &mut Context<Editor>,
16982) -> InlayHintSettings {
16983    let file = snapshot.file_at(location);
16984    let language = snapshot.language_at(location).map(|l| l.name());
16985    language_settings(language, file, cx).inlay_hints
16986}
16987
16988fn consume_contiguous_rows(
16989    contiguous_row_selections: &mut Vec<Selection<Point>>,
16990    selection: &Selection<Point>,
16991    display_map: &DisplaySnapshot,
16992    selections: &mut Peekable<std::slice::Iter<Selection<Point>>>,
16993) -> (MultiBufferRow, MultiBufferRow) {
16994    contiguous_row_selections.push(selection.clone());
16995    let start_row = MultiBufferRow(selection.start.row);
16996    let mut end_row = ending_row(selection, display_map);
16997
16998    while let Some(next_selection) = selections.peek() {
16999        if next_selection.start.row <= end_row.0 {
17000            end_row = ending_row(next_selection, display_map);
17001            contiguous_row_selections.push(selections.next().unwrap().clone());
17002        } else {
17003            break;
17004        }
17005    }
17006    (start_row, end_row)
17007}
17008
17009fn ending_row(next_selection: &Selection<Point>, display_map: &DisplaySnapshot) -> MultiBufferRow {
17010    if next_selection.end.column > 0 || next_selection.is_empty() {
17011        MultiBufferRow(display_map.next_line_boundary(next_selection.end).0.row + 1)
17012    } else {
17013        MultiBufferRow(next_selection.end.row)
17014    }
17015}
17016
17017impl EditorSnapshot {
17018    pub fn remote_selections_in_range<'a>(
17019        &'a self,
17020        range: &'a Range<Anchor>,
17021        collaboration_hub: &dyn CollaborationHub,
17022        cx: &'a App,
17023    ) -> impl 'a + Iterator<Item = RemoteSelection> {
17024        let participant_names = collaboration_hub.user_names(cx);
17025        let participant_indices = collaboration_hub.user_participant_indices(cx);
17026        let collaborators_by_peer_id = collaboration_hub.collaborators(cx);
17027        let collaborators_by_replica_id = collaborators_by_peer_id
17028            .iter()
17029            .map(|(_, collaborator)| (collaborator.replica_id, collaborator))
17030            .collect::<HashMap<_, _>>();
17031        self.buffer_snapshot
17032            .selections_in_range(range, false)
17033            .filter_map(move |(replica_id, line_mode, cursor_shape, selection)| {
17034                let collaborator = collaborators_by_replica_id.get(&replica_id)?;
17035                let participant_index = participant_indices.get(&collaborator.user_id).copied();
17036                let user_name = participant_names.get(&collaborator.user_id).cloned();
17037                Some(RemoteSelection {
17038                    replica_id,
17039                    selection,
17040                    cursor_shape,
17041                    line_mode,
17042                    participant_index,
17043                    peer_id: collaborator.peer_id,
17044                    user_name,
17045                })
17046            })
17047    }
17048
17049    pub fn hunks_for_ranges(
17050        &self,
17051        ranges: impl Iterator<Item = Range<Point>>,
17052    ) -> Vec<MultiBufferDiffHunk> {
17053        let mut hunks = Vec::new();
17054        let mut processed_buffer_rows: HashMap<BufferId, HashSet<Range<text::Anchor>>> =
17055            HashMap::default();
17056        for query_range in ranges {
17057            let query_rows =
17058                MultiBufferRow(query_range.start.row)..MultiBufferRow(query_range.end.row + 1);
17059            for hunk in self.buffer_snapshot.diff_hunks_in_range(
17060                Point::new(query_rows.start.0, 0)..Point::new(query_rows.end.0, 0),
17061            ) {
17062                // Deleted hunk is an empty row range, no caret can be placed there and Zed allows to revert it
17063                // when the caret is just above or just below the deleted hunk.
17064                let allow_adjacent = hunk.status().is_deleted();
17065                let related_to_selection = if allow_adjacent {
17066                    hunk.row_range.overlaps(&query_rows)
17067                        || hunk.row_range.start == query_rows.end
17068                        || hunk.row_range.end == query_rows.start
17069                } else {
17070                    hunk.row_range.overlaps(&query_rows)
17071                };
17072                if related_to_selection {
17073                    if !processed_buffer_rows
17074                        .entry(hunk.buffer_id)
17075                        .or_default()
17076                        .insert(hunk.buffer_range.start..hunk.buffer_range.end)
17077                    {
17078                        continue;
17079                    }
17080                    hunks.push(hunk);
17081                }
17082            }
17083        }
17084
17085        hunks
17086    }
17087
17088    fn display_diff_hunks_for_rows<'a>(
17089        &'a self,
17090        display_rows: Range<DisplayRow>,
17091        folded_buffers: &'a HashSet<BufferId>,
17092    ) -> impl 'a + Iterator<Item = DisplayDiffHunk> {
17093        let buffer_start = DisplayPoint::new(display_rows.start, 0).to_point(self);
17094        let buffer_end = DisplayPoint::new(display_rows.end, 0).to_point(self);
17095
17096        self.buffer_snapshot
17097            .diff_hunks_in_range(buffer_start..buffer_end)
17098            .filter_map(|hunk| {
17099                if folded_buffers.contains(&hunk.buffer_id) {
17100                    return None;
17101                }
17102
17103                let hunk_start_point = Point::new(hunk.row_range.start.0, 0);
17104                let hunk_end_point = Point::new(hunk.row_range.end.0, 0);
17105
17106                let hunk_display_start = self.point_to_display_point(hunk_start_point, Bias::Left);
17107                let hunk_display_end = self.point_to_display_point(hunk_end_point, Bias::Right);
17108
17109                let display_hunk = if hunk_display_start.column() != 0 {
17110                    DisplayDiffHunk::Folded {
17111                        display_row: hunk_display_start.row(),
17112                    }
17113                } else {
17114                    let mut end_row = hunk_display_end.row();
17115                    if hunk_display_end.column() > 0 {
17116                        end_row.0 += 1;
17117                    }
17118                    DisplayDiffHunk::Unfolded {
17119                        status: hunk.status(),
17120                        diff_base_byte_range: hunk.diff_base_byte_range,
17121                        display_row_range: hunk_display_start.row()..end_row,
17122                        multi_buffer_range: Anchor::range_in_buffer(
17123                            hunk.excerpt_id,
17124                            hunk.buffer_id,
17125                            hunk.buffer_range,
17126                        ),
17127                    }
17128                };
17129
17130                Some(display_hunk)
17131            })
17132    }
17133
17134    pub fn language_at<T: ToOffset>(&self, position: T) -> Option<&Arc<Language>> {
17135        self.display_snapshot.buffer_snapshot.language_at(position)
17136    }
17137
17138    pub fn is_focused(&self) -> bool {
17139        self.is_focused
17140    }
17141
17142    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
17143        self.placeholder_text.as_ref()
17144    }
17145
17146    pub fn scroll_position(&self) -> gpui::Point<f32> {
17147        self.scroll_anchor.scroll_position(&self.display_snapshot)
17148    }
17149
17150    fn gutter_dimensions(
17151        &self,
17152        font_id: FontId,
17153        font_size: Pixels,
17154        max_line_number_width: Pixels,
17155        cx: &App,
17156    ) -> Option<GutterDimensions> {
17157        if !self.show_gutter {
17158            return None;
17159        }
17160
17161        let descent = cx.text_system().descent(font_id, font_size);
17162        let em_width = cx.text_system().em_width(font_id, font_size).log_err()?;
17163        let em_advance = cx.text_system().em_advance(font_id, font_size).log_err()?;
17164
17165        let show_git_gutter = self.show_git_diff_gutter.unwrap_or_else(|| {
17166            matches!(
17167                ProjectSettings::get_global(cx).git.git_gutter,
17168                Some(GitGutterSetting::TrackedFiles)
17169            )
17170        });
17171        let gutter_settings = EditorSettings::get_global(cx).gutter;
17172        let show_line_numbers = self
17173            .show_line_numbers
17174            .unwrap_or(gutter_settings.line_numbers);
17175        let line_gutter_width = if show_line_numbers {
17176            // Avoid flicker-like gutter resizes when the line number gains another digit and only resize the gutter on files with N*10^5 lines.
17177            let min_width_for_number_on_gutter = em_advance * 4.0;
17178            max_line_number_width.max(min_width_for_number_on_gutter)
17179        } else {
17180            0.0.into()
17181        };
17182
17183        let show_code_actions = self
17184            .show_code_actions
17185            .unwrap_or(gutter_settings.code_actions);
17186
17187        let show_runnables = self.show_runnables.unwrap_or(gutter_settings.runnables);
17188
17189        let git_blame_entries_width =
17190            self.git_blame_gutter_max_author_length
17191                .map(|max_author_length| {
17192                    const MAX_RELATIVE_TIMESTAMP: &str = "60 minutes ago";
17193
17194                    /// The number of characters to dedicate to gaps and margins.
17195                    const SPACING_WIDTH: usize = 4;
17196
17197                    let max_char_count = max_author_length
17198                        .min(GIT_BLAME_MAX_AUTHOR_CHARS_DISPLAYED)
17199                        + ::git::SHORT_SHA_LENGTH
17200                        + MAX_RELATIVE_TIMESTAMP.len()
17201                        + SPACING_WIDTH;
17202
17203                    em_advance * max_char_count
17204                });
17205
17206        let mut left_padding = git_blame_entries_width.unwrap_or(Pixels::ZERO);
17207        left_padding += if show_code_actions || show_runnables {
17208            em_width * 3.0
17209        } else if show_git_gutter && show_line_numbers {
17210            em_width * 2.0
17211        } else if show_git_gutter || show_line_numbers {
17212            em_width
17213        } else {
17214            px(0.)
17215        };
17216
17217        let right_padding = if gutter_settings.folds && show_line_numbers {
17218            em_width * 4.0
17219        } else if gutter_settings.folds {
17220            em_width * 3.0
17221        } else if show_line_numbers {
17222            em_width
17223        } else {
17224            px(0.)
17225        };
17226
17227        Some(GutterDimensions {
17228            left_padding,
17229            right_padding,
17230            width: line_gutter_width + left_padding + right_padding,
17231            margin: -descent,
17232            git_blame_entries_width,
17233        })
17234    }
17235
17236    pub fn render_crease_toggle(
17237        &self,
17238        buffer_row: MultiBufferRow,
17239        row_contains_cursor: bool,
17240        editor: Entity<Editor>,
17241        window: &mut Window,
17242        cx: &mut App,
17243    ) -> Option<AnyElement> {
17244        let folded = self.is_line_folded(buffer_row);
17245        let mut is_foldable = false;
17246
17247        if let Some(crease) = self
17248            .crease_snapshot
17249            .query_row(buffer_row, &self.buffer_snapshot)
17250        {
17251            is_foldable = true;
17252            match crease {
17253                Crease::Inline { render_toggle, .. } | Crease::Block { render_toggle, .. } => {
17254                    if let Some(render_toggle) = render_toggle {
17255                        let toggle_callback =
17256                            Arc::new(move |folded, window: &mut Window, cx: &mut App| {
17257                                if folded {
17258                                    editor.update(cx, |editor, cx| {
17259                                        editor.fold_at(&crate::FoldAt { buffer_row }, window, cx)
17260                                    });
17261                                } else {
17262                                    editor.update(cx, |editor, cx| {
17263                                        editor.unfold_at(
17264                                            &crate::UnfoldAt { buffer_row },
17265                                            window,
17266                                            cx,
17267                                        )
17268                                    });
17269                                }
17270                            });
17271                        return Some((render_toggle)(
17272                            buffer_row,
17273                            folded,
17274                            toggle_callback,
17275                            window,
17276                            cx,
17277                        ));
17278                    }
17279                }
17280            }
17281        }
17282
17283        is_foldable |= self.starts_indent(buffer_row);
17284
17285        if folded || (is_foldable && (row_contains_cursor || self.gutter_hovered)) {
17286            Some(
17287                Disclosure::new(("gutter_crease", buffer_row.0), !folded)
17288                    .toggle_state(folded)
17289                    .on_click(window.listener_for(&editor, move |this, _e, window, cx| {
17290                        if folded {
17291                            this.unfold_at(&UnfoldAt { buffer_row }, window, cx);
17292                        } else {
17293                            this.fold_at(&FoldAt { buffer_row }, window, cx);
17294                        }
17295                    }))
17296                    .into_any_element(),
17297            )
17298        } else {
17299            None
17300        }
17301    }
17302
17303    pub fn render_crease_trailer(
17304        &self,
17305        buffer_row: MultiBufferRow,
17306        window: &mut Window,
17307        cx: &mut App,
17308    ) -> Option<AnyElement> {
17309        let folded = self.is_line_folded(buffer_row);
17310        if let Crease::Inline { render_trailer, .. } = self
17311            .crease_snapshot
17312            .query_row(buffer_row, &self.buffer_snapshot)?
17313        {
17314            let render_trailer = render_trailer.as_ref()?;
17315            Some(render_trailer(buffer_row, folded, window, cx))
17316        } else {
17317            None
17318        }
17319    }
17320}
17321
17322impl Deref for EditorSnapshot {
17323    type Target = DisplaySnapshot;
17324
17325    fn deref(&self) -> &Self::Target {
17326        &self.display_snapshot
17327    }
17328}
17329
17330#[derive(Clone, Debug, PartialEq, Eq)]
17331pub enum EditorEvent {
17332    InputIgnored {
17333        text: Arc<str>,
17334    },
17335    InputHandled {
17336        utf16_range_to_replace: Option<Range<isize>>,
17337        text: Arc<str>,
17338    },
17339    ExcerptsAdded {
17340        buffer: Entity<Buffer>,
17341        predecessor: ExcerptId,
17342        excerpts: Vec<(ExcerptId, ExcerptRange<language::Anchor>)>,
17343    },
17344    ExcerptsRemoved {
17345        ids: Vec<ExcerptId>,
17346    },
17347    BufferFoldToggled {
17348        ids: Vec<ExcerptId>,
17349        folded: bool,
17350    },
17351    ExcerptsEdited {
17352        ids: Vec<ExcerptId>,
17353    },
17354    ExcerptsExpanded {
17355        ids: Vec<ExcerptId>,
17356    },
17357    BufferEdited,
17358    Edited {
17359        transaction_id: clock::Lamport,
17360    },
17361    Reparsed(BufferId),
17362    Focused,
17363    FocusedIn,
17364    Blurred,
17365    DirtyChanged,
17366    Saved,
17367    TitleChanged,
17368    DiffBaseChanged,
17369    SelectionsChanged {
17370        local: bool,
17371    },
17372    ScrollPositionChanged {
17373        local: bool,
17374        autoscroll: bool,
17375    },
17376    Closed,
17377    TransactionUndone {
17378        transaction_id: clock::Lamport,
17379    },
17380    TransactionBegun {
17381        transaction_id: clock::Lamport,
17382    },
17383    Reloaded,
17384    CursorShapeChanged,
17385}
17386
17387impl EventEmitter<EditorEvent> for Editor {}
17388
17389impl Focusable for Editor {
17390    fn focus_handle(&self, _cx: &App) -> FocusHandle {
17391        self.focus_handle.clone()
17392    }
17393}
17394
17395impl Render for Editor {
17396    fn render(&mut self, _: &mut Window, cx: &mut Context<'_, Self>) -> impl IntoElement {
17397        let settings = ThemeSettings::get_global(cx);
17398
17399        let mut text_style = match self.mode {
17400            EditorMode::SingleLine { .. } | EditorMode::AutoHeight { .. } => TextStyle {
17401                color: cx.theme().colors().editor_foreground,
17402                font_family: settings.ui_font.family.clone(),
17403                font_features: settings.ui_font.features.clone(),
17404                font_fallbacks: settings.ui_font.fallbacks.clone(),
17405                font_size: rems(0.875).into(),
17406                font_weight: settings.ui_font.weight,
17407                line_height: relative(settings.buffer_line_height.value()),
17408                ..Default::default()
17409            },
17410            EditorMode::Full => TextStyle {
17411                color: cx.theme().colors().editor_foreground,
17412                font_family: settings.buffer_font.family.clone(),
17413                font_features: settings.buffer_font.features.clone(),
17414                font_fallbacks: settings.buffer_font.fallbacks.clone(),
17415                font_size: settings.buffer_font_size(cx).into(),
17416                font_weight: settings.buffer_font.weight,
17417                line_height: relative(settings.buffer_line_height.value()),
17418                ..Default::default()
17419            },
17420        };
17421        if let Some(text_style_refinement) = &self.text_style_refinement {
17422            text_style.refine(text_style_refinement)
17423        }
17424
17425        let background = match self.mode {
17426            EditorMode::SingleLine { .. } => cx.theme().system().transparent,
17427            EditorMode::AutoHeight { max_lines: _ } => cx.theme().system().transparent,
17428            EditorMode::Full => cx.theme().colors().editor_background,
17429        };
17430
17431        EditorElement::new(
17432            &cx.entity(),
17433            EditorStyle {
17434                background,
17435                local_player: cx.theme().players().local(),
17436                text: text_style,
17437                scrollbar_width: EditorElement::SCROLLBAR_WIDTH,
17438                syntax: cx.theme().syntax().clone(),
17439                status: cx.theme().status().clone(),
17440                inlay_hints_style: make_inlay_hints_style(cx),
17441                inline_completion_styles: make_suggestion_styles(cx),
17442                unnecessary_code_fade: ThemeSettings::get_global(cx).unnecessary_code_fade,
17443            },
17444        )
17445    }
17446}
17447
17448impl EntityInputHandler for Editor {
17449    fn text_for_range(
17450        &mut self,
17451        range_utf16: Range<usize>,
17452        adjusted_range: &mut Option<Range<usize>>,
17453        _: &mut Window,
17454        cx: &mut Context<Self>,
17455    ) -> Option<String> {
17456        let snapshot = self.buffer.read(cx).read(cx);
17457        let start = snapshot.clip_offset_utf16(OffsetUtf16(range_utf16.start), Bias::Left);
17458        let end = snapshot.clip_offset_utf16(OffsetUtf16(range_utf16.end), Bias::Right);
17459        if (start.0..end.0) != range_utf16 {
17460            adjusted_range.replace(start.0..end.0);
17461        }
17462        Some(snapshot.text_for_range(start..end).collect())
17463    }
17464
17465    fn selected_text_range(
17466        &mut self,
17467        ignore_disabled_input: bool,
17468        _: &mut Window,
17469        cx: &mut Context<Self>,
17470    ) -> Option<UTF16Selection> {
17471        // Prevent the IME menu from appearing when holding down an alphabetic key
17472        // while input is disabled.
17473        if !ignore_disabled_input && !self.input_enabled {
17474            return None;
17475        }
17476
17477        let selection = self.selections.newest::<OffsetUtf16>(cx);
17478        let range = selection.range();
17479
17480        Some(UTF16Selection {
17481            range: range.start.0..range.end.0,
17482            reversed: selection.reversed,
17483        })
17484    }
17485
17486    fn marked_text_range(&self, _: &mut Window, cx: &mut Context<Self>) -> Option<Range<usize>> {
17487        let snapshot = self.buffer.read(cx).read(cx);
17488        let range = self.text_highlights::<InputComposition>(cx)?.1.first()?;
17489        Some(range.start.to_offset_utf16(&snapshot).0..range.end.to_offset_utf16(&snapshot).0)
17490    }
17491
17492    fn unmark_text(&mut self, _: &mut Window, cx: &mut Context<Self>) {
17493        self.clear_highlights::<InputComposition>(cx);
17494        self.ime_transaction.take();
17495    }
17496
17497    fn replace_text_in_range(
17498        &mut self,
17499        range_utf16: Option<Range<usize>>,
17500        text: &str,
17501        window: &mut Window,
17502        cx: &mut Context<Self>,
17503    ) {
17504        if !self.input_enabled {
17505            cx.emit(EditorEvent::InputIgnored { text: text.into() });
17506            return;
17507        }
17508
17509        self.transact(window, cx, |this, window, cx| {
17510            let new_selected_ranges = if let Some(range_utf16) = range_utf16 {
17511                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
17512                Some(this.selection_replacement_ranges(range_utf16, cx))
17513            } else {
17514                this.marked_text_ranges(cx)
17515            };
17516
17517            let range_to_replace = new_selected_ranges.as_ref().and_then(|ranges_to_replace| {
17518                let newest_selection_id = this.selections.newest_anchor().id;
17519                this.selections
17520                    .all::<OffsetUtf16>(cx)
17521                    .iter()
17522                    .zip(ranges_to_replace.iter())
17523                    .find_map(|(selection, range)| {
17524                        if selection.id == newest_selection_id {
17525                            Some(
17526                                (range.start.0 as isize - selection.head().0 as isize)
17527                                    ..(range.end.0 as isize - selection.head().0 as isize),
17528                            )
17529                        } else {
17530                            None
17531                        }
17532                    })
17533            });
17534
17535            cx.emit(EditorEvent::InputHandled {
17536                utf16_range_to_replace: range_to_replace,
17537                text: text.into(),
17538            });
17539
17540            if let Some(new_selected_ranges) = new_selected_ranges {
17541                this.change_selections(None, window, cx, |selections| {
17542                    selections.select_ranges(new_selected_ranges)
17543                });
17544                this.backspace(&Default::default(), window, cx);
17545            }
17546
17547            this.handle_input(text, window, cx);
17548        });
17549
17550        if let Some(transaction) = self.ime_transaction {
17551            self.buffer.update(cx, |buffer, cx| {
17552                buffer.group_until_transaction(transaction, cx);
17553            });
17554        }
17555
17556        self.unmark_text(window, cx);
17557    }
17558
17559    fn replace_and_mark_text_in_range(
17560        &mut self,
17561        range_utf16: Option<Range<usize>>,
17562        text: &str,
17563        new_selected_range_utf16: Option<Range<usize>>,
17564        window: &mut Window,
17565        cx: &mut Context<Self>,
17566    ) {
17567        if !self.input_enabled {
17568            return;
17569        }
17570
17571        let transaction = self.transact(window, cx, |this, window, cx| {
17572            let ranges_to_replace = if let Some(mut marked_ranges) = this.marked_text_ranges(cx) {
17573                let snapshot = this.buffer.read(cx).read(cx);
17574                if let Some(relative_range_utf16) = range_utf16.as_ref() {
17575                    for marked_range in &mut marked_ranges {
17576                        marked_range.end.0 = marked_range.start.0 + relative_range_utf16.end;
17577                        marked_range.start.0 += relative_range_utf16.start;
17578                        marked_range.start =
17579                            snapshot.clip_offset_utf16(marked_range.start, Bias::Left);
17580                        marked_range.end =
17581                            snapshot.clip_offset_utf16(marked_range.end, Bias::Right);
17582                    }
17583                }
17584                Some(marked_ranges)
17585            } else if let Some(range_utf16) = range_utf16 {
17586                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
17587                Some(this.selection_replacement_ranges(range_utf16, cx))
17588            } else {
17589                None
17590            };
17591
17592            let range_to_replace = ranges_to_replace.as_ref().and_then(|ranges_to_replace| {
17593                let newest_selection_id = this.selections.newest_anchor().id;
17594                this.selections
17595                    .all::<OffsetUtf16>(cx)
17596                    .iter()
17597                    .zip(ranges_to_replace.iter())
17598                    .find_map(|(selection, range)| {
17599                        if selection.id == newest_selection_id {
17600                            Some(
17601                                (range.start.0 as isize - selection.head().0 as isize)
17602                                    ..(range.end.0 as isize - selection.head().0 as isize),
17603                            )
17604                        } else {
17605                            None
17606                        }
17607                    })
17608            });
17609
17610            cx.emit(EditorEvent::InputHandled {
17611                utf16_range_to_replace: range_to_replace,
17612                text: text.into(),
17613            });
17614
17615            if let Some(ranges) = ranges_to_replace {
17616                this.change_selections(None, window, cx, |s| s.select_ranges(ranges));
17617            }
17618
17619            let marked_ranges = {
17620                let snapshot = this.buffer.read(cx).read(cx);
17621                this.selections
17622                    .disjoint_anchors()
17623                    .iter()
17624                    .map(|selection| {
17625                        selection.start.bias_left(&snapshot)..selection.end.bias_right(&snapshot)
17626                    })
17627                    .collect::<Vec<_>>()
17628            };
17629
17630            if text.is_empty() {
17631                this.unmark_text(window, cx);
17632            } else {
17633                this.highlight_text::<InputComposition>(
17634                    marked_ranges.clone(),
17635                    HighlightStyle {
17636                        underline: Some(UnderlineStyle {
17637                            thickness: px(1.),
17638                            color: None,
17639                            wavy: false,
17640                        }),
17641                        ..Default::default()
17642                    },
17643                    cx,
17644                );
17645            }
17646
17647            // Disable auto-closing when composing text (i.e. typing a `"` on a Brazilian keyboard)
17648            let use_autoclose = this.use_autoclose;
17649            let use_auto_surround = this.use_auto_surround;
17650            this.set_use_autoclose(false);
17651            this.set_use_auto_surround(false);
17652            this.handle_input(text, window, cx);
17653            this.set_use_autoclose(use_autoclose);
17654            this.set_use_auto_surround(use_auto_surround);
17655
17656            if let Some(new_selected_range) = new_selected_range_utf16 {
17657                let snapshot = this.buffer.read(cx).read(cx);
17658                let new_selected_ranges = marked_ranges
17659                    .into_iter()
17660                    .map(|marked_range| {
17661                        let insertion_start = marked_range.start.to_offset_utf16(&snapshot).0;
17662                        let new_start = OffsetUtf16(new_selected_range.start + insertion_start);
17663                        let new_end = OffsetUtf16(new_selected_range.end + insertion_start);
17664                        snapshot.clip_offset_utf16(new_start, Bias::Left)
17665                            ..snapshot.clip_offset_utf16(new_end, Bias::Right)
17666                    })
17667                    .collect::<Vec<_>>();
17668
17669                drop(snapshot);
17670                this.change_selections(None, window, cx, |selections| {
17671                    selections.select_ranges(new_selected_ranges)
17672                });
17673            }
17674        });
17675
17676        self.ime_transaction = self.ime_transaction.or(transaction);
17677        if let Some(transaction) = self.ime_transaction {
17678            self.buffer.update(cx, |buffer, cx| {
17679                buffer.group_until_transaction(transaction, cx);
17680            });
17681        }
17682
17683        if self.text_highlights::<InputComposition>(cx).is_none() {
17684            self.ime_transaction.take();
17685        }
17686    }
17687
17688    fn bounds_for_range(
17689        &mut self,
17690        range_utf16: Range<usize>,
17691        element_bounds: gpui::Bounds<Pixels>,
17692        window: &mut Window,
17693        cx: &mut Context<Self>,
17694    ) -> Option<gpui::Bounds<Pixels>> {
17695        let text_layout_details = self.text_layout_details(window);
17696        let gpui::Size {
17697            width: em_width,
17698            height: line_height,
17699        } = self.character_size(window);
17700
17701        let snapshot = self.snapshot(window, cx);
17702        let scroll_position = snapshot.scroll_position();
17703        let scroll_left = scroll_position.x * em_width;
17704
17705        let start = OffsetUtf16(range_utf16.start).to_display_point(&snapshot);
17706        let x = snapshot.x_for_display_point(start, &text_layout_details) - scroll_left
17707            + self.gutter_dimensions.width
17708            + self.gutter_dimensions.margin;
17709        let y = line_height * (start.row().as_f32() - scroll_position.y);
17710
17711        Some(Bounds {
17712            origin: element_bounds.origin + point(x, y),
17713            size: size(em_width, line_height),
17714        })
17715    }
17716
17717    fn character_index_for_point(
17718        &mut self,
17719        point: gpui::Point<Pixels>,
17720        _window: &mut Window,
17721        _cx: &mut Context<Self>,
17722    ) -> Option<usize> {
17723        let position_map = self.last_position_map.as_ref()?;
17724        if !position_map.text_hitbox.contains(&point) {
17725            return None;
17726        }
17727        let display_point = position_map.point_for_position(point).previous_valid;
17728        let anchor = position_map
17729            .snapshot
17730            .display_point_to_anchor(display_point, Bias::Left);
17731        let utf16_offset = anchor.to_offset_utf16(&position_map.snapshot.buffer_snapshot);
17732        Some(utf16_offset.0)
17733    }
17734}
17735
17736trait SelectionExt {
17737    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
17738    fn spanned_rows(
17739        &self,
17740        include_end_if_at_line_start: bool,
17741        map: &DisplaySnapshot,
17742    ) -> Range<MultiBufferRow>;
17743}
17744
17745impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
17746    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
17747        let start = self
17748            .start
17749            .to_point(&map.buffer_snapshot)
17750            .to_display_point(map);
17751        let end = self
17752            .end
17753            .to_point(&map.buffer_snapshot)
17754            .to_display_point(map);
17755        if self.reversed {
17756            end..start
17757        } else {
17758            start..end
17759        }
17760    }
17761
17762    fn spanned_rows(
17763        &self,
17764        include_end_if_at_line_start: bool,
17765        map: &DisplaySnapshot,
17766    ) -> Range<MultiBufferRow> {
17767        let start = self.start.to_point(&map.buffer_snapshot);
17768        let mut end = self.end.to_point(&map.buffer_snapshot);
17769        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
17770            end.row -= 1;
17771        }
17772
17773        let buffer_start = map.prev_line_boundary(start).0;
17774        let buffer_end = map.next_line_boundary(end).0;
17775        MultiBufferRow(buffer_start.row)..MultiBufferRow(buffer_end.row + 1)
17776    }
17777}
17778
17779impl<T: InvalidationRegion> InvalidationStack<T> {
17780    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
17781    where
17782        S: Clone + ToOffset,
17783    {
17784        while let Some(region) = self.last() {
17785            let all_selections_inside_invalidation_ranges =
17786                if selections.len() == region.ranges().len() {
17787                    selections
17788                        .iter()
17789                        .zip(region.ranges().iter().map(|r| r.to_offset(buffer)))
17790                        .all(|(selection, invalidation_range)| {
17791                            let head = selection.head().to_offset(buffer);
17792                            invalidation_range.start <= head && invalidation_range.end >= head
17793                        })
17794                } else {
17795                    false
17796                };
17797
17798            if all_selections_inside_invalidation_ranges {
17799                break;
17800            } else {
17801                self.pop();
17802            }
17803        }
17804    }
17805}
17806
17807impl<T> Default for InvalidationStack<T> {
17808    fn default() -> Self {
17809        Self(Default::default())
17810    }
17811}
17812
17813impl<T> Deref for InvalidationStack<T> {
17814    type Target = Vec<T>;
17815
17816    fn deref(&self) -> &Self::Target {
17817        &self.0
17818    }
17819}
17820
17821impl<T> DerefMut for InvalidationStack<T> {
17822    fn deref_mut(&mut self) -> &mut Self::Target {
17823        &mut self.0
17824    }
17825}
17826
17827impl InvalidationRegion for SnippetState {
17828    fn ranges(&self) -> &[Range<Anchor>] {
17829        &self.ranges[self.active_index]
17830    }
17831}
17832
17833pub fn diagnostic_block_renderer(
17834    diagnostic: Diagnostic,
17835    max_message_rows: Option<u8>,
17836    allow_closing: bool,
17837) -> RenderBlock {
17838    let (text_without_backticks, code_ranges) =
17839        highlight_diagnostic_message(&diagnostic, max_message_rows);
17840
17841    Arc::new(move |cx: &mut BlockContext| {
17842        let group_id: SharedString = cx.block_id.to_string().into();
17843
17844        let mut text_style = cx.window.text_style().clone();
17845        text_style.color = diagnostic_style(diagnostic.severity, cx.theme().status());
17846        let theme_settings = ThemeSettings::get_global(cx);
17847        text_style.font_family = theme_settings.buffer_font.family.clone();
17848        text_style.font_style = theme_settings.buffer_font.style;
17849        text_style.font_features = theme_settings.buffer_font.features.clone();
17850        text_style.font_weight = theme_settings.buffer_font.weight;
17851
17852        let multi_line_diagnostic = diagnostic.message.contains('\n');
17853
17854        let buttons = |diagnostic: &Diagnostic| {
17855            if multi_line_diagnostic {
17856                v_flex()
17857            } else {
17858                h_flex()
17859            }
17860            .when(allow_closing, |div| {
17861                div.children(diagnostic.is_primary.then(|| {
17862                    IconButton::new("close-block", IconName::XCircle)
17863                        .icon_color(Color::Muted)
17864                        .size(ButtonSize::Compact)
17865                        .style(ButtonStyle::Transparent)
17866                        .visible_on_hover(group_id.clone())
17867                        .on_click(move |_click, window, cx| {
17868                            window.dispatch_action(Box::new(Cancel), cx)
17869                        })
17870                        .tooltip(|window, cx| {
17871                            Tooltip::for_action("Close Diagnostics", &Cancel, window, cx)
17872                        })
17873                }))
17874            })
17875            .child(
17876                IconButton::new("copy-block", IconName::Copy)
17877                    .icon_color(Color::Muted)
17878                    .size(ButtonSize::Compact)
17879                    .style(ButtonStyle::Transparent)
17880                    .visible_on_hover(group_id.clone())
17881                    .on_click({
17882                        let message = diagnostic.message.clone();
17883                        move |_click, _, cx| {
17884                            cx.write_to_clipboard(ClipboardItem::new_string(message.clone()))
17885                        }
17886                    })
17887                    .tooltip(Tooltip::text("Copy diagnostic message")),
17888            )
17889        };
17890
17891        let icon_size = buttons(&diagnostic).into_any_element().layout_as_root(
17892            AvailableSpace::min_size(),
17893            cx.window,
17894            cx.app,
17895        );
17896
17897        h_flex()
17898            .id(cx.block_id)
17899            .group(group_id.clone())
17900            .relative()
17901            .size_full()
17902            .block_mouse_down()
17903            .pl(cx.gutter_dimensions.width)
17904            .w(cx.max_width - cx.gutter_dimensions.full_width())
17905            .child(
17906                div()
17907                    .flex()
17908                    .w(cx.anchor_x - cx.gutter_dimensions.width - icon_size.width)
17909                    .flex_shrink(),
17910            )
17911            .child(buttons(&diagnostic))
17912            .child(div().flex().flex_shrink_0().child(
17913                StyledText::new(text_without_backticks.clone()).with_highlights(
17914                    &text_style,
17915                    code_ranges.iter().map(|range| {
17916                        (
17917                            range.clone(),
17918                            HighlightStyle {
17919                                font_weight: Some(FontWeight::BOLD),
17920                                ..Default::default()
17921                            },
17922                        )
17923                    }),
17924                ),
17925            ))
17926            .into_any_element()
17927    })
17928}
17929
17930fn inline_completion_edit_text(
17931    current_snapshot: &BufferSnapshot,
17932    edits: &[(Range<Anchor>, String)],
17933    edit_preview: &EditPreview,
17934    include_deletions: bool,
17935    cx: &App,
17936) -> HighlightedText {
17937    let edits = edits
17938        .iter()
17939        .map(|(anchor, text)| {
17940            (
17941                anchor.start.text_anchor..anchor.end.text_anchor,
17942                text.clone(),
17943            )
17944        })
17945        .collect::<Vec<_>>();
17946
17947    edit_preview.highlight_edits(current_snapshot, &edits, include_deletions, cx)
17948}
17949
17950pub fn highlight_diagnostic_message(
17951    diagnostic: &Diagnostic,
17952    mut max_message_rows: Option<u8>,
17953) -> (SharedString, Vec<Range<usize>>) {
17954    let mut text_without_backticks = String::new();
17955    let mut code_ranges = Vec::new();
17956
17957    if let Some(source) = &diagnostic.source {
17958        text_without_backticks.push_str(source);
17959        code_ranges.push(0..source.len());
17960        text_without_backticks.push_str(": ");
17961    }
17962
17963    let mut prev_offset = 0;
17964    let mut in_code_block = false;
17965    let has_row_limit = max_message_rows.is_some();
17966    let mut newline_indices = diagnostic
17967        .message
17968        .match_indices('\n')
17969        .filter(|_| has_row_limit)
17970        .map(|(ix, _)| ix)
17971        .fuse()
17972        .peekable();
17973
17974    for (quote_ix, _) in diagnostic
17975        .message
17976        .match_indices('`')
17977        .chain([(diagnostic.message.len(), "")])
17978    {
17979        let mut first_newline_ix = None;
17980        let mut last_newline_ix = None;
17981        while let Some(newline_ix) = newline_indices.peek() {
17982            if *newline_ix < quote_ix {
17983                if first_newline_ix.is_none() {
17984                    first_newline_ix = Some(*newline_ix);
17985                }
17986                last_newline_ix = Some(*newline_ix);
17987
17988                if let Some(rows_left) = &mut max_message_rows {
17989                    if *rows_left == 0 {
17990                        break;
17991                    } else {
17992                        *rows_left -= 1;
17993                    }
17994                }
17995                let _ = newline_indices.next();
17996            } else {
17997                break;
17998            }
17999        }
18000        let prev_len = text_without_backticks.len();
18001        let new_text = &diagnostic.message[prev_offset..first_newline_ix.unwrap_or(quote_ix)];
18002        text_without_backticks.push_str(new_text);
18003        if in_code_block {
18004            code_ranges.push(prev_len..text_without_backticks.len());
18005        }
18006        prev_offset = last_newline_ix.unwrap_or(quote_ix) + 1;
18007        in_code_block = !in_code_block;
18008        if first_newline_ix.map_or(false, |newline_ix| newline_ix < quote_ix) {
18009            text_without_backticks.push_str("...");
18010            break;
18011        }
18012    }
18013
18014    (text_without_backticks.into(), code_ranges)
18015}
18016
18017fn diagnostic_style(severity: DiagnosticSeverity, colors: &StatusColors) -> Hsla {
18018    match severity {
18019        DiagnosticSeverity::ERROR => colors.error,
18020        DiagnosticSeverity::WARNING => colors.warning,
18021        DiagnosticSeverity::INFORMATION => colors.info,
18022        DiagnosticSeverity::HINT => colors.info,
18023        _ => colors.ignored,
18024    }
18025}
18026
18027pub fn styled_runs_for_code_label<'a>(
18028    label: &'a CodeLabel,
18029    syntax_theme: &'a theme::SyntaxTheme,
18030) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
18031    let fade_out = HighlightStyle {
18032        fade_out: Some(0.35),
18033        ..Default::default()
18034    };
18035
18036    let mut prev_end = label.filter_range.end;
18037    label
18038        .runs
18039        .iter()
18040        .enumerate()
18041        .flat_map(move |(ix, (range, highlight_id))| {
18042            let style = if let Some(style) = highlight_id.style(syntax_theme) {
18043                style
18044            } else {
18045                return Default::default();
18046            };
18047            let mut muted_style = style;
18048            muted_style.highlight(fade_out);
18049
18050            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
18051            if range.start >= label.filter_range.end {
18052                if range.start > prev_end {
18053                    runs.push((prev_end..range.start, fade_out));
18054                }
18055                runs.push((range.clone(), muted_style));
18056            } else if range.end <= label.filter_range.end {
18057                runs.push((range.clone(), style));
18058            } else {
18059                runs.push((range.start..label.filter_range.end, style));
18060                runs.push((label.filter_range.end..range.end, muted_style));
18061            }
18062            prev_end = cmp::max(prev_end, range.end);
18063
18064            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
18065                runs.push((prev_end..label.text.len(), fade_out));
18066            }
18067
18068            runs
18069        })
18070}
18071
18072pub(crate) fn split_words(text: &str) -> impl std::iter::Iterator<Item = &str> + '_ {
18073    let mut prev_index = 0;
18074    let mut prev_codepoint: Option<char> = None;
18075    text.char_indices()
18076        .chain([(text.len(), '\0')])
18077        .filter_map(move |(index, codepoint)| {
18078            let prev_codepoint = prev_codepoint.replace(codepoint)?;
18079            let is_boundary = index == text.len()
18080                || !prev_codepoint.is_uppercase() && codepoint.is_uppercase()
18081                || !prev_codepoint.is_alphanumeric() && codepoint.is_alphanumeric();
18082            if is_boundary {
18083                let chunk = &text[prev_index..index];
18084                prev_index = index;
18085                Some(chunk)
18086            } else {
18087                None
18088            }
18089        })
18090}
18091
18092pub trait RangeToAnchorExt: Sized {
18093    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor>;
18094
18095    fn to_display_points(self, snapshot: &EditorSnapshot) -> Range<DisplayPoint> {
18096        let anchor_range = self.to_anchors(&snapshot.buffer_snapshot);
18097        anchor_range.start.to_display_point(snapshot)..anchor_range.end.to_display_point(snapshot)
18098    }
18099}
18100
18101impl<T: ToOffset> RangeToAnchorExt for Range<T> {
18102    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor> {
18103        let start_offset = self.start.to_offset(snapshot);
18104        let end_offset = self.end.to_offset(snapshot);
18105        if start_offset == end_offset {
18106            snapshot.anchor_before(start_offset)..snapshot.anchor_before(end_offset)
18107        } else {
18108            snapshot.anchor_after(self.start)..snapshot.anchor_before(self.end)
18109        }
18110    }
18111}
18112
18113pub trait RowExt {
18114    fn as_f32(&self) -> f32;
18115
18116    fn next_row(&self) -> Self;
18117
18118    fn previous_row(&self) -> Self;
18119
18120    fn minus(&self, other: Self) -> u32;
18121}
18122
18123impl RowExt for DisplayRow {
18124    fn as_f32(&self) -> f32 {
18125        self.0 as f32
18126    }
18127
18128    fn next_row(&self) -> Self {
18129        Self(self.0 + 1)
18130    }
18131
18132    fn previous_row(&self) -> Self {
18133        Self(self.0.saturating_sub(1))
18134    }
18135
18136    fn minus(&self, other: Self) -> u32 {
18137        self.0 - other.0
18138    }
18139}
18140
18141impl RowExt for MultiBufferRow {
18142    fn as_f32(&self) -> f32 {
18143        self.0 as f32
18144    }
18145
18146    fn next_row(&self) -> Self {
18147        Self(self.0 + 1)
18148    }
18149
18150    fn previous_row(&self) -> Self {
18151        Self(self.0.saturating_sub(1))
18152    }
18153
18154    fn minus(&self, other: Self) -> u32 {
18155        self.0 - other.0
18156    }
18157}
18158
18159trait RowRangeExt {
18160    type Row;
18161
18162    fn len(&self) -> usize;
18163
18164    fn iter_rows(&self) -> impl DoubleEndedIterator<Item = Self::Row>;
18165}
18166
18167impl RowRangeExt for Range<MultiBufferRow> {
18168    type Row = MultiBufferRow;
18169
18170    fn len(&self) -> usize {
18171        (self.end.0 - self.start.0) as usize
18172    }
18173
18174    fn iter_rows(&self) -> impl DoubleEndedIterator<Item = MultiBufferRow> {
18175        (self.start.0..self.end.0).map(MultiBufferRow)
18176    }
18177}
18178
18179impl RowRangeExt for Range<DisplayRow> {
18180    type Row = DisplayRow;
18181
18182    fn len(&self) -> usize {
18183        (self.end.0 - self.start.0) as usize
18184    }
18185
18186    fn iter_rows(&self) -> impl DoubleEndedIterator<Item = DisplayRow> {
18187        (self.start.0..self.end.0).map(DisplayRow)
18188    }
18189}
18190
18191/// If select range has more than one line, we
18192/// just point the cursor to range.start.
18193fn collapse_multiline_range(range: Range<Point>) -> Range<Point> {
18194    if range.start.row == range.end.row {
18195        range
18196    } else {
18197        range.start..range.start
18198    }
18199}
18200pub struct KillRing(ClipboardItem);
18201impl Global for KillRing {}
18202
18203const UPDATE_DEBOUNCE: Duration = Duration::from_millis(50);
18204
18205fn all_edits_insertions_or_deletions(
18206    edits: &Vec<(Range<Anchor>, String)>,
18207    snapshot: &MultiBufferSnapshot,
18208) -> bool {
18209    let mut all_insertions = true;
18210    let mut all_deletions = true;
18211
18212    for (range, new_text) in edits.iter() {
18213        let range_is_empty = range.to_offset(&snapshot).is_empty();
18214        let text_is_empty = new_text.is_empty();
18215
18216        if range_is_empty != text_is_empty {
18217            if range_is_empty {
18218                all_deletions = false;
18219            } else {
18220                all_insertions = false;
18221            }
18222        } else {
18223            return false;
18224        }
18225
18226        if !all_insertions && !all_deletions {
18227            return false;
18228        }
18229    }
18230    all_insertions || all_deletions
18231}