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;
   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::{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 code_context_menus::{
   77    AvailableCodeAction, CodeActionContents, CodeActionsItem, CodeActionsMenu, CodeContextMenu,
   78    CompletionsMenu, ContextMenuOrigin,
   79};
   80use git::blame::GitBlame;
   81use gpui::{
   82    div, impl_actions, point, prelude::*, pulsating_between, px, relative, size, Action, Animation,
   83    AnimationExt, AnyElement, App, AsyncWindowContext, AvailableSpace, Bounds, ClipboardEntry,
   84    ClipboardItem, Context, DispatchPhase, ElementId, Entity, EntityInputHandler, EventEmitter,
   85    FocusHandle, FocusOutEvent, Focusable, FontId, FontWeight, Global, HighlightStyle, Hsla,
   86    InteractiveText, KeyContext, Modifiers, MouseButton, MouseDownEvent, PaintQuad, ParentElement,
   87    Pixels, Render, SharedString, Size, Styled, StyledText, Subscription, Task, TextStyle,
   88    TextStyleRefinement, UTF16Selection, UnderlineStyle, UniformListScrollHandle, WeakEntity,
   89    WeakFocusHandle, Window,
   90};
   91use highlight_matching_bracket::refresh_matching_bracket_highlights;
   92use hover_popover::{hide_hover, HoverState};
   93use indent_guides::ActiveIndentGuidesState;
   94use inlay_hint_cache::{InlayHintCache, InlaySplice, InvalidationStrategy};
   95pub use inline_completion::Direction;
   96use inline_completion::{EditPredictionProvider, InlineCompletionProviderHandle};
   97pub use items::MAX_TAB_TITLE_LEN;
   98use itertools::Itertools;
   99use language::{
  100    language_settings::{self, all_language_settings, language_settings, InlayHintSettings},
  101    markdown, point_from_lsp, AutoindentMode, BracketPair, Buffer, Capability, CharKind, CodeLabel,
  102    CompletionDocumentation, CursorShape, Diagnostic, DiskState, EditPredictionsMode, EditPreview,
  103    HighlightedText, IndentKind, IndentSize, Language, OffsetRangeExt, Point, Selection,
  104    SelectionGoal, TextObject, TransactionId, TreeSitterOptions,
  105};
  106use language::{point_to_lsp, BufferRow, CharClassifier, Runnable, RunnableRange};
  107use linked_editing_ranges::refresh_linked_ranges;
  108use mouse_context_menu::MouseContextMenu;
  109pub use proposed_changes_editor::{
  110    ProposedChangeLocation, ProposedChangesEditor, ProposedChangesEditorToolbar,
  111};
  112use similar::{ChangeTag, TextDiff};
  113use std::iter::Peekable;
  114use task::{ResolvedTask, TaskTemplate, TaskVariables};
  115
  116use hover_links::{find_file, HoverLink, HoveredLinkState, InlayHighlight};
  117pub use lsp::CompletionContext;
  118use lsp::{
  119    CompletionItemKind, CompletionTriggerKind, DiagnosticSeverity, InsertTextFormat,
  120    LanguageServerId, LanguageServerName,
  121};
  122
  123use language::BufferSnapshot;
  124use movement::TextLayoutDetails;
  125pub use multi_buffer::{
  126    Anchor, AnchorRangeExt, ExcerptId, ExcerptRange, MultiBuffer, MultiBufferSnapshot, RowInfo,
  127    ToOffset, ToPoint,
  128};
  129use multi_buffer::{
  130    ExcerptInfo, ExpandExcerptDirection, MultiBufferDiffHunk, MultiBufferPoint, MultiBufferRow,
  131    ToOffsetUtf16,
  132};
  133use project::{
  134    lsp_store::{FormatTrigger, LspFormatTarget, OpenLspBufferHandle},
  135    project_settings::{GitGutterSetting, ProjectSettings},
  136    CodeAction, Completion, CompletionIntent, DocumentHighlight, InlayHint, Location, LocationLink,
  137    LspStore, PrepareRenameResponse, Project, ProjectItem, ProjectTransaction, TaskSourceKind,
  138};
  139use rand::prelude::*;
  140use rpc::{proto::*, ErrorExt};
  141use scroll::{Autoscroll, OngoingScroll, ScrollAnchor, ScrollManager, ScrollbarAutoHide};
  142use selections_collection::{
  143    resolve_selections, MutableSelectionsCollection, SelectionsCollection,
  144};
  145use serde::{Deserialize, Serialize};
  146use settings::{update_settings_file, Settings, SettingsLocation, SettingsStore};
  147use smallvec::SmallVec;
  148use snippet::Snippet;
  149use std::{
  150    any::TypeId,
  151    borrow::Cow,
  152    cell::RefCell,
  153    cmp::{self, Ordering, Reverse},
  154    mem,
  155    num::NonZeroU32,
  156    ops::{ControlFlow, Deref, DerefMut, Not as _, Range, RangeInclusive},
  157    path::{Path, PathBuf},
  158    rc::Rc,
  159    sync::Arc,
  160    time::{Duration, Instant},
  161};
  162pub use sum_tree::Bias;
  163use sum_tree::TreeMap;
  164use text::{BufferId, OffsetUtf16, Rope};
  165use theme::{
  166    observe_buffer_font_size_adjustment, ActiveTheme, PlayerColor, StatusColors, SyntaxTheme,
  167    ThemeColors, ThemeSettings,
  168};
  169use ui::{
  170    h_flex, prelude::*, ButtonSize, ButtonStyle, Disclosure, IconButton, IconName, IconSize, Key,
  171    Tooltip,
  172};
  173use util::{defer, maybe, post_inc, RangeExt, ResultExt, TakeUntilExt, TryFutureExt};
  174use workspace::item::{ItemHandle, PreviewTabsSettings};
  175use workspace::notifications::{DetachAndPromptErr, NotificationId, NotifyTaskExt};
  176use workspace::{
  177    searchable::SearchEvent, ItemNavHistory, SplitDirection, ViewId, Workspace, WorkspaceId,
  178};
  179use workspace::{Item as WorkspaceItem, OpenInTerminal, OpenTerminal, TabBarSettings, Toast};
  180
  181use crate::hover_links::{find_url, find_url_from_range};
  182use crate::signature_help::{SignatureHelpHiddenBy, SignatureHelpState};
  183
  184pub const FILE_HEADER_HEIGHT: u32 = 2;
  185pub const MULTI_BUFFER_EXCERPT_HEADER_HEIGHT: u32 = 1;
  186pub const MULTI_BUFFER_EXCERPT_FOOTER_HEIGHT: u32 = 1;
  187pub const DEFAULT_MULTIBUFFER_CONTEXT: u32 = 2;
  188const CURSOR_BLINK_INTERVAL: Duration = Duration::from_millis(500);
  189const MAX_LINE_LEN: usize = 1024;
  190const MIN_NAVIGATION_HISTORY_ROW_DELTA: i64 = 10;
  191const MAX_SELECTION_HISTORY_LEN: usize = 1024;
  192pub(crate) const CURSORS_VISIBLE_FOR: Duration = Duration::from_millis(2000);
  193#[doc(hidden)]
  194pub const CODE_ACTIONS_DEBOUNCE_TIMEOUT: Duration = Duration::from_millis(250);
  195
  196pub(crate) const FORMAT_TIMEOUT: Duration = Duration::from_secs(2);
  197pub(crate) const SCROLL_CENTER_TOP_BOTTOM_DEBOUNCE_TIMEOUT: Duration = Duration::from_secs(1);
  198
  199pub(crate) const EDIT_PREDICTION_KEY_CONTEXT: &str = "edit_prediction";
  200pub(crate) const EDIT_PREDICTION_CONFLICT_KEY_CONTEXT: &str = "edit_prediction_conflict";
  201
  202pub fn render_parsed_markdown(
  203    element_id: impl Into<ElementId>,
  204    parsed: &language::ParsedMarkdown,
  205    editor_style: &EditorStyle,
  206    workspace: Option<WeakEntity<Workspace>>,
  207    cx: &mut App,
  208) -> InteractiveText {
  209    let code_span_background_color = cx
  210        .theme()
  211        .colors()
  212        .editor_document_highlight_read_background;
  213
  214    let highlights = gpui::combine_highlights(
  215        parsed.highlights.iter().filter_map(|(range, highlight)| {
  216            let highlight = highlight.to_highlight_style(&editor_style.syntax)?;
  217            Some((range.clone(), highlight))
  218        }),
  219        parsed
  220            .regions
  221            .iter()
  222            .zip(&parsed.region_ranges)
  223            .filter_map(|(region, range)| {
  224                if region.code {
  225                    Some((
  226                        range.clone(),
  227                        HighlightStyle {
  228                            background_color: Some(code_span_background_color),
  229                            ..Default::default()
  230                        },
  231                    ))
  232                } else {
  233                    None
  234                }
  235            }),
  236    );
  237
  238    let mut links = Vec::new();
  239    let mut link_ranges = Vec::new();
  240    for (range, region) in parsed.region_ranges.iter().zip(&parsed.regions) {
  241        if let Some(link) = region.link.clone() {
  242            links.push(link);
  243            link_ranges.push(range.clone());
  244        }
  245    }
  246
  247    InteractiveText::new(
  248        element_id,
  249        StyledText::new(parsed.text.clone()).with_highlights(&editor_style.text, highlights),
  250    )
  251    .on_click(
  252        link_ranges,
  253        move |clicked_range_ix, window, cx| match &links[clicked_range_ix] {
  254            markdown::Link::Web { url } => cx.open_url(url),
  255            markdown::Link::Path { path } => {
  256                if let Some(workspace) = &workspace {
  257                    _ = workspace.update(cx, |workspace, cx| {
  258                        workspace
  259                            .open_abs_path(path.clone(), false, window, cx)
  260                            .detach();
  261                    });
  262                }
  263            }
  264        },
  265    )
  266}
  267
  268#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
  269pub enum InlayId {
  270    InlineCompletion(usize),
  271    Hint(usize),
  272}
  273
  274impl InlayId {
  275    fn id(&self) -> usize {
  276        match self {
  277            Self::InlineCompletion(id) => *id,
  278            Self::Hint(id) => *id,
  279        }
  280    }
  281}
  282
  283enum DocumentHighlightRead {}
  284enum DocumentHighlightWrite {}
  285enum InputComposition {}
  286
  287#[derive(Debug, Copy, Clone, PartialEq, Eq)]
  288pub enum Navigated {
  289    Yes,
  290    No,
  291}
  292
  293impl Navigated {
  294    pub fn from_bool(yes: bool) -> Navigated {
  295        if yes {
  296            Navigated::Yes
  297        } else {
  298            Navigated::No
  299        }
  300    }
  301}
  302
  303pub fn init_settings(cx: &mut App) {
  304    EditorSettings::register(cx);
  305}
  306
  307pub fn init(cx: &mut App) {
  308    init_settings(cx);
  309
  310    workspace::register_project_item::<Editor>(cx);
  311    workspace::FollowableViewRegistry::register::<Editor>(cx);
  312    workspace::register_serializable_item::<Editor>(cx);
  313
  314    cx.observe_new(
  315        |workspace: &mut Workspace, _: Option<&mut Window>, _cx: &mut Context<Workspace>| {
  316            workspace.register_action(Editor::new_file);
  317            workspace.register_action(Editor::new_file_vertical);
  318            workspace.register_action(Editor::new_file_horizontal);
  319            workspace.register_action(Editor::cancel_language_server_work);
  320        },
  321    )
  322    .detach();
  323
  324    cx.on_action(move |_: &workspace::NewFile, cx| {
  325        let app_state = workspace::AppState::global(cx);
  326        if let Some(app_state) = app_state.upgrade() {
  327            workspace::open_new(
  328                Default::default(),
  329                app_state,
  330                cx,
  331                |workspace, window, cx| {
  332                    Editor::new_file(workspace, &Default::default(), window, cx)
  333                },
  334            )
  335            .detach();
  336        }
  337    });
  338    cx.on_action(move |_: &workspace::NewWindow, cx| {
  339        let app_state = workspace::AppState::global(cx);
  340        if let Some(app_state) = app_state.upgrade() {
  341            workspace::open_new(
  342                Default::default(),
  343                app_state,
  344                cx,
  345                |workspace, window, cx| {
  346                    cx.activate(true);
  347                    Editor::new_file(workspace, &Default::default(), window, cx)
  348                },
  349            )
  350            .detach();
  351        }
  352    });
  353}
  354
  355pub struct SearchWithinRange;
  356
  357trait InvalidationRegion {
  358    fn ranges(&self) -> &[Range<Anchor>];
  359}
  360
  361#[derive(Clone, Debug, PartialEq)]
  362pub enum SelectPhase {
  363    Begin {
  364        position: DisplayPoint,
  365        add: bool,
  366        click_count: usize,
  367    },
  368    BeginColumnar {
  369        position: DisplayPoint,
  370        reset: bool,
  371        goal_column: u32,
  372    },
  373    Extend {
  374        position: DisplayPoint,
  375        click_count: usize,
  376    },
  377    Update {
  378        position: DisplayPoint,
  379        goal_column: u32,
  380        scroll_delta: gpui::Point<f32>,
  381    },
  382    End,
  383}
  384
  385#[derive(Clone, Debug)]
  386pub enum SelectMode {
  387    Character,
  388    Word(Range<Anchor>),
  389    Line(Range<Anchor>),
  390    All,
  391}
  392
  393#[derive(Copy, Clone, PartialEq, Eq, Debug)]
  394pub enum EditorMode {
  395    SingleLine { auto_width: bool },
  396    AutoHeight { max_lines: usize },
  397    Full,
  398}
  399
  400#[derive(Copy, Clone, Debug)]
  401pub enum SoftWrap {
  402    /// Prefer not to wrap at all.
  403    ///
  404    /// Note: this is currently internal, as actually limited by [`crate::MAX_LINE_LEN`] until it wraps.
  405    /// The mode is used inside git diff hunks, where it's seems currently more useful to not wrap as much as possible.
  406    GitDiff,
  407    /// Prefer a single line generally, unless an overly long line is encountered.
  408    None,
  409    /// Soft wrap lines that exceed the editor width.
  410    EditorWidth,
  411    /// Soft wrap lines at the preferred line length.
  412    Column(u32),
  413    /// Soft wrap line at the preferred line length or the editor width (whichever is smaller).
  414    Bounded(u32),
  415}
  416
  417#[derive(Clone)]
  418pub struct EditorStyle {
  419    pub background: Hsla,
  420    pub local_player: PlayerColor,
  421    pub text: TextStyle,
  422    pub scrollbar_width: Pixels,
  423    pub syntax: Arc<SyntaxTheme>,
  424    pub status: StatusColors,
  425    pub inlay_hints_style: HighlightStyle,
  426    pub inline_completion_styles: InlineCompletionStyles,
  427    pub unnecessary_code_fade: f32,
  428}
  429
  430impl Default for EditorStyle {
  431    fn default() -> Self {
  432        Self {
  433            background: Hsla::default(),
  434            local_player: PlayerColor::default(),
  435            text: TextStyle::default(),
  436            scrollbar_width: Pixels::default(),
  437            syntax: Default::default(),
  438            // HACK: Status colors don't have a real default.
  439            // We should look into removing the status colors from the editor
  440            // style and retrieve them directly from the theme.
  441            status: StatusColors::dark(),
  442            inlay_hints_style: HighlightStyle::default(),
  443            inline_completion_styles: InlineCompletionStyles {
  444                insertion: HighlightStyle::default(),
  445                whitespace: HighlightStyle::default(),
  446            },
  447            unnecessary_code_fade: Default::default(),
  448        }
  449    }
  450}
  451
  452pub fn make_inlay_hints_style(cx: &mut App) -> HighlightStyle {
  453    let show_background = language_settings::language_settings(None, None, cx)
  454        .inlay_hints
  455        .show_background;
  456
  457    HighlightStyle {
  458        color: Some(cx.theme().status().hint),
  459        background_color: show_background.then(|| cx.theme().status().hint_background),
  460        ..HighlightStyle::default()
  461    }
  462}
  463
  464pub fn make_suggestion_styles(cx: &mut App) -> InlineCompletionStyles {
  465    InlineCompletionStyles {
  466        insertion: HighlightStyle {
  467            color: Some(cx.theme().status().predictive),
  468            ..HighlightStyle::default()
  469        },
  470        whitespace: HighlightStyle {
  471            background_color: Some(cx.theme().status().created_background),
  472            ..HighlightStyle::default()
  473        },
  474    }
  475}
  476
  477type CompletionId = usize;
  478
  479pub(crate) enum EditDisplayMode {
  480    TabAccept,
  481    DiffPopover,
  482    Inline,
  483}
  484
  485enum InlineCompletion {
  486    Edit {
  487        edits: Vec<(Range<Anchor>, String)>,
  488        edit_preview: Option<EditPreview>,
  489        display_mode: EditDisplayMode,
  490        snapshot: BufferSnapshot,
  491    },
  492    Move {
  493        target: Anchor,
  494        snapshot: BufferSnapshot,
  495    },
  496}
  497
  498struct InlineCompletionState {
  499    inlay_ids: Vec<InlayId>,
  500    completion: InlineCompletion,
  501    completion_id: Option<SharedString>,
  502    invalidation_range: Range<Anchor>,
  503}
  504
  505enum EditPredictionSettings {
  506    Disabled,
  507    Enabled {
  508        show_in_menu: bool,
  509        preview_requires_modifier: bool,
  510    },
  511}
  512
  513impl EditPredictionSettings {
  514    pub fn is_enabled(&self) -> bool {
  515        match self {
  516            EditPredictionSettings::Disabled => false,
  517            EditPredictionSettings::Enabled { .. } => true,
  518        }
  519    }
  520}
  521
  522enum InlineCompletionHighlight {}
  523
  524pub enum MenuInlineCompletionsPolicy {
  525    Never,
  526    ByProvider,
  527}
  528
  529pub enum EditPredictionPreview {
  530    /// Modifier is not pressed
  531    Inactive,
  532    /// Modifier pressed
  533    Active {
  534        previous_scroll_position: Option<ScrollAnchor>,
  535    },
  536}
  537
  538#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Debug, Default)]
  539struct EditorActionId(usize);
  540
  541impl EditorActionId {
  542    pub fn post_inc(&mut self) -> Self {
  543        let answer = self.0;
  544
  545        *self = Self(answer + 1);
  546
  547        Self(answer)
  548    }
  549}
  550
  551// type GetFieldEditorTheme = dyn Fn(&theme::Theme) -> theme::FieldEditor;
  552// type OverrideTextStyle = dyn Fn(&EditorStyle) -> Option<HighlightStyle>;
  553
  554type BackgroundHighlight = (fn(&ThemeColors) -> Hsla, Arc<[Range<Anchor>]>);
  555type GutterHighlight = (fn(&App) -> Hsla, Arc<[Range<Anchor>]>);
  556
  557#[derive(Default)]
  558struct ScrollbarMarkerState {
  559    scrollbar_size: Size<Pixels>,
  560    dirty: bool,
  561    markers: Arc<[PaintQuad]>,
  562    pending_refresh: Option<Task<Result<()>>>,
  563}
  564
  565impl ScrollbarMarkerState {
  566    fn should_refresh(&self, scrollbar_size: Size<Pixels>) -> bool {
  567        self.pending_refresh.is_none() && (self.scrollbar_size != scrollbar_size || self.dirty)
  568    }
  569}
  570
  571#[derive(Clone, Debug)]
  572struct RunnableTasks {
  573    templates: Vec<(TaskSourceKind, TaskTemplate)>,
  574    offset: MultiBufferOffset,
  575    // We need the column at which the task context evaluation should take place (when we're spawning it via gutter).
  576    column: u32,
  577    // Values of all named captures, including those starting with '_'
  578    extra_variables: HashMap<String, String>,
  579    // Full range of the tagged region. We use it to determine which `extra_variables` to grab for context resolution in e.g. a modal.
  580    context_range: Range<BufferOffset>,
  581}
  582
  583impl RunnableTasks {
  584    fn resolve<'a>(
  585        &'a self,
  586        cx: &'a task::TaskContext,
  587    ) -> impl Iterator<Item = (TaskSourceKind, ResolvedTask)> + 'a {
  588        self.templates.iter().filter_map(|(kind, template)| {
  589            template
  590                .resolve_task(&kind.to_id_base(), cx)
  591                .map(|task| (kind.clone(), task))
  592        })
  593    }
  594}
  595
  596#[derive(Clone)]
  597struct ResolvedTasks {
  598    templates: SmallVec<[(TaskSourceKind, ResolvedTask); 1]>,
  599    position: Anchor,
  600}
  601#[derive(Copy, Clone, Debug)]
  602struct MultiBufferOffset(usize);
  603#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
  604struct BufferOffset(usize);
  605
  606// Addons allow storing per-editor state in other crates (e.g. Vim)
  607pub trait Addon: 'static {
  608    fn extend_key_context(&self, _: &mut KeyContext, _: &App) {}
  609
  610    fn render_buffer_header_controls(
  611        &self,
  612        _: &ExcerptInfo,
  613        _: &Window,
  614        _: &App,
  615    ) -> Option<AnyElement> {
  616        None
  617    }
  618
  619    fn to_any(&self) -> &dyn std::any::Any;
  620}
  621
  622#[derive(Debug, Copy, Clone, PartialEq, Eq)]
  623pub enum IsVimMode {
  624    Yes,
  625    No,
  626}
  627
  628/// Zed's primary implementation of text input, allowing users to edit a [`MultiBuffer`].
  629///
  630/// See the [module level documentation](self) for more information.
  631pub struct Editor {
  632    focus_handle: FocusHandle,
  633    last_focused_descendant: Option<WeakFocusHandle>,
  634    /// The text buffer being edited
  635    buffer: Entity<MultiBuffer>,
  636    /// Map of how text in the buffer should be displayed.
  637    /// Handles soft wraps, folds, fake inlay text insertions, etc.
  638    pub display_map: Entity<DisplayMap>,
  639    pub selections: SelectionsCollection,
  640    pub scroll_manager: ScrollManager,
  641    /// When inline assist editors are linked, they all render cursors because
  642    /// typing enters text into each of them, even the ones that aren't focused.
  643    pub(crate) show_cursor_when_unfocused: bool,
  644    columnar_selection_tail: Option<Anchor>,
  645    add_selections_state: Option<AddSelectionsState>,
  646    select_next_state: Option<SelectNextState>,
  647    select_prev_state: Option<SelectNextState>,
  648    selection_history: SelectionHistory,
  649    autoclose_regions: Vec<AutocloseRegion>,
  650    snippet_stack: InvalidationStack<SnippetState>,
  651    select_larger_syntax_node_stack: Vec<Box<[Selection<usize>]>>,
  652    ime_transaction: Option<TransactionId>,
  653    active_diagnostics: Option<ActiveDiagnosticGroup>,
  654    soft_wrap_mode_override: Option<language_settings::SoftWrap>,
  655
  656    // TODO: make this a access method
  657    pub project: Option<Entity<Project>>,
  658    semantics_provider: Option<Rc<dyn SemanticsProvider>>,
  659    completion_provider: Option<Box<dyn CompletionProvider>>,
  660    collaboration_hub: Option<Box<dyn CollaborationHub>>,
  661    blink_manager: Entity<BlinkManager>,
  662    show_cursor_names: bool,
  663    hovered_cursors: HashMap<HoveredCursor, Task<()>>,
  664    pub show_local_selections: bool,
  665    mode: EditorMode,
  666    show_breadcrumbs: bool,
  667    show_gutter: bool,
  668    show_scrollbars: bool,
  669    show_line_numbers: Option<bool>,
  670    use_relative_line_numbers: Option<bool>,
  671    show_git_diff_gutter: Option<bool>,
  672    show_code_actions: Option<bool>,
  673    show_runnables: Option<bool>,
  674    show_wrap_guides: Option<bool>,
  675    show_indent_guides: Option<bool>,
  676    placeholder_text: Option<Arc<str>>,
  677    highlight_order: usize,
  678    highlighted_rows: HashMap<TypeId, Vec<RowHighlight>>,
  679    background_highlights: TreeMap<TypeId, BackgroundHighlight>,
  680    gutter_highlights: TreeMap<TypeId, GutterHighlight>,
  681    scrollbar_marker_state: ScrollbarMarkerState,
  682    active_indent_guides_state: ActiveIndentGuidesState,
  683    nav_history: Option<ItemNavHistory>,
  684    context_menu: RefCell<Option<CodeContextMenu>>,
  685    mouse_context_menu: Option<MouseContextMenu>,
  686    completion_tasks: Vec<(CompletionId, Task<Option<()>>)>,
  687    signature_help_state: SignatureHelpState,
  688    auto_signature_help: Option<bool>,
  689    find_all_references_task_sources: Vec<Anchor>,
  690    next_completion_id: CompletionId,
  691    available_code_actions: Option<(Location, Rc<[AvailableCodeAction]>)>,
  692    code_actions_task: Option<Task<Result<()>>>,
  693    document_highlights_task: Option<Task<()>>,
  694    linked_editing_range_task: Option<Task<Option<()>>>,
  695    linked_edit_ranges: linked_editing_ranges::LinkedEditingRanges,
  696    pending_rename: Option<RenameState>,
  697    searchable: bool,
  698    cursor_shape: CursorShape,
  699    current_line_highlight: Option<CurrentLineHighlight>,
  700    collapse_matches: bool,
  701    autoindent_mode: Option<AutoindentMode>,
  702    workspace: Option<(WeakEntity<Workspace>, Option<WorkspaceId>)>,
  703    input_enabled: bool,
  704    use_modal_editing: bool,
  705    read_only: bool,
  706    leader_peer_id: Option<PeerId>,
  707    remote_id: Option<ViewId>,
  708    hover_state: HoverState,
  709    pending_mouse_down: Option<Rc<RefCell<Option<MouseDownEvent>>>>,
  710    gutter_hovered: bool,
  711    hovered_link_state: Option<HoveredLinkState>,
  712    edit_prediction_provider: Option<RegisteredInlineCompletionProvider>,
  713    code_action_providers: Vec<Rc<dyn CodeActionProvider>>,
  714    active_inline_completion: Option<InlineCompletionState>,
  715    /// Used to prevent flickering as the user types while the menu is open
  716    stale_inline_completion_in_menu: Option<InlineCompletionState>,
  717    edit_prediction_settings: EditPredictionSettings,
  718    inline_completions_hidden_for_vim_mode: bool,
  719    show_inline_completions_override: Option<bool>,
  720    menu_inline_completions_policy: MenuInlineCompletionsPolicy,
  721    edit_prediction_preview: EditPredictionPreview,
  722    edit_prediction_cursor_on_leading_whitespace: bool,
  723    edit_prediction_requires_modifier_in_leading_space: bool,
  724    inlay_hint_cache: InlayHintCache,
  725    next_inlay_id: usize,
  726    _subscriptions: Vec<Subscription>,
  727    pixel_position_of_newest_cursor: Option<gpui::Point<Pixels>>,
  728    gutter_dimensions: GutterDimensions,
  729    style: Option<EditorStyle>,
  730    text_style_refinement: Option<TextStyleRefinement>,
  731    next_editor_action_id: EditorActionId,
  732    editor_actions:
  733        Rc<RefCell<BTreeMap<EditorActionId, Box<dyn Fn(&mut Window, &mut Context<Self>)>>>>,
  734    use_autoclose: bool,
  735    use_auto_surround: bool,
  736    auto_replace_emoji_shortcode: bool,
  737    show_git_blame_gutter: bool,
  738    show_git_blame_inline: bool,
  739    show_git_blame_inline_delay_task: Option<Task<()>>,
  740    distinguish_unstaged_diff_hunks: bool,
  741    git_blame_inline_enabled: bool,
  742    serialize_dirty_buffers: bool,
  743    show_selection_menu: Option<bool>,
  744    blame: Option<Entity<GitBlame>>,
  745    blame_subscription: Option<Subscription>,
  746    custom_context_menu: Option<
  747        Box<
  748            dyn 'static
  749                + Fn(
  750                    &mut Self,
  751                    DisplayPoint,
  752                    &mut Window,
  753                    &mut Context<Self>,
  754                ) -> Option<Entity<ui::ContextMenu>>,
  755        >,
  756    >,
  757    last_bounds: Option<Bounds<Pixels>>,
  758    last_position_map: Option<Rc<PositionMap>>,
  759    expect_bounds_change: Option<Bounds<Pixels>>,
  760    tasks: BTreeMap<(BufferId, BufferRow), RunnableTasks>,
  761    tasks_update_task: Option<Task<()>>,
  762    in_project_search: bool,
  763    previous_search_ranges: Option<Arc<[Range<Anchor>]>>,
  764    breadcrumb_header: Option<String>,
  765    focused_block: Option<FocusedBlock>,
  766    next_scroll_position: NextScrollCursorCenterTopBottom,
  767    addons: HashMap<TypeId, Box<dyn Addon>>,
  768    registered_buffers: HashMap<BufferId, OpenLspBufferHandle>,
  769    load_diff_task: Option<Shared<Task<()>>>,
  770    selection_mark_mode: bool,
  771    toggle_fold_multiple_buffers: Task<()>,
  772    _scroll_cursor_center_top_bottom_task: Task<()>,
  773}
  774
  775#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)]
  776enum NextScrollCursorCenterTopBottom {
  777    #[default]
  778    Center,
  779    Top,
  780    Bottom,
  781}
  782
  783impl NextScrollCursorCenterTopBottom {
  784    fn next(&self) -> Self {
  785        match self {
  786            Self::Center => Self::Top,
  787            Self::Top => Self::Bottom,
  788            Self::Bottom => Self::Center,
  789        }
  790    }
  791}
  792
  793#[derive(Clone)]
  794pub struct EditorSnapshot {
  795    pub mode: EditorMode,
  796    show_gutter: bool,
  797    show_line_numbers: Option<bool>,
  798    show_git_diff_gutter: Option<bool>,
  799    show_code_actions: Option<bool>,
  800    show_runnables: Option<bool>,
  801    git_blame_gutter_max_author_length: Option<usize>,
  802    pub display_snapshot: DisplaySnapshot,
  803    pub placeholder_text: Option<Arc<str>>,
  804    is_focused: bool,
  805    scroll_anchor: ScrollAnchor,
  806    ongoing_scroll: OngoingScroll,
  807    current_line_highlight: CurrentLineHighlight,
  808    gutter_hovered: bool,
  809}
  810
  811const GIT_BLAME_MAX_AUTHOR_CHARS_DISPLAYED: usize = 20;
  812
  813#[derive(Default, Debug, Clone, Copy)]
  814pub struct GutterDimensions {
  815    pub left_padding: Pixels,
  816    pub right_padding: Pixels,
  817    pub width: Pixels,
  818    pub margin: Pixels,
  819    pub git_blame_entries_width: Option<Pixels>,
  820}
  821
  822impl GutterDimensions {
  823    /// The full width of the space taken up by the gutter.
  824    pub fn full_width(&self) -> Pixels {
  825        self.margin + self.width
  826    }
  827
  828    /// The width of the space reserved for the fold indicators,
  829    /// use alongside 'justify_end' and `gutter_width` to
  830    /// right align content with the line numbers
  831    pub fn fold_area_width(&self) -> Pixels {
  832        self.margin + self.right_padding
  833    }
  834}
  835
  836#[derive(Debug)]
  837pub struct RemoteSelection {
  838    pub replica_id: ReplicaId,
  839    pub selection: Selection<Anchor>,
  840    pub cursor_shape: CursorShape,
  841    pub peer_id: PeerId,
  842    pub line_mode: bool,
  843    pub participant_index: Option<ParticipantIndex>,
  844    pub user_name: Option<SharedString>,
  845}
  846
  847#[derive(Clone, Debug)]
  848struct SelectionHistoryEntry {
  849    selections: Arc<[Selection<Anchor>]>,
  850    select_next_state: Option<SelectNextState>,
  851    select_prev_state: Option<SelectNextState>,
  852    add_selections_state: Option<AddSelectionsState>,
  853}
  854
  855enum SelectionHistoryMode {
  856    Normal,
  857    Undoing,
  858    Redoing,
  859}
  860
  861#[derive(Clone, PartialEq, Eq, Hash)]
  862struct HoveredCursor {
  863    replica_id: u16,
  864    selection_id: usize,
  865}
  866
  867impl Default for SelectionHistoryMode {
  868    fn default() -> Self {
  869        Self::Normal
  870    }
  871}
  872
  873#[derive(Default)]
  874struct SelectionHistory {
  875    #[allow(clippy::type_complexity)]
  876    selections_by_transaction:
  877        HashMap<TransactionId, (Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)>,
  878    mode: SelectionHistoryMode,
  879    undo_stack: VecDeque<SelectionHistoryEntry>,
  880    redo_stack: VecDeque<SelectionHistoryEntry>,
  881}
  882
  883impl SelectionHistory {
  884    fn insert_transaction(
  885        &mut self,
  886        transaction_id: TransactionId,
  887        selections: Arc<[Selection<Anchor>]>,
  888    ) {
  889        self.selections_by_transaction
  890            .insert(transaction_id, (selections, None));
  891    }
  892
  893    #[allow(clippy::type_complexity)]
  894    fn transaction(
  895        &self,
  896        transaction_id: TransactionId,
  897    ) -> Option<&(Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)> {
  898        self.selections_by_transaction.get(&transaction_id)
  899    }
  900
  901    #[allow(clippy::type_complexity)]
  902    fn transaction_mut(
  903        &mut self,
  904        transaction_id: TransactionId,
  905    ) -> Option<&mut (Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)> {
  906        self.selections_by_transaction.get_mut(&transaction_id)
  907    }
  908
  909    fn push(&mut self, entry: SelectionHistoryEntry) {
  910        if !entry.selections.is_empty() {
  911            match self.mode {
  912                SelectionHistoryMode::Normal => {
  913                    self.push_undo(entry);
  914                    self.redo_stack.clear();
  915                }
  916                SelectionHistoryMode::Undoing => self.push_redo(entry),
  917                SelectionHistoryMode::Redoing => self.push_undo(entry),
  918            }
  919        }
  920    }
  921
  922    fn push_undo(&mut self, entry: SelectionHistoryEntry) {
  923        if self
  924            .undo_stack
  925            .back()
  926            .map_or(true, |e| e.selections != entry.selections)
  927        {
  928            self.undo_stack.push_back(entry);
  929            if self.undo_stack.len() > MAX_SELECTION_HISTORY_LEN {
  930                self.undo_stack.pop_front();
  931            }
  932        }
  933    }
  934
  935    fn push_redo(&mut self, entry: SelectionHistoryEntry) {
  936        if self
  937            .redo_stack
  938            .back()
  939            .map_or(true, |e| e.selections != entry.selections)
  940        {
  941            self.redo_stack.push_back(entry);
  942            if self.redo_stack.len() > MAX_SELECTION_HISTORY_LEN {
  943                self.redo_stack.pop_front();
  944            }
  945        }
  946    }
  947}
  948
  949struct RowHighlight {
  950    index: usize,
  951    range: Range<Anchor>,
  952    color: Hsla,
  953    should_autoscroll: bool,
  954}
  955
  956#[derive(Clone, Debug)]
  957struct AddSelectionsState {
  958    above: bool,
  959    stack: Vec<usize>,
  960}
  961
  962#[derive(Clone)]
  963struct SelectNextState {
  964    query: AhoCorasick,
  965    wordwise: bool,
  966    done: bool,
  967}
  968
  969impl std::fmt::Debug for SelectNextState {
  970    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  971        f.debug_struct(std::any::type_name::<Self>())
  972            .field("wordwise", &self.wordwise)
  973            .field("done", &self.done)
  974            .finish()
  975    }
  976}
  977
  978#[derive(Debug)]
  979struct AutocloseRegion {
  980    selection_id: usize,
  981    range: Range<Anchor>,
  982    pair: BracketPair,
  983}
  984
  985#[derive(Debug)]
  986struct SnippetState {
  987    ranges: Vec<Vec<Range<Anchor>>>,
  988    active_index: usize,
  989    choices: Vec<Option<Vec<String>>>,
  990}
  991
  992#[doc(hidden)]
  993pub struct RenameState {
  994    pub range: Range<Anchor>,
  995    pub old_name: Arc<str>,
  996    pub editor: Entity<Editor>,
  997    block_id: CustomBlockId,
  998}
  999
 1000struct InvalidationStack<T>(Vec<T>);
 1001
 1002struct RegisteredInlineCompletionProvider {
 1003    provider: Arc<dyn InlineCompletionProviderHandle>,
 1004    _subscription: Subscription,
 1005}
 1006
 1007#[derive(Debug)]
 1008struct ActiveDiagnosticGroup {
 1009    primary_range: Range<Anchor>,
 1010    primary_message: String,
 1011    group_id: usize,
 1012    blocks: HashMap<CustomBlockId, Diagnostic>,
 1013    is_valid: bool,
 1014}
 1015
 1016#[derive(Serialize, Deserialize, Clone, Debug)]
 1017pub struct ClipboardSelection {
 1018    pub len: usize,
 1019    pub is_entire_line: bool,
 1020    pub first_line_indent: u32,
 1021}
 1022
 1023#[derive(Debug)]
 1024pub(crate) struct NavigationData {
 1025    cursor_anchor: Anchor,
 1026    cursor_position: Point,
 1027    scroll_anchor: ScrollAnchor,
 1028    scroll_top_row: u32,
 1029}
 1030
 1031#[derive(Debug, Clone, Copy, PartialEq, Eq)]
 1032pub enum GotoDefinitionKind {
 1033    Symbol,
 1034    Declaration,
 1035    Type,
 1036    Implementation,
 1037}
 1038
 1039#[derive(Debug, Clone)]
 1040enum InlayHintRefreshReason {
 1041    Toggle(bool),
 1042    SettingsChange(InlayHintSettings),
 1043    NewLinesShown,
 1044    BufferEdited(HashSet<Arc<Language>>),
 1045    RefreshRequested,
 1046    ExcerptsRemoved(Vec<ExcerptId>),
 1047}
 1048
 1049impl InlayHintRefreshReason {
 1050    fn description(&self) -> &'static str {
 1051        match self {
 1052            Self::Toggle(_) => "toggle",
 1053            Self::SettingsChange(_) => "settings change",
 1054            Self::NewLinesShown => "new lines shown",
 1055            Self::BufferEdited(_) => "buffer edited",
 1056            Self::RefreshRequested => "refresh requested",
 1057            Self::ExcerptsRemoved(_) => "excerpts removed",
 1058        }
 1059    }
 1060}
 1061
 1062pub enum FormatTarget {
 1063    Buffers,
 1064    Ranges(Vec<Range<MultiBufferPoint>>),
 1065}
 1066
 1067pub(crate) struct FocusedBlock {
 1068    id: BlockId,
 1069    focus_handle: WeakFocusHandle,
 1070}
 1071
 1072#[derive(Clone)]
 1073enum JumpData {
 1074    MultiBufferRow {
 1075        row: MultiBufferRow,
 1076        line_offset_from_top: u32,
 1077    },
 1078    MultiBufferPoint {
 1079        excerpt_id: ExcerptId,
 1080        position: Point,
 1081        anchor: text::Anchor,
 1082        line_offset_from_top: u32,
 1083    },
 1084}
 1085
 1086pub enum MultibufferSelectionMode {
 1087    First,
 1088    All,
 1089}
 1090
 1091impl Editor {
 1092    pub fn single_line(window: &mut Window, cx: &mut Context<Self>) -> Self {
 1093        let buffer = cx.new(|cx| Buffer::local("", cx));
 1094        let buffer = cx.new(|cx| MultiBuffer::singleton(buffer, cx));
 1095        Self::new(
 1096            EditorMode::SingleLine { auto_width: false },
 1097            buffer,
 1098            None,
 1099            false,
 1100            window,
 1101            cx,
 1102        )
 1103    }
 1104
 1105    pub fn multi_line(window: &mut Window, cx: &mut Context<Self>) -> Self {
 1106        let buffer = cx.new(|cx| Buffer::local("", cx));
 1107        let buffer = cx.new(|cx| MultiBuffer::singleton(buffer, cx));
 1108        Self::new(EditorMode::Full, buffer, None, false, window, cx)
 1109    }
 1110
 1111    pub fn auto_width(window: &mut Window, cx: &mut Context<Self>) -> Self {
 1112        let buffer = cx.new(|cx| Buffer::local("", cx));
 1113        let buffer = cx.new(|cx| MultiBuffer::singleton(buffer, cx));
 1114        Self::new(
 1115            EditorMode::SingleLine { auto_width: true },
 1116            buffer,
 1117            None,
 1118            false,
 1119            window,
 1120            cx,
 1121        )
 1122    }
 1123
 1124    pub fn auto_height(max_lines: usize, window: &mut Window, cx: &mut Context<Self>) -> Self {
 1125        let buffer = cx.new(|cx| Buffer::local("", cx));
 1126        let buffer = cx.new(|cx| MultiBuffer::singleton(buffer, cx));
 1127        Self::new(
 1128            EditorMode::AutoHeight { max_lines },
 1129            buffer,
 1130            None,
 1131            false,
 1132            window,
 1133            cx,
 1134        )
 1135    }
 1136
 1137    pub fn for_buffer(
 1138        buffer: Entity<Buffer>,
 1139        project: Option<Entity<Project>>,
 1140        window: &mut Window,
 1141        cx: &mut Context<Self>,
 1142    ) -> Self {
 1143        let buffer = cx.new(|cx| MultiBuffer::singleton(buffer, cx));
 1144        Self::new(EditorMode::Full, buffer, project, false, window, cx)
 1145    }
 1146
 1147    pub fn for_multibuffer(
 1148        buffer: Entity<MultiBuffer>,
 1149        project: Option<Entity<Project>>,
 1150        show_excerpt_controls: bool,
 1151        window: &mut Window,
 1152        cx: &mut Context<Self>,
 1153    ) -> Self {
 1154        Self::new(
 1155            EditorMode::Full,
 1156            buffer,
 1157            project,
 1158            show_excerpt_controls,
 1159            window,
 1160            cx,
 1161        )
 1162    }
 1163
 1164    pub fn clone(&self, window: &mut Window, cx: &mut Context<Self>) -> Self {
 1165        let show_excerpt_controls = self.display_map.read(cx).show_excerpt_controls();
 1166        let mut clone = Self::new(
 1167            self.mode,
 1168            self.buffer.clone(),
 1169            self.project.clone(),
 1170            show_excerpt_controls,
 1171            window,
 1172            cx,
 1173        );
 1174        self.display_map.update(cx, |display_map, cx| {
 1175            let snapshot = display_map.snapshot(cx);
 1176            clone.display_map.update(cx, |display_map, cx| {
 1177                display_map.set_state(&snapshot, cx);
 1178            });
 1179        });
 1180        clone.selections.clone_state(&self.selections);
 1181        clone.scroll_manager.clone_state(&self.scroll_manager);
 1182        clone.searchable = self.searchable;
 1183        clone
 1184    }
 1185
 1186    pub fn new(
 1187        mode: EditorMode,
 1188        buffer: Entity<MultiBuffer>,
 1189        project: Option<Entity<Project>>,
 1190        show_excerpt_controls: bool,
 1191        window: &mut Window,
 1192        cx: &mut Context<Self>,
 1193    ) -> Self {
 1194        let style = window.text_style();
 1195        let font_size = style.font_size.to_pixels(window.rem_size());
 1196        let editor = cx.entity().downgrade();
 1197        let fold_placeholder = FoldPlaceholder {
 1198            constrain_width: true,
 1199            render: Arc::new(move |fold_id, fold_range, _, cx| {
 1200                let editor = editor.clone();
 1201                div()
 1202                    .id(fold_id)
 1203                    .bg(cx.theme().colors().ghost_element_background)
 1204                    .hover(|style| style.bg(cx.theme().colors().ghost_element_hover))
 1205                    .active(|style| style.bg(cx.theme().colors().ghost_element_active))
 1206                    .rounded_sm()
 1207                    .size_full()
 1208                    .cursor_pointer()
 1209                    .child("")
 1210                    .on_mouse_down(MouseButton::Left, |_, _, cx| cx.stop_propagation())
 1211                    .on_click(move |_, _window, cx| {
 1212                        editor
 1213                            .update(cx, |editor, cx| {
 1214                                editor.unfold_ranges(
 1215                                    &[fold_range.start..fold_range.end],
 1216                                    true,
 1217                                    false,
 1218                                    cx,
 1219                                );
 1220                                cx.stop_propagation();
 1221                            })
 1222                            .ok();
 1223                    })
 1224                    .into_any()
 1225            }),
 1226            merge_adjacent: true,
 1227            ..Default::default()
 1228        };
 1229        let display_map = cx.new(|cx| {
 1230            DisplayMap::new(
 1231                buffer.clone(),
 1232                style.font(),
 1233                font_size,
 1234                None,
 1235                show_excerpt_controls,
 1236                FILE_HEADER_HEIGHT,
 1237                MULTI_BUFFER_EXCERPT_HEADER_HEIGHT,
 1238                MULTI_BUFFER_EXCERPT_FOOTER_HEIGHT,
 1239                fold_placeholder,
 1240                cx,
 1241            )
 1242        });
 1243
 1244        let selections = SelectionsCollection::new(display_map.clone(), buffer.clone());
 1245
 1246        let blink_manager = cx.new(|cx| BlinkManager::new(CURSOR_BLINK_INTERVAL, cx));
 1247
 1248        let soft_wrap_mode_override = matches!(mode, EditorMode::SingleLine { .. })
 1249            .then(|| language_settings::SoftWrap::None);
 1250
 1251        let mut project_subscriptions = Vec::new();
 1252        if mode == EditorMode::Full {
 1253            if let Some(project) = project.as_ref() {
 1254                if buffer.read(cx).is_singleton() {
 1255                    project_subscriptions.push(cx.observe_in(project, window, |_, _, _, cx| {
 1256                        cx.emit(EditorEvent::TitleChanged);
 1257                    }));
 1258                }
 1259                project_subscriptions.push(cx.subscribe_in(
 1260                    project,
 1261                    window,
 1262                    |editor, _, event, window, cx| {
 1263                        if let project::Event::RefreshInlayHints = event {
 1264                            editor
 1265                                .refresh_inlay_hints(InlayHintRefreshReason::RefreshRequested, cx);
 1266                        } else if let project::Event::SnippetEdit(id, snippet_edits) = event {
 1267                            if let Some(buffer) = editor.buffer.read(cx).buffer(*id) {
 1268                                let focus_handle = editor.focus_handle(cx);
 1269                                if focus_handle.is_focused(window) {
 1270                                    let snapshot = buffer.read(cx).snapshot();
 1271                                    for (range, snippet) in snippet_edits {
 1272                                        let editor_range =
 1273                                            language::range_from_lsp(*range).to_offset(&snapshot);
 1274                                        editor
 1275                                            .insert_snippet(
 1276                                                &[editor_range],
 1277                                                snippet.clone(),
 1278                                                window,
 1279                                                cx,
 1280                                            )
 1281                                            .ok();
 1282                                    }
 1283                                }
 1284                            }
 1285                        }
 1286                    },
 1287                ));
 1288                if let Some(task_inventory) = project
 1289                    .read(cx)
 1290                    .task_store()
 1291                    .read(cx)
 1292                    .task_inventory()
 1293                    .cloned()
 1294                {
 1295                    project_subscriptions.push(cx.observe_in(
 1296                        &task_inventory,
 1297                        window,
 1298                        |editor, _, window, cx| {
 1299                            editor.tasks_update_task = Some(editor.refresh_runnables(window, cx));
 1300                        },
 1301                    ));
 1302                }
 1303            }
 1304        }
 1305
 1306        let buffer_snapshot = buffer.read(cx).snapshot(cx);
 1307
 1308        let inlay_hint_settings =
 1309            inlay_hint_settings(selections.newest_anchor().head(), &buffer_snapshot, cx);
 1310        let focus_handle = cx.focus_handle();
 1311        cx.on_focus(&focus_handle, window, Self::handle_focus)
 1312            .detach();
 1313        cx.on_focus_in(&focus_handle, window, Self::handle_focus_in)
 1314            .detach();
 1315        cx.on_focus_out(&focus_handle, window, Self::handle_focus_out)
 1316            .detach();
 1317        cx.on_blur(&focus_handle, window, Self::handle_blur)
 1318            .detach();
 1319
 1320        let show_indent_guides = if matches!(mode, EditorMode::SingleLine { .. }) {
 1321            Some(false)
 1322        } else {
 1323            None
 1324        };
 1325
 1326        let mut code_action_providers = Vec::new();
 1327        let mut load_uncommitted_diff = None;
 1328        if let Some(project) = project.clone() {
 1329            load_uncommitted_diff = Some(
 1330                get_uncommitted_diff_for_buffer(
 1331                    &project,
 1332                    buffer.read(cx).all_buffers(),
 1333                    buffer.clone(),
 1334                    cx,
 1335                )
 1336                .shared(),
 1337            );
 1338            code_action_providers.push(Rc::new(project) as Rc<_>);
 1339        }
 1340
 1341        let mut this = Self {
 1342            focus_handle,
 1343            show_cursor_when_unfocused: false,
 1344            last_focused_descendant: None,
 1345            buffer: buffer.clone(),
 1346            display_map: display_map.clone(),
 1347            selections,
 1348            scroll_manager: ScrollManager::new(cx),
 1349            columnar_selection_tail: None,
 1350            add_selections_state: None,
 1351            select_next_state: None,
 1352            select_prev_state: None,
 1353            selection_history: Default::default(),
 1354            autoclose_regions: Default::default(),
 1355            snippet_stack: Default::default(),
 1356            select_larger_syntax_node_stack: Vec::new(),
 1357            ime_transaction: Default::default(),
 1358            active_diagnostics: None,
 1359            soft_wrap_mode_override,
 1360            completion_provider: project.clone().map(|project| Box::new(project) as _),
 1361            semantics_provider: project.clone().map(|project| Rc::new(project) as _),
 1362            collaboration_hub: project.clone().map(|project| Box::new(project) as _),
 1363            project,
 1364            blink_manager: blink_manager.clone(),
 1365            show_local_selections: true,
 1366            show_scrollbars: true,
 1367            mode,
 1368            show_breadcrumbs: EditorSettings::get_global(cx).toolbar.breadcrumbs,
 1369            show_gutter: mode == EditorMode::Full,
 1370            show_line_numbers: None,
 1371            use_relative_line_numbers: None,
 1372            show_git_diff_gutter: None,
 1373            show_code_actions: None,
 1374            show_runnables: None,
 1375            show_wrap_guides: None,
 1376            show_indent_guides,
 1377            placeholder_text: None,
 1378            highlight_order: 0,
 1379            highlighted_rows: HashMap::default(),
 1380            background_highlights: Default::default(),
 1381            gutter_highlights: TreeMap::default(),
 1382            scrollbar_marker_state: ScrollbarMarkerState::default(),
 1383            active_indent_guides_state: ActiveIndentGuidesState::default(),
 1384            nav_history: None,
 1385            context_menu: RefCell::new(None),
 1386            mouse_context_menu: None,
 1387            completion_tasks: Default::default(),
 1388            signature_help_state: SignatureHelpState::default(),
 1389            auto_signature_help: None,
 1390            find_all_references_task_sources: Vec::new(),
 1391            next_completion_id: 0,
 1392            next_inlay_id: 0,
 1393            code_action_providers,
 1394            available_code_actions: Default::default(),
 1395            code_actions_task: Default::default(),
 1396            document_highlights_task: Default::default(),
 1397            linked_editing_range_task: Default::default(),
 1398            pending_rename: Default::default(),
 1399            searchable: true,
 1400            cursor_shape: EditorSettings::get_global(cx)
 1401                .cursor_shape
 1402                .unwrap_or_default(),
 1403            current_line_highlight: None,
 1404            autoindent_mode: Some(AutoindentMode::EachLine),
 1405            collapse_matches: false,
 1406            workspace: None,
 1407            input_enabled: true,
 1408            use_modal_editing: mode == EditorMode::Full,
 1409            read_only: false,
 1410            use_autoclose: true,
 1411            use_auto_surround: true,
 1412            auto_replace_emoji_shortcode: false,
 1413            leader_peer_id: None,
 1414            remote_id: None,
 1415            hover_state: Default::default(),
 1416            pending_mouse_down: None,
 1417            hovered_link_state: Default::default(),
 1418            edit_prediction_provider: None,
 1419            active_inline_completion: None,
 1420            stale_inline_completion_in_menu: None,
 1421            edit_prediction_preview: EditPredictionPreview::Inactive,
 1422            inlay_hint_cache: InlayHintCache::new(inlay_hint_settings),
 1423
 1424            gutter_hovered: false,
 1425            pixel_position_of_newest_cursor: None,
 1426            last_bounds: None,
 1427            last_position_map: None,
 1428            expect_bounds_change: None,
 1429            gutter_dimensions: GutterDimensions::default(),
 1430            style: None,
 1431            show_cursor_names: false,
 1432            hovered_cursors: Default::default(),
 1433            next_editor_action_id: EditorActionId::default(),
 1434            editor_actions: Rc::default(),
 1435            inline_completions_hidden_for_vim_mode: false,
 1436            show_inline_completions_override: None,
 1437            menu_inline_completions_policy: MenuInlineCompletionsPolicy::ByProvider,
 1438            edit_prediction_settings: EditPredictionSettings::Disabled,
 1439            edit_prediction_cursor_on_leading_whitespace: false,
 1440            edit_prediction_requires_modifier_in_leading_space: true,
 1441            custom_context_menu: None,
 1442            show_git_blame_gutter: false,
 1443            show_git_blame_inline: false,
 1444            distinguish_unstaged_diff_hunks: false,
 1445            show_selection_menu: None,
 1446            show_git_blame_inline_delay_task: None,
 1447            git_blame_inline_enabled: ProjectSettings::get_global(cx).git.inline_blame_enabled(),
 1448            serialize_dirty_buffers: ProjectSettings::get_global(cx)
 1449                .session
 1450                .restore_unsaved_buffers,
 1451            blame: None,
 1452            blame_subscription: None,
 1453            tasks: Default::default(),
 1454            _subscriptions: vec![
 1455                cx.observe(&buffer, Self::on_buffer_changed),
 1456                cx.subscribe_in(&buffer, window, Self::on_buffer_event),
 1457                cx.observe_in(&display_map, window, Self::on_display_map_changed),
 1458                cx.observe(&blink_manager, |_, _, cx| cx.notify()),
 1459                cx.observe_global_in::<SettingsStore>(window, Self::settings_changed),
 1460                observe_buffer_font_size_adjustment(cx, |_, cx| cx.notify()),
 1461                cx.observe_window_activation(window, |editor, window, cx| {
 1462                    let active = window.is_window_active();
 1463                    editor.blink_manager.update(cx, |blink_manager, cx| {
 1464                        if active {
 1465                            blink_manager.enable(cx);
 1466                        } else {
 1467                            blink_manager.disable(cx);
 1468                        }
 1469                    });
 1470                }),
 1471            ],
 1472            tasks_update_task: None,
 1473            linked_edit_ranges: Default::default(),
 1474            in_project_search: false,
 1475            previous_search_ranges: None,
 1476            breadcrumb_header: None,
 1477            focused_block: None,
 1478            next_scroll_position: NextScrollCursorCenterTopBottom::default(),
 1479            addons: HashMap::default(),
 1480            registered_buffers: HashMap::default(),
 1481            _scroll_cursor_center_top_bottom_task: Task::ready(()),
 1482            selection_mark_mode: false,
 1483            toggle_fold_multiple_buffers: Task::ready(()),
 1484            text_style_refinement: None,
 1485            load_diff_task: load_uncommitted_diff,
 1486        };
 1487        this.tasks_update_task = Some(this.refresh_runnables(window, cx));
 1488        this._subscriptions.extend(project_subscriptions);
 1489
 1490        this.end_selection(window, cx);
 1491        this.scroll_manager.show_scrollbar(window, cx);
 1492
 1493        if mode == EditorMode::Full {
 1494            let should_auto_hide_scrollbars = cx.should_auto_hide_scrollbars();
 1495            cx.set_global(ScrollbarAutoHide(should_auto_hide_scrollbars));
 1496
 1497            if this.git_blame_inline_enabled {
 1498                this.git_blame_inline_enabled = true;
 1499                this.start_git_blame_inline(false, window, cx);
 1500            }
 1501
 1502            if let Some(buffer) = buffer.read(cx).as_singleton() {
 1503                if let Some(project) = this.project.as_ref() {
 1504                    let lsp_store = project.read(cx).lsp_store();
 1505                    let handle = lsp_store.update(cx, |lsp_store, cx| {
 1506                        lsp_store.register_buffer_with_language_servers(&buffer, cx)
 1507                    });
 1508                    this.registered_buffers
 1509                        .insert(buffer.read(cx).remote_id(), handle);
 1510                }
 1511            }
 1512        }
 1513
 1514        this.report_editor_event("Editor Opened", None, cx);
 1515        this
 1516    }
 1517
 1518    pub fn mouse_menu_is_focused(&self, window: &Window, cx: &App) -> bool {
 1519        self.mouse_context_menu
 1520            .as_ref()
 1521            .is_some_and(|menu| menu.context_menu.focus_handle(cx).is_focused(window))
 1522    }
 1523
 1524    fn key_context(&self, window: &Window, cx: &App) -> KeyContext {
 1525        self.key_context_internal(self.has_active_inline_completion(), window, cx)
 1526    }
 1527
 1528    fn key_context_internal(
 1529        &self,
 1530        has_active_edit_prediction: bool,
 1531        window: &Window,
 1532        cx: &App,
 1533    ) -> KeyContext {
 1534        let mut key_context = KeyContext::new_with_defaults();
 1535        key_context.add("Editor");
 1536        let mode = match self.mode {
 1537            EditorMode::SingleLine { .. } => "single_line",
 1538            EditorMode::AutoHeight { .. } => "auto_height",
 1539            EditorMode::Full => "full",
 1540        };
 1541
 1542        if EditorSettings::jupyter_enabled(cx) {
 1543            key_context.add("jupyter");
 1544        }
 1545
 1546        key_context.set("mode", mode);
 1547        if self.pending_rename.is_some() {
 1548            key_context.add("renaming");
 1549        }
 1550
 1551        match self.context_menu.borrow().as_ref() {
 1552            Some(CodeContextMenu::Completions(_)) => {
 1553                key_context.add("menu");
 1554                key_context.add("showing_completions");
 1555            }
 1556            Some(CodeContextMenu::CodeActions(_)) => {
 1557                key_context.add("menu");
 1558                key_context.add("showing_code_actions")
 1559            }
 1560            None => {}
 1561        }
 1562
 1563        // Disable vim contexts when a sub-editor (e.g. rename/inline assistant) is focused.
 1564        if !self.focus_handle(cx).contains_focused(window, cx)
 1565            || (self.is_focused(window) || self.mouse_menu_is_focused(window, cx))
 1566        {
 1567            for addon in self.addons.values() {
 1568                addon.extend_key_context(&mut key_context, cx)
 1569            }
 1570        }
 1571
 1572        if let Some(extension) = self
 1573            .buffer
 1574            .read(cx)
 1575            .as_singleton()
 1576            .and_then(|buffer| buffer.read(cx).file()?.path().extension()?.to_str())
 1577        {
 1578            key_context.set("extension", extension.to_string());
 1579        }
 1580
 1581        if has_active_edit_prediction {
 1582            if self.edit_prediction_in_conflict() {
 1583                key_context.add(EDIT_PREDICTION_CONFLICT_KEY_CONTEXT);
 1584            } else {
 1585                key_context.add(EDIT_PREDICTION_KEY_CONTEXT);
 1586                key_context.add("copilot_suggestion");
 1587            }
 1588        }
 1589
 1590        if self.selection_mark_mode {
 1591            key_context.add("selection_mode");
 1592        }
 1593
 1594        key_context
 1595    }
 1596
 1597    pub fn edit_prediction_in_conflict(&self) -> bool {
 1598        if !self.show_edit_predictions_in_menu() {
 1599            return false;
 1600        }
 1601
 1602        let showing_completions = self
 1603            .context_menu
 1604            .borrow()
 1605            .as_ref()
 1606            .map_or(false, |context| {
 1607                matches!(context, CodeContextMenu::Completions(_))
 1608            });
 1609
 1610        showing_completions
 1611            || self.edit_prediction_requires_modifier()
 1612            // Require modifier key when the cursor is on leading whitespace, to allow `tab`
 1613            // bindings to insert tab characters.
 1614            || (self.edit_prediction_requires_modifier_in_leading_space && self.edit_prediction_cursor_on_leading_whitespace)
 1615    }
 1616
 1617    pub fn accept_edit_prediction_keybind(
 1618        &self,
 1619        window: &Window,
 1620        cx: &App,
 1621    ) -> AcceptEditPredictionBinding {
 1622        let key_context = self.key_context_internal(true, window, cx);
 1623        let in_conflict = self.edit_prediction_in_conflict();
 1624
 1625        AcceptEditPredictionBinding(
 1626            window
 1627                .bindings_for_action_in_context(&AcceptEditPrediction, key_context)
 1628                .into_iter()
 1629                .filter(|binding| {
 1630                    !in_conflict
 1631                        || binding
 1632                            .keystrokes()
 1633                            .first()
 1634                            .map_or(false, |keystroke| keystroke.modifiers.modified())
 1635                })
 1636                .rev()
 1637                .min_by_key(|binding| {
 1638                    binding
 1639                        .keystrokes()
 1640                        .first()
 1641                        .map_or(u8::MAX, |k| k.modifiers.number_of_modifiers())
 1642                }),
 1643        )
 1644    }
 1645
 1646    pub fn new_file(
 1647        workspace: &mut Workspace,
 1648        _: &workspace::NewFile,
 1649        window: &mut Window,
 1650        cx: &mut Context<Workspace>,
 1651    ) {
 1652        Self::new_in_workspace(workspace, window, cx).detach_and_prompt_err(
 1653            "Failed to create buffer",
 1654            window,
 1655            cx,
 1656            |e, _, _| match e.error_code() {
 1657                ErrorCode::RemoteUpgradeRequired => Some(format!(
 1658                "The remote instance of Zed does not support this yet. It must be upgraded to {}",
 1659                e.error_tag("required").unwrap_or("the latest version")
 1660            )),
 1661                _ => None,
 1662            },
 1663        );
 1664    }
 1665
 1666    pub fn new_in_workspace(
 1667        workspace: &mut Workspace,
 1668        window: &mut Window,
 1669        cx: &mut Context<Workspace>,
 1670    ) -> Task<Result<Entity<Editor>>> {
 1671        let project = workspace.project().clone();
 1672        let create = project.update(cx, |project, cx| project.create_buffer(cx));
 1673
 1674        cx.spawn_in(window, |workspace, mut cx| async move {
 1675            let buffer = create.await?;
 1676            workspace.update_in(&mut cx, |workspace, window, cx| {
 1677                let editor =
 1678                    cx.new(|cx| Editor::for_buffer(buffer, Some(project.clone()), window, cx));
 1679                workspace.add_item_to_active_pane(Box::new(editor.clone()), None, true, window, cx);
 1680                editor
 1681            })
 1682        })
 1683    }
 1684
 1685    fn new_file_vertical(
 1686        workspace: &mut Workspace,
 1687        _: &workspace::NewFileSplitVertical,
 1688        window: &mut Window,
 1689        cx: &mut Context<Workspace>,
 1690    ) {
 1691        Self::new_file_in_direction(workspace, SplitDirection::vertical(cx), window, cx)
 1692    }
 1693
 1694    fn new_file_horizontal(
 1695        workspace: &mut Workspace,
 1696        _: &workspace::NewFileSplitHorizontal,
 1697        window: &mut Window,
 1698        cx: &mut Context<Workspace>,
 1699    ) {
 1700        Self::new_file_in_direction(workspace, SplitDirection::horizontal(cx), window, cx)
 1701    }
 1702
 1703    fn new_file_in_direction(
 1704        workspace: &mut Workspace,
 1705        direction: SplitDirection,
 1706        window: &mut Window,
 1707        cx: &mut Context<Workspace>,
 1708    ) {
 1709        let project = workspace.project().clone();
 1710        let create = project.update(cx, |project, cx| project.create_buffer(cx));
 1711
 1712        cx.spawn_in(window, |workspace, mut cx| async move {
 1713            let buffer = create.await?;
 1714            workspace.update_in(&mut cx, move |workspace, window, cx| {
 1715                workspace.split_item(
 1716                    direction,
 1717                    Box::new(
 1718                        cx.new(|cx| Editor::for_buffer(buffer, Some(project.clone()), window, cx)),
 1719                    ),
 1720                    window,
 1721                    cx,
 1722                )
 1723            })?;
 1724            anyhow::Ok(())
 1725        })
 1726        .detach_and_prompt_err("Failed to create buffer", window, cx, |e, _, _| {
 1727            match e.error_code() {
 1728                ErrorCode::RemoteUpgradeRequired => Some(format!(
 1729                "The remote instance of Zed does not support this yet. It must be upgraded to {}",
 1730                e.error_tag("required").unwrap_or("the latest version")
 1731            )),
 1732                _ => None,
 1733            }
 1734        });
 1735    }
 1736
 1737    pub fn leader_peer_id(&self) -> Option<PeerId> {
 1738        self.leader_peer_id
 1739    }
 1740
 1741    pub fn buffer(&self) -> &Entity<MultiBuffer> {
 1742        &self.buffer
 1743    }
 1744
 1745    pub fn workspace(&self) -> Option<Entity<Workspace>> {
 1746        self.workspace.as_ref()?.0.upgrade()
 1747    }
 1748
 1749    pub fn title<'a>(&self, cx: &'a App) -> Cow<'a, str> {
 1750        self.buffer().read(cx).title(cx)
 1751    }
 1752
 1753    pub fn snapshot(&self, window: &mut Window, cx: &mut App) -> EditorSnapshot {
 1754        let git_blame_gutter_max_author_length = self
 1755            .render_git_blame_gutter(cx)
 1756            .then(|| {
 1757                if let Some(blame) = self.blame.as_ref() {
 1758                    let max_author_length =
 1759                        blame.update(cx, |blame, cx| blame.max_author_length(cx));
 1760                    Some(max_author_length)
 1761                } else {
 1762                    None
 1763                }
 1764            })
 1765            .flatten();
 1766
 1767        EditorSnapshot {
 1768            mode: self.mode,
 1769            show_gutter: self.show_gutter,
 1770            show_line_numbers: self.show_line_numbers,
 1771            show_git_diff_gutter: self.show_git_diff_gutter,
 1772            show_code_actions: self.show_code_actions,
 1773            show_runnables: self.show_runnables,
 1774            git_blame_gutter_max_author_length,
 1775            display_snapshot: self.display_map.update(cx, |map, cx| map.snapshot(cx)),
 1776            scroll_anchor: self.scroll_manager.anchor(),
 1777            ongoing_scroll: self.scroll_manager.ongoing_scroll(),
 1778            placeholder_text: self.placeholder_text.clone(),
 1779            is_focused: self.focus_handle.is_focused(window),
 1780            current_line_highlight: self
 1781                .current_line_highlight
 1782                .unwrap_or_else(|| EditorSettings::get_global(cx).current_line_highlight),
 1783            gutter_hovered: self.gutter_hovered,
 1784        }
 1785    }
 1786
 1787    pub fn language_at<T: ToOffset>(&self, point: T, cx: &App) -> Option<Arc<Language>> {
 1788        self.buffer.read(cx).language_at(point, cx)
 1789    }
 1790
 1791    pub fn file_at<T: ToOffset>(&self, point: T, cx: &App) -> Option<Arc<dyn language::File>> {
 1792        self.buffer.read(cx).read(cx).file_at(point).cloned()
 1793    }
 1794
 1795    pub fn active_excerpt(
 1796        &self,
 1797        cx: &App,
 1798    ) -> Option<(ExcerptId, Entity<Buffer>, Range<text::Anchor>)> {
 1799        self.buffer
 1800            .read(cx)
 1801            .excerpt_containing(self.selections.newest_anchor().head(), cx)
 1802    }
 1803
 1804    pub fn mode(&self) -> EditorMode {
 1805        self.mode
 1806    }
 1807
 1808    pub fn collaboration_hub(&self) -> Option<&dyn CollaborationHub> {
 1809        self.collaboration_hub.as_deref()
 1810    }
 1811
 1812    pub fn set_collaboration_hub(&mut self, hub: Box<dyn CollaborationHub>) {
 1813        self.collaboration_hub = Some(hub);
 1814    }
 1815
 1816    pub fn set_in_project_search(&mut self, in_project_search: bool) {
 1817        self.in_project_search = in_project_search;
 1818    }
 1819
 1820    pub fn set_custom_context_menu(
 1821        &mut self,
 1822        f: impl 'static
 1823            + Fn(
 1824                &mut Self,
 1825                DisplayPoint,
 1826                &mut Window,
 1827                &mut Context<Self>,
 1828            ) -> Option<Entity<ui::ContextMenu>>,
 1829    ) {
 1830        self.custom_context_menu = Some(Box::new(f))
 1831    }
 1832
 1833    pub fn set_completion_provider(&mut self, provider: Option<Box<dyn CompletionProvider>>) {
 1834        self.completion_provider = provider;
 1835    }
 1836
 1837    pub fn semantics_provider(&self) -> Option<Rc<dyn SemanticsProvider>> {
 1838        self.semantics_provider.clone()
 1839    }
 1840
 1841    pub fn set_semantics_provider(&mut self, provider: Option<Rc<dyn SemanticsProvider>>) {
 1842        self.semantics_provider = provider;
 1843    }
 1844
 1845    pub fn set_edit_prediction_provider<T>(
 1846        &mut self,
 1847        provider: Option<Entity<T>>,
 1848        window: &mut Window,
 1849        cx: &mut Context<Self>,
 1850    ) where
 1851        T: EditPredictionProvider,
 1852    {
 1853        self.edit_prediction_provider =
 1854            provider.map(|provider| RegisteredInlineCompletionProvider {
 1855                _subscription: cx.observe_in(&provider, window, |this, _, window, cx| {
 1856                    if this.focus_handle.is_focused(window) {
 1857                        this.update_visible_inline_completion(window, cx);
 1858                    }
 1859                }),
 1860                provider: Arc::new(provider),
 1861            });
 1862        self.refresh_inline_completion(false, false, window, cx);
 1863    }
 1864
 1865    pub fn placeholder_text(&self) -> Option<&str> {
 1866        self.placeholder_text.as_deref()
 1867    }
 1868
 1869    pub fn set_placeholder_text(
 1870        &mut self,
 1871        placeholder_text: impl Into<Arc<str>>,
 1872        cx: &mut Context<Self>,
 1873    ) {
 1874        let placeholder_text = Some(placeholder_text.into());
 1875        if self.placeholder_text != placeholder_text {
 1876            self.placeholder_text = placeholder_text;
 1877            cx.notify();
 1878        }
 1879    }
 1880
 1881    pub fn set_cursor_shape(&mut self, cursor_shape: CursorShape, cx: &mut Context<Self>) {
 1882        self.cursor_shape = cursor_shape;
 1883
 1884        // Disrupt blink for immediate user feedback that the cursor shape has changed
 1885        self.blink_manager.update(cx, BlinkManager::show_cursor);
 1886
 1887        cx.notify();
 1888    }
 1889
 1890    pub fn set_current_line_highlight(
 1891        &mut self,
 1892        current_line_highlight: Option<CurrentLineHighlight>,
 1893    ) {
 1894        self.current_line_highlight = current_line_highlight;
 1895    }
 1896
 1897    pub fn set_collapse_matches(&mut self, collapse_matches: bool) {
 1898        self.collapse_matches = collapse_matches;
 1899    }
 1900
 1901    fn register_buffers_with_language_servers(&mut self, cx: &mut Context<Self>) {
 1902        let buffers = self.buffer.read(cx).all_buffers();
 1903        let Some(lsp_store) = self.lsp_store(cx) else {
 1904            return;
 1905        };
 1906        lsp_store.update(cx, |lsp_store, cx| {
 1907            for buffer in buffers {
 1908                self.registered_buffers
 1909                    .entry(buffer.read(cx).remote_id())
 1910                    .or_insert_with(|| {
 1911                        lsp_store.register_buffer_with_language_servers(&buffer, cx)
 1912                    });
 1913            }
 1914        })
 1915    }
 1916
 1917    pub fn range_for_match<T: std::marker::Copy>(&self, range: &Range<T>) -> Range<T> {
 1918        if self.collapse_matches {
 1919            return range.start..range.start;
 1920        }
 1921        range.clone()
 1922    }
 1923
 1924    pub fn set_clip_at_line_ends(&mut self, clip: bool, cx: &mut Context<Self>) {
 1925        if self.display_map.read(cx).clip_at_line_ends != clip {
 1926            self.display_map
 1927                .update(cx, |map, _| map.clip_at_line_ends = clip);
 1928        }
 1929    }
 1930
 1931    pub fn set_input_enabled(&mut self, input_enabled: bool) {
 1932        self.input_enabled = input_enabled;
 1933    }
 1934
 1935    pub fn set_inline_completions_hidden_for_vim_mode(
 1936        &mut self,
 1937        hidden: bool,
 1938        window: &mut Window,
 1939        cx: &mut Context<Self>,
 1940    ) {
 1941        if hidden != self.inline_completions_hidden_for_vim_mode {
 1942            self.inline_completions_hidden_for_vim_mode = hidden;
 1943            if hidden {
 1944                self.update_visible_inline_completion(window, cx);
 1945            } else {
 1946                self.refresh_inline_completion(true, false, window, cx);
 1947            }
 1948        }
 1949    }
 1950
 1951    pub fn set_menu_inline_completions_policy(&mut self, value: MenuInlineCompletionsPolicy) {
 1952        self.menu_inline_completions_policy = value;
 1953    }
 1954
 1955    pub fn set_autoindent(&mut self, autoindent: bool) {
 1956        if autoindent {
 1957            self.autoindent_mode = Some(AutoindentMode::EachLine);
 1958        } else {
 1959            self.autoindent_mode = None;
 1960        }
 1961    }
 1962
 1963    pub fn read_only(&self, cx: &App) -> bool {
 1964        self.read_only || self.buffer.read(cx).read_only()
 1965    }
 1966
 1967    pub fn set_read_only(&mut self, read_only: bool) {
 1968        self.read_only = read_only;
 1969    }
 1970
 1971    pub fn set_use_autoclose(&mut self, autoclose: bool) {
 1972        self.use_autoclose = autoclose;
 1973    }
 1974
 1975    pub fn set_use_auto_surround(&mut self, auto_surround: bool) {
 1976        self.use_auto_surround = auto_surround;
 1977    }
 1978
 1979    pub fn set_auto_replace_emoji_shortcode(&mut self, auto_replace: bool) {
 1980        self.auto_replace_emoji_shortcode = auto_replace;
 1981    }
 1982
 1983    pub fn toggle_inline_completions(
 1984        &mut self,
 1985        _: &ToggleEditPrediction,
 1986        window: &mut Window,
 1987        cx: &mut Context<Self>,
 1988    ) {
 1989        if self.show_inline_completions_override.is_some() {
 1990            self.set_show_edit_predictions(None, window, cx);
 1991        } else {
 1992            let show_edit_predictions = !self.edit_predictions_enabled();
 1993            self.set_show_edit_predictions(Some(show_edit_predictions), window, cx);
 1994        }
 1995    }
 1996
 1997    pub fn set_show_edit_predictions(
 1998        &mut self,
 1999        show_edit_predictions: Option<bool>,
 2000        window: &mut Window,
 2001        cx: &mut Context<Self>,
 2002    ) {
 2003        self.show_inline_completions_override = show_edit_predictions;
 2004        self.refresh_inline_completion(false, true, window, cx);
 2005    }
 2006
 2007    fn inline_completions_disabled_in_scope(
 2008        &self,
 2009        buffer: &Entity<Buffer>,
 2010        buffer_position: language::Anchor,
 2011        cx: &App,
 2012    ) -> bool {
 2013        let snapshot = buffer.read(cx).snapshot();
 2014        let settings = snapshot.settings_at(buffer_position, cx);
 2015
 2016        let Some(scope) = snapshot.language_scope_at(buffer_position) else {
 2017            return false;
 2018        };
 2019
 2020        scope.override_name().map_or(false, |scope_name| {
 2021            settings
 2022                .edit_predictions_disabled_in
 2023                .iter()
 2024                .any(|s| s == scope_name)
 2025        })
 2026    }
 2027
 2028    pub fn set_use_modal_editing(&mut self, to: bool) {
 2029        self.use_modal_editing = to;
 2030    }
 2031
 2032    pub fn use_modal_editing(&self) -> bool {
 2033        self.use_modal_editing
 2034    }
 2035
 2036    fn selections_did_change(
 2037        &mut self,
 2038        local: bool,
 2039        old_cursor_position: &Anchor,
 2040        show_completions: bool,
 2041        window: &mut Window,
 2042        cx: &mut Context<Self>,
 2043    ) {
 2044        window.invalidate_character_coordinates();
 2045
 2046        // Copy selections to primary selection buffer
 2047        #[cfg(any(target_os = "linux", target_os = "freebsd"))]
 2048        if local {
 2049            let selections = self.selections.all::<usize>(cx);
 2050            let buffer_handle = self.buffer.read(cx).read(cx);
 2051
 2052            let mut text = String::new();
 2053            for (index, selection) in selections.iter().enumerate() {
 2054                let text_for_selection = buffer_handle
 2055                    .text_for_range(selection.start..selection.end)
 2056                    .collect::<String>();
 2057
 2058                text.push_str(&text_for_selection);
 2059                if index != selections.len() - 1 {
 2060                    text.push('\n');
 2061                }
 2062            }
 2063
 2064            if !text.is_empty() {
 2065                cx.write_to_primary(ClipboardItem::new_string(text));
 2066            }
 2067        }
 2068
 2069        if self.focus_handle.is_focused(window) && self.leader_peer_id.is_none() {
 2070            self.buffer.update(cx, |buffer, cx| {
 2071                buffer.set_active_selections(
 2072                    &self.selections.disjoint_anchors(),
 2073                    self.selections.line_mode,
 2074                    self.cursor_shape,
 2075                    cx,
 2076                )
 2077            });
 2078        }
 2079        let display_map = self
 2080            .display_map
 2081            .update(cx, |display_map, cx| display_map.snapshot(cx));
 2082        let buffer = &display_map.buffer_snapshot;
 2083        self.add_selections_state = None;
 2084        self.select_next_state = None;
 2085        self.select_prev_state = None;
 2086        self.select_larger_syntax_node_stack.clear();
 2087        self.invalidate_autoclose_regions(&self.selections.disjoint_anchors(), buffer);
 2088        self.snippet_stack
 2089            .invalidate(&self.selections.disjoint_anchors(), buffer);
 2090        self.take_rename(false, window, cx);
 2091
 2092        let new_cursor_position = self.selections.newest_anchor().head();
 2093
 2094        self.push_to_nav_history(
 2095            *old_cursor_position,
 2096            Some(new_cursor_position.to_point(buffer)),
 2097            cx,
 2098        );
 2099
 2100        if local {
 2101            let new_cursor_position = self.selections.newest_anchor().head();
 2102            let mut context_menu = self.context_menu.borrow_mut();
 2103            let completion_menu = match context_menu.as_ref() {
 2104                Some(CodeContextMenu::Completions(menu)) => Some(menu),
 2105                _ => {
 2106                    *context_menu = None;
 2107                    None
 2108                }
 2109            };
 2110            if let Some(buffer_id) = new_cursor_position.buffer_id {
 2111                if !self.registered_buffers.contains_key(&buffer_id) {
 2112                    if let Some(lsp_store) = self.lsp_store(cx) {
 2113                        lsp_store.update(cx, |lsp_store, cx| {
 2114                            let Some(buffer) = self.buffer.read(cx).buffer(buffer_id) else {
 2115                                return;
 2116                            };
 2117                            self.registered_buffers.insert(
 2118                                buffer_id,
 2119                                lsp_store.register_buffer_with_language_servers(&buffer, cx),
 2120                            );
 2121                        })
 2122                    }
 2123                }
 2124            }
 2125
 2126            if let Some(completion_menu) = completion_menu {
 2127                let cursor_position = new_cursor_position.to_offset(buffer);
 2128                let (word_range, kind) =
 2129                    buffer.surrounding_word(completion_menu.initial_position, true);
 2130                if kind == Some(CharKind::Word)
 2131                    && word_range.to_inclusive().contains(&cursor_position)
 2132                {
 2133                    let mut completion_menu = completion_menu.clone();
 2134                    drop(context_menu);
 2135
 2136                    let query = Self::completion_query(buffer, cursor_position);
 2137                    cx.spawn(move |this, mut cx| async move {
 2138                        completion_menu
 2139                            .filter(query.as_deref(), cx.background_executor().clone())
 2140                            .await;
 2141
 2142                        this.update(&mut cx, |this, cx| {
 2143                            let mut context_menu = this.context_menu.borrow_mut();
 2144                            let Some(CodeContextMenu::Completions(menu)) = context_menu.as_ref()
 2145                            else {
 2146                                return;
 2147                            };
 2148
 2149                            if menu.id > completion_menu.id {
 2150                                return;
 2151                            }
 2152
 2153                            *context_menu = Some(CodeContextMenu::Completions(completion_menu));
 2154                            drop(context_menu);
 2155                            cx.notify();
 2156                        })
 2157                    })
 2158                    .detach();
 2159
 2160                    if show_completions {
 2161                        self.show_completions(&ShowCompletions { trigger: None }, window, cx);
 2162                    }
 2163                } else {
 2164                    drop(context_menu);
 2165                    self.hide_context_menu(window, cx);
 2166                }
 2167            } else {
 2168                drop(context_menu);
 2169            }
 2170
 2171            hide_hover(self, cx);
 2172
 2173            if old_cursor_position.to_display_point(&display_map).row()
 2174                != new_cursor_position.to_display_point(&display_map).row()
 2175            {
 2176                self.available_code_actions.take();
 2177            }
 2178            self.refresh_code_actions(window, cx);
 2179            self.refresh_document_highlights(cx);
 2180            refresh_matching_bracket_highlights(self, window, cx);
 2181            self.update_visible_inline_completion(window, cx);
 2182            self.edit_prediction_requires_modifier_in_leading_space = true;
 2183            linked_editing_ranges::refresh_linked_ranges(self, window, cx);
 2184            if self.git_blame_inline_enabled {
 2185                self.start_inline_blame_timer(window, cx);
 2186            }
 2187        }
 2188
 2189        self.blink_manager.update(cx, BlinkManager::pause_blinking);
 2190        cx.emit(EditorEvent::SelectionsChanged { local });
 2191
 2192        if self.selections.disjoint_anchors().len() == 1 {
 2193            cx.emit(SearchEvent::ActiveMatchChanged)
 2194        }
 2195        cx.notify();
 2196    }
 2197
 2198    pub fn change_selections<R>(
 2199        &mut self,
 2200        autoscroll: Option<Autoscroll>,
 2201        window: &mut Window,
 2202        cx: &mut Context<Self>,
 2203        change: impl FnOnce(&mut MutableSelectionsCollection<'_>) -> R,
 2204    ) -> R {
 2205        self.change_selections_inner(autoscroll, true, window, cx, change)
 2206    }
 2207
 2208    pub fn change_selections_inner<R>(
 2209        &mut self,
 2210        autoscroll: Option<Autoscroll>,
 2211        request_completions: bool,
 2212        window: &mut Window,
 2213        cx: &mut Context<Self>,
 2214        change: impl FnOnce(&mut MutableSelectionsCollection<'_>) -> R,
 2215    ) -> R {
 2216        let old_cursor_position = self.selections.newest_anchor().head();
 2217        self.push_to_selection_history();
 2218
 2219        let (changed, result) = self.selections.change_with(cx, change);
 2220
 2221        if changed {
 2222            if let Some(autoscroll) = autoscroll {
 2223                self.request_autoscroll(autoscroll, cx);
 2224            }
 2225            self.selections_did_change(true, &old_cursor_position, request_completions, window, cx);
 2226
 2227            if self.should_open_signature_help_automatically(
 2228                &old_cursor_position,
 2229                self.signature_help_state.backspace_pressed(),
 2230                cx,
 2231            ) {
 2232                self.show_signature_help(&ShowSignatureHelp, window, cx);
 2233            }
 2234            self.signature_help_state.set_backspace_pressed(false);
 2235        }
 2236
 2237        result
 2238    }
 2239
 2240    pub fn edit<I, S, T>(&mut self, edits: I, cx: &mut Context<Self>)
 2241    where
 2242        I: IntoIterator<Item = (Range<S>, T)>,
 2243        S: ToOffset,
 2244        T: Into<Arc<str>>,
 2245    {
 2246        if self.read_only(cx) {
 2247            return;
 2248        }
 2249
 2250        self.buffer
 2251            .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
 2252    }
 2253
 2254    pub fn edit_with_autoindent<I, S, T>(&mut self, edits: I, cx: &mut Context<Self>)
 2255    where
 2256        I: IntoIterator<Item = (Range<S>, T)>,
 2257        S: ToOffset,
 2258        T: Into<Arc<str>>,
 2259    {
 2260        if self.read_only(cx) {
 2261            return;
 2262        }
 2263
 2264        self.buffer.update(cx, |buffer, cx| {
 2265            buffer.edit(edits, self.autoindent_mode.clone(), cx)
 2266        });
 2267    }
 2268
 2269    pub fn edit_with_block_indent<I, S, T>(
 2270        &mut self,
 2271        edits: I,
 2272        original_indent_columns: Vec<u32>,
 2273        cx: &mut Context<Self>,
 2274    ) where
 2275        I: IntoIterator<Item = (Range<S>, T)>,
 2276        S: ToOffset,
 2277        T: Into<Arc<str>>,
 2278    {
 2279        if self.read_only(cx) {
 2280            return;
 2281        }
 2282
 2283        self.buffer.update(cx, |buffer, cx| {
 2284            buffer.edit(
 2285                edits,
 2286                Some(AutoindentMode::Block {
 2287                    original_indent_columns,
 2288                }),
 2289                cx,
 2290            )
 2291        });
 2292    }
 2293
 2294    fn select(&mut self, phase: SelectPhase, window: &mut Window, cx: &mut Context<Self>) {
 2295        self.hide_context_menu(window, cx);
 2296
 2297        match phase {
 2298            SelectPhase::Begin {
 2299                position,
 2300                add,
 2301                click_count,
 2302            } => self.begin_selection(position, add, click_count, window, cx),
 2303            SelectPhase::BeginColumnar {
 2304                position,
 2305                goal_column,
 2306                reset,
 2307            } => self.begin_columnar_selection(position, goal_column, reset, window, cx),
 2308            SelectPhase::Extend {
 2309                position,
 2310                click_count,
 2311            } => self.extend_selection(position, click_count, window, cx),
 2312            SelectPhase::Update {
 2313                position,
 2314                goal_column,
 2315                scroll_delta,
 2316            } => self.update_selection(position, goal_column, scroll_delta, window, cx),
 2317            SelectPhase::End => self.end_selection(window, cx),
 2318        }
 2319    }
 2320
 2321    fn extend_selection(
 2322        &mut self,
 2323        position: DisplayPoint,
 2324        click_count: usize,
 2325        window: &mut Window,
 2326        cx: &mut Context<Self>,
 2327    ) {
 2328        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 2329        let tail = self.selections.newest::<usize>(cx).tail();
 2330        self.begin_selection(position, false, click_count, window, cx);
 2331
 2332        let position = position.to_offset(&display_map, Bias::Left);
 2333        let tail_anchor = display_map.buffer_snapshot.anchor_before(tail);
 2334
 2335        let mut pending_selection = self
 2336            .selections
 2337            .pending_anchor()
 2338            .expect("extend_selection not called with pending selection");
 2339        if position >= tail {
 2340            pending_selection.start = tail_anchor;
 2341        } else {
 2342            pending_selection.end = tail_anchor;
 2343            pending_selection.reversed = true;
 2344        }
 2345
 2346        let mut pending_mode = self.selections.pending_mode().unwrap();
 2347        match &mut pending_mode {
 2348            SelectMode::Word(range) | SelectMode::Line(range) => *range = tail_anchor..tail_anchor,
 2349            _ => {}
 2350        }
 2351
 2352        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 2353            s.set_pending(pending_selection, pending_mode)
 2354        });
 2355    }
 2356
 2357    fn begin_selection(
 2358        &mut self,
 2359        position: DisplayPoint,
 2360        add: bool,
 2361        click_count: usize,
 2362        window: &mut Window,
 2363        cx: &mut Context<Self>,
 2364    ) {
 2365        if !self.focus_handle.is_focused(window) {
 2366            self.last_focused_descendant = None;
 2367            window.focus(&self.focus_handle);
 2368        }
 2369
 2370        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 2371        let buffer = &display_map.buffer_snapshot;
 2372        let newest_selection = self.selections.newest_anchor().clone();
 2373        let position = display_map.clip_point(position, Bias::Left);
 2374
 2375        let start;
 2376        let end;
 2377        let mode;
 2378        let mut auto_scroll;
 2379        match click_count {
 2380            1 => {
 2381                start = buffer.anchor_before(position.to_point(&display_map));
 2382                end = start;
 2383                mode = SelectMode::Character;
 2384                auto_scroll = true;
 2385            }
 2386            2 => {
 2387                let range = movement::surrounding_word(&display_map, position);
 2388                start = buffer.anchor_before(range.start.to_point(&display_map));
 2389                end = buffer.anchor_before(range.end.to_point(&display_map));
 2390                mode = SelectMode::Word(start..end);
 2391                auto_scroll = true;
 2392            }
 2393            3 => {
 2394                let position = display_map
 2395                    .clip_point(position, Bias::Left)
 2396                    .to_point(&display_map);
 2397                let line_start = display_map.prev_line_boundary(position).0;
 2398                let next_line_start = buffer.clip_point(
 2399                    display_map.next_line_boundary(position).0 + Point::new(1, 0),
 2400                    Bias::Left,
 2401                );
 2402                start = buffer.anchor_before(line_start);
 2403                end = buffer.anchor_before(next_line_start);
 2404                mode = SelectMode::Line(start..end);
 2405                auto_scroll = true;
 2406            }
 2407            _ => {
 2408                start = buffer.anchor_before(0);
 2409                end = buffer.anchor_before(buffer.len());
 2410                mode = SelectMode::All;
 2411                auto_scroll = false;
 2412            }
 2413        }
 2414        auto_scroll &= EditorSettings::get_global(cx).autoscroll_on_clicks;
 2415
 2416        let point_to_delete: Option<usize> = {
 2417            let selected_points: Vec<Selection<Point>> =
 2418                self.selections.disjoint_in_range(start..end, cx);
 2419
 2420            if !add || click_count > 1 {
 2421                None
 2422            } else if !selected_points.is_empty() {
 2423                Some(selected_points[0].id)
 2424            } else {
 2425                let clicked_point_already_selected =
 2426                    self.selections.disjoint.iter().find(|selection| {
 2427                        selection.start.to_point(buffer) == start.to_point(buffer)
 2428                            || selection.end.to_point(buffer) == end.to_point(buffer)
 2429                    });
 2430
 2431                clicked_point_already_selected.map(|selection| selection.id)
 2432            }
 2433        };
 2434
 2435        let selections_count = self.selections.count();
 2436
 2437        self.change_selections(auto_scroll.then(Autoscroll::newest), window, cx, |s| {
 2438            if let Some(point_to_delete) = point_to_delete {
 2439                s.delete(point_to_delete);
 2440
 2441                if selections_count == 1 {
 2442                    s.set_pending_anchor_range(start..end, mode);
 2443                }
 2444            } else {
 2445                if !add {
 2446                    s.clear_disjoint();
 2447                } else if click_count > 1 {
 2448                    s.delete(newest_selection.id)
 2449                }
 2450
 2451                s.set_pending_anchor_range(start..end, mode);
 2452            }
 2453        });
 2454    }
 2455
 2456    fn begin_columnar_selection(
 2457        &mut self,
 2458        position: DisplayPoint,
 2459        goal_column: u32,
 2460        reset: bool,
 2461        window: &mut Window,
 2462        cx: &mut Context<Self>,
 2463    ) {
 2464        if !self.focus_handle.is_focused(window) {
 2465            self.last_focused_descendant = None;
 2466            window.focus(&self.focus_handle);
 2467        }
 2468
 2469        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 2470
 2471        if reset {
 2472            let pointer_position = display_map
 2473                .buffer_snapshot
 2474                .anchor_before(position.to_point(&display_map));
 2475
 2476            self.change_selections(Some(Autoscroll::newest()), window, cx, |s| {
 2477                s.clear_disjoint();
 2478                s.set_pending_anchor_range(
 2479                    pointer_position..pointer_position,
 2480                    SelectMode::Character,
 2481                );
 2482            });
 2483        }
 2484
 2485        let tail = self.selections.newest::<Point>(cx).tail();
 2486        self.columnar_selection_tail = Some(display_map.buffer_snapshot.anchor_before(tail));
 2487
 2488        if !reset {
 2489            self.select_columns(
 2490                tail.to_display_point(&display_map),
 2491                position,
 2492                goal_column,
 2493                &display_map,
 2494                window,
 2495                cx,
 2496            );
 2497        }
 2498    }
 2499
 2500    fn update_selection(
 2501        &mut self,
 2502        position: DisplayPoint,
 2503        goal_column: u32,
 2504        scroll_delta: gpui::Point<f32>,
 2505        window: &mut Window,
 2506        cx: &mut Context<Self>,
 2507    ) {
 2508        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 2509
 2510        if let Some(tail) = self.columnar_selection_tail.as_ref() {
 2511            let tail = tail.to_display_point(&display_map);
 2512            self.select_columns(tail, position, goal_column, &display_map, window, cx);
 2513        } else if let Some(mut pending) = self.selections.pending_anchor() {
 2514            let buffer = self.buffer.read(cx).snapshot(cx);
 2515            let head;
 2516            let tail;
 2517            let mode = self.selections.pending_mode().unwrap();
 2518            match &mode {
 2519                SelectMode::Character => {
 2520                    head = position.to_point(&display_map);
 2521                    tail = pending.tail().to_point(&buffer);
 2522                }
 2523                SelectMode::Word(original_range) => {
 2524                    let original_display_range = original_range.start.to_display_point(&display_map)
 2525                        ..original_range.end.to_display_point(&display_map);
 2526                    let original_buffer_range = original_display_range.start.to_point(&display_map)
 2527                        ..original_display_range.end.to_point(&display_map);
 2528                    if movement::is_inside_word(&display_map, position)
 2529                        || original_display_range.contains(&position)
 2530                    {
 2531                        let word_range = movement::surrounding_word(&display_map, position);
 2532                        if word_range.start < original_display_range.start {
 2533                            head = word_range.start.to_point(&display_map);
 2534                        } else {
 2535                            head = word_range.end.to_point(&display_map);
 2536                        }
 2537                    } else {
 2538                        head = position.to_point(&display_map);
 2539                    }
 2540
 2541                    if head <= original_buffer_range.start {
 2542                        tail = original_buffer_range.end;
 2543                    } else {
 2544                        tail = original_buffer_range.start;
 2545                    }
 2546                }
 2547                SelectMode::Line(original_range) => {
 2548                    let original_range = original_range.to_point(&display_map.buffer_snapshot);
 2549
 2550                    let position = display_map
 2551                        .clip_point(position, Bias::Left)
 2552                        .to_point(&display_map);
 2553                    let line_start = display_map.prev_line_boundary(position).0;
 2554                    let next_line_start = buffer.clip_point(
 2555                        display_map.next_line_boundary(position).0 + Point::new(1, 0),
 2556                        Bias::Left,
 2557                    );
 2558
 2559                    if line_start < original_range.start {
 2560                        head = line_start
 2561                    } else {
 2562                        head = next_line_start
 2563                    }
 2564
 2565                    if head <= original_range.start {
 2566                        tail = original_range.end;
 2567                    } else {
 2568                        tail = original_range.start;
 2569                    }
 2570                }
 2571                SelectMode::All => {
 2572                    return;
 2573                }
 2574            };
 2575
 2576            if head < tail {
 2577                pending.start = buffer.anchor_before(head);
 2578                pending.end = buffer.anchor_before(tail);
 2579                pending.reversed = true;
 2580            } else {
 2581                pending.start = buffer.anchor_before(tail);
 2582                pending.end = buffer.anchor_before(head);
 2583                pending.reversed = false;
 2584            }
 2585
 2586            self.change_selections(None, window, cx, |s| {
 2587                s.set_pending(pending, mode);
 2588            });
 2589        } else {
 2590            log::error!("update_selection dispatched with no pending selection");
 2591            return;
 2592        }
 2593
 2594        self.apply_scroll_delta(scroll_delta, window, cx);
 2595        cx.notify();
 2596    }
 2597
 2598    fn end_selection(&mut self, window: &mut Window, cx: &mut Context<Self>) {
 2599        self.columnar_selection_tail.take();
 2600        if self.selections.pending_anchor().is_some() {
 2601            let selections = self.selections.all::<usize>(cx);
 2602            self.change_selections(None, window, cx, |s| {
 2603                s.select(selections);
 2604                s.clear_pending();
 2605            });
 2606        }
 2607    }
 2608
 2609    fn select_columns(
 2610        &mut self,
 2611        tail: DisplayPoint,
 2612        head: DisplayPoint,
 2613        goal_column: u32,
 2614        display_map: &DisplaySnapshot,
 2615        window: &mut Window,
 2616        cx: &mut Context<Self>,
 2617    ) {
 2618        let start_row = cmp::min(tail.row(), head.row());
 2619        let end_row = cmp::max(tail.row(), head.row());
 2620        let start_column = cmp::min(tail.column(), goal_column);
 2621        let end_column = cmp::max(tail.column(), goal_column);
 2622        let reversed = start_column < tail.column();
 2623
 2624        let selection_ranges = (start_row.0..=end_row.0)
 2625            .map(DisplayRow)
 2626            .filter_map(|row| {
 2627                if start_column <= display_map.line_len(row) && !display_map.is_block_line(row) {
 2628                    let start = display_map
 2629                        .clip_point(DisplayPoint::new(row, start_column), Bias::Left)
 2630                        .to_point(display_map);
 2631                    let end = display_map
 2632                        .clip_point(DisplayPoint::new(row, end_column), Bias::Right)
 2633                        .to_point(display_map);
 2634                    if reversed {
 2635                        Some(end..start)
 2636                    } else {
 2637                        Some(start..end)
 2638                    }
 2639                } else {
 2640                    None
 2641                }
 2642            })
 2643            .collect::<Vec<_>>();
 2644
 2645        self.change_selections(None, window, cx, |s| {
 2646            s.select_ranges(selection_ranges);
 2647        });
 2648        cx.notify();
 2649    }
 2650
 2651    pub fn has_pending_nonempty_selection(&self) -> bool {
 2652        let pending_nonempty_selection = match self.selections.pending_anchor() {
 2653            Some(Selection { start, end, .. }) => start != end,
 2654            None => false,
 2655        };
 2656
 2657        pending_nonempty_selection
 2658            || (self.columnar_selection_tail.is_some() && self.selections.disjoint.len() > 1)
 2659    }
 2660
 2661    pub fn has_pending_selection(&self) -> bool {
 2662        self.selections.pending_anchor().is_some() || self.columnar_selection_tail.is_some()
 2663    }
 2664
 2665    pub fn cancel(&mut self, _: &Cancel, window: &mut Window, cx: &mut Context<Self>) {
 2666        self.selection_mark_mode = false;
 2667
 2668        if self.clear_expanded_diff_hunks(cx) {
 2669            cx.notify();
 2670            return;
 2671        }
 2672        if self.dismiss_menus_and_popups(true, window, cx) {
 2673            return;
 2674        }
 2675
 2676        if self.mode == EditorMode::Full
 2677            && self.change_selections(Some(Autoscroll::fit()), window, cx, |s| s.try_cancel())
 2678        {
 2679            return;
 2680        }
 2681
 2682        cx.propagate();
 2683    }
 2684
 2685    pub fn dismiss_menus_and_popups(
 2686        &mut self,
 2687        is_user_requested: bool,
 2688        window: &mut Window,
 2689        cx: &mut Context<Self>,
 2690    ) -> bool {
 2691        if self.take_rename(false, window, cx).is_some() {
 2692            return true;
 2693        }
 2694
 2695        if hide_hover(self, cx) {
 2696            return true;
 2697        }
 2698
 2699        if self.hide_signature_help(cx, SignatureHelpHiddenBy::Escape) {
 2700            return true;
 2701        }
 2702
 2703        if self.hide_context_menu(window, cx).is_some() {
 2704            return true;
 2705        }
 2706
 2707        if self.mouse_context_menu.take().is_some() {
 2708            return true;
 2709        }
 2710
 2711        if is_user_requested && self.discard_inline_completion(true, cx) {
 2712            return true;
 2713        }
 2714
 2715        if self.snippet_stack.pop().is_some() {
 2716            return true;
 2717        }
 2718
 2719        if self.mode == EditorMode::Full && self.active_diagnostics.is_some() {
 2720            self.dismiss_diagnostics(cx);
 2721            return true;
 2722        }
 2723
 2724        false
 2725    }
 2726
 2727    fn linked_editing_ranges_for(
 2728        &self,
 2729        selection: Range<text::Anchor>,
 2730        cx: &App,
 2731    ) -> Option<HashMap<Entity<Buffer>, Vec<Range<text::Anchor>>>> {
 2732        if self.linked_edit_ranges.is_empty() {
 2733            return None;
 2734        }
 2735        let ((base_range, linked_ranges), buffer_snapshot, buffer) =
 2736            selection.end.buffer_id.and_then(|end_buffer_id| {
 2737                if selection.start.buffer_id != Some(end_buffer_id) {
 2738                    return None;
 2739                }
 2740                let buffer = self.buffer.read(cx).buffer(end_buffer_id)?;
 2741                let snapshot = buffer.read(cx).snapshot();
 2742                self.linked_edit_ranges
 2743                    .get(end_buffer_id, selection.start..selection.end, &snapshot)
 2744                    .map(|ranges| (ranges, snapshot, buffer))
 2745            })?;
 2746        use text::ToOffset as TO;
 2747        // find offset from the start of current range to current cursor position
 2748        let start_byte_offset = TO::to_offset(&base_range.start, &buffer_snapshot);
 2749
 2750        let start_offset = TO::to_offset(&selection.start, &buffer_snapshot);
 2751        let start_difference = start_offset - start_byte_offset;
 2752        let end_offset = TO::to_offset(&selection.end, &buffer_snapshot);
 2753        let end_difference = end_offset - start_byte_offset;
 2754        // Current range has associated linked ranges.
 2755        let mut linked_edits = HashMap::<_, Vec<_>>::default();
 2756        for range in linked_ranges.iter() {
 2757            let start_offset = TO::to_offset(&range.start, &buffer_snapshot);
 2758            let end_offset = start_offset + end_difference;
 2759            let start_offset = start_offset + start_difference;
 2760            if start_offset > buffer_snapshot.len() || end_offset > buffer_snapshot.len() {
 2761                continue;
 2762            }
 2763            if self.selections.disjoint_anchor_ranges().any(|s| {
 2764                if s.start.buffer_id != selection.start.buffer_id
 2765                    || s.end.buffer_id != selection.end.buffer_id
 2766                {
 2767                    return false;
 2768                }
 2769                TO::to_offset(&s.start.text_anchor, &buffer_snapshot) <= end_offset
 2770                    && TO::to_offset(&s.end.text_anchor, &buffer_snapshot) >= start_offset
 2771            }) {
 2772                continue;
 2773            }
 2774            let start = buffer_snapshot.anchor_after(start_offset);
 2775            let end = buffer_snapshot.anchor_after(end_offset);
 2776            linked_edits
 2777                .entry(buffer.clone())
 2778                .or_default()
 2779                .push(start..end);
 2780        }
 2781        Some(linked_edits)
 2782    }
 2783
 2784    pub fn handle_input(&mut self, text: &str, window: &mut Window, cx: &mut Context<Self>) {
 2785        let text: Arc<str> = text.into();
 2786
 2787        if self.read_only(cx) {
 2788            return;
 2789        }
 2790
 2791        let selections = self.selections.all_adjusted(cx);
 2792        let mut bracket_inserted = false;
 2793        let mut edits = Vec::new();
 2794        let mut linked_edits = HashMap::<_, Vec<_>>::default();
 2795        let mut new_selections = Vec::with_capacity(selections.len());
 2796        let mut new_autoclose_regions = Vec::new();
 2797        let snapshot = self.buffer.read(cx).read(cx);
 2798
 2799        for (selection, autoclose_region) in
 2800            self.selections_with_autoclose_regions(selections, &snapshot)
 2801        {
 2802            if let Some(scope) = snapshot.language_scope_at(selection.head()) {
 2803                // Determine if the inserted text matches the opening or closing
 2804                // bracket of any of this language's bracket pairs.
 2805                let mut bracket_pair = None;
 2806                let mut is_bracket_pair_start = false;
 2807                let mut is_bracket_pair_end = false;
 2808                if !text.is_empty() {
 2809                    // `text` can be empty when a user is using IME (e.g. Chinese Wubi Simplified)
 2810                    //  and they are removing the character that triggered IME popup.
 2811                    for (pair, enabled) in scope.brackets() {
 2812                        if !pair.close && !pair.surround {
 2813                            continue;
 2814                        }
 2815
 2816                        if enabled && pair.start.ends_with(text.as_ref()) {
 2817                            let prefix_len = pair.start.len() - text.len();
 2818                            let preceding_text_matches_prefix = prefix_len == 0
 2819                                || (selection.start.column >= (prefix_len as u32)
 2820                                    && snapshot.contains_str_at(
 2821                                        Point::new(
 2822                                            selection.start.row,
 2823                                            selection.start.column - (prefix_len as u32),
 2824                                        ),
 2825                                        &pair.start[..prefix_len],
 2826                                    ));
 2827                            if preceding_text_matches_prefix {
 2828                                bracket_pair = Some(pair.clone());
 2829                                is_bracket_pair_start = true;
 2830                                break;
 2831                            }
 2832                        }
 2833                        if pair.end.as_str() == text.as_ref() {
 2834                            bracket_pair = Some(pair.clone());
 2835                            is_bracket_pair_end = true;
 2836                            break;
 2837                        }
 2838                    }
 2839                }
 2840
 2841                if let Some(bracket_pair) = bracket_pair {
 2842                    let snapshot_settings = snapshot.settings_at(selection.start, cx);
 2843                    let autoclose = self.use_autoclose && snapshot_settings.use_autoclose;
 2844                    let auto_surround =
 2845                        self.use_auto_surround && snapshot_settings.use_auto_surround;
 2846                    if selection.is_empty() {
 2847                        if is_bracket_pair_start {
 2848                            // If the inserted text is a suffix of an opening bracket and the
 2849                            // selection is preceded by the rest of the opening bracket, then
 2850                            // insert the closing bracket.
 2851                            let following_text_allows_autoclose = snapshot
 2852                                .chars_at(selection.start)
 2853                                .next()
 2854                                .map_or(true, |c| scope.should_autoclose_before(c));
 2855
 2856                            let is_closing_quote = if bracket_pair.end == bracket_pair.start
 2857                                && bracket_pair.start.len() == 1
 2858                            {
 2859                                let target = bracket_pair.start.chars().next().unwrap();
 2860                                let current_line_count = snapshot
 2861                                    .reversed_chars_at(selection.start)
 2862                                    .take_while(|&c| c != '\n')
 2863                                    .filter(|&c| c == target)
 2864                                    .count();
 2865                                current_line_count % 2 == 1
 2866                            } else {
 2867                                false
 2868                            };
 2869
 2870                            if autoclose
 2871                                && bracket_pair.close
 2872                                && following_text_allows_autoclose
 2873                                && !is_closing_quote
 2874                            {
 2875                                let anchor = snapshot.anchor_before(selection.end);
 2876                                new_selections.push((selection.map(|_| anchor), text.len()));
 2877                                new_autoclose_regions.push((
 2878                                    anchor,
 2879                                    text.len(),
 2880                                    selection.id,
 2881                                    bracket_pair.clone(),
 2882                                ));
 2883                                edits.push((
 2884                                    selection.range(),
 2885                                    format!("{}{}", text, bracket_pair.end).into(),
 2886                                ));
 2887                                bracket_inserted = true;
 2888                                continue;
 2889                            }
 2890                        }
 2891
 2892                        if let Some(region) = autoclose_region {
 2893                            // If the selection is followed by an auto-inserted closing bracket,
 2894                            // then don't insert that closing bracket again; just move the selection
 2895                            // past the closing bracket.
 2896                            let should_skip = selection.end == region.range.end.to_point(&snapshot)
 2897                                && text.as_ref() == region.pair.end.as_str();
 2898                            if should_skip {
 2899                                let anchor = snapshot.anchor_after(selection.end);
 2900                                new_selections
 2901                                    .push((selection.map(|_| anchor), region.pair.end.len()));
 2902                                continue;
 2903                            }
 2904                        }
 2905
 2906                        let always_treat_brackets_as_autoclosed = snapshot
 2907                            .settings_at(selection.start, cx)
 2908                            .always_treat_brackets_as_autoclosed;
 2909                        if always_treat_brackets_as_autoclosed
 2910                            && is_bracket_pair_end
 2911                            && snapshot.contains_str_at(selection.end, text.as_ref())
 2912                        {
 2913                            // Otherwise, when `always_treat_brackets_as_autoclosed` is set to `true
 2914                            // and the inserted text is a closing bracket and the selection is followed
 2915                            // by the closing bracket then move the selection past the closing bracket.
 2916                            let anchor = snapshot.anchor_after(selection.end);
 2917                            new_selections.push((selection.map(|_| anchor), text.len()));
 2918                            continue;
 2919                        }
 2920                    }
 2921                    // If an opening bracket is 1 character long and is typed while
 2922                    // text is selected, then surround that text with the bracket pair.
 2923                    else if auto_surround
 2924                        && bracket_pair.surround
 2925                        && is_bracket_pair_start
 2926                        && bracket_pair.start.chars().count() == 1
 2927                    {
 2928                        edits.push((selection.start..selection.start, text.clone()));
 2929                        edits.push((
 2930                            selection.end..selection.end,
 2931                            bracket_pair.end.as_str().into(),
 2932                        ));
 2933                        bracket_inserted = true;
 2934                        new_selections.push((
 2935                            Selection {
 2936                                id: selection.id,
 2937                                start: snapshot.anchor_after(selection.start),
 2938                                end: snapshot.anchor_before(selection.end),
 2939                                reversed: selection.reversed,
 2940                                goal: selection.goal,
 2941                            },
 2942                            0,
 2943                        ));
 2944                        continue;
 2945                    }
 2946                }
 2947            }
 2948
 2949            if self.auto_replace_emoji_shortcode
 2950                && selection.is_empty()
 2951                && text.as_ref().ends_with(':')
 2952            {
 2953                if let Some(possible_emoji_short_code) =
 2954                    Self::find_possible_emoji_shortcode_at_position(&snapshot, selection.start)
 2955                {
 2956                    if !possible_emoji_short_code.is_empty() {
 2957                        if let Some(emoji) = emojis::get_by_shortcode(&possible_emoji_short_code) {
 2958                            let emoji_shortcode_start = Point::new(
 2959                                selection.start.row,
 2960                                selection.start.column - possible_emoji_short_code.len() as u32 - 1,
 2961                            );
 2962
 2963                            // Remove shortcode from buffer
 2964                            edits.push((
 2965                                emoji_shortcode_start..selection.start,
 2966                                "".to_string().into(),
 2967                            ));
 2968                            new_selections.push((
 2969                                Selection {
 2970                                    id: selection.id,
 2971                                    start: snapshot.anchor_after(emoji_shortcode_start),
 2972                                    end: snapshot.anchor_before(selection.start),
 2973                                    reversed: selection.reversed,
 2974                                    goal: selection.goal,
 2975                                },
 2976                                0,
 2977                            ));
 2978
 2979                            // Insert emoji
 2980                            let selection_start_anchor = snapshot.anchor_after(selection.start);
 2981                            new_selections.push((selection.map(|_| selection_start_anchor), 0));
 2982                            edits.push((selection.start..selection.end, emoji.to_string().into()));
 2983
 2984                            continue;
 2985                        }
 2986                    }
 2987                }
 2988            }
 2989
 2990            // If not handling any auto-close operation, then just replace the selected
 2991            // text with the given input and move the selection to the end of the
 2992            // newly inserted text.
 2993            let anchor = snapshot.anchor_after(selection.end);
 2994            if !self.linked_edit_ranges.is_empty() {
 2995                let start_anchor = snapshot.anchor_before(selection.start);
 2996
 2997                let is_word_char = text.chars().next().map_or(true, |char| {
 2998                    let classifier = snapshot.char_classifier_at(start_anchor.to_offset(&snapshot));
 2999                    classifier.is_word(char)
 3000                });
 3001
 3002                if is_word_char {
 3003                    if let Some(ranges) = self
 3004                        .linked_editing_ranges_for(start_anchor.text_anchor..anchor.text_anchor, cx)
 3005                    {
 3006                        for (buffer, edits) in ranges {
 3007                            linked_edits
 3008                                .entry(buffer.clone())
 3009                                .or_default()
 3010                                .extend(edits.into_iter().map(|range| (range, text.clone())));
 3011                        }
 3012                    }
 3013                }
 3014            }
 3015
 3016            new_selections.push((selection.map(|_| anchor), 0));
 3017            edits.push((selection.start..selection.end, text.clone()));
 3018        }
 3019
 3020        drop(snapshot);
 3021
 3022        self.transact(window, cx, |this, window, cx| {
 3023            this.buffer.update(cx, |buffer, cx| {
 3024                buffer.edit(edits, this.autoindent_mode.clone(), cx);
 3025            });
 3026            for (buffer, edits) in linked_edits {
 3027                buffer.update(cx, |buffer, cx| {
 3028                    let snapshot = buffer.snapshot();
 3029                    let edits = edits
 3030                        .into_iter()
 3031                        .map(|(range, text)| {
 3032                            use text::ToPoint as TP;
 3033                            let end_point = TP::to_point(&range.end, &snapshot);
 3034                            let start_point = TP::to_point(&range.start, &snapshot);
 3035                            (start_point..end_point, text)
 3036                        })
 3037                        .sorted_by_key(|(range, _)| range.start)
 3038                        .collect::<Vec<_>>();
 3039                    buffer.edit(edits, None, cx);
 3040                })
 3041            }
 3042            let new_anchor_selections = new_selections.iter().map(|e| &e.0);
 3043            let new_selection_deltas = new_selections.iter().map(|e| e.1);
 3044            let map = this.display_map.update(cx, |map, cx| map.snapshot(cx));
 3045            let new_selections = resolve_selections::<usize, _>(new_anchor_selections, &map)
 3046                .zip(new_selection_deltas)
 3047                .map(|(selection, delta)| Selection {
 3048                    id: selection.id,
 3049                    start: selection.start + delta,
 3050                    end: selection.end + delta,
 3051                    reversed: selection.reversed,
 3052                    goal: SelectionGoal::None,
 3053                })
 3054                .collect::<Vec<_>>();
 3055
 3056            let mut i = 0;
 3057            for (position, delta, selection_id, pair) in new_autoclose_regions {
 3058                let position = position.to_offset(&map.buffer_snapshot) + delta;
 3059                let start = map.buffer_snapshot.anchor_before(position);
 3060                let end = map.buffer_snapshot.anchor_after(position);
 3061                while let Some(existing_state) = this.autoclose_regions.get(i) {
 3062                    match existing_state.range.start.cmp(&start, &map.buffer_snapshot) {
 3063                        Ordering::Less => i += 1,
 3064                        Ordering::Greater => break,
 3065                        Ordering::Equal => {
 3066                            match end.cmp(&existing_state.range.end, &map.buffer_snapshot) {
 3067                                Ordering::Less => i += 1,
 3068                                Ordering::Equal => break,
 3069                                Ordering::Greater => break,
 3070                            }
 3071                        }
 3072                    }
 3073                }
 3074                this.autoclose_regions.insert(
 3075                    i,
 3076                    AutocloseRegion {
 3077                        selection_id,
 3078                        range: start..end,
 3079                        pair,
 3080                    },
 3081                );
 3082            }
 3083
 3084            let had_active_inline_completion = this.has_active_inline_completion();
 3085            this.change_selections_inner(Some(Autoscroll::fit()), false, window, cx, |s| {
 3086                s.select(new_selections)
 3087            });
 3088
 3089            if !bracket_inserted {
 3090                if let Some(on_type_format_task) =
 3091                    this.trigger_on_type_formatting(text.to_string(), window, cx)
 3092                {
 3093                    on_type_format_task.detach_and_log_err(cx);
 3094                }
 3095            }
 3096
 3097            let editor_settings = EditorSettings::get_global(cx);
 3098            if bracket_inserted
 3099                && (editor_settings.auto_signature_help
 3100                    || editor_settings.show_signature_help_after_edits)
 3101            {
 3102                this.show_signature_help(&ShowSignatureHelp, window, cx);
 3103            }
 3104
 3105            let trigger_in_words =
 3106                this.show_edit_predictions_in_menu() || !had_active_inline_completion;
 3107            this.trigger_completion_on_input(&text, trigger_in_words, window, cx);
 3108            linked_editing_ranges::refresh_linked_ranges(this, window, cx);
 3109            this.refresh_inline_completion(true, false, window, cx);
 3110        });
 3111    }
 3112
 3113    fn find_possible_emoji_shortcode_at_position(
 3114        snapshot: &MultiBufferSnapshot,
 3115        position: Point,
 3116    ) -> Option<String> {
 3117        let mut chars = Vec::new();
 3118        let mut found_colon = false;
 3119        for char in snapshot.reversed_chars_at(position).take(100) {
 3120            // Found a possible emoji shortcode in the middle of the buffer
 3121            if found_colon {
 3122                if char.is_whitespace() {
 3123                    chars.reverse();
 3124                    return Some(chars.iter().collect());
 3125                }
 3126                // If the previous character is not a whitespace, we are in the middle of a word
 3127                // and we only want to complete the shortcode if the word is made up of other emojis
 3128                let mut containing_word = String::new();
 3129                for ch in snapshot
 3130                    .reversed_chars_at(position)
 3131                    .skip(chars.len() + 1)
 3132                    .take(100)
 3133                {
 3134                    if ch.is_whitespace() {
 3135                        break;
 3136                    }
 3137                    containing_word.push(ch);
 3138                }
 3139                let containing_word = containing_word.chars().rev().collect::<String>();
 3140                if util::word_consists_of_emojis(containing_word.as_str()) {
 3141                    chars.reverse();
 3142                    return Some(chars.iter().collect());
 3143                }
 3144            }
 3145
 3146            if char.is_whitespace() || !char.is_ascii() {
 3147                return None;
 3148            }
 3149            if char == ':' {
 3150                found_colon = true;
 3151            } else {
 3152                chars.push(char);
 3153            }
 3154        }
 3155        // Found a possible emoji shortcode at the beginning of the buffer
 3156        chars.reverse();
 3157        Some(chars.iter().collect())
 3158    }
 3159
 3160    pub fn newline(&mut self, _: &Newline, window: &mut Window, cx: &mut Context<Self>) {
 3161        self.transact(window, cx, |this, window, cx| {
 3162            let (edits, selection_fixup_info): (Vec<_>, Vec<_>) = {
 3163                let selections = this.selections.all::<usize>(cx);
 3164                let multi_buffer = this.buffer.read(cx);
 3165                let buffer = multi_buffer.snapshot(cx);
 3166                selections
 3167                    .iter()
 3168                    .map(|selection| {
 3169                        let start_point = selection.start.to_point(&buffer);
 3170                        let mut indent =
 3171                            buffer.indent_size_for_line(MultiBufferRow(start_point.row));
 3172                        indent.len = cmp::min(indent.len, start_point.column);
 3173                        let start = selection.start;
 3174                        let end = selection.end;
 3175                        let selection_is_empty = start == end;
 3176                        let language_scope = buffer.language_scope_at(start);
 3177                        let (comment_delimiter, insert_extra_newline) = if let Some(language) =
 3178                            &language_scope
 3179                        {
 3180                            let leading_whitespace_len = buffer
 3181                                .reversed_chars_at(start)
 3182                                .take_while(|c| c.is_whitespace() && *c != '\n')
 3183                                .map(|c| c.len_utf8())
 3184                                .sum::<usize>();
 3185
 3186                            let trailing_whitespace_len = buffer
 3187                                .chars_at(end)
 3188                                .take_while(|c| c.is_whitespace() && *c != '\n')
 3189                                .map(|c| c.len_utf8())
 3190                                .sum::<usize>();
 3191
 3192                            let insert_extra_newline =
 3193                                language.brackets().any(|(pair, enabled)| {
 3194                                    let pair_start = pair.start.trim_end();
 3195                                    let pair_end = pair.end.trim_start();
 3196
 3197                                    enabled
 3198                                        && pair.newline
 3199                                        && buffer.contains_str_at(
 3200                                            end + trailing_whitespace_len,
 3201                                            pair_end,
 3202                                        )
 3203                                        && buffer.contains_str_at(
 3204                                            (start - leading_whitespace_len)
 3205                                                .saturating_sub(pair_start.len()),
 3206                                            pair_start,
 3207                                        )
 3208                                });
 3209
 3210                            // Comment extension on newline is allowed only for cursor selections
 3211                            let comment_delimiter = maybe!({
 3212                                if !selection_is_empty {
 3213                                    return None;
 3214                                }
 3215
 3216                                if !multi_buffer.settings_at(0, cx).extend_comment_on_newline {
 3217                                    return None;
 3218                                }
 3219
 3220                                let delimiters = language.line_comment_prefixes();
 3221                                let max_len_of_delimiter =
 3222                                    delimiters.iter().map(|delimiter| delimiter.len()).max()?;
 3223                                let (snapshot, range) =
 3224                                    buffer.buffer_line_for_row(MultiBufferRow(start_point.row))?;
 3225
 3226                                let mut index_of_first_non_whitespace = 0;
 3227                                let comment_candidate = snapshot
 3228                                    .chars_for_range(range)
 3229                                    .skip_while(|c| {
 3230                                        let should_skip = c.is_whitespace();
 3231                                        if should_skip {
 3232                                            index_of_first_non_whitespace += 1;
 3233                                        }
 3234                                        should_skip
 3235                                    })
 3236                                    .take(max_len_of_delimiter)
 3237                                    .collect::<String>();
 3238                                let comment_prefix = delimiters.iter().find(|comment_prefix| {
 3239                                    comment_candidate.starts_with(comment_prefix.as_ref())
 3240                                })?;
 3241                                let cursor_is_placed_after_comment_marker =
 3242                                    index_of_first_non_whitespace + comment_prefix.len()
 3243                                        <= start_point.column as usize;
 3244                                if cursor_is_placed_after_comment_marker {
 3245                                    Some(comment_prefix.clone())
 3246                                } else {
 3247                                    None
 3248                                }
 3249                            });
 3250                            (comment_delimiter, insert_extra_newline)
 3251                        } else {
 3252                            (None, false)
 3253                        };
 3254
 3255                        let capacity_for_delimiter = comment_delimiter
 3256                            .as_deref()
 3257                            .map(str::len)
 3258                            .unwrap_or_default();
 3259                        let mut new_text =
 3260                            String::with_capacity(1 + capacity_for_delimiter + indent.len as usize);
 3261                        new_text.push('\n');
 3262                        new_text.extend(indent.chars());
 3263                        if let Some(delimiter) = &comment_delimiter {
 3264                            new_text.push_str(delimiter);
 3265                        }
 3266                        if insert_extra_newline {
 3267                            new_text = new_text.repeat(2);
 3268                        }
 3269
 3270                        let anchor = buffer.anchor_after(end);
 3271                        let new_selection = selection.map(|_| anchor);
 3272                        (
 3273                            (start..end, new_text),
 3274                            (insert_extra_newline, new_selection),
 3275                        )
 3276                    })
 3277                    .unzip()
 3278            };
 3279
 3280            this.edit_with_autoindent(edits, cx);
 3281            let buffer = this.buffer.read(cx).snapshot(cx);
 3282            let new_selections = selection_fixup_info
 3283                .into_iter()
 3284                .map(|(extra_newline_inserted, new_selection)| {
 3285                    let mut cursor = new_selection.end.to_point(&buffer);
 3286                    if extra_newline_inserted {
 3287                        cursor.row -= 1;
 3288                        cursor.column = buffer.line_len(MultiBufferRow(cursor.row));
 3289                    }
 3290                    new_selection.map(|_| cursor)
 3291                })
 3292                .collect();
 3293
 3294            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 3295                s.select(new_selections)
 3296            });
 3297            this.refresh_inline_completion(true, false, window, cx);
 3298        });
 3299    }
 3300
 3301    pub fn newline_above(&mut self, _: &NewlineAbove, window: &mut Window, cx: &mut Context<Self>) {
 3302        let buffer = self.buffer.read(cx);
 3303        let snapshot = buffer.snapshot(cx);
 3304
 3305        let mut edits = Vec::new();
 3306        let mut rows = Vec::new();
 3307
 3308        for (rows_inserted, selection) in self.selections.all_adjusted(cx).into_iter().enumerate() {
 3309            let cursor = selection.head();
 3310            let row = cursor.row;
 3311
 3312            let start_of_line = snapshot.clip_point(Point::new(row, 0), Bias::Left);
 3313
 3314            let newline = "\n".to_string();
 3315            edits.push((start_of_line..start_of_line, newline));
 3316
 3317            rows.push(row + rows_inserted as u32);
 3318        }
 3319
 3320        self.transact(window, cx, |editor, window, cx| {
 3321            editor.edit(edits, cx);
 3322
 3323            editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 3324                let mut index = 0;
 3325                s.move_cursors_with(|map, _, _| {
 3326                    let row = rows[index];
 3327                    index += 1;
 3328
 3329                    let point = Point::new(row, 0);
 3330                    let boundary = map.next_line_boundary(point).1;
 3331                    let clipped = map.clip_point(boundary, Bias::Left);
 3332
 3333                    (clipped, SelectionGoal::None)
 3334                });
 3335            });
 3336
 3337            let mut indent_edits = Vec::new();
 3338            let multibuffer_snapshot = editor.buffer.read(cx).snapshot(cx);
 3339            for row in rows {
 3340                let indents = multibuffer_snapshot.suggested_indents(row..row + 1, cx);
 3341                for (row, indent) in indents {
 3342                    if indent.len == 0 {
 3343                        continue;
 3344                    }
 3345
 3346                    let text = match indent.kind {
 3347                        IndentKind::Space => " ".repeat(indent.len as usize),
 3348                        IndentKind::Tab => "\t".repeat(indent.len as usize),
 3349                    };
 3350                    let point = Point::new(row.0, 0);
 3351                    indent_edits.push((point..point, text));
 3352                }
 3353            }
 3354            editor.edit(indent_edits, cx);
 3355        });
 3356    }
 3357
 3358    pub fn newline_below(&mut self, _: &NewlineBelow, window: &mut Window, cx: &mut Context<Self>) {
 3359        let buffer = self.buffer.read(cx);
 3360        let snapshot = buffer.snapshot(cx);
 3361
 3362        let mut edits = Vec::new();
 3363        let mut rows = Vec::new();
 3364        let mut rows_inserted = 0;
 3365
 3366        for selection in self.selections.all_adjusted(cx) {
 3367            let cursor = selection.head();
 3368            let row = cursor.row;
 3369
 3370            let point = Point::new(row + 1, 0);
 3371            let start_of_line = snapshot.clip_point(point, Bias::Left);
 3372
 3373            let newline = "\n".to_string();
 3374            edits.push((start_of_line..start_of_line, newline));
 3375
 3376            rows_inserted += 1;
 3377            rows.push(row + rows_inserted);
 3378        }
 3379
 3380        self.transact(window, cx, |editor, window, cx| {
 3381            editor.edit(edits, cx);
 3382
 3383            editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 3384                let mut index = 0;
 3385                s.move_cursors_with(|map, _, _| {
 3386                    let row = rows[index];
 3387                    index += 1;
 3388
 3389                    let point = Point::new(row, 0);
 3390                    let boundary = map.next_line_boundary(point).1;
 3391                    let clipped = map.clip_point(boundary, Bias::Left);
 3392
 3393                    (clipped, SelectionGoal::None)
 3394                });
 3395            });
 3396
 3397            let mut indent_edits = Vec::new();
 3398            let multibuffer_snapshot = editor.buffer.read(cx).snapshot(cx);
 3399            for row in rows {
 3400                let indents = multibuffer_snapshot.suggested_indents(row..row + 1, cx);
 3401                for (row, indent) in indents {
 3402                    if indent.len == 0 {
 3403                        continue;
 3404                    }
 3405
 3406                    let text = match indent.kind {
 3407                        IndentKind::Space => " ".repeat(indent.len as usize),
 3408                        IndentKind::Tab => "\t".repeat(indent.len as usize),
 3409                    };
 3410                    let point = Point::new(row.0, 0);
 3411                    indent_edits.push((point..point, text));
 3412                }
 3413            }
 3414            editor.edit(indent_edits, cx);
 3415        });
 3416    }
 3417
 3418    pub fn insert(&mut self, text: &str, window: &mut Window, cx: &mut Context<Self>) {
 3419        let autoindent = text.is_empty().not().then(|| AutoindentMode::Block {
 3420            original_indent_columns: Vec::new(),
 3421        });
 3422        self.insert_with_autoindent_mode(text, autoindent, window, cx);
 3423    }
 3424
 3425    fn insert_with_autoindent_mode(
 3426        &mut self,
 3427        text: &str,
 3428        autoindent_mode: Option<AutoindentMode>,
 3429        window: &mut Window,
 3430        cx: &mut Context<Self>,
 3431    ) {
 3432        if self.read_only(cx) {
 3433            return;
 3434        }
 3435
 3436        let text: Arc<str> = text.into();
 3437        self.transact(window, cx, |this, window, cx| {
 3438            let old_selections = this.selections.all_adjusted(cx);
 3439            let selection_anchors = this.buffer.update(cx, |buffer, cx| {
 3440                let anchors = {
 3441                    let snapshot = buffer.read(cx);
 3442                    old_selections
 3443                        .iter()
 3444                        .map(|s| {
 3445                            let anchor = snapshot.anchor_after(s.head());
 3446                            s.map(|_| anchor)
 3447                        })
 3448                        .collect::<Vec<_>>()
 3449                };
 3450                buffer.edit(
 3451                    old_selections
 3452                        .iter()
 3453                        .map(|s| (s.start..s.end, text.clone())),
 3454                    autoindent_mode,
 3455                    cx,
 3456                );
 3457                anchors
 3458            });
 3459
 3460            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 3461                s.select_anchors(selection_anchors);
 3462            });
 3463
 3464            cx.notify();
 3465        });
 3466    }
 3467
 3468    fn trigger_completion_on_input(
 3469        &mut self,
 3470        text: &str,
 3471        trigger_in_words: bool,
 3472        window: &mut Window,
 3473        cx: &mut Context<Self>,
 3474    ) {
 3475        if self.is_completion_trigger(text, trigger_in_words, cx) {
 3476            self.show_completions(
 3477                &ShowCompletions {
 3478                    trigger: Some(text.to_owned()).filter(|x| !x.is_empty()),
 3479                },
 3480                window,
 3481                cx,
 3482            );
 3483        } else {
 3484            self.hide_context_menu(window, cx);
 3485        }
 3486    }
 3487
 3488    fn is_completion_trigger(
 3489        &self,
 3490        text: &str,
 3491        trigger_in_words: bool,
 3492        cx: &mut Context<Self>,
 3493    ) -> bool {
 3494        let position = self.selections.newest_anchor().head();
 3495        let multibuffer = self.buffer.read(cx);
 3496        let Some(buffer) = position
 3497            .buffer_id
 3498            .and_then(|buffer_id| multibuffer.buffer(buffer_id).clone())
 3499        else {
 3500            return false;
 3501        };
 3502
 3503        if let Some(completion_provider) = &self.completion_provider {
 3504            completion_provider.is_completion_trigger(
 3505                &buffer,
 3506                position.text_anchor,
 3507                text,
 3508                trigger_in_words,
 3509                cx,
 3510            )
 3511        } else {
 3512            false
 3513        }
 3514    }
 3515
 3516    /// If any empty selections is touching the start of its innermost containing autoclose
 3517    /// region, expand it to select the brackets.
 3518    fn select_autoclose_pair(&mut self, window: &mut Window, cx: &mut Context<Self>) {
 3519        let selections = self.selections.all::<usize>(cx);
 3520        let buffer = self.buffer.read(cx).read(cx);
 3521        let new_selections = self
 3522            .selections_with_autoclose_regions(selections, &buffer)
 3523            .map(|(mut selection, region)| {
 3524                if !selection.is_empty() {
 3525                    return selection;
 3526                }
 3527
 3528                if let Some(region) = region {
 3529                    let mut range = region.range.to_offset(&buffer);
 3530                    if selection.start == range.start && range.start >= region.pair.start.len() {
 3531                        range.start -= region.pair.start.len();
 3532                        if buffer.contains_str_at(range.start, &region.pair.start)
 3533                            && buffer.contains_str_at(range.end, &region.pair.end)
 3534                        {
 3535                            range.end += region.pair.end.len();
 3536                            selection.start = range.start;
 3537                            selection.end = range.end;
 3538
 3539                            return selection;
 3540                        }
 3541                    }
 3542                }
 3543
 3544                let always_treat_brackets_as_autoclosed = buffer
 3545                    .settings_at(selection.start, cx)
 3546                    .always_treat_brackets_as_autoclosed;
 3547
 3548                if !always_treat_brackets_as_autoclosed {
 3549                    return selection;
 3550                }
 3551
 3552                if let Some(scope) = buffer.language_scope_at(selection.start) {
 3553                    for (pair, enabled) in scope.brackets() {
 3554                        if !enabled || !pair.close {
 3555                            continue;
 3556                        }
 3557
 3558                        if buffer.contains_str_at(selection.start, &pair.end) {
 3559                            let pair_start_len = pair.start.len();
 3560                            if buffer.contains_str_at(
 3561                                selection.start.saturating_sub(pair_start_len),
 3562                                &pair.start,
 3563                            ) {
 3564                                selection.start -= pair_start_len;
 3565                                selection.end += pair.end.len();
 3566
 3567                                return selection;
 3568                            }
 3569                        }
 3570                    }
 3571                }
 3572
 3573                selection
 3574            })
 3575            .collect();
 3576
 3577        drop(buffer);
 3578        self.change_selections(None, window, cx, |selections| {
 3579            selections.select(new_selections)
 3580        });
 3581    }
 3582
 3583    /// Iterate the given selections, and for each one, find the smallest surrounding
 3584    /// autoclose region. This uses the ordering of the selections and the autoclose
 3585    /// regions to avoid repeated comparisons.
 3586    fn selections_with_autoclose_regions<'a, D: ToOffset + Clone>(
 3587        &'a self,
 3588        selections: impl IntoIterator<Item = Selection<D>>,
 3589        buffer: &'a MultiBufferSnapshot,
 3590    ) -> impl Iterator<Item = (Selection<D>, Option<&'a AutocloseRegion>)> {
 3591        let mut i = 0;
 3592        let mut regions = self.autoclose_regions.as_slice();
 3593        selections.into_iter().map(move |selection| {
 3594            let range = selection.start.to_offset(buffer)..selection.end.to_offset(buffer);
 3595
 3596            let mut enclosing = None;
 3597            while let Some(pair_state) = regions.get(i) {
 3598                if pair_state.range.end.to_offset(buffer) < range.start {
 3599                    regions = &regions[i + 1..];
 3600                    i = 0;
 3601                } else if pair_state.range.start.to_offset(buffer) > range.end {
 3602                    break;
 3603                } else {
 3604                    if pair_state.selection_id == selection.id {
 3605                        enclosing = Some(pair_state);
 3606                    }
 3607                    i += 1;
 3608                }
 3609            }
 3610
 3611            (selection, enclosing)
 3612        })
 3613    }
 3614
 3615    /// Remove any autoclose regions that no longer contain their selection.
 3616    fn invalidate_autoclose_regions(
 3617        &mut self,
 3618        mut selections: &[Selection<Anchor>],
 3619        buffer: &MultiBufferSnapshot,
 3620    ) {
 3621        self.autoclose_regions.retain(|state| {
 3622            let mut i = 0;
 3623            while let Some(selection) = selections.get(i) {
 3624                if selection.end.cmp(&state.range.start, buffer).is_lt() {
 3625                    selections = &selections[1..];
 3626                    continue;
 3627                }
 3628                if selection.start.cmp(&state.range.end, buffer).is_gt() {
 3629                    break;
 3630                }
 3631                if selection.id == state.selection_id {
 3632                    return true;
 3633                } else {
 3634                    i += 1;
 3635                }
 3636            }
 3637            false
 3638        });
 3639    }
 3640
 3641    fn completion_query(buffer: &MultiBufferSnapshot, position: impl ToOffset) -> Option<String> {
 3642        let offset = position.to_offset(buffer);
 3643        let (word_range, kind) = buffer.surrounding_word(offset, true);
 3644        if offset > word_range.start && kind == Some(CharKind::Word) {
 3645            Some(
 3646                buffer
 3647                    .text_for_range(word_range.start..offset)
 3648                    .collect::<String>(),
 3649            )
 3650        } else {
 3651            None
 3652        }
 3653    }
 3654
 3655    pub fn toggle_inlay_hints(
 3656        &mut self,
 3657        _: &ToggleInlayHints,
 3658        _: &mut Window,
 3659        cx: &mut Context<Self>,
 3660    ) {
 3661        self.refresh_inlay_hints(
 3662            InlayHintRefreshReason::Toggle(!self.inlay_hint_cache.enabled),
 3663            cx,
 3664        );
 3665    }
 3666
 3667    pub fn inlay_hints_enabled(&self) -> bool {
 3668        self.inlay_hint_cache.enabled
 3669    }
 3670
 3671    fn refresh_inlay_hints(&mut self, reason: InlayHintRefreshReason, cx: &mut Context<Self>) {
 3672        if self.semantics_provider.is_none() || self.mode != EditorMode::Full {
 3673            return;
 3674        }
 3675
 3676        let reason_description = reason.description();
 3677        let ignore_debounce = matches!(
 3678            reason,
 3679            InlayHintRefreshReason::SettingsChange(_)
 3680                | InlayHintRefreshReason::Toggle(_)
 3681                | InlayHintRefreshReason::ExcerptsRemoved(_)
 3682        );
 3683        let (invalidate_cache, required_languages) = match reason {
 3684            InlayHintRefreshReason::Toggle(enabled) => {
 3685                self.inlay_hint_cache.enabled = enabled;
 3686                if enabled {
 3687                    (InvalidationStrategy::RefreshRequested, None)
 3688                } else {
 3689                    self.inlay_hint_cache.clear();
 3690                    self.splice_inlays(
 3691                        &self
 3692                            .visible_inlay_hints(cx)
 3693                            .iter()
 3694                            .map(|inlay| inlay.id)
 3695                            .collect::<Vec<InlayId>>(),
 3696                        Vec::new(),
 3697                        cx,
 3698                    );
 3699                    return;
 3700                }
 3701            }
 3702            InlayHintRefreshReason::SettingsChange(new_settings) => {
 3703                match self.inlay_hint_cache.update_settings(
 3704                    &self.buffer,
 3705                    new_settings,
 3706                    self.visible_inlay_hints(cx),
 3707                    cx,
 3708                ) {
 3709                    ControlFlow::Break(Some(InlaySplice {
 3710                        to_remove,
 3711                        to_insert,
 3712                    })) => {
 3713                        self.splice_inlays(&to_remove, to_insert, cx);
 3714                        return;
 3715                    }
 3716                    ControlFlow::Break(None) => return,
 3717                    ControlFlow::Continue(()) => (InvalidationStrategy::RefreshRequested, None),
 3718                }
 3719            }
 3720            InlayHintRefreshReason::ExcerptsRemoved(excerpts_removed) => {
 3721                if let Some(InlaySplice {
 3722                    to_remove,
 3723                    to_insert,
 3724                }) = self.inlay_hint_cache.remove_excerpts(excerpts_removed)
 3725                {
 3726                    self.splice_inlays(&to_remove, to_insert, cx);
 3727                }
 3728                return;
 3729            }
 3730            InlayHintRefreshReason::NewLinesShown => (InvalidationStrategy::None, None),
 3731            InlayHintRefreshReason::BufferEdited(buffer_languages) => {
 3732                (InvalidationStrategy::BufferEdited, Some(buffer_languages))
 3733            }
 3734            InlayHintRefreshReason::RefreshRequested => {
 3735                (InvalidationStrategy::RefreshRequested, None)
 3736            }
 3737        };
 3738
 3739        if let Some(InlaySplice {
 3740            to_remove,
 3741            to_insert,
 3742        }) = self.inlay_hint_cache.spawn_hint_refresh(
 3743            reason_description,
 3744            self.excerpts_for_inlay_hints_query(required_languages.as_ref(), cx),
 3745            invalidate_cache,
 3746            ignore_debounce,
 3747            cx,
 3748        ) {
 3749            self.splice_inlays(&to_remove, to_insert, cx);
 3750        }
 3751    }
 3752
 3753    fn visible_inlay_hints(&self, cx: &Context<Editor>) -> Vec<Inlay> {
 3754        self.display_map
 3755            .read(cx)
 3756            .current_inlays()
 3757            .filter(move |inlay| matches!(inlay.id, InlayId::Hint(_)))
 3758            .cloned()
 3759            .collect()
 3760    }
 3761
 3762    pub fn excerpts_for_inlay_hints_query(
 3763        &self,
 3764        restrict_to_languages: Option<&HashSet<Arc<Language>>>,
 3765        cx: &mut Context<Editor>,
 3766    ) -> HashMap<ExcerptId, (Entity<Buffer>, clock::Global, Range<usize>)> {
 3767        let Some(project) = self.project.as_ref() else {
 3768            return HashMap::default();
 3769        };
 3770        let project = project.read(cx);
 3771        let multi_buffer = self.buffer().read(cx);
 3772        let multi_buffer_snapshot = multi_buffer.snapshot(cx);
 3773        let multi_buffer_visible_start = self
 3774            .scroll_manager
 3775            .anchor()
 3776            .anchor
 3777            .to_point(&multi_buffer_snapshot);
 3778        let multi_buffer_visible_end = multi_buffer_snapshot.clip_point(
 3779            multi_buffer_visible_start
 3780                + Point::new(self.visible_line_count().unwrap_or(0.).ceil() as u32, 0),
 3781            Bias::Left,
 3782        );
 3783        let multi_buffer_visible_range = multi_buffer_visible_start..multi_buffer_visible_end;
 3784        multi_buffer_snapshot
 3785            .range_to_buffer_ranges(multi_buffer_visible_range)
 3786            .into_iter()
 3787            .filter(|(_, excerpt_visible_range, _)| !excerpt_visible_range.is_empty())
 3788            .filter_map(|(buffer, excerpt_visible_range, excerpt_id)| {
 3789                let buffer_file = project::File::from_dyn(buffer.file())?;
 3790                let buffer_worktree = project.worktree_for_id(buffer_file.worktree_id(cx), cx)?;
 3791                let worktree_entry = buffer_worktree
 3792                    .read(cx)
 3793                    .entry_for_id(buffer_file.project_entry_id(cx)?)?;
 3794                if worktree_entry.is_ignored {
 3795                    return None;
 3796                }
 3797
 3798                let language = buffer.language()?;
 3799                if let Some(restrict_to_languages) = restrict_to_languages {
 3800                    if !restrict_to_languages.contains(language) {
 3801                        return None;
 3802                    }
 3803                }
 3804                Some((
 3805                    excerpt_id,
 3806                    (
 3807                        multi_buffer.buffer(buffer.remote_id()).unwrap(),
 3808                        buffer.version().clone(),
 3809                        excerpt_visible_range,
 3810                    ),
 3811                ))
 3812            })
 3813            .collect()
 3814    }
 3815
 3816    pub fn text_layout_details(&self, window: &mut Window) -> TextLayoutDetails {
 3817        TextLayoutDetails {
 3818            text_system: window.text_system().clone(),
 3819            editor_style: self.style.clone().unwrap(),
 3820            rem_size: window.rem_size(),
 3821            scroll_anchor: self.scroll_manager.anchor(),
 3822            visible_rows: self.visible_line_count(),
 3823            vertical_scroll_margin: self.scroll_manager.vertical_scroll_margin,
 3824        }
 3825    }
 3826
 3827    pub fn splice_inlays(
 3828        &self,
 3829        to_remove: &[InlayId],
 3830        to_insert: Vec<Inlay>,
 3831        cx: &mut Context<Self>,
 3832    ) {
 3833        self.display_map.update(cx, |display_map, cx| {
 3834            display_map.splice_inlays(to_remove, to_insert, cx)
 3835        });
 3836        cx.notify();
 3837    }
 3838
 3839    fn trigger_on_type_formatting(
 3840        &self,
 3841        input: String,
 3842        window: &mut Window,
 3843        cx: &mut Context<Self>,
 3844    ) -> Option<Task<Result<()>>> {
 3845        if input.len() != 1 {
 3846            return None;
 3847        }
 3848
 3849        let project = self.project.as_ref()?;
 3850        let position = self.selections.newest_anchor().head();
 3851        let (buffer, buffer_position) = self
 3852            .buffer
 3853            .read(cx)
 3854            .text_anchor_for_position(position, cx)?;
 3855
 3856        let settings = language_settings::language_settings(
 3857            buffer
 3858                .read(cx)
 3859                .language_at(buffer_position)
 3860                .map(|l| l.name()),
 3861            buffer.read(cx).file(),
 3862            cx,
 3863        );
 3864        if !settings.use_on_type_format {
 3865            return None;
 3866        }
 3867
 3868        // OnTypeFormatting returns a list of edits, no need to pass them between Zed instances,
 3869        // hence we do LSP request & edit on host side only — add formats to host's history.
 3870        let push_to_lsp_host_history = true;
 3871        // If this is not the host, append its history with new edits.
 3872        let push_to_client_history = project.read(cx).is_via_collab();
 3873
 3874        let on_type_formatting = project.update(cx, |project, cx| {
 3875            project.on_type_format(
 3876                buffer.clone(),
 3877                buffer_position,
 3878                input,
 3879                push_to_lsp_host_history,
 3880                cx,
 3881            )
 3882        });
 3883        Some(cx.spawn_in(window, |editor, mut cx| async move {
 3884            if let Some(transaction) = on_type_formatting.await? {
 3885                if push_to_client_history {
 3886                    buffer
 3887                        .update(&mut cx, |buffer, _| {
 3888                            buffer.push_transaction(transaction, Instant::now());
 3889                        })
 3890                        .ok();
 3891                }
 3892                editor.update(&mut cx, |editor, cx| {
 3893                    editor.refresh_document_highlights(cx);
 3894                })?;
 3895            }
 3896            Ok(())
 3897        }))
 3898    }
 3899
 3900    pub fn show_completions(
 3901        &mut self,
 3902        options: &ShowCompletions,
 3903        window: &mut Window,
 3904        cx: &mut Context<Self>,
 3905    ) {
 3906        if self.pending_rename.is_some() {
 3907            return;
 3908        }
 3909
 3910        let Some(provider) = self.completion_provider.as_ref() else {
 3911            return;
 3912        };
 3913
 3914        if !self.snippet_stack.is_empty() && self.context_menu.borrow().as_ref().is_some() {
 3915            return;
 3916        }
 3917
 3918        let position = self.selections.newest_anchor().head();
 3919        if position.diff_base_anchor.is_some() {
 3920            return;
 3921        }
 3922        let (buffer, buffer_position) =
 3923            if let Some(output) = self.buffer.read(cx).text_anchor_for_position(position, cx) {
 3924                output
 3925            } else {
 3926                return;
 3927            };
 3928        let show_completion_documentation = buffer
 3929            .read(cx)
 3930            .snapshot()
 3931            .settings_at(buffer_position, cx)
 3932            .show_completion_documentation;
 3933
 3934        let query = Self::completion_query(&self.buffer.read(cx).read(cx), position);
 3935
 3936        let trigger_kind = match &options.trigger {
 3937            Some(trigger) if buffer.read(cx).completion_triggers().contains(trigger) => {
 3938                CompletionTriggerKind::TRIGGER_CHARACTER
 3939            }
 3940            _ => CompletionTriggerKind::INVOKED,
 3941        };
 3942        let completion_context = CompletionContext {
 3943            trigger_character: options.trigger.as_ref().and_then(|trigger| {
 3944                if trigger_kind == CompletionTriggerKind::TRIGGER_CHARACTER {
 3945                    Some(String::from(trigger))
 3946                } else {
 3947                    None
 3948                }
 3949            }),
 3950            trigger_kind,
 3951        };
 3952        let completions =
 3953            provider.completions(&buffer, buffer_position, completion_context, window, cx);
 3954        let sort_completions = provider.sort_completions();
 3955
 3956        let id = post_inc(&mut self.next_completion_id);
 3957        let task = cx.spawn_in(window, |editor, mut cx| {
 3958            async move {
 3959                editor.update(&mut cx, |this, _| {
 3960                    this.completion_tasks.retain(|(task_id, _)| *task_id >= id);
 3961                })?;
 3962                let completions = completions.await.log_err();
 3963                let menu = if let Some(completions) = completions {
 3964                    let mut menu = CompletionsMenu::new(
 3965                        id,
 3966                        sort_completions,
 3967                        show_completion_documentation,
 3968                        position,
 3969                        buffer.clone(),
 3970                        completions.into(),
 3971                    );
 3972
 3973                    menu.filter(query.as_deref(), cx.background_executor().clone())
 3974                        .await;
 3975
 3976                    menu.visible().then_some(menu)
 3977                } else {
 3978                    None
 3979                };
 3980
 3981                editor.update_in(&mut cx, |editor, window, cx| {
 3982                    match editor.context_menu.borrow().as_ref() {
 3983                        None => {}
 3984                        Some(CodeContextMenu::Completions(prev_menu)) => {
 3985                            if prev_menu.id > id {
 3986                                return;
 3987                            }
 3988                        }
 3989                        _ => return,
 3990                    }
 3991
 3992                    if editor.focus_handle.is_focused(window) && menu.is_some() {
 3993                        let mut menu = menu.unwrap();
 3994                        menu.resolve_visible_completions(editor.completion_provider.as_deref(), cx);
 3995
 3996                        *editor.context_menu.borrow_mut() =
 3997                            Some(CodeContextMenu::Completions(menu));
 3998
 3999                        if editor.show_edit_predictions_in_menu() {
 4000                            editor.update_visible_inline_completion(window, cx);
 4001                        } else {
 4002                            editor.discard_inline_completion(false, cx);
 4003                        }
 4004
 4005                        cx.notify();
 4006                    } else if editor.completion_tasks.len() <= 1 {
 4007                        // If there are no more completion tasks and the last menu was
 4008                        // empty, we should hide it.
 4009                        let was_hidden = editor.hide_context_menu(window, cx).is_none();
 4010                        // If it was already hidden and we don't show inline
 4011                        // completions in the menu, we should also show the
 4012                        // inline-completion when available.
 4013                        if was_hidden && editor.show_edit_predictions_in_menu() {
 4014                            editor.update_visible_inline_completion(window, cx);
 4015                        }
 4016                    }
 4017                })?;
 4018
 4019                Ok::<_, anyhow::Error>(())
 4020            }
 4021            .log_err()
 4022        });
 4023
 4024        self.completion_tasks.push((id, task));
 4025    }
 4026
 4027    pub fn confirm_completion(
 4028        &mut self,
 4029        action: &ConfirmCompletion,
 4030        window: &mut Window,
 4031        cx: &mut Context<Self>,
 4032    ) -> Option<Task<Result<()>>> {
 4033        self.do_completion(action.item_ix, CompletionIntent::Complete, window, cx)
 4034    }
 4035
 4036    pub fn compose_completion(
 4037        &mut self,
 4038        action: &ComposeCompletion,
 4039        window: &mut Window,
 4040        cx: &mut Context<Self>,
 4041    ) -> Option<Task<Result<()>>> {
 4042        self.do_completion(action.item_ix, CompletionIntent::Compose, window, cx)
 4043    }
 4044
 4045    fn do_completion(
 4046        &mut self,
 4047        item_ix: Option<usize>,
 4048        intent: CompletionIntent,
 4049        window: &mut Window,
 4050        cx: &mut Context<Editor>,
 4051    ) -> Option<Task<std::result::Result<(), anyhow::Error>>> {
 4052        use language::ToOffset as _;
 4053
 4054        let completions_menu =
 4055            if let CodeContextMenu::Completions(menu) = self.hide_context_menu(window, cx)? {
 4056                menu
 4057            } else {
 4058                return None;
 4059            };
 4060
 4061        let entries = completions_menu.entries.borrow();
 4062        let mat = entries.get(item_ix.unwrap_or(completions_menu.selected_item))?;
 4063        if self.show_edit_predictions_in_menu() {
 4064            self.discard_inline_completion(true, cx);
 4065        }
 4066        let candidate_id = mat.candidate_id;
 4067        drop(entries);
 4068
 4069        let buffer_handle = completions_menu.buffer;
 4070        let completion = completions_menu
 4071            .completions
 4072            .borrow()
 4073            .get(candidate_id)?
 4074            .clone();
 4075        cx.stop_propagation();
 4076
 4077        let snippet;
 4078        let text;
 4079
 4080        if completion.is_snippet() {
 4081            snippet = Some(Snippet::parse(&completion.new_text).log_err()?);
 4082            text = snippet.as_ref().unwrap().text.clone();
 4083        } else {
 4084            snippet = None;
 4085            text = completion.new_text.clone();
 4086        };
 4087        let selections = self.selections.all::<usize>(cx);
 4088        let buffer = buffer_handle.read(cx);
 4089        let old_range = completion.old_range.to_offset(buffer);
 4090        let old_text = buffer.text_for_range(old_range.clone()).collect::<String>();
 4091
 4092        let newest_selection = self.selections.newest_anchor();
 4093        if newest_selection.start.buffer_id != Some(buffer_handle.read(cx).remote_id()) {
 4094            return None;
 4095        }
 4096
 4097        let lookbehind = newest_selection
 4098            .start
 4099            .text_anchor
 4100            .to_offset(buffer)
 4101            .saturating_sub(old_range.start);
 4102        let lookahead = old_range
 4103            .end
 4104            .saturating_sub(newest_selection.end.text_anchor.to_offset(buffer));
 4105        let mut common_prefix_len = old_text
 4106            .bytes()
 4107            .zip(text.bytes())
 4108            .take_while(|(a, b)| a == b)
 4109            .count();
 4110
 4111        let snapshot = self.buffer.read(cx).snapshot(cx);
 4112        let mut range_to_replace: Option<Range<isize>> = None;
 4113        let mut ranges = Vec::new();
 4114        let mut linked_edits = HashMap::<_, Vec<_>>::default();
 4115        for selection in &selections {
 4116            if snapshot.contains_str_at(selection.start.saturating_sub(lookbehind), &old_text) {
 4117                let start = selection.start.saturating_sub(lookbehind);
 4118                let end = selection.end + lookahead;
 4119                if selection.id == newest_selection.id {
 4120                    range_to_replace = Some(
 4121                        ((start + common_prefix_len) as isize - selection.start as isize)
 4122                            ..(end as isize - selection.start as isize),
 4123                    );
 4124                }
 4125                ranges.push(start + common_prefix_len..end);
 4126            } else {
 4127                common_prefix_len = 0;
 4128                ranges.clear();
 4129                ranges.extend(selections.iter().map(|s| {
 4130                    if s.id == newest_selection.id {
 4131                        range_to_replace = Some(
 4132                            old_range.start.to_offset_utf16(&snapshot).0 as isize
 4133                                - selection.start as isize
 4134                                ..old_range.end.to_offset_utf16(&snapshot).0 as isize
 4135                                    - selection.start as isize,
 4136                        );
 4137                        old_range.clone()
 4138                    } else {
 4139                        s.start..s.end
 4140                    }
 4141                }));
 4142                break;
 4143            }
 4144            if !self.linked_edit_ranges.is_empty() {
 4145                let start_anchor = snapshot.anchor_before(selection.head());
 4146                let end_anchor = snapshot.anchor_after(selection.tail());
 4147                if let Some(ranges) = self
 4148                    .linked_editing_ranges_for(start_anchor.text_anchor..end_anchor.text_anchor, cx)
 4149                {
 4150                    for (buffer, edits) in ranges {
 4151                        linked_edits.entry(buffer.clone()).or_default().extend(
 4152                            edits
 4153                                .into_iter()
 4154                                .map(|range| (range, text[common_prefix_len..].to_owned())),
 4155                        );
 4156                    }
 4157                }
 4158            }
 4159        }
 4160        let text = &text[common_prefix_len..];
 4161
 4162        cx.emit(EditorEvent::InputHandled {
 4163            utf16_range_to_replace: range_to_replace,
 4164            text: text.into(),
 4165        });
 4166
 4167        self.transact(window, cx, |this, window, cx| {
 4168            if let Some(mut snippet) = snippet {
 4169                snippet.text = text.to_string();
 4170                for tabstop in snippet
 4171                    .tabstops
 4172                    .iter_mut()
 4173                    .flat_map(|tabstop| tabstop.ranges.iter_mut())
 4174                {
 4175                    tabstop.start -= common_prefix_len as isize;
 4176                    tabstop.end -= common_prefix_len as isize;
 4177                }
 4178
 4179                this.insert_snippet(&ranges, snippet, window, cx).log_err();
 4180            } else {
 4181                this.buffer.update(cx, |buffer, cx| {
 4182                    buffer.edit(
 4183                        ranges.iter().map(|range| (range.clone(), text)),
 4184                        this.autoindent_mode.clone(),
 4185                        cx,
 4186                    );
 4187                });
 4188            }
 4189            for (buffer, edits) in linked_edits {
 4190                buffer.update(cx, |buffer, cx| {
 4191                    let snapshot = buffer.snapshot();
 4192                    let edits = edits
 4193                        .into_iter()
 4194                        .map(|(range, text)| {
 4195                            use text::ToPoint as TP;
 4196                            let end_point = TP::to_point(&range.end, &snapshot);
 4197                            let start_point = TP::to_point(&range.start, &snapshot);
 4198                            (start_point..end_point, text)
 4199                        })
 4200                        .sorted_by_key(|(range, _)| range.start)
 4201                        .collect::<Vec<_>>();
 4202                    buffer.edit(edits, None, cx);
 4203                })
 4204            }
 4205
 4206            this.refresh_inline_completion(true, false, window, cx);
 4207        });
 4208
 4209        let show_new_completions_on_confirm = completion
 4210            .confirm
 4211            .as_ref()
 4212            .map_or(false, |confirm| confirm(intent, window, cx));
 4213        if show_new_completions_on_confirm {
 4214            self.show_completions(&ShowCompletions { trigger: None }, window, cx);
 4215        }
 4216
 4217        let provider = self.completion_provider.as_ref()?;
 4218        drop(completion);
 4219        let apply_edits = provider.apply_additional_edits_for_completion(
 4220            buffer_handle,
 4221            completions_menu.completions.clone(),
 4222            candidate_id,
 4223            true,
 4224            cx,
 4225        );
 4226
 4227        let editor_settings = EditorSettings::get_global(cx);
 4228        if editor_settings.show_signature_help_after_edits || editor_settings.auto_signature_help {
 4229            // After the code completion is finished, users often want to know what signatures are needed.
 4230            // so we should automatically call signature_help
 4231            self.show_signature_help(&ShowSignatureHelp, window, cx);
 4232        }
 4233
 4234        Some(cx.foreground_executor().spawn(async move {
 4235            apply_edits.await?;
 4236            Ok(())
 4237        }))
 4238    }
 4239
 4240    pub fn toggle_code_actions(
 4241        &mut self,
 4242        action: &ToggleCodeActions,
 4243        window: &mut Window,
 4244        cx: &mut Context<Self>,
 4245    ) {
 4246        let mut context_menu = self.context_menu.borrow_mut();
 4247        if let Some(CodeContextMenu::CodeActions(code_actions)) = context_menu.as_ref() {
 4248            if code_actions.deployed_from_indicator == action.deployed_from_indicator {
 4249                // Toggle if we're selecting the same one
 4250                *context_menu = None;
 4251                cx.notify();
 4252                return;
 4253            } else {
 4254                // Otherwise, clear it and start a new one
 4255                *context_menu = None;
 4256                cx.notify();
 4257            }
 4258        }
 4259        drop(context_menu);
 4260        let snapshot = self.snapshot(window, cx);
 4261        let deployed_from_indicator = action.deployed_from_indicator;
 4262        let mut task = self.code_actions_task.take();
 4263        let action = action.clone();
 4264        cx.spawn_in(window, |editor, mut cx| async move {
 4265            while let Some(prev_task) = task {
 4266                prev_task.await.log_err();
 4267                task = editor.update(&mut cx, |this, _| this.code_actions_task.take())?;
 4268            }
 4269
 4270            let spawned_test_task = editor.update_in(&mut cx, |editor, window, cx| {
 4271                if editor.focus_handle.is_focused(window) {
 4272                    let multibuffer_point = action
 4273                        .deployed_from_indicator
 4274                        .map(|row| DisplayPoint::new(row, 0).to_point(&snapshot))
 4275                        .unwrap_or_else(|| editor.selections.newest::<Point>(cx).head());
 4276                    let (buffer, buffer_row) = snapshot
 4277                        .buffer_snapshot
 4278                        .buffer_line_for_row(MultiBufferRow(multibuffer_point.row))
 4279                        .and_then(|(buffer_snapshot, range)| {
 4280                            editor
 4281                                .buffer
 4282                                .read(cx)
 4283                                .buffer(buffer_snapshot.remote_id())
 4284                                .map(|buffer| (buffer, range.start.row))
 4285                        })?;
 4286                    let (_, code_actions) = editor
 4287                        .available_code_actions
 4288                        .clone()
 4289                        .and_then(|(location, code_actions)| {
 4290                            let snapshot = location.buffer.read(cx).snapshot();
 4291                            let point_range = location.range.to_point(&snapshot);
 4292                            let point_range = point_range.start.row..=point_range.end.row;
 4293                            if point_range.contains(&buffer_row) {
 4294                                Some((location, code_actions))
 4295                            } else {
 4296                                None
 4297                            }
 4298                        })
 4299                        .unzip();
 4300                    let buffer_id = buffer.read(cx).remote_id();
 4301                    let tasks = editor
 4302                        .tasks
 4303                        .get(&(buffer_id, buffer_row))
 4304                        .map(|t| Arc::new(t.to_owned()));
 4305                    if tasks.is_none() && code_actions.is_none() {
 4306                        return None;
 4307                    }
 4308
 4309                    editor.completion_tasks.clear();
 4310                    editor.discard_inline_completion(false, cx);
 4311                    let task_context =
 4312                        tasks
 4313                            .as_ref()
 4314                            .zip(editor.project.clone())
 4315                            .map(|(tasks, project)| {
 4316                                Self::build_tasks_context(&project, &buffer, buffer_row, tasks, cx)
 4317                            });
 4318
 4319                    Some(cx.spawn_in(window, |editor, mut cx| async move {
 4320                        let task_context = match task_context {
 4321                            Some(task_context) => task_context.await,
 4322                            None => None,
 4323                        };
 4324                        let resolved_tasks =
 4325                            tasks.zip(task_context).map(|(tasks, task_context)| {
 4326                                Rc::new(ResolvedTasks {
 4327                                    templates: tasks.resolve(&task_context).collect(),
 4328                                    position: snapshot.buffer_snapshot.anchor_before(Point::new(
 4329                                        multibuffer_point.row,
 4330                                        tasks.column,
 4331                                    )),
 4332                                })
 4333                            });
 4334                        let spawn_straight_away = resolved_tasks
 4335                            .as_ref()
 4336                            .map_or(false, |tasks| tasks.templates.len() == 1)
 4337                            && code_actions
 4338                                .as_ref()
 4339                                .map_or(true, |actions| actions.is_empty());
 4340                        if let Ok(task) = editor.update_in(&mut cx, |editor, window, cx| {
 4341                            *editor.context_menu.borrow_mut() =
 4342                                Some(CodeContextMenu::CodeActions(CodeActionsMenu {
 4343                                    buffer,
 4344                                    actions: CodeActionContents {
 4345                                        tasks: resolved_tasks,
 4346                                        actions: code_actions,
 4347                                    },
 4348                                    selected_item: Default::default(),
 4349                                    scroll_handle: UniformListScrollHandle::default(),
 4350                                    deployed_from_indicator,
 4351                                }));
 4352                            if spawn_straight_away {
 4353                                if let Some(task) = editor.confirm_code_action(
 4354                                    &ConfirmCodeAction { item_ix: Some(0) },
 4355                                    window,
 4356                                    cx,
 4357                                ) {
 4358                                    cx.notify();
 4359                                    return task;
 4360                                }
 4361                            }
 4362                            cx.notify();
 4363                            Task::ready(Ok(()))
 4364                        }) {
 4365                            task.await
 4366                        } else {
 4367                            Ok(())
 4368                        }
 4369                    }))
 4370                } else {
 4371                    Some(Task::ready(Ok(())))
 4372                }
 4373            })?;
 4374            if let Some(task) = spawned_test_task {
 4375                task.await?;
 4376            }
 4377
 4378            Ok::<_, anyhow::Error>(())
 4379        })
 4380        .detach_and_log_err(cx);
 4381    }
 4382
 4383    pub fn confirm_code_action(
 4384        &mut self,
 4385        action: &ConfirmCodeAction,
 4386        window: &mut Window,
 4387        cx: &mut Context<Self>,
 4388    ) -> Option<Task<Result<()>>> {
 4389        let actions_menu =
 4390            if let CodeContextMenu::CodeActions(menu) = self.hide_context_menu(window, cx)? {
 4391                menu
 4392            } else {
 4393                return None;
 4394            };
 4395        let action_ix = action.item_ix.unwrap_or(actions_menu.selected_item);
 4396        let action = actions_menu.actions.get(action_ix)?;
 4397        let title = action.label();
 4398        let buffer = actions_menu.buffer;
 4399        let workspace = self.workspace()?;
 4400
 4401        match action {
 4402            CodeActionsItem::Task(task_source_kind, resolved_task) => {
 4403                workspace.update(cx, |workspace, cx| {
 4404                    workspace::tasks::schedule_resolved_task(
 4405                        workspace,
 4406                        task_source_kind,
 4407                        resolved_task,
 4408                        false,
 4409                        cx,
 4410                    );
 4411
 4412                    Some(Task::ready(Ok(())))
 4413                })
 4414            }
 4415            CodeActionsItem::CodeAction {
 4416                excerpt_id,
 4417                action,
 4418                provider,
 4419            } => {
 4420                let apply_code_action =
 4421                    provider.apply_code_action(buffer, action, excerpt_id, true, window, cx);
 4422                let workspace = workspace.downgrade();
 4423                Some(cx.spawn_in(window, |editor, cx| async move {
 4424                    let project_transaction = apply_code_action.await?;
 4425                    Self::open_project_transaction(
 4426                        &editor,
 4427                        workspace,
 4428                        project_transaction,
 4429                        title,
 4430                        cx,
 4431                    )
 4432                    .await
 4433                }))
 4434            }
 4435        }
 4436    }
 4437
 4438    pub async fn open_project_transaction(
 4439        this: &WeakEntity<Editor>,
 4440        workspace: WeakEntity<Workspace>,
 4441        transaction: ProjectTransaction,
 4442        title: String,
 4443        mut cx: AsyncWindowContext,
 4444    ) -> Result<()> {
 4445        let mut entries = transaction.0.into_iter().collect::<Vec<_>>();
 4446        cx.update(|_, cx| {
 4447            entries.sort_unstable_by_key(|(buffer, _)| {
 4448                buffer.read(cx).file().map(|f| f.path().clone())
 4449            });
 4450        })?;
 4451
 4452        // If the project transaction's edits are all contained within this editor, then
 4453        // avoid opening a new editor to display them.
 4454
 4455        if let Some((buffer, transaction)) = entries.first() {
 4456            if entries.len() == 1 {
 4457                let excerpt = this.update(&mut cx, |editor, cx| {
 4458                    editor
 4459                        .buffer()
 4460                        .read(cx)
 4461                        .excerpt_containing(editor.selections.newest_anchor().head(), cx)
 4462                })?;
 4463                if let Some((_, excerpted_buffer, excerpt_range)) = excerpt {
 4464                    if excerpted_buffer == *buffer {
 4465                        let all_edits_within_excerpt = buffer.read_with(&cx, |buffer, _| {
 4466                            let excerpt_range = excerpt_range.to_offset(buffer);
 4467                            buffer
 4468                                .edited_ranges_for_transaction::<usize>(transaction)
 4469                                .all(|range| {
 4470                                    excerpt_range.start <= range.start
 4471                                        && excerpt_range.end >= range.end
 4472                                })
 4473                        })?;
 4474
 4475                        if all_edits_within_excerpt {
 4476                            return Ok(());
 4477                        }
 4478                    }
 4479                }
 4480            }
 4481        } else {
 4482            return Ok(());
 4483        }
 4484
 4485        let mut ranges_to_highlight = Vec::new();
 4486        let excerpt_buffer = cx.new(|cx| {
 4487            let mut multibuffer = MultiBuffer::new(Capability::ReadWrite).with_title(title);
 4488            for (buffer_handle, transaction) in &entries {
 4489                let buffer = buffer_handle.read(cx);
 4490                ranges_to_highlight.extend(
 4491                    multibuffer.push_excerpts_with_context_lines(
 4492                        buffer_handle.clone(),
 4493                        buffer
 4494                            .edited_ranges_for_transaction::<usize>(transaction)
 4495                            .collect(),
 4496                        DEFAULT_MULTIBUFFER_CONTEXT,
 4497                        cx,
 4498                    ),
 4499                );
 4500            }
 4501            multibuffer.push_transaction(entries.iter().map(|(b, t)| (b, t)), cx);
 4502            multibuffer
 4503        })?;
 4504
 4505        workspace.update_in(&mut cx, |workspace, window, cx| {
 4506            let project = workspace.project().clone();
 4507            let editor = cx
 4508                .new(|cx| Editor::for_multibuffer(excerpt_buffer, Some(project), true, window, cx));
 4509            workspace.add_item_to_active_pane(Box::new(editor.clone()), None, true, window, cx);
 4510            editor.update(cx, |editor, cx| {
 4511                editor.highlight_background::<Self>(
 4512                    &ranges_to_highlight,
 4513                    |theme| theme.editor_highlighted_line_background,
 4514                    cx,
 4515                );
 4516            });
 4517        })?;
 4518
 4519        Ok(())
 4520    }
 4521
 4522    pub fn clear_code_action_providers(&mut self) {
 4523        self.code_action_providers.clear();
 4524        self.available_code_actions.take();
 4525    }
 4526
 4527    pub fn add_code_action_provider(
 4528        &mut self,
 4529        provider: Rc<dyn CodeActionProvider>,
 4530        window: &mut Window,
 4531        cx: &mut Context<Self>,
 4532    ) {
 4533        if self
 4534            .code_action_providers
 4535            .iter()
 4536            .any(|existing_provider| existing_provider.id() == provider.id())
 4537        {
 4538            return;
 4539        }
 4540
 4541        self.code_action_providers.push(provider);
 4542        self.refresh_code_actions(window, cx);
 4543    }
 4544
 4545    pub fn remove_code_action_provider(
 4546        &mut self,
 4547        id: Arc<str>,
 4548        window: &mut Window,
 4549        cx: &mut Context<Self>,
 4550    ) {
 4551        self.code_action_providers
 4552            .retain(|provider| provider.id() != id);
 4553        self.refresh_code_actions(window, cx);
 4554    }
 4555
 4556    fn refresh_code_actions(&mut self, window: &mut Window, cx: &mut Context<Self>) -> Option<()> {
 4557        let buffer = self.buffer.read(cx);
 4558        let newest_selection = self.selections.newest_anchor().clone();
 4559        if newest_selection.head().diff_base_anchor.is_some() {
 4560            return None;
 4561        }
 4562        let (start_buffer, start) = buffer.text_anchor_for_position(newest_selection.start, cx)?;
 4563        let (end_buffer, end) = buffer.text_anchor_for_position(newest_selection.end, cx)?;
 4564        if start_buffer != end_buffer {
 4565            return None;
 4566        }
 4567
 4568        self.code_actions_task = Some(cx.spawn_in(window, |this, mut cx| async move {
 4569            cx.background_executor()
 4570                .timer(CODE_ACTIONS_DEBOUNCE_TIMEOUT)
 4571                .await;
 4572
 4573            let (providers, tasks) = this.update_in(&mut cx, |this, window, cx| {
 4574                let providers = this.code_action_providers.clone();
 4575                let tasks = this
 4576                    .code_action_providers
 4577                    .iter()
 4578                    .map(|provider| provider.code_actions(&start_buffer, start..end, window, cx))
 4579                    .collect::<Vec<_>>();
 4580                (providers, tasks)
 4581            })?;
 4582
 4583            let mut actions = Vec::new();
 4584            for (provider, provider_actions) in
 4585                providers.into_iter().zip(future::join_all(tasks).await)
 4586            {
 4587                if let Some(provider_actions) = provider_actions.log_err() {
 4588                    actions.extend(provider_actions.into_iter().map(|action| {
 4589                        AvailableCodeAction {
 4590                            excerpt_id: newest_selection.start.excerpt_id,
 4591                            action,
 4592                            provider: provider.clone(),
 4593                        }
 4594                    }));
 4595                }
 4596            }
 4597
 4598            this.update(&mut cx, |this, cx| {
 4599                this.available_code_actions = if actions.is_empty() {
 4600                    None
 4601                } else {
 4602                    Some((
 4603                        Location {
 4604                            buffer: start_buffer,
 4605                            range: start..end,
 4606                        },
 4607                        actions.into(),
 4608                    ))
 4609                };
 4610                cx.notify();
 4611            })
 4612        }));
 4613        None
 4614    }
 4615
 4616    fn start_inline_blame_timer(&mut self, window: &mut Window, cx: &mut Context<Self>) {
 4617        if let Some(delay) = ProjectSettings::get_global(cx).git.inline_blame_delay() {
 4618            self.show_git_blame_inline = false;
 4619
 4620            self.show_git_blame_inline_delay_task =
 4621                Some(cx.spawn_in(window, |this, mut cx| async move {
 4622                    cx.background_executor().timer(delay).await;
 4623
 4624                    this.update(&mut cx, |this, cx| {
 4625                        this.show_git_blame_inline = true;
 4626                        cx.notify();
 4627                    })
 4628                    .log_err();
 4629                }));
 4630        }
 4631    }
 4632
 4633    fn refresh_document_highlights(&mut self, cx: &mut Context<Self>) -> Option<()> {
 4634        if self.pending_rename.is_some() {
 4635            return None;
 4636        }
 4637
 4638        let provider = self.semantics_provider.clone()?;
 4639        let buffer = self.buffer.read(cx);
 4640        let newest_selection = self.selections.newest_anchor().clone();
 4641        let cursor_position = newest_selection.head();
 4642        let (cursor_buffer, cursor_buffer_position) =
 4643            buffer.text_anchor_for_position(cursor_position, cx)?;
 4644        let (tail_buffer, _) = buffer.text_anchor_for_position(newest_selection.tail(), cx)?;
 4645        if cursor_buffer != tail_buffer {
 4646            return None;
 4647        }
 4648        let debounce = EditorSettings::get_global(cx).lsp_highlight_debounce;
 4649        self.document_highlights_task = Some(cx.spawn(|this, mut cx| async move {
 4650            cx.background_executor()
 4651                .timer(Duration::from_millis(debounce))
 4652                .await;
 4653
 4654            let highlights = if let Some(highlights) = cx
 4655                .update(|cx| {
 4656                    provider.document_highlights(&cursor_buffer, cursor_buffer_position, cx)
 4657                })
 4658                .ok()
 4659                .flatten()
 4660            {
 4661                highlights.await.log_err()
 4662            } else {
 4663                None
 4664            };
 4665
 4666            if let Some(highlights) = highlights {
 4667                this.update(&mut cx, |this, cx| {
 4668                    if this.pending_rename.is_some() {
 4669                        return;
 4670                    }
 4671
 4672                    let buffer_id = cursor_position.buffer_id;
 4673                    let buffer = this.buffer.read(cx);
 4674                    if !buffer
 4675                        .text_anchor_for_position(cursor_position, cx)
 4676                        .map_or(false, |(buffer, _)| buffer == cursor_buffer)
 4677                    {
 4678                        return;
 4679                    }
 4680
 4681                    let cursor_buffer_snapshot = cursor_buffer.read(cx);
 4682                    let mut write_ranges = Vec::new();
 4683                    let mut read_ranges = Vec::new();
 4684                    for highlight in highlights {
 4685                        for (excerpt_id, excerpt_range) in
 4686                            buffer.excerpts_for_buffer(cursor_buffer.read(cx).remote_id(), cx)
 4687                        {
 4688                            let start = highlight
 4689                                .range
 4690                                .start
 4691                                .max(&excerpt_range.context.start, cursor_buffer_snapshot);
 4692                            let end = highlight
 4693                                .range
 4694                                .end
 4695                                .min(&excerpt_range.context.end, cursor_buffer_snapshot);
 4696                            if start.cmp(&end, cursor_buffer_snapshot).is_ge() {
 4697                                continue;
 4698                            }
 4699
 4700                            let range = Anchor {
 4701                                buffer_id,
 4702                                excerpt_id,
 4703                                text_anchor: start,
 4704                                diff_base_anchor: None,
 4705                            }..Anchor {
 4706                                buffer_id,
 4707                                excerpt_id,
 4708                                text_anchor: end,
 4709                                diff_base_anchor: None,
 4710                            };
 4711                            if highlight.kind == lsp::DocumentHighlightKind::WRITE {
 4712                                write_ranges.push(range);
 4713                            } else {
 4714                                read_ranges.push(range);
 4715                            }
 4716                        }
 4717                    }
 4718
 4719                    this.highlight_background::<DocumentHighlightRead>(
 4720                        &read_ranges,
 4721                        |theme| theme.editor_document_highlight_read_background,
 4722                        cx,
 4723                    );
 4724                    this.highlight_background::<DocumentHighlightWrite>(
 4725                        &write_ranges,
 4726                        |theme| theme.editor_document_highlight_write_background,
 4727                        cx,
 4728                    );
 4729                    cx.notify();
 4730                })
 4731                .log_err();
 4732            }
 4733        }));
 4734        None
 4735    }
 4736
 4737    pub fn refresh_inline_completion(
 4738        &mut self,
 4739        debounce: bool,
 4740        user_requested: bool,
 4741        window: &mut Window,
 4742        cx: &mut Context<Self>,
 4743    ) -> Option<()> {
 4744        let provider = self.edit_prediction_provider()?;
 4745        let cursor = self.selections.newest_anchor().head();
 4746        let (buffer, cursor_buffer_position) =
 4747            self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
 4748
 4749        if !self.inline_completions_enabled_in_buffer(&buffer, cursor_buffer_position, cx) {
 4750            self.discard_inline_completion(false, cx);
 4751            return None;
 4752        }
 4753
 4754        if !user_requested
 4755            && (!self.should_show_edit_predictions()
 4756                || !self.is_focused(window)
 4757                || buffer.read(cx).is_empty())
 4758        {
 4759            self.discard_inline_completion(false, cx);
 4760            return None;
 4761        }
 4762
 4763        self.update_visible_inline_completion(window, cx);
 4764        provider.refresh(
 4765            self.project.clone(),
 4766            buffer,
 4767            cursor_buffer_position,
 4768            debounce,
 4769            cx,
 4770        );
 4771        Some(())
 4772    }
 4773
 4774    fn show_edit_predictions_in_menu(&self) -> bool {
 4775        match self.edit_prediction_settings {
 4776            EditPredictionSettings::Disabled => false,
 4777            EditPredictionSettings::Enabled { show_in_menu, .. } => show_in_menu,
 4778        }
 4779    }
 4780
 4781    pub fn edit_predictions_enabled(&self) -> bool {
 4782        match self.edit_prediction_settings {
 4783            EditPredictionSettings::Disabled => false,
 4784            EditPredictionSettings::Enabled { .. } => true,
 4785        }
 4786    }
 4787
 4788    fn edit_prediction_requires_modifier(&self) -> bool {
 4789        match self.edit_prediction_settings {
 4790            EditPredictionSettings::Disabled => false,
 4791            EditPredictionSettings::Enabled {
 4792                preview_requires_modifier,
 4793                ..
 4794            } => preview_requires_modifier,
 4795        }
 4796    }
 4797
 4798    fn edit_prediction_settings_at_position(
 4799        &self,
 4800        buffer: &Entity<Buffer>,
 4801        buffer_position: language::Anchor,
 4802        cx: &App,
 4803    ) -> EditPredictionSettings {
 4804        if self.mode != EditorMode::Full
 4805            || !self.show_inline_completions_override.unwrap_or(true)
 4806            || self.inline_completions_disabled_in_scope(buffer, buffer_position, cx)
 4807        {
 4808            return EditPredictionSettings::Disabled;
 4809        }
 4810
 4811        let buffer = buffer.read(cx);
 4812
 4813        let file = buffer.file();
 4814
 4815        if !language_settings(buffer.language().map(|l| l.name()), file, cx).show_edit_predictions {
 4816            return EditPredictionSettings::Disabled;
 4817        };
 4818
 4819        let by_provider = matches!(
 4820            self.menu_inline_completions_policy,
 4821            MenuInlineCompletionsPolicy::ByProvider
 4822        );
 4823
 4824        let show_in_menu = by_provider
 4825            && self
 4826                .edit_prediction_provider
 4827                .as_ref()
 4828                .map_or(false, |provider| {
 4829                    provider.provider.show_completions_in_menu()
 4830                });
 4831
 4832        let preview_requires_modifier =
 4833            all_language_settings(file, cx).edit_predictions_mode() == EditPredictionsMode::Auto;
 4834
 4835        EditPredictionSettings::Enabled {
 4836            show_in_menu,
 4837            preview_requires_modifier,
 4838        }
 4839    }
 4840
 4841    fn should_show_edit_predictions(&self) -> bool {
 4842        self.snippet_stack.is_empty() && self.edit_predictions_enabled()
 4843    }
 4844
 4845    pub fn edit_prediction_preview_is_active(&self) -> bool {
 4846        matches!(
 4847            self.edit_prediction_preview,
 4848            EditPredictionPreview::Active { .. }
 4849        )
 4850    }
 4851
 4852    pub fn inline_completions_enabled(&self, cx: &App) -> bool {
 4853        let cursor = self.selections.newest_anchor().head();
 4854        if let Some((buffer, cursor_position)) =
 4855            self.buffer.read(cx).text_anchor_for_position(cursor, cx)
 4856        {
 4857            self.inline_completions_enabled_in_buffer(&buffer, cursor_position, cx)
 4858        } else {
 4859            false
 4860        }
 4861    }
 4862
 4863    fn inline_completions_enabled_in_buffer(
 4864        &self,
 4865        buffer: &Entity<Buffer>,
 4866        buffer_position: language::Anchor,
 4867        cx: &App,
 4868    ) -> bool {
 4869        maybe!({
 4870            let provider = self.edit_prediction_provider()?;
 4871            if !provider.is_enabled(&buffer, buffer_position, cx) {
 4872                return Some(false);
 4873            }
 4874            let buffer = buffer.read(cx);
 4875            let Some(file) = buffer.file() else {
 4876                return Some(true);
 4877            };
 4878            let settings = all_language_settings(Some(file), cx);
 4879            Some(settings.inline_completions_enabled_for_path(file.path()))
 4880        })
 4881        .unwrap_or(false)
 4882    }
 4883
 4884    fn cycle_inline_completion(
 4885        &mut self,
 4886        direction: Direction,
 4887        window: &mut Window,
 4888        cx: &mut Context<Self>,
 4889    ) -> Option<()> {
 4890        let provider = self.edit_prediction_provider()?;
 4891        let cursor = self.selections.newest_anchor().head();
 4892        let (buffer, cursor_buffer_position) =
 4893            self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
 4894        if self.inline_completions_hidden_for_vim_mode || !self.should_show_edit_predictions() {
 4895            return None;
 4896        }
 4897
 4898        provider.cycle(buffer, cursor_buffer_position, direction, cx);
 4899        self.update_visible_inline_completion(window, cx);
 4900
 4901        Some(())
 4902    }
 4903
 4904    pub fn show_inline_completion(
 4905        &mut self,
 4906        _: &ShowEditPrediction,
 4907        window: &mut Window,
 4908        cx: &mut Context<Self>,
 4909    ) {
 4910        if !self.has_active_inline_completion() {
 4911            self.refresh_inline_completion(false, true, window, cx);
 4912            return;
 4913        }
 4914
 4915        self.update_visible_inline_completion(window, cx);
 4916    }
 4917
 4918    pub fn display_cursor_names(
 4919        &mut self,
 4920        _: &DisplayCursorNames,
 4921        window: &mut Window,
 4922        cx: &mut Context<Self>,
 4923    ) {
 4924        self.show_cursor_names(window, cx);
 4925    }
 4926
 4927    fn show_cursor_names(&mut self, window: &mut Window, cx: &mut Context<Self>) {
 4928        self.show_cursor_names = true;
 4929        cx.notify();
 4930        cx.spawn_in(window, |this, mut cx| async move {
 4931            cx.background_executor().timer(CURSORS_VISIBLE_FOR).await;
 4932            this.update(&mut cx, |this, cx| {
 4933                this.show_cursor_names = false;
 4934                cx.notify()
 4935            })
 4936            .ok()
 4937        })
 4938        .detach();
 4939    }
 4940
 4941    pub fn next_edit_prediction(
 4942        &mut self,
 4943        _: &NextEditPrediction,
 4944        window: &mut Window,
 4945        cx: &mut Context<Self>,
 4946    ) {
 4947        if self.has_active_inline_completion() {
 4948            self.cycle_inline_completion(Direction::Next, window, cx);
 4949        } else {
 4950            let is_copilot_disabled = self
 4951                .refresh_inline_completion(false, true, window, cx)
 4952                .is_none();
 4953            if is_copilot_disabled {
 4954                cx.propagate();
 4955            }
 4956        }
 4957    }
 4958
 4959    pub fn previous_edit_prediction(
 4960        &mut self,
 4961        _: &PreviousEditPrediction,
 4962        window: &mut Window,
 4963        cx: &mut Context<Self>,
 4964    ) {
 4965        if self.has_active_inline_completion() {
 4966            self.cycle_inline_completion(Direction::Prev, window, cx);
 4967        } else {
 4968            let is_copilot_disabled = self
 4969                .refresh_inline_completion(false, true, window, cx)
 4970                .is_none();
 4971            if is_copilot_disabled {
 4972                cx.propagate();
 4973            }
 4974        }
 4975    }
 4976
 4977    pub fn accept_edit_prediction(
 4978        &mut self,
 4979        _: &AcceptEditPrediction,
 4980        window: &mut Window,
 4981        cx: &mut Context<Self>,
 4982    ) {
 4983        if self.show_edit_predictions_in_menu() {
 4984            self.hide_context_menu(window, cx);
 4985        }
 4986
 4987        let Some(active_inline_completion) = self.active_inline_completion.as_ref() else {
 4988            return;
 4989        };
 4990
 4991        self.report_inline_completion_event(
 4992            active_inline_completion.completion_id.clone(),
 4993            true,
 4994            cx,
 4995        );
 4996
 4997        match &active_inline_completion.completion {
 4998            InlineCompletion::Move { target, .. } => {
 4999                let target = *target;
 5000
 5001                if let Some(position_map) = &self.last_position_map {
 5002                    if position_map
 5003                        .visible_row_range
 5004                        .contains(&target.to_display_point(&position_map.snapshot).row())
 5005                        || !self.edit_prediction_requires_modifier()
 5006                    {
 5007                        // Note that this is also done in vim's handler of the Tab action.
 5008                        self.change_selections(
 5009                            Some(Autoscroll::newest()),
 5010                            window,
 5011                            cx,
 5012                            |selections| {
 5013                                selections.select_anchor_ranges([target..target]);
 5014                            },
 5015                        );
 5016                        self.clear_row_highlights::<EditPredictionPreview>();
 5017
 5018                        self.edit_prediction_preview = EditPredictionPreview::Active {
 5019                            previous_scroll_position: None,
 5020                        };
 5021                    } else {
 5022                        self.edit_prediction_preview = EditPredictionPreview::Active {
 5023                            previous_scroll_position: Some(position_map.snapshot.scroll_anchor),
 5024                        };
 5025                        self.highlight_rows::<EditPredictionPreview>(
 5026                            target..target,
 5027                            cx.theme().colors().editor_highlighted_line_background,
 5028                            true,
 5029                            cx,
 5030                        );
 5031                        self.request_autoscroll(Autoscroll::fit(), cx);
 5032                    }
 5033                }
 5034            }
 5035            InlineCompletion::Edit { edits, .. } => {
 5036                if let Some(provider) = self.edit_prediction_provider() {
 5037                    provider.accept(cx);
 5038                }
 5039
 5040                let snapshot = self.buffer.read(cx).snapshot(cx);
 5041                let last_edit_end = edits.last().unwrap().0.end.bias_right(&snapshot);
 5042
 5043                self.buffer.update(cx, |buffer, cx| {
 5044                    buffer.edit(edits.iter().cloned(), None, cx)
 5045                });
 5046
 5047                self.change_selections(None, window, cx, |s| {
 5048                    s.select_anchor_ranges([last_edit_end..last_edit_end])
 5049                });
 5050
 5051                self.update_visible_inline_completion(window, cx);
 5052                if self.active_inline_completion.is_none() {
 5053                    self.refresh_inline_completion(true, true, window, cx);
 5054                }
 5055
 5056                cx.notify();
 5057            }
 5058        }
 5059
 5060        self.edit_prediction_requires_modifier_in_leading_space = false;
 5061    }
 5062
 5063    pub fn accept_partial_inline_completion(
 5064        &mut self,
 5065        _: &AcceptPartialEditPrediction,
 5066        window: &mut Window,
 5067        cx: &mut Context<Self>,
 5068    ) {
 5069        let Some(active_inline_completion) = self.active_inline_completion.as_ref() else {
 5070            return;
 5071        };
 5072        if self.selections.count() != 1 {
 5073            return;
 5074        }
 5075
 5076        self.report_inline_completion_event(
 5077            active_inline_completion.completion_id.clone(),
 5078            true,
 5079            cx,
 5080        );
 5081
 5082        match &active_inline_completion.completion {
 5083            InlineCompletion::Move { target, .. } => {
 5084                let target = *target;
 5085                self.change_selections(Some(Autoscroll::newest()), window, cx, |selections| {
 5086                    selections.select_anchor_ranges([target..target]);
 5087                });
 5088            }
 5089            InlineCompletion::Edit { edits, .. } => {
 5090                // Find an insertion that starts at the cursor position.
 5091                let snapshot = self.buffer.read(cx).snapshot(cx);
 5092                let cursor_offset = self.selections.newest::<usize>(cx).head();
 5093                let insertion = edits.iter().find_map(|(range, text)| {
 5094                    let range = range.to_offset(&snapshot);
 5095                    if range.is_empty() && range.start == cursor_offset {
 5096                        Some(text)
 5097                    } else {
 5098                        None
 5099                    }
 5100                });
 5101
 5102                if let Some(text) = insertion {
 5103                    let mut partial_completion = text
 5104                        .chars()
 5105                        .by_ref()
 5106                        .take_while(|c| c.is_alphabetic())
 5107                        .collect::<String>();
 5108                    if partial_completion.is_empty() {
 5109                        partial_completion = text
 5110                            .chars()
 5111                            .by_ref()
 5112                            .take_while(|c| c.is_whitespace() || !c.is_alphabetic())
 5113                            .collect::<String>();
 5114                    }
 5115
 5116                    cx.emit(EditorEvent::InputHandled {
 5117                        utf16_range_to_replace: None,
 5118                        text: partial_completion.clone().into(),
 5119                    });
 5120
 5121                    self.insert_with_autoindent_mode(&partial_completion, None, window, cx);
 5122
 5123                    self.refresh_inline_completion(true, true, window, cx);
 5124                    cx.notify();
 5125                } else {
 5126                    self.accept_edit_prediction(&Default::default(), window, cx);
 5127                }
 5128            }
 5129        }
 5130    }
 5131
 5132    fn discard_inline_completion(
 5133        &mut self,
 5134        should_report_inline_completion_event: bool,
 5135        cx: &mut Context<Self>,
 5136    ) -> bool {
 5137        if should_report_inline_completion_event {
 5138            let completion_id = self
 5139                .active_inline_completion
 5140                .as_ref()
 5141                .and_then(|active_completion| active_completion.completion_id.clone());
 5142
 5143            self.report_inline_completion_event(completion_id, false, cx);
 5144        }
 5145
 5146        if let Some(provider) = self.edit_prediction_provider() {
 5147            provider.discard(cx);
 5148        }
 5149
 5150        self.take_active_inline_completion(cx)
 5151    }
 5152
 5153    fn report_inline_completion_event(&self, id: Option<SharedString>, accepted: bool, cx: &App) {
 5154        let Some(provider) = self.edit_prediction_provider() else {
 5155            return;
 5156        };
 5157
 5158        let Some((_, buffer, _)) = self
 5159            .buffer
 5160            .read(cx)
 5161            .excerpt_containing(self.selections.newest_anchor().head(), cx)
 5162        else {
 5163            return;
 5164        };
 5165
 5166        let extension = buffer
 5167            .read(cx)
 5168            .file()
 5169            .and_then(|file| Some(file.path().extension()?.to_string_lossy().to_string()));
 5170
 5171        let event_type = match accepted {
 5172            true => "Edit Prediction Accepted",
 5173            false => "Edit Prediction Discarded",
 5174        };
 5175        telemetry::event!(
 5176            event_type,
 5177            provider = provider.name(),
 5178            prediction_id = id,
 5179            suggestion_accepted = accepted,
 5180            file_extension = extension,
 5181        );
 5182    }
 5183
 5184    pub fn has_active_inline_completion(&self) -> bool {
 5185        self.active_inline_completion.is_some()
 5186    }
 5187
 5188    fn take_active_inline_completion(&mut self, cx: &mut Context<Self>) -> bool {
 5189        let Some(active_inline_completion) = self.active_inline_completion.take() else {
 5190            return false;
 5191        };
 5192
 5193        self.splice_inlays(&active_inline_completion.inlay_ids, Default::default(), cx);
 5194        self.clear_highlights::<InlineCompletionHighlight>(cx);
 5195        self.stale_inline_completion_in_menu = Some(active_inline_completion);
 5196        true
 5197    }
 5198
 5199    /// Returns true when we're displaying the edit prediction popover below the cursor
 5200    /// like we are not previewing and the LSP autocomplete menu is visible
 5201    /// or we are in `when_holding_modifier` mode.
 5202    pub fn edit_prediction_visible_in_cursor_popover(&self, has_completion: bool) -> bool {
 5203        if self.edit_prediction_preview_is_active()
 5204            || !self.show_edit_predictions_in_menu()
 5205            || !self.edit_predictions_enabled()
 5206        {
 5207            return false;
 5208        }
 5209
 5210        if self.has_visible_completions_menu() {
 5211            return true;
 5212        }
 5213
 5214        has_completion && self.edit_prediction_requires_modifier()
 5215    }
 5216
 5217    fn handle_modifiers_changed(
 5218        &mut self,
 5219        modifiers: Modifiers,
 5220        position_map: &PositionMap,
 5221        window: &mut Window,
 5222        cx: &mut Context<Self>,
 5223    ) {
 5224        if self.show_edit_predictions_in_menu() {
 5225            self.update_edit_prediction_preview(&modifiers, window, cx);
 5226        }
 5227
 5228        let mouse_position = window.mouse_position();
 5229        if !position_map.text_hitbox.is_hovered(window) {
 5230            return;
 5231        }
 5232
 5233        self.update_hovered_link(
 5234            position_map.point_for_position(mouse_position),
 5235            &position_map.snapshot,
 5236            modifiers,
 5237            window,
 5238            cx,
 5239        )
 5240    }
 5241
 5242    fn update_edit_prediction_preview(
 5243        &mut self,
 5244        modifiers: &Modifiers,
 5245        window: &mut Window,
 5246        cx: &mut Context<Self>,
 5247    ) {
 5248        let accept_keybind = self.accept_edit_prediction_keybind(window, cx);
 5249        let Some(accept_keystroke) = accept_keybind.keystroke() else {
 5250            return;
 5251        };
 5252
 5253        if &accept_keystroke.modifiers == modifiers && accept_keystroke.modifiers.modified() {
 5254            if matches!(
 5255                self.edit_prediction_preview,
 5256                EditPredictionPreview::Inactive
 5257            ) {
 5258                self.edit_prediction_preview = EditPredictionPreview::Active {
 5259                    previous_scroll_position: None,
 5260                };
 5261
 5262                self.update_visible_inline_completion(window, cx);
 5263                cx.notify();
 5264            }
 5265        } else if let EditPredictionPreview::Active {
 5266            previous_scroll_position,
 5267        } = self.edit_prediction_preview
 5268        {
 5269            if let (Some(previous_scroll_position), Some(position_map)) =
 5270                (previous_scroll_position, self.last_position_map.as_ref())
 5271            {
 5272                self.set_scroll_position(
 5273                    previous_scroll_position
 5274                        .scroll_position(&position_map.snapshot.display_snapshot),
 5275                    window,
 5276                    cx,
 5277                );
 5278            }
 5279
 5280            self.edit_prediction_preview = EditPredictionPreview::Inactive;
 5281            self.clear_row_highlights::<EditPredictionPreview>();
 5282            self.update_visible_inline_completion(window, cx);
 5283            cx.notify();
 5284        }
 5285    }
 5286
 5287    fn update_visible_inline_completion(
 5288        &mut self,
 5289        _window: &mut Window,
 5290        cx: &mut Context<Self>,
 5291    ) -> Option<()> {
 5292        let selection = self.selections.newest_anchor();
 5293        let cursor = selection.head();
 5294        let multibuffer = self.buffer.read(cx).snapshot(cx);
 5295        let offset_selection = selection.map(|endpoint| endpoint.to_offset(&multibuffer));
 5296        let excerpt_id = cursor.excerpt_id;
 5297
 5298        let show_in_menu = self.show_edit_predictions_in_menu();
 5299        let completions_menu_has_precedence = !show_in_menu
 5300            && (self.context_menu.borrow().is_some()
 5301                || (!self.completion_tasks.is_empty() && !self.has_active_inline_completion()));
 5302
 5303        if completions_menu_has_precedence
 5304            || !offset_selection.is_empty()
 5305            || self
 5306                .active_inline_completion
 5307                .as_ref()
 5308                .map_or(false, |completion| {
 5309                    let invalidation_range = completion.invalidation_range.to_offset(&multibuffer);
 5310                    let invalidation_range = invalidation_range.start..=invalidation_range.end;
 5311                    !invalidation_range.contains(&offset_selection.head())
 5312                })
 5313        {
 5314            self.discard_inline_completion(false, cx);
 5315            return None;
 5316        }
 5317
 5318        self.take_active_inline_completion(cx);
 5319        let Some(provider) = self.edit_prediction_provider() else {
 5320            self.edit_prediction_settings = EditPredictionSettings::Disabled;
 5321            return None;
 5322        };
 5323
 5324        let (buffer, cursor_buffer_position) =
 5325            self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
 5326
 5327        self.edit_prediction_settings =
 5328            self.edit_prediction_settings_at_position(&buffer, cursor_buffer_position, cx);
 5329
 5330        if !self.edit_prediction_settings.is_enabled() {
 5331            self.discard_inline_completion(false, cx);
 5332            return None;
 5333        }
 5334
 5335        self.edit_prediction_cursor_on_leading_whitespace =
 5336            multibuffer.is_line_whitespace_upto(cursor);
 5337
 5338        let inline_completion = provider.suggest(&buffer, cursor_buffer_position, cx)?;
 5339        let edits = inline_completion
 5340            .edits
 5341            .into_iter()
 5342            .flat_map(|(range, new_text)| {
 5343                let start = multibuffer.anchor_in_excerpt(excerpt_id, range.start)?;
 5344                let end = multibuffer.anchor_in_excerpt(excerpt_id, range.end)?;
 5345                Some((start..end, new_text))
 5346            })
 5347            .collect::<Vec<_>>();
 5348        if edits.is_empty() {
 5349            return None;
 5350        }
 5351
 5352        let first_edit_start = edits.first().unwrap().0.start;
 5353        let first_edit_start_point = first_edit_start.to_point(&multibuffer);
 5354        let edit_start_row = first_edit_start_point.row.saturating_sub(2);
 5355
 5356        let last_edit_end = edits.last().unwrap().0.end;
 5357        let last_edit_end_point = last_edit_end.to_point(&multibuffer);
 5358        let edit_end_row = cmp::min(multibuffer.max_point().row, last_edit_end_point.row + 2);
 5359
 5360        let cursor_row = cursor.to_point(&multibuffer).row;
 5361
 5362        let snapshot = multibuffer.buffer_for_excerpt(excerpt_id).cloned()?;
 5363
 5364        let mut inlay_ids = Vec::new();
 5365        let invalidation_row_range;
 5366        let move_invalidation_row_range = if cursor_row < edit_start_row {
 5367            Some(cursor_row..edit_end_row)
 5368        } else if cursor_row > edit_end_row {
 5369            Some(edit_start_row..cursor_row)
 5370        } else {
 5371            None
 5372        };
 5373        let is_move =
 5374            move_invalidation_row_range.is_some() || self.inline_completions_hidden_for_vim_mode;
 5375        let completion = if is_move {
 5376            invalidation_row_range =
 5377                move_invalidation_row_range.unwrap_or(edit_start_row..edit_end_row);
 5378            let target = first_edit_start;
 5379            InlineCompletion::Move { target, snapshot }
 5380        } else {
 5381            let show_completions_in_buffer = !self.edit_prediction_visible_in_cursor_popover(true)
 5382                && !self.inline_completions_hidden_for_vim_mode;
 5383
 5384            if show_completions_in_buffer {
 5385                if edits
 5386                    .iter()
 5387                    .all(|(range, _)| range.to_offset(&multibuffer).is_empty())
 5388                {
 5389                    let mut inlays = Vec::new();
 5390                    for (range, new_text) in &edits {
 5391                        let inlay = Inlay::inline_completion(
 5392                            post_inc(&mut self.next_inlay_id),
 5393                            range.start,
 5394                            new_text.as_str(),
 5395                        );
 5396                        inlay_ids.push(inlay.id);
 5397                        inlays.push(inlay);
 5398                    }
 5399
 5400                    self.splice_inlays(&[], inlays, cx);
 5401                } else {
 5402                    let background_color = cx.theme().status().deleted_background;
 5403                    self.highlight_text::<InlineCompletionHighlight>(
 5404                        edits.iter().map(|(range, _)| range.clone()).collect(),
 5405                        HighlightStyle {
 5406                            background_color: Some(background_color),
 5407                            ..Default::default()
 5408                        },
 5409                        cx,
 5410                    );
 5411                }
 5412            }
 5413
 5414            invalidation_row_range = edit_start_row..edit_end_row;
 5415
 5416            let display_mode = if all_edits_insertions_or_deletions(&edits, &multibuffer) {
 5417                if provider.show_tab_accept_marker() {
 5418                    EditDisplayMode::TabAccept
 5419                } else {
 5420                    EditDisplayMode::Inline
 5421                }
 5422            } else {
 5423                EditDisplayMode::DiffPopover
 5424            };
 5425
 5426            InlineCompletion::Edit {
 5427                edits,
 5428                edit_preview: inline_completion.edit_preview,
 5429                display_mode,
 5430                snapshot,
 5431            }
 5432        };
 5433
 5434        let invalidation_range = multibuffer
 5435            .anchor_before(Point::new(invalidation_row_range.start, 0))
 5436            ..multibuffer.anchor_after(Point::new(
 5437                invalidation_row_range.end,
 5438                multibuffer.line_len(MultiBufferRow(invalidation_row_range.end)),
 5439            ));
 5440
 5441        self.stale_inline_completion_in_menu = None;
 5442        self.active_inline_completion = Some(InlineCompletionState {
 5443            inlay_ids,
 5444            completion,
 5445            completion_id: inline_completion.id,
 5446            invalidation_range,
 5447        });
 5448
 5449        cx.notify();
 5450
 5451        Some(())
 5452    }
 5453
 5454    pub fn edit_prediction_provider(&self) -> Option<Arc<dyn InlineCompletionProviderHandle>> {
 5455        Some(self.edit_prediction_provider.as_ref()?.provider.clone())
 5456    }
 5457
 5458    fn render_code_actions_indicator(
 5459        &self,
 5460        _style: &EditorStyle,
 5461        row: DisplayRow,
 5462        is_active: bool,
 5463        cx: &mut Context<Self>,
 5464    ) -> Option<IconButton> {
 5465        if self.available_code_actions.is_some() {
 5466            Some(
 5467                IconButton::new("code_actions_indicator", ui::IconName::Bolt)
 5468                    .shape(ui::IconButtonShape::Square)
 5469                    .icon_size(IconSize::XSmall)
 5470                    .icon_color(Color::Muted)
 5471                    .toggle_state(is_active)
 5472                    .tooltip({
 5473                        let focus_handle = self.focus_handle.clone();
 5474                        move |window, cx| {
 5475                            Tooltip::for_action_in(
 5476                                "Toggle Code Actions",
 5477                                &ToggleCodeActions {
 5478                                    deployed_from_indicator: None,
 5479                                },
 5480                                &focus_handle,
 5481                                window,
 5482                                cx,
 5483                            )
 5484                        }
 5485                    })
 5486                    .on_click(cx.listener(move |editor, _e, window, cx| {
 5487                        window.focus(&editor.focus_handle(cx));
 5488                        editor.toggle_code_actions(
 5489                            &ToggleCodeActions {
 5490                                deployed_from_indicator: Some(row),
 5491                            },
 5492                            window,
 5493                            cx,
 5494                        );
 5495                    })),
 5496            )
 5497        } else {
 5498            None
 5499        }
 5500    }
 5501
 5502    fn clear_tasks(&mut self) {
 5503        self.tasks.clear()
 5504    }
 5505
 5506    fn insert_tasks(&mut self, key: (BufferId, BufferRow), value: RunnableTasks) {
 5507        if self.tasks.insert(key, value).is_some() {
 5508            // This case should hopefully be rare, but just in case...
 5509            log::error!("multiple different run targets found on a single line, only the last target will be rendered")
 5510        }
 5511    }
 5512
 5513    fn build_tasks_context(
 5514        project: &Entity<Project>,
 5515        buffer: &Entity<Buffer>,
 5516        buffer_row: u32,
 5517        tasks: &Arc<RunnableTasks>,
 5518        cx: &mut Context<Self>,
 5519    ) -> Task<Option<task::TaskContext>> {
 5520        let position = Point::new(buffer_row, tasks.column);
 5521        let range_start = buffer.read(cx).anchor_at(position, Bias::Right);
 5522        let location = Location {
 5523            buffer: buffer.clone(),
 5524            range: range_start..range_start,
 5525        };
 5526        // Fill in the environmental variables from the tree-sitter captures
 5527        let mut captured_task_variables = TaskVariables::default();
 5528        for (capture_name, value) in tasks.extra_variables.clone() {
 5529            captured_task_variables.insert(
 5530                task::VariableName::Custom(capture_name.into()),
 5531                value.clone(),
 5532            );
 5533        }
 5534        project.update(cx, |project, cx| {
 5535            project.task_store().update(cx, |task_store, cx| {
 5536                task_store.task_context_for_location(captured_task_variables, location, cx)
 5537            })
 5538        })
 5539    }
 5540
 5541    pub fn spawn_nearest_task(
 5542        &mut self,
 5543        action: &SpawnNearestTask,
 5544        window: &mut Window,
 5545        cx: &mut Context<Self>,
 5546    ) {
 5547        let Some((workspace, _)) = self.workspace.clone() else {
 5548            return;
 5549        };
 5550        let Some(project) = self.project.clone() else {
 5551            return;
 5552        };
 5553
 5554        // Try to find a closest, enclosing node using tree-sitter that has a
 5555        // task
 5556        let Some((buffer, buffer_row, tasks)) = self
 5557            .find_enclosing_node_task(cx)
 5558            // Or find the task that's closest in row-distance.
 5559            .or_else(|| self.find_closest_task(cx))
 5560        else {
 5561            return;
 5562        };
 5563
 5564        let reveal_strategy = action.reveal;
 5565        let task_context = Self::build_tasks_context(&project, &buffer, buffer_row, &tasks, cx);
 5566        cx.spawn_in(window, |_, mut cx| async move {
 5567            let context = task_context.await?;
 5568            let (task_source_kind, mut resolved_task) = tasks.resolve(&context).next()?;
 5569
 5570            let resolved = resolved_task.resolved.as_mut()?;
 5571            resolved.reveal = reveal_strategy;
 5572
 5573            workspace
 5574                .update(&mut cx, |workspace, cx| {
 5575                    workspace::tasks::schedule_resolved_task(
 5576                        workspace,
 5577                        task_source_kind,
 5578                        resolved_task,
 5579                        false,
 5580                        cx,
 5581                    );
 5582                })
 5583                .ok()
 5584        })
 5585        .detach();
 5586    }
 5587
 5588    fn find_closest_task(
 5589        &mut self,
 5590        cx: &mut Context<Self>,
 5591    ) -> Option<(Entity<Buffer>, u32, Arc<RunnableTasks>)> {
 5592        let cursor_row = self.selections.newest_adjusted(cx).head().row;
 5593
 5594        let ((buffer_id, row), tasks) = self
 5595            .tasks
 5596            .iter()
 5597            .min_by_key(|((_, row), _)| cursor_row.abs_diff(*row))?;
 5598
 5599        let buffer = self.buffer.read(cx).buffer(*buffer_id)?;
 5600        let tasks = Arc::new(tasks.to_owned());
 5601        Some((buffer, *row, tasks))
 5602    }
 5603
 5604    fn find_enclosing_node_task(
 5605        &mut self,
 5606        cx: &mut Context<Self>,
 5607    ) -> Option<(Entity<Buffer>, u32, Arc<RunnableTasks>)> {
 5608        let snapshot = self.buffer.read(cx).snapshot(cx);
 5609        let offset = self.selections.newest::<usize>(cx).head();
 5610        let excerpt = snapshot.excerpt_containing(offset..offset)?;
 5611        let buffer_id = excerpt.buffer().remote_id();
 5612
 5613        let layer = excerpt.buffer().syntax_layer_at(offset)?;
 5614        let mut cursor = layer.node().walk();
 5615
 5616        while cursor.goto_first_child_for_byte(offset).is_some() {
 5617            if cursor.node().end_byte() == offset {
 5618                cursor.goto_next_sibling();
 5619            }
 5620        }
 5621
 5622        // Ascend to the smallest ancestor that contains the range and has a task.
 5623        loop {
 5624            let node = cursor.node();
 5625            let node_range = node.byte_range();
 5626            let symbol_start_row = excerpt.buffer().offset_to_point(node.start_byte()).row;
 5627
 5628            // Check if this node contains our offset
 5629            if node_range.start <= offset && node_range.end >= offset {
 5630                // If it contains offset, check for task
 5631                if let Some(tasks) = self.tasks.get(&(buffer_id, symbol_start_row)) {
 5632                    let buffer = self.buffer.read(cx).buffer(buffer_id)?;
 5633                    return Some((buffer, symbol_start_row, Arc::new(tasks.to_owned())));
 5634                }
 5635            }
 5636
 5637            if !cursor.goto_parent() {
 5638                break;
 5639            }
 5640        }
 5641        None
 5642    }
 5643
 5644    fn render_run_indicator(
 5645        &self,
 5646        _style: &EditorStyle,
 5647        is_active: bool,
 5648        row: DisplayRow,
 5649        cx: &mut Context<Self>,
 5650    ) -> IconButton {
 5651        IconButton::new(("run_indicator", row.0 as usize), ui::IconName::Play)
 5652            .shape(ui::IconButtonShape::Square)
 5653            .icon_size(IconSize::XSmall)
 5654            .icon_color(Color::Muted)
 5655            .toggle_state(is_active)
 5656            .on_click(cx.listener(move |editor, _e, window, cx| {
 5657                window.focus(&editor.focus_handle(cx));
 5658                editor.toggle_code_actions(
 5659                    &ToggleCodeActions {
 5660                        deployed_from_indicator: Some(row),
 5661                    },
 5662                    window,
 5663                    cx,
 5664                );
 5665            }))
 5666    }
 5667
 5668    pub fn context_menu_visible(&self) -> bool {
 5669        !self.edit_prediction_preview_is_active()
 5670            && self
 5671                .context_menu
 5672                .borrow()
 5673                .as_ref()
 5674                .map_or(false, |menu| menu.visible())
 5675    }
 5676
 5677    fn context_menu_origin(&self) -> Option<ContextMenuOrigin> {
 5678        self.context_menu
 5679            .borrow()
 5680            .as_ref()
 5681            .map(|menu| menu.origin())
 5682    }
 5683
 5684    fn edit_prediction_cursor_popover_height(&self) -> Pixels {
 5685        px(30.)
 5686    }
 5687
 5688    fn current_user_player_color(&self, cx: &mut App) -> PlayerColor {
 5689        if self.read_only(cx) {
 5690            cx.theme().players().read_only()
 5691        } else {
 5692            self.style.as_ref().unwrap().local_player
 5693        }
 5694    }
 5695
 5696    fn render_edit_prediction_accept_keybind(&self, window: &mut Window, cx: &App) -> Option<Div> {
 5697        let accept_binding = self.accept_edit_prediction_keybind(window, cx);
 5698        let accept_keystroke = accept_binding.keystroke()?;
 5699
 5700        let is_platform_style_mac = PlatformStyle::platform() == PlatformStyle::Mac;
 5701
 5702        let modifiers_color = if accept_keystroke.modifiers == window.modifiers() {
 5703            Color::Accent
 5704        } else {
 5705            Color::Muted
 5706        };
 5707
 5708        h_flex()
 5709            .px_0p5()
 5710            .when(is_platform_style_mac, |parent| parent.gap_0p5())
 5711            .font(theme::ThemeSettings::get_global(cx).buffer_font.clone())
 5712            .text_size(TextSize::XSmall.rems(cx))
 5713            .child(h_flex().children(ui::render_modifiers(
 5714                &accept_keystroke.modifiers,
 5715                PlatformStyle::platform(),
 5716                Some(modifiers_color),
 5717                Some(IconSize::XSmall.rems().into()),
 5718                true,
 5719            )))
 5720            .when(is_platform_style_mac, |parent| {
 5721                parent.child(accept_keystroke.key.clone())
 5722            })
 5723            .when(!is_platform_style_mac, |parent| {
 5724                parent.child(
 5725                    Key::new(
 5726                        util::capitalize(&accept_keystroke.key),
 5727                        Some(Color::Default),
 5728                    )
 5729                    .size(Some(IconSize::XSmall.rems().into())),
 5730                )
 5731            })
 5732            .into()
 5733    }
 5734
 5735    fn render_edit_prediction_line_popover(
 5736        &self,
 5737        label: impl Into<SharedString>,
 5738        icon: Option<IconName>,
 5739        window: &mut Window,
 5740        cx: &App,
 5741    ) -> Option<Div> {
 5742        let bg_color = Self::edit_prediction_line_popover_bg_color(cx);
 5743
 5744        let padding_right = if icon.is_some() { px(4.) } else { px(8.) };
 5745
 5746        let result = h_flex()
 5747            .gap_1()
 5748            .border_1()
 5749            .rounded_lg()
 5750            .shadow_sm()
 5751            .bg(bg_color)
 5752            .border_color(cx.theme().colors().text_accent.opacity(0.4))
 5753            .py_0p5()
 5754            .pl_1()
 5755            .pr(padding_right)
 5756            .children(self.render_edit_prediction_accept_keybind(window, cx))
 5757            .child(Label::new(label).size(LabelSize::Small))
 5758            .when_some(icon, |element, icon| {
 5759                element.child(
 5760                    div()
 5761                        .mt(px(1.5))
 5762                        .child(Icon::new(icon).size(IconSize::Small)),
 5763                )
 5764            });
 5765
 5766        Some(result)
 5767    }
 5768
 5769    fn edit_prediction_line_popover_bg_color(cx: &App) -> Hsla {
 5770        let accent_color = cx.theme().colors().text_accent;
 5771        let editor_bg_color = cx.theme().colors().editor_background;
 5772        editor_bg_color.blend(accent_color.opacity(0.1))
 5773    }
 5774
 5775    #[allow(clippy::too_many_arguments)]
 5776    fn render_edit_prediction_cursor_popover(
 5777        &self,
 5778        min_width: Pixels,
 5779        max_width: Pixels,
 5780        cursor_point: Point,
 5781        style: &EditorStyle,
 5782        accept_keystroke: &gpui::Keystroke,
 5783        _window: &Window,
 5784        cx: &mut Context<Editor>,
 5785    ) -> Option<AnyElement> {
 5786        let provider = self.edit_prediction_provider.as_ref()?;
 5787
 5788        if provider.provider.needs_terms_acceptance(cx) {
 5789            return Some(
 5790                h_flex()
 5791                    .min_w(min_width)
 5792                    .flex_1()
 5793                    .px_2()
 5794                    .py_1()
 5795                    .gap_3()
 5796                    .elevation_2(cx)
 5797                    .hover(|style| style.bg(cx.theme().colors().element_hover))
 5798                    .id("accept-terms")
 5799                    .cursor_pointer()
 5800                    .on_mouse_down(MouseButton::Left, |_, window, _| window.prevent_default())
 5801                    .on_click(cx.listener(|this, _event, window, cx| {
 5802                        cx.stop_propagation();
 5803                        this.report_editor_event("Edit Prediction Provider ToS Clicked", None, cx);
 5804                        window.dispatch_action(
 5805                            zed_actions::OpenZedPredictOnboarding.boxed_clone(),
 5806                            cx,
 5807                        );
 5808                    }))
 5809                    .child(
 5810                        h_flex()
 5811                            .flex_1()
 5812                            .gap_2()
 5813                            .child(Icon::new(IconName::ZedPredict))
 5814                            .child(Label::new("Accept Terms of Service"))
 5815                            .child(div().w_full())
 5816                            .child(
 5817                                Icon::new(IconName::ArrowUpRight)
 5818                                    .color(Color::Muted)
 5819                                    .size(IconSize::Small),
 5820                            )
 5821                            .into_any_element(),
 5822                    )
 5823                    .into_any(),
 5824            );
 5825        }
 5826
 5827        let is_refreshing = provider.provider.is_refreshing(cx);
 5828
 5829        fn pending_completion_container() -> Div {
 5830            h_flex()
 5831                .h_full()
 5832                .flex_1()
 5833                .gap_2()
 5834                .child(Icon::new(IconName::ZedPredict))
 5835        }
 5836
 5837        let completion = match &self.active_inline_completion {
 5838            Some(completion) => match &completion.completion {
 5839                InlineCompletion::Move {
 5840                    target, snapshot, ..
 5841                } if !self.has_visible_completions_menu() => {
 5842                    use text::ToPoint as _;
 5843
 5844                    return Some(
 5845                        h_flex()
 5846                            .px_2()
 5847                            .py_1()
 5848                            .elevation_2(cx)
 5849                            .border_color(cx.theme().colors().border)
 5850                            .rounded_tl(px(0.))
 5851                            .gap_2()
 5852                            .child(
 5853                                if target.text_anchor.to_point(&snapshot).row > cursor_point.row {
 5854                                    Icon::new(IconName::ZedPredictDown)
 5855                                } else {
 5856                                    Icon::new(IconName::ZedPredictUp)
 5857                                },
 5858                            )
 5859                            .child(Label::new("Hold").size(LabelSize::Small))
 5860                            .child(h_flex().children(ui::render_modifiers(
 5861                                &accept_keystroke.modifiers,
 5862                                PlatformStyle::platform(),
 5863                                Some(Color::Default),
 5864                                Some(IconSize::Small.rems().into()),
 5865                                false,
 5866                            )))
 5867                            .into_any(),
 5868                    );
 5869                }
 5870                _ => self.render_edit_prediction_cursor_popover_preview(
 5871                    completion,
 5872                    cursor_point,
 5873                    style,
 5874                    cx,
 5875                )?,
 5876            },
 5877
 5878            None if is_refreshing => match &self.stale_inline_completion_in_menu {
 5879                Some(stale_completion) => self.render_edit_prediction_cursor_popover_preview(
 5880                    stale_completion,
 5881                    cursor_point,
 5882                    style,
 5883                    cx,
 5884                )?,
 5885
 5886                None => {
 5887                    pending_completion_container().child(Label::new("...").size(LabelSize::Small))
 5888                }
 5889            },
 5890
 5891            None => pending_completion_container().child(Label::new("No Prediction")),
 5892        };
 5893
 5894        let completion = if is_refreshing {
 5895            completion
 5896                .with_animation(
 5897                    "loading-completion",
 5898                    Animation::new(Duration::from_secs(2))
 5899                        .repeat()
 5900                        .with_easing(pulsating_between(0.4, 0.8)),
 5901                    |label, delta| label.opacity(delta),
 5902                )
 5903                .into_any_element()
 5904        } else {
 5905            completion.into_any_element()
 5906        };
 5907
 5908        let has_completion = self.active_inline_completion.is_some();
 5909
 5910        let is_platform_style_mac = PlatformStyle::platform() == PlatformStyle::Mac;
 5911        Some(
 5912            h_flex()
 5913                .min_w(min_width)
 5914                .max_w(max_width)
 5915                .flex_1()
 5916                .elevation_2(cx)
 5917                .border_color(cx.theme().colors().border)
 5918                .child(
 5919                    div()
 5920                        .flex_1()
 5921                        .py_1()
 5922                        .px_2()
 5923                        .overflow_hidden()
 5924                        .child(completion),
 5925                )
 5926                .child(
 5927                    h_flex()
 5928                        .h_full()
 5929                        .border_l_1()
 5930                        .rounded_r_lg()
 5931                        .border_color(cx.theme().colors().border)
 5932                        .bg(Self::edit_prediction_line_popover_bg_color(cx))
 5933                        .gap_1()
 5934                        .py_1()
 5935                        .px_2()
 5936                        .child(
 5937                            h_flex()
 5938                                .font(theme::ThemeSettings::get_global(cx).buffer_font.clone())
 5939                                .when(is_platform_style_mac, |parent| parent.gap_1())
 5940                                .child(h_flex().children(ui::render_modifiers(
 5941                                    &accept_keystroke.modifiers,
 5942                                    PlatformStyle::platform(),
 5943                                    Some(if !has_completion {
 5944                                        Color::Muted
 5945                                    } else {
 5946                                        Color::Default
 5947                                    }),
 5948                                    None,
 5949                                    false,
 5950                                ))),
 5951                        )
 5952                        .child(Label::new("Preview").into_any_element())
 5953                        .opacity(if has_completion { 1.0 } else { 0.4 }),
 5954                )
 5955                .into_any(),
 5956        )
 5957    }
 5958
 5959    fn render_edit_prediction_cursor_popover_preview(
 5960        &self,
 5961        completion: &InlineCompletionState,
 5962        cursor_point: Point,
 5963        style: &EditorStyle,
 5964        cx: &mut Context<Editor>,
 5965    ) -> Option<Div> {
 5966        use text::ToPoint as _;
 5967
 5968        fn render_relative_row_jump(
 5969            prefix: impl Into<String>,
 5970            current_row: u32,
 5971            target_row: u32,
 5972        ) -> Div {
 5973            let (row_diff, arrow) = if target_row < current_row {
 5974                (current_row - target_row, IconName::ArrowUp)
 5975            } else {
 5976                (target_row - current_row, IconName::ArrowDown)
 5977            };
 5978
 5979            h_flex()
 5980                .child(
 5981                    Label::new(format!("{}{}", prefix.into(), row_diff))
 5982                        .color(Color::Muted)
 5983                        .size(LabelSize::Small),
 5984                )
 5985                .child(Icon::new(arrow).color(Color::Muted).size(IconSize::Small))
 5986        }
 5987
 5988        match &completion.completion {
 5989            InlineCompletion::Move {
 5990                target, snapshot, ..
 5991            } => Some(
 5992                h_flex()
 5993                    .px_2()
 5994                    .gap_2()
 5995                    .flex_1()
 5996                    .child(
 5997                        if target.text_anchor.to_point(&snapshot).row > cursor_point.row {
 5998                            Icon::new(IconName::ZedPredictDown)
 5999                        } else {
 6000                            Icon::new(IconName::ZedPredictUp)
 6001                        },
 6002                    )
 6003                    .child(Label::new("Jump to Edit")),
 6004            ),
 6005
 6006            InlineCompletion::Edit {
 6007                edits,
 6008                edit_preview,
 6009                snapshot,
 6010                display_mode: _,
 6011            } => {
 6012                let first_edit_row = edits.first()?.0.start.text_anchor.to_point(&snapshot).row;
 6013
 6014                let highlighted_edits = crate::inline_completion_edit_text(
 6015                    &snapshot,
 6016                    &edits,
 6017                    edit_preview.as_ref()?,
 6018                    true,
 6019                    cx,
 6020                );
 6021
 6022                let len_total = highlighted_edits.text.len();
 6023                let first_line = &highlighted_edits.text
 6024                    [..highlighted_edits.text.find('\n').unwrap_or(len_total)];
 6025                let first_line_len = first_line.len();
 6026
 6027                let first_highlight_start = highlighted_edits
 6028                    .highlights
 6029                    .first()
 6030                    .map_or(0, |(range, _)| range.start);
 6031                let drop_prefix_len = first_line
 6032                    .char_indices()
 6033                    .find(|(_, c)| !c.is_whitespace())
 6034                    .map_or(first_highlight_start, |(ix, _)| {
 6035                        ix.min(first_highlight_start)
 6036                    });
 6037
 6038                let preview_text = &first_line[drop_prefix_len..];
 6039                let preview_len = preview_text.len();
 6040                let highlights = highlighted_edits
 6041                    .highlights
 6042                    .into_iter()
 6043                    .take_until(|(range, _)| range.start > first_line_len)
 6044                    .map(|(range, style)| {
 6045                        (
 6046                            range.start - drop_prefix_len
 6047                                ..(range.end - drop_prefix_len).min(preview_len),
 6048                            style,
 6049                        )
 6050                    });
 6051
 6052                let styled_text = gpui::StyledText::new(SharedString::new(preview_text))
 6053                    .with_highlights(&style.text, highlights);
 6054
 6055                let preview = h_flex()
 6056                    .gap_1()
 6057                    .min_w_16()
 6058                    .child(styled_text)
 6059                    .when(len_total > first_line_len, |parent| parent.child(""));
 6060
 6061                let left = if first_edit_row != cursor_point.row {
 6062                    render_relative_row_jump("", cursor_point.row, first_edit_row)
 6063                        .into_any_element()
 6064                } else {
 6065                    Icon::new(IconName::ZedPredict).into_any_element()
 6066                };
 6067
 6068                Some(
 6069                    h_flex()
 6070                        .h_full()
 6071                        .flex_1()
 6072                        .gap_2()
 6073                        .pr_1()
 6074                        .overflow_x_hidden()
 6075                        .font(theme::ThemeSettings::get_global(cx).buffer_font.clone())
 6076                        .child(left)
 6077                        .child(preview),
 6078                )
 6079            }
 6080        }
 6081    }
 6082
 6083    fn render_context_menu(
 6084        &self,
 6085        style: &EditorStyle,
 6086        max_height_in_lines: u32,
 6087        y_flipped: bool,
 6088        window: &mut Window,
 6089        cx: &mut Context<Editor>,
 6090    ) -> Option<AnyElement> {
 6091        let menu = self.context_menu.borrow();
 6092        let menu = menu.as_ref()?;
 6093        if !menu.visible() {
 6094            return None;
 6095        };
 6096        Some(menu.render(style, max_height_in_lines, y_flipped, window, cx))
 6097    }
 6098
 6099    fn render_context_menu_aside(
 6100        &self,
 6101        style: &EditorStyle,
 6102        max_size: Size<Pixels>,
 6103        cx: &mut Context<Editor>,
 6104    ) -> Option<AnyElement> {
 6105        self.context_menu.borrow().as_ref().and_then(|menu| {
 6106            if menu.visible() {
 6107                menu.render_aside(
 6108                    style,
 6109                    max_size,
 6110                    self.workspace.as_ref().map(|(w, _)| w.clone()),
 6111                    cx,
 6112                )
 6113            } else {
 6114                None
 6115            }
 6116        })
 6117    }
 6118
 6119    fn hide_context_menu(
 6120        &mut self,
 6121        window: &mut Window,
 6122        cx: &mut Context<Self>,
 6123    ) -> Option<CodeContextMenu> {
 6124        cx.notify();
 6125        self.completion_tasks.clear();
 6126        let context_menu = self.context_menu.borrow_mut().take();
 6127        self.stale_inline_completion_in_menu.take();
 6128        self.update_visible_inline_completion(window, cx);
 6129        context_menu
 6130    }
 6131
 6132    fn show_snippet_choices(
 6133        &mut self,
 6134        choices: &Vec<String>,
 6135        selection: Range<Anchor>,
 6136        cx: &mut Context<Self>,
 6137    ) {
 6138        if selection.start.buffer_id.is_none() {
 6139            return;
 6140        }
 6141        let buffer_id = selection.start.buffer_id.unwrap();
 6142        let buffer = self.buffer().read(cx).buffer(buffer_id);
 6143        let id = post_inc(&mut self.next_completion_id);
 6144
 6145        if let Some(buffer) = buffer {
 6146            *self.context_menu.borrow_mut() = Some(CodeContextMenu::Completions(
 6147                CompletionsMenu::new_snippet_choices(id, true, choices, selection, buffer),
 6148            ));
 6149        }
 6150    }
 6151
 6152    pub fn insert_snippet(
 6153        &mut self,
 6154        insertion_ranges: &[Range<usize>],
 6155        snippet: Snippet,
 6156        window: &mut Window,
 6157        cx: &mut Context<Self>,
 6158    ) -> Result<()> {
 6159        struct Tabstop<T> {
 6160            is_end_tabstop: bool,
 6161            ranges: Vec<Range<T>>,
 6162            choices: Option<Vec<String>>,
 6163        }
 6164
 6165        let tabstops = self.buffer.update(cx, |buffer, cx| {
 6166            let snippet_text: Arc<str> = snippet.text.clone().into();
 6167            buffer.edit(
 6168                insertion_ranges
 6169                    .iter()
 6170                    .cloned()
 6171                    .map(|range| (range, snippet_text.clone())),
 6172                Some(AutoindentMode::EachLine),
 6173                cx,
 6174            );
 6175
 6176            let snapshot = &*buffer.read(cx);
 6177            let snippet = &snippet;
 6178            snippet
 6179                .tabstops
 6180                .iter()
 6181                .map(|tabstop| {
 6182                    let is_end_tabstop = tabstop.ranges.first().map_or(false, |tabstop| {
 6183                        tabstop.is_empty() && tabstop.start == snippet.text.len() as isize
 6184                    });
 6185                    let mut tabstop_ranges = tabstop
 6186                        .ranges
 6187                        .iter()
 6188                        .flat_map(|tabstop_range| {
 6189                            let mut delta = 0_isize;
 6190                            insertion_ranges.iter().map(move |insertion_range| {
 6191                                let insertion_start = insertion_range.start as isize + delta;
 6192                                delta +=
 6193                                    snippet.text.len() as isize - insertion_range.len() as isize;
 6194
 6195                                let start = ((insertion_start + tabstop_range.start) as usize)
 6196                                    .min(snapshot.len());
 6197                                let end = ((insertion_start + tabstop_range.end) as usize)
 6198                                    .min(snapshot.len());
 6199                                snapshot.anchor_before(start)..snapshot.anchor_after(end)
 6200                            })
 6201                        })
 6202                        .collect::<Vec<_>>();
 6203                    tabstop_ranges.sort_unstable_by(|a, b| a.start.cmp(&b.start, snapshot));
 6204
 6205                    Tabstop {
 6206                        is_end_tabstop,
 6207                        ranges: tabstop_ranges,
 6208                        choices: tabstop.choices.clone(),
 6209                    }
 6210                })
 6211                .collect::<Vec<_>>()
 6212        });
 6213        if let Some(tabstop) = tabstops.first() {
 6214            self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 6215                s.select_ranges(tabstop.ranges.iter().cloned());
 6216            });
 6217
 6218            if let Some(choices) = &tabstop.choices {
 6219                if let Some(selection) = tabstop.ranges.first() {
 6220                    self.show_snippet_choices(choices, selection.clone(), cx)
 6221                }
 6222            }
 6223
 6224            // If we're already at the last tabstop and it's at the end of the snippet,
 6225            // we're done, we don't need to keep the state around.
 6226            if !tabstop.is_end_tabstop {
 6227                let choices = tabstops
 6228                    .iter()
 6229                    .map(|tabstop| tabstop.choices.clone())
 6230                    .collect();
 6231
 6232                let ranges = tabstops
 6233                    .into_iter()
 6234                    .map(|tabstop| tabstop.ranges)
 6235                    .collect::<Vec<_>>();
 6236
 6237                self.snippet_stack.push(SnippetState {
 6238                    active_index: 0,
 6239                    ranges,
 6240                    choices,
 6241                });
 6242            }
 6243
 6244            // Check whether the just-entered snippet ends with an auto-closable bracket.
 6245            if self.autoclose_regions.is_empty() {
 6246                let snapshot = self.buffer.read(cx).snapshot(cx);
 6247                for selection in &mut self.selections.all::<Point>(cx) {
 6248                    let selection_head = selection.head();
 6249                    let Some(scope) = snapshot.language_scope_at(selection_head) else {
 6250                        continue;
 6251                    };
 6252
 6253                    let mut bracket_pair = None;
 6254                    let next_chars = snapshot.chars_at(selection_head).collect::<String>();
 6255                    let prev_chars = snapshot
 6256                        .reversed_chars_at(selection_head)
 6257                        .collect::<String>();
 6258                    for (pair, enabled) in scope.brackets() {
 6259                        if enabled
 6260                            && pair.close
 6261                            && prev_chars.starts_with(pair.start.as_str())
 6262                            && next_chars.starts_with(pair.end.as_str())
 6263                        {
 6264                            bracket_pair = Some(pair.clone());
 6265                            break;
 6266                        }
 6267                    }
 6268                    if let Some(pair) = bracket_pair {
 6269                        let start = snapshot.anchor_after(selection_head);
 6270                        let end = snapshot.anchor_after(selection_head);
 6271                        self.autoclose_regions.push(AutocloseRegion {
 6272                            selection_id: selection.id,
 6273                            range: start..end,
 6274                            pair,
 6275                        });
 6276                    }
 6277                }
 6278            }
 6279        }
 6280        Ok(())
 6281    }
 6282
 6283    pub fn move_to_next_snippet_tabstop(
 6284        &mut self,
 6285        window: &mut Window,
 6286        cx: &mut Context<Self>,
 6287    ) -> bool {
 6288        self.move_to_snippet_tabstop(Bias::Right, window, cx)
 6289    }
 6290
 6291    pub fn move_to_prev_snippet_tabstop(
 6292        &mut self,
 6293        window: &mut Window,
 6294        cx: &mut Context<Self>,
 6295    ) -> bool {
 6296        self.move_to_snippet_tabstop(Bias::Left, window, cx)
 6297    }
 6298
 6299    pub fn move_to_snippet_tabstop(
 6300        &mut self,
 6301        bias: Bias,
 6302        window: &mut Window,
 6303        cx: &mut Context<Self>,
 6304    ) -> bool {
 6305        if let Some(mut snippet) = self.snippet_stack.pop() {
 6306            match bias {
 6307                Bias::Left => {
 6308                    if snippet.active_index > 0 {
 6309                        snippet.active_index -= 1;
 6310                    } else {
 6311                        self.snippet_stack.push(snippet);
 6312                        return false;
 6313                    }
 6314                }
 6315                Bias::Right => {
 6316                    if snippet.active_index + 1 < snippet.ranges.len() {
 6317                        snippet.active_index += 1;
 6318                    } else {
 6319                        self.snippet_stack.push(snippet);
 6320                        return false;
 6321                    }
 6322                }
 6323            }
 6324            if let Some(current_ranges) = snippet.ranges.get(snippet.active_index) {
 6325                self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 6326                    s.select_anchor_ranges(current_ranges.iter().cloned())
 6327                });
 6328
 6329                if let Some(choices) = &snippet.choices[snippet.active_index] {
 6330                    if let Some(selection) = current_ranges.first() {
 6331                        self.show_snippet_choices(&choices, selection.clone(), cx);
 6332                    }
 6333                }
 6334
 6335                // If snippet state is not at the last tabstop, push it back on the stack
 6336                if snippet.active_index + 1 < snippet.ranges.len() {
 6337                    self.snippet_stack.push(snippet);
 6338                }
 6339                return true;
 6340            }
 6341        }
 6342
 6343        false
 6344    }
 6345
 6346    pub fn clear(&mut self, window: &mut Window, cx: &mut Context<Self>) {
 6347        self.transact(window, cx, |this, window, cx| {
 6348            this.select_all(&SelectAll, window, cx);
 6349            this.insert("", window, cx);
 6350        });
 6351    }
 6352
 6353    pub fn backspace(&mut self, _: &Backspace, window: &mut Window, cx: &mut Context<Self>) {
 6354        self.transact(window, cx, |this, window, cx| {
 6355            this.select_autoclose_pair(window, cx);
 6356            let mut linked_ranges = HashMap::<_, Vec<_>>::default();
 6357            if !this.linked_edit_ranges.is_empty() {
 6358                let selections = this.selections.all::<MultiBufferPoint>(cx);
 6359                let snapshot = this.buffer.read(cx).snapshot(cx);
 6360
 6361                for selection in selections.iter() {
 6362                    let selection_start = snapshot.anchor_before(selection.start).text_anchor;
 6363                    let selection_end = snapshot.anchor_after(selection.end).text_anchor;
 6364                    if selection_start.buffer_id != selection_end.buffer_id {
 6365                        continue;
 6366                    }
 6367                    if let Some(ranges) =
 6368                        this.linked_editing_ranges_for(selection_start..selection_end, cx)
 6369                    {
 6370                        for (buffer, entries) in ranges {
 6371                            linked_ranges.entry(buffer).or_default().extend(entries);
 6372                        }
 6373                    }
 6374                }
 6375            }
 6376
 6377            let mut selections = this.selections.all::<MultiBufferPoint>(cx);
 6378            if !this.selections.line_mode {
 6379                let display_map = this.display_map.update(cx, |map, cx| map.snapshot(cx));
 6380                for selection in &mut selections {
 6381                    if selection.is_empty() {
 6382                        let old_head = selection.head();
 6383                        let mut new_head =
 6384                            movement::left(&display_map, old_head.to_display_point(&display_map))
 6385                                .to_point(&display_map);
 6386                        if let Some((buffer, line_buffer_range)) = display_map
 6387                            .buffer_snapshot
 6388                            .buffer_line_for_row(MultiBufferRow(old_head.row))
 6389                        {
 6390                            let indent_size =
 6391                                buffer.indent_size_for_line(line_buffer_range.start.row);
 6392                            let indent_len = match indent_size.kind {
 6393                                IndentKind::Space => {
 6394                                    buffer.settings_at(line_buffer_range.start, cx).tab_size
 6395                                }
 6396                                IndentKind::Tab => NonZeroU32::new(1).unwrap(),
 6397                            };
 6398                            if old_head.column <= indent_size.len && old_head.column > 0 {
 6399                                let indent_len = indent_len.get();
 6400                                new_head = cmp::min(
 6401                                    new_head,
 6402                                    MultiBufferPoint::new(
 6403                                        old_head.row,
 6404                                        ((old_head.column - 1) / indent_len) * indent_len,
 6405                                    ),
 6406                                );
 6407                            }
 6408                        }
 6409
 6410                        selection.set_head(new_head, SelectionGoal::None);
 6411                    }
 6412                }
 6413            }
 6414
 6415            this.signature_help_state.set_backspace_pressed(true);
 6416            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 6417                s.select(selections)
 6418            });
 6419            this.insert("", window, cx);
 6420            let empty_str: Arc<str> = Arc::from("");
 6421            for (buffer, edits) in linked_ranges {
 6422                let snapshot = buffer.read(cx).snapshot();
 6423                use text::ToPoint as TP;
 6424
 6425                let edits = edits
 6426                    .into_iter()
 6427                    .map(|range| {
 6428                        let end_point = TP::to_point(&range.end, &snapshot);
 6429                        let mut start_point = TP::to_point(&range.start, &snapshot);
 6430
 6431                        if end_point == start_point {
 6432                            let offset = text::ToOffset::to_offset(&range.start, &snapshot)
 6433                                .saturating_sub(1);
 6434                            start_point =
 6435                                snapshot.clip_point(TP::to_point(&offset, &snapshot), Bias::Left);
 6436                        };
 6437
 6438                        (start_point..end_point, empty_str.clone())
 6439                    })
 6440                    .sorted_by_key(|(range, _)| range.start)
 6441                    .collect::<Vec<_>>();
 6442                buffer.update(cx, |this, cx| {
 6443                    this.edit(edits, None, cx);
 6444                })
 6445            }
 6446            this.refresh_inline_completion(true, false, window, cx);
 6447            linked_editing_ranges::refresh_linked_ranges(this, window, cx);
 6448        });
 6449    }
 6450
 6451    pub fn delete(&mut self, _: &Delete, window: &mut Window, cx: &mut Context<Self>) {
 6452        self.transact(window, cx, |this, window, cx| {
 6453            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 6454                let line_mode = s.line_mode;
 6455                s.move_with(|map, selection| {
 6456                    if selection.is_empty() && !line_mode {
 6457                        let cursor = movement::right(map, selection.head());
 6458                        selection.end = cursor;
 6459                        selection.reversed = true;
 6460                        selection.goal = SelectionGoal::None;
 6461                    }
 6462                })
 6463            });
 6464            this.insert("", window, cx);
 6465            this.refresh_inline_completion(true, false, window, cx);
 6466        });
 6467    }
 6468
 6469    pub fn tab_prev(&mut self, _: &TabPrev, window: &mut Window, cx: &mut Context<Self>) {
 6470        if self.move_to_prev_snippet_tabstop(window, cx) {
 6471            return;
 6472        }
 6473
 6474        self.outdent(&Outdent, window, cx);
 6475    }
 6476
 6477    pub fn tab(&mut self, _: &Tab, window: &mut Window, cx: &mut Context<Self>) {
 6478        if self.move_to_next_snippet_tabstop(window, cx) || self.read_only(cx) {
 6479            return;
 6480        }
 6481
 6482        let mut selections = self.selections.all_adjusted(cx);
 6483        let buffer = self.buffer.read(cx);
 6484        let snapshot = buffer.snapshot(cx);
 6485        let rows_iter = selections.iter().map(|s| s.head().row);
 6486        let suggested_indents = snapshot.suggested_indents(rows_iter, cx);
 6487
 6488        let mut edits = Vec::new();
 6489        let mut prev_edited_row = 0;
 6490        let mut row_delta = 0;
 6491        for selection in &mut selections {
 6492            if selection.start.row != prev_edited_row {
 6493                row_delta = 0;
 6494            }
 6495            prev_edited_row = selection.end.row;
 6496
 6497            // If the selection is non-empty, then increase the indentation of the selected lines.
 6498            if !selection.is_empty() {
 6499                row_delta =
 6500                    Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
 6501                continue;
 6502            }
 6503
 6504            // If the selection is empty and the cursor is in the leading whitespace before the
 6505            // suggested indentation, then auto-indent the line.
 6506            let cursor = selection.head();
 6507            let current_indent = snapshot.indent_size_for_line(MultiBufferRow(cursor.row));
 6508            if let Some(suggested_indent) =
 6509                suggested_indents.get(&MultiBufferRow(cursor.row)).copied()
 6510            {
 6511                if cursor.column < suggested_indent.len
 6512                    && cursor.column <= current_indent.len
 6513                    && current_indent.len <= suggested_indent.len
 6514                {
 6515                    selection.start = Point::new(cursor.row, suggested_indent.len);
 6516                    selection.end = selection.start;
 6517                    if row_delta == 0 {
 6518                        edits.extend(Buffer::edit_for_indent_size_adjustment(
 6519                            cursor.row,
 6520                            current_indent,
 6521                            suggested_indent,
 6522                        ));
 6523                        row_delta = suggested_indent.len - current_indent.len;
 6524                    }
 6525                    continue;
 6526                }
 6527            }
 6528
 6529            // Otherwise, insert a hard or soft tab.
 6530            let settings = buffer.settings_at(cursor, cx);
 6531            let tab_size = if settings.hard_tabs {
 6532                IndentSize::tab()
 6533            } else {
 6534                let tab_size = settings.tab_size.get();
 6535                let char_column = snapshot
 6536                    .text_for_range(Point::new(cursor.row, 0)..cursor)
 6537                    .flat_map(str::chars)
 6538                    .count()
 6539                    + row_delta as usize;
 6540                let chars_to_next_tab_stop = tab_size - (char_column as u32 % tab_size);
 6541                IndentSize::spaces(chars_to_next_tab_stop)
 6542            };
 6543            selection.start = Point::new(cursor.row, cursor.column + row_delta + tab_size.len);
 6544            selection.end = selection.start;
 6545            edits.push((cursor..cursor, tab_size.chars().collect::<String>()));
 6546            row_delta += tab_size.len;
 6547        }
 6548
 6549        self.transact(window, cx, |this, window, cx| {
 6550            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
 6551            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 6552                s.select(selections)
 6553            });
 6554            this.refresh_inline_completion(true, false, window, cx);
 6555        });
 6556    }
 6557
 6558    pub fn indent(&mut self, _: &Indent, window: &mut Window, cx: &mut Context<Self>) {
 6559        if self.read_only(cx) {
 6560            return;
 6561        }
 6562        let mut selections = self.selections.all::<Point>(cx);
 6563        let mut prev_edited_row = 0;
 6564        let mut row_delta = 0;
 6565        let mut edits = Vec::new();
 6566        let buffer = self.buffer.read(cx);
 6567        let snapshot = buffer.snapshot(cx);
 6568        for selection in &mut selections {
 6569            if selection.start.row != prev_edited_row {
 6570                row_delta = 0;
 6571            }
 6572            prev_edited_row = selection.end.row;
 6573
 6574            row_delta =
 6575                Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
 6576        }
 6577
 6578        self.transact(window, cx, |this, window, cx| {
 6579            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
 6580            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 6581                s.select(selections)
 6582            });
 6583        });
 6584    }
 6585
 6586    fn indent_selection(
 6587        buffer: &MultiBuffer,
 6588        snapshot: &MultiBufferSnapshot,
 6589        selection: &mut Selection<Point>,
 6590        edits: &mut Vec<(Range<Point>, String)>,
 6591        delta_for_start_row: u32,
 6592        cx: &App,
 6593    ) -> u32 {
 6594        let settings = buffer.settings_at(selection.start, cx);
 6595        let tab_size = settings.tab_size.get();
 6596        let indent_kind = if settings.hard_tabs {
 6597            IndentKind::Tab
 6598        } else {
 6599            IndentKind::Space
 6600        };
 6601        let mut start_row = selection.start.row;
 6602        let mut end_row = selection.end.row + 1;
 6603
 6604        // If a selection ends at the beginning of a line, don't indent
 6605        // that last line.
 6606        if selection.end.column == 0 && selection.end.row > selection.start.row {
 6607            end_row -= 1;
 6608        }
 6609
 6610        // Avoid re-indenting a row that has already been indented by a
 6611        // previous selection, but still update this selection's column
 6612        // to reflect that indentation.
 6613        if delta_for_start_row > 0 {
 6614            start_row += 1;
 6615            selection.start.column += delta_for_start_row;
 6616            if selection.end.row == selection.start.row {
 6617                selection.end.column += delta_for_start_row;
 6618            }
 6619        }
 6620
 6621        let mut delta_for_end_row = 0;
 6622        let has_multiple_rows = start_row + 1 != end_row;
 6623        for row in start_row..end_row {
 6624            let current_indent = snapshot.indent_size_for_line(MultiBufferRow(row));
 6625            let indent_delta = match (current_indent.kind, indent_kind) {
 6626                (IndentKind::Space, IndentKind::Space) => {
 6627                    let columns_to_next_tab_stop = tab_size - (current_indent.len % tab_size);
 6628                    IndentSize::spaces(columns_to_next_tab_stop)
 6629                }
 6630                (IndentKind::Tab, IndentKind::Space) => IndentSize::spaces(tab_size),
 6631                (_, IndentKind::Tab) => IndentSize::tab(),
 6632            };
 6633
 6634            let start = if has_multiple_rows || current_indent.len < selection.start.column {
 6635                0
 6636            } else {
 6637                selection.start.column
 6638            };
 6639            let row_start = Point::new(row, start);
 6640            edits.push((
 6641                row_start..row_start,
 6642                indent_delta.chars().collect::<String>(),
 6643            ));
 6644
 6645            // Update this selection's endpoints to reflect the indentation.
 6646            if row == selection.start.row {
 6647                selection.start.column += indent_delta.len;
 6648            }
 6649            if row == selection.end.row {
 6650                selection.end.column += indent_delta.len;
 6651                delta_for_end_row = indent_delta.len;
 6652            }
 6653        }
 6654
 6655        if selection.start.row == selection.end.row {
 6656            delta_for_start_row + delta_for_end_row
 6657        } else {
 6658            delta_for_end_row
 6659        }
 6660    }
 6661
 6662    pub fn outdent(&mut self, _: &Outdent, window: &mut Window, cx: &mut Context<Self>) {
 6663        if self.read_only(cx) {
 6664            return;
 6665        }
 6666        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 6667        let selections = self.selections.all::<Point>(cx);
 6668        let mut deletion_ranges = Vec::new();
 6669        let mut last_outdent = None;
 6670        {
 6671            let buffer = self.buffer.read(cx);
 6672            let snapshot = buffer.snapshot(cx);
 6673            for selection in &selections {
 6674                let settings = buffer.settings_at(selection.start, cx);
 6675                let tab_size = settings.tab_size.get();
 6676                let mut rows = selection.spanned_rows(false, &display_map);
 6677
 6678                // Avoid re-outdenting a row that has already been outdented by a
 6679                // previous selection.
 6680                if let Some(last_row) = last_outdent {
 6681                    if last_row == rows.start {
 6682                        rows.start = rows.start.next_row();
 6683                    }
 6684                }
 6685                let has_multiple_rows = rows.len() > 1;
 6686                for row in rows.iter_rows() {
 6687                    let indent_size = snapshot.indent_size_for_line(row);
 6688                    if indent_size.len > 0 {
 6689                        let deletion_len = match indent_size.kind {
 6690                            IndentKind::Space => {
 6691                                let columns_to_prev_tab_stop = indent_size.len % tab_size;
 6692                                if columns_to_prev_tab_stop == 0 {
 6693                                    tab_size
 6694                                } else {
 6695                                    columns_to_prev_tab_stop
 6696                                }
 6697                            }
 6698                            IndentKind::Tab => 1,
 6699                        };
 6700                        let start = if has_multiple_rows
 6701                            || deletion_len > selection.start.column
 6702                            || indent_size.len < selection.start.column
 6703                        {
 6704                            0
 6705                        } else {
 6706                            selection.start.column - deletion_len
 6707                        };
 6708                        deletion_ranges.push(
 6709                            Point::new(row.0, start)..Point::new(row.0, start + deletion_len),
 6710                        );
 6711                        last_outdent = Some(row);
 6712                    }
 6713                }
 6714            }
 6715        }
 6716
 6717        self.transact(window, cx, |this, window, cx| {
 6718            this.buffer.update(cx, |buffer, cx| {
 6719                let empty_str: Arc<str> = Arc::default();
 6720                buffer.edit(
 6721                    deletion_ranges
 6722                        .into_iter()
 6723                        .map(|range| (range, empty_str.clone())),
 6724                    None,
 6725                    cx,
 6726                );
 6727            });
 6728            let selections = this.selections.all::<usize>(cx);
 6729            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 6730                s.select(selections)
 6731            });
 6732        });
 6733    }
 6734
 6735    pub fn autoindent(&mut self, _: &AutoIndent, window: &mut Window, cx: &mut Context<Self>) {
 6736        if self.read_only(cx) {
 6737            return;
 6738        }
 6739        let selections = self
 6740            .selections
 6741            .all::<usize>(cx)
 6742            .into_iter()
 6743            .map(|s| s.range());
 6744
 6745        self.transact(window, cx, |this, window, cx| {
 6746            this.buffer.update(cx, |buffer, cx| {
 6747                buffer.autoindent_ranges(selections, cx);
 6748            });
 6749            let selections = this.selections.all::<usize>(cx);
 6750            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 6751                s.select(selections)
 6752            });
 6753        });
 6754    }
 6755
 6756    pub fn delete_line(&mut self, _: &DeleteLine, window: &mut Window, cx: &mut Context<Self>) {
 6757        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 6758        let selections = self.selections.all::<Point>(cx);
 6759
 6760        let mut new_cursors = Vec::new();
 6761        let mut edit_ranges = Vec::new();
 6762        let mut selections = selections.iter().peekable();
 6763        while let Some(selection) = selections.next() {
 6764            let mut rows = selection.spanned_rows(false, &display_map);
 6765            let goal_display_column = selection.head().to_display_point(&display_map).column();
 6766
 6767            // Accumulate contiguous regions of rows that we want to delete.
 6768            while let Some(next_selection) = selections.peek() {
 6769                let next_rows = next_selection.spanned_rows(false, &display_map);
 6770                if next_rows.start <= rows.end {
 6771                    rows.end = next_rows.end;
 6772                    selections.next().unwrap();
 6773                } else {
 6774                    break;
 6775                }
 6776            }
 6777
 6778            let buffer = &display_map.buffer_snapshot;
 6779            let mut edit_start = Point::new(rows.start.0, 0).to_offset(buffer);
 6780            let edit_end;
 6781            let cursor_buffer_row;
 6782            if buffer.max_point().row >= rows.end.0 {
 6783                // If there's a line after the range, delete the \n from the end of the row range
 6784                // and position the cursor on the next line.
 6785                edit_end = Point::new(rows.end.0, 0).to_offset(buffer);
 6786                cursor_buffer_row = rows.end;
 6787            } else {
 6788                // If there isn't a line after the range, delete the \n from the line before the
 6789                // start of the row range and position the cursor there.
 6790                edit_start = edit_start.saturating_sub(1);
 6791                edit_end = buffer.len();
 6792                cursor_buffer_row = rows.start.previous_row();
 6793            }
 6794
 6795            let mut cursor = Point::new(cursor_buffer_row.0, 0).to_display_point(&display_map);
 6796            *cursor.column_mut() =
 6797                cmp::min(goal_display_column, display_map.line_len(cursor.row()));
 6798
 6799            new_cursors.push((
 6800                selection.id,
 6801                buffer.anchor_after(cursor.to_point(&display_map)),
 6802            ));
 6803            edit_ranges.push(edit_start..edit_end);
 6804        }
 6805
 6806        self.transact(window, cx, |this, window, cx| {
 6807            let buffer = this.buffer.update(cx, |buffer, cx| {
 6808                let empty_str: Arc<str> = Arc::default();
 6809                buffer.edit(
 6810                    edit_ranges
 6811                        .into_iter()
 6812                        .map(|range| (range, empty_str.clone())),
 6813                    None,
 6814                    cx,
 6815                );
 6816                buffer.snapshot(cx)
 6817            });
 6818            let new_selections = new_cursors
 6819                .into_iter()
 6820                .map(|(id, cursor)| {
 6821                    let cursor = cursor.to_point(&buffer);
 6822                    Selection {
 6823                        id,
 6824                        start: cursor,
 6825                        end: cursor,
 6826                        reversed: false,
 6827                        goal: SelectionGoal::None,
 6828                    }
 6829                })
 6830                .collect();
 6831
 6832            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 6833                s.select(new_selections);
 6834            });
 6835        });
 6836    }
 6837
 6838    pub fn join_lines_impl(
 6839        &mut self,
 6840        insert_whitespace: bool,
 6841        window: &mut Window,
 6842        cx: &mut Context<Self>,
 6843    ) {
 6844        if self.read_only(cx) {
 6845            return;
 6846        }
 6847        let mut row_ranges = Vec::<Range<MultiBufferRow>>::new();
 6848        for selection in self.selections.all::<Point>(cx) {
 6849            let start = MultiBufferRow(selection.start.row);
 6850            // Treat single line selections as if they include the next line. Otherwise this action
 6851            // would do nothing for single line selections individual cursors.
 6852            let end = if selection.start.row == selection.end.row {
 6853                MultiBufferRow(selection.start.row + 1)
 6854            } else {
 6855                MultiBufferRow(selection.end.row)
 6856            };
 6857
 6858            if let Some(last_row_range) = row_ranges.last_mut() {
 6859                if start <= last_row_range.end {
 6860                    last_row_range.end = end;
 6861                    continue;
 6862                }
 6863            }
 6864            row_ranges.push(start..end);
 6865        }
 6866
 6867        let snapshot = self.buffer.read(cx).snapshot(cx);
 6868        let mut cursor_positions = Vec::new();
 6869        for row_range in &row_ranges {
 6870            let anchor = snapshot.anchor_before(Point::new(
 6871                row_range.end.previous_row().0,
 6872                snapshot.line_len(row_range.end.previous_row()),
 6873            ));
 6874            cursor_positions.push(anchor..anchor);
 6875        }
 6876
 6877        self.transact(window, cx, |this, window, cx| {
 6878            for row_range in row_ranges.into_iter().rev() {
 6879                for row in row_range.iter_rows().rev() {
 6880                    let end_of_line = Point::new(row.0, snapshot.line_len(row));
 6881                    let next_line_row = row.next_row();
 6882                    let indent = snapshot.indent_size_for_line(next_line_row);
 6883                    let start_of_next_line = Point::new(next_line_row.0, indent.len);
 6884
 6885                    let replace =
 6886                        if snapshot.line_len(next_line_row) > indent.len && insert_whitespace {
 6887                            " "
 6888                        } else {
 6889                            ""
 6890                        };
 6891
 6892                    this.buffer.update(cx, |buffer, cx| {
 6893                        buffer.edit([(end_of_line..start_of_next_line, replace)], None, cx)
 6894                    });
 6895                }
 6896            }
 6897
 6898            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 6899                s.select_anchor_ranges(cursor_positions)
 6900            });
 6901        });
 6902    }
 6903
 6904    pub fn join_lines(&mut self, _: &JoinLines, window: &mut Window, cx: &mut Context<Self>) {
 6905        self.join_lines_impl(true, window, cx);
 6906    }
 6907
 6908    pub fn sort_lines_case_sensitive(
 6909        &mut self,
 6910        _: &SortLinesCaseSensitive,
 6911        window: &mut Window,
 6912        cx: &mut Context<Self>,
 6913    ) {
 6914        self.manipulate_lines(window, cx, |lines| lines.sort())
 6915    }
 6916
 6917    pub fn sort_lines_case_insensitive(
 6918        &mut self,
 6919        _: &SortLinesCaseInsensitive,
 6920        window: &mut Window,
 6921        cx: &mut Context<Self>,
 6922    ) {
 6923        self.manipulate_lines(window, cx, |lines| {
 6924            lines.sort_by_key(|line| line.to_lowercase())
 6925        })
 6926    }
 6927
 6928    pub fn unique_lines_case_insensitive(
 6929        &mut self,
 6930        _: &UniqueLinesCaseInsensitive,
 6931        window: &mut Window,
 6932        cx: &mut Context<Self>,
 6933    ) {
 6934        self.manipulate_lines(window, cx, |lines| {
 6935            let mut seen = HashSet::default();
 6936            lines.retain(|line| seen.insert(line.to_lowercase()));
 6937        })
 6938    }
 6939
 6940    pub fn unique_lines_case_sensitive(
 6941        &mut self,
 6942        _: &UniqueLinesCaseSensitive,
 6943        window: &mut Window,
 6944        cx: &mut Context<Self>,
 6945    ) {
 6946        self.manipulate_lines(window, cx, |lines| {
 6947            let mut seen = HashSet::default();
 6948            lines.retain(|line| seen.insert(*line));
 6949        })
 6950    }
 6951
 6952    pub fn revert_file(&mut self, _: &RevertFile, window: &mut Window, cx: &mut Context<Self>) {
 6953        let mut revert_changes = HashMap::default();
 6954        let snapshot = self.snapshot(window, cx);
 6955        for hunk in snapshot
 6956            .hunks_for_ranges(Some(Point::zero()..snapshot.buffer_snapshot.max_point()).into_iter())
 6957        {
 6958            self.prepare_revert_change(&mut revert_changes, &hunk, cx);
 6959        }
 6960        if !revert_changes.is_empty() {
 6961            self.transact(window, cx, |editor, window, cx| {
 6962                editor.revert(revert_changes, window, cx);
 6963            });
 6964        }
 6965    }
 6966
 6967    pub fn reload_file(&mut self, _: &ReloadFile, window: &mut Window, cx: &mut Context<Self>) {
 6968        let Some(project) = self.project.clone() else {
 6969            return;
 6970        };
 6971        self.reload(project, window, cx)
 6972            .detach_and_notify_err(window, cx);
 6973    }
 6974
 6975    pub fn revert_selected_hunks(
 6976        &mut self,
 6977        _: &RevertSelectedHunks,
 6978        window: &mut Window,
 6979        cx: &mut Context<Self>,
 6980    ) {
 6981        let selections = self.selections.all(cx).into_iter().map(|s| s.range());
 6982        self.discard_hunks_in_ranges(selections, window, cx);
 6983    }
 6984
 6985    fn discard_hunks_in_ranges(
 6986        &mut self,
 6987        ranges: impl Iterator<Item = Range<Point>>,
 6988        window: &mut Window,
 6989        cx: &mut Context<Editor>,
 6990    ) {
 6991        let mut revert_changes = HashMap::default();
 6992        let snapshot = self.snapshot(window, cx);
 6993        for hunk in &snapshot.hunks_for_ranges(ranges) {
 6994            self.prepare_revert_change(&mut revert_changes, &hunk, cx);
 6995        }
 6996        if !revert_changes.is_empty() {
 6997            self.transact(window, cx, |editor, window, cx| {
 6998                editor.revert(revert_changes, window, cx);
 6999            });
 7000        }
 7001    }
 7002
 7003    pub fn open_active_item_in_terminal(
 7004        &mut self,
 7005        _: &OpenInTerminal,
 7006        window: &mut Window,
 7007        cx: &mut Context<Self>,
 7008    ) {
 7009        if let Some(working_directory) = self.active_excerpt(cx).and_then(|(_, buffer, _)| {
 7010            let project_path = buffer.read(cx).project_path(cx)?;
 7011            let project = self.project.as_ref()?.read(cx);
 7012            let entry = project.entry_for_path(&project_path, cx)?;
 7013            let parent = match &entry.canonical_path {
 7014                Some(canonical_path) => canonical_path.to_path_buf(),
 7015                None => project.absolute_path(&project_path, cx)?,
 7016            }
 7017            .parent()?
 7018            .to_path_buf();
 7019            Some(parent)
 7020        }) {
 7021            window.dispatch_action(OpenTerminal { working_directory }.boxed_clone(), cx);
 7022        }
 7023    }
 7024
 7025    pub fn prepare_revert_change(
 7026        &self,
 7027        revert_changes: &mut HashMap<BufferId, Vec<(Range<text::Anchor>, Rope)>>,
 7028        hunk: &MultiBufferDiffHunk,
 7029        cx: &mut App,
 7030    ) -> Option<()> {
 7031        let buffer = self.buffer.read(cx);
 7032        let diff = buffer.diff_for(hunk.buffer_id)?;
 7033        let buffer = buffer.buffer(hunk.buffer_id)?;
 7034        let buffer = buffer.read(cx);
 7035        let original_text = diff
 7036            .read(cx)
 7037            .base_text()
 7038            .as_ref()?
 7039            .as_rope()
 7040            .slice(hunk.diff_base_byte_range.clone());
 7041        let buffer_snapshot = buffer.snapshot();
 7042        let buffer_revert_changes = revert_changes.entry(buffer.remote_id()).or_default();
 7043        if let Err(i) = buffer_revert_changes.binary_search_by(|probe| {
 7044            probe
 7045                .0
 7046                .start
 7047                .cmp(&hunk.buffer_range.start, &buffer_snapshot)
 7048                .then(probe.0.end.cmp(&hunk.buffer_range.end, &buffer_snapshot))
 7049        }) {
 7050            buffer_revert_changes.insert(i, (hunk.buffer_range.clone(), original_text));
 7051            Some(())
 7052        } else {
 7053            None
 7054        }
 7055    }
 7056
 7057    pub fn reverse_lines(&mut self, _: &ReverseLines, window: &mut Window, cx: &mut Context<Self>) {
 7058        self.manipulate_lines(window, cx, |lines| lines.reverse())
 7059    }
 7060
 7061    pub fn shuffle_lines(&mut self, _: &ShuffleLines, window: &mut Window, cx: &mut Context<Self>) {
 7062        self.manipulate_lines(window, cx, |lines| lines.shuffle(&mut thread_rng()))
 7063    }
 7064
 7065    fn manipulate_lines<Fn>(
 7066        &mut self,
 7067        window: &mut Window,
 7068        cx: &mut Context<Self>,
 7069        mut callback: Fn,
 7070    ) where
 7071        Fn: FnMut(&mut Vec<&str>),
 7072    {
 7073        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 7074        let buffer = self.buffer.read(cx).snapshot(cx);
 7075
 7076        let mut edits = Vec::new();
 7077
 7078        let selections = self.selections.all::<Point>(cx);
 7079        let mut selections = selections.iter().peekable();
 7080        let mut contiguous_row_selections = Vec::new();
 7081        let mut new_selections = Vec::new();
 7082        let mut added_lines = 0;
 7083        let mut removed_lines = 0;
 7084
 7085        while let Some(selection) = selections.next() {
 7086            let (start_row, end_row) = consume_contiguous_rows(
 7087                &mut contiguous_row_selections,
 7088                selection,
 7089                &display_map,
 7090                &mut selections,
 7091            );
 7092
 7093            let start_point = Point::new(start_row.0, 0);
 7094            let end_point = Point::new(
 7095                end_row.previous_row().0,
 7096                buffer.line_len(end_row.previous_row()),
 7097            );
 7098            let text = buffer
 7099                .text_for_range(start_point..end_point)
 7100                .collect::<String>();
 7101
 7102            let mut lines = text.split('\n').collect_vec();
 7103
 7104            let lines_before = lines.len();
 7105            callback(&mut lines);
 7106            let lines_after = lines.len();
 7107
 7108            edits.push((start_point..end_point, lines.join("\n")));
 7109
 7110            // Selections must change based on added and removed line count
 7111            let start_row =
 7112                MultiBufferRow(start_point.row + added_lines as u32 - removed_lines as u32);
 7113            let end_row = MultiBufferRow(start_row.0 + lines_after.saturating_sub(1) as u32);
 7114            new_selections.push(Selection {
 7115                id: selection.id,
 7116                start: start_row,
 7117                end: end_row,
 7118                goal: SelectionGoal::None,
 7119                reversed: selection.reversed,
 7120            });
 7121
 7122            if lines_after > lines_before {
 7123                added_lines += lines_after - lines_before;
 7124            } else if lines_before > lines_after {
 7125                removed_lines += lines_before - lines_after;
 7126            }
 7127        }
 7128
 7129        self.transact(window, cx, |this, window, cx| {
 7130            let buffer = this.buffer.update(cx, |buffer, cx| {
 7131                buffer.edit(edits, None, cx);
 7132                buffer.snapshot(cx)
 7133            });
 7134
 7135            // Recalculate offsets on newly edited buffer
 7136            let new_selections = new_selections
 7137                .iter()
 7138                .map(|s| {
 7139                    let start_point = Point::new(s.start.0, 0);
 7140                    let end_point = Point::new(s.end.0, buffer.line_len(s.end));
 7141                    Selection {
 7142                        id: s.id,
 7143                        start: buffer.point_to_offset(start_point),
 7144                        end: buffer.point_to_offset(end_point),
 7145                        goal: s.goal,
 7146                        reversed: s.reversed,
 7147                    }
 7148                })
 7149                .collect();
 7150
 7151            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 7152                s.select(new_selections);
 7153            });
 7154
 7155            this.request_autoscroll(Autoscroll::fit(), cx);
 7156        });
 7157    }
 7158
 7159    pub fn convert_to_upper_case(
 7160        &mut self,
 7161        _: &ConvertToUpperCase,
 7162        window: &mut Window,
 7163        cx: &mut Context<Self>,
 7164    ) {
 7165        self.manipulate_text(window, cx, |text| text.to_uppercase())
 7166    }
 7167
 7168    pub fn convert_to_lower_case(
 7169        &mut self,
 7170        _: &ConvertToLowerCase,
 7171        window: &mut Window,
 7172        cx: &mut Context<Self>,
 7173    ) {
 7174        self.manipulate_text(window, cx, |text| text.to_lowercase())
 7175    }
 7176
 7177    pub fn convert_to_title_case(
 7178        &mut self,
 7179        _: &ConvertToTitleCase,
 7180        window: &mut Window,
 7181        cx: &mut Context<Self>,
 7182    ) {
 7183        self.manipulate_text(window, cx, |text| {
 7184            text.split('\n')
 7185                .map(|line| line.to_case(Case::Title))
 7186                .join("\n")
 7187        })
 7188    }
 7189
 7190    pub fn convert_to_snake_case(
 7191        &mut self,
 7192        _: &ConvertToSnakeCase,
 7193        window: &mut Window,
 7194        cx: &mut Context<Self>,
 7195    ) {
 7196        self.manipulate_text(window, cx, |text| text.to_case(Case::Snake))
 7197    }
 7198
 7199    pub fn convert_to_kebab_case(
 7200        &mut self,
 7201        _: &ConvertToKebabCase,
 7202        window: &mut Window,
 7203        cx: &mut Context<Self>,
 7204    ) {
 7205        self.manipulate_text(window, cx, |text| text.to_case(Case::Kebab))
 7206    }
 7207
 7208    pub fn convert_to_upper_camel_case(
 7209        &mut self,
 7210        _: &ConvertToUpperCamelCase,
 7211        window: &mut Window,
 7212        cx: &mut Context<Self>,
 7213    ) {
 7214        self.manipulate_text(window, cx, |text| {
 7215            text.split('\n')
 7216                .map(|line| line.to_case(Case::UpperCamel))
 7217                .join("\n")
 7218        })
 7219    }
 7220
 7221    pub fn convert_to_lower_camel_case(
 7222        &mut self,
 7223        _: &ConvertToLowerCamelCase,
 7224        window: &mut Window,
 7225        cx: &mut Context<Self>,
 7226    ) {
 7227        self.manipulate_text(window, cx, |text| text.to_case(Case::Camel))
 7228    }
 7229
 7230    pub fn convert_to_opposite_case(
 7231        &mut self,
 7232        _: &ConvertToOppositeCase,
 7233        window: &mut Window,
 7234        cx: &mut Context<Self>,
 7235    ) {
 7236        self.manipulate_text(window, cx, |text| {
 7237            text.chars()
 7238                .fold(String::with_capacity(text.len()), |mut t, c| {
 7239                    if c.is_uppercase() {
 7240                        t.extend(c.to_lowercase());
 7241                    } else {
 7242                        t.extend(c.to_uppercase());
 7243                    }
 7244                    t
 7245                })
 7246        })
 7247    }
 7248
 7249    fn manipulate_text<Fn>(&mut self, window: &mut Window, cx: &mut Context<Self>, mut callback: Fn)
 7250    where
 7251        Fn: FnMut(&str) -> String,
 7252    {
 7253        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 7254        let buffer = self.buffer.read(cx).snapshot(cx);
 7255
 7256        let mut new_selections = Vec::new();
 7257        let mut edits = Vec::new();
 7258        let mut selection_adjustment = 0i32;
 7259
 7260        for selection in self.selections.all::<usize>(cx) {
 7261            let selection_is_empty = selection.is_empty();
 7262
 7263            let (start, end) = if selection_is_empty {
 7264                let word_range = movement::surrounding_word(
 7265                    &display_map,
 7266                    selection.start.to_display_point(&display_map),
 7267                );
 7268                let start = word_range.start.to_offset(&display_map, Bias::Left);
 7269                let end = word_range.end.to_offset(&display_map, Bias::Left);
 7270                (start, end)
 7271            } else {
 7272                (selection.start, selection.end)
 7273            };
 7274
 7275            let text = buffer.text_for_range(start..end).collect::<String>();
 7276            let old_length = text.len() as i32;
 7277            let text = callback(&text);
 7278
 7279            new_selections.push(Selection {
 7280                start: (start as i32 - selection_adjustment) as usize,
 7281                end: ((start + text.len()) as i32 - selection_adjustment) as usize,
 7282                goal: SelectionGoal::None,
 7283                ..selection
 7284            });
 7285
 7286            selection_adjustment += old_length - text.len() as i32;
 7287
 7288            edits.push((start..end, text));
 7289        }
 7290
 7291        self.transact(window, cx, |this, window, cx| {
 7292            this.buffer.update(cx, |buffer, cx| {
 7293                buffer.edit(edits, None, cx);
 7294            });
 7295
 7296            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 7297                s.select(new_selections);
 7298            });
 7299
 7300            this.request_autoscroll(Autoscroll::fit(), cx);
 7301        });
 7302    }
 7303
 7304    pub fn duplicate(
 7305        &mut self,
 7306        upwards: bool,
 7307        whole_lines: bool,
 7308        window: &mut Window,
 7309        cx: &mut Context<Self>,
 7310    ) {
 7311        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 7312        let buffer = &display_map.buffer_snapshot;
 7313        let selections = self.selections.all::<Point>(cx);
 7314
 7315        let mut edits = Vec::new();
 7316        let mut selections_iter = selections.iter().peekable();
 7317        while let Some(selection) = selections_iter.next() {
 7318            let mut rows = selection.spanned_rows(false, &display_map);
 7319            // duplicate line-wise
 7320            if whole_lines || selection.start == selection.end {
 7321                // Avoid duplicating the same lines twice.
 7322                while let Some(next_selection) = selections_iter.peek() {
 7323                    let next_rows = next_selection.spanned_rows(false, &display_map);
 7324                    if next_rows.start < rows.end {
 7325                        rows.end = next_rows.end;
 7326                        selections_iter.next().unwrap();
 7327                    } else {
 7328                        break;
 7329                    }
 7330                }
 7331
 7332                // Copy the text from the selected row region and splice it either at the start
 7333                // or end of the region.
 7334                let start = Point::new(rows.start.0, 0);
 7335                let end = Point::new(
 7336                    rows.end.previous_row().0,
 7337                    buffer.line_len(rows.end.previous_row()),
 7338                );
 7339                let text = buffer
 7340                    .text_for_range(start..end)
 7341                    .chain(Some("\n"))
 7342                    .collect::<String>();
 7343                let insert_location = if upwards {
 7344                    Point::new(rows.end.0, 0)
 7345                } else {
 7346                    start
 7347                };
 7348                edits.push((insert_location..insert_location, text));
 7349            } else {
 7350                // duplicate character-wise
 7351                let start = selection.start;
 7352                let end = selection.end;
 7353                let text = buffer.text_for_range(start..end).collect::<String>();
 7354                edits.push((selection.end..selection.end, text));
 7355            }
 7356        }
 7357
 7358        self.transact(window, cx, |this, _, cx| {
 7359            this.buffer.update(cx, |buffer, cx| {
 7360                buffer.edit(edits, None, cx);
 7361            });
 7362
 7363            this.request_autoscroll(Autoscroll::fit(), cx);
 7364        });
 7365    }
 7366
 7367    pub fn duplicate_line_up(
 7368        &mut self,
 7369        _: &DuplicateLineUp,
 7370        window: &mut Window,
 7371        cx: &mut Context<Self>,
 7372    ) {
 7373        self.duplicate(true, true, window, cx);
 7374    }
 7375
 7376    pub fn duplicate_line_down(
 7377        &mut self,
 7378        _: &DuplicateLineDown,
 7379        window: &mut Window,
 7380        cx: &mut Context<Self>,
 7381    ) {
 7382        self.duplicate(false, true, window, cx);
 7383    }
 7384
 7385    pub fn duplicate_selection(
 7386        &mut self,
 7387        _: &DuplicateSelection,
 7388        window: &mut Window,
 7389        cx: &mut Context<Self>,
 7390    ) {
 7391        self.duplicate(false, false, window, cx);
 7392    }
 7393
 7394    pub fn move_line_up(&mut self, _: &MoveLineUp, window: &mut Window, cx: &mut Context<Self>) {
 7395        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 7396        let buffer = self.buffer.read(cx).snapshot(cx);
 7397
 7398        let mut edits = Vec::new();
 7399        let mut unfold_ranges = Vec::new();
 7400        let mut refold_creases = Vec::new();
 7401
 7402        let selections = self.selections.all::<Point>(cx);
 7403        let mut selections = selections.iter().peekable();
 7404        let mut contiguous_row_selections = Vec::new();
 7405        let mut new_selections = Vec::new();
 7406
 7407        while let Some(selection) = selections.next() {
 7408            // Find all the selections that span a contiguous row range
 7409            let (start_row, end_row) = consume_contiguous_rows(
 7410                &mut contiguous_row_selections,
 7411                selection,
 7412                &display_map,
 7413                &mut selections,
 7414            );
 7415
 7416            // Move the text spanned by the row range to be before the line preceding the row range
 7417            if start_row.0 > 0 {
 7418                let range_to_move = Point::new(
 7419                    start_row.previous_row().0,
 7420                    buffer.line_len(start_row.previous_row()),
 7421                )
 7422                    ..Point::new(
 7423                        end_row.previous_row().0,
 7424                        buffer.line_len(end_row.previous_row()),
 7425                    );
 7426                let insertion_point = display_map
 7427                    .prev_line_boundary(Point::new(start_row.previous_row().0, 0))
 7428                    .0;
 7429
 7430                // Don't move lines across excerpts
 7431                if buffer
 7432                    .excerpt_containing(insertion_point..range_to_move.end)
 7433                    .is_some()
 7434                {
 7435                    let text = buffer
 7436                        .text_for_range(range_to_move.clone())
 7437                        .flat_map(|s| s.chars())
 7438                        .skip(1)
 7439                        .chain(['\n'])
 7440                        .collect::<String>();
 7441
 7442                    edits.push((
 7443                        buffer.anchor_after(range_to_move.start)
 7444                            ..buffer.anchor_before(range_to_move.end),
 7445                        String::new(),
 7446                    ));
 7447                    let insertion_anchor = buffer.anchor_after(insertion_point);
 7448                    edits.push((insertion_anchor..insertion_anchor, text));
 7449
 7450                    let row_delta = range_to_move.start.row - insertion_point.row + 1;
 7451
 7452                    // Move selections up
 7453                    new_selections.extend(contiguous_row_selections.drain(..).map(
 7454                        |mut selection| {
 7455                            selection.start.row -= row_delta;
 7456                            selection.end.row -= row_delta;
 7457                            selection
 7458                        },
 7459                    ));
 7460
 7461                    // Move folds up
 7462                    unfold_ranges.push(range_to_move.clone());
 7463                    for fold in display_map.folds_in_range(
 7464                        buffer.anchor_before(range_to_move.start)
 7465                            ..buffer.anchor_after(range_to_move.end),
 7466                    ) {
 7467                        let mut start = fold.range.start.to_point(&buffer);
 7468                        let mut end = fold.range.end.to_point(&buffer);
 7469                        start.row -= row_delta;
 7470                        end.row -= row_delta;
 7471                        refold_creases.push(Crease::simple(start..end, fold.placeholder.clone()));
 7472                    }
 7473                }
 7474            }
 7475
 7476            // If we didn't move line(s), preserve the existing selections
 7477            new_selections.append(&mut contiguous_row_selections);
 7478        }
 7479
 7480        self.transact(window, cx, |this, window, cx| {
 7481            this.unfold_ranges(&unfold_ranges, true, true, cx);
 7482            this.buffer.update(cx, |buffer, cx| {
 7483                for (range, text) in edits {
 7484                    buffer.edit([(range, text)], None, cx);
 7485                }
 7486            });
 7487            this.fold_creases(refold_creases, true, window, cx);
 7488            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 7489                s.select(new_selections);
 7490            })
 7491        });
 7492    }
 7493
 7494    pub fn move_line_down(
 7495        &mut self,
 7496        _: &MoveLineDown,
 7497        window: &mut Window,
 7498        cx: &mut Context<Self>,
 7499    ) {
 7500        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 7501        let buffer = self.buffer.read(cx).snapshot(cx);
 7502
 7503        let mut edits = Vec::new();
 7504        let mut unfold_ranges = Vec::new();
 7505        let mut refold_creases = Vec::new();
 7506
 7507        let selections = self.selections.all::<Point>(cx);
 7508        let mut selections = selections.iter().peekable();
 7509        let mut contiguous_row_selections = Vec::new();
 7510        let mut new_selections = Vec::new();
 7511
 7512        while let Some(selection) = selections.next() {
 7513            // Find all the selections that span a contiguous row range
 7514            let (start_row, end_row) = consume_contiguous_rows(
 7515                &mut contiguous_row_selections,
 7516                selection,
 7517                &display_map,
 7518                &mut selections,
 7519            );
 7520
 7521            // Move the text spanned by the row range to be after the last line of the row range
 7522            if end_row.0 <= buffer.max_point().row {
 7523                let range_to_move =
 7524                    MultiBufferPoint::new(start_row.0, 0)..MultiBufferPoint::new(end_row.0, 0);
 7525                let insertion_point = display_map
 7526                    .next_line_boundary(MultiBufferPoint::new(end_row.0, 0))
 7527                    .0;
 7528
 7529                // Don't move lines across excerpt boundaries
 7530                if buffer
 7531                    .excerpt_containing(range_to_move.start..insertion_point)
 7532                    .is_some()
 7533                {
 7534                    let mut text = String::from("\n");
 7535                    text.extend(buffer.text_for_range(range_to_move.clone()));
 7536                    text.pop(); // Drop trailing newline
 7537                    edits.push((
 7538                        buffer.anchor_after(range_to_move.start)
 7539                            ..buffer.anchor_before(range_to_move.end),
 7540                        String::new(),
 7541                    ));
 7542                    let insertion_anchor = buffer.anchor_after(insertion_point);
 7543                    edits.push((insertion_anchor..insertion_anchor, text));
 7544
 7545                    let row_delta = insertion_point.row - range_to_move.end.row + 1;
 7546
 7547                    // Move selections down
 7548                    new_selections.extend(contiguous_row_selections.drain(..).map(
 7549                        |mut selection| {
 7550                            selection.start.row += row_delta;
 7551                            selection.end.row += row_delta;
 7552                            selection
 7553                        },
 7554                    ));
 7555
 7556                    // Move folds down
 7557                    unfold_ranges.push(range_to_move.clone());
 7558                    for fold in display_map.folds_in_range(
 7559                        buffer.anchor_before(range_to_move.start)
 7560                            ..buffer.anchor_after(range_to_move.end),
 7561                    ) {
 7562                        let mut start = fold.range.start.to_point(&buffer);
 7563                        let mut end = fold.range.end.to_point(&buffer);
 7564                        start.row += row_delta;
 7565                        end.row += row_delta;
 7566                        refold_creases.push(Crease::simple(start..end, fold.placeholder.clone()));
 7567                    }
 7568                }
 7569            }
 7570
 7571            // If we didn't move line(s), preserve the existing selections
 7572            new_selections.append(&mut contiguous_row_selections);
 7573        }
 7574
 7575        self.transact(window, cx, |this, window, cx| {
 7576            this.unfold_ranges(&unfold_ranges, true, true, cx);
 7577            this.buffer.update(cx, |buffer, cx| {
 7578                for (range, text) in edits {
 7579                    buffer.edit([(range, text)], None, cx);
 7580                }
 7581            });
 7582            this.fold_creases(refold_creases, true, window, cx);
 7583            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 7584                s.select(new_selections)
 7585            });
 7586        });
 7587    }
 7588
 7589    pub fn transpose(&mut self, _: &Transpose, window: &mut Window, cx: &mut Context<Self>) {
 7590        let text_layout_details = &self.text_layout_details(window);
 7591        self.transact(window, cx, |this, window, cx| {
 7592            let edits = this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 7593                let mut edits: Vec<(Range<usize>, String)> = Default::default();
 7594                let line_mode = s.line_mode;
 7595                s.move_with(|display_map, selection| {
 7596                    if !selection.is_empty() || line_mode {
 7597                        return;
 7598                    }
 7599
 7600                    let mut head = selection.head();
 7601                    let mut transpose_offset = head.to_offset(display_map, Bias::Right);
 7602                    if head.column() == display_map.line_len(head.row()) {
 7603                        transpose_offset = display_map
 7604                            .buffer_snapshot
 7605                            .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
 7606                    }
 7607
 7608                    if transpose_offset == 0 {
 7609                        return;
 7610                    }
 7611
 7612                    *head.column_mut() += 1;
 7613                    head = display_map.clip_point(head, Bias::Right);
 7614                    let goal = SelectionGoal::HorizontalPosition(
 7615                        display_map
 7616                            .x_for_display_point(head, text_layout_details)
 7617                            .into(),
 7618                    );
 7619                    selection.collapse_to(head, goal);
 7620
 7621                    let transpose_start = display_map
 7622                        .buffer_snapshot
 7623                        .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
 7624                    if edits.last().map_or(true, |e| e.0.end <= transpose_start) {
 7625                        let transpose_end = display_map
 7626                            .buffer_snapshot
 7627                            .clip_offset(transpose_offset + 1, Bias::Right);
 7628                        if let Some(ch) =
 7629                            display_map.buffer_snapshot.chars_at(transpose_start).next()
 7630                        {
 7631                            edits.push((transpose_start..transpose_offset, String::new()));
 7632                            edits.push((transpose_end..transpose_end, ch.to_string()));
 7633                        }
 7634                    }
 7635                });
 7636                edits
 7637            });
 7638            this.buffer
 7639                .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
 7640            let selections = this.selections.all::<usize>(cx);
 7641            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 7642                s.select(selections);
 7643            });
 7644        });
 7645    }
 7646
 7647    pub fn rewrap(&mut self, _: &Rewrap, _: &mut Window, cx: &mut Context<Self>) {
 7648        self.rewrap_impl(IsVimMode::No, cx)
 7649    }
 7650
 7651    pub fn rewrap_impl(&mut self, is_vim_mode: IsVimMode, cx: &mut Context<Self>) {
 7652        let buffer = self.buffer.read(cx).snapshot(cx);
 7653        let selections = self.selections.all::<Point>(cx);
 7654        let mut selections = selections.iter().peekable();
 7655
 7656        let mut edits = Vec::new();
 7657        let mut rewrapped_row_ranges = Vec::<RangeInclusive<u32>>::new();
 7658
 7659        while let Some(selection) = selections.next() {
 7660            let mut start_row = selection.start.row;
 7661            let mut end_row = selection.end.row;
 7662
 7663            // Skip selections that overlap with a range that has already been rewrapped.
 7664            let selection_range = start_row..end_row;
 7665            if rewrapped_row_ranges
 7666                .iter()
 7667                .any(|range| range.overlaps(&selection_range))
 7668            {
 7669                continue;
 7670            }
 7671
 7672            let mut should_rewrap = is_vim_mode == IsVimMode::Yes;
 7673
 7674            if let Some(language_scope) = buffer.language_scope_at(selection.head()) {
 7675                match language_scope.language_name().as_ref() {
 7676                    "Markdown" | "Plain Text" => {
 7677                        should_rewrap = true;
 7678                    }
 7679                    _ => {}
 7680                }
 7681            }
 7682
 7683            let tab_size = buffer.settings_at(selection.head(), cx).tab_size;
 7684
 7685            // Since not all lines in the selection may be at the same indent
 7686            // level, choose the indent size that is the most common between all
 7687            // of the lines.
 7688            //
 7689            // If there is a tie, we use the deepest indent.
 7690            let (indent_size, indent_end) = {
 7691                let mut indent_size_occurrences = HashMap::default();
 7692                let mut rows_by_indent_size = HashMap::<IndentSize, Vec<u32>>::default();
 7693
 7694                for row in start_row..=end_row {
 7695                    let indent = buffer.indent_size_for_line(MultiBufferRow(row));
 7696                    rows_by_indent_size.entry(indent).or_default().push(row);
 7697                    *indent_size_occurrences.entry(indent).or_insert(0) += 1;
 7698                }
 7699
 7700                let indent_size = indent_size_occurrences
 7701                    .into_iter()
 7702                    .max_by_key(|(indent, count)| (*count, indent.len_with_expanded_tabs(tab_size)))
 7703                    .map(|(indent, _)| indent)
 7704                    .unwrap_or_default();
 7705                let row = rows_by_indent_size[&indent_size][0];
 7706                let indent_end = Point::new(row, indent_size.len);
 7707
 7708                (indent_size, indent_end)
 7709            };
 7710
 7711            let mut line_prefix = indent_size.chars().collect::<String>();
 7712
 7713            if let Some(comment_prefix) =
 7714                buffer
 7715                    .language_scope_at(selection.head())
 7716                    .and_then(|language| {
 7717                        language
 7718                            .line_comment_prefixes()
 7719                            .iter()
 7720                            .find(|prefix| buffer.contains_str_at(indent_end, prefix))
 7721                            .cloned()
 7722                    })
 7723            {
 7724                line_prefix.push_str(&comment_prefix);
 7725                should_rewrap = true;
 7726            }
 7727
 7728            if !should_rewrap {
 7729                continue;
 7730            }
 7731
 7732            if selection.is_empty() {
 7733                'expand_upwards: while start_row > 0 {
 7734                    let prev_row = start_row - 1;
 7735                    if buffer.contains_str_at(Point::new(prev_row, 0), &line_prefix)
 7736                        && buffer.line_len(MultiBufferRow(prev_row)) as usize > line_prefix.len()
 7737                    {
 7738                        start_row = prev_row;
 7739                    } else {
 7740                        break 'expand_upwards;
 7741                    }
 7742                }
 7743
 7744                'expand_downwards: while end_row < buffer.max_point().row {
 7745                    let next_row = end_row + 1;
 7746                    if buffer.contains_str_at(Point::new(next_row, 0), &line_prefix)
 7747                        && buffer.line_len(MultiBufferRow(next_row)) as usize > line_prefix.len()
 7748                    {
 7749                        end_row = next_row;
 7750                    } else {
 7751                        break 'expand_downwards;
 7752                    }
 7753                }
 7754            }
 7755
 7756            let start = Point::new(start_row, 0);
 7757            let end = Point::new(end_row, buffer.line_len(MultiBufferRow(end_row)));
 7758            let selection_text = buffer.text_for_range(start..end).collect::<String>();
 7759            let Some(lines_without_prefixes) = selection_text
 7760                .lines()
 7761                .map(|line| {
 7762                    line.strip_prefix(&line_prefix)
 7763                        .or_else(|| line.trim_start().strip_prefix(&line_prefix.trim_start()))
 7764                        .ok_or_else(|| {
 7765                            anyhow!("line did not start with prefix {line_prefix:?}: {line:?}")
 7766                        })
 7767                })
 7768                .collect::<Result<Vec<_>, _>>()
 7769                .log_err()
 7770            else {
 7771                continue;
 7772            };
 7773
 7774            let wrap_column = buffer
 7775                .settings_at(Point::new(start_row, 0), cx)
 7776                .preferred_line_length as usize;
 7777            let wrapped_text = wrap_with_prefix(
 7778                line_prefix,
 7779                lines_without_prefixes.join(" "),
 7780                wrap_column,
 7781                tab_size,
 7782            );
 7783
 7784            // TODO: should always use char-based diff while still supporting cursor behavior that
 7785            // matches vim.
 7786            let diff = match is_vim_mode {
 7787                IsVimMode::Yes => TextDiff::from_lines(&selection_text, &wrapped_text),
 7788                IsVimMode::No => TextDiff::from_chars(&selection_text, &wrapped_text),
 7789            };
 7790            let mut offset = start.to_offset(&buffer);
 7791            let mut moved_since_edit = true;
 7792
 7793            for change in diff.iter_all_changes() {
 7794                let value = change.value();
 7795                match change.tag() {
 7796                    ChangeTag::Equal => {
 7797                        offset += value.len();
 7798                        moved_since_edit = true;
 7799                    }
 7800                    ChangeTag::Delete => {
 7801                        let start = buffer.anchor_after(offset);
 7802                        let end = buffer.anchor_before(offset + value.len());
 7803
 7804                        if moved_since_edit {
 7805                            edits.push((start..end, String::new()));
 7806                        } else {
 7807                            edits.last_mut().unwrap().0.end = end;
 7808                        }
 7809
 7810                        offset += value.len();
 7811                        moved_since_edit = false;
 7812                    }
 7813                    ChangeTag::Insert => {
 7814                        if moved_since_edit {
 7815                            let anchor = buffer.anchor_after(offset);
 7816                            edits.push((anchor..anchor, value.to_string()));
 7817                        } else {
 7818                            edits.last_mut().unwrap().1.push_str(value);
 7819                        }
 7820
 7821                        moved_since_edit = false;
 7822                    }
 7823                }
 7824            }
 7825
 7826            rewrapped_row_ranges.push(start_row..=end_row);
 7827        }
 7828
 7829        self.buffer
 7830            .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
 7831    }
 7832
 7833    pub fn cut_common(&mut self, window: &mut Window, cx: &mut Context<Self>) -> ClipboardItem {
 7834        let mut text = String::new();
 7835        let buffer = self.buffer.read(cx).snapshot(cx);
 7836        let mut selections = self.selections.all::<Point>(cx);
 7837        let mut clipboard_selections = Vec::with_capacity(selections.len());
 7838        {
 7839            let max_point = buffer.max_point();
 7840            let mut is_first = true;
 7841            for selection in &mut selections {
 7842                let is_entire_line = selection.is_empty() || self.selections.line_mode;
 7843                if is_entire_line {
 7844                    selection.start = Point::new(selection.start.row, 0);
 7845                    if !selection.is_empty() && selection.end.column == 0 {
 7846                        selection.end = cmp::min(max_point, selection.end);
 7847                    } else {
 7848                        selection.end = cmp::min(max_point, Point::new(selection.end.row + 1, 0));
 7849                    }
 7850                    selection.goal = SelectionGoal::None;
 7851                }
 7852                if is_first {
 7853                    is_first = false;
 7854                } else {
 7855                    text += "\n";
 7856                }
 7857                let mut len = 0;
 7858                for chunk in buffer.text_for_range(selection.start..selection.end) {
 7859                    text.push_str(chunk);
 7860                    len += chunk.len();
 7861                }
 7862                clipboard_selections.push(ClipboardSelection {
 7863                    len,
 7864                    is_entire_line,
 7865                    first_line_indent: buffer
 7866                        .indent_size_for_line(MultiBufferRow(selection.start.row))
 7867                        .len,
 7868                });
 7869            }
 7870        }
 7871
 7872        self.transact(window, cx, |this, window, cx| {
 7873            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 7874                s.select(selections);
 7875            });
 7876            this.insert("", window, cx);
 7877        });
 7878        ClipboardItem::new_string_with_json_metadata(text, clipboard_selections)
 7879    }
 7880
 7881    pub fn cut(&mut self, _: &Cut, window: &mut Window, cx: &mut Context<Self>) {
 7882        let item = self.cut_common(window, cx);
 7883        cx.write_to_clipboard(item);
 7884    }
 7885
 7886    pub fn kill_ring_cut(&mut self, _: &KillRingCut, window: &mut Window, cx: &mut Context<Self>) {
 7887        self.change_selections(None, window, cx, |s| {
 7888            s.move_with(|snapshot, sel| {
 7889                if sel.is_empty() {
 7890                    sel.end = DisplayPoint::new(sel.end.row(), snapshot.line_len(sel.end.row()))
 7891                }
 7892            });
 7893        });
 7894        let item = self.cut_common(window, cx);
 7895        cx.set_global(KillRing(item))
 7896    }
 7897
 7898    pub fn kill_ring_yank(
 7899        &mut self,
 7900        _: &KillRingYank,
 7901        window: &mut Window,
 7902        cx: &mut Context<Self>,
 7903    ) {
 7904        let (text, metadata) = if let Some(KillRing(item)) = cx.try_global() {
 7905            if let Some(ClipboardEntry::String(kill_ring)) = item.entries().first() {
 7906                (kill_ring.text().to_string(), kill_ring.metadata_json())
 7907            } else {
 7908                return;
 7909            }
 7910        } else {
 7911            return;
 7912        };
 7913        self.do_paste(&text, metadata, false, window, cx);
 7914    }
 7915
 7916    pub fn copy(&mut self, _: &Copy, _: &mut Window, cx: &mut Context<Self>) {
 7917        let selections = self.selections.all::<Point>(cx);
 7918        let buffer = self.buffer.read(cx).read(cx);
 7919        let mut text = String::new();
 7920
 7921        let mut clipboard_selections = Vec::with_capacity(selections.len());
 7922        {
 7923            let max_point = buffer.max_point();
 7924            let mut is_first = true;
 7925            for selection in selections.iter() {
 7926                let mut start = selection.start;
 7927                let mut end = selection.end;
 7928                let is_entire_line = selection.is_empty() || self.selections.line_mode;
 7929                if is_entire_line {
 7930                    start = Point::new(start.row, 0);
 7931                    end = cmp::min(max_point, Point::new(end.row + 1, 0));
 7932                }
 7933                if is_first {
 7934                    is_first = false;
 7935                } else {
 7936                    text += "\n";
 7937                }
 7938                let mut len = 0;
 7939                for chunk in buffer.text_for_range(start..end) {
 7940                    text.push_str(chunk);
 7941                    len += chunk.len();
 7942                }
 7943                clipboard_selections.push(ClipboardSelection {
 7944                    len,
 7945                    is_entire_line,
 7946                    first_line_indent: buffer.indent_size_for_line(MultiBufferRow(start.row)).len,
 7947                });
 7948            }
 7949        }
 7950
 7951        cx.write_to_clipboard(ClipboardItem::new_string_with_json_metadata(
 7952            text,
 7953            clipboard_selections,
 7954        ));
 7955    }
 7956
 7957    pub fn do_paste(
 7958        &mut self,
 7959        text: &String,
 7960        clipboard_selections: Option<Vec<ClipboardSelection>>,
 7961        handle_entire_lines: bool,
 7962        window: &mut Window,
 7963        cx: &mut Context<Self>,
 7964    ) {
 7965        if self.read_only(cx) {
 7966            return;
 7967        }
 7968
 7969        let clipboard_text = Cow::Borrowed(text);
 7970
 7971        self.transact(window, cx, |this, window, cx| {
 7972            if let Some(mut clipboard_selections) = clipboard_selections {
 7973                let old_selections = this.selections.all::<usize>(cx);
 7974                let all_selections_were_entire_line =
 7975                    clipboard_selections.iter().all(|s| s.is_entire_line);
 7976                let first_selection_indent_column =
 7977                    clipboard_selections.first().map(|s| s.first_line_indent);
 7978                if clipboard_selections.len() != old_selections.len() {
 7979                    clipboard_selections.drain(..);
 7980                }
 7981                let cursor_offset = this.selections.last::<usize>(cx).head();
 7982                let mut auto_indent_on_paste = true;
 7983
 7984                this.buffer.update(cx, |buffer, cx| {
 7985                    let snapshot = buffer.read(cx);
 7986                    auto_indent_on_paste =
 7987                        snapshot.settings_at(cursor_offset, cx).auto_indent_on_paste;
 7988
 7989                    let mut start_offset = 0;
 7990                    let mut edits = Vec::new();
 7991                    let mut original_indent_columns = Vec::new();
 7992                    for (ix, selection) in old_selections.iter().enumerate() {
 7993                        let to_insert;
 7994                        let entire_line;
 7995                        let original_indent_column;
 7996                        if let Some(clipboard_selection) = clipboard_selections.get(ix) {
 7997                            let end_offset = start_offset + clipboard_selection.len;
 7998                            to_insert = &clipboard_text[start_offset..end_offset];
 7999                            entire_line = clipboard_selection.is_entire_line;
 8000                            start_offset = end_offset + 1;
 8001                            original_indent_column = Some(clipboard_selection.first_line_indent);
 8002                        } else {
 8003                            to_insert = clipboard_text.as_str();
 8004                            entire_line = all_selections_were_entire_line;
 8005                            original_indent_column = first_selection_indent_column
 8006                        }
 8007
 8008                        // If the corresponding selection was empty when this slice of the
 8009                        // clipboard text was written, then the entire line containing the
 8010                        // selection was copied. If this selection is also currently empty,
 8011                        // then paste the line before the current line of the buffer.
 8012                        let range = if selection.is_empty() && handle_entire_lines && entire_line {
 8013                            let column = selection.start.to_point(&snapshot).column as usize;
 8014                            let line_start = selection.start - column;
 8015                            line_start..line_start
 8016                        } else {
 8017                            selection.range()
 8018                        };
 8019
 8020                        edits.push((range, to_insert));
 8021                        original_indent_columns.extend(original_indent_column);
 8022                    }
 8023                    drop(snapshot);
 8024
 8025                    buffer.edit(
 8026                        edits,
 8027                        if auto_indent_on_paste {
 8028                            Some(AutoindentMode::Block {
 8029                                original_indent_columns,
 8030                            })
 8031                        } else {
 8032                            None
 8033                        },
 8034                        cx,
 8035                    );
 8036                });
 8037
 8038                let selections = this.selections.all::<usize>(cx);
 8039                this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8040                    s.select(selections)
 8041                });
 8042            } else {
 8043                this.insert(&clipboard_text, window, cx);
 8044            }
 8045        });
 8046    }
 8047
 8048    pub fn paste(&mut self, _: &Paste, window: &mut Window, cx: &mut Context<Self>) {
 8049        if let Some(item) = cx.read_from_clipboard() {
 8050            let entries = item.entries();
 8051
 8052            match entries.first() {
 8053                // For now, we only support applying metadata if there's one string. In the future, we can incorporate all the selections
 8054                // of all the pasted entries.
 8055                Some(ClipboardEntry::String(clipboard_string)) if entries.len() == 1 => self
 8056                    .do_paste(
 8057                        clipboard_string.text(),
 8058                        clipboard_string.metadata_json::<Vec<ClipboardSelection>>(),
 8059                        true,
 8060                        window,
 8061                        cx,
 8062                    ),
 8063                _ => self.do_paste(&item.text().unwrap_or_default(), None, true, window, cx),
 8064            }
 8065        }
 8066    }
 8067
 8068    pub fn undo(&mut self, _: &Undo, window: &mut Window, cx: &mut Context<Self>) {
 8069        if self.read_only(cx) {
 8070            return;
 8071        }
 8072
 8073        if let Some(transaction_id) = self.buffer.update(cx, |buffer, cx| buffer.undo(cx)) {
 8074            if let Some((selections, _)) =
 8075                self.selection_history.transaction(transaction_id).cloned()
 8076            {
 8077                self.change_selections(None, window, cx, |s| {
 8078                    s.select_anchors(selections.to_vec());
 8079                });
 8080            }
 8081            self.request_autoscroll(Autoscroll::fit(), cx);
 8082            self.unmark_text(window, cx);
 8083            self.refresh_inline_completion(true, false, window, cx);
 8084            cx.emit(EditorEvent::Edited { transaction_id });
 8085            cx.emit(EditorEvent::TransactionUndone { transaction_id });
 8086        }
 8087    }
 8088
 8089    pub fn redo(&mut self, _: &Redo, window: &mut Window, cx: &mut Context<Self>) {
 8090        if self.read_only(cx) {
 8091            return;
 8092        }
 8093
 8094        if let Some(transaction_id) = self.buffer.update(cx, |buffer, cx| buffer.redo(cx)) {
 8095            if let Some((_, Some(selections))) =
 8096                self.selection_history.transaction(transaction_id).cloned()
 8097            {
 8098                self.change_selections(None, window, cx, |s| {
 8099                    s.select_anchors(selections.to_vec());
 8100                });
 8101            }
 8102            self.request_autoscroll(Autoscroll::fit(), cx);
 8103            self.unmark_text(window, cx);
 8104            self.refresh_inline_completion(true, false, window, cx);
 8105            cx.emit(EditorEvent::Edited { transaction_id });
 8106        }
 8107    }
 8108
 8109    pub fn finalize_last_transaction(&mut self, cx: &mut Context<Self>) {
 8110        self.buffer
 8111            .update(cx, |buffer, cx| buffer.finalize_last_transaction(cx));
 8112    }
 8113
 8114    pub fn group_until_transaction(&mut self, tx_id: TransactionId, cx: &mut Context<Self>) {
 8115        self.buffer
 8116            .update(cx, |buffer, cx| buffer.group_until_transaction(tx_id, cx));
 8117    }
 8118
 8119    pub fn move_left(&mut self, _: &MoveLeft, window: &mut Window, cx: &mut Context<Self>) {
 8120        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8121            let line_mode = s.line_mode;
 8122            s.move_with(|map, selection| {
 8123                let cursor = if selection.is_empty() && !line_mode {
 8124                    movement::left(map, selection.start)
 8125                } else {
 8126                    selection.start
 8127                };
 8128                selection.collapse_to(cursor, SelectionGoal::None);
 8129            });
 8130        })
 8131    }
 8132
 8133    pub fn select_left(&mut self, _: &SelectLeft, window: &mut Window, cx: &mut Context<Self>) {
 8134        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8135            s.move_heads_with(|map, head, _| (movement::left(map, head), SelectionGoal::None));
 8136        })
 8137    }
 8138
 8139    pub fn move_right(&mut self, _: &MoveRight, window: &mut Window, cx: &mut Context<Self>) {
 8140        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8141            let line_mode = s.line_mode;
 8142            s.move_with(|map, selection| {
 8143                let cursor = if selection.is_empty() && !line_mode {
 8144                    movement::right(map, selection.end)
 8145                } else {
 8146                    selection.end
 8147                };
 8148                selection.collapse_to(cursor, SelectionGoal::None)
 8149            });
 8150        })
 8151    }
 8152
 8153    pub fn select_right(&mut self, _: &SelectRight, window: &mut Window, cx: &mut Context<Self>) {
 8154        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8155            s.move_heads_with(|map, head, _| (movement::right(map, head), SelectionGoal::None));
 8156        })
 8157    }
 8158
 8159    pub fn move_up(&mut self, _: &MoveUp, window: &mut Window, cx: &mut Context<Self>) {
 8160        if self.take_rename(true, window, cx).is_some() {
 8161            return;
 8162        }
 8163
 8164        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 8165            cx.propagate();
 8166            return;
 8167        }
 8168
 8169        let text_layout_details = &self.text_layout_details(window);
 8170        let selection_count = self.selections.count();
 8171        let first_selection = self.selections.first_anchor();
 8172
 8173        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8174            let line_mode = s.line_mode;
 8175            s.move_with(|map, selection| {
 8176                if !selection.is_empty() && !line_mode {
 8177                    selection.goal = SelectionGoal::None;
 8178                }
 8179                let (cursor, goal) = movement::up(
 8180                    map,
 8181                    selection.start,
 8182                    selection.goal,
 8183                    false,
 8184                    text_layout_details,
 8185                );
 8186                selection.collapse_to(cursor, goal);
 8187            });
 8188        });
 8189
 8190        if selection_count == 1 && first_selection.range() == self.selections.first_anchor().range()
 8191        {
 8192            cx.propagate();
 8193        }
 8194    }
 8195
 8196    pub fn move_up_by_lines(
 8197        &mut self,
 8198        action: &MoveUpByLines,
 8199        window: &mut Window,
 8200        cx: &mut Context<Self>,
 8201    ) {
 8202        if self.take_rename(true, window, cx).is_some() {
 8203            return;
 8204        }
 8205
 8206        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 8207            cx.propagate();
 8208            return;
 8209        }
 8210
 8211        let text_layout_details = &self.text_layout_details(window);
 8212
 8213        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8214            let line_mode = s.line_mode;
 8215            s.move_with(|map, selection| {
 8216                if !selection.is_empty() && !line_mode {
 8217                    selection.goal = SelectionGoal::None;
 8218                }
 8219                let (cursor, goal) = movement::up_by_rows(
 8220                    map,
 8221                    selection.start,
 8222                    action.lines,
 8223                    selection.goal,
 8224                    false,
 8225                    text_layout_details,
 8226                );
 8227                selection.collapse_to(cursor, goal);
 8228            });
 8229        })
 8230    }
 8231
 8232    pub fn move_down_by_lines(
 8233        &mut self,
 8234        action: &MoveDownByLines,
 8235        window: &mut Window,
 8236        cx: &mut Context<Self>,
 8237    ) {
 8238        if self.take_rename(true, window, cx).is_some() {
 8239            return;
 8240        }
 8241
 8242        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 8243            cx.propagate();
 8244            return;
 8245        }
 8246
 8247        let text_layout_details = &self.text_layout_details(window);
 8248
 8249        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8250            let line_mode = s.line_mode;
 8251            s.move_with(|map, selection| {
 8252                if !selection.is_empty() && !line_mode {
 8253                    selection.goal = SelectionGoal::None;
 8254                }
 8255                let (cursor, goal) = movement::down_by_rows(
 8256                    map,
 8257                    selection.start,
 8258                    action.lines,
 8259                    selection.goal,
 8260                    false,
 8261                    text_layout_details,
 8262                );
 8263                selection.collapse_to(cursor, goal);
 8264            });
 8265        })
 8266    }
 8267
 8268    pub fn select_down_by_lines(
 8269        &mut self,
 8270        action: &SelectDownByLines,
 8271        window: &mut Window,
 8272        cx: &mut Context<Self>,
 8273    ) {
 8274        let text_layout_details = &self.text_layout_details(window);
 8275        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8276            s.move_heads_with(|map, head, goal| {
 8277                movement::down_by_rows(map, head, action.lines, goal, false, text_layout_details)
 8278            })
 8279        })
 8280    }
 8281
 8282    pub fn select_up_by_lines(
 8283        &mut self,
 8284        action: &SelectUpByLines,
 8285        window: &mut Window,
 8286        cx: &mut Context<Self>,
 8287    ) {
 8288        let text_layout_details = &self.text_layout_details(window);
 8289        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8290            s.move_heads_with(|map, head, goal| {
 8291                movement::up_by_rows(map, head, action.lines, goal, false, text_layout_details)
 8292            })
 8293        })
 8294    }
 8295
 8296    pub fn select_page_up(
 8297        &mut self,
 8298        _: &SelectPageUp,
 8299        window: &mut Window,
 8300        cx: &mut Context<Self>,
 8301    ) {
 8302        let Some(row_count) = self.visible_row_count() else {
 8303            return;
 8304        };
 8305
 8306        let text_layout_details = &self.text_layout_details(window);
 8307
 8308        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8309            s.move_heads_with(|map, head, goal| {
 8310                movement::up_by_rows(map, head, row_count, goal, false, text_layout_details)
 8311            })
 8312        })
 8313    }
 8314
 8315    pub fn move_page_up(
 8316        &mut self,
 8317        action: &MovePageUp,
 8318        window: &mut Window,
 8319        cx: &mut Context<Self>,
 8320    ) {
 8321        if self.take_rename(true, window, cx).is_some() {
 8322            return;
 8323        }
 8324
 8325        if self
 8326            .context_menu
 8327            .borrow_mut()
 8328            .as_mut()
 8329            .map(|menu| menu.select_first(self.completion_provider.as_deref(), cx))
 8330            .unwrap_or(false)
 8331        {
 8332            return;
 8333        }
 8334
 8335        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 8336            cx.propagate();
 8337            return;
 8338        }
 8339
 8340        let Some(row_count) = self.visible_row_count() else {
 8341            return;
 8342        };
 8343
 8344        let autoscroll = if action.center_cursor {
 8345            Autoscroll::center()
 8346        } else {
 8347            Autoscroll::fit()
 8348        };
 8349
 8350        let text_layout_details = &self.text_layout_details(window);
 8351
 8352        self.change_selections(Some(autoscroll), window, cx, |s| {
 8353            let line_mode = s.line_mode;
 8354            s.move_with(|map, selection| {
 8355                if !selection.is_empty() && !line_mode {
 8356                    selection.goal = SelectionGoal::None;
 8357                }
 8358                let (cursor, goal) = movement::up_by_rows(
 8359                    map,
 8360                    selection.end,
 8361                    row_count,
 8362                    selection.goal,
 8363                    false,
 8364                    text_layout_details,
 8365                );
 8366                selection.collapse_to(cursor, goal);
 8367            });
 8368        });
 8369    }
 8370
 8371    pub fn select_up(&mut self, _: &SelectUp, window: &mut Window, cx: &mut Context<Self>) {
 8372        let text_layout_details = &self.text_layout_details(window);
 8373        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8374            s.move_heads_with(|map, head, goal| {
 8375                movement::up(map, head, goal, false, text_layout_details)
 8376            })
 8377        })
 8378    }
 8379
 8380    pub fn move_down(&mut self, _: &MoveDown, window: &mut Window, cx: &mut Context<Self>) {
 8381        self.take_rename(true, window, cx);
 8382
 8383        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 8384            cx.propagate();
 8385            return;
 8386        }
 8387
 8388        let text_layout_details = &self.text_layout_details(window);
 8389        let selection_count = self.selections.count();
 8390        let first_selection = self.selections.first_anchor();
 8391
 8392        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8393            let line_mode = s.line_mode;
 8394            s.move_with(|map, selection| {
 8395                if !selection.is_empty() && !line_mode {
 8396                    selection.goal = SelectionGoal::None;
 8397                }
 8398                let (cursor, goal) = movement::down(
 8399                    map,
 8400                    selection.end,
 8401                    selection.goal,
 8402                    false,
 8403                    text_layout_details,
 8404                );
 8405                selection.collapse_to(cursor, goal);
 8406            });
 8407        });
 8408
 8409        if selection_count == 1 && first_selection.range() == self.selections.first_anchor().range()
 8410        {
 8411            cx.propagate();
 8412        }
 8413    }
 8414
 8415    pub fn select_page_down(
 8416        &mut self,
 8417        _: &SelectPageDown,
 8418        window: &mut Window,
 8419        cx: &mut Context<Self>,
 8420    ) {
 8421        let Some(row_count) = self.visible_row_count() else {
 8422            return;
 8423        };
 8424
 8425        let text_layout_details = &self.text_layout_details(window);
 8426
 8427        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8428            s.move_heads_with(|map, head, goal| {
 8429                movement::down_by_rows(map, head, row_count, goal, false, text_layout_details)
 8430            })
 8431        })
 8432    }
 8433
 8434    pub fn move_page_down(
 8435        &mut self,
 8436        action: &MovePageDown,
 8437        window: &mut Window,
 8438        cx: &mut Context<Self>,
 8439    ) {
 8440        if self.take_rename(true, window, cx).is_some() {
 8441            return;
 8442        }
 8443
 8444        if self
 8445            .context_menu
 8446            .borrow_mut()
 8447            .as_mut()
 8448            .map(|menu| menu.select_last(self.completion_provider.as_deref(), cx))
 8449            .unwrap_or(false)
 8450        {
 8451            return;
 8452        }
 8453
 8454        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 8455            cx.propagate();
 8456            return;
 8457        }
 8458
 8459        let Some(row_count) = self.visible_row_count() else {
 8460            return;
 8461        };
 8462
 8463        let autoscroll = if action.center_cursor {
 8464            Autoscroll::center()
 8465        } else {
 8466            Autoscroll::fit()
 8467        };
 8468
 8469        let text_layout_details = &self.text_layout_details(window);
 8470        self.change_selections(Some(autoscroll), window, cx, |s| {
 8471            let line_mode = s.line_mode;
 8472            s.move_with(|map, selection| {
 8473                if !selection.is_empty() && !line_mode {
 8474                    selection.goal = SelectionGoal::None;
 8475                }
 8476                let (cursor, goal) = movement::down_by_rows(
 8477                    map,
 8478                    selection.end,
 8479                    row_count,
 8480                    selection.goal,
 8481                    false,
 8482                    text_layout_details,
 8483                );
 8484                selection.collapse_to(cursor, goal);
 8485            });
 8486        });
 8487    }
 8488
 8489    pub fn select_down(&mut self, _: &SelectDown, window: &mut Window, cx: &mut Context<Self>) {
 8490        let text_layout_details = &self.text_layout_details(window);
 8491        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8492            s.move_heads_with(|map, head, goal| {
 8493                movement::down(map, head, goal, false, text_layout_details)
 8494            })
 8495        });
 8496    }
 8497
 8498    pub fn context_menu_first(
 8499        &mut self,
 8500        _: &ContextMenuFirst,
 8501        _window: &mut Window,
 8502        cx: &mut Context<Self>,
 8503    ) {
 8504        if let Some(context_menu) = self.context_menu.borrow_mut().as_mut() {
 8505            context_menu.select_first(self.completion_provider.as_deref(), cx);
 8506        }
 8507    }
 8508
 8509    pub fn context_menu_prev(
 8510        &mut self,
 8511        _: &ContextMenuPrev,
 8512        _window: &mut Window,
 8513        cx: &mut Context<Self>,
 8514    ) {
 8515        if let Some(context_menu) = self.context_menu.borrow_mut().as_mut() {
 8516            context_menu.select_prev(self.completion_provider.as_deref(), cx);
 8517        }
 8518    }
 8519
 8520    pub fn context_menu_next(
 8521        &mut self,
 8522        _: &ContextMenuNext,
 8523        _window: &mut Window,
 8524        cx: &mut Context<Self>,
 8525    ) {
 8526        if let Some(context_menu) = self.context_menu.borrow_mut().as_mut() {
 8527            context_menu.select_next(self.completion_provider.as_deref(), cx);
 8528        }
 8529    }
 8530
 8531    pub fn context_menu_last(
 8532        &mut self,
 8533        _: &ContextMenuLast,
 8534        _window: &mut Window,
 8535        cx: &mut Context<Self>,
 8536    ) {
 8537        if let Some(context_menu) = self.context_menu.borrow_mut().as_mut() {
 8538            context_menu.select_last(self.completion_provider.as_deref(), cx);
 8539        }
 8540    }
 8541
 8542    pub fn move_to_previous_word_start(
 8543        &mut self,
 8544        _: &MoveToPreviousWordStart,
 8545        window: &mut Window,
 8546        cx: &mut Context<Self>,
 8547    ) {
 8548        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8549            s.move_cursors_with(|map, head, _| {
 8550                (
 8551                    movement::previous_word_start(map, head),
 8552                    SelectionGoal::None,
 8553                )
 8554            });
 8555        })
 8556    }
 8557
 8558    pub fn move_to_previous_subword_start(
 8559        &mut self,
 8560        _: &MoveToPreviousSubwordStart,
 8561        window: &mut Window,
 8562        cx: &mut Context<Self>,
 8563    ) {
 8564        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8565            s.move_cursors_with(|map, head, _| {
 8566                (
 8567                    movement::previous_subword_start(map, head),
 8568                    SelectionGoal::None,
 8569                )
 8570            });
 8571        })
 8572    }
 8573
 8574    pub fn select_to_previous_word_start(
 8575        &mut self,
 8576        _: &SelectToPreviousWordStart,
 8577        window: &mut Window,
 8578        cx: &mut Context<Self>,
 8579    ) {
 8580        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8581            s.move_heads_with(|map, head, _| {
 8582                (
 8583                    movement::previous_word_start(map, head),
 8584                    SelectionGoal::None,
 8585                )
 8586            });
 8587        })
 8588    }
 8589
 8590    pub fn select_to_previous_subword_start(
 8591        &mut self,
 8592        _: &SelectToPreviousSubwordStart,
 8593        window: &mut Window,
 8594        cx: &mut Context<Self>,
 8595    ) {
 8596        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8597            s.move_heads_with(|map, head, _| {
 8598                (
 8599                    movement::previous_subword_start(map, head),
 8600                    SelectionGoal::None,
 8601                )
 8602            });
 8603        })
 8604    }
 8605
 8606    pub fn delete_to_previous_word_start(
 8607        &mut self,
 8608        action: &DeleteToPreviousWordStart,
 8609        window: &mut Window,
 8610        cx: &mut Context<Self>,
 8611    ) {
 8612        self.transact(window, cx, |this, window, cx| {
 8613            this.select_autoclose_pair(window, cx);
 8614            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8615                let line_mode = s.line_mode;
 8616                s.move_with(|map, selection| {
 8617                    if selection.is_empty() && !line_mode {
 8618                        let cursor = if action.ignore_newlines {
 8619                            movement::previous_word_start(map, selection.head())
 8620                        } else {
 8621                            movement::previous_word_start_or_newline(map, selection.head())
 8622                        };
 8623                        selection.set_head(cursor, SelectionGoal::None);
 8624                    }
 8625                });
 8626            });
 8627            this.insert("", window, cx);
 8628        });
 8629    }
 8630
 8631    pub fn delete_to_previous_subword_start(
 8632        &mut self,
 8633        _: &DeleteToPreviousSubwordStart,
 8634        window: &mut Window,
 8635        cx: &mut Context<Self>,
 8636    ) {
 8637        self.transact(window, cx, |this, window, cx| {
 8638            this.select_autoclose_pair(window, cx);
 8639            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8640                let line_mode = s.line_mode;
 8641                s.move_with(|map, selection| {
 8642                    if selection.is_empty() && !line_mode {
 8643                        let cursor = movement::previous_subword_start(map, selection.head());
 8644                        selection.set_head(cursor, SelectionGoal::None);
 8645                    }
 8646                });
 8647            });
 8648            this.insert("", window, cx);
 8649        });
 8650    }
 8651
 8652    pub fn move_to_next_word_end(
 8653        &mut self,
 8654        _: &MoveToNextWordEnd,
 8655        window: &mut Window,
 8656        cx: &mut Context<Self>,
 8657    ) {
 8658        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8659            s.move_cursors_with(|map, head, _| {
 8660                (movement::next_word_end(map, head), SelectionGoal::None)
 8661            });
 8662        })
 8663    }
 8664
 8665    pub fn move_to_next_subword_end(
 8666        &mut self,
 8667        _: &MoveToNextSubwordEnd,
 8668        window: &mut Window,
 8669        cx: &mut Context<Self>,
 8670    ) {
 8671        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8672            s.move_cursors_with(|map, head, _| {
 8673                (movement::next_subword_end(map, head), SelectionGoal::None)
 8674            });
 8675        })
 8676    }
 8677
 8678    pub fn select_to_next_word_end(
 8679        &mut self,
 8680        _: &SelectToNextWordEnd,
 8681        window: &mut Window,
 8682        cx: &mut Context<Self>,
 8683    ) {
 8684        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8685            s.move_heads_with(|map, head, _| {
 8686                (movement::next_word_end(map, head), SelectionGoal::None)
 8687            });
 8688        })
 8689    }
 8690
 8691    pub fn select_to_next_subword_end(
 8692        &mut self,
 8693        _: &SelectToNextSubwordEnd,
 8694        window: &mut Window,
 8695        cx: &mut Context<Self>,
 8696    ) {
 8697        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8698            s.move_heads_with(|map, head, _| {
 8699                (movement::next_subword_end(map, head), SelectionGoal::None)
 8700            });
 8701        })
 8702    }
 8703
 8704    pub fn delete_to_next_word_end(
 8705        &mut self,
 8706        action: &DeleteToNextWordEnd,
 8707        window: &mut Window,
 8708        cx: &mut Context<Self>,
 8709    ) {
 8710        self.transact(window, cx, |this, window, cx| {
 8711            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8712                let line_mode = s.line_mode;
 8713                s.move_with(|map, selection| {
 8714                    if selection.is_empty() && !line_mode {
 8715                        let cursor = if action.ignore_newlines {
 8716                            movement::next_word_end(map, selection.head())
 8717                        } else {
 8718                            movement::next_word_end_or_newline(map, selection.head())
 8719                        };
 8720                        selection.set_head(cursor, SelectionGoal::None);
 8721                    }
 8722                });
 8723            });
 8724            this.insert("", window, cx);
 8725        });
 8726    }
 8727
 8728    pub fn delete_to_next_subword_end(
 8729        &mut self,
 8730        _: &DeleteToNextSubwordEnd,
 8731        window: &mut Window,
 8732        cx: &mut Context<Self>,
 8733    ) {
 8734        self.transact(window, cx, |this, window, cx| {
 8735            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8736                s.move_with(|map, selection| {
 8737                    if selection.is_empty() {
 8738                        let cursor = movement::next_subword_end(map, selection.head());
 8739                        selection.set_head(cursor, SelectionGoal::None);
 8740                    }
 8741                });
 8742            });
 8743            this.insert("", window, cx);
 8744        });
 8745    }
 8746
 8747    pub fn move_to_beginning_of_line(
 8748        &mut self,
 8749        action: &MoveToBeginningOfLine,
 8750        window: &mut Window,
 8751        cx: &mut Context<Self>,
 8752    ) {
 8753        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8754            s.move_cursors_with(|map, head, _| {
 8755                (
 8756                    movement::indented_line_beginning(map, head, action.stop_at_soft_wraps),
 8757                    SelectionGoal::None,
 8758                )
 8759            });
 8760        })
 8761    }
 8762
 8763    pub fn select_to_beginning_of_line(
 8764        &mut self,
 8765        action: &SelectToBeginningOfLine,
 8766        window: &mut Window,
 8767        cx: &mut Context<Self>,
 8768    ) {
 8769        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8770            s.move_heads_with(|map, head, _| {
 8771                (
 8772                    movement::indented_line_beginning(map, head, action.stop_at_soft_wraps),
 8773                    SelectionGoal::None,
 8774                )
 8775            });
 8776        });
 8777    }
 8778
 8779    pub fn delete_to_beginning_of_line(
 8780        &mut self,
 8781        _: &DeleteToBeginningOfLine,
 8782        window: &mut Window,
 8783        cx: &mut Context<Self>,
 8784    ) {
 8785        self.transact(window, cx, |this, window, cx| {
 8786            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8787                s.move_with(|_, selection| {
 8788                    selection.reversed = true;
 8789                });
 8790            });
 8791
 8792            this.select_to_beginning_of_line(
 8793                &SelectToBeginningOfLine {
 8794                    stop_at_soft_wraps: false,
 8795                },
 8796                window,
 8797                cx,
 8798            );
 8799            this.backspace(&Backspace, window, cx);
 8800        });
 8801    }
 8802
 8803    pub fn move_to_end_of_line(
 8804        &mut self,
 8805        action: &MoveToEndOfLine,
 8806        window: &mut Window,
 8807        cx: &mut Context<Self>,
 8808    ) {
 8809        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8810            s.move_cursors_with(|map, head, _| {
 8811                (
 8812                    movement::line_end(map, head, action.stop_at_soft_wraps),
 8813                    SelectionGoal::None,
 8814                )
 8815            });
 8816        })
 8817    }
 8818
 8819    pub fn select_to_end_of_line(
 8820        &mut self,
 8821        action: &SelectToEndOfLine,
 8822        window: &mut Window,
 8823        cx: &mut Context<Self>,
 8824    ) {
 8825        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8826            s.move_heads_with(|map, head, _| {
 8827                (
 8828                    movement::line_end(map, head, action.stop_at_soft_wraps),
 8829                    SelectionGoal::None,
 8830                )
 8831            });
 8832        })
 8833    }
 8834
 8835    pub fn delete_to_end_of_line(
 8836        &mut self,
 8837        _: &DeleteToEndOfLine,
 8838        window: &mut Window,
 8839        cx: &mut Context<Self>,
 8840    ) {
 8841        self.transact(window, cx, |this, window, cx| {
 8842            this.select_to_end_of_line(
 8843                &SelectToEndOfLine {
 8844                    stop_at_soft_wraps: false,
 8845                },
 8846                window,
 8847                cx,
 8848            );
 8849            this.delete(&Delete, window, cx);
 8850        });
 8851    }
 8852
 8853    pub fn cut_to_end_of_line(
 8854        &mut self,
 8855        _: &CutToEndOfLine,
 8856        window: &mut Window,
 8857        cx: &mut Context<Self>,
 8858    ) {
 8859        self.transact(window, cx, |this, window, cx| {
 8860            this.select_to_end_of_line(
 8861                &SelectToEndOfLine {
 8862                    stop_at_soft_wraps: false,
 8863                },
 8864                window,
 8865                cx,
 8866            );
 8867            this.cut(&Cut, window, cx);
 8868        });
 8869    }
 8870
 8871    pub fn move_to_start_of_paragraph(
 8872        &mut self,
 8873        _: &MoveToStartOfParagraph,
 8874        window: &mut Window,
 8875        cx: &mut Context<Self>,
 8876    ) {
 8877        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 8878            cx.propagate();
 8879            return;
 8880        }
 8881
 8882        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8883            s.move_with(|map, selection| {
 8884                selection.collapse_to(
 8885                    movement::start_of_paragraph(map, selection.head(), 1),
 8886                    SelectionGoal::None,
 8887                )
 8888            });
 8889        })
 8890    }
 8891
 8892    pub fn move_to_end_of_paragraph(
 8893        &mut self,
 8894        _: &MoveToEndOfParagraph,
 8895        window: &mut Window,
 8896        cx: &mut Context<Self>,
 8897    ) {
 8898        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 8899            cx.propagate();
 8900            return;
 8901        }
 8902
 8903        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8904            s.move_with(|map, selection| {
 8905                selection.collapse_to(
 8906                    movement::end_of_paragraph(map, selection.head(), 1),
 8907                    SelectionGoal::None,
 8908                )
 8909            });
 8910        })
 8911    }
 8912
 8913    pub fn select_to_start_of_paragraph(
 8914        &mut self,
 8915        _: &SelectToStartOfParagraph,
 8916        window: &mut Window,
 8917        cx: &mut Context<Self>,
 8918    ) {
 8919        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 8920            cx.propagate();
 8921            return;
 8922        }
 8923
 8924        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8925            s.move_heads_with(|map, head, _| {
 8926                (
 8927                    movement::start_of_paragraph(map, head, 1),
 8928                    SelectionGoal::None,
 8929                )
 8930            });
 8931        })
 8932    }
 8933
 8934    pub fn select_to_end_of_paragraph(
 8935        &mut self,
 8936        _: &SelectToEndOfParagraph,
 8937        window: &mut Window,
 8938        cx: &mut Context<Self>,
 8939    ) {
 8940        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 8941            cx.propagate();
 8942            return;
 8943        }
 8944
 8945        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8946            s.move_heads_with(|map, head, _| {
 8947                (
 8948                    movement::end_of_paragraph(map, head, 1),
 8949                    SelectionGoal::None,
 8950                )
 8951            });
 8952        })
 8953    }
 8954
 8955    pub fn move_to_beginning(
 8956        &mut self,
 8957        _: &MoveToBeginning,
 8958        window: &mut Window,
 8959        cx: &mut Context<Self>,
 8960    ) {
 8961        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 8962            cx.propagate();
 8963            return;
 8964        }
 8965
 8966        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8967            s.select_ranges(vec![0..0]);
 8968        });
 8969    }
 8970
 8971    pub fn select_to_beginning(
 8972        &mut self,
 8973        _: &SelectToBeginning,
 8974        window: &mut Window,
 8975        cx: &mut Context<Self>,
 8976    ) {
 8977        let mut selection = self.selections.last::<Point>(cx);
 8978        selection.set_head(Point::zero(), SelectionGoal::None);
 8979
 8980        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8981            s.select(vec![selection]);
 8982        });
 8983    }
 8984
 8985    pub fn move_to_end(&mut self, _: &MoveToEnd, window: &mut Window, cx: &mut Context<Self>) {
 8986        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 8987            cx.propagate();
 8988            return;
 8989        }
 8990
 8991        let cursor = self.buffer.read(cx).read(cx).len();
 8992        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 8993            s.select_ranges(vec![cursor..cursor])
 8994        });
 8995    }
 8996
 8997    pub fn set_nav_history(&mut self, nav_history: Option<ItemNavHistory>) {
 8998        self.nav_history = nav_history;
 8999    }
 9000
 9001    pub fn nav_history(&self) -> Option<&ItemNavHistory> {
 9002        self.nav_history.as_ref()
 9003    }
 9004
 9005    fn push_to_nav_history(
 9006        &mut self,
 9007        cursor_anchor: Anchor,
 9008        new_position: Option<Point>,
 9009        cx: &mut Context<Self>,
 9010    ) {
 9011        if let Some(nav_history) = self.nav_history.as_mut() {
 9012            let buffer = self.buffer.read(cx).read(cx);
 9013            let cursor_position = cursor_anchor.to_point(&buffer);
 9014            let scroll_state = self.scroll_manager.anchor();
 9015            let scroll_top_row = scroll_state.top_row(&buffer);
 9016            drop(buffer);
 9017
 9018            if let Some(new_position) = new_position {
 9019                let row_delta = (new_position.row as i64 - cursor_position.row as i64).abs();
 9020                if row_delta < MIN_NAVIGATION_HISTORY_ROW_DELTA {
 9021                    return;
 9022                }
 9023            }
 9024
 9025            nav_history.push(
 9026                Some(NavigationData {
 9027                    cursor_anchor,
 9028                    cursor_position,
 9029                    scroll_anchor: scroll_state,
 9030                    scroll_top_row,
 9031                }),
 9032                cx,
 9033            );
 9034        }
 9035    }
 9036
 9037    pub fn select_to_end(&mut self, _: &SelectToEnd, window: &mut Window, cx: &mut Context<Self>) {
 9038        let buffer = self.buffer.read(cx).snapshot(cx);
 9039        let mut selection = self.selections.first::<usize>(cx);
 9040        selection.set_head(buffer.len(), SelectionGoal::None);
 9041        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9042            s.select(vec![selection]);
 9043        });
 9044    }
 9045
 9046    pub fn select_all(&mut self, _: &SelectAll, window: &mut Window, cx: &mut Context<Self>) {
 9047        let end = self.buffer.read(cx).read(cx).len();
 9048        self.change_selections(None, window, cx, |s| {
 9049            s.select_ranges(vec![0..end]);
 9050        });
 9051    }
 9052
 9053    pub fn select_line(&mut self, _: &SelectLine, window: &mut Window, cx: &mut Context<Self>) {
 9054        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 9055        let mut selections = self.selections.all::<Point>(cx);
 9056        let max_point = display_map.buffer_snapshot.max_point();
 9057        for selection in &mut selections {
 9058            let rows = selection.spanned_rows(true, &display_map);
 9059            selection.start = Point::new(rows.start.0, 0);
 9060            selection.end = cmp::min(max_point, Point::new(rows.end.0, 0));
 9061            selection.reversed = false;
 9062        }
 9063        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9064            s.select(selections);
 9065        });
 9066    }
 9067
 9068    pub fn split_selection_into_lines(
 9069        &mut self,
 9070        _: &SplitSelectionIntoLines,
 9071        window: &mut Window,
 9072        cx: &mut Context<Self>,
 9073    ) {
 9074        let mut to_unfold = Vec::new();
 9075        let mut new_selection_ranges = Vec::new();
 9076        {
 9077            let selections = self.selections.all::<Point>(cx);
 9078            let buffer = self.buffer.read(cx).read(cx);
 9079            for selection in selections {
 9080                for row in selection.start.row..selection.end.row {
 9081                    let cursor = Point::new(row, buffer.line_len(MultiBufferRow(row)));
 9082                    new_selection_ranges.push(cursor..cursor);
 9083                }
 9084                new_selection_ranges.push(selection.end..selection.end);
 9085                to_unfold.push(selection.start..selection.end);
 9086            }
 9087        }
 9088        self.unfold_ranges(&to_unfold, true, true, cx);
 9089        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9090            s.select_ranges(new_selection_ranges);
 9091        });
 9092    }
 9093
 9094    pub fn add_selection_above(
 9095        &mut self,
 9096        _: &AddSelectionAbove,
 9097        window: &mut Window,
 9098        cx: &mut Context<Self>,
 9099    ) {
 9100        self.add_selection(true, window, cx);
 9101    }
 9102
 9103    pub fn add_selection_below(
 9104        &mut self,
 9105        _: &AddSelectionBelow,
 9106        window: &mut Window,
 9107        cx: &mut Context<Self>,
 9108    ) {
 9109        self.add_selection(false, window, cx);
 9110    }
 9111
 9112    fn add_selection(&mut self, above: bool, window: &mut Window, cx: &mut Context<Self>) {
 9113        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 9114        let mut selections = self.selections.all::<Point>(cx);
 9115        let text_layout_details = self.text_layout_details(window);
 9116        let mut state = self.add_selections_state.take().unwrap_or_else(|| {
 9117            let oldest_selection = selections.iter().min_by_key(|s| s.id).unwrap().clone();
 9118            let range = oldest_selection.display_range(&display_map).sorted();
 9119
 9120            let start_x = display_map.x_for_display_point(range.start, &text_layout_details);
 9121            let end_x = display_map.x_for_display_point(range.end, &text_layout_details);
 9122            let positions = start_x.min(end_x)..start_x.max(end_x);
 9123
 9124            selections.clear();
 9125            let mut stack = Vec::new();
 9126            for row in range.start.row().0..=range.end.row().0 {
 9127                if let Some(selection) = self.selections.build_columnar_selection(
 9128                    &display_map,
 9129                    DisplayRow(row),
 9130                    &positions,
 9131                    oldest_selection.reversed,
 9132                    &text_layout_details,
 9133                ) {
 9134                    stack.push(selection.id);
 9135                    selections.push(selection);
 9136                }
 9137            }
 9138
 9139            if above {
 9140                stack.reverse();
 9141            }
 9142
 9143            AddSelectionsState { above, stack }
 9144        });
 9145
 9146        let last_added_selection = *state.stack.last().unwrap();
 9147        let mut new_selections = Vec::new();
 9148        if above == state.above {
 9149            let end_row = if above {
 9150                DisplayRow(0)
 9151            } else {
 9152                display_map.max_point().row()
 9153            };
 9154
 9155            'outer: for selection in selections {
 9156                if selection.id == last_added_selection {
 9157                    let range = selection.display_range(&display_map).sorted();
 9158                    debug_assert_eq!(range.start.row(), range.end.row());
 9159                    let mut row = range.start.row();
 9160                    let positions =
 9161                        if let SelectionGoal::HorizontalRange { start, end } = selection.goal {
 9162                            px(start)..px(end)
 9163                        } else {
 9164                            let start_x =
 9165                                display_map.x_for_display_point(range.start, &text_layout_details);
 9166                            let end_x =
 9167                                display_map.x_for_display_point(range.end, &text_layout_details);
 9168                            start_x.min(end_x)..start_x.max(end_x)
 9169                        };
 9170
 9171                    while row != end_row {
 9172                        if above {
 9173                            row.0 -= 1;
 9174                        } else {
 9175                            row.0 += 1;
 9176                        }
 9177
 9178                        if let Some(new_selection) = self.selections.build_columnar_selection(
 9179                            &display_map,
 9180                            row,
 9181                            &positions,
 9182                            selection.reversed,
 9183                            &text_layout_details,
 9184                        ) {
 9185                            state.stack.push(new_selection.id);
 9186                            if above {
 9187                                new_selections.push(new_selection);
 9188                                new_selections.push(selection);
 9189                            } else {
 9190                                new_selections.push(selection);
 9191                                new_selections.push(new_selection);
 9192                            }
 9193
 9194                            continue 'outer;
 9195                        }
 9196                    }
 9197                }
 9198
 9199                new_selections.push(selection);
 9200            }
 9201        } else {
 9202            new_selections = selections;
 9203            new_selections.retain(|s| s.id != last_added_selection);
 9204            state.stack.pop();
 9205        }
 9206
 9207        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9208            s.select(new_selections);
 9209        });
 9210        if state.stack.len() > 1 {
 9211            self.add_selections_state = Some(state);
 9212        }
 9213    }
 9214
 9215    pub fn select_next_match_internal(
 9216        &mut self,
 9217        display_map: &DisplaySnapshot,
 9218        replace_newest: bool,
 9219        autoscroll: Option<Autoscroll>,
 9220        window: &mut Window,
 9221        cx: &mut Context<Self>,
 9222    ) -> Result<()> {
 9223        fn select_next_match_ranges(
 9224            this: &mut Editor,
 9225            range: Range<usize>,
 9226            replace_newest: bool,
 9227            auto_scroll: Option<Autoscroll>,
 9228            window: &mut Window,
 9229            cx: &mut Context<Editor>,
 9230        ) {
 9231            this.unfold_ranges(&[range.clone()], false, true, cx);
 9232            this.change_selections(auto_scroll, window, cx, |s| {
 9233                if replace_newest {
 9234                    s.delete(s.newest_anchor().id);
 9235                }
 9236                s.insert_range(range.clone());
 9237            });
 9238        }
 9239
 9240        let buffer = &display_map.buffer_snapshot;
 9241        let mut selections = self.selections.all::<usize>(cx);
 9242        if let Some(mut select_next_state) = self.select_next_state.take() {
 9243            let query = &select_next_state.query;
 9244            if !select_next_state.done {
 9245                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
 9246                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
 9247                let mut next_selected_range = None;
 9248
 9249                let bytes_after_last_selection =
 9250                    buffer.bytes_in_range(last_selection.end..buffer.len());
 9251                let bytes_before_first_selection = buffer.bytes_in_range(0..first_selection.start);
 9252                let query_matches = query
 9253                    .stream_find_iter(bytes_after_last_selection)
 9254                    .map(|result| (last_selection.end, result))
 9255                    .chain(
 9256                        query
 9257                            .stream_find_iter(bytes_before_first_selection)
 9258                            .map(|result| (0, result)),
 9259                    );
 9260
 9261                for (start_offset, query_match) in query_matches {
 9262                    let query_match = query_match.unwrap(); // can only fail due to I/O
 9263                    let offset_range =
 9264                        start_offset + query_match.start()..start_offset + query_match.end();
 9265                    let display_range = offset_range.start.to_display_point(display_map)
 9266                        ..offset_range.end.to_display_point(display_map);
 9267
 9268                    if !select_next_state.wordwise
 9269                        || (!movement::is_inside_word(display_map, display_range.start)
 9270                            && !movement::is_inside_word(display_map, display_range.end))
 9271                    {
 9272                        // TODO: This is n^2, because we might check all the selections
 9273                        if !selections
 9274                            .iter()
 9275                            .any(|selection| selection.range().overlaps(&offset_range))
 9276                        {
 9277                            next_selected_range = Some(offset_range);
 9278                            break;
 9279                        }
 9280                    }
 9281                }
 9282
 9283                if let Some(next_selected_range) = next_selected_range {
 9284                    select_next_match_ranges(
 9285                        self,
 9286                        next_selected_range,
 9287                        replace_newest,
 9288                        autoscroll,
 9289                        window,
 9290                        cx,
 9291                    );
 9292                } else {
 9293                    select_next_state.done = true;
 9294                }
 9295            }
 9296
 9297            self.select_next_state = Some(select_next_state);
 9298        } else {
 9299            let mut only_carets = true;
 9300            let mut same_text_selected = true;
 9301            let mut selected_text = None;
 9302
 9303            let mut selections_iter = selections.iter().peekable();
 9304            while let Some(selection) = selections_iter.next() {
 9305                if selection.start != selection.end {
 9306                    only_carets = false;
 9307                }
 9308
 9309                if same_text_selected {
 9310                    if selected_text.is_none() {
 9311                        selected_text =
 9312                            Some(buffer.text_for_range(selection.range()).collect::<String>());
 9313                    }
 9314
 9315                    if let Some(next_selection) = selections_iter.peek() {
 9316                        if next_selection.range().len() == selection.range().len() {
 9317                            let next_selected_text = buffer
 9318                                .text_for_range(next_selection.range())
 9319                                .collect::<String>();
 9320                            if Some(next_selected_text) != selected_text {
 9321                                same_text_selected = false;
 9322                                selected_text = None;
 9323                            }
 9324                        } else {
 9325                            same_text_selected = false;
 9326                            selected_text = None;
 9327                        }
 9328                    }
 9329                }
 9330            }
 9331
 9332            if only_carets {
 9333                for selection in &mut selections {
 9334                    let word_range = movement::surrounding_word(
 9335                        display_map,
 9336                        selection.start.to_display_point(display_map),
 9337                    );
 9338                    selection.start = word_range.start.to_offset(display_map, Bias::Left);
 9339                    selection.end = word_range.end.to_offset(display_map, Bias::Left);
 9340                    selection.goal = SelectionGoal::None;
 9341                    selection.reversed = false;
 9342                    select_next_match_ranges(
 9343                        self,
 9344                        selection.start..selection.end,
 9345                        replace_newest,
 9346                        autoscroll,
 9347                        window,
 9348                        cx,
 9349                    );
 9350                }
 9351
 9352                if selections.len() == 1 {
 9353                    let selection = selections
 9354                        .last()
 9355                        .expect("ensured that there's only one selection");
 9356                    let query = buffer
 9357                        .text_for_range(selection.start..selection.end)
 9358                        .collect::<String>();
 9359                    let is_empty = query.is_empty();
 9360                    let select_state = SelectNextState {
 9361                        query: AhoCorasick::new(&[query])?,
 9362                        wordwise: true,
 9363                        done: is_empty,
 9364                    };
 9365                    self.select_next_state = Some(select_state);
 9366                } else {
 9367                    self.select_next_state = None;
 9368                }
 9369            } else if let Some(selected_text) = selected_text {
 9370                self.select_next_state = Some(SelectNextState {
 9371                    query: AhoCorasick::new(&[selected_text])?,
 9372                    wordwise: false,
 9373                    done: false,
 9374                });
 9375                self.select_next_match_internal(
 9376                    display_map,
 9377                    replace_newest,
 9378                    autoscroll,
 9379                    window,
 9380                    cx,
 9381                )?;
 9382            }
 9383        }
 9384        Ok(())
 9385    }
 9386
 9387    pub fn select_all_matches(
 9388        &mut self,
 9389        _action: &SelectAllMatches,
 9390        window: &mut Window,
 9391        cx: &mut Context<Self>,
 9392    ) -> Result<()> {
 9393        self.push_to_selection_history();
 9394        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 9395
 9396        self.select_next_match_internal(&display_map, false, None, window, cx)?;
 9397        let Some(select_next_state) = self.select_next_state.as_mut() else {
 9398            return Ok(());
 9399        };
 9400        if select_next_state.done {
 9401            return Ok(());
 9402        }
 9403
 9404        let mut new_selections = self.selections.all::<usize>(cx);
 9405
 9406        let buffer = &display_map.buffer_snapshot;
 9407        let query_matches = select_next_state
 9408            .query
 9409            .stream_find_iter(buffer.bytes_in_range(0..buffer.len()));
 9410
 9411        for query_match in query_matches {
 9412            let query_match = query_match.unwrap(); // can only fail due to I/O
 9413            let offset_range = query_match.start()..query_match.end();
 9414            let display_range = offset_range.start.to_display_point(&display_map)
 9415                ..offset_range.end.to_display_point(&display_map);
 9416
 9417            if !select_next_state.wordwise
 9418                || (!movement::is_inside_word(&display_map, display_range.start)
 9419                    && !movement::is_inside_word(&display_map, display_range.end))
 9420            {
 9421                self.selections.change_with(cx, |selections| {
 9422                    new_selections.push(Selection {
 9423                        id: selections.new_selection_id(),
 9424                        start: offset_range.start,
 9425                        end: offset_range.end,
 9426                        reversed: false,
 9427                        goal: SelectionGoal::None,
 9428                    });
 9429                });
 9430            }
 9431        }
 9432
 9433        new_selections.sort_by_key(|selection| selection.start);
 9434        let mut ix = 0;
 9435        while ix + 1 < new_selections.len() {
 9436            let current_selection = &new_selections[ix];
 9437            let next_selection = &new_selections[ix + 1];
 9438            if current_selection.range().overlaps(&next_selection.range()) {
 9439                if current_selection.id < next_selection.id {
 9440                    new_selections.remove(ix + 1);
 9441                } else {
 9442                    new_selections.remove(ix);
 9443                }
 9444            } else {
 9445                ix += 1;
 9446            }
 9447        }
 9448
 9449        let reversed = self.selections.oldest::<usize>(cx).reversed;
 9450
 9451        for selection in new_selections.iter_mut() {
 9452            selection.reversed = reversed;
 9453        }
 9454
 9455        select_next_state.done = true;
 9456        self.unfold_ranges(
 9457            &new_selections
 9458                .iter()
 9459                .map(|selection| selection.range())
 9460                .collect::<Vec<_>>(),
 9461            false,
 9462            false,
 9463            cx,
 9464        );
 9465        self.change_selections(Some(Autoscroll::fit()), window, cx, |selections| {
 9466            selections.select(new_selections)
 9467        });
 9468
 9469        Ok(())
 9470    }
 9471
 9472    pub fn select_next(
 9473        &mut self,
 9474        action: &SelectNext,
 9475        window: &mut Window,
 9476        cx: &mut Context<Self>,
 9477    ) -> Result<()> {
 9478        self.push_to_selection_history();
 9479        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 9480        self.select_next_match_internal(
 9481            &display_map,
 9482            action.replace_newest,
 9483            Some(Autoscroll::newest()),
 9484            window,
 9485            cx,
 9486        )?;
 9487        Ok(())
 9488    }
 9489
 9490    pub fn select_previous(
 9491        &mut self,
 9492        action: &SelectPrevious,
 9493        window: &mut Window,
 9494        cx: &mut Context<Self>,
 9495    ) -> Result<()> {
 9496        self.push_to_selection_history();
 9497        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 9498        let buffer = &display_map.buffer_snapshot;
 9499        let mut selections = self.selections.all::<usize>(cx);
 9500        if let Some(mut select_prev_state) = self.select_prev_state.take() {
 9501            let query = &select_prev_state.query;
 9502            if !select_prev_state.done {
 9503                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
 9504                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
 9505                let mut next_selected_range = None;
 9506                // When we're iterating matches backwards, the oldest match will actually be the furthest one in the buffer.
 9507                let bytes_before_last_selection =
 9508                    buffer.reversed_bytes_in_range(0..last_selection.start);
 9509                let bytes_after_first_selection =
 9510                    buffer.reversed_bytes_in_range(first_selection.end..buffer.len());
 9511                let query_matches = query
 9512                    .stream_find_iter(bytes_before_last_selection)
 9513                    .map(|result| (last_selection.start, result))
 9514                    .chain(
 9515                        query
 9516                            .stream_find_iter(bytes_after_first_selection)
 9517                            .map(|result| (buffer.len(), result)),
 9518                    );
 9519                for (end_offset, query_match) in query_matches {
 9520                    let query_match = query_match.unwrap(); // can only fail due to I/O
 9521                    let offset_range =
 9522                        end_offset - query_match.end()..end_offset - query_match.start();
 9523                    let display_range = offset_range.start.to_display_point(&display_map)
 9524                        ..offset_range.end.to_display_point(&display_map);
 9525
 9526                    if !select_prev_state.wordwise
 9527                        || (!movement::is_inside_word(&display_map, display_range.start)
 9528                            && !movement::is_inside_word(&display_map, display_range.end))
 9529                    {
 9530                        next_selected_range = Some(offset_range);
 9531                        break;
 9532                    }
 9533                }
 9534
 9535                if let Some(next_selected_range) = next_selected_range {
 9536                    self.unfold_ranges(&[next_selected_range.clone()], false, true, cx);
 9537                    self.change_selections(Some(Autoscroll::newest()), window, cx, |s| {
 9538                        if action.replace_newest {
 9539                            s.delete(s.newest_anchor().id);
 9540                        }
 9541                        s.insert_range(next_selected_range);
 9542                    });
 9543                } else {
 9544                    select_prev_state.done = true;
 9545                }
 9546            }
 9547
 9548            self.select_prev_state = Some(select_prev_state);
 9549        } else {
 9550            let mut only_carets = true;
 9551            let mut same_text_selected = true;
 9552            let mut selected_text = None;
 9553
 9554            let mut selections_iter = selections.iter().peekable();
 9555            while let Some(selection) = selections_iter.next() {
 9556                if selection.start != selection.end {
 9557                    only_carets = false;
 9558                }
 9559
 9560                if same_text_selected {
 9561                    if selected_text.is_none() {
 9562                        selected_text =
 9563                            Some(buffer.text_for_range(selection.range()).collect::<String>());
 9564                    }
 9565
 9566                    if let Some(next_selection) = selections_iter.peek() {
 9567                        if next_selection.range().len() == selection.range().len() {
 9568                            let next_selected_text = buffer
 9569                                .text_for_range(next_selection.range())
 9570                                .collect::<String>();
 9571                            if Some(next_selected_text) != selected_text {
 9572                                same_text_selected = false;
 9573                                selected_text = None;
 9574                            }
 9575                        } else {
 9576                            same_text_selected = false;
 9577                            selected_text = None;
 9578                        }
 9579                    }
 9580                }
 9581            }
 9582
 9583            if only_carets {
 9584                for selection in &mut selections {
 9585                    let word_range = movement::surrounding_word(
 9586                        &display_map,
 9587                        selection.start.to_display_point(&display_map),
 9588                    );
 9589                    selection.start = word_range.start.to_offset(&display_map, Bias::Left);
 9590                    selection.end = word_range.end.to_offset(&display_map, Bias::Left);
 9591                    selection.goal = SelectionGoal::None;
 9592                    selection.reversed = false;
 9593                }
 9594                if selections.len() == 1 {
 9595                    let selection = selections
 9596                        .last()
 9597                        .expect("ensured that there's only one selection");
 9598                    let query = buffer
 9599                        .text_for_range(selection.start..selection.end)
 9600                        .collect::<String>();
 9601                    let is_empty = query.is_empty();
 9602                    let select_state = SelectNextState {
 9603                        query: AhoCorasick::new(&[query.chars().rev().collect::<String>()])?,
 9604                        wordwise: true,
 9605                        done: is_empty,
 9606                    };
 9607                    self.select_prev_state = Some(select_state);
 9608                } else {
 9609                    self.select_prev_state = None;
 9610                }
 9611
 9612                self.unfold_ranges(
 9613                    &selections.iter().map(|s| s.range()).collect::<Vec<_>>(),
 9614                    false,
 9615                    true,
 9616                    cx,
 9617                );
 9618                self.change_selections(Some(Autoscroll::newest()), window, cx, |s| {
 9619                    s.select(selections);
 9620                });
 9621            } else if let Some(selected_text) = selected_text {
 9622                self.select_prev_state = Some(SelectNextState {
 9623                    query: AhoCorasick::new(&[selected_text.chars().rev().collect::<String>()])?,
 9624                    wordwise: false,
 9625                    done: false,
 9626                });
 9627                self.select_previous(action, window, cx)?;
 9628            }
 9629        }
 9630        Ok(())
 9631    }
 9632
 9633    pub fn toggle_comments(
 9634        &mut self,
 9635        action: &ToggleComments,
 9636        window: &mut Window,
 9637        cx: &mut Context<Self>,
 9638    ) {
 9639        if self.read_only(cx) {
 9640            return;
 9641        }
 9642        let text_layout_details = &self.text_layout_details(window);
 9643        self.transact(window, cx, |this, window, cx| {
 9644            let mut selections = this.selections.all::<MultiBufferPoint>(cx);
 9645            let mut edits = Vec::new();
 9646            let mut selection_edit_ranges = Vec::new();
 9647            let mut last_toggled_row = None;
 9648            let snapshot = this.buffer.read(cx).read(cx);
 9649            let empty_str: Arc<str> = Arc::default();
 9650            let mut suffixes_inserted = Vec::new();
 9651            let ignore_indent = action.ignore_indent;
 9652
 9653            fn comment_prefix_range(
 9654                snapshot: &MultiBufferSnapshot,
 9655                row: MultiBufferRow,
 9656                comment_prefix: &str,
 9657                comment_prefix_whitespace: &str,
 9658                ignore_indent: bool,
 9659            ) -> Range<Point> {
 9660                let indent_size = if ignore_indent {
 9661                    0
 9662                } else {
 9663                    snapshot.indent_size_for_line(row).len
 9664                };
 9665
 9666                let start = Point::new(row.0, indent_size);
 9667
 9668                let mut line_bytes = snapshot
 9669                    .bytes_in_range(start..snapshot.max_point())
 9670                    .flatten()
 9671                    .copied();
 9672
 9673                // If this line currently begins with the line comment prefix, then record
 9674                // the range containing the prefix.
 9675                if line_bytes
 9676                    .by_ref()
 9677                    .take(comment_prefix.len())
 9678                    .eq(comment_prefix.bytes())
 9679                {
 9680                    // Include any whitespace that matches the comment prefix.
 9681                    let matching_whitespace_len = line_bytes
 9682                        .zip(comment_prefix_whitespace.bytes())
 9683                        .take_while(|(a, b)| a == b)
 9684                        .count() as u32;
 9685                    let end = Point::new(
 9686                        start.row,
 9687                        start.column + comment_prefix.len() as u32 + matching_whitespace_len,
 9688                    );
 9689                    start..end
 9690                } else {
 9691                    start..start
 9692                }
 9693            }
 9694
 9695            fn comment_suffix_range(
 9696                snapshot: &MultiBufferSnapshot,
 9697                row: MultiBufferRow,
 9698                comment_suffix: &str,
 9699                comment_suffix_has_leading_space: bool,
 9700            ) -> Range<Point> {
 9701                let end = Point::new(row.0, snapshot.line_len(row));
 9702                let suffix_start_column = end.column.saturating_sub(comment_suffix.len() as u32);
 9703
 9704                let mut line_end_bytes = snapshot
 9705                    .bytes_in_range(Point::new(end.row, suffix_start_column.saturating_sub(1))..end)
 9706                    .flatten()
 9707                    .copied();
 9708
 9709                let leading_space_len = if suffix_start_column > 0
 9710                    && line_end_bytes.next() == Some(b' ')
 9711                    && comment_suffix_has_leading_space
 9712                {
 9713                    1
 9714                } else {
 9715                    0
 9716                };
 9717
 9718                // If this line currently begins with the line comment prefix, then record
 9719                // the range containing the prefix.
 9720                if line_end_bytes.by_ref().eq(comment_suffix.bytes()) {
 9721                    let start = Point::new(end.row, suffix_start_column - leading_space_len);
 9722                    start..end
 9723                } else {
 9724                    end..end
 9725                }
 9726            }
 9727
 9728            // TODO: Handle selections that cross excerpts
 9729            for selection in &mut selections {
 9730                let start_column = snapshot
 9731                    .indent_size_for_line(MultiBufferRow(selection.start.row))
 9732                    .len;
 9733                let language = if let Some(language) =
 9734                    snapshot.language_scope_at(Point::new(selection.start.row, start_column))
 9735                {
 9736                    language
 9737                } else {
 9738                    continue;
 9739                };
 9740
 9741                selection_edit_ranges.clear();
 9742
 9743                // If multiple selections contain a given row, avoid processing that
 9744                // row more than once.
 9745                let mut start_row = MultiBufferRow(selection.start.row);
 9746                if last_toggled_row == Some(start_row) {
 9747                    start_row = start_row.next_row();
 9748                }
 9749                let end_row =
 9750                    if selection.end.row > selection.start.row && selection.end.column == 0 {
 9751                        MultiBufferRow(selection.end.row - 1)
 9752                    } else {
 9753                        MultiBufferRow(selection.end.row)
 9754                    };
 9755                last_toggled_row = Some(end_row);
 9756
 9757                if start_row > end_row {
 9758                    continue;
 9759                }
 9760
 9761                // If the language has line comments, toggle those.
 9762                let mut full_comment_prefixes = language.line_comment_prefixes().to_vec();
 9763
 9764                // If ignore_indent is set, trim spaces from the right side of all full_comment_prefixes
 9765                if ignore_indent {
 9766                    full_comment_prefixes = full_comment_prefixes
 9767                        .into_iter()
 9768                        .map(|s| Arc::from(s.trim_end()))
 9769                        .collect();
 9770                }
 9771
 9772                if !full_comment_prefixes.is_empty() {
 9773                    let first_prefix = full_comment_prefixes
 9774                        .first()
 9775                        .expect("prefixes is non-empty");
 9776                    let prefix_trimmed_lengths = full_comment_prefixes
 9777                        .iter()
 9778                        .map(|p| p.trim_end_matches(' ').len())
 9779                        .collect::<SmallVec<[usize; 4]>>();
 9780
 9781                    let mut all_selection_lines_are_comments = true;
 9782
 9783                    for row in start_row.0..=end_row.0 {
 9784                        let row = MultiBufferRow(row);
 9785                        if start_row < end_row && snapshot.is_line_blank(row) {
 9786                            continue;
 9787                        }
 9788
 9789                        let prefix_range = full_comment_prefixes
 9790                            .iter()
 9791                            .zip(prefix_trimmed_lengths.iter().copied())
 9792                            .map(|(prefix, trimmed_prefix_len)| {
 9793                                comment_prefix_range(
 9794                                    snapshot.deref(),
 9795                                    row,
 9796                                    &prefix[..trimmed_prefix_len],
 9797                                    &prefix[trimmed_prefix_len..],
 9798                                    ignore_indent,
 9799                                )
 9800                            })
 9801                            .max_by_key(|range| range.end.column - range.start.column)
 9802                            .expect("prefixes is non-empty");
 9803
 9804                        if prefix_range.is_empty() {
 9805                            all_selection_lines_are_comments = false;
 9806                        }
 9807
 9808                        selection_edit_ranges.push(prefix_range);
 9809                    }
 9810
 9811                    if all_selection_lines_are_comments {
 9812                        edits.extend(
 9813                            selection_edit_ranges
 9814                                .iter()
 9815                                .cloned()
 9816                                .map(|range| (range, empty_str.clone())),
 9817                        );
 9818                    } else {
 9819                        let min_column = selection_edit_ranges
 9820                            .iter()
 9821                            .map(|range| range.start.column)
 9822                            .min()
 9823                            .unwrap_or(0);
 9824                        edits.extend(selection_edit_ranges.iter().map(|range| {
 9825                            let position = Point::new(range.start.row, min_column);
 9826                            (position..position, first_prefix.clone())
 9827                        }));
 9828                    }
 9829                } else if let Some((full_comment_prefix, comment_suffix)) =
 9830                    language.block_comment_delimiters()
 9831                {
 9832                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
 9833                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
 9834                    let prefix_range = comment_prefix_range(
 9835                        snapshot.deref(),
 9836                        start_row,
 9837                        comment_prefix,
 9838                        comment_prefix_whitespace,
 9839                        ignore_indent,
 9840                    );
 9841                    let suffix_range = comment_suffix_range(
 9842                        snapshot.deref(),
 9843                        end_row,
 9844                        comment_suffix.trim_start_matches(' '),
 9845                        comment_suffix.starts_with(' '),
 9846                    );
 9847
 9848                    if prefix_range.is_empty() || suffix_range.is_empty() {
 9849                        edits.push((
 9850                            prefix_range.start..prefix_range.start,
 9851                            full_comment_prefix.clone(),
 9852                        ));
 9853                        edits.push((suffix_range.end..suffix_range.end, comment_suffix.clone()));
 9854                        suffixes_inserted.push((end_row, comment_suffix.len()));
 9855                    } else {
 9856                        edits.push((prefix_range, empty_str.clone()));
 9857                        edits.push((suffix_range, empty_str.clone()));
 9858                    }
 9859                } else {
 9860                    continue;
 9861                }
 9862            }
 9863
 9864            drop(snapshot);
 9865            this.buffer.update(cx, |buffer, cx| {
 9866                buffer.edit(edits, None, cx);
 9867            });
 9868
 9869            // Adjust selections so that they end before any comment suffixes that
 9870            // were inserted.
 9871            let mut suffixes_inserted = suffixes_inserted.into_iter().peekable();
 9872            let mut selections = this.selections.all::<Point>(cx);
 9873            let snapshot = this.buffer.read(cx).read(cx);
 9874            for selection in &mut selections {
 9875                while let Some((row, suffix_len)) = suffixes_inserted.peek().copied() {
 9876                    match row.cmp(&MultiBufferRow(selection.end.row)) {
 9877                        Ordering::Less => {
 9878                            suffixes_inserted.next();
 9879                            continue;
 9880                        }
 9881                        Ordering::Greater => break,
 9882                        Ordering::Equal => {
 9883                            if selection.end.column == snapshot.line_len(row) {
 9884                                if selection.is_empty() {
 9885                                    selection.start.column -= suffix_len as u32;
 9886                                }
 9887                                selection.end.column -= suffix_len as u32;
 9888                            }
 9889                            break;
 9890                        }
 9891                    }
 9892                }
 9893            }
 9894
 9895            drop(snapshot);
 9896            this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9897                s.select(selections)
 9898            });
 9899
 9900            let selections = this.selections.all::<Point>(cx);
 9901            let selections_on_single_row = selections.windows(2).all(|selections| {
 9902                selections[0].start.row == selections[1].start.row
 9903                    && selections[0].end.row == selections[1].end.row
 9904                    && selections[0].start.row == selections[0].end.row
 9905            });
 9906            let selections_selecting = selections
 9907                .iter()
 9908                .any(|selection| selection.start != selection.end);
 9909            let advance_downwards = action.advance_downwards
 9910                && selections_on_single_row
 9911                && !selections_selecting
 9912                && !matches!(this.mode, EditorMode::SingleLine { .. });
 9913
 9914            if advance_downwards {
 9915                let snapshot = this.buffer.read(cx).snapshot(cx);
 9916
 9917                this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9918                    s.move_cursors_with(|display_snapshot, display_point, _| {
 9919                        let mut point = display_point.to_point(display_snapshot);
 9920                        point.row += 1;
 9921                        point = snapshot.clip_point(point, Bias::Left);
 9922                        let display_point = point.to_display_point(display_snapshot);
 9923                        let goal = SelectionGoal::HorizontalPosition(
 9924                            display_snapshot
 9925                                .x_for_display_point(display_point, text_layout_details)
 9926                                .into(),
 9927                        );
 9928                        (display_point, goal)
 9929                    })
 9930                });
 9931            }
 9932        });
 9933    }
 9934
 9935    pub fn select_enclosing_symbol(
 9936        &mut self,
 9937        _: &SelectEnclosingSymbol,
 9938        window: &mut Window,
 9939        cx: &mut Context<Self>,
 9940    ) {
 9941        let buffer = self.buffer.read(cx).snapshot(cx);
 9942        let old_selections = self.selections.all::<usize>(cx).into_boxed_slice();
 9943
 9944        fn update_selection(
 9945            selection: &Selection<usize>,
 9946            buffer_snap: &MultiBufferSnapshot,
 9947        ) -> Option<Selection<usize>> {
 9948            let cursor = selection.head();
 9949            let (_buffer_id, symbols) = buffer_snap.symbols_containing(cursor, None)?;
 9950            for symbol in symbols.iter().rev() {
 9951                let start = symbol.range.start.to_offset(buffer_snap);
 9952                let end = symbol.range.end.to_offset(buffer_snap);
 9953                let new_range = start..end;
 9954                if start < selection.start || end > selection.end {
 9955                    return Some(Selection {
 9956                        id: selection.id,
 9957                        start: new_range.start,
 9958                        end: new_range.end,
 9959                        goal: SelectionGoal::None,
 9960                        reversed: selection.reversed,
 9961                    });
 9962                }
 9963            }
 9964            None
 9965        }
 9966
 9967        let mut selected_larger_symbol = false;
 9968        let new_selections = old_selections
 9969            .iter()
 9970            .map(|selection| match update_selection(selection, &buffer) {
 9971                Some(new_selection) => {
 9972                    if new_selection.range() != selection.range() {
 9973                        selected_larger_symbol = true;
 9974                    }
 9975                    new_selection
 9976                }
 9977                None => selection.clone(),
 9978            })
 9979            .collect::<Vec<_>>();
 9980
 9981        if selected_larger_symbol {
 9982            self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
 9983                s.select(new_selections);
 9984            });
 9985        }
 9986    }
 9987
 9988    pub fn select_larger_syntax_node(
 9989        &mut self,
 9990        _: &SelectLargerSyntaxNode,
 9991        window: &mut Window,
 9992        cx: &mut Context<Self>,
 9993    ) {
 9994        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 9995        let buffer = self.buffer.read(cx).snapshot(cx);
 9996        let old_selections = self.selections.all::<usize>(cx).into_boxed_slice();
 9997
 9998        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
 9999        let mut selected_larger_node = false;
10000        let new_selections = old_selections
10001            .iter()
10002            .map(|selection| {
10003                let old_range = selection.start..selection.end;
10004                let mut new_range = old_range.clone();
10005                let mut new_node = None;
10006                while let Some((node, containing_range)) = buffer.syntax_ancestor(new_range.clone())
10007                {
10008                    new_node = Some(node);
10009                    new_range = containing_range;
10010                    if !display_map.intersects_fold(new_range.start)
10011                        && !display_map.intersects_fold(new_range.end)
10012                    {
10013                        break;
10014                    }
10015                }
10016
10017                if let Some(node) = new_node {
10018                    // Log the ancestor, to support using this action as a way to explore TreeSitter
10019                    // nodes. Parent and grandparent are also logged because this operation will not
10020                    // visit nodes that have the same range as their parent.
10021                    log::info!("Node: {node:?}");
10022                    let parent = node.parent();
10023                    log::info!("Parent: {parent:?}");
10024                    let grandparent = parent.and_then(|x| x.parent());
10025                    log::info!("Grandparent: {grandparent:?}");
10026                }
10027
10028                selected_larger_node |= new_range != old_range;
10029                Selection {
10030                    id: selection.id,
10031                    start: new_range.start,
10032                    end: new_range.end,
10033                    goal: SelectionGoal::None,
10034                    reversed: selection.reversed,
10035                }
10036            })
10037            .collect::<Vec<_>>();
10038
10039        if selected_larger_node {
10040            stack.push(old_selections);
10041            self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10042                s.select(new_selections);
10043            });
10044        }
10045        self.select_larger_syntax_node_stack = stack;
10046    }
10047
10048    pub fn select_smaller_syntax_node(
10049        &mut self,
10050        _: &SelectSmallerSyntaxNode,
10051        window: &mut Window,
10052        cx: &mut Context<Self>,
10053    ) {
10054        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
10055        if let Some(selections) = stack.pop() {
10056            self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10057                s.select(selections.to_vec());
10058            });
10059        }
10060        self.select_larger_syntax_node_stack = stack;
10061    }
10062
10063    fn refresh_runnables(&mut self, window: &mut Window, cx: &mut Context<Self>) -> Task<()> {
10064        if !EditorSettings::get_global(cx).gutter.runnables {
10065            self.clear_tasks();
10066            return Task::ready(());
10067        }
10068        let project = self.project.as_ref().map(Entity::downgrade);
10069        cx.spawn_in(window, |this, mut cx| async move {
10070            cx.background_executor().timer(UPDATE_DEBOUNCE).await;
10071            let Some(project) = project.and_then(|p| p.upgrade()) else {
10072                return;
10073            };
10074            let Ok(display_snapshot) = this.update(&mut cx, |this, cx| {
10075                this.display_map.update(cx, |map, cx| map.snapshot(cx))
10076            }) else {
10077                return;
10078            };
10079
10080            let hide_runnables = project
10081                .update(&mut cx, |project, cx| {
10082                    // Do not display any test indicators in non-dev server remote projects.
10083                    project.is_via_collab() && project.ssh_connection_string(cx).is_none()
10084                })
10085                .unwrap_or(true);
10086            if hide_runnables {
10087                return;
10088            }
10089            let new_rows =
10090                cx.background_executor()
10091                    .spawn({
10092                        let snapshot = display_snapshot.clone();
10093                        async move {
10094                            Self::fetch_runnable_ranges(&snapshot, Anchor::min()..Anchor::max())
10095                        }
10096                    })
10097                    .await;
10098
10099            let rows = Self::runnable_rows(project, display_snapshot, new_rows, cx.clone());
10100            this.update(&mut cx, |this, _| {
10101                this.clear_tasks();
10102                for (key, value) in rows {
10103                    this.insert_tasks(key, value);
10104                }
10105            })
10106            .ok();
10107        })
10108    }
10109    fn fetch_runnable_ranges(
10110        snapshot: &DisplaySnapshot,
10111        range: Range<Anchor>,
10112    ) -> Vec<language::RunnableRange> {
10113        snapshot.buffer_snapshot.runnable_ranges(range).collect()
10114    }
10115
10116    fn runnable_rows(
10117        project: Entity<Project>,
10118        snapshot: DisplaySnapshot,
10119        runnable_ranges: Vec<RunnableRange>,
10120        mut cx: AsyncWindowContext,
10121    ) -> Vec<((BufferId, u32), RunnableTasks)> {
10122        runnable_ranges
10123            .into_iter()
10124            .filter_map(|mut runnable| {
10125                let tasks = cx
10126                    .update(|_, cx| Self::templates_with_tags(&project, &mut runnable.runnable, cx))
10127                    .ok()?;
10128                if tasks.is_empty() {
10129                    return None;
10130                }
10131
10132                let point = runnable.run_range.start.to_point(&snapshot.buffer_snapshot);
10133
10134                let row = snapshot
10135                    .buffer_snapshot
10136                    .buffer_line_for_row(MultiBufferRow(point.row))?
10137                    .1
10138                    .start
10139                    .row;
10140
10141                let context_range =
10142                    BufferOffset(runnable.full_range.start)..BufferOffset(runnable.full_range.end);
10143                Some((
10144                    (runnable.buffer_id, row),
10145                    RunnableTasks {
10146                        templates: tasks,
10147                        offset: MultiBufferOffset(runnable.run_range.start),
10148                        context_range,
10149                        column: point.column,
10150                        extra_variables: runnable.extra_captures,
10151                    },
10152                ))
10153            })
10154            .collect()
10155    }
10156
10157    fn templates_with_tags(
10158        project: &Entity<Project>,
10159        runnable: &mut Runnable,
10160        cx: &mut App,
10161    ) -> Vec<(TaskSourceKind, TaskTemplate)> {
10162        let (inventory, worktree_id, file) = project.read_with(cx, |project, cx| {
10163            let (worktree_id, file) = project
10164                .buffer_for_id(runnable.buffer, cx)
10165                .and_then(|buffer| buffer.read(cx).file())
10166                .map(|file| (file.worktree_id(cx), file.clone()))
10167                .unzip();
10168
10169            (
10170                project.task_store().read(cx).task_inventory().cloned(),
10171                worktree_id,
10172                file,
10173            )
10174        });
10175
10176        let tags = mem::take(&mut runnable.tags);
10177        let mut tags: Vec<_> = tags
10178            .into_iter()
10179            .flat_map(|tag| {
10180                let tag = tag.0.clone();
10181                inventory
10182                    .as_ref()
10183                    .into_iter()
10184                    .flat_map(|inventory| {
10185                        inventory.read(cx).list_tasks(
10186                            file.clone(),
10187                            Some(runnable.language.clone()),
10188                            worktree_id,
10189                            cx,
10190                        )
10191                    })
10192                    .filter(move |(_, template)| {
10193                        template.tags.iter().any(|source_tag| source_tag == &tag)
10194                    })
10195            })
10196            .sorted_by_key(|(kind, _)| kind.to_owned())
10197            .collect();
10198        if let Some((leading_tag_source, _)) = tags.first() {
10199            // Strongest source wins; if we have worktree tag binding, prefer that to
10200            // global and language bindings;
10201            // if we have a global binding, prefer that to language binding.
10202            let first_mismatch = tags
10203                .iter()
10204                .position(|(tag_source, _)| tag_source != leading_tag_source);
10205            if let Some(index) = first_mismatch {
10206                tags.truncate(index);
10207            }
10208        }
10209
10210        tags
10211    }
10212
10213    pub fn move_to_enclosing_bracket(
10214        &mut self,
10215        _: &MoveToEnclosingBracket,
10216        window: &mut Window,
10217        cx: &mut Context<Self>,
10218    ) {
10219        self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10220            s.move_offsets_with(|snapshot, selection| {
10221                let Some(enclosing_bracket_ranges) =
10222                    snapshot.enclosing_bracket_ranges(selection.start..selection.end)
10223                else {
10224                    return;
10225                };
10226
10227                let mut best_length = usize::MAX;
10228                let mut best_inside = false;
10229                let mut best_in_bracket_range = false;
10230                let mut best_destination = None;
10231                for (open, close) in enclosing_bracket_ranges {
10232                    let close = close.to_inclusive();
10233                    let length = close.end() - open.start;
10234                    let inside = selection.start >= open.end && selection.end <= *close.start();
10235                    let in_bracket_range = open.to_inclusive().contains(&selection.head())
10236                        || close.contains(&selection.head());
10237
10238                    // If best is next to a bracket and current isn't, skip
10239                    if !in_bracket_range && best_in_bracket_range {
10240                        continue;
10241                    }
10242
10243                    // Prefer smaller lengths unless best is inside and current isn't
10244                    if length > best_length && (best_inside || !inside) {
10245                        continue;
10246                    }
10247
10248                    best_length = length;
10249                    best_inside = inside;
10250                    best_in_bracket_range = in_bracket_range;
10251                    best_destination = Some(
10252                        if close.contains(&selection.start) && close.contains(&selection.end) {
10253                            if inside {
10254                                open.end
10255                            } else {
10256                                open.start
10257                            }
10258                        } else if inside {
10259                            *close.start()
10260                        } else {
10261                            *close.end()
10262                        },
10263                    );
10264                }
10265
10266                if let Some(destination) = best_destination {
10267                    selection.collapse_to(destination, SelectionGoal::None);
10268                }
10269            })
10270        });
10271    }
10272
10273    pub fn undo_selection(
10274        &mut self,
10275        _: &UndoSelection,
10276        window: &mut Window,
10277        cx: &mut Context<Self>,
10278    ) {
10279        self.end_selection(window, cx);
10280        self.selection_history.mode = SelectionHistoryMode::Undoing;
10281        if let Some(entry) = self.selection_history.undo_stack.pop_back() {
10282            self.change_selections(None, window, cx, |s| {
10283                s.select_anchors(entry.selections.to_vec())
10284            });
10285            self.select_next_state = entry.select_next_state;
10286            self.select_prev_state = entry.select_prev_state;
10287            self.add_selections_state = entry.add_selections_state;
10288            self.request_autoscroll(Autoscroll::newest(), cx);
10289        }
10290        self.selection_history.mode = SelectionHistoryMode::Normal;
10291    }
10292
10293    pub fn redo_selection(
10294        &mut self,
10295        _: &RedoSelection,
10296        window: &mut Window,
10297        cx: &mut Context<Self>,
10298    ) {
10299        self.end_selection(window, cx);
10300        self.selection_history.mode = SelectionHistoryMode::Redoing;
10301        if let Some(entry) = self.selection_history.redo_stack.pop_back() {
10302            self.change_selections(None, window, cx, |s| {
10303                s.select_anchors(entry.selections.to_vec())
10304            });
10305            self.select_next_state = entry.select_next_state;
10306            self.select_prev_state = entry.select_prev_state;
10307            self.add_selections_state = entry.add_selections_state;
10308            self.request_autoscroll(Autoscroll::newest(), cx);
10309        }
10310        self.selection_history.mode = SelectionHistoryMode::Normal;
10311    }
10312
10313    pub fn expand_excerpts(
10314        &mut self,
10315        action: &ExpandExcerpts,
10316        _: &mut Window,
10317        cx: &mut Context<Self>,
10318    ) {
10319        self.expand_excerpts_for_direction(action.lines, ExpandExcerptDirection::UpAndDown, cx)
10320    }
10321
10322    pub fn expand_excerpts_down(
10323        &mut self,
10324        action: &ExpandExcerptsDown,
10325        _: &mut Window,
10326        cx: &mut Context<Self>,
10327    ) {
10328        self.expand_excerpts_for_direction(action.lines, ExpandExcerptDirection::Down, cx)
10329    }
10330
10331    pub fn expand_excerpts_up(
10332        &mut self,
10333        action: &ExpandExcerptsUp,
10334        _: &mut Window,
10335        cx: &mut Context<Self>,
10336    ) {
10337        self.expand_excerpts_for_direction(action.lines, ExpandExcerptDirection::Up, cx)
10338    }
10339
10340    pub fn expand_excerpts_for_direction(
10341        &mut self,
10342        lines: u32,
10343        direction: ExpandExcerptDirection,
10344
10345        cx: &mut Context<Self>,
10346    ) {
10347        let selections = self.selections.disjoint_anchors();
10348
10349        let lines = if lines == 0 {
10350            EditorSettings::get_global(cx).expand_excerpt_lines
10351        } else {
10352            lines
10353        };
10354
10355        self.buffer.update(cx, |buffer, cx| {
10356            let snapshot = buffer.snapshot(cx);
10357            let mut excerpt_ids = selections
10358                .iter()
10359                .flat_map(|selection| snapshot.excerpt_ids_for_range(selection.range()))
10360                .collect::<Vec<_>>();
10361            excerpt_ids.sort();
10362            excerpt_ids.dedup();
10363            buffer.expand_excerpts(excerpt_ids, lines, direction, cx)
10364        })
10365    }
10366
10367    pub fn expand_excerpt(
10368        &mut self,
10369        excerpt: ExcerptId,
10370        direction: ExpandExcerptDirection,
10371        cx: &mut Context<Self>,
10372    ) {
10373        let lines = EditorSettings::get_global(cx).expand_excerpt_lines;
10374        self.buffer.update(cx, |buffer, cx| {
10375            buffer.expand_excerpts([excerpt], lines, direction, cx)
10376        })
10377    }
10378
10379    pub fn go_to_singleton_buffer_point(
10380        &mut self,
10381        point: Point,
10382        window: &mut Window,
10383        cx: &mut Context<Self>,
10384    ) {
10385        self.go_to_singleton_buffer_range(point..point, window, cx);
10386    }
10387
10388    pub fn go_to_singleton_buffer_range(
10389        &mut self,
10390        range: Range<Point>,
10391        window: &mut Window,
10392        cx: &mut Context<Self>,
10393    ) {
10394        let multibuffer = self.buffer().read(cx);
10395        let Some(buffer) = multibuffer.as_singleton() else {
10396            return;
10397        };
10398        let Some(start) = multibuffer.buffer_point_to_anchor(&buffer, range.start, cx) else {
10399            return;
10400        };
10401        let Some(end) = multibuffer.buffer_point_to_anchor(&buffer, range.end, cx) else {
10402            return;
10403        };
10404        self.change_selections(Some(Autoscroll::center()), window, cx, |s| {
10405            s.select_anchor_ranges([start..end])
10406        });
10407    }
10408
10409    fn go_to_diagnostic(
10410        &mut self,
10411        _: &GoToDiagnostic,
10412        window: &mut Window,
10413        cx: &mut Context<Self>,
10414    ) {
10415        self.go_to_diagnostic_impl(Direction::Next, window, cx)
10416    }
10417
10418    fn go_to_prev_diagnostic(
10419        &mut self,
10420        _: &GoToPrevDiagnostic,
10421        window: &mut Window,
10422        cx: &mut Context<Self>,
10423    ) {
10424        self.go_to_diagnostic_impl(Direction::Prev, window, cx)
10425    }
10426
10427    pub fn go_to_diagnostic_impl(
10428        &mut self,
10429        direction: Direction,
10430        window: &mut Window,
10431        cx: &mut Context<Self>,
10432    ) {
10433        let buffer = self.buffer.read(cx).snapshot(cx);
10434        let selection = self.selections.newest::<usize>(cx);
10435
10436        // If there is an active Diagnostic Popover jump to its diagnostic instead.
10437        if direction == Direction::Next {
10438            if let Some(popover) = self.hover_state.diagnostic_popover.as_ref() {
10439                let Some(buffer_id) = popover.local_diagnostic.range.start.buffer_id else {
10440                    return;
10441                };
10442                self.activate_diagnostics(
10443                    buffer_id,
10444                    popover.local_diagnostic.diagnostic.group_id,
10445                    window,
10446                    cx,
10447                );
10448                if let Some(active_diagnostics) = self.active_diagnostics.as_ref() {
10449                    let primary_range_start = active_diagnostics.primary_range.start;
10450                    self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10451                        let mut new_selection = s.newest_anchor().clone();
10452                        new_selection.collapse_to(primary_range_start, SelectionGoal::None);
10453                        s.select_anchors(vec![new_selection.clone()]);
10454                    });
10455                    self.refresh_inline_completion(false, true, window, cx);
10456                }
10457                return;
10458            }
10459        }
10460
10461        let active_group_id = self
10462            .active_diagnostics
10463            .as_ref()
10464            .map(|active_group| active_group.group_id);
10465        let active_primary_range = self.active_diagnostics.as_ref().map(|active_diagnostics| {
10466            active_diagnostics
10467                .primary_range
10468                .to_offset(&buffer)
10469                .to_inclusive()
10470        });
10471        let search_start = if let Some(active_primary_range) = active_primary_range.as_ref() {
10472            if active_primary_range.contains(&selection.head()) {
10473                *active_primary_range.start()
10474            } else {
10475                selection.head()
10476            }
10477        } else {
10478            selection.head()
10479        };
10480
10481        let snapshot = self.snapshot(window, cx);
10482        let primary_diagnostics_before = buffer
10483            .diagnostics_in_range::<usize>(0..search_start)
10484            .filter(|entry| entry.diagnostic.is_primary)
10485            .filter(|entry| entry.range.start != entry.range.end)
10486            .filter(|entry| entry.diagnostic.severity <= DiagnosticSeverity::WARNING)
10487            .filter(|entry| !snapshot.intersects_fold(entry.range.start))
10488            .collect::<Vec<_>>();
10489        let last_same_group_diagnostic_before = active_group_id.and_then(|active_group_id| {
10490            primary_diagnostics_before
10491                .iter()
10492                .position(|entry| entry.diagnostic.group_id == active_group_id)
10493        });
10494
10495        let primary_diagnostics_after = buffer
10496            .diagnostics_in_range::<usize>(search_start..buffer.len())
10497            .filter(|entry| entry.diagnostic.is_primary)
10498            .filter(|entry| entry.range.start != entry.range.end)
10499            .filter(|entry| entry.diagnostic.severity <= DiagnosticSeverity::WARNING)
10500            .filter(|diagnostic| !snapshot.intersects_fold(diagnostic.range.start))
10501            .collect::<Vec<_>>();
10502        let last_same_group_diagnostic_after = active_group_id.and_then(|active_group_id| {
10503            primary_diagnostics_after
10504                .iter()
10505                .enumerate()
10506                .rev()
10507                .find_map(|(i, entry)| {
10508                    if entry.diagnostic.group_id == active_group_id {
10509                        Some(i)
10510                    } else {
10511                        None
10512                    }
10513                })
10514        });
10515
10516        let next_primary_diagnostic = match direction {
10517            Direction::Prev => primary_diagnostics_before
10518                .iter()
10519                .take(last_same_group_diagnostic_before.unwrap_or(usize::MAX))
10520                .rev()
10521                .next(),
10522            Direction::Next => primary_diagnostics_after
10523                .iter()
10524                .skip(
10525                    last_same_group_diagnostic_after
10526                        .map(|index| index + 1)
10527                        .unwrap_or(0),
10528                )
10529                .next(),
10530        };
10531
10532        // Cycle around to the start of the buffer, potentially moving back to the start of
10533        // the currently active diagnostic.
10534        let cycle_around = || match direction {
10535            Direction::Prev => primary_diagnostics_after
10536                .iter()
10537                .rev()
10538                .chain(primary_diagnostics_before.iter().rev())
10539                .next(),
10540            Direction::Next => primary_diagnostics_before
10541                .iter()
10542                .chain(primary_diagnostics_after.iter())
10543                .next(),
10544        };
10545
10546        if let Some((primary_range, group_id)) = next_primary_diagnostic
10547            .or_else(cycle_around)
10548            .map(|entry| (&entry.range, entry.diagnostic.group_id))
10549        {
10550            let Some(buffer_id) = buffer.anchor_after(primary_range.start).buffer_id else {
10551                return;
10552            };
10553            self.activate_diagnostics(buffer_id, group_id, window, cx);
10554            if self.active_diagnostics.is_some() {
10555                self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10556                    s.select(vec![Selection {
10557                        id: selection.id,
10558                        start: primary_range.start,
10559                        end: primary_range.start,
10560                        reversed: false,
10561                        goal: SelectionGoal::None,
10562                    }]);
10563                });
10564                self.refresh_inline_completion(false, true, window, cx);
10565            }
10566        }
10567    }
10568
10569    fn go_to_next_hunk(&mut self, _: &GoToHunk, window: &mut Window, cx: &mut Context<Self>) {
10570        let snapshot = self.snapshot(window, cx);
10571        let selection = self.selections.newest::<Point>(cx);
10572        self.go_to_hunk_after_position(&snapshot, selection.head(), window, cx);
10573    }
10574
10575    fn go_to_hunk_after_position(
10576        &mut self,
10577        snapshot: &EditorSnapshot,
10578        position: Point,
10579        window: &mut Window,
10580        cx: &mut Context<Editor>,
10581    ) -> Option<MultiBufferDiffHunk> {
10582        let mut hunk = snapshot
10583            .buffer_snapshot
10584            .diff_hunks_in_range(position..snapshot.buffer_snapshot.max_point())
10585            .find(|hunk| hunk.row_range.start.0 > position.row);
10586        if hunk.is_none() {
10587            hunk = snapshot
10588                .buffer_snapshot
10589                .diff_hunks_in_range(Point::zero()..position)
10590                .find(|hunk| hunk.row_range.end.0 < position.row)
10591        }
10592        if let Some(hunk) = &hunk {
10593            let destination = Point::new(hunk.row_range.start.0, 0);
10594            self.unfold_ranges(&[destination..destination], false, false, cx);
10595            self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10596                s.select_ranges(vec![destination..destination]);
10597            });
10598        }
10599
10600        hunk
10601    }
10602
10603    fn go_to_prev_hunk(&mut self, _: &GoToPrevHunk, window: &mut Window, cx: &mut Context<Self>) {
10604        let snapshot = self.snapshot(window, cx);
10605        let selection = self.selections.newest::<Point>(cx);
10606        self.go_to_hunk_before_position(&snapshot, selection.head(), window, cx);
10607    }
10608
10609    fn go_to_hunk_before_position(
10610        &mut self,
10611        snapshot: &EditorSnapshot,
10612        position: Point,
10613        window: &mut Window,
10614        cx: &mut Context<Editor>,
10615    ) -> Option<MultiBufferDiffHunk> {
10616        let mut hunk = snapshot.buffer_snapshot.diff_hunk_before(position);
10617        if hunk.is_none() {
10618            hunk = snapshot.buffer_snapshot.diff_hunk_before(Point::MAX);
10619        }
10620        if let Some(hunk) = &hunk {
10621            let destination = Point::new(hunk.row_range.start.0, 0);
10622            self.unfold_ranges(&[destination..destination], false, false, cx);
10623            self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
10624                s.select_ranges(vec![destination..destination]);
10625            });
10626        }
10627
10628        hunk
10629    }
10630
10631    pub fn go_to_definition(
10632        &mut self,
10633        _: &GoToDefinition,
10634        window: &mut Window,
10635        cx: &mut Context<Self>,
10636    ) -> Task<Result<Navigated>> {
10637        let definition =
10638            self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, false, window, cx);
10639        cx.spawn_in(window, |editor, mut cx| async move {
10640            if definition.await? == Navigated::Yes {
10641                return Ok(Navigated::Yes);
10642            }
10643            match editor.update_in(&mut cx, |editor, window, cx| {
10644                editor.find_all_references(&FindAllReferences, window, cx)
10645            })? {
10646                Some(references) => references.await,
10647                None => Ok(Navigated::No),
10648            }
10649        })
10650    }
10651
10652    pub fn go_to_declaration(
10653        &mut self,
10654        _: &GoToDeclaration,
10655        window: &mut Window,
10656        cx: &mut Context<Self>,
10657    ) -> Task<Result<Navigated>> {
10658        self.go_to_definition_of_kind(GotoDefinitionKind::Declaration, false, window, cx)
10659    }
10660
10661    pub fn go_to_declaration_split(
10662        &mut self,
10663        _: &GoToDeclaration,
10664        window: &mut Window,
10665        cx: &mut Context<Self>,
10666    ) -> Task<Result<Navigated>> {
10667        self.go_to_definition_of_kind(GotoDefinitionKind::Declaration, true, window, cx)
10668    }
10669
10670    pub fn go_to_implementation(
10671        &mut self,
10672        _: &GoToImplementation,
10673        window: &mut Window,
10674        cx: &mut Context<Self>,
10675    ) -> Task<Result<Navigated>> {
10676        self.go_to_definition_of_kind(GotoDefinitionKind::Implementation, false, window, cx)
10677    }
10678
10679    pub fn go_to_implementation_split(
10680        &mut self,
10681        _: &GoToImplementationSplit,
10682        window: &mut Window,
10683        cx: &mut Context<Self>,
10684    ) -> Task<Result<Navigated>> {
10685        self.go_to_definition_of_kind(GotoDefinitionKind::Implementation, true, window, cx)
10686    }
10687
10688    pub fn go_to_type_definition(
10689        &mut self,
10690        _: &GoToTypeDefinition,
10691        window: &mut Window,
10692        cx: &mut Context<Self>,
10693    ) -> Task<Result<Navigated>> {
10694        self.go_to_definition_of_kind(GotoDefinitionKind::Type, false, window, cx)
10695    }
10696
10697    pub fn go_to_definition_split(
10698        &mut self,
10699        _: &GoToDefinitionSplit,
10700        window: &mut Window,
10701        cx: &mut Context<Self>,
10702    ) -> Task<Result<Navigated>> {
10703        self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, true, window, cx)
10704    }
10705
10706    pub fn go_to_type_definition_split(
10707        &mut self,
10708        _: &GoToTypeDefinitionSplit,
10709        window: &mut Window,
10710        cx: &mut Context<Self>,
10711    ) -> Task<Result<Navigated>> {
10712        self.go_to_definition_of_kind(GotoDefinitionKind::Type, true, window, cx)
10713    }
10714
10715    fn go_to_definition_of_kind(
10716        &mut self,
10717        kind: GotoDefinitionKind,
10718        split: bool,
10719        window: &mut Window,
10720        cx: &mut Context<Self>,
10721    ) -> Task<Result<Navigated>> {
10722        let Some(provider) = self.semantics_provider.clone() else {
10723            return Task::ready(Ok(Navigated::No));
10724        };
10725        let head = self.selections.newest::<usize>(cx).head();
10726        let buffer = self.buffer.read(cx);
10727        let (buffer, head) = if let Some(text_anchor) = buffer.text_anchor_for_position(head, cx) {
10728            text_anchor
10729        } else {
10730            return Task::ready(Ok(Navigated::No));
10731        };
10732
10733        let Some(definitions) = provider.definitions(&buffer, head, kind, cx) else {
10734            return Task::ready(Ok(Navigated::No));
10735        };
10736
10737        cx.spawn_in(window, |editor, mut cx| async move {
10738            let definitions = definitions.await?;
10739            let navigated = editor
10740                .update_in(&mut cx, |editor, window, cx| {
10741                    editor.navigate_to_hover_links(
10742                        Some(kind),
10743                        definitions
10744                            .into_iter()
10745                            .filter(|location| {
10746                                hover_links::exclude_link_to_position(&buffer, &head, location, cx)
10747                            })
10748                            .map(HoverLink::Text)
10749                            .collect::<Vec<_>>(),
10750                        split,
10751                        window,
10752                        cx,
10753                    )
10754                })?
10755                .await?;
10756            anyhow::Ok(navigated)
10757        })
10758    }
10759
10760    pub fn open_url(&mut self, _: &OpenUrl, window: &mut Window, cx: &mut Context<Self>) {
10761        let selection = self.selections.newest_anchor();
10762        let head = selection.head();
10763        let tail = selection.tail();
10764
10765        let Some((buffer, start_position)) =
10766            self.buffer.read(cx).text_anchor_for_position(head, cx)
10767        else {
10768            return;
10769        };
10770
10771        let end_position = if head != tail {
10772            let Some((_, pos)) = self.buffer.read(cx).text_anchor_for_position(tail, cx) else {
10773                return;
10774            };
10775            Some(pos)
10776        } else {
10777            None
10778        };
10779
10780        let url_finder = cx.spawn_in(window, |editor, mut cx| async move {
10781            let url = if let Some(end_pos) = end_position {
10782                find_url_from_range(&buffer, start_position..end_pos, cx.clone())
10783            } else {
10784                find_url(&buffer, start_position, cx.clone()).map(|(_, url)| url)
10785            };
10786
10787            if let Some(url) = url {
10788                editor.update(&mut cx, |_, cx| {
10789                    cx.open_url(&url);
10790                })
10791            } else {
10792                Ok(())
10793            }
10794        });
10795
10796        url_finder.detach();
10797    }
10798
10799    pub fn open_selected_filename(
10800        &mut self,
10801        _: &OpenSelectedFilename,
10802        window: &mut Window,
10803        cx: &mut Context<Self>,
10804    ) {
10805        let Some(workspace) = self.workspace() else {
10806            return;
10807        };
10808
10809        let position = self.selections.newest_anchor().head();
10810
10811        let Some((buffer, buffer_position)) =
10812            self.buffer.read(cx).text_anchor_for_position(position, cx)
10813        else {
10814            return;
10815        };
10816
10817        let project = self.project.clone();
10818
10819        cx.spawn_in(window, |_, mut cx| async move {
10820            let result = find_file(&buffer, project, buffer_position, &mut cx).await;
10821
10822            if let Some((_, path)) = result {
10823                workspace
10824                    .update_in(&mut cx, |workspace, window, cx| {
10825                        workspace.open_resolved_path(path, window, cx)
10826                    })?
10827                    .await?;
10828            }
10829            anyhow::Ok(())
10830        })
10831        .detach();
10832    }
10833
10834    pub(crate) fn navigate_to_hover_links(
10835        &mut self,
10836        kind: Option<GotoDefinitionKind>,
10837        mut definitions: Vec<HoverLink>,
10838        split: bool,
10839        window: &mut Window,
10840        cx: &mut Context<Editor>,
10841    ) -> Task<Result<Navigated>> {
10842        // If there is one definition, just open it directly
10843        if definitions.len() == 1 {
10844            let definition = definitions.pop().unwrap();
10845
10846            enum TargetTaskResult {
10847                Location(Option<Location>),
10848                AlreadyNavigated,
10849            }
10850
10851            let target_task = match definition {
10852                HoverLink::Text(link) => {
10853                    Task::ready(anyhow::Ok(TargetTaskResult::Location(Some(link.target))))
10854                }
10855                HoverLink::InlayHint(lsp_location, server_id) => {
10856                    let computation =
10857                        self.compute_target_location(lsp_location, server_id, window, cx);
10858                    cx.background_executor().spawn(async move {
10859                        let location = computation.await?;
10860                        Ok(TargetTaskResult::Location(location))
10861                    })
10862                }
10863                HoverLink::Url(url) => {
10864                    cx.open_url(&url);
10865                    Task::ready(Ok(TargetTaskResult::AlreadyNavigated))
10866                }
10867                HoverLink::File(path) => {
10868                    if let Some(workspace) = self.workspace() {
10869                        cx.spawn_in(window, |_, mut cx| async move {
10870                            workspace
10871                                .update_in(&mut cx, |workspace, window, cx| {
10872                                    workspace.open_resolved_path(path, window, cx)
10873                                })?
10874                                .await
10875                                .map(|_| TargetTaskResult::AlreadyNavigated)
10876                        })
10877                    } else {
10878                        Task::ready(Ok(TargetTaskResult::Location(None)))
10879                    }
10880                }
10881            };
10882            cx.spawn_in(window, |editor, mut cx| async move {
10883                let target = match target_task.await.context("target resolution task")? {
10884                    TargetTaskResult::AlreadyNavigated => return Ok(Navigated::Yes),
10885                    TargetTaskResult::Location(None) => return Ok(Navigated::No),
10886                    TargetTaskResult::Location(Some(target)) => target,
10887                };
10888
10889                editor.update_in(&mut cx, |editor, window, cx| {
10890                    let Some(workspace) = editor.workspace() else {
10891                        return Navigated::No;
10892                    };
10893                    let pane = workspace.read(cx).active_pane().clone();
10894
10895                    let range = target.range.to_point(target.buffer.read(cx));
10896                    let range = editor.range_for_match(&range);
10897                    let range = collapse_multiline_range(range);
10898
10899                    if Some(&target.buffer) == editor.buffer.read(cx).as_singleton().as_ref() {
10900                        editor.go_to_singleton_buffer_range(range.clone(), window, cx);
10901                    } else {
10902                        window.defer(cx, move |window, cx| {
10903                            let target_editor: Entity<Self> =
10904                                workspace.update(cx, |workspace, cx| {
10905                                    let pane = if split {
10906                                        workspace.adjacent_pane(window, cx)
10907                                    } else {
10908                                        workspace.active_pane().clone()
10909                                    };
10910
10911                                    workspace.open_project_item(
10912                                        pane,
10913                                        target.buffer.clone(),
10914                                        true,
10915                                        true,
10916                                        window,
10917                                        cx,
10918                                    )
10919                                });
10920                            target_editor.update(cx, |target_editor, cx| {
10921                                // When selecting a definition in a different buffer, disable the nav history
10922                                // to avoid creating a history entry at the previous cursor location.
10923                                pane.update(cx, |pane, _| pane.disable_history());
10924                                target_editor.go_to_singleton_buffer_range(range, window, cx);
10925                                pane.update(cx, |pane, _| pane.enable_history());
10926                            });
10927                        });
10928                    }
10929                    Navigated::Yes
10930                })
10931            })
10932        } else if !definitions.is_empty() {
10933            cx.spawn_in(window, |editor, mut cx| async move {
10934                let (title, location_tasks, workspace) = editor
10935                    .update_in(&mut cx, |editor, window, cx| {
10936                        let tab_kind = match kind {
10937                            Some(GotoDefinitionKind::Implementation) => "Implementations",
10938                            _ => "Definitions",
10939                        };
10940                        let title = definitions
10941                            .iter()
10942                            .find_map(|definition| match definition {
10943                                HoverLink::Text(link) => link.origin.as_ref().map(|origin| {
10944                                    let buffer = origin.buffer.read(cx);
10945                                    format!(
10946                                        "{} for {}",
10947                                        tab_kind,
10948                                        buffer
10949                                            .text_for_range(origin.range.clone())
10950                                            .collect::<String>()
10951                                    )
10952                                }),
10953                                HoverLink::InlayHint(_, _) => None,
10954                                HoverLink::Url(_) => None,
10955                                HoverLink::File(_) => None,
10956                            })
10957                            .unwrap_or(tab_kind.to_string());
10958                        let location_tasks = definitions
10959                            .into_iter()
10960                            .map(|definition| match definition {
10961                                HoverLink::Text(link) => Task::ready(Ok(Some(link.target))),
10962                                HoverLink::InlayHint(lsp_location, server_id) => editor
10963                                    .compute_target_location(lsp_location, server_id, window, cx),
10964                                HoverLink::Url(_) => Task::ready(Ok(None)),
10965                                HoverLink::File(_) => Task::ready(Ok(None)),
10966                            })
10967                            .collect::<Vec<_>>();
10968                        (title, location_tasks, editor.workspace().clone())
10969                    })
10970                    .context("location tasks preparation")?;
10971
10972                let locations = future::join_all(location_tasks)
10973                    .await
10974                    .into_iter()
10975                    .filter_map(|location| location.transpose())
10976                    .collect::<Result<_>>()
10977                    .context("location tasks")?;
10978
10979                let Some(workspace) = workspace else {
10980                    return Ok(Navigated::No);
10981                };
10982                let opened = workspace
10983                    .update_in(&mut cx, |workspace, window, cx| {
10984                        Self::open_locations_in_multibuffer(
10985                            workspace,
10986                            locations,
10987                            title,
10988                            split,
10989                            MultibufferSelectionMode::First,
10990                            window,
10991                            cx,
10992                        )
10993                    })
10994                    .ok();
10995
10996                anyhow::Ok(Navigated::from_bool(opened.is_some()))
10997            })
10998        } else {
10999            Task::ready(Ok(Navigated::No))
11000        }
11001    }
11002
11003    fn compute_target_location(
11004        &self,
11005        lsp_location: lsp::Location,
11006        server_id: LanguageServerId,
11007        window: &mut Window,
11008        cx: &mut Context<Self>,
11009    ) -> Task<anyhow::Result<Option<Location>>> {
11010        let Some(project) = self.project.clone() else {
11011            return Task::ready(Ok(None));
11012        };
11013
11014        cx.spawn_in(window, move |editor, mut cx| async move {
11015            let location_task = editor.update(&mut cx, |_, cx| {
11016                project.update(cx, |project, cx| {
11017                    let language_server_name = project
11018                        .language_server_statuses(cx)
11019                        .find(|(id, _)| server_id == *id)
11020                        .map(|(_, status)| LanguageServerName::from(status.name.as_str()));
11021                    language_server_name.map(|language_server_name| {
11022                        project.open_local_buffer_via_lsp(
11023                            lsp_location.uri.clone(),
11024                            server_id,
11025                            language_server_name,
11026                            cx,
11027                        )
11028                    })
11029                })
11030            })?;
11031            let location = match location_task {
11032                Some(task) => Some({
11033                    let target_buffer_handle = task.await.context("open local buffer")?;
11034                    let range = target_buffer_handle.update(&mut cx, |target_buffer, _| {
11035                        let target_start = target_buffer
11036                            .clip_point_utf16(point_from_lsp(lsp_location.range.start), Bias::Left);
11037                        let target_end = target_buffer
11038                            .clip_point_utf16(point_from_lsp(lsp_location.range.end), Bias::Left);
11039                        target_buffer.anchor_after(target_start)
11040                            ..target_buffer.anchor_before(target_end)
11041                    })?;
11042                    Location {
11043                        buffer: target_buffer_handle,
11044                        range,
11045                    }
11046                }),
11047                None => None,
11048            };
11049            Ok(location)
11050        })
11051    }
11052
11053    pub fn find_all_references(
11054        &mut self,
11055        _: &FindAllReferences,
11056        window: &mut Window,
11057        cx: &mut Context<Self>,
11058    ) -> Option<Task<Result<Navigated>>> {
11059        let selection = self.selections.newest::<usize>(cx);
11060        let multi_buffer = self.buffer.read(cx);
11061        let head = selection.head();
11062
11063        let multi_buffer_snapshot = multi_buffer.snapshot(cx);
11064        let head_anchor = multi_buffer_snapshot.anchor_at(
11065            head,
11066            if head < selection.tail() {
11067                Bias::Right
11068            } else {
11069                Bias::Left
11070            },
11071        );
11072
11073        match self
11074            .find_all_references_task_sources
11075            .binary_search_by(|anchor| anchor.cmp(&head_anchor, &multi_buffer_snapshot))
11076        {
11077            Ok(_) => {
11078                log::info!(
11079                    "Ignoring repeated FindAllReferences invocation with the position of already running task"
11080                );
11081                return None;
11082            }
11083            Err(i) => {
11084                self.find_all_references_task_sources.insert(i, head_anchor);
11085            }
11086        }
11087
11088        let (buffer, head) = multi_buffer.text_anchor_for_position(head, cx)?;
11089        let workspace = self.workspace()?;
11090        let project = workspace.read(cx).project().clone();
11091        let references = project.update(cx, |project, cx| project.references(&buffer, head, cx));
11092        Some(cx.spawn_in(window, |editor, mut cx| async move {
11093            let _cleanup = defer({
11094                let mut cx = cx.clone();
11095                move || {
11096                    let _ = editor.update(&mut cx, |editor, _| {
11097                        if let Ok(i) =
11098                            editor
11099                                .find_all_references_task_sources
11100                                .binary_search_by(|anchor| {
11101                                    anchor.cmp(&head_anchor, &multi_buffer_snapshot)
11102                                })
11103                        {
11104                            editor.find_all_references_task_sources.remove(i);
11105                        }
11106                    });
11107                }
11108            });
11109
11110            let locations = references.await?;
11111            if locations.is_empty() {
11112                return anyhow::Ok(Navigated::No);
11113            }
11114
11115            workspace.update_in(&mut cx, |workspace, window, cx| {
11116                let title = locations
11117                    .first()
11118                    .as_ref()
11119                    .map(|location| {
11120                        let buffer = location.buffer.read(cx);
11121                        format!(
11122                            "References to `{}`",
11123                            buffer
11124                                .text_for_range(location.range.clone())
11125                                .collect::<String>()
11126                        )
11127                    })
11128                    .unwrap();
11129                Self::open_locations_in_multibuffer(
11130                    workspace,
11131                    locations,
11132                    title,
11133                    false,
11134                    MultibufferSelectionMode::First,
11135                    window,
11136                    cx,
11137                );
11138                Navigated::Yes
11139            })
11140        }))
11141    }
11142
11143    /// Opens a multibuffer with the given project locations in it
11144    pub fn open_locations_in_multibuffer(
11145        workspace: &mut Workspace,
11146        mut locations: Vec<Location>,
11147        title: String,
11148        split: bool,
11149        multibuffer_selection_mode: MultibufferSelectionMode,
11150        window: &mut Window,
11151        cx: &mut Context<Workspace>,
11152    ) {
11153        // If there are multiple definitions, open them in a multibuffer
11154        locations.sort_by_key(|location| location.buffer.read(cx).remote_id());
11155        let mut locations = locations.into_iter().peekable();
11156        let mut ranges = Vec::new();
11157        let capability = workspace.project().read(cx).capability();
11158
11159        let excerpt_buffer = cx.new(|cx| {
11160            let mut multibuffer = MultiBuffer::new(capability);
11161            while let Some(location) = locations.next() {
11162                let buffer = location.buffer.read(cx);
11163                let mut ranges_for_buffer = Vec::new();
11164                let range = location.range.to_offset(buffer);
11165                ranges_for_buffer.push(range.clone());
11166
11167                while let Some(next_location) = locations.peek() {
11168                    if next_location.buffer == location.buffer {
11169                        ranges_for_buffer.push(next_location.range.to_offset(buffer));
11170                        locations.next();
11171                    } else {
11172                        break;
11173                    }
11174                }
11175
11176                ranges_for_buffer.sort_by_key(|range| (range.start, Reverse(range.end)));
11177                ranges.extend(multibuffer.push_excerpts_with_context_lines(
11178                    location.buffer.clone(),
11179                    ranges_for_buffer,
11180                    DEFAULT_MULTIBUFFER_CONTEXT,
11181                    cx,
11182                ))
11183            }
11184
11185            multibuffer.with_title(title)
11186        });
11187
11188        let editor = cx.new(|cx| {
11189            Editor::for_multibuffer(
11190                excerpt_buffer,
11191                Some(workspace.project().clone()),
11192                true,
11193                window,
11194                cx,
11195            )
11196        });
11197        editor.update(cx, |editor, cx| {
11198            match multibuffer_selection_mode {
11199                MultibufferSelectionMode::First => {
11200                    if let Some(first_range) = ranges.first() {
11201                        editor.change_selections(None, window, cx, |selections| {
11202                            selections.clear_disjoint();
11203                            selections.select_anchor_ranges(std::iter::once(first_range.clone()));
11204                        });
11205                    }
11206                    editor.highlight_background::<Self>(
11207                        &ranges,
11208                        |theme| theme.editor_highlighted_line_background,
11209                        cx,
11210                    );
11211                }
11212                MultibufferSelectionMode::All => {
11213                    editor.change_selections(None, window, cx, |selections| {
11214                        selections.clear_disjoint();
11215                        selections.select_anchor_ranges(ranges);
11216                    });
11217                }
11218            }
11219            editor.register_buffers_with_language_servers(cx);
11220        });
11221
11222        let item = Box::new(editor);
11223        let item_id = item.item_id();
11224
11225        if split {
11226            workspace.split_item(SplitDirection::Right, item.clone(), window, cx);
11227        } else {
11228            let destination_index = workspace.active_pane().update(cx, |pane, cx| {
11229                if PreviewTabsSettings::get_global(cx).enable_preview_from_code_navigation {
11230                    pane.close_current_preview_item(window, cx)
11231                } else {
11232                    None
11233                }
11234            });
11235            workspace.add_item_to_active_pane(item.clone(), destination_index, true, window, cx);
11236        }
11237        workspace.active_pane().update(cx, |pane, cx| {
11238            pane.set_preview_item_id(Some(item_id), cx);
11239        });
11240    }
11241
11242    pub fn rename(
11243        &mut self,
11244        _: &Rename,
11245        window: &mut Window,
11246        cx: &mut Context<Self>,
11247    ) -> Option<Task<Result<()>>> {
11248        use language::ToOffset as _;
11249
11250        let provider = self.semantics_provider.clone()?;
11251        let selection = self.selections.newest_anchor().clone();
11252        let (cursor_buffer, cursor_buffer_position) = self
11253            .buffer
11254            .read(cx)
11255            .text_anchor_for_position(selection.head(), cx)?;
11256        let (tail_buffer, cursor_buffer_position_end) = self
11257            .buffer
11258            .read(cx)
11259            .text_anchor_for_position(selection.tail(), cx)?;
11260        if tail_buffer != cursor_buffer {
11261            return None;
11262        }
11263
11264        let snapshot = cursor_buffer.read(cx).snapshot();
11265        let cursor_buffer_offset = cursor_buffer_position.to_offset(&snapshot);
11266        let cursor_buffer_offset_end = cursor_buffer_position_end.to_offset(&snapshot);
11267        let prepare_rename = provider
11268            .range_for_rename(&cursor_buffer, cursor_buffer_position, cx)
11269            .unwrap_or_else(|| Task::ready(Ok(None)));
11270        drop(snapshot);
11271
11272        Some(cx.spawn_in(window, |this, mut cx| async move {
11273            let rename_range = if let Some(range) = prepare_rename.await? {
11274                Some(range)
11275            } else {
11276                this.update(&mut cx, |this, cx| {
11277                    let buffer = this.buffer.read(cx).snapshot(cx);
11278                    let mut buffer_highlights = this
11279                        .document_highlights_for_position(selection.head(), &buffer)
11280                        .filter(|highlight| {
11281                            highlight.start.excerpt_id == selection.head().excerpt_id
11282                                && highlight.end.excerpt_id == selection.head().excerpt_id
11283                        });
11284                    buffer_highlights
11285                        .next()
11286                        .map(|highlight| highlight.start.text_anchor..highlight.end.text_anchor)
11287                })?
11288            };
11289            if let Some(rename_range) = rename_range {
11290                this.update_in(&mut cx, |this, window, cx| {
11291                    let snapshot = cursor_buffer.read(cx).snapshot();
11292                    let rename_buffer_range = rename_range.to_offset(&snapshot);
11293                    let cursor_offset_in_rename_range =
11294                        cursor_buffer_offset.saturating_sub(rename_buffer_range.start);
11295                    let cursor_offset_in_rename_range_end =
11296                        cursor_buffer_offset_end.saturating_sub(rename_buffer_range.start);
11297
11298                    this.take_rename(false, window, cx);
11299                    let buffer = this.buffer.read(cx).read(cx);
11300                    let cursor_offset = selection.head().to_offset(&buffer);
11301                    let rename_start = cursor_offset.saturating_sub(cursor_offset_in_rename_range);
11302                    let rename_end = rename_start + rename_buffer_range.len();
11303                    let range = buffer.anchor_before(rename_start)..buffer.anchor_after(rename_end);
11304                    let mut old_highlight_id = None;
11305                    let old_name: Arc<str> = buffer
11306                        .chunks(rename_start..rename_end, true)
11307                        .map(|chunk| {
11308                            if old_highlight_id.is_none() {
11309                                old_highlight_id = chunk.syntax_highlight_id;
11310                            }
11311                            chunk.text
11312                        })
11313                        .collect::<String>()
11314                        .into();
11315
11316                    drop(buffer);
11317
11318                    // Position the selection in the rename editor so that it matches the current selection.
11319                    this.show_local_selections = false;
11320                    let rename_editor = cx.new(|cx| {
11321                        let mut editor = Editor::single_line(window, cx);
11322                        editor.buffer.update(cx, |buffer, cx| {
11323                            buffer.edit([(0..0, old_name.clone())], None, cx)
11324                        });
11325                        let rename_selection_range = match cursor_offset_in_rename_range
11326                            .cmp(&cursor_offset_in_rename_range_end)
11327                        {
11328                            Ordering::Equal => {
11329                                editor.select_all(&SelectAll, window, cx);
11330                                return editor;
11331                            }
11332                            Ordering::Less => {
11333                                cursor_offset_in_rename_range..cursor_offset_in_rename_range_end
11334                            }
11335                            Ordering::Greater => {
11336                                cursor_offset_in_rename_range_end..cursor_offset_in_rename_range
11337                            }
11338                        };
11339                        if rename_selection_range.end > old_name.len() {
11340                            editor.select_all(&SelectAll, window, cx);
11341                        } else {
11342                            editor.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
11343                                s.select_ranges([rename_selection_range]);
11344                            });
11345                        }
11346                        editor
11347                    });
11348                    cx.subscribe(&rename_editor, |_, _, e: &EditorEvent, cx| {
11349                        if e == &EditorEvent::Focused {
11350                            cx.emit(EditorEvent::FocusedIn)
11351                        }
11352                    })
11353                    .detach();
11354
11355                    let write_highlights =
11356                        this.clear_background_highlights::<DocumentHighlightWrite>(cx);
11357                    let read_highlights =
11358                        this.clear_background_highlights::<DocumentHighlightRead>(cx);
11359                    let ranges = write_highlights
11360                        .iter()
11361                        .flat_map(|(_, ranges)| ranges.iter())
11362                        .chain(read_highlights.iter().flat_map(|(_, ranges)| ranges.iter()))
11363                        .cloned()
11364                        .collect();
11365
11366                    this.highlight_text::<Rename>(
11367                        ranges,
11368                        HighlightStyle {
11369                            fade_out: Some(0.6),
11370                            ..Default::default()
11371                        },
11372                        cx,
11373                    );
11374                    let rename_focus_handle = rename_editor.focus_handle(cx);
11375                    window.focus(&rename_focus_handle);
11376                    let block_id = this.insert_blocks(
11377                        [BlockProperties {
11378                            style: BlockStyle::Flex,
11379                            placement: BlockPlacement::Below(range.start),
11380                            height: 1,
11381                            render: Arc::new({
11382                                let rename_editor = rename_editor.clone();
11383                                move |cx: &mut BlockContext| {
11384                                    let mut text_style = cx.editor_style.text.clone();
11385                                    if let Some(highlight_style) = old_highlight_id
11386                                        .and_then(|h| h.style(&cx.editor_style.syntax))
11387                                    {
11388                                        text_style = text_style.highlight(highlight_style);
11389                                    }
11390                                    div()
11391                                        .block_mouse_down()
11392                                        .pl(cx.anchor_x)
11393                                        .child(EditorElement::new(
11394                                            &rename_editor,
11395                                            EditorStyle {
11396                                                background: cx.theme().system().transparent,
11397                                                local_player: cx.editor_style.local_player,
11398                                                text: text_style,
11399                                                scrollbar_width: cx.editor_style.scrollbar_width,
11400                                                syntax: cx.editor_style.syntax.clone(),
11401                                                status: cx.editor_style.status.clone(),
11402                                                inlay_hints_style: HighlightStyle {
11403                                                    font_weight: Some(FontWeight::BOLD),
11404                                                    ..make_inlay_hints_style(cx.app)
11405                                                },
11406                                                inline_completion_styles: make_suggestion_styles(
11407                                                    cx.app,
11408                                                ),
11409                                                ..EditorStyle::default()
11410                                            },
11411                                        ))
11412                                        .into_any_element()
11413                                }
11414                            }),
11415                            priority: 0,
11416                        }],
11417                        Some(Autoscroll::fit()),
11418                        cx,
11419                    )[0];
11420                    this.pending_rename = Some(RenameState {
11421                        range,
11422                        old_name,
11423                        editor: rename_editor,
11424                        block_id,
11425                    });
11426                })?;
11427            }
11428
11429            Ok(())
11430        }))
11431    }
11432
11433    pub fn confirm_rename(
11434        &mut self,
11435        _: &ConfirmRename,
11436        window: &mut Window,
11437        cx: &mut Context<Self>,
11438    ) -> Option<Task<Result<()>>> {
11439        let rename = self.take_rename(false, window, cx)?;
11440        let workspace = self.workspace()?.downgrade();
11441        let (buffer, start) = self
11442            .buffer
11443            .read(cx)
11444            .text_anchor_for_position(rename.range.start, cx)?;
11445        let (end_buffer, _) = self
11446            .buffer
11447            .read(cx)
11448            .text_anchor_for_position(rename.range.end, cx)?;
11449        if buffer != end_buffer {
11450            return None;
11451        }
11452
11453        let old_name = rename.old_name;
11454        let new_name = rename.editor.read(cx).text(cx);
11455
11456        let rename = self.semantics_provider.as_ref()?.perform_rename(
11457            &buffer,
11458            start,
11459            new_name.clone(),
11460            cx,
11461        )?;
11462
11463        Some(cx.spawn_in(window, |editor, mut cx| async move {
11464            let project_transaction = rename.await?;
11465            Self::open_project_transaction(
11466                &editor,
11467                workspace,
11468                project_transaction,
11469                format!("Rename: {}{}", old_name, new_name),
11470                cx.clone(),
11471            )
11472            .await?;
11473
11474            editor.update(&mut cx, |editor, cx| {
11475                editor.refresh_document_highlights(cx);
11476            })?;
11477            Ok(())
11478        }))
11479    }
11480
11481    fn take_rename(
11482        &mut self,
11483        moving_cursor: bool,
11484        window: &mut Window,
11485        cx: &mut Context<Self>,
11486    ) -> Option<RenameState> {
11487        let rename = self.pending_rename.take()?;
11488        if rename.editor.focus_handle(cx).is_focused(window) {
11489            window.focus(&self.focus_handle);
11490        }
11491
11492        self.remove_blocks(
11493            [rename.block_id].into_iter().collect(),
11494            Some(Autoscroll::fit()),
11495            cx,
11496        );
11497        self.clear_highlights::<Rename>(cx);
11498        self.show_local_selections = true;
11499
11500        if moving_cursor {
11501            let cursor_in_rename_editor = rename.editor.update(cx, |editor, cx| {
11502                editor.selections.newest::<usize>(cx).head()
11503            });
11504
11505            // Update the selection to match the position of the selection inside
11506            // the rename editor.
11507            let snapshot = self.buffer.read(cx).read(cx);
11508            let rename_range = rename.range.to_offset(&snapshot);
11509            let cursor_in_editor = snapshot
11510                .clip_offset(rename_range.start + cursor_in_rename_editor, Bias::Left)
11511                .min(rename_range.end);
11512            drop(snapshot);
11513
11514            self.change_selections(None, window, cx, |s| {
11515                s.select_ranges(vec![cursor_in_editor..cursor_in_editor])
11516            });
11517        } else {
11518            self.refresh_document_highlights(cx);
11519        }
11520
11521        Some(rename)
11522    }
11523
11524    pub fn pending_rename(&self) -> Option<&RenameState> {
11525        self.pending_rename.as_ref()
11526    }
11527
11528    fn format(
11529        &mut self,
11530        _: &Format,
11531        window: &mut Window,
11532        cx: &mut Context<Self>,
11533    ) -> Option<Task<Result<()>>> {
11534        let project = match &self.project {
11535            Some(project) => project.clone(),
11536            None => return None,
11537        };
11538
11539        Some(self.perform_format(
11540            project,
11541            FormatTrigger::Manual,
11542            FormatTarget::Buffers,
11543            window,
11544            cx,
11545        ))
11546    }
11547
11548    fn format_selections(
11549        &mut self,
11550        _: &FormatSelections,
11551        window: &mut Window,
11552        cx: &mut Context<Self>,
11553    ) -> Option<Task<Result<()>>> {
11554        let project = match &self.project {
11555            Some(project) => project.clone(),
11556            None => return None,
11557        };
11558
11559        let ranges = self
11560            .selections
11561            .all_adjusted(cx)
11562            .into_iter()
11563            .map(|selection| selection.range())
11564            .collect_vec();
11565
11566        Some(self.perform_format(
11567            project,
11568            FormatTrigger::Manual,
11569            FormatTarget::Ranges(ranges),
11570            window,
11571            cx,
11572        ))
11573    }
11574
11575    fn perform_format(
11576        &mut self,
11577        project: Entity<Project>,
11578        trigger: FormatTrigger,
11579        target: FormatTarget,
11580        window: &mut Window,
11581        cx: &mut Context<Self>,
11582    ) -> Task<Result<()>> {
11583        let buffer = self.buffer.clone();
11584        let (buffers, target) = match target {
11585            FormatTarget::Buffers => {
11586                let mut buffers = buffer.read(cx).all_buffers();
11587                if trigger == FormatTrigger::Save {
11588                    buffers.retain(|buffer| buffer.read(cx).is_dirty());
11589                }
11590                (buffers, LspFormatTarget::Buffers)
11591            }
11592            FormatTarget::Ranges(selection_ranges) => {
11593                let multi_buffer = buffer.read(cx);
11594                let snapshot = multi_buffer.read(cx);
11595                let mut buffers = HashSet::default();
11596                let mut buffer_id_to_ranges: BTreeMap<BufferId, Vec<Range<text::Anchor>>> =
11597                    BTreeMap::new();
11598                for selection_range in selection_ranges {
11599                    for (buffer, buffer_range, _) in
11600                        snapshot.range_to_buffer_ranges(selection_range)
11601                    {
11602                        let buffer_id = buffer.remote_id();
11603                        let start = buffer.anchor_before(buffer_range.start);
11604                        let end = buffer.anchor_after(buffer_range.end);
11605                        buffers.insert(multi_buffer.buffer(buffer_id).unwrap());
11606                        buffer_id_to_ranges
11607                            .entry(buffer_id)
11608                            .and_modify(|buffer_ranges| buffer_ranges.push(start..end))
11609                            .or_insert_with(|| vec![start..end]);
11610                    }
11611                }
11612                (buffers, LspFormatTarget::Ranges(buffer_id_to_ranges))
11613            }
11614        };
11615
11616        let mut timeout = cx.background_executor().timer(FORMAT_TIMEOUT).fuse();
11617        let format = project.update(cx, |project, cx| {
11618            project.format(buffers, target, true, trigger, cx)
11619        });
11620
11621        cx.spawn_in(window, |_, mut cx| async move {
11622            let transaction = futures::select_biased! {
11623                () = timeout => {
11624                    log::warn!("timed out waiting for formatting");
11625                    None
11626                }
11627                transaction = format.log_err().fuse() => transaction,
11628            };
11629
11630            buffer
11631                .update(&mut cx, |buffer, cx| {
11632                    if let Some(transaction) = transaction {
11633                        if !buffer.is_singleton() {
11634                            buffer.push_transaction(&transaction.0, cx);
11635                        }
11636                    }
11637
11638                    cx.notify();
11639                })
11640                .ok();
11641
11642            Ok(())
11643        })
11644    }
11645
11646    fn restart_language_server(
11647        &mut self,
11648        _: &RestartLanguageServer,
11649        _: &mut Window,
11650        cx: &mut Context<Self>,
11651    ) {
11652        if let Some(project) = self.project.clone() {
11653            self.buffer.update(cx, |multi_buffer, cx| {
11654                project.update(cx, |project, cx| {
11655                    project.restart_language_servers_for_buffers(multi_buffer.all_buffers(), cx);
11656                });
11657            })
11658        }
11659    }
11660
11661    fn cancel_language_server_work(
11662        workspace: &mut Workspace,
11663        _: &actions::CancelLanguageServerWork,
11664        _: &mut Window,
11665        cx: &mut Context<Workspace>,
11666    ) {
11667        let project = workspace.project();
11668        let buffers = workspace
11669            .active_item(cx)
11670            .and_then(|item| item.act_as::<Editor>(cx))
11671            .map_or(HashSet::default(), |editor| {
11672                editor.read(cx).buffer.read(cx).all_buffers()
11673            });
11674        project.update(cx, |project, cx| {
11675            project.cancel_language_server_work_for_buffers(buffers, cx);
11676        });
11677    }
11678
11679    fn show_character_palette(
11680        &mut self,
11681        _: &ShowCharacterPalette,
11682        window: &mut Window,
11683        _: &mut Context<Self>,
11684    ) {
11685        window.show_character_palette();
11686    }
11687
11688    fn refresh_active_diagnostics(&mut self, cx: &mut Context<Editor>) {
11689        if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
11690            let buffer = self.buffer.read(cx).snapshot(cx);
11691            let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
11692            let primary_range_end = active_diagnostics.primary_range.end.to_offset(&buffer);
11693            let is_valid = buffer
11694                .diagnostics_in_range::<usize>(primary_range_start..primary_range_end)
11695                .any(|entry| {
11696                    entry.diagnostic.is_primary
11697                        && !entry.range.is_empty()
11698                        && entry.range.start == primary_range_start
11699                        && entry.diagnostic.message == active_diagnostics.primary_message
11700                });
11701
11702            if is_valid != active_diagnostics.is_valid {
11703                active_diagnostics.is_valid = is_valid;
11704                let mut new_styles = HashMap::default();
11705                for (block_id, diagnostic) in &active_diagnostics.blocks {
11706                    new_styles.insert(
11707                        *block_id,
11708                        diagnostic_block_renderer(diagnostic.clone(), None, true, is_valid),
11709                    );
11710                }
11711                self.display_map.update(cx, |display_map, _cx| {
11712                    display_map.replace_blocks(new_styles)
11713                });
11714            }
11715        }
11716    }
11717
11718    fn activate_diagnostics(
11719        &mut self,
11720        buffer_id: BufferId,
11721        group_id: usize,
11722        window: &mut Window,
11723        cx: &mut Context<Self>,
11724    ) {
11725        self.dismiss_diagnostics(cx);
11726        let snapshot = self.snapshot(window, cx);
11727        self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
11728            let buffer = self.buffer.read(cx).snapshot(cx);
11729
11730            let mut primary_range = None;
11731            let mut primary_message = None;
11732            let diagnostic_group = buffer
11733                .diagnostic_group(buffer_id, group_id)
11734                .filter_map(|entry| {
11735                    let start = entry.range.start;
11736                    let end = entry.range.end;
11737                    if snapshot.is_line_folded(MultiBufferRow(start.row))
11738                        && (start.row == end.row
11739                            || snapshot.is_line_folded(MultiBufferRow(end.row)))
11740                    {
11741                        return None;
11742                    }
11743                    if entry.diagnostic.is_primary {
11744                        primary_range = Some(entry.range.clone());
11745                        primary_message = Some(entry.diagnostic.message.clone());
11746                    }
11747                    Some(entry)
11748                })
11749                .collect::<Vec<_>>();
11750            let primary_range = primary_range?;
11751            let primary_message = primary_message?;
11752
11753            let blocks = display_map
11754                .insert_blocks(
11755                    diagnostic_group.iter().map(|entry| {
11756                        let diagnostic = entry.diagnostic.clone();
11757                        let message_height = diagnostic.message.matches('\n').count() as u32 + 1;
11758                        BlockProperties {
11759                            style: BlockStyle::Fixed,
11760                            placement: BlockPlacement::Below(
11761                                buffer.anchor_after(entry.range.start),
11762                            ),
11763                            height: message_height,
11764                            render: diagnostic_block_renderer(diagnostic, None, true, true),
11765                            priority: 0,
11766                        }
11767                    }),
11768                    cx,
11769                )
11770                .into_iter()
11771                .zip(diagnostic_group.into_iter().map(|entry| entry.diagnostic))
11772                .collect();
11773
11774            Some(ActiveDiagnosticGroup {
11775                primary_range: buffer.anchor_before(primary_range.start)
11776                    ..buffer.anchor_after(primary_range.end),
11777                primary_message,
11778                group_id,
11779                blocks,
11780                is_valid: true,
11781            })
11782        });
11783    }
11784
11785    fn dismiss_diagnostics(&mut self, cx: &mut Context<Self>) {
11786        if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
11787            self.display_map.update(cx, |display_map, cx| {
11788                display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx);
11789            });
11790            cx.notify();
11791        }
11792    }
11793
11794    pub fn set_selections_from_remote(
11795        &mut self,
11796        selections: Vec<Selection<Anchor>>,
11797        pending_selection: Option<Selection<Anchor>>,
11798        window: &mut Window,
11799        cx: &mut Context<Self>,
11800    ) {
11801        let old_cursor_position = self.selections.newest_anchor().head();
11802        self.selections.change_with(cx, |s| {
11803            s.select_anchors(selections);
11804            if let Some(pending_selection) = pending_selection {
11805                s.set_pending(pending_selection, SelectMode::Character);
11806            } else {
11807                s.clear_pending();
11808            }
11809        });
11810        self.selections_did_change(false, &old_cursor_position, true, window, cx);
11811    }
11812
11813    fn push_to_selection_history(&mut self) {
11814        self.selection_history.push(SelectionHistoryEntry {
11815            selections: self.selections.disjoint_anchors(),
11816            select_next_state: self.select_next_state.clone(),
11817            select_prev_state: self.select_prev_state.clone(),
11818            add_selections_state: self.add_selections_state.clone(),
11819        });
11820    }
11821
11822    pub fn transact(
11823        &mut self,
11824        window: &mut Window,
11825        cx: &mut Context<Self>,
11826        update: impl FnOnce(&mut Self, &mut Window, &mut Context<Self>),
11827    ) -> Option<TransactionId> {
11828        self.start_transaction_at(Instant::now(), window, cx);
11829        update(self, window, cx);
11830        self.end_transaction_at(Instant::now(), cx)
11831    }
11832
11833    pub fn start_transaction_at(
11834        &mut self,
11835        now: Instant,
11836        window: &mut Window,
11837        cx: &mut Context<Self>,
11838    ) {
11839        self.end_selection(window, cx);
11840        if let Some(tx_id) = self
11841            .buffer
11842            .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx))
11843        {
11844            self.selection_history
11845                .insert_transaction(tx_id, self.selections.disjoint_anchors());
11846            cx.emit(EditorEvent::TransactionBegun {
11847                transaction_id: tx_id,
11848            })
11849        }
11850    }
11851
11852    pub fn end_transaction_at(
11853        &mut self,
11854        now: Instant,
11855        cx: &mut Context<Self>,
11856    ) -> Option<TransactionId> {
11857        if let Some(transaction_id) = self
11858            .buffer
11859            .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
11860        {
11861            if let Some((_, end_selections)) =
11862                self.selection_history.transaction_mut(transaction_id)
11863            {
11864                *end_selections = Some(self.selections.disjoint_anchors());
11865            } else {
11866                log::error!("unexpectedly ended a transaction that wasn't started by this editor");
11867            }
11868
11869            cx.emit(EditorEvent::Edited { transaction_id });
11870            Some(transaction_id)
11871        } else {
11872            None
11873        }
11874    }
11875
11876    pub fn set_mark(&mut self, _: &actions::SetMark, window: &mut Window, cx: &mut Context<Self>) {
11877        if self.selection_mark_mode {
11878            self.change_selections(None, window, cx, |s| {
11879                s.move_with(|_, sel| {
11880                    sel.collapse_to(sel.head(), SelectionGoal::None);
11881                });
11882            })
11883        }
11884        self.selection_mark_mode = true;
11885        cx.notify();
11886    }
11887
11888    pub fn swap_selection_ends(
11889        &mut self,
11890        _: &actions::SwapSelectionEnds,
11891        window: &mut Window,
11892        cx: &mut Context<Self>,
11893    ) {
11894        self.change_selections(None, window, cx, |s| {
11895            s.move_with(|_, sel| {
11896                if sel.start != sel.end {
11897                    sel.reversed = !sel.reversed
11898                }
11899            });
11900        });
11901        self.request_autoscroll(Autoscroll::newest(), cx);
11902        cx.notify();
11903    }
11904
11905    pub fn toggle_fold(
11906        &mut self,
11907        _: &actions::ToggleFold,
11908        window: &mut Window,
11909        cx: &mut Context<Self>,
11910    ) {
11911        if self.is_singleton(cx) {
11912            let selection = self.selections.newest::<Point>(cx);
11913
11914            let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
11915            let range = if selection.is_empty() {
11916                let point = selection.head().to_display_point(&display_map);
11917                let start = DisplayPoint::new(point.row(), 0).to_point(&display_map);
11918                let end = DisplayPoint::new(point.row(), display_map.line_len(point.row()))
11919                    .to_point(&display_map);
11920                start..end
11921            } else {
11922                selection.range()
11923            };
11924            if display_map.folds_in_range(range).next().is_some() {
11925                self.unfold_lines(&Default::default(), window, cx)
11926            } else {
11927                self.fold(&Default::default(), window, cx)
11928            }
11929        } else {
11930            let multi_buffer_snapshot = self.buffer.read(cx).snapshot(cx);
11931            let buffer_ids: HashSet<_> = multi_buffer_snapshot
11932                .ranges_to_buffer_ranges(self.selections.disjoint_anchor_ranges())
11933                .map(|(snapshot, _, _)| snapshot.remote_id())
11934                .collect();
11935
11936            for buffer_id in buffer_ids {
11937                if self.is_buffer_folded(buffer_id, cx) {
11938                    self.unfold_buffer(buffer_id, cx);
11939                } else {
11940                    self.fold_buffer(buffer_id, cx);
11941                }
11942            }
11943        }
11944    }
11945
11946    pub fn toggle_fold_recursive(
11947        &mut self,
11948        _: &actions::ToggleFoldRecursive,
11949        window: &mut Window,
11950        cx: &mut Context<Self>,
11951    ) {
11952        let selection = self.selections.newest::<Point>(cx);
11953
11954        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
11955        let range = if selection.is_empty() {
11956            let point = selection.head().to_display_point(&display_map);
11957            let start = DisplayPoint::new(point.row(), 0).to_point(&display_map);
11958            let end = DisplayPoint::new(point.row(), display_map.line_len(point.row()))
11959                .to_point(&display_map);
11960            start..end
11961        } else {
11962            selection.range()
11963        };
11964        if display_map.folds_in_range(range).next().is_some() {
11965            self.unfold_recursive(&Default::default(), window, cx)
11966        } else {
11967            self.fold_recursive(&Default::default(), window, cx)
11968        }
11969    }
11970
11971    pub fn fold(&mut self, _: &actions::Fold, window: &mut Window, cx: &mut Context<Self>) {
11972        if self.is_singleton(cx) {
11973            let mut to_fold = Vec::new();
11974            let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
11975            let selections = self.selections.all_adjusted(cx);
11976
11977            for selection in selections {
11978                let range = selection.range().sorted();
11979                let buffer_start_row = range.start.row;
11980
11981                if range.start.row != range.end.row {
11982                    let mut found = false;
11983                    let mut row = range.start.row;
11984                    while row <= range.end.row {
11985                        if let Some(crease) = display_map.crease_for_buffer_row(MultiBufferRow(row))
11986                        {
11987                            found = true;
11988                            row = crease.range().end.row + 1;
11989                            to_fold.push(crease);
11990                        } else {
11991                            row += 1
11992                        }
11993                    }
11994                    if found {
11995                        continue;
11996                    }
11997                }
11998
11999                for row in (0..=range.start.row).rev() {
12000                    if let Some(crease) = display_map.crease_for_buffer_row(MultiBufferRow(row)) {
12001                        if crease.range().end.row >= buffer_start_row {
12002                            to_fold.push(crease);
12003                            if row <= range.start.row {
12004                                break;
12005                            }
12006                        }
12007                    }
12008                }
12009            }
12010
12011            self.fold_creases(to_fold, true, window, cx);
12012        } else {
12013            let multi_buffer_snapshot = self.buffer.read(cx).snapshot(cx);
12014
12015            let buffer_ids: HashSet<_> = multi_buffer_snapshot
12016                .ranges_to_buffer_ranges(self.selections.disjoint_anchor_ranges())
12017                .map(|(snapshot, _, _)| snapshot.remote_id())
12018                .collect();
12019            for buffer_id in buffer_ids {
12020                self.fold_buffer(buffer_id, cx);
12021            }
12022        }
12023    }
12024
12025    fn fold_at_level(
12026        &mut self,
12027        fold_at: &FoldAtLevel,
12028        window: &mut Window,
12029        cx: &mut Context<Self>,
12030    ) {
12031        if !self.buffer.read(cx).is_singleton() {
12032            return;
12033        }
12034
12035        let fold_at_level = fold_at.0;
12036        let snapshot = self.buffer.read(cx).snapshot(cx);
12037        let mut to_fold = Vec::new();
12038        let mut stack = vec![(0, snapshot.max_row().0, 1)];
12039
12040        while let Some((mut start_row, end_row, current_level)) = stack.pop() {
12041            while start_row < end_row {
12042                match self
12043                    .snapshot(window, cx)
12044                    .crease_for_buffer_row(MultiBufferRow(start_row))
12045                {
12046                    Some(crease) => {
12047                        let nested_start_row = crease.range().start.row + 1;
12048                        let nested_end_row = crease.range().end.row;
12049
12050                        if current_level < fold_at_level {
12051                            stack.push((nested_start_row, nested_end_row, current_level + 1));
12052                        } else if current_level == fold_at_level {
12053                            to_fold.push(crease);
12054                        }
12055
12056                        start_row = nested_end_row + 1;
12057                    }
12058                    None => start_row += 1,
12059                }
12060            }
12061        }
12062
12063        self.fold_creases(to_fold, true, window, cx);
12064    }
12065
12066    pub fn fold_all(&mut self, _: &actions::FoldAll, window: &mut Window, cx: &mut Context<Self>) {
12067        if self.buffer.read(cx).is_singleton() {
12068            let mut fold_ranges = Vec::new();
12069            let snapshot = self.buffer.read(cx).snapshot(cx);
12070
12071            for row in 0..snapshot.max_row().0 {
12072                if let Some(foldable_range) = self
12073                    .snapshot(window, cx)
12074                    .crease_for_buffer_row(MultiBufferRow(row))
12075                {
12076                    fold_ranges.push(foldable_range);
12077                }
12078            }
12079
12080            self.fold_creases(fold_ranges, true, window, cx);
12081        } else {
12082            self.toggle_fold_multiple_buffers = cx.spawn_in(window, |editor, mut cx| async move {
12083                editor
12084                    .update_in(&mut cx, |editor, _, cx| {
12085                        for buffer_id in editor.buffer.read(cx).excerpt_buffer_ids() {
12086                            editor.fold_buffer(buffer_id, cx);
12087                        }
12088                    })
12089                    .ok();
12090            });
12091        }
12092    }
12093
12094    pub fn fold_function_bodies(
12095        &mut self,
12096        _: &actions::FoldFunctionBodies,
12097        window: &mut Window,
12098        cx: &mut Context<Self>,
12099    ) {
12100        let snapshot = self.buffer.read(cx).snapshot(cx);
12101
12102        let ranges = snapshot
12103            .text_object_ranges(0..snapshot.len(), TreeSitterOptions::default())
12104            .filter_map(|(range, obj)| (obj == TextObject::InsideFunction).then_some(range))
12105            .collect::<Vec<_>>();
12106
12107        let creases = ranges
12108            .into_iter()
12109            .map(|range| Crease::simple(range, self.display_map.read(cx).fold_placeholder.clone()))
12110            .collect();
12111
12112        self.fold_creases(creases, true, window, cx);
12113    }
12114
12115    pub fn fold_recursive(
12116        &mut self,
12117        _: &actions::FoldRecursive,
12118        window: &mut Window,
12119        cx: &mut Context<Self>,
12120    ) {
12121        let mut to_fold = Vec::new();
12122        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
12123        let selections = self.selections.all_adjusted(cx);
12124
12125        for selection in selections {
12126            let range = selection.range().sorted();
12127            let buffer_start_row = range.start.row;
12128
12129            if range.start.row != range.end.row {
12130                let mut found = false;
12131                for row in range.start.row..=range.end.row {
12132                    if let Some(crease) = display_map.crease_for_buffer_row(MultiBufferRow(row)) {
12133                        found = true;
12134                        to_fold.push(crease);
12135                    }
12136                }
12137                if found {
12138                    continue;
12139                }
12140            }
12141
12142            for row in (0..=range.start.row).rev() {
12143                if let Some(crease) = display_map.crease_for_buffer_row(MultiBufferRow(row)) {
12144                    if crease.range().end.row >= buffer_start_row {
12145                        to_fold.push(crease);
12146                    } else {
12147                        break;
12148                    }
12149                }
12150            }
12151        }
12152
12153        self.fold_creases(to_fold, true, window, cx);
12154    }
12155
12156    pub fn fold_at(&mut self, fold_at: &FoldAt, window: &mut Window, cx: &mut Context<Self>) {
12157        let buffer_row = fold_at.buffer_row;
12158        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
12159
12160        if let Some(crease) = display_map.crease_for_buffer_row(buffer_row) {
12161            let autoscroll = self
12162                .selections
12163                .all::<Point>(cx)
12164                .iter()
12165                .any(|selection| crease.range().overlaps(&selection.range()));
12166
12167            self.fold_creases(vec![crease], autoscroll, window, cx);
12168        }
12169    }
12170
12171    pub fn unfold_lines(&mut self, _: &UnfoldLines, _window: &mut Window, cx: &mut Context<Self>) {
12172        if self.is_singleton(cx) {
12173            let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
12174            let buffer = &display_map.buffer_snapshot;
12175            let selections = self.selections.all::<Point>(cx);
12176            let ranges = selections
12177                .iter()
12178                .map(|s| {
12179                    let range = s.display_range(&display_map).sorted();
12180                    let mut start = range.start.to_point(&display_map);
12181                    let mut end = range.end.to_point(&display_map);
12182                    start.column = 0;
12183                    end.column = buffer.line_len(MultiBufferRow(end.row));
12184                    start..end
12185                })
12186                .collect::<Vec<_>>();
12187
12188            self.unfold_ranges(&ranges, true, true, cx);
12189        } else {
12190            let multi_buffer_snapshot = self.buffer.read(cx).snapshot(cx);
12191            let buffer_ids: HashSet<_> = multi_buffer_snapshot
12192                .ranges_to_buffer_ranges(self.selections.disjoint_anchor_ranges())
12193                .map(|(snapshot, _, _)| snapshot.remote_id())
12194                .collect();
12195            for buffer_id in buffer_ids {
12196                self.unfold_buffer(buffer_id, cx);
12197            }
12198        }
12199    }
12200
12201    pub fn unfold_recursive(
12202        &mut self,
12203        _: &UnfoldRecursive,
12204        _window: &mut Window,
12205        cx: &mut Context<Self>,
12206    ) {
12207        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
12208        let selections = self.selections.all::<Point>(cx);
12209        let ranges = selections
12210            .iter()
12211            .map(|s| {
12212                let mut range = s.display_range(&display_map).sorted();
12213                *range.start.column_mut() = 0;
12214                *range.end.column_mut() = display_map.line_len(range.end.row());
12215                let start = range.start.to_point(&display_map);
12216                let end = range.end.to_point(&display_map);
12217                start..end
12218            })
12219            .collect::<Vec<_>>();
12220
12221        self.unfold_ranges(&ranges, true, true, cx);
12222    }
12223
12224    pub fn unfold_at(
12225        &mut self,
12226        unfold_at: &UnfoldAt,
12227        _window: &mut Window,
12228        cx: &mut Context<Self>,
12229    ) {
12230        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
12231
12232        let intersection_range = Point::new(unfold_at.buffer_row.0, 0)
12233            ..Point::new(
12234                unfold_at.buffer_row.0,
12235                display_map.buffer_snapshot.line_len(unfold_at.buffer_row),
12236            );
12237
12238        let autoscroll = self
12239            .selections
12240            .all::<Point>(cx)
12241            .iter()
12242            .any(|selection| RangeExt::overlaps(&selection.range(), &intersection_range));
12243
12244        self.unfold_ranges(&[intersection_range], true, autoscroll, cx);
12245    }
12246
12247    pub fn unfold_all(
12248        &mut self,
12249        _: &actions::UnfoldAll,
12250        _window: &mut Window,
12251        cx: &mut Context<Self>,
12252    ) {
12253        if self.buffer.read(cx).is_singleton() {
12254            let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
12255            self.unfold_ranges(&[0..display_map.buffer_snapshot.len()], true, true, cx);
12256        } else {
12257            self.toggle_fold_multiple_buffers = cx.spawn(|editor, mut cx| async move {
12258                editor
12259                    .update(&mut cx, |editor, cx| {
12260                        for buffer_id in editor.buffer.read(cx).excerpt_buffer_ids() {
12261                            editor.unfold_buffer(buffer_id, cx);
12262                        }
12263                    })
12264                    .ok();
12265            });
12266        }
12267    }
12268
12269    pub fn fold_selected_ranges(
12270        &mut self,
12271        _: &FoldSelectedRanges,
12272        window: &mut Window,
12273        cx: &mut Context<Self>,
12274    ) {
12275        let selections = self.selections.all::<Point>(cx);
12276        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
12277        let line_mode = self.selections.line_mode;
12278        let ranges = selections
12279            .into_iter()
12280            .map(|s| {
12281                if line_mode {
12282                    let start = Point::new(s.start.row, 0);
12283                    let end = Point::new(
12284                        s.end.row,
12285                        display_map
12286                            .buffer_snapshot
12287                            .line_len(MultiBufferRow(s.end.row)),
12288                    );
12289                    Crease::simple(start..end, display_map.fold_placeholder.clone())
12290                } else {
12291                    Crease::simple(s.start..s.end, display_map.fold_placeholder.clone())
12292                }
12293            })
12294            .collect::<Vec<_>>();
12295        self.fold_creases(ranges, true, window, cx);
12296    }
12297
12298    pub fn fold_ranges<T: ToOffset + Clone>(
12299        &mut self,
12300        ranges: Vec<Range<T>>,
12301        auto_scroll: bool,
12302        window: &mut Window,
12303        cx: &mut Context<Self>,
12304    ) {
12305        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
12306        let ranges = ranges
12307            .into_iter()
12308            .map(|r| Crease::simple(r, display_map.fold_placeholder.clone()))
12309            .collect::<Vec<_>>();
12310        self.fold_creases(ranges, auto_scroll, window, cx);
12311    }
12312
12313    pub fn fold_creases<T: ToOffset + Clone>(
12314        &mut self,
12315        creases: Vec<Crease<T>>,
12316        auto_scroll: bool,
12317        window: &mut Window,
12318        cx: &mut Context<Self>,
12319    ) {
12320        if creases.is_empty() {
12321            return;
12322        }
12323
12324        let mut buffers_affected = HashSet::default();
12325        let multi_buffer = self.buffer().read(cx);
12326        for crease in &creases {
12327            if let Some((_, buffer, _)) =
12328                multi_buffer.excerpt_containing(crease.range().start.clone(), cx)
12329            {
12330                buffers_affected.insert(buffer.read(cx).remote_id());
12331            };
12332        }
12333
12334        self.display_map.update(cx, |map, cx| map.fold(creases, cx));
12335
12336        if auto_scroll {
12337            self.request_autoscroll(Autoscroll::fit(), cx);
12338        }
12339
12340        cx.notify();
12341
12342        if let Some(active_diagnostics) = self.active_diagnostics.take() {
12343            // Clear diagnostics block when folding a range that contains it.
12344            let snapshot = self.snapshot(window, cx);
12345            if snapshot.intersects_fold(active_diagnostics.primary_range.start) {
12346                drop(snapshot);
12347                self.active_diagnostics = Some(active_diagnostics);
12348                self.dismiss_diagnostics(cx);
12349            } else {
12350                self.active_diagnostics = Some(active_diagnostics);
12351            }
12352        }
12353
12354        self.scrollbar_marker_state.dirty = true;
12355    }
12356
12357    /// Removes any folds whose ranges intersect any of the given ranges.
12358    pub fn unfold_ranges<T: ToOffset + Clone>(
12359        &mut self,
12360        ranges: &[Range<T>],
12361        inclusive: bool,
12362        auto_scroll: bool,
12363        cx: &mut Context<Self>,
12364    ) {
12365        self.remove_folds_with(ranges, auto_scroll, cx, |map, cx| {
12366            map.unfold_intersecting(ranges.iter().cloned(), inclusive, cx)
12367        });
12368    }
12369
12370    pub fn fold_buffer(&mut self, buffer_id: BufferId, cx: &mut Context<Self>) {
12371        if self.buffer().read(cx).is_singleton() || self.is_buffer_folded(buffer_id, cx) {
12372            return;
12373        }
12374        let folded_excerpts = self.buffer().read(cx).excerpts_for_buffer(buffer_id, cx);
12375        self.display_map
12376            .update(cx, |display_map, cx| display_map.fold_buffer(buffer_id, cx));
12377        cx.emit(EditorEvent::BufferFoldToggled {
12378            ids: folded_excerpts.iter().map(|&(id, _)| id).collect(),
12379            folded: true,
12380        });
12381        cx.notify();
12382    }
12383
12384    pub fn unfold_buffer(&mut self, buffer_id: BufferId, cx: &mut Context<Self>) {
12385        if self.buffer().read(cx).is_singleton() || !self.is_buffer_folded(buffer_id, cx) {
12386            return;
12387        }
12388        let unfolded_excerpts = self.buffer().read(cx).excerpts_for_buffer(buffer_id, cx);
12389        self.display_map.update(cx, |display_map, cx| {
12390            display_map.unfold_buffer(buffer_id, cx);
12391        });
12392        cx.emit(EditorEvent::BufferFoldToggled {
12393            ids: unfolded_excerpts.iter().map(|&(id, _)| id).collect(),
12394            folded: false,
12395        });
12396        cx.notify();
12397    }
12398
12399    pub fn is_buffer_folded(&self, buffer: BufferId, cx: &App) -> bool {
12400        self.display_map.read(cx).is_buffer_folded(buffer)
12401    }
12402
12403    pub fn folded_buffers<'a>(&self, cx: &'a App) -> &'a HashSet<BufferId> {
12404        self.display_map.read(cx).folded_buffers()
12405    }
12406
12407    /// Removes any folds with the given ranges.
12408    pub fn remove_folds_with_type<T: ToOffset + Clone>(
12409        &mut self,
12410        ranges: &[Range<T>],
12411        type_id: TypeId,
12412        auto_scroll: bool,
12413        cx: &mut Context<Self>,
12414    ) {
12415        self.remove_folds_with(ranges, auto_scroll, cx, |map, cx| {
12416            map.remove_folds_with_type(ranges.iter().cloned(), type_id, cx)
12417        });
12418    }
12419
12420    fn remove_folds_with<T: ToOffset + Clone>(
12421        &mut self,
12422        ranges: &[Range<T>],
12423        auto_scroll: bool,
12424        cx: &mut Context<Self>,
12425        update: impl FnOnce(&mut DisplayMap, &mut Context<DisplayMap>),
12426    ) {
12427        if ranges.is_empty() {
12428            return;
12429        }
12430
12431        let mut buffers_affected = HashSet::default();
12432        let multi_buffer = self.buffer().read(cx);
12433        for range in ranges {
12434            if let Some((_, buffer, _)) = multi_buffer.excerpt_containing(range.start.clone(), cx) {
12435                buffers_affected.insert(buffer.read(cx).remote_id());
12436            };
12437        }
12438
12439        self.display_map.update(cx, update);
12440
12441        if auto_scroll {
12442            self.request_autoscroll(Autoscroll::fit(), cx);
12443        }
12444
12445        cx.notify();
12446        self.scrollbar_marker_state.dirty = true;
12447        self.active_indent_guides_state.dirty = true;
12448    }
12449
12450    pub fn default_fold_placeholder(&self, cx: &App) -> FoldPlaceholder {
12451        self.display_map.read(cx).fold_placeholder.clone()
12452    }
12453
12454    pub fn set_expand_all_diff_hunks(&mut self, cx: &mut App) {
12455        self.buffer.update(cx, |buffer, cx| {
12456            buffer.set_all_diff_hunks_expanded(cx);
12457        });
12458    }
12459
12460    pub fn set_distinguish_unstaged_diff_hunks(&mut self) {
12461        self.distinguish_unstaged_diff_hunks = true;
12462    }
12463
12464    pub fn expand_all_diff_hunks(
12465        &mut self,
12466        _: &ExpandAllHunkDiffs,
12467        _window: &mut Window,
12468        cx: &mut Context<Self>,
12469    ) {
12470        self.buffer.update(cx, |buffer, cx| {
12471            buffer.expand_diff_hunks(vec![Anchor::min()..Anchor::max()], cx)
12472        });
12473    }
12474
12475    pub fn toggle_selected_diff_hunks(
12476        &mut self,
12477        _: &ToggleSelectedDiffHunks,
12478        _window: &mut Window,
12479        cx: &mut Context<Self>,
12480    ) {
12481        let ranges: Vec<_> = self.selections.disjoint.iter().map(|s| s.range()).collect();
12482        self.toggle_diff_hunks_in_ranges(ranges, cx);
12483    }
12484
12485    fn diff_hunks_in_ranges<'a>(
12486        &'a self,
12487        ranges: &'a [Range<Anchor>],
12488        buffer: &'a MultiBufferSnapshot,
12489    ) -> impl 'a + Iterator<Item = MultiBufferDiffHunk> {
12490        ranges.iter().flat_map(move |range| {
12491            let end_excerpt_id = range.end.excerpt_id;
12492            let range = range.to_point(buffer);
12493            let mut peek_end = range.end;
12494            if range.end.row < buffer.max_row().0 {
12495                peek_end = Point::new(range.end.row + 1, 0);
12496            }
12497            buffer
12498                .diff_hunks_in_range(range.start..peek_end)
12499                .filter(move |hunk| hunk.excerpt_id.cmp(&end_excerpt_id, buffer).is_le())
12500        })
12501    }
12502
12503    pub fn has_stageable_diff_hunks_in_ranges(
12504        &self,
12505        ranges: &[Range<Anchor>],
12506        snapshot: &MultiBufferSnapshot,
12507    ) -> bool {
12508        let mut hunks = self.diff_hunks_in_ranges(ranges, &snapshot);
12509        hunks.any(|hunk| hunk.secondary_status == DiffHunkSecondaryStatus::HasSecondaryHunk)
12510    }
12511
12512    pub fn toggle_staged_selected_diff_hunks(
12513        &mut self,
12514        _: &ToggleStagedSelectedDiffHunks,
12515        _window: &mut Window,
12516        cx: &mut Context<Self>,
12517    ) {
12518        let ranges: Vec<_> = self.selections.disjoint.iter().map(|s| s.range()).collect();
12519        self.stage_or_unstage_diff_hunks(&ranges, cx);
12520    }
12521
12522    pub fn stage_or_unstage_diff_hunks(
12523        &mut self,
12524        ranges: &[Range<Anchor>],
12525        cx: &mut Context<Self>,
12526    ) {
12527        let Some(project) = &self.project else {
12528            return;
12529        };
12530        let snapshot = self.buffer.read(cx).snapshot(cx);
12531        let stage = self.has_stageable_diff_hunks_in_ranges(ranges, &snapshot);
12532
12533        let chunk_by = self
12534            .diff_hunks_in_ranges(&ranges, &snapshot)
12535            .chunk_by(|hunk| hunk.buffer_id);
12536        for (buffer_id, hunks) in &chunk_by {
12537            let Some(buffer) = project.read(cx).buffer_for_id(buffer_id, cx) else {
12538                log::debug!("no buffer for id");
12539                continue;
12540            };
12541            let buffer = buffer.read(cx).snapshot();
12542            let Some((repo, path)) = project
12543                .read(cx)
12544                .repository_and_path_for_buffer_id(buffer_id, cx)
12545            else {
12546                log::debug!("no git repo for buffer id");
12547                continue;
12548            };
12549            let Some(diff) = snapshot.diff_for_buffer_id(buffer_id) else {
12550                log::debug!("no diff for buffer id");
12551                continue;
12552            };
12553            let Some(secondary_diff) = diff.secondary_diff() else {
12554                log::debug!("no secondary diff for buffer id");
12555                continue;
12556            };
12557
12558            let edits = diff.secondary_edits_for_stage_or_unstage(
12559                stage,
12560                hunks.map(|hunk| {
12561                    (
12562                        hunk.diff_base_byte_range.clone(),
12563                        hunk.secondary_diff_base_byte_range.clone(),
12564                        hunk.buffer_range.clone(),
12565                    )
12566                }),
12567                &buffer,
12568            );
12569
12570            let index_base = secondary_diff.base_text().map_or_else(
12571                || Rope::from(""),
12572                |snapshot| snapshot.text.as_rope().clone(),
12573            );
12574            let index_buffer = cx.new(|cx| {
12575                Buffer::local_normalized(index_base.clone(), text::LineEnding::default(), cx)
12576            });
12577            let new_index_text = index_buffer.update(cx, |index_buffer, cx| {
12578                index_buffer.edit(edits, None, cx);
12579                index_buffer.snapshot().as_rope().to_string()
12580            });
12581            let new_index_text = if new_index_text.is_empty()
12582                && (diff.is_single_insertion
12583                    || buffer
12584                        .file()
12585                        .map_or(false, |file| file.disk_state() == DiskState::New))
12586            {
12587                log::debug!("removing from index");
12588                None
12589            } else {
12590                Some(new_index_text)
12591            };
12592
12593            let _ = repo.read(cx).set_index_text(&path, new_index_text);
12594        }
12595    }
12596
12597    pub fn expand_selected_diff_hunks(&mut self, cx: &mut Context<Self>) {
12598        let ranges: Vec<_> = self.selections.disjoint.iter().map(|s| s.range()).collect();
12599        self.buffer
12600            .update(cx, |buffer, cx| buffer.expand_diff_hunks(ranges, cx))
12601    }
12602
12603    pub fn clear_expanded_diff_hunks(&mut self, cx: &mut Context<Self>) -> bool {
12604        self.buffer.update(cx, |buffer, cx| {
12605            let ranges = vec![Anchor::min()..Anchor::max()];
12606            if !buffer.all_diff_hunks_expanded()
12607                && buffer.has_expanded_diff_hunks_in_ranges(&ranges, cx)
12608            {
12609                buffer.collapse_diff_hunks(ranges, cx);
12610                true
12611            } else {
12612                false
12613            }
12614        })
12615    }
12616
12617    fn toggle_diff_hunks_in_ranges(
12618        &mut self,
12619        ranges: Vec<Range<Anchor>>,
12620        cx: &mut Context<'_, Editor>,
12621    ) {
12622        self.buffer.update(cx, |buffer, cx| {
12623            let expand = !buffer.has_expanded_diff_hunks_in_ranges(&ranges, cx);
12624            buffer.expand_or_collapse_diff_hunks(ranges, expand, cx);
12625        })
12626    }
12627
12628    fn toggle_diff_hunks_in_ranges_narrow(
12629        &mut self,
12630        ranges: Vec<Range<Anchor>>,
12631        cx: &mut Context<'_, Editor>,
12632    ) {
12633        self.buffer.update(cx, |buffer, cx| {
12634            let expand = !buffer.has_expanded_diff_hunks_in_ranges(&ranges, cx);
12635            buffer.expand_or_collapse_diff_hunks_narrow(ranges, expand, cx);
12636        })
12637    }
12638
12639    pub(crate) fn apply_all_diff_hunks(
12640        &mut self,
12641        _: &ApplyAllDiffHunks,
12642        window: &mut Window,
12643        cx: &mut Context<Self>,
12644    ) {
12645        let buffers = self.buffer.read(cx).all_buffers();
12646        for branch_buffer in buffers {
12647            branch_buffer.update(cx, |branch_buffer, cx| {
12648                branch_buffer.merge_into_base(Vec::new(), cx);
12649            });
12650        }
12651
12652        if let Some(project) = self.project.clone() {
12653            self.save(true, project, window, cx).detach_and_log_err(cx);
12654        }
12655    }
12656
12657    pub(crate) fn apply_selected_diff_hunks(
12658        &mut self,
12659        _: &ApplyDiffHunk,
12660        window: &mut Window,
12661        cx: &mut Context<Self>,
12662    ) {
12663        let snapshot = self.snapshot(window, cx);
12664        let hunks = snapshot.hunks_for_ranges(self.selections.ranges(cx).into_iter());
12665        let mut ranges_by_buffer = HashMap::default();
12666        self.transact(window, cx, |editor, _window, cx| {
12667            for hunk in hunks {
12668                if let Some(buffer) = editor.buffer.read(cx).buffer(hunk.buffer_id) {
12669                    ranges_by_buffer
12670                        .entry(buffer.clone())
12671                        .or_insert_with(Vec::new)
12672                        .push(hunk.buffer_range.to_offset(buffer.read(cx)));
12673                }
12674            }
12675
12676            for (buffer, ranges) in ranges_by_buffer {
12677                buffer.update(cx, |buffer, cx| {
12678                    buffer.merge_into_base(ranges, cx);
12679                });
12680            }
12681        });
12682
12683        if let Some(project) = self.project.clone() {
12684            self.save(true, project, window, cx).detach_and_log_err(cx);
12685        }
12686    }
12687
12688    pub fn set_gutter_hovered(&mut self, hovered: bool, cx: &mut Context<Self>) {
12689        if hovered != self.gutter_hovered {
12690            self.gutter_hovered = hovered;
12691            cx.notify();
12692        }
12693    }
12694
12695    pub fn insert_blocks(
12696        &mut self,
12697        blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
12698        autoscroll: Option<Autoscroll>,
12699        cx: &mut Context<Self>,
12700    ) -> Vec<CustomBlockId> {
12701        let blocks = self
12702            .display_map
12703            .update(cx, |display_map, cx| display_map.insert_blocks(blocks, cx));
12704        if let Some(autoscroll) = autoscroll {
12705            self.request_autoscroll(autoscroll, cx);
12706        }
12707        cx.notify();
12708        blocks
12709    }
12710
12711    pub fn resize_blocks(
12712        &mut self,
12713        heights: HashMap<CustomBlockId, u32>,
12714        autoscroll: Option<Autoscroll>,
12715        cx: &mut Context<Self>,
12716    ) {
12717        self.display_map
12718            .update(cx, |display_map, cx| display_map.resize_blocks(heights, cx));
12719        if let Some(autoscroll) = autoscroll {
12720            self.request_autoscroll(autoscroll, cx);
12721        }
12722        cx.notify();
12723    }
12724
12725    pub fn replace_blocks(
12726        &mut self,
12727        renderers: HashMap<CustomBlockId, RenderBlock>,
12728        autoscroll: Option<Autoscroll>,
12729        cx: &mut Context<Self>,
12730    ) {
12731        self.display_map
12732            .update(cx, |display_map, _cx| display_map.replace_blocks(renderers));
12733        if let Some(autoscroll) = autoscroll {
12734            self.request_autoscroll(autoscroll, cx);
12735        }
12736        cx.notify();
12737    }
12738
12739    pub fn remove_blocks(
12740        &mut self,
12741        block_ids: HashSet<CustomBlockId>,
12742        autoscroll: Option<Autoscroll>,
12743        cx: &mut Context<Self>,
12744    ) {
12745        self.display_map.update(cx, |display_map, cx| {
12746            display_map.remove_blocks(block_ids, cx)
12747        });
12748        if let Some(autoscroll) = autoscroll {
12749            self.request_autoscroll(autoscroll, cx);
12750        }
12751        cx.notify();
12752    }
12753
12754    pub fn row_for_block(
12755        &self,
12756        block_id: CustomBlockId,
12757        cx: &mut Context<Self>,
12758    ) -> Option<DisplayRow> {
12759        self.display_map
12760            .update(cx, |map, cx| map.row_for_block(block_id, cx))
12761    }
12762
12763    pub(crate) fn set_focused_block(&mut self, focused_block: FocusedBlock) {
12764        self.focused_block = Some(focused_block);
12765    }
12766
12767    pub(crate) fn take_focused_block(&mut self) -> Option<FocusedBlock> {
12768        self.focused_block.take()
12769    }
12770
12771    pub fn insert_creases(
12772        &mut self,
12773        creases: impl IntoIterator<Item = Crease<Anchor>>,
12774        cx: &mut Context<Self>,
12775    ) -> Vec<CreaseId> {
12776        self.display_map
12777            .update(cx, |map, cx| map.insert_creases(creases, cx))
12778    }
12779
12780    pub fn remove_creases(
12781        &mut self,
12782        ids: impl IntoIterator<Item = CreaseId>,
12783        cx: &mut Context<Self>,
12784    ) {
12785        self.display_map
12786            .update(cx, |map, cx| map.remove_creases(ids, cx));
12787    }
12788
12789    pub fn longest_row(&self, cx: &mut App) -> DisplayRow {
12790        self.display_map
12791            .update(cx, |map, cx| map.snapshot(cx))
12792            .longest_row()
12793    }
12794
12795    pub fn max_point(&self, cx: &mut App) -> DisplayPoint {
12796        self.display_map
12797            .update(cx, |map, cx| map.snapshot(cx))
12798            .max_point()
12799    }
12800
12801    pub fn text(&self, cx: &App) -> String {
12802        self.buffer.read(cx).read(cx).text()
12803    }
12804
12805    pub fn is_empty(&self, cx: &App) -> bool {
12806        self.buffer.read(cx).read(cx).is_empty()
12807    }
12808
12809    pub fn text_option(&self, cx: &App) -> Option<String> {
12810        let text = self.text(cx);
12811        let text = text.trim();
12812
12813        if text.is_empty() {
12814            return None;
12815        }
12816
12817        Some(text.to_string())
12818    }
12819
12820    pub fn set_text(
12821        &mut self,
12822        text: impl Into<Arc<str>>,
12823        window: &mut Window,
12824        cx: &mut Context<Self>,
12825    ) {
12826        self.transact(window, cx, |this, _, cx| {
12827            this.buffer
12828                .read(cx)
12829                .as_singleton()
12830                .expect("you can only call set_text on editors for singleton buffers")
12831                .update(cx, |buffer, cx| buffer.set_text(text, cx));
12832        });
12833    }
12834
12835    pub fn display_text(&self, cx: &mut App) -> String {
12836        self.display_map
12837            .update(cx, |map, cx| map.snapshot(cx))
12838            .text()
12839    }
12840
12841    pub fn wrap_guides(&self, cx: &App) -> SmallVec<[(usize, bool); 2]> {
12842        let mut wrap_guides = smallvec::smallvec![];
12843
12844        if self.show_wrap_guides == Some(false) {
12845            return wrap_guides;
12846        }
12847
12848        let settings = self.buffer.read(cx).settings_at(0, cx);
12849        if settings.show_wrap_guides {
12850            if let SoftWrap::Column(soft_wrap) = self.soft_wrap_mode(cx) {
12851                wrap_guides.push((soft_wrap as usize, true));
12852            } else if let SoftWrap::Bounded(soft_wrap) = self.soft_wrap_mode(cx) {
12853                wrap_guides.push((soft_wrap as usize, true));
12854            }
12855            wrap_guides.extend(settings.wrap_guides.iter().map(|guide| (*guide, false)))
12856        }
12857
12858        wrap_guides
12859    }
12860
12861    pub fn soft_wrap_mode(&self, cx: &App) -> SoftWrap {
12862        let settings = self.buffer.read(cx).settings_at(0, cx);
12863        let mode = self.soft_wrap_mode_override.unwrap_or(settings.soft_wrap);
12864        match mode {
12865            language_settings::SoftWrap::PreferLine | language_settings::SoftWrap::None => {
12866                SoftWrap::None
12867            }
12868            language_settings::SoftWrap::EditorWidth => SoftWrap::EditorWidth,
12869            language_settings::SoftWrap::PreferredLineLength => {
12870                SoftWrap::Column(settings.preferred_line_length)
12871            }
12872            language_settings::SoftWrap::Bounded => {
12873                SoftWrap::Bounded(settings.preferred_line_length)
12874            }
12875        }
12876    }
12877
12878    pub fn set_soft_wrap_mode(
12879        &mut self,
12880        mode: language_settings::SoftWrap,
12881
12882        cx: &mut Context<Self>,
12883    ) {
12884        self.soft_wrap_mode_override = Some(mode);
12885        cx.notify();
12886    }
12887
12888    pub fn set_text_style_refinement(&mut self, style: TextStyleRefinement) {
12889        self.text_style_refinement = Some(style);
12890    }
12891
12892    /// called by the Element so we know what style we were most recently rendered with.
12893    pub(crate) fn set_style(
12894        &mut self,
12895        style: EditorStyle,
12896        window: &mut Window,
12897        cx: &mut Context<Self>,
12898    ) {
12899        let rem_size = window.rem_size();
12900        self.display_map.update(cx, |map, cx| {
12901            map.set_font(
12902                style.text.font(),
12903                style.text.font_size.to_pixels(rem_size),
12904                cx,
12905            )
12906        });
12907        self.style = Some(style);
12908    }
12909
12910    pub fn style(&self) -> Option<&EditorStyle> {
12911        self.style.as_ref()
12912    }
12913
12914    // Called by the element. This method is not designed to be called outside of the editor
12915    // element's layout code because it does not notify when rewrapping is computed synchronously.
12916    pub(crate) fn set_wrap_width(&self, width: Option<Pixels>, cx: &mut App) -> bool {
12917        self.display_map
12918            .update(cx, |map, cx| map.set_wrap_width(width, cx))
12919    }
12920
12921    pub fn set_soft_wrap(&mut self) {
12922        self.soft_wrap_mode_override = Some(language_settings::SoftWrap::EditorWidth)
12923    }
12924
12925    pub fn toggle_soft_wrap(&mut self, _: &ToggleSoftWrap, _: &mut Window, cx: &mut Context<Self>) {
12926        if self.soft_wrap_mode_override.is_some() {
12927            self.soft_wrap_mode_override.take();
12928        } else {
12929            let soft_wrap = match self.soft_wrap_mode(cx) {
12930                SoftWrap::GitDiff => return,
12931                SoftWrap::None => language_settings::SoftWrap::EditorWidth,
12932                SoftWrap::EditorWidth | SoftWrap::Column(_) | SoftWrap::Bounded(_) => {
12933                    language_settings::SoftWrap::None
12934                }
12935            };
12936            self.soft_wrap_mode_override = Some(soft_wrap);
12937        }
12938        cx.notify();
12939    }
12940
12941    pub fn toggle_tab_bar(&mut self, _: &ToggleTabBar, _: &mut Window, cx: &mut Context<Self>) {
12942        let Some(workspace) = self.workspace() else {
12943            return;
12944        };
12945        let fs = workspace.read(cx).app_state().fs.clone();
12946        let current_show = TabBarSettings::get_global(cx).show;
12947        update_settings_file::<TabBarSettings>(fs, cx, move |setting, _| {
12948            setting.show = Some(!current_show);
12949        });
12950    }
12951
12952    pub fn toggle_indent_guides(
12953        &mut self,
12954        _: &ToggleIndentGuides,
12955        _: &mut Window,
12956        cx: &mut Context<Self>,
12957    ) {
12958        let currently_enabled = self.should_show_indent_guides().unwrap_or_else(|| {
12959            self.buffer
12960                .read(cx)
12961                .settings_at(0, cx)
12962                .indent_guides
12963                .enabled
12964        });
12965        self.show_indent_guides = Some(!currently_enabled);
12966        cx.notify();
12967    }
12968
12969    fn should_show_indent_guides(&self) -> Option<bool> {
12970        self.show_indent_guides
12971    }
12972
12973    pub fn toggle_line_numbers(
12974        &mut self,
12975        _: &ToggleLineNumbers,
12976        _: &mut Window,
12977        cx: &mut Context<Self>,
12978    ) {
12979        let mut editor_settings = EditorSettings::get_global(cx).clone();
12980        editor_settings.gutter.line_numbers = !editor_settings.gutter.line_numbers;
12981        EditorSettings::override_global(editor_settings, cx);
12982    }
12983
12984    pub fn should_use_relative_line_numbers(&self, cx: &mut App) -> bool {
12985        self.use_relative_line_numbers
12986            .unwrap_or(EditorSettings::get_global(cx).relative_line_numbers)
12987    }
12988
12989    pub fn toggle_relative_line_numbers(
12990        &mut self,
12991        _: &ToggleRelativeLineNumbers,
12992        _: &mut Window,
12993        cx: &mut Context<Self>,
12994    ) {
12995        let is_relative = self.should_use_relative_line_numbers(cx);
12996        self.set_relative_line_number(Some(!is_relative), cx)
12997    }
12998
12999    pub fn set_relative_line_number(&mut self, is_relative: Option<bool>, cx: &mut Context<Self>) {
13000        self.use_relative_line_numbers = is_relative;
13001        cx.notify();
13002    }
13003
13004    pub fn set_show_gutter(&mut self, show_gutter: bool, cx: &mut Context<Self>) {
13005        self.show_gutter = show_gutter;
13006        cx.notify();
13007    }
13008
13009    pub fn set_show_scrollbars(&mut self, show_scrollbars: bool, cx: &mut Context<Self>) {
13010        self.show_scrollbars = show_scrollbars;
13011        cx.notify();
13012    }
13013
13014    pub fn set_show_line_numbers(&mut self, show_line_numbers: bool, cx: &mut Context<Self>) {
13015        self.show_line_numbers = Some(show_line_numbers);
13016        cx.notify();
13017    }
13018
13019    pub fn set_show_git_diff_gutter(&mut self, show_git_diff_gutter: bool, cx: &mut Context<Self>) {
13020        self.show_git_diff_gutter = Some(show_git_diff_gutter);
13021        cx.notify();
13022    }
13023
13024    pub fn set_show_code_actions(&mut self, show_code_actions: bool, cx: &mut Context<Self>) {
13025        self.show_code_actions = Some(show_code_actions);
13026        cx.notify();
13027    }
13028
13029    pub fn set_show_runnables(&mut self, show_runnables: bool, cx: &mut Context<Self>) {
13030        self.show_runnables = Some(show_runnables);
13031        cx.notify();
13032    }
13033
13034    pub fn set_masked(&mut self, masked: bool, cx: &mut Context<Self>) {
13035        if self.display_map.read(cx).masked != masked {
13036            self.display_map.update(cx, |map, _| map.masked = masked);
13037        }
13038        cx.notify()
13039    }
13040
13041    pub fn set_show_wrap_guides(&mut self, show_wrap_guides: bool, cx: &mut Context<Self>) {
13042        self.show_wrap_guides = Some(show_wrap_guides);
13043        cx.notify();
13044    }
13045
13046    pub fn set_show_indent_guides(&mut self, show_indent_guides: bool, cx: &mut Context<Self>) {
13047        self.show_indent_guides = Some(show_indent_guides);
13048        cx.notify();
13049    }
13050
13051    pub fn working_directory(&self, cx: &App) -> Option<PathBuf> {
13052        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
13053            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
13054                if let Some(dir) = file.abs_path(cx).parent() {
13055                    return Some(dir.to_owned());
13056                }
13057            }
13058
13059            if let Some(project_path) = buffer.read(cx).project_path(cx) {
13060                return Some(project_path.path.to_path_buf());
13061            }
13062        }
13063
13064        None
13065    }
13066
13067    fn target_file<'a>(&self, cx: &'a App) -> Option<&'a dyn language::LocalFile> {
13068        self.active_excerpt(cx)?
13069            .1
13070            .read(cx)
13071            .file()
13072            .and_then(|f| f.as_local())
13073    }
13074
13075    pub fn target_file_abs_path(&self, cx: &mut Context<Self>) -> Option<PathBuf> {
13076        self.active_excerpt(cx).and_then(|(_, buffer, _)| {
13077            let buffer = buffer.read(cx);
13078            if let Some(project_path) = buffer.project_path(cx) {
13079                let project = self.project.as_ref()?.read(cx);
13080                project.absolute_path(&project_path, cx)
13081            } else {
13082                buffer
13083                    .file()
13084                    .and_then(|file| file.as_local().map(|file| file.abs_path(cx)))
13085            }
13086        })
13087    }
13088
13089    fn target_file_path(&self, cx: &mut Context<Self>) -> Option<PathBuf> {
13090        self.active_excerpt(cx).and_then(|(_, buffer, _)| {
13091            let project_path = buffer.read(cx).project_path(cx)?;
13092            let project = self.project.as_ref()?.read(cx);
13093            let entry = project.entry_for_path(&project_path, cx)?;
13094            let path = entry.path.to_path_buf();
13095            Some(path)
13096        })
13097    }
13098
13099    pub fn reveal_in_finder(
13100        &mut self,
13101        _: &RevealInFileManager,
13102        _window: &mut Window,
13103        cx: &mut Context<Self>,
13104    ) {
13105        if let Some(target) = self.target_file(cx) {
13106            cx.reveal_path(&target.abs_path(cx));
13107        }
13108    }
13109
13110    pub fn copy_path(
13111        &mut self,
13112        _: &zed_actions::workspace::CopyPath,
13113        _window: &mut Window,
13114        cx: &mut Context<Self>,
13115    ) {
13116        if let Some(path) = self.target_file_abs_path(cx) {
13117            if let Some(path) = path.to_str() {
13118                cx.write_to_clipboard(ClipboardItem::new_string(path.to_string()));
13119            }
13120        }
13121    }
13122
13123    pub fn copy_relative_path(
13124        &mut self,
13125        _: &zed_actions::workspace::CopyRelativePath,
13126        _window: &mut Window,
13127        cx: &mut Context<Self>,
13128    ) {
13129        if let Some(path) = self.target_file_path(cx) {
13130            if let Some(path) = path.to_str() {
13131                cx.write_to_clipboard(ClipboardItem::new_string(path.to_string()));
13132            }
13133        }
13134    }
13135
13136    pub fn copy_file_name_without_extension(
13137        &mut self,
13138        _: &CopyFileNameWithoutExtension,
13139        _: &mut Window,
13140        cx: &mut Context<Self>,
13141    ) {
13142        if let Some(file) = self.target_file(cx) {
13143            if let Some(file_stem) = file.path().file_stem() {
13144                if let Some(name) = file_stem.to_str() {
13145                    cx.write_to_clipboard(ClipboardItem::new_string(name.to_string()));
13146                }
13147            }
13148        }
13149    }
13150
13151    pub fn copy_file_name(&mut self, _: &CopyFileName, _: &mut Window, cx: &mut Context<Self>) {
13152        if let Some(file) = self.target_file(cx) {
13153            if let Some(file_name) = file.path().file_name() {
13154                if let Some(name) = file_name.to_str() {
13155                    cx.write_to_clipboard(ClipboardItem::new_string(name.to_string()));
13156                }
13157            }
13158        }
13159    }
13160
13161    pub fn toggle_git_blame(
13162        &mut self,
13163        _: &ToggleGitBlame,
13164        window: &mut Window,
13165        cx: &mut Context<Self>,
13166    ) {
13167        self.show_git_blame_gutter = !self.show_git_blame_gutter;
13168
13169        if self.show_git_blame_gutter && !self.has_blame_entries(cx) {
13170            self.start_git_blame(true, window, cx);
13171        }
13172
13173        cx.notify();
13174    }
13175
13176    pub fn toggle_git_blame_inline(
13177        &mut self,
13178        _: &ToggleGitBlameInline,
13179        window: &mut Window,
13180        cx: &mut Context<Self>,
13181    ) {
13182        self.toggle_git_blame_inline_internal(true, window, cx);
13183        cx.notify();
13184    }
13185
13186    pub fn git_blame_inline_enabled(&self) -> bool {
13187        self.git_blame_inline_enabled
13188    }
13189
13190    pub fn toggle_selection_menu(
13191        &mut self,
13192        _: &ToggleSelectionMenu,
13193        _: &mut Window,
13194        cx: &mut Context<Self>,
13195    ) {
13196        self.show_selection_menu = self
13197            .show_selection_menu
13198            .map(|show_selections_menu| !show_selections_menu)
13199            .or_else(|| Some(!EditorSettings::get_global(cx).toolbar.selections_menu));
13200
13201        cx.notify();
13202    }
13203
13204    pub fn selection_menu_enabled(&self, cx: &App) -> bool {
13205        self.show_selection_menu
13206            .unwrap_or_else(|| EditorSettings::get_global(cx).toolbar.selections_menu)
13207    }
13208
13209    fn start_git_blame(
13210        &mut self,
13211        user_triggered: bool,
13212        window: &mut Window,
13213        cx: &mut Context<Self>,
13214    ) {
13215        if let Some(project) = self.project.as_ref() {
13216            let Some(buffer) = self.buffer().read(cx).as_singleton() else {
13217                return;
13218            };
13219
13220            if buffer.read(cx).file().is_none() {
13221                return;
13222            }
13223
13224            let focused = self.focus_handle(cx).contains_focused(window, cx);
13225
13226            let project = project.clone();
13227            let blame = cx.new(|cx| GitBlame::new(buffer, project, user_triggered, focused, cx));
13228            self.blame_subscription =
13229                Some(cx.observe_in(&blame, window, |_, _, _, cx| cx.notify()));
13230            self.blame = Some(blame);
13231        }
13232    }
13233
13234    fn toggle_git_blame_inline_internal(
13235        &mut self,
13236        user_triggered: bool,
13237        window: &mut Window,
13238        cx: &mut Context<Self>,
13239    ) {
13240        if self.git_blame_inline_enabled {
13241            self.git_blame_inline_enabled = false;
13242            self.show_git_blame_inline = false;
13243            self.show_git_blame_inline_delay_task.take();
13244        } else {
13245            self.git_blame_inline_enabled = true;
13246            self.start_git_blame_inline(user_triggered, window, cx);
13247        }
13248
13249        cx.notify();
13250    }
13251
13252    fn start_git_blame_inline(
13253        &mut self,
13254        user_triggered: bool,
13255        window: &mut Window,
13256        cx: &mut Context<Self>,
13257    ) {
13258        self.start_git_blame(user_triggered, window, cx);
13259
13260        if ProjectSettings::get_global(cx)
13261            .git
13262            .inline_blame_delay()
13263            .is_some()
13264        {
13265            self.start_inline_blame_timer(window, cx);
13266        } else {
13267            self.show_git_blame_inline = true
13268        }
13269    }
13270
13271    pub fn blame(&self) -> Option<&Entity<GitBlame>> {
13272        self.blame.as_ref()
13273    }
13274
13275    pub fn show_git_blame_gutter(&self) -> bool {
13276        self.show_git_blame_gutter
13277    }
13278
13279    pub fn render_git_blame_gutter(&self, cx: &App) -> bool {
13280        self.show_git_blame_gutter && self.has_blame_entries(cx)
13281    }
13282
13283    pub fn render_git_blame_inline(&self, window: &Window, cx: &App) -> bool {
13284        self.show_git_blame_inline
13285            && self.focus_handle.is_focused(window)
13286            && !self.newest_selection_head_on_empty_line(cx)
13287            && self.has_blame_entries(cx)
13288    }
13289
13290    fn has_blame_entries(&self, cx: &App) -> bool {
13291        self.blame()
13292            .map_or(false, |blame| blame.read(cx).has_generated_entries())
13293    }
13294
13295    fn newest_selection_head_on_empty_line(&self, cx: &App) -> bool {
13296        let cursor_anchor = self.selections.newest_anchor().head();
13297
13298        let snapshot = self.buffer.read(cx).snapshot(cx);
13299        let buffer_row = MultiBufferRow(cursor_anchor.to_point(&snapshot).row);
13300
13301        snapshot.line_len(buffer_row) == 0
13302    }
13303
13304    fn get_permalink_to_line(&self, cx: &mut Context<Self>) -> Task<Result<url::Url>> {
13305        let buffer_and_selection = maybe!({
13306            let selection = self.selections.newest::<Point>(cx);
13307            let selection_range = selection.range();
13308
13309            let multi_buffer = self.buffer().read(cx);
13310            let multi_buffer_snapshot = multi_buffer.snapshot(cx);
13311            let buffer_ranges = multi_buffer_snapshot.range_to_buffer_ranges(selection_range);
13312
13313            let (buffer, range, _) = if selection.reversed {
13314                buffer_ranges.first()
13315            } else {
13316                buffer_ranges.last()
13317            }?;
13318
13319            let selection = text::ToPoint::to_point(&range.start, &buffer).row
13320                ..text::ToPoint::to_point(&range.end, &buffer).row;
13321            Some((
13322                multi_buffer.buffer(buffer.remote_id()).unwrap().clone(),
13323                selection,
13324            ))
13325        });
13326
13327        let Some((buffer, selection)) = buffer_and_selection else {
13328            return Task::ready(Err(anyhow!("failed to determine buffer and selection")));
13329        };
13330
13331        let Some(project) = self.project.as_ref() else {
13332            return Task::ready(Err(anyhow!("editor does not have project")));
13333        };
13334
13335        project.update(cx, |project, cx| {
13336            project.get_permalink_to_line(&buffer, selection, cx)
13337        })
13338    }
13339
13340    pub fn copy_permalink_to_line(
13341        &mut self,
13342        _: &CopyPermalinkToLine,
13343        window: &mut Window,
13344        cx: &mut Context<Self>,
13345    ) {
13346        let permalink_task = self.get_permalink_to_line(cx);
13347        let workspace = self.workspace();
13348
13349        cx.spawn_in(window, |_, mut cx| async move {
13350            match permalink_task.await {
13351                Ok(permalink) => {
13352                    cx.update(|_, cx| {
13353                        cx.write_to_clipboard(ClipboardItem::new_string(permalink.to_string()));
13354                    })
13355                    .ok();
13356                }
13357                Err(err) => {
13358                    let message = format!("Failed to copy permalink: {err}");
13359
13360                    Err::<(), anyhow::Error>(err).log_err();
13361
13362                    if let Some(workspace) = workspace {
13363                        workspace
13364                            .update_in(&mut cx, |workspace, _, cx| {
13365                                struct CopyPermalinkToLine;
13366
13367                                workspace.show_toast(
13368                                    Toast::new(
13369                                        NotificationId::unique::<CopyPermalinkToLine>(),
13370                                        message,
13371                                    ),
13372                                    cx,
13373                                )
13374                            })
13375                            .ok();
13376                    }
13377                }
13378            }
13379        })
13380        .detach();
13381    }
13382
13383    pub fn copy_file_location(
13384        &mut self,
13385        _: &CopyFileLocation,
13386        _: &mut Window,
13387        cx: &mut Context<Self>,
13388    ) {
13389        let selection = self.selections.newest::<Point>(cx).start.row + 1;
13390        if let Some(file) = self.target_file(cx) {
13391            if let Some(path) = file.path().to_str() {
13392                cx.write_to_clipboard(ClipboardItem::new_string(format!("{path}:{selection}")));
13393            }
13394        }
13395    }
13396
13397    pub fn open_permalink_to_line(
13398        &mut self,
13399        _: &OpenPermalinkToLine,
13400        window: &mut Window,
13401        cx: &mut Context<Self>,
13402    ) {
13403        let permalink_task = self.get_permalink_to_line(cx);
13404        let workspace = self.workspace();
13405
13406        cx.spawn_in(window, |_, mut cx| async move {
13407            match permalink_task.await {
13408                Ok(permalink) => {
13409                    cx.update(|_, cx| {
13410                        cx.open_url(permalink.as_ref());
13411                    })
13412                    .ok();
13413                }
13414                Err(err) => {
13415                    let message = format!("Failed to open permalink: {err}");
13416
13417                    Err::<(), anyhow::Error>(err).log_err();
13418
13419                    if let Some(workspace) = workspace {
13420                        workspace
13421                            .update(&mut cx, |workspace, cx| {
13422                                struct OpenPermalinkToLine;
13423
13424                                workspace.show_toast(
13425                                    Toast::new(
13426                                        NotificationId::unique::<OpenPermalinkToLine>(),
13427                                        message,
13428                                    ),
13429                                    cx,
13430                                )
13431                            })
13432                            .ok();
13433                    }
13434                }
13435            }
13436        })
13437        .detach();
13438    }
13439
13440    pub fn insert_uuid_v4(
13441        &mut self,
13442        _: &InsertUuidV4,
13443        window: &mut Window,
13444        cx: &mut Context<Self>,
13445    ) {
13446        self.insert_uuid(UuidVersion::V4, window, cx);
13447    }
13448
13449    pub fn insert_uuid_v7(
13450        &mut self,
13451        _: &InsertUuidV7,
13452        window: &mut Window,
13453        cx: &mut Context<Self>,
13454    ) {
13455        self.insert_uuid(UuidVersion::V7, window, cx);
13456    }
13457
13458    fn insert_uuid(&mut self, version: UuidVersion, window: &mut Window, cx: &mut Context<Self>) {
13459        self.transact(window, cx, |this, window, cx| {
13460            let edits = this
13461                .selections
13462                .all::<Point>(cx)
13463                .into_iter()
13464                .map(|selection| {
13465                    let uuid = match version {
13466                        UuidVersion::V4 => uuid::Uuid::new_v4(),
13467                        UuidVersion::V7 => uuid::Uuid::now_v7(),
13468                    };
13469
13470                    (selection.range(), uuid.to_string())
13471                });
13472            this.edit(edits, cx);
13473            this.refresh_inline_completion(true, false, window, cx);
13474        });
13475    }
13476
13477    pub fn open_selections_in_multibuffer(
13478        &mut self,
13479        _: &OpenSelectionsInMultibuffer,
13480        window: &mut Window,
13481        cx: &mut Context<Self>,
13482    ) {
13483        let multibuffer = self.buffer.read(cx);
13484
13485        let Some(buffer) = multibuffer.as_singleton() else {
13486            return;
13487        };
13488
13489        let Some(workspace) = self.workspace() else {
13490            return;
13491        };
13492
13493        let locations = self
13494            .selections
13495            .disjoint_anchors()
13496            .iter()
13497            .map(|range| Location {
13498                buffer: buffer.clone(),
13499                range: range.start.text_anchor..range.end.text_anchor,
13500            })
13501            .collect::<Vec<_>>();
13502
13503        let title = multibuffer.title(cx).to_string();
13504
13505        cx.spawn_in(window, |_, mut cx| async move {
13506            workspace.update_in(&mut cx, |workspace, window, cx| {
13507                Self::open_locations_in_multibuffer(
13508                    workspace,
13509                    locations,
13510                    format!("Selections for '{title}'"),
13511                    false,
13512                    MultibufferSelectionMode::All,
13513                    window,
13514                    cx,
13515                );
13516            })
13517        })
13518        .detach();
13519    }
13520
13521    /// Adds a row highlight for the given range. If a row has multiple highlights, the
13522    /// last highlight added will be used.
13523    ///
13524    /// If the range ends at the beginning of a line, then that line will not be highlighted.
13525    pub fn highlight_rows<T: 'static>(
13526        &mut self,
13527        range: Range<Anchor>,
13528        color: Hsla,
13529        should_autoscroll: bool,
13530        cx: &mut Context<Self>,
13531    ) {
13532        let snapshot = self.buffer().read(cx).snapshot(cx);
13533        let row_highlights = self.highlighted_rows.entry(TypeId::of::<T>()).or_default();
13534        let ix = row_highlights.binary_search_by(|highlight| {
13535            Ordering::Equal
13536                .then_with(|| highlight.range.start.cmp(&range.start, &snapshot))
13537                .then_with(|| highlight.range.end.cmp(&range.end, &snapshot))
13538        });
13539
13540        if let Err(mut ix) = ix {
13541            let index = post_inc(&mut self.highlight_order);
13542
13543            // If this range intersects with the preceding highlight, then merge it with
13544            // the preceding highlight. Otherwise insert a new highlight.
13545            let mut merged = false;
13546            if ix > 0 {
13547                let prev_highlight = &mut row_highlights[ix - 1];
13548                if prev_highlight
13549                    .range
13550                    .end
13551                    .cmp(&range.start, &snapshot)
13552                    .is_ge()
13553                {
13554                    ix -= 1;
13555                    if prev_highlight.range.end.cmp(&range.end, &snapshot).is_lt() {
13556                        prev_highlight.range.end = range.end;
13557                    }
13558                    merged = true;
13559                    prev_highlight.index = index;
13560                    prev_highlight.color = color;
13561                    prev_highlight.should_autoscroll = should_autoscroll;
13562                }
13563            }
13564
13565            if !merged {
13566                row_highlights.insert(
13567                    ix,
13568                    RowHighlight {
13569                        range: range.clone(),
13570                        index,
13571                        color,
13572                        should_autoscroll,
13573                    },
13574                );
13575            }
13576
13577            // If any of the following highlights intersect with this one, merge them.
13578            while let Some(next_highlight) = row_highlights.get(ix + 1) {
13579                let highlight = &row_highlights[ix];
13580                if next_highlight
13581                    .range
13582                    .start
13583                    .cmp(&highlight.range.end, &snapshot)
13584                    .is_le()
13585                {
13586                    if next_highlight
13587                        .range
13588                        .end
13589                        .cmp(&highlight.range.end, &snapshot)
13590                        .is_gt()
13591                    {
13592                        row_highlights[ix].range.end = next_highlight.range.end;
13593                    }
13594                    row_highlights.remove(ix + 1);
13595                } else {
13596                    break;
13597                }
13598            }
13599        }
13600    }
13601
13602    /// Remove any highlighted row ranges of the given type that intersect the
13603    /// given ranges.
13604    pub fn remove_highlighted_rows<T: 'static>(
13605        &mut self,
13606        ranges_to_remove: Vec<Range<Anchor>>,
13607        cx: &mut Context<Self>,
13608    ) {
13609        let snapshot = self.buffer().read(cx).snapshot(cx);
13610        let row_highlights = self.highlighted_rows.entry(TypeId::of::<T>()).or_default();
13611        let mut ranges_to_remove = ranges_to_remove.iter().peekable();
13612        row_highlights.retain(|highlight| {
13613            while let Some(range_to_remove) = ranges_to_remove.peek() {
13614                match range_to_remove.end.cmp(&highlight.range.start, &snapshot) {
13615                    Ordering::Less | Ordering::Equal => {
13616                        ranges_to_remove.next();
13617                    }
13618                    Ordering::Greater => {
13619                        match range_to_remove.start.cmp(&highlight.range.end, &snapshot) {
13620                            Ordering::Less | Ordering::Equal => {
13621                                return false;
13622                            }
13623                            Ordering::Greater => break,
13624                        }
13625                    }
13626                }
13627            }
13628
13629            true
13630        })
13631    }
13632
13633    /// Clear all anchor ranges for a certain highlight context type, so no corresponding rows will be highlighted.
13634    pub fn clear_row_highlights<T: 'static>(&mut self) {
13635        self.highlighted_rows.remove(&TypeId::of::<T>());
13636    }
13637
13638    /// For a highlight given context type, gets all anchor ranges that will be used for row highlighting.
13639    pub fn highlighted_rows<T: 'static>(&self) -> impl '_ + Iterator<Item = (Range<Anchor>, Hsla)> {
13640        self.highlighted_rows
13641            .get(&TypeId::of::<T>())
13642            .map_or(&[] as &[_], |vec| vec.as_slice())
13643            .iter()
13644            .map(|highlight| (highlight.range.clone(), highlight.color))
13645    }
13646
13647    /// Merges all anchor ranges for all context types ever set, picking the last highlight added in case of a row conflict.
13648    /// Returns a map of display rows that are highlighted and their corresponding highlight color.
13649    /// Allows to ignore certain kinds of highlights.
13650    pub fn highlighted_display_rows(
13651        &self,
13652        window: &mut Window,
13653        cx: &mut App,
13654    ) -> BTreeMap<DisplayRow, Hsla> {
13655        let snapshot = self.snapshot(window, cx);
13656        let mut used_highlight_orders = HashMap::default();
13657        self.highlighted_rows
13658            .iter()
13659            .flat_map(|(_, highlighted_rows)| highlighted_rows.iter())
13660            .fold(
13661                BTreeMap::<DisplayRow, Hsla>::new(),
13662                |mut unique_rows, highlight| {
13663                    let start = highlight.range.start.to_display_point(&snapshot);
13664                    let end = highlight.range.end.to_display_point(&snapshot);
13665                    let start_row = start.row().0;
13666                    let end_row = if highlight.range.end.text_anchor != text::Anchor::MAX
13667                        && end.column() == 0
13668                    {
13669                        end.row().0.saturating_sub(1)
13670                    } else {
13671                        end.row().0
13672                    };
13673                    for row in start_row..=end_row {
13674                        let used_index =
13675                            used_highlight_orders.entry(row).or_insert(highlight.index);
13676                        if highlight.index >= *used_index {
13677                            *used_index = highlight.index;
13678                            unique_rows.insert(DisplayRow(row), highlight.color);
13679                        }
13680                    }
13681                    unique_rows
13682                },
13683            )
13684    }
13685
13686    pub fn highlighted_display_row_for_autoscroll(
13687        &self,
13688        snapshot: &DisplaySnapshot,
13689    ) -> Option<DisplayRow> {
13690        self.highlighted_rows
13691            .values()
13692            .flat_map(|highlighted_rows| highlighted_rows.iter())
13693            .filter_map(|highlight| {
13694                if highlight.should_autoscroll {
13695                    Some(highlight.range.start.to_display_point(snapshot).row())
13696                } else {
13697                    None
13698                }
13699            })
13700            .min()
13701    }
13702
13703    pub fn set_search_within_ranges(&mut self, ranges: &[Range<Anchor>], cx: &mut Context<Self>) {
13704        self.highlight_background::<SearchWithinRange>(
13705            ranges,
13706            |colors| colors.editor_document_highlight_read_background,
13707            cx,
13708        )
13709    }
13710
13711    pub fn set_breadcrumb_header(&mut self, new_header: String) {
13712        self.breadcrumb_header = Some(new_header);
13713    }
13714
13715    pub fn clear_search_within_ranges(&mut self, cx: &mut Context<Self>) {
13716        self.clear_background_highlights::<SearchWithinRange>(cx);
13717    }
13718
13719    pub fn highlight_background<T: 'static>(
13720        &mut self,
13721        ranges: &[Range<Anchor>],
13722        color_fetcher: fn(&ThemeColors) -> Hsla,
13723        cx: &mut Context<Self>,
13724    ) {
13725        self.background_highlights
13726            .insert(TypeId::of::<T>(), (color_fetcher, Arc::from(ranges)));
13727        self.scrollbar_marker_state.dirty = true;
13728        cx.notify();
13729    }
13730
13731    pub fn clear_background_highlights<T: 'static>(
13732        &mut self,
13733        cx: &mut Context<Self>,
13734    ) -> Option<BackgroundHighlight> {
13735        let text_highlights = self.background_highlights.remove(&TypeId::of::<T>())?;
13736        if !text_highlights.1.is_empty() {
13737            self.scrollbar_marker_state.dirty = true;
13738            cx.notify();
13739        }
13740        Some(text_highlights)
13741    }
13742
13743    pub fn highlight_gutter<T: 'static>(
13744        &mut self,
13745        ranges: &[Range<Anchor>],
13746        color_fetcher: fn(&App) -> Hsla,
13747        cx: &mut Context<Self>,
13748    ) {
13749        self.gutter_highlights
13750            .insert(TypeId::of::<T>(), (color_fetcher, Arc::from(ranges)));
13751        cx.notify();
13752    }
13753
13754    pub fn clear_gutter_highlights<T: 'static>(
13755        &mut self,
13756        cx: &mut Context<Self>,
13757    ) -> Option<GutterHighlight> {
13758        cx.notify();
13759        self.gutter_highlights.remove(&TypeId::of::<T>())
13760    }
13761
13762    #[cfg(feature = "test-support")]
13763    pub fn all_text_background_highlights(
13764        &self,
13765        window: &mut Window,
13766        cx: &mut Context<Self>,
13767    ) -> Vec<(Range<DisplayPoint>, Hsla)> {
13768        let snapshot = self.snapshot(window, cx);
13769        let buffer = &snapshot.buffer_snapshot;
13770        let start = buffer.anchor_before(0);
13771        let end = buffer.anchor_after(buffer.len());
13772        let theme = cx.theme().colors();
13773        self.background_highlights_in_range(start..end, &snapshot, theme)
13774    }
13775
13776    #[cfg(feature = "test-support")]
13777    pub fn search_background_highlights(&mut self, cx: &mut Context<Self>) -> Vec<Range<Point>> {
13778        let snapshot = self.buffer().read(cx).snapshot(cx);
13779
13780        let highlights = self
13781            .background_highlights
13782            .get(&TypeId::of::<items::BufferSearchHighlights>());
13783
13784        if let Some((_color, ranges)) = highlights {
13785            ranges
13786                .iter()
13787                .map(|range| range.start.to_point(&snapshot)..range.end.to_point(&snapshot))
13788                .collect_vec()
13789        } else {
13790            vec![]
13791        }
13792    }
13793
13794    fn document_highlights_for_position<'a>(
13795        &'a self,
13796        position: Anchor,
13797        buffer: &'a MultiBufferSnapshot,
13798    ) -> impl 'a + Iterator<Item = &'a Range<Anchor>> {
13799        let read_highlights = self
13800            .background_highlights
13801            .get(&TypeId::of::<DocumentHighlightRead>())
13802            .map(|h| &h.1);
13803        let write_highlights = self
13804            .background_highlights
13805            .get(&TypeId::of::<DocumentHighlightWrite>())
13806            .map(|h| &h.1);
13807        let left_position = position.bias_left(buffer);
13808        let right_position = position.bias_right(buffer);
13809        read_highlights
13810            .into_iter()
13811            .chain(write_highlights)
13812            .flat_map(move |ranges| {
13813                let start_ix = match ranges.binary_search_by(|probe| {
13814                    let cmp = probe.end.cmp(&left_position, buffer);
13815                    if cmp.is_ge() {
13816                        Ordering::Greater
13817                    } else {
13818                        Ordering::Less
13819                    }
13820                }) {
13821                    Ok(i) | Err(i) => i,
13822                };
13823
13824                ranges[start_ix..]
13825                    .iter()
13826                    .take_while(move |range| range.start.cmp(&right_position, buffer).is_le())
13827            })
13828    }
13829
13830    pub fn has_background_highlights<T: 'static>(&self) -> bool {
13831        self.background_highlights
13832            .get(&TypeId::of::<T>())
13833            .map_or(false, |(_, highlights)| !highlights.is_empty())
13834    }
13835
13836    pub fn background_highlights_in_range(
13837        &self,
13838        search_range: Range<Anchor>,
13839        display_snapshot: &DisplaySnapshot,
13840        theme: &ThemeColors,
13841    ) -> Vec<(Range<DisplayPoint>, Hsla)> {
13842        let mut results = Vec::new();
13843        for (color_fetcher, ranges) in self.background_highlights.values() {
13844            let color = color_fetcher(theme);
13845            let start_ix = match ranges.binary_search_by(|probe| {
13846                let cmp = probe
13847                    .end
13848                    .cmp(&search_range.start, &display_snapshot.buffer_snapshot);
13849                if cmp.is_gt() {
13850                    Ordering::Greater
13851                } else {
13852                    Ordering::Less
13853                }
13854            }) {
13855                Ok(i) | Err(i) => i,
13856            };
13857            for range in &ranges[start_ix..] {
13858                if range
13859                    .start
13860                    .cmp(&search_range.end, &display_snapshot.buffer_snapshot)
13861                    .is_ge()
13862                {
13863                    break;
13864                }
13865
13866                let start = range.start.to_display_point(display_snapshot);
13867                let end = range.end.to_display_point(display_snapshot);
13868                results.push((start..end, color))
13869            }
13870        }
13871        results
13872    }
13873
13874    pub fn background_highlight_row_ranges<T: 'static>(
13875        &self,
13876        search_range: Range<Anchor>,
13877        display_snapshot: &DisplaySnapshot,
13878        count: usize,
13879    ) -> Vec<RangeInclusive<DisplayPoint>> {
13880        let mut results = Vec::new();
13881        let Some((_, ranges)) = self.background_highlights.get(&TypeId::of::<T>()) else {
13882            return vec![];
13883        };
13884
13885        let start_ix = match ranges.binary_search_by(|probe| {
13886            let cmp = probe
13887                .end
13888                .cmp(&search_range.start, &display_snapshot.buffer_snapshot);
13889            if cmp.is_gt() {
13890                Ordering::Greater
13891            } else {
13892                Ordering::Less
13893            }
13894        }) {
13895            Ok(i) | Err(i) => i,
13896        };
13897        let mut push_region = |start: Option<Point>, end: Option<Point>| {
13898            if let (Some(start_display), Some(end_display)) = (start, end) {
13899                results.push(
13900                    start_display.to_display_point(display_snapshot)
13901                        ..=end_display.to_display_point(display_snapshot),
13902                );
13903            }
13904        };
13905        let mut start_row: Option<Point> = None;
13906        let mut end_row: Option<Point> = None;
13907        if ranges.len() > count {
13908            return Vec::new();
13909        }
13910        for range in &ranges[start_ix..] {
13911            if range
13912                .start
13913                .cmp(&search_range.end, &display_snapshot.buffer_snapshot)
13914                .is_ge()
13915            {
13916                break;
13917            }
13918            let end = range.end.to_point(&display_snapshot.buffer_snapshot);
13919            if let Some(current_row) = &end_row {
13920                if end.row == current_row.row {
13921                    continue;
13922                }
13923            }
13924            let start = range.start.to_point(&display_snapshot.buffer_snapshot);
13925            if start_row.is_none() {
13926                assert_eq!(end_row, None);
13927                start_row = Some(start);
13928                end_row = Some(end);
13929                continue;
13930            }
13931            if let Some(current_end) = end_row.as_mut() {
13932                if start.row > current_end.row + 1 {
13933                    push_region(start_row, end_row);
13934                    start_row = Some(start);
13935                    end_row = Some(end);
13936                } else {
13937                    // Merge two hunks.
13938                    *current_end = end;
13939                }
13940            } else {
13941                unreachable!();
13942            }
13943        }
13944        // We might still have a hunk that was not rendered (if there was a search hit on the last line)
13945        push_region(start_row, end_row);
13946        results
13947    }
13948
13949    pub fn gutter_highlights_in_range(
13950        &self,
13951        search_range: Range<Anchor>,
13952        display_snapshot: &DisplaySnapshot,
13953        cx: &App,
13954    ) -> Vec<(Range<DisplayPoint>, Hsla)> {
13955        let mut results = Vec::new();
13956        for (color_fetcher, ranges) in self.gutter_highlights.values() {
13957            let color = color_fetcher(cx);
13958            let start_ix = match ranges.binary_search_by(|probe| {
13959                let cmp = probe
13960                    .end
13961                    .cmp(&search_range.start, &display_snapshot.buffer_snapshot);
13962                if cmp.is_gt() {
13963                    Ordering::Greater
13964                } else {
13965                    Ordering::Less
13966                }
13967            }) {
13968                Ok(i) | Err(i) => i,
13969            };
13970            for range in &ranges[start_ix..] {
13971                if range
13972                    .start
13973                    .cmp(&search_range.end, &display_snapshot.buffer_snapshot)
13974                    .is_ge()
13975                {
13976                    break;
13977                }
13978
13979                let start = range.start.to_display_point(display_snapshot);
13980                let end = range.end.to_display_point(display_snapshot);
13981                results.push((start..end, color))
13982            }
13983        }
13984        results
13985    }
13986
13987    /// Get the text ranges corresponding to the redaction query
13988    pub fn redacted_ranges(
13989        &self,
13990        search_range: Range<Anchor>,
13991        display_snapshot: &DisplaySnapshot,
13992        cx: &App,
13993    ) -> Vec<Range<DisplayPoint>> {
13994        display_snapshot
13995            .buffer_snapshot
13996            .redacted_ranges(search_range, |file| {
13997                if let Some(file) = file {
13998                    file.is_private()
13999                        && EditorSettings::get(
14000                            Some(SettingsLocation {
14001                                worktree_id: file.worktree_id(cx),
14002                                path: file.path().as_ref(),
14003                            }),
14004                            cx,
14005                        )
14006                        .redact_private_values
14007                } else {
14008                    false
14009                }
14010            })
14011            .map(|range| {
14012                range.start.to_display_point(display_snapshot)
14013                    ..range.end.to_display_point(display_snapshot)
14014            })
14015            .collect()
14016    }
14017
14018    pub fn highlight_text<T: 'static>(
14019        &mut self,
14020        ranges: Vec<Range<Anchor>>,
14021        style: HighlightStyle,
14022        cx: &mut Context<Self>,
14023    ) {
14024        self.display_map.update(cx, |map, _| {
14025            map.highlight_text(TypeId::of::<T>(), ranges, style)
14026        });
14027        cx.notify();
14028    }
14029
14030    pub(crate) fn highlight_inlays<T: 'static>(
14031        &mut self,
14032        highlights: Vec<InlayHighlight>,
14033        style: HighlightStyle,
14034        cx: &mut Context<Self>,
14035    ) {
14036        self.display_map.update(cx, |map, _| {
14037            map.highlight_inlays(TypeId::of::<T>(), highlights, style)
14038        });
14039        cx.notify();
14040    }
14041
14042    pub fn text_highlights<'a, T: 'static>(
14043        &'a self,
14044        cx: &'a App,
14045    ) -> Option<(HighlightStyle, &'a [Range<Anchor>])> {
14046        self.display_map.read(cx).text_highlights(TypeId::of::<T>())
14047    }
14048
14049    pub fn clear_highlights<T: 'static>(&mut self, cx: &mut Context<Self>) {
14050        let cleared = self
14051            .display_map
14052            .update(cx, |map, _| map.clear_highlights(TypeId::of::<T>()));
14053        if cleared {
14054            cx.notify();
14055        }
14056    }
14057
14058    pub fn show_local_cursors(&self, window: &mut Window, cx: &mut App) -> bool {
14059        (self.read_only(cx) || self.blink_manager.read(cx).visible())
14060            && self.focus_handle.is_focused(window)
14061    }
14062
14063    pub fn set_show_cursor_when_unfocused(&mut self, is_enabled: bool, cx: &mut Context<Self>) {
14064        self.show_cursor_when_unfocused = is_enabled;
14065        cx.notify();
14066    }
14067
14068    pub fn lsp_store(&self, cx: &App) -> Option<Entity<LspStore>> {
14069        self.project
14070            .as_ref()
14071            .map(|project| project.read(cx).lsp_store())
14072    }
14073
14074    fn on_buffer_changed(&mut self, _: Entity<MultiBuffer>, cx: &mut Context<Self>) {
14075        cx.notify();
14076    }
14077
14078    fn on_buffer_event(
14079        &mut self,
14080        multibuffer: &Entity<MultiBuffer>,
14081        event: &multi_buffer::Event,
14082        window: &mut Window,
14083        cx: &mut Context<Self>,
14084    ) {
14085        match event {
14086            multi_buffer::Event::Edited {
14087                singleton_buffer_edited,
14088                edited_buffer: buffer_edited,
14089            } => {
14090                self.scrollbar_marker_state.dirty = true;
14091                self.active_indent_guides_state.dirty = true;
14092                self.refresh_active_diagnostics(cx);
14093                self.refresh_code_actions(window, cx);
14094                if self.has_active_inline_completion() {
14095                    self.update_visible_inline_completion(window, cx);
14096                }
14097                if let Some(buffer) = buffer_edited {
14098                    let buffer_id = buffer.read(cx).remote_id();
14099                    if !self.registered_buffers.contains_key(&buffer_id) {
14100                        if let Some(lsp_store) = self.lsp_store(cx) {
14101                            lsp_store.update(cx, |lsp_store, cx| {
14102                                self.registered_buffers.insert(
14103                                    buffer_id,
14104                                    lsp_store.register_buffer_with_language_servers(&buffer, cx),
14105                                );
14106                            })
14107                        }
14108                    }
14109                }
14110                cx.emit(EditorEvent::BufferEdited);
14111                cx.emit(SearchEvent::MatchesInvalidated);
14112                if *singleton_buffer_edited {
14113                    if let Some(project) = &self.project {
14114                        let project = project.read(cx);
14115                        #[allow(clippy::mutable_key_type)]
14116                        let languages_affected = multibuffer
14117                            .read(cx)
14118                            .all_buffers()
14119                            .into_iter()
14120                            .filter_map(|buffer| {
14121                                let buffer = buffer.read(cx);
14122                                let language = buffer.language()?;
14123                                if project.is_local()
14124                                    && project
14125                                        .language_servers_for_local_buffer(buffer, cx)
14126                                        .count()
14127                                        == 0
14128                                {
14129                                    None
14130                                } else {
14131                                    Some(language)
14132                                }
14133                            })
14134                            .cloned()
14135                            .collect::<HashSet<_>>();
14136                        if !languages_affected.is_empty() {
14137                            self.refresh_inlay_hints(
14138                                InlayHintRefreshReason::BufferEdited(languages_affected),
14139                                cx,
14140                            );
14141                        }
14142                    }
14143                }
14144
14145                let Some(project) = &self.project else { return };
14146                let (telemetry, is_via_ssh) = {
14147                    let project = project.read(cx);
14148                    let telemetry = project.client().telemetry().clone();
14149                    let is_via_ssh = project.is_via_ssh();
14150                    (telemetry, is_via_ssh)
14151                };
14152                refresh_linked_ranges(self, window, cx);
14153                telemetry.log_edit_event("editor", is_via_ssh);
14154            }
14155            multi_buffer::Event::ExcerptsAdded {
14156                buffer,
14157                predecessor,
14158                excerpts,
14159            } => {
14160                self.tasks_update_task = Some(self.refresh_runnables(window, cx));
14161                let buffer_id = buffer.read(cx).remote_id();
14162                if self.buffer.read(cx).diff_for(buffer_id).is_none() {
14163                    if let Some(project) = &self.project {
14164                        get_uncommitted_diff_for_buffer(
14165                            project,
14166                            [buffer.clone()],
14167                            self.buffer.clone(),
14168                            cx,
14169                        )
14170                        .detach();
14171                    }
14172                }
14173                cx.emit(EditorEvent::ExcerptsAdded {
14174                    buffer: buffer.clone(),
14175                    predecessor: *predecessor,
14176                    excerpts: excerpts.clone(),
14177                });
14178                self.refresh_inlay_hints(InlayHintRefreshReason::NewLinesShown, cx);
14179            }
14180            multi_buffer::Event::ExcerptsRemoved { ids } => {
14181                self.refresh_inlay_hints(InlayHintRefreshReason::ExcerptsRemoved(ids.clone()), cx);
14182                let buffer = self.buffer.read(cx);
14183                self.registered_buffers
14184                    .retain(|buffer_id, _| buffer.buffer(*buffer_id).is_some());
14185                cx.emit(EditorEvent::ExcerptsRemoved { ids: ids.clone() })
14186            }
14187            multi_buffer::Event::ExcerptsEdited { ids } => {
14188                cx.emit(EditorEvent::ExcerptsEdited { ids: ids.clone() })
14189            }
14190            multi_buffer::Event::ExcerptsExpanded { ids } => {
14191                self.refresh_inlay_hints(InlayHintRefreshReason::NewLinesShown, cx);
14192                cx.emit(EditorEvent::ExcerptsExpanded { ids: ids.clone() })
14193            }
14194            multi_buffer::Event::Reparsed(buffer_id) => {
14195                self.tasks_update_task = Some(self.refresh_runnables(window, cx));
14196
14197                cx.emit(EditorEvent::Reparsed(*buffer_id));
14198            }
14199            multi_buffer::Event::DiffHunksToggled => {
14200                self.tasks_update_task = Some(self.refresh_runnables(window, cx));
14201            }
14202            multi_buffer::Event::LanguageChanged(buffer_id) => {
14203                linked_editing_ranges::refresh_linked_ranges(self, window, cx);
14204                cx.emit(EditorEvent::Reparsed(*buffer_id));
14205                cx.notify();
14206            }
14207            multi_buffer::Event::DirtyChanged => cx.emit(EditorEvent::DirtyChanged),
14208            multi_buffer::Event::Saved => cx.emit(EditorEvent::Saved),
14209            multi_buffer::Event::FileHandleChanged | multi_buffer::Event::Reloaded => {
14210                cx.emit(EditorEvent::TitleChanged)
14211            }
14212            // multi_buffer::Event::DiffBaseChanged => {
14213            //     self.scrollbar_marker_state.dirty = true;
14214            //     cx.emit(EditorEvent::DiffBaseChanged);
14215            //     cx.notify();
14216            // }
14217            multi_buffer::Event::Closed => cx.emit(EditorEvent::Closed),
14218            multi_buffer::Event::DiagnosticsUpdated => {
14219                self.refresh_active_diagnostics(cx);
14220                self.scrollbar_marker_state.dirty = true;
14221                cx.notify();
14222            }
14223            _ => {}
14224        };
14225    }
14226
14227    fn on_display_map_changed(
14228        &mut self,
14229        _: Entity<DisplayMap>,
14230        _: &mut Window,
14231        cx: &mut Context<Self>,
14232    ) {
14233        cx.notify();
14234    }
14235
14236    fn settings_changed(&mut self, window: &mut Window, cx: &mut Context<Self>) {
14237        self.tasks_update_task = Some(self.refresh_runnables(window, cx));
14238        self.refresh_inline_completion(true, false, window, cx);
14239        self.refresh_inlay_hints(
14240            InlayHintRefreshReason::SettingsChange(inlay_hint_settings(
14241                self.selections.newest_anchor().head(),
14242                &self.buffer.read(cx).snapshot(cx),
14243                cx,
14244            )),
14245            cx,
14246        );
14247
14248        let old_cursor_shape = self.cursor_shape;
14249
14250        {
14251            let editor_settings = EditorSettings::get_global(cx);
14252            self.scroll_manager.vertical_scroll_margin = editor_settings.vertical_scroll_margin;
14253            self.show_breadcrumbs = editor_settings.toolbar.breadcrumbs;
14254            self.cursor_shape = editor_settings.cursor_shape.unwrap_or_default();
14255        }
14256
14257        if old_cursor_shape != self.cursor_shape {
14258            cx.emit(EditorEvent::CursorShapeChanged);
14259        }
14260
14261        let project_settings = ProjectSettings::get_global(cx);
14262        self.serialize_dirty_buffers = project_settings.session.restore_unsaved_buffers;
14263
14264        if self.mode == EditorMode::Full {
14265            let inline_blame_enabled = project_settings.git.inline_blame_enabled();
14266            if self.git_blame_inline_enabled != inline_blame_enabled {
14267                self.toggle_git_blame_inline_internal(false, window, cx);
14268            }
14269        }
14270
14271        cx.notify();
14272    }
14273
14274    pub fn set_searchable(&mut self, searchable: bool) {
14275        self.searchable = searchable;
14276    }
14277
14278    pub fn searchable(&self) -> bool {
14279        self.searchable
14280    }
14281
14282    fn open_proposed_changes_editor(
14283        &mut self,
14284        _: &OpenProposedChangesEditor,
14285        window: &mut Window,
14286        cx: &mut Context<Self>,
14287    ) {
14288        let Some(workspace) = self.workspace() else {
14289            cx.propagate();
14290            return;
14291        };
14292
14293        let selections = self.selections.all::<usize>(cx);
14294        let multi_buffer = self.buffer.read(cx);
14295        let multi_buffer_snapshot = multi_buffer.snapshot(cx);
14296        let mut new_selections_by_buffer = HashMap::default();
14297        for selection in selections {
14298            for (buffer, range, _) in
14299                multi_buffer_snapshot.range_to_buffer_ranges(selection.start..selection.end)
14300            {
14301                let mut range = range.to_point(buffer);
14302                range.start.column = 0;
14303                range.end.column = buffer.line_len(range.end.row);
14304                new_selections_by_buffer
14305                    .entry(multi_buffer.buffer(buffer.remote_id()).unwrap())
14306                    .or_insert(Vec::new())
14307                    .push(range)
14308            }
14309        }
14310
14311        let proposed_changes_buffers = new_selections_by_buffer
14312            .into_iter()
14313            .map(|(buffer, ranges)| ProposedChangeLocation { buffer, ranges })
14314            .collect::<Vec<_>>();
14315        let proposed_changes_editor = cx.new(|cx| {
14316            ProposedChangesEditor::new(
14317                "Proposed changes",
14318                proposed_changes_buffers,
14319                self.project.clone(),
14320                window,
14321                cx,
14322            )
14323        });
14324
14325        window.defer(cx, move |window, cx| {
14326            workspace.update(cx, |workspace, cx| {
14327                workspace.active_pane().update(cx, |pane, cx| {
14328                    pane.add_item(
14329                        Box::new(proposed_changes_editor),
14330                        true,
14331                        true,
14332                        None,
14333                        window,
14334                        cx,
14335                    );
14336                });
14337            });
14338        });
14339    }
14340
14341    pub fn open_excerpts_in_split(
14342        &mut self,
14343        _: &OpenExcerptsSplit,
14344        window: &mut Window,
14345        cx: &mut Context<Self>,
14346    ) {
14347        self.open_excerpts_common(None, true, window, cx)
14348    }
14349
14350    pub fn open_excerpts(&mut self, _: &OpenExcerpts, window: &mut Window, cx: &mut Context<Self>) {
14351        self.open_excerpts_common(None, false, window, cx)
14352    }
14353
14354    fn open_excerpts_common(
14355        &mut self,
14356        jump_data: Option<JumpData>,
14357        split: bool,
14358        window: &mut Window,
14359        cx: &mut Context<Self>,
14360    ) {
14361        let Some(workspace) = self.workspace() else {
14362            cx.propagate();
14363            return;
14364        };
14365
14366        if self.buffer.read(cx).is_singleton() {
14367            cx.propagate();
14368            return;
14369        }
14370
14371        let mut new_selections_by_buffer = HashMap::default();
14372        match &jump_data {
14373            Some(JumpData::MultiBufferPoint {
14374                excerpt_id,
14375                position,
14376                anchor,
14377                line_offset_from_top,
14378            }) => {
14379                let multi_buffer_snapshot = self.buffer.read(cx).snapshot(cx);
14380                if let Some(buffer) = multi_buffer_snapshot
14381                    .buffer_id_for_excerpt(*excerpt_id)
14382                    .and_then(|buffer_id| self.buffer.read(cx).buffer(buffer_id))
14383                {
14384                    let buffer_snapshot = buffer.read(cx).snapshot();
14385                    let jump_to_point = if buffer_snapshot.can_resolve(anchor) {
14386                        language::ToPoint::to_point(anchor, &buffer_snapshot)
14387                    } else {
14388                        buffer_snapshot.clip_point(*position, Bias::Left)
14389                    };
14390                    let jump_to_offset = buffer_snapshot.point_to_offset(jump_to_point);
14391                    new_selections_by_buffer.insert(
14392                        buffer,
14393                        (
14394                            vec![jump_to_offset..jump_to_offset],
14395                            Some(*line_offset_from_top),
14396                        ),
14397                    );
14398                }
14399            }
14400            Some(JumpData::MultiBufferRow {
14401                row,
14402                line_offset_from_top,
14403            }) => {
14404                let point = MultiBufferPoint::new(row.0, 0);
14405                if let Some((buffer, buffer_point, _)) =
14406                    self.buffer.read(cx).point_to_buffer_point(point, cx)
14407                {
14408                    let buffer_offset = buffer.read(cx).point_to_offset(buffer_point);
14409                    new_selections_by_buffer
14410                        .entry(buffer)
14411                        .or_insert((Vec::new(), Some(*line_offset_from_top)))
14412                        .0
14413                        .push(buffer_offset..buffer_offset)
14414                }
14415            }
14416            None => {
14417                let selections = self.selections.all::<usize>(cx);
14418                let multi_buffer = self.buffer.read(cx);
14419                for selection in selections {
14420                    for (buffer, mut range, _) in multi_buffer
14421                        .snapshot(cx)
14422                        .range_to_buffer_ranges(selection.range())
14423                    {
14424                        // When editing branch buffers, jump to the corresponding location
14425                        // in their base buffer.
14426                        let mut buffer_handle = multi_buffer.buffer(buffer.remote_id()).unwrap();
14427                        let buffer = buffer_handle.read(cx);
14428                        if let Some(base_buffer) = buffer.base_buffer() {
14429                            range = buffer.range_to_version(range, &base_buffer.read(cx).version());
14430                            buffer_handle = base_buffer;
14431                        }
14432
14433                        if selection.reversed {
14434                            mem::swap(&mut range.start, &mut range.end);
14435                        }
14436                        new_selections_by_buffer
14437                            .entry(buffer_handle)
14438                            .or_insert((Vec::new(), None))
14439                            .0
14440                            .push(range)
14441                    }
14442                }
14443            }
14444        }
14445
14446        if new_selections_by_buffer.is_empty() {
14447            return;
14448        }
14449
14450        // We defer the pane interaction because we ourselves are a workspace item
14451        // and activating a new item causes the pane to call a method on us reentrantly,
14452        // which panics if we're on the stack.
14453        window.defer(cx, move |window, cx| {
14454            workspace.update(cx, |workspace, cx| {
14455                let pane = if split {
14456                    workspace.adjacent_pane(window, cx)
14457                } else {
14458                    workspace.active_pane().clone()
14459                };
14460
14461                for (buffer, (ranges, scroll_offset)) in new_selections_by_buffer {
14462                    let editor = buffer
14463                        .read(cx)
14464                        .file()
14465                        .is_none()
14466                        .then(|| {
14467                            // Handle file-less buffers separately: those are not really the project items, so won't have a project path or entity id,
14468                            // so `workspace.open_project_item` will never find them, always opening a new editor.
14469                            // Instead, we try to activate the existing editor in the pane first.
14470                            let (editor, pane_item_index) =
14471                                pane.read(cx).items().enumerate().find_map(|(i, item)| {
14472                                    let editor = item.downcast::<Editor>()?;
14473                                    let singleton_buffer =
14474                                        editor.read(cx).buffer().read(cx).as_singleton()?;
14475                                    if singleton_buffer == buffer {
14476                                        Some((editor, i))
14477                                    } else {
14478                                        None
14479                                    }
14480                                })?;
14481                            pane.update(cx, |pane, cx| {
14482                                pane.activate_item(pane_item_index, true, true, window, cx)
14483                            });
14484                            Some(editor)
14485                        })
14486                        .flatten()
14487                        .unwrap_or_else(|| {
14488                            workspace.open_project_item::<Self>(
14489                                pane.clone(),
14490                                buffer,
14491                                true,
14492                                true,
14493                                window,
14494                                cx,
14495                            )
14496                        });
14497
14498                    editor.update(cx, |editor, cx| {
14499                        let autoscroll = match scroll_offset {
14500                            Some(scroll_offset) => Autoscroll::top_relative(scroll_offset as usize),
14501                            None => Autoscroll::newest(),
14502                        };
14503                        let nav_history = editor.nav_history.take();
14504                        editor.change_selections(Some(autoscroll), window, cx, |s| {
14505                            s.select_ranges(ranges);
14506                        });
14507                        editor.nav_history = nav_history;
14508                    });
14509                }
14510            })
14511        });
14512    }
14513
14514    fn marked_text_ranges(&self, cx: &App) -> Option<Vec<Range<OffsetUtf16>>> {
14515        let snapshot = self.buffer.read(cx).read(cx);
14516        let (_, ranges) = self.text_highlights::<InputComposition>(cx)?;
14517        Some(
14518            ranges
14519                .iter()
14520                .map(move |range| {
14521                    range.start.to_offset_utf16(&snapshot)..range.end.to_offset_utf16(&snapshot)
14522                })
14523                .collect(),
14524        )
14525    }
14526
14527    fn selection_replacement_ranges(
14528        &self,
14529        range: Range<OffsetUtf16>,
14530        cx: &mut App,
14531    ) -> Vec<Range<OffsetUtf16>> {
14532        let selections = self.selections.all::<OffsetUtf16>(cx);
14533        let newest_selection = selections
14534            .iter()
14535            .max_by_key(|selection| selection.id)
14536            .unwrap();
14537        let start_delta = range.start.0 as isize - newest_selection.start.0 as isize;
14538        let end_delta = range.end.0 as isize - newest_selection.end.0 as isize;
14539        let snapshot = self.buffer.read(cx).read(cx);
14540        selections
14541            .into_iter()
14542            .map(|mut selection| {
14543                selection.start.0 =
14544                    (selection.start.0 as isize).saturating_add(start_delta) as usize;
14545                selection.end.0 = (selection.end.0 as isize).saturating_add(end_delta) as usize;
14546                snapshot.clip_offset_utf16(selection.start, Bias::Left)
14547                    ..snapshot.clip_offset_utf16(selection.end, Bias::Right)
14548            })
14549            .collect()
14550    }
14551
14552    fn report_editor_event(
14553        &self,
14554        event_type: &'static str,
14555        file_extension: Option<String>,
14556        cx: &App,
14557    ) {
14558        if cfg!(any(test, feature = "test-support")) {
14559            return;
14560        }
14561
14562        let Some(project) = &self.project else { return };
14563
14564        // If None, we are in a file without an extension
14565        let file = self
14566            .buffer
14567            .read(cx)
14568            .as_singleton()
14569            .and_then(|b| b.read(cx).file());
14570        let file_extension = file_extension.or(file
14571            .as_ref()
14572            .and_then(|file| Path::new(file.file_name(cx)).extension())
14573            .and_then(|e| e.to_str())
14574            .map(|a| a.to_string()));
14575
14576        let vim_mode = cx
14577            .global::<SettingsStore>()
14578            .raw_user_settings()
14579            .get("vim_mode")
14580            == Some(&serde_json::Value::Bool(true));
14581
14582        let edit_predictions_provider = all_language_settings(file, cx).edit_predictions.provider;
14583        let copilot_enabled = edit_predictions_provider
14584            == language::language_settings::EditPredictionProvider::Copilot;
14585        let copilot_enabled_for_language = self
14586            .buffer
14587            .read(cx)
14588            .settings_at(0, cx)
14589            .show_edit_predictions;
14590
14591        let project = project.read(cx);
14592        telemetry::event!(
14593            event_type,
14594            file_extension,
14595            vim_mode,
14596            copilot_enabled,
14597            copilot_enabled_for_language,
14598            edit_predictions_provider,
14599            is_via_ssh = project.is_via_ssh(),
14600        );
14601    }
14602
14603    /// Copy the highlighted chunks to the clipboard as JSON. The format is an array of lines,
14604    /// with each line being an array of {text, highlight} objects.
14605    fn copy_highlight_json(
14606        &mut self,
14607        _: &CopyHighlightJson,
14608        window: &mut Window,
14609        cx: &mut Context<Self>,
14610    ) {
14611        #[derive(Serialize)]
14612        struct Chunk<'a> {
14613            text: String,
14614            highlight: Option<&'a str>,
14615        }
14616
14617        let snapshot = self.buffer.read(cx).snapshot(cx);
14618        let range = self
14619            .selected_text_range(false, window, cx)
14620            .and_then(|selection| {
14621                if selection.range.is_empty() {
14622                    None
14623                } else {
14624                    Some(selection.range)
14625                }
14626            })
14627            .unwrap_or_else(|| 0..snapshot.len());
14628
14629        let chunks = snapshot.chunks(range, true);
14630        let mut lines = Vec::new();
14631        let mut line: VecDeque<Chunk> = VecDeque::new();
14632
14633        let Some(style) = self.style.as_ref() else {
14634            return;
14635        };
14636
14637        for chunk in chunks {
14638            let highlight = chunk
14639                .syntax_highlight_id
14640                .and_then(|id| id.name(&style.syntax));
14641            let mut chunk_lines = chunk.text.split('\n').peekable();
14642            while let Some(text) = chunk_lines.next() {
14643                let mut merged_with_last_token = false;
14644                if let Some(last_token) = line.back_mut() {
14645                    if last_token.highlight == highlight {
14646                        last_token.text.push_str(text);
14647                        merged_with_last_token = true;
14648                    }
14649                }
14650
14651                if !merged_with_last_token {
14652                    line.push_back(Chunk {
14653                        text: text.into(),
14654                        highlight,
14655                    });
14656                }
14657
14658                if chunk_lines.peek().is_some() {
14659                    if line.len() > 1 && line.front().unwrap().text.is_empty() {
14660                        line.pop_front();
14661                    }
14662                    if line.len() > 1 && line.back().unwrap().text.is_empty() {
14663                        line.pop_back();
14664                    }
14665
14666                    lines.push(mem::take(&mut line));
14667                }
14668            }
14669        }
14670
14671        let Some(lines) = serde_json::to_string_pretty(&lines).log_err() else {
14672            return;
14673        };
14674        cx.write_to_clipboard(ClipboardItem::new_string(lines));
14675    }
14676
14677    pub fn open_context_menu(
14678        &mut self,
14679        _: &OpenContextMenu,
14680        window: &mut Window,
14681        cx: &mut Context<Self>,
14682    ) {
14683        self.request_autoscroll(Autoscroll::newest(), cx);
14684        let position = self.selections.newest_display(cx).start;
14685        mouse_context_menu::deploy_context_menu(self, None, position, window, cx);
14686    }
14687
14688    pub fn inlay_hint_cache(&self) -> &InlayHintCache {
14689        &self.inlay_hint_cache
14690    }
14691
14692    pub fn replay_insert_event(
14693        &mut self,
14694        text: &str,
14695        relative_utf16_range: Option<Range<isize>>,
14696        window: &mut Window,
14697        cx: &mut Context<Self>,
14698    ) {
14699        if !self.input_enabled {
14700            cx.emit(EditorEvent::InputIgnored { text: text.into() });
14701            return;
14702        }
14703        if let Some(relative_utf16_range) = relative_utf16_range {
14704            let selections = self.selections.all::<OffsetUtf16>(cx);
14705            self.change_selections(None, window, cx, |s| {
14706                let new_ranges = selections.into_iter().map(|range| {
14707                    let start = OffsetUtf16(
14708                        range
14709                            .head()
14710                            .0
14711                            .saturating_add_signed(relative_utf16_range.start),
14712                    );
14713                    let end = OffsetUtf16(
14714                        range
14715                            .head()
14716                            .0
14717                            .saturating_add_signed(relative_utf16_range.end),
14718                    );
14719                    start..end
14720                });
14721                s.select_ranges(new_ranges);
14722            });
14723        }
14724
14725        self.handle_input(text, window, cx);
14726    }
14727
14728    pub fn supports_inlay_hints(&self, cx: &App) -> bool {
14729        let Some(provider) = self.semantics_provider.as_ref() else {
14730            return false;
14731        };
14732
14733        let mut supports = false;
14734        self.buffer().read(cx).for_each_buffer(|buffer| {
14735            supports |= provider.supports_inlay_hints(buffer, cx);
14736        });
14737        supports
14738    }
14739
14740    pub fn is_focused(&self, window: &Window) -> bool {
14741        self.focus_handle.is_focused(window)
14742    }
14743
14744    fn handle_focus(&mut self, window: &mut Window, cx: &mut Context<Self>) {
14745        cx.emit(EditorEvent::Focused);
14746
14747        if let Some(descendant) = self
14748            .last_focused_descendant
14749            .take()
14750            .and_then(|descendant| descendant.upgrade())
14751        {
14752            window.focus(&descendant);
14753        } else {
14754            if let Some(blame) = self.blame.as_ref() {
14755                blame.update(cx, GitBlame::focus)
14756            }
14757
14758            self.blink_manager.update(cx, BlinkManager::enable);
14759            self.show_cursor_names(window, cx);
14760            self.buffer.update(cx, |buffer, cx| {
14761                buffer.finalize_last_transaction(cx);
14762                if self.leader_peer_id.is_none() {
14763                    buffer.set_active_selections(
14764                        &self.selections.disjoint_anchors(),
14765                        self.selections.line_mode,
14766                        self.cursor_shape,
14767                        cx,
14768                    );
14769                }
14770            });
14771        }
14772    }
14773
14774    fn handle_focus_in(&mut self, _: &mut Window, cx: &mut Context<Self>) {
14775        cx.emit(EditorEvent::FocusedIn)
14776    }
14777
14778    fn handle_focus_out(
14779        &mut self,
14780        event: FocusOutEvent,
14781        _window: &mut Window,
14782        _cx: &mut Context<Self>,
14783    ) {
14784        if event.blurred != self.focus_handle {
14785            self.last_focused_descendant = Some(event.blurred);
14786        }
14787    }
14788
14789    pub fn handle_blur(&mut self, window: &mut Window, cx: &mut Context<Self>) {
14790        self.blink_manager.update(cx, BlinkManager::disable);
14791        self.buffer
14792            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
14793
14794        if let Some(blame) = self.blame.as_ref() {
14795            blame.update(cx, GitBlame::blur)
14796        }
14797        if !self.hover_state.focused(window, cx) {
14798            hide_hover(self, cx);
14799        }
14800
14801        self.hide_context_menu(window, cx);
14802        self.discard_inline_completion(false, cx);
14803        cx.emit(EditorEvent::Blurred);
14804        cx.notify();
14805    }
14806
14807    pub fn register_action<A: Action>(
14808        &mut self,
14809        listener: impl Fn(&A, &mut Window, &mut App) + 'static,
14810    ) -> Subscription {
14811        let id = self.next_editor_action_id.post_inc();
14812        let listener = Arc::new(listener);
14813        self.editor_actions.borrow_mut().insert(
14814            id,
14815            Box::new(move |window, _| {
14816                let listener = listener.clone();
14817                window.on_action(TypeId::of::<A>(), move |action, phase, window, cx| {
14818                    let action = action.downcast_ref().unwrap();
14819                    if phase == DispatchPhase::Bubble {
14820                        listener(action, window, cx)
14821                    }
14822                })
14823            }),
14824        );
14825
14826        let editor_actions = self.editor_actions.clone();
14827        Subscription::new(move || {
14828            editor_actions.borrow_mut().remove(&id);
14829        })
14830    }
14831
14832    pub fn file_header_size(&self) -> u32 {
14833        FILE_HEADER_HEIGHT
14834    }
14835
14836    pub fn revert(
14837        &mut self,
14838        revert_changes: HashMap<BufferId, Vec<(Range<text::Anchor>, Rope)>>,
14839        window: &mut Window,
14840        cx: &mut Context<Self>,
14841    ) {
14842        self.buffer().update(cx, |multi_buffer, cx| {
14843            for (buffer_id, changes) in revert_changes {
14844                if let Some(buffer) = multi_buffer.buffer(buffer_id) {
14845                    buffer.update(cx, |buffer, cx| {
14846                        buffer.edit(
14847                            changes.into_iter().map(|(range, text)| {
14848                                (range, text.to_string().map(Arc::<str>::from))
14849                            }),
14850                            None,
14851                            cx,
14852                        );
14853                    });
14854                }
14855            }
14856        });
14857        self.change_selections(None, window, cx, |selections| selections.refresh());
14858    }
14859
14860    pub fn to_pixel_point(
14861        &self,
14862        source: multi_buffer::Anchor,
14863        editor_snapshot: &EditorSnapshot,
14864        window: &mut Window,
14865    ) -> Option<gpui::Point<Pixels>> {
14866        let source_point = source.to_display_point(editor_snapshot);
14867        self.display_to_pixel_point(source_point, editor_snapshot, window)
14868    }
14869
14870    pub fn display_to_pixel_point(
14871        &self,
14872        source: DisplayPoint,
14873        editor_snapshot: &EditorSnapshot,
14874        window: &mut Window,
14875    ) -> Option<gpui::Point<Pixels>> {
14876        let line_height = self.style()?.text.line_height_in_pixels(window.rem_size());
14877        let text_layout_details = self.text_layout_details(window);
14878        let scroll_top = text_layout_details
14879            .scroll_anchor
14880            .scroll_position(editor_snapshot)
14881            .y;
14882
14883        if source.row().as_f32() < scroll_top.floor() {
14884            return None;
14885        }
14886        let source_x = editor_snapshot.x_for_display_point(source, &text_layout_details);
14887        let source_y = line_height * (source.row().as_f32() - scroll_top);
14888        Some(gpui::Point::new(source_x, source_y))
14889    }
14890
14891    pub fn has_visible_completions_menu(&self) -> bool {
14892        !self.edit_prediction_preview_is_active()
14893            && self.context_menu.borrow().as_ref().map_or(false, |menu| {
14894                menu.visible() && matches!(menu, CodeContextMenu::Completions(_))
14895            })
14896    }
14897
14898    pub fn register_addon<T: Addon>(&mut self, instance: T) {
14899        self.addons
14900            .insert(std::any::TypeId::of::<T>(), Box::new(instance));
14901    }
14902
14903    pub fn unregister_addon<T: Addon>(&mut self) {
14904        self.addons.remove(&std::any::TypeId::of::<T>());
14905    }
14906
14907    pub fn addon<T: Addon>(&self) -> Option<&T> {
14908        let type_id = std::any::TypeId::of::<T>();
14909        self.addons
14910            .get(&type_id)
14911            .and_then(|item| item.to_any().downcast_ref::<T>())
14912    }
14913
14914    fn character_size(&self, window: &mut Window) -> gpui::Size<Pixels> {
14915        let text_layout_details = self.text_layout_details(window);
14916        let style = &text_layout_details.editor_style;
14917        let font_id = window.text_system().resolve_font(&style.text.font());
14918        let font_size = style.text.font_size.to_pixels(window.rem_size());
14919        let line_height = style.text.line_height_in_pixels(window.rem_size());
14920        let em_width = window.text_system().em_width(font_id, font_size).unwrap();
14921
14922        gpui::Size::new(em_width, line_height)
14923    }
14924
14925    pub fn wait_for_diff_to_load(&self) -> Option<Shared<Task<()>>> {
14926        self.load_diff_task.clone()
14927    }
14928}
14929
14930fn get_uncommitted_diff_for_buffer(
14931    project: &Entity<Project>,
14932    buffers: impl IntoIterator<Item = Entity<Buffer>>,
14933    buffer: Entity<MultiBuffer>,
14934    cx: &mut App,
14935) -> Task<()> {
14936    let mut tasks = Vec::new();
14937    project.update(cx, |project, cx| {
14938        for buffer in buffers {
14939            tasks.push(project.open_uncommitted_diff(buffer.clone(), cx))
14940        }
14941    });
14942    cx.spawn(|mut cx| async move {
14943        let diffs = futures::future::join_all(tasks).await;
14944        buffer
14945            .update(&mut cx, |buffer, cx| {
14946                for diff in diffs.into_iter().flatten() {
14947                    buffer.add_diff(diff, cx);
14948                }
14949            })
14950            .ok();
14951    })
14952}
14953
14954fn char_len_with_expanded_tabs(offset: usize, text: &str, tab_size: NonZeroU32) -> usize {
14955    let tab_size = tab_size.get() as usize;
14956    let mut width = offset;
14957
14958    for ch in text.chars() {
14959        width += if ch == '\t' {
14960            tab_size - (width % tab_size)
14961        } else {
14962            1
14963        };
14964    }
14965
14966    width - offset
14967}
14968
14969#[cfg(test)]
14970mod tests {
14971    use super::*;
14972
14973    #[test]
14974    fn test_string_size_with_expanded_tabs() {
14975        let nz = |val| NonZeroU32::new(val).unwrap();
14976        assert_eq!(char_len_with_expanded_tabs(0, "", nz(4)), 0);
14977        assert_eq!(char_len_with_expanded_tabs(0, "hello", nz(4)), 5);
14978        assert_eq!(char_len_with_expanded_tabs(0, "\thello", nz(4)), 9);
14979        assert_eq!(char_len_with_expanded_tabs(0, "abc\tab", nz(4)), 6);
14980        assert_eq!(char_len_with_expanded_tabs(0, "hello\t", nz(4)), 8);
14981        assert_eq!(char_len_with_expanded_tabs(0, "\t\t", nz(8)), 16);
14982        assert_eq!(char_len_with_expanded_tabs(0, "x\t", nz(8)), 8);
14983        assert_eq!(char_len_with_expanded_tabs(7, "x\t", nz(8)), 9);
14984    }
14985}
14986
14987/// Tokenizes a string into runs of text that should stick together, or that is whitespace.
14988struct WordBreakingTokenizer<'a> {
14989    input: &'a str,
14990}
14991
14992impl<'a> WordBreakingTokenizer<'a> {
14993    fn new(input: &'a str) -> Self {
14994        Self { input }
14995    }
14996}
14997
14998fn is_char_ideographic(ch: char) -> bool {
14999    use unicode_script::Script::*;
15000    use unicode_script::UnicodeScript;
15001    matches!(ch.script(), Han | Tangut | Yi)
15002}
15003
15004fn is_grapheme_ideographic(text: &str) -> bool {
15005    text.chars().any(is_char_ideographic)
15006}
15007
15008fn is_grapheme_whitespace(text: &str) -> bool {
15009    text.chars().any(|x| x.is_whitespace())
15010}
15011
15012fn should_stay_with_preceding_ideograph(text: &str) -> bool {
15013    text.chars().next().map_or(false, |ch| {
15014        matches!(ch, '。' | '、' | ',' | '?' | '!' | ':' | ';' | '…')
15015    })
15016}
15017
15018#[derive(PartialEq, Eq, Debug, Clone, Copy)]
15019struct WordBreakToken<'a> {
15020    token: &'a str,
15021    grapheme_len: usize,
15022    is_whitespace: bool,
15023}
15024
15025impl<'a> Iterator for WordBreakingTokenizer<'a> {
15026    /// Yields a span, the count of graphemes in the token, and whether it was
15027    /// whitespace. Note that it also breaks at word boundaries.
15028    type Item = WordBreakToken<'a>;
15029
15030    fn next(&mut self) -> Option<Self::Item> {
15031        use unicode_segmentation::UnicodeSegmentation;
15032        if self.input.is_empty() {
15033            return None;
15034        }
15035
15036        let mut iter = self.input.graphemes(true).peekable();
15037        let mut offset = 0;
15038        let mut graphemes = 0;
15039        if let Some(first_grapheme) = iter.next() {
15040            let is_whitespace = is_grapheme_whitespace(first_grapheme);
15041            offset += first_grapheme.len();
15042            graphemes += 1;
15043            if is_grapheme_ideographic(first_grapheme) && !is_whitespace {
15044                if let Some(grapheme) = iter.peek().copied() {
15045                    if should_stay_with_preceding_ideograph(grapheme) {
15046                        offset += grapheme.len();
15047                        graphemes += 1;
15048                    }
15049                }
15050            } else {
15051                let mut words = self.input[offset..].split_word_bound_indices().peekable();
15052                let mut next_word_bound = words.peek().copied();
15053                if next_word_bound.map_or(false, |(i, _)| i == 0) {
15054                    next_word_bound = words.next();
15055                }
15056                while let Some(grapheme) = iter.peek().copied() {
15057                    if next_word_bound.map_or(false, |(i, _)| i == offset) {
15058                        break;
15059                    };
15060                    if is_grapheme_whitespace(grapheme) != is_whitespace {
15061                        break;
15062                    };
15063                    offset += grapheme.len();
15064                    graphemes += 1;
15065                    iter.next();
15066                }
15067            }
15068            let token = &self.input[..offset];
15069            self.input = &self.input[offset..];
15070            if is_whitespace {
15071                Some(WordBreakToken {
15072                    token: " ",
15073                    grapheme_len: 1,
15074                    is_whitespace: true,
15075                })
15076            } else {
15077                Some(WordBreakToken {
15078                    token,
15079                    grapheme_len: graphemes,
15080                    is_whitespace: false,
15081                })
15082            }
15083        } else {
15084            None
15085        }
15086    }
15087}
15088
15089#[test]
15090fn test_word_breaking_tokenizer() {
15091    let tests: &[(&str, &[(&str, usize, bool)])] = &[
15092        ("", &[]),
15093        ("  ", &[(" ", 1, true)]),
15094        ("Ʒ", &[("Ʒ", 1, false)]),
15095        ("Ǽ", &[("Ǽ", 1, false)]),
15096        ("", &[("", 1, false)]),
15097        ("⋑⋑", &[("⋑⋑", 2, false)]),
15098        (
15099            "原理,进而",
15100            &[
15101                ("", 1, false),
15102                ("理,", 2, false),
15103                ("", 1, false),
15104                ("", 1, false),
15105            ],
15106        ),
15107        (
15108            "hello world",
15109            &[("hello", 5, false), (" ", 1, true), ("world", 5, false)],
15110        ),
15111        (
15112            "hello, world",
15113            &[("hello,", 6, false), (" ", 1, true), ("world", 5, false)],
15114        ),
15115        (
15116            "  hello world",
15117            &[
15118                (" ", 1, true),
15119                ("hello", 5, false),
15120                (" ", 1, true),
15121                ("world", 5, false),
15122            ],
15123        ),
15124        (
15125            "这是什么 \n 钢笔",
15126            &[
15127                ("", 1, false),
15128                ("", 1, false),
15129                ("", 1, false),
15130                ("", 1, false),
15131                (" ", 1, true),
15132                ("", 1, false),
15133                ("", 1, false),
15134            ],
15135        ),
15136        (" mutton", &[(" ", 1, true), ("mutton", 6, false)]),
15137    ];
15138
15139    for (input, result) in tests {
15140        assert_eq!(
15141            WordBreakingTokenizer::new(input).collect::<Vec<_>>(),
15142            result
15143                .iter()
15144                .copied()
15145                .map(|(token, grapheme_len, is_whitespace)| WordBreakToken {
15146                    token,
15147                    grapheme_len,
15148                    is_whitespace,
15149                })
15150                .collect::<Vec<_>>()
15151        );
15152    }
15153}
15154
15155fn wrap_with_prefix(
15156    line_prefix: String,
15157    unwrapped_text: String,
15158    wrap_column: usize,
15159    tab_size: NonZeroU32,
15160) -> String {
15161    let line_prefix_len = char_len_with_expanded_tabs(0, &line_prefix, tab_size);
15162    let mut wrapped_text = String::new();
15163    let mut current_line = line_prefix.clone();
15164
15165    let tokenizer = WordBreakingTokenizer::new(&unwrapped_text);
15166    let mut current_line_len = line_prefix_len;
15167    for WordBreakToken {
15168        token,
15169        grapheme_len,
15170        is_whitespace,
15171    } in tokenizer
15172    {
15173        if current_line_len + grapheme_len > wrap_column && current_line_len != line_prefix_len {
15174            wrapped_text.push_str(current_line.trim_end());
15175            wrapped_text.push('\n');
15176            current_line.truncate(line_prefix.len());
15177            current_line_len = line_prefix_len;
15178            if !is_whitespace {
15179                current_line.push_str(token);
15180                current_line_len += grapheme_len;
15181            }
15182        } else if !is_whitespace {
15183            current_line.push_str(token);
15184            current_line_len += grapheme_len;
15185        } else if current_line_len != line_prefix_len {
15186            current_line.push(' ');
15187            current_line_len += 1;
15188        }
15189    }
15190
15191    if !current_line.is_empty() {
15192        wrapped_text.push_str(&current_line);
15193    }
15194    wrapped_text
15195}
15196
15197#[test]
15198fn test_wrap_with_prefix() {
15199    assert_eq!(
15200        wrap_with_prefix(
15201            "# ".to_string(),
15202            "abcdefg".to_string(),
15203            4,
15204            NonZeroU32::new(4).unwrap()
15205        ),
15206        "# abcdefg"
15207    );
15208    assert_eq!(
15209        wrap_with_prefix(
15210            "".to_string(),
15211            "\thello world".to_string(),
15212            8,
15213            NonZeroU32::new(4).unwrap()
15214        ),
15215        "hello\nworld"
15216    );
15217    assert_eq!(
15218        wrap_with_prefix(
15219            "// ".to_string(),
15220            "xx \nyy zz aa bb cc".to_string(),
15221            12,
15222            NonZeroU32::new(4).unwrap()
15223        ),
15224        "// xx yy zz\n// aa bb cc"
15225    );
15226    assert_eq!(
15227        wrap_with_prefix(
15228            String::new(),
15229            "这是什么 \n 钢笔".to_string(),
15230            3,
15231            NonZeroU32::new(4).unwrap()
15232        ),
15233        "这是什\n么 钢\n"
15234    );
15235}
15236
15237pub trait CollaborationHub {
15238    fn collaborators<'a>(&self, cx: &'a App) -> &'a HashMap<PeerId, Collaborator>;
15239    fn user_participant_indices<'a>(&self, cx: &'a App) -> &'a HashMap<u64, ParticipantIndex>;
15240    fn user_names(&self, cx: &App) -> HashMap<u64, SharedString>;
15241}
15242
15243impl CollaborationHub for Entity<Project> {
15244    fn collaborators<'a>(&self, cx: &'a App) -> &'a HashMap<PeerId, Collaborator> {
15245        self.read(cx).collaborators()
15246    }
15247
15248    fn user_participant_indices<'a>(&self, cx: &'a App) -> &'a HashMap<u64, ParticipantIndex> {
15249        self.read(cx).user_store().read(cx).participant_indices()
15250    }
15251
15252    fn user_names(&self, cx: &App) -> HashMap<u64, SharedString> {
15253        let this = self.read(cx);
15254        let user_ids = this.collaborators().values().map(|c| c.user_id);
15255        this.user_store().read_with(cx, |user_store, cx| {
15256            user_store.participant_names(user_ids, cx)
15257        })
15258    }
15259}
15260
15261pub trait SemanticsProvider {
15262    fn hover(
15263        &self,
15264        buffer: &Entity<Buffer>,
15265        position: text::Anchor,
15266        cx: &mut App,
15267    ) -> Option<Task<Vec<project::Hover>>>;
15268
15269    fn inlay_hints(
15270        &self,
15271        buffer_handle: Entity<Buffer>,
15272        range: Range<text::Anchor>,
15273        cx: &mut App,
15274    ) -> Option<Task<anyhow::Result<Vec<InlayHint>>>>;
15275
15276    fn resolve_inlay_hint(
15277        &self,
15278        hint: InlayHint,
15279        buffer_handle: Entity<Buffer>,
15280        server_id: LanguageServerId,
15281        cx: &mut App,
15282    ) -> Option<Task<anyhow::Result<InlayHint>>>;
15283
15284    fn supports_inlay_hints(&self, buffer: &Entity<Buffer>, cx: &App) -> bool;
15285
15286    fn document_highlights(
15287        &self,
15288        buffer: &Entity<Buffer>,
15289        position: text::Anchor,
15290        cx: &mut App,
15291    ) -> Option<Task<Result<Vec<DocumentHighlight>>>>;
15292
15293    fn definitions(
15294        &self,
15295        buffer: &Entity<Buffer>,
15296        position: text::Anchor,
15297        kind: GotoDefinitionKind,
15298        cx: &mut App,
15299    ) -> Option<Task<Result<Vec<LocationLink>>>>;
15300
15301    fn range_for_rename(
15302        &self,
15303        buffer: &Entity<Buffer>,
15304        position: text::Anchor,
15305        cx: &mut App,
15306    ) -> Option<Task<Result<Option<Range<text::Anchor>>>>>;
15307
15308    fn perform_rename(
15309        &self,
15310        buffer: &Entity<Buffer>,
15311        position: text::Anchor,
15312        new_name: String,
15313        cx: &mut App,
15314    ) -> Option<Task<Result<ProjectTransaction>>>;
15315}
15316
15317pub trait CompletionProvider {
15318    fn completions(
15319        &self,
15320        buffer: &Entity<Buffer>,
15321        buffer_position: text::Anchor,
15322        trigger: CompletionContext,
15323        window: &mut Window,
15324        cx: &mut Context<Editor>,
15325    ) -> Task<Result<Vec<Completion>>>;
15326
15327    fn resolve_completions(
15328        &self,
15329        buffer: Entity<Buffer>,
15330        completion_indices: Vec<usize>,
15331        completions: Rc<RefCell<Box<[Completion]>>>,
15332        cx: &mut Context<Editor>,
15333    ) -> Task<Result<bool>>;
15334
15335    fn apply_additional_edits_for_completion(
15336        &self,
15337        _buffer: Entity<Buffer>,
15338        _completions: Rc<RefCell<Box<[Completion]>>>,
15339        _completion_index: usize,
15340        _push_to_history: bool,
15341        _cx: &mut Context<Editor>,
15342    ) -> Task<Result<Option<language::Transaction>>> {
15343        Task::ready(Ok(None))
15344    }
15345
15346    fn is_completion_trigger(
15347        &self,
15348        buffer: &Entity<Buffer>,
15349        position: language::Anchor,
15350        text: &str,
15351        trigger_in_words: bool,
15352        cx: &mut Context<Editor>,
15353    ) -> bool;
15354
15355    fn sort_completions(&self) -> bool {
15356        true
15357    }
15358}
15359
15360pub trait CodeActionProvider {
15361    fn id(&self) -> Arc<str>;
15362
15363    fn code_actions(
15364        &self,
15365        buffer: &Entity<Buffer>,
15366        range: Range<text::Anchor>,
15367        window: &mut Window,
15368        cx: &mut App,
15369    ) -> Task<Result<Vec<CodeAction>>>;
15370
15371    fn apply_code_action(
15372        &self,
15373        buffer_handle: Entity<Buffer>,
15374        action: CodeAction,
15375        excerpt_id: ExcerptId,
15376        push_to_history: bool,
15377        window: &mut Window,
15378        cx: &mut App,
15379    ) -> Task<Result<ProjectTransaction>>;
15380}
15381
15382impl CodeActionProvider for Entity<Project> {
15383    fn id(&self) -> Arc<str> {
15384        "project".into()
15385    }
15386
15387    fn code_actions(
15388        &self,
15389        buffer: &Entity<Buffer>,
15390        range: Range<text::Anchor>,
15391        _window: &mut Window,
15392        cx: &mut App,
15393    ) -> Task<Result<Vec<CodeAction>>> {
15394        self.update(cx, |project, cx| {
15395            project.code_actions(buffer, range, None, cx)
15396        })
15397    }
15398
15399    fn apply_code_action(
15400        &self,
15401        buffer_handle: Entity<Buffer>,
15402        action: CodeAction,
15403        _excerpt_id: ExcerptId,
15404        push_to_history: bool,
15405        _window: &mut Window,
15406        cx: &mut App,
15407    ) -> Task<Result<ProjectTransaction>> {
15408        self.update(cx, |project, cx| {
15409            project.apply_code_action(buffer_handle, action, push_to_history, cx)
15410        })
15411    }
15412}
15413
15414fn snippet_completions(
15415    project: &Project,
15416    buffer: &Entity<Buffer>,
15417    buffer_position: text::Anchor,
15418    cx: &mut App,
15419) -> Task<Result<Vec<Completion>>> {
15420    let language = buffer.read(cx).language_at(buffer_position);
15421    let language_name = language.as_ref().map(|language| language.lsp_id());
15422    let snippet_store = project.snippets().read(cx);
15423    let snippets = snippet_store.snippets_for(language_name, cx);
15424
15425    if snippets.is_empty() {
15426        return Task::ready(Ok(vec![]));
15427    }
15428    let snapshot = buffer.read(cx).text_snapshot();
15429    let chars: String = snapshot
15430        .reversed_chars_for_range(text::Anchor::MIN..buffer_position)
15431        .collect();
15432
15433    let scope = language.map(|language| language.default_scope());
15434    let executor = cx.background_executor().clone();
15435
15436    cx.background_executor().spawn(async move {
15437        let classifier = CharClassifier::new(scope).for_completion(true);
15438        let mut last_word = chars
15439            .chars()
15440            .take_while(|c| classifier.is_word(*c))
15441            .collect::<String>();
15442        last_word = last_word.chars().rev().collect();
15443
15444        if last_word.is_empty() {
15445            return Ok(vec![]);
15446        }
15447
15448        let as_offset = text::ToOffset::to_offset(&buffer_position, &snapshot);
15449        let to_lsp = |point: &text::Anchor| {
15450            let end = text::ToPointUtf16::to_point_utf16(point, &snapshot);
15451            point_to_lsp(end)
15452        };
15453        let lsp_end = to_lsp(&buffer_position);
15454
15455        let candidates = snippets
15456            .iter()
15457            .enumerate()
15458            .flat_map(|(ix, snippet)| {
15459                snippet
15460                    .prefix
15461                    .iter()
15462                    .map(move |prefix| StringMatchCandidate::new(ix, &prefix))
15463            })
15464            .collect::<Vec<StringMatchCandidate>>();
15465
15466        let mut matches = fuzzy::match_strings(
15467            &candidates,
15468            &last_word,
15469            last_word.chars().any(|c| c.is_uppercase()),
15470            100,
15471            &Default::default(),
15472            executor,
15473        )
15474        .await;
15475
15476        // Remove all candidates where the query's start does not match the start of any word in the candidate
15477        if let Some(query_start) = last_word.chars().next() {
15478            matches.retain(|string_match| {
15479                split_words(&string_match.string).any(|word| {
15480                    // Check that the first codepoint of the word as lowercase matches the first
15481                    // codepoint of the query as lowercase
15482                    word.chars()
15483                        .flat_map(|codepoint| codepoint.to_lowercase())
15484                        .zip(query_start.to_lowercase())
15485                        .all(|(word_cp, query_cp)| word_cp == query_cp)
15486                })
15487            });
15488        }
15489
15490        let matched_strings = matches
15491            .into_iter()
15492            .map(|m| m.string)
15493            .collect::<HashSet<_>>();
15494
15495        let result: Vec<Completion> = snippets
15496            .into_iter()
15497            .filter_map(|snippet| {
15498                let matching_prefix = snippet
15499                    .prefix
15500                    .iter()
15501                    .find(|prefix| matched_strings.contains(*prefix))?;
15502                let start = as_offset - last_word.len();
15503                let start = snapshot.anchor_before(start);
15504                let range = start..buffer_position;
15505                let lsp_start = to_lsp(&start);
15506                let lsp_range = lsp::Range {
15507                    start: lsp_start,
15508                    end: lsp_end,
15509                };
15510                Some(Completion {
15511                    old_range: range,
15512                    new_text: snippet.body.clone(),
15513                    resolved: false,
15514                    label: CodeLabel {
15515                        text: matching_prefix.clone(),
15516                        runs: vec![],
15517                        filter_range: 0..matching_prefix.len(),
15518                    },
15519                    server_id: LanguageServerId(usize::MAX),
15520                    documentation: snippet
15521                        .description
15522                        .clone()
15523                        .map(CompletionDocumentation::SingleLine),
15524                    lsp_completion: lsp::CompletionItem {
15525                        label: snippet.prefix.first().unwrap().clone(),
15526                        kind: Some(CompletionItemKind::SNIPPET),
15527                        label_details: snippet.description.as_ref().map(|description| {
15528                            lsp::CompletionItemLabelDetails {
15529                                detail: Some(description.clone()),
15530                                description: None,
15531                            }
15532                        }),
15533                        insert_text_format: Some(InsertTextFormat::SNIPPET),
15534                        text_edit: Some(lsp::CompletionTextEdit::InsertAndReplace(
15535                            lsp::InsertReplaceEdit {
15536                                new_text: snippet.body.clone(),
15537                                insert: lsp_range,
15538                                replace: lsp_range,
15539                            },
15540                        )),
15541                        filter_text: Some(snippet.body.clone()),
15542                        sort_text: Some(char::MAX.to_string()),
15543                        ..Default::default()
15544                    },
15545                    confirm: None,
15546                })
15547            })
15548            .collect();
15549
15550        Ok(result)
15551    })
15552}
15553
15554impl CompletionProvider for Entity<Project> {
15555    fn completions(
15556        &self,
15557        buffer: &Entity<Buffer>,
15558        buffer_position: text::Anchor,
15559        options: CompletionContext,
15560        _window: &mut Window,
15561        cx: &mut Context<Editor>,
15562    ) -> Task<Result<Vec<Completion>>> {
15563        self.update(cx, |project, cx| {
15564            let snippets = snippet_completions(project, buffer, buffer_position, cx);
15565            let project_completions = project.completions(buffer, buffer_position, options, cx);
15566            cx.background_executor().spawn(async move {
15567                let mut completions = project_completions.await?;
15568                let snippets_completions = snippets.await?;
15569                completions.extend(snippets_completions);
15570                Ok(completions)
15571            })
15572        })
15573    }
15574
15575    fn resolve_completions(
15576        &self,
15577        buffer: Entity<Buffer>,
15578        completion_indices: Vec<usize>,
15579        completions: Rc<RefCell<Box<[Completion]>>>,
15580        cx: &mut Context<Editor>,
15581    ) -> Task<Result<bool>> {
15582        self.update(cx, |project, cx| {
15583            project.lsp_store().update(cx, |lsp_store, cx| {
15584                lsp_store.resolve_completions(buffer, completion_indices, completions, cx)
15585            })
15586        })
15587    }
15588
15589    fn apply_additional_edits_for_completion(
15590        &self,
15591        buffer: Entity<Buffer>,
15592        completions: Rc<RefCell<Box<[Completion]>>>,
15593        completion_index: usize,
15594        push_to_history: bool,
15595        cx: &mut Context<Editor>,
15596    ) -> Task<Result<Option<language::Transaction>>> {
15597        self.update(cx, |project, cx| {
15598            project.lsp_store().update(cx, |lsp_store, cx| {
15599                lsp_store.apply_additional_edits_for_completion(
15600                    buffer,
15601                    completions,
15602                    completion_index,
15603                    push_to_history,
15604                    cx,
15605                )
15606            })
15607        })
15608    }
15609
15610    fn is_completion_trigger(
15611        &self,
15612        buffer: &Entity<Buffer>,
15613        position: language::Anchor,
15614        text: &str,
15615        trigger_in_words: bool,
15616        cx: &mut Context<Editor>,
15617    ) -> bool {
15618        let mut chars = text.chars();
15619        let char = if let Some(char) = chars.next() {
15620            char
15621        } else {
15622            return false;
15623        };
15624        if chars.next().is_some() {
15625            return false;
15626        }
15627
15628        let buffer = buffer.read(cx);
15629        let snapshot = buffer.snapshot();
15630        if !snapshot.settings_at(position, cx).show_completions_on_input {
15631            return false;
15632        }
15633        let classifier = snapshot.char_classifier_at(position).for_completion(true);
15634        if trigger_in_words && classifier.is_word(char) {
15635            return true;
15636        }
15637
15638        buffer.completion_triggers().contains(text)
15639    }
15640}
15641
15642impl SemanticsProvider for Entity<Project> {
15643    fn hover(
15644        &self,
15645        buffer: &Entity<Buffer>,
15646        position: text::Anchor,
15647        cx: &mut App,
15648    ) -> Option<Task<Vec<project::Hover>>> {
15649        Some(self.update(cx, |project, cx| project.hover(buffer, position, cx)))
15650    }
15651
15652    fn document_highlights(
15653        &self,
15654        buffer: &Entity<Buffer>,
15655        position: text::Anchor,
15656        cx: &mut App,
15657    ) -> Option<Task<Result<Vec<DocumentHighlight>>>> {
15658        Some(self.update(cx, |project, cx| {
15659            project.document_highlights(buffer, position, cx)
15660        }))
15661    }
15662
15663    fn definitions(
15664        &self,
15665        buffer: &Entity<Buffer>,
15666        position: text::Anchor,
15667        kind: GotoDefinitionKind,
15668        cx: &mut App,
15669    ) -> Option<Task<Result<Vec<LocationLink>>>> {
15670        Some(self.update(cx, |project, cx| match kind {
15671            GotoDefinitionKind::Symbol => project.definition(&buffer, position, cx),
15672            GotoDefinitionKind::Declaration => project.declaration(&buffer, position, cx),
15673            GotoDefinitionKind::Type => project.type_definition(&buffer, position, cx),
15674            GotoDefinitionKind::Implementation => project.implementation(&buffer, position, cx),
15675        }))
15676    }
15677
15678    fn supports_inlay_hints(&self, buffer: &Entity<Buffer>, cx: &App) -> bool {
15679        // TODO: make this work for remote projects
15680        self.read(cx)
15681            .language_servers_for_local_buffer(buffer.read(cx), cx)
15682            .any(
15683                |(_, server)| match server.capabilities().inlay_hint_provider {
15684                    Some(lsp::OneOf::Left(enabled)) => enabled,
15685                    Some(lsp::OneOf::Right(_)) => true,
15686                    None => false,
15687                },
15688            )
15689    }
15690
15691    fn inlay_hints(
15692        &self,
15693        buffer_handle: Entity<Buffer>,
15694        range: Range<text::Anchor>,
15695        cx: &mut App,
15696    ) -> Option<Task<anyhow::Result<Vec<InlayHint>>>> {
15697        Some(self.update(cx, |project, cx| {
15698            project.inlay_hints(buffer_handle, range, cx)
15699        }))
15700    }
15701
15702    fn resolve_inlay_hint(
15703        &self,
15704        hint: InlayHint,
15705        buffer_handle: Entity<Buffer>,
15706        server_id: LanguageServerId,
15707        cx: &mut App,
15708    ) -> Option<Task<anyhow::Result<InlayHint>>> {
15709        Some(self.update(cx, |project, cx| {
15710            project.resolve_inlay_hint(hint, buffer_handle, server_id, cx)
15711        }))
15712    }
15713
15714    fn range_for_rename(
15715        &self,
15716        buffer: &Entity<Buffer>,
15717        position: text::Anchor,
15718        cx: &mut App,
15719    ) -> Option<Task<Result<Option<Range<text::Anchor>>>>> {
15720        Some(self.update(cx, |project, cx| {
15721            let buffer = buffer.clone();
15722            let task = project.prepare_rename(buffer.clone(), position, cx);
15723            cx.spawn(|_, mut cx| async move {
15724                Ok(match task.await? {
15725                    PrepareRenameResponse::Success(range) => Some(range),
15726                    PrepareRenameResponse::InvalidPosition => None,
15727                    PrepareRenameResponse::OnlyUnpreparedRenameSupported => {
15728                        // Fallback on using TreeSitter info to determine identifier range
15729                        buffer.update(&mut cx, |buffer, _| {
15730                            let snapshot = buffer.snapshot();
15731                            let (range, kind) = snapshot.surrounding_word(position);
15732                            if kind != Some(CharKind::Word) {
15733                                return None;
15734                            }
15735                            Some(
15736                                snapshot.anchor_before(range.start)
15737                                    ..snapshot.anchor_after(range.end),
15738                            )
15739                        })?
15740                    }
15741                })
15742            })
15743        }))
15744    }
15745
15746    fn perform_rename(
15747        &self,
15748        buffer: &Entity<Buffer>,
15749        position: text::Anchor,
15750        new_name: String,
15751        cx: &mut App,
15752    ) -> Option<Task<Result<ProjectTransaction>>> {
15753        Some(self.update(cx, |project, cx| {
15754            project.perform_rename(buffer.clone(), position, new_name, cx)
15755        }))
15756    }
15757}
15758
15759fn inlay_hint_settings(
15760    location: Anchor,
15761    snapshot: &MultiBufferSnapshot,
15762    cx: &mut Context<Editor>,
15763) -> InlayHintSettings {
15764    let file = snapshot.file_at(location);
15765    let language = snapshot.language_at(location).map(|l| l.name());
15766    language_settings(language, file, cx).inlay_hints
15767}
15768
15769fn consume_contiguous_rows(
15770    contiguous_row_selections: &mut Vec<Selection<Point>>,
15771    selection: &Selection<Point>,
15772    display_map: &DisplaySnapshot,
15773    selections: &mut Peekable<std::slice::Iter<Selection<Point>>>,
15774) -> (MultiBufferRow, MultiBufferRow) {
15775    contiguous_row_selections.push(selection.clone());
15776    let start_row = MultiBufferRow(selection.start.row);
15777    let mut end_row = ending_row(selection, display_map);
15778
15779    while let Some(next_selection) = selections.peek() {
15780        if next_selection.start.row <= end_row.0 {
15781            end_row = ending_row(next_selection, display_map);
15782            contiguous_row_selections.push(selections.next().unwrap().clone());
15783        } else {
15784            break;
15785        }
15786    }
15787    (start_row, end_row)
15788}
15789
15790fn ending_row(next_selection: &Selection<Point>, display_map: &DisplaySnapshot) -> MultiBufferRow {
15791    if next_selection.end.column > 0 || next_selection.is_empty() {
15792        MultiBufferRow(display_map.next_line_boundary(next_selection.end).0.row + 1)
15793    } else {
15794        MultiBufferRow(next_selection.end.row)
15795    }
15796}
15797
15798impl EditorSnapshot {
15799    pub fn remote_selections_in_range<'a>(
15800        &'a self,
15801        range: &'a Range<Anchor>,
15802        collaboration_hub: &dyn CollaborationHub,
15803        cx: &'a App,
15804    ) -> impl 'a + Iterator<Item = RemoteSelection> {
15805        let participant_names = collaboration_hub.user_names(cx);
15806        let participant_indices = collaboration_hub.user_participant_indices(cx);
15807        let collaborators_by_peer_id = collaboration_hub.collaborators(cx);
15808        let collaborators_by_replica_id = collaborators_by_peer_id
15809            .iter()
15810            .map(|(_, collaborator)| (collaborator.replica_id, collaborator))
15811            .collect::<HashMap<_, _>>();
15812        self.buffer_snapshot
15813            .selections_in_range(range, false)
15814            .filter_map(move |(replica_id, line_mode, cursor_shape, selection)| {
15815                let collaborator = collaborators_by_replica_id.get(&replica_id)?;
15816                let participant_index = participant_indices.get(&collaborator.user_id).copied();
15817                let user_name = participant_names.get(&collaborator.user_id).cloned();
15818                Some(RemoteSelection {
15819                    replica_id,
15820                    selection,
15821                    cursor_shape,
15822                    line_mode,
15823                    participant_index,
15824                    peer_id: collaborator.peer_id,
15825                    user_name,
15826                })
15827            })
15828    }
15829
15830    pub fn hunks_for_ranges(
15831        &self,
15832        ranges: impl Iterator<Item = Range<Point>>,
15833    ) -> Vec<MultiBufferDiffHunk> {
15834        let mut hunks = Vec::new();
15835        let mut processed_buffer_rows: HashMap<BufferId, HashSet<Range<text::Anchor>>> =
15836            HashMap::default();
15837        for query_range in ranges {
15838            let query_rows =
15839                MultiBufferRow(query_range.start.row)..MultiBufferRow(query_range.end.row + 1);
15840            for hunk in self.buffer_snapshot.diff_hunks_in_range(
15841                Point::new(query_rows.start.0, 0)..Point::new(query_rows.end.0, 0),
15842            ) {
15843                // Deleted hunk is an empty row range, no caret can be placed there and Zed allows to revert it
15844                // when the caret is just above or just below the deleted hunk.
15845                let allow_adjacent = hunk.status().is_removed();
15846                let related_to_selection = if allow_adjacent {
15847                    hunk.row_range.overlaps(&query_rows)
15848                        || hunk.row_range.start == query_rows.end
15849                        || hunk.row_range.end == query_rows.start
15850                } else {
15851                    hunk.row_range.overlaps(&query_rows)
15852                };
15853                if related_to_selection {
15854                    if !processed_buffer_rows
15855                        .entry(hunk.buffer_id)
15856                        .or_default()
15857                        .insert(hunk.buffer_range.start..hunk.buffer_range.end)
15858                    {
15859                        continue;
15860                    }
15861                    hunks.push(hunk);
15862                }
15863            }
15864        }
15865
15866        hunks
15867    }
15868
15869    pub fn language_at<T: ToOffset>(&self, position: T) -> Option<&Arc<Language>> {
15870        self.display_snapshot.buffer_snapshot.language_at(position)
15871    }
15872
15873    pub fn is_focused(&self) -> bool {
15874        self.is_focused
15875    }
15876
15877    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
15878        self.placeholder_text.as_ref()
15879    }
15880
15881    pub fn scroll_position(&self) -> gpui::Point<f32> {
15882        self.scroll_anchor.scroll_position(&self.display_snapshot)
15883    }
15884
15885    fn gutter_dimensions(
15886        &self,
15887        font_id: FontId,
15888        font_size: Pixels,
15889        max_line_number_width: Pixels,
15890        cx: &App,
15891    ) -> Option<GutterDimensions> {
15892        if !self.show_gutter {
15893            return None;
15894        }
15895
15896        let descent = cx.text_system().descent(font_id, font_size);
15897        let em_width = cx.text_system().em_width(font_id, font_size).log_err()?;
15898        let em_advance = cx.text_system().em_advance(font_id, font_size).log_err()?;
15899
15900        let show_git_gutter = self.show_git_diff_gutter.unwrap_or_else(|| {
15901            matches!(
15902                ProjectSettings::get_global(cx).git.git_gutter,
15903                Some(GitGutterSetting::TrackedFiles)
15904            )
15905        });
15906        let gutter_settings = EditorSettings::get_global(cx).gutter;
15907        let show_line_numbers = self
15908            .show_line_numbers
15909            .unwrap_or(gutter_settings.line_numbers);
15910        let line_gutter_width = if show_line_numbers {
15911            // Avoid flicker-like gutter resizes when the line number gains another digit and only resize the gutter on files with N*10^5 lines.
15912            let min_width_for_number_on_gutter = em_advance * 4.0;
15913            max_line_number_width.max(min_width_for_number_on_gutter)
15914        } else {
15915            0.0.into()
15916        };
15917
15918        let show_code_actions = self
15919            .show_code_actions
15920            .unwrap_or(gutter_settings.code_actions);
15921
15922        let show_runnables = self.show_runnables.unwrap_or(gutter_settings.runnables);
15923
15924        let git_blame_entries_width =
15925            self.git_blame_gutter_max_author_length
15926                .map(|max_author_length| {
15927                    const MAX_RELATIVE_TIMESTAMP: &str = "60 minutes ago";
15928
15929                    /// The number of characters to dedicate to gaps and margins.
15930                    const SPACING_WIDTH: usize = 4;
15931
15932                    let max_char_count = max_author_length
15933                        .min(GIT_BLAME_MAX_AUTHOR_CHARS_DISPLAYED)
15934                        + ::git::SHORT_SHA_LENGTH
15935                        + MAX_RELATIVE_TIMESTAMP.len()
15936                        + SPACING_WIDTH;
15937
15938                    em_advance * max_char_count
15939                });
15940
15941        let mut left_padding = git_blame_entries_width.unwrap_or(Pixels::ZERO);
15942        left_padding += if show_code_actions || show_runnables {
15943            em_width * 3.0
15944        } else if show_git_gutter && show_line_numbers {
15945            em_width * 2.0
15946        } else if show_git_gutter || show_line_numbers {
15947            em_width
15948        } else {
15949            px(0.)
15950        };
15951
15952        let right_padding = if gutter_settings.folds && show_line_numbers {
15953            em_width * 4.0
15954        } else if gutter_settings.folds {
15955            em_width * 3.0
15956        } else if show_line_numbers {
15957            em_width
15958        } else {
15959            px(0.)
15960        };
15961
15962        Some(GutterDimensions {
15963            left_padding,
15964            right_padding,
15965            width: line_gutter_width + left_padding + right_padding,
15966            margin: -descent,
15967            git_blame_entries_width,
15968        })
15969    }
15970
15971    pub fn render_crease_toggle(
15972        &self,
15973        buffer_row: MultiBufferRow,
15974        row_contains_cursor: bool,
15975        editor: Entity<Editor>,
15976        window: &mut Window,
15977        cx: &mut App,
15978    ) -> Option<AnyElement> {
15979        let folded = self.is_line_folded(buffer_row);
15980        let mut is_foldable = false;
15981
15982        if let Some(crease) = self
15983            .crease_snapshot
15984            .query_row(buffer_row, &self.buffer_snapshot)
15985        {
15986            is_foldable = true;
15987            match crease {
15988                Crease::Inline { render_toggle, .. } | Crease::Block { render_toggle, .. } => {
15989                    if let Some(render_toggle) = render_toggle {
15990                        let toggle_callback =
15991                            Arc::new(move |folded, window: &mut Window, cx: &mut App| {
15992                                if folded {
15993                                    editor.update(cx, |editor, cx| {
15994                                        editor.fold_at(&crate::FoldAt { buffer_row }, window, cx)
15995                                    });
15996                                } else {
15997                                    editor.update(cx, |editor, cx| {
15998                                        editor.unfold_at(
15999                                            &crate::UnfoldAt { buffer_row },
16000                                            window,
16001                                            cx,
16002                                        )
16003                                    });
16004                                }
16005                            });
16006                        return Some((render_toggle)(
16007                            buffer_row,
16008                            folded,
16009                            toggle_callback,
16010                            window,
16011                            cx,
16012                        ));
16013                    }
16014                }
16015            }
16016        }
16017
16018        is_foldable |= self.starts_indent(buffer_row);
16019
16020        if folded || (is_foldable && (row_contains_cursor || self.gutter_hovered)) {
16021            Some(
16022                Disclosure::new(("gutter_crease", buffer_row.0), !folded)
16023                    .toggle_state(folded)
16024                    .on_click(window.listener_for(&editor, move |this, _e, window, cx| {
16025                        if folded {
16026                            this.unfold_at(&UnfoldAt { buffer_row }, window, cx);
16027                        } else {
16028                            this.fold_at(&FoldAt { buffer_row }, window, cx);
16029                        }
16030                    }))
16031                    .into_any_element(),
16032            )
16033        } else {
16034            None
16035        }
16036    }
16037
16038    pub fn render_crease_trailer(
16039        &self,
16040        buffer_row: MultiBufferRow,
16041        window: &mut Window,
16042        cx: &mut App,
16043    ) -> Option<AnyElement> {
16044        let folded = self.is_line_folded(buffer_row);
16045        if let Crease::Inline { render_trailer, .. } = self
16046            .crease_snapshot
16047            .query_row(buffer_row, &self.buffer_snapshot)?
16048        {
16049            let render_trailer = render_trailer.as_ref()?;
16050            Some(render_trailer(buffer_row, folded, window, cx))
16051        } else {
16052            None
16053        }
16054    }
16055}
16056
16057impl Deref for EditorSnapshot {
16058    type Target = DisplaySnapshot;
16059
16060    fn deref(&self) -> &Self::Target {
16061        &self.display_snapshot
16062    }
16063}
16064
16065#[derive(Clone, Debug, PartialEq, Eq)]
16066pub enum EditorEvent {
16067    InputIgnored {
16068        text: Arc<str>,
16069    },
16070    InputHandled {
16071        utf16_range_to_replace: Option<Range<isize>>,
16072        text: Arc<str>,
16073    },
16074    ExcerptsAdded {
16075        buffer: Entity<Buffer>,
16076        predecessor: ExcerptId,
16077        excerpts: Vec<(ExcerptId, ExcerptRange<language::Anchor>)>,
16078    },
16079    ExcerptsRemoved {
16080        ids: Vec<ExcerptId>,
16081    },
16082    BufferFoldToggled {
16083        ids: Vec<ExcerptId>,
16084        folded: bool,
16085    },
16086    ExcerptsEdited {
16087        ids: Vec<ExcerptId>,
16088    },
16089    ExcerptsExpanded {
16090        ids: Vec<ExcerptId>,
16091    },
16092    BufferEdited,
16093    Edited {
16094        transaction_id: clock::Lamport,
16095    },
16096    Reparsed(BufferId),
16097    Focused,
16098    FocusedIn,
16099    Blurred,
16100    DirtyChanged,
16101    Saved,
16102    TitleChanged,
16103    DiffBaseChanged,
16104    SelectionsChanged {
16105        local: bool,
16106    },
16107    ScrollPositionChanged {
16108        local: bool,
16109        autoscroll: bool,
16110    },
16111    Closed,
16112    TransactionUndone {
16113        transaction_id: clock::Lamport,
16114    },
16115    TransactionBegun {
16116        transaction_id: clock::Lamport,
16117    },
16118    Reloaded,
16119    CursorShapeChanged,
16120}
16121
16122impl EventEmitter<EditorEvent> for Editor {}
16123
16124impl Focusable for Editor {
16125    fn focus_handle(&self, _cx: &App) -> FocusHandle {
16126        self.focus_handle.clone()
16127    }
16128}
16129
16130impl Render for Editor {
16131    fn render<'a>(&mut self, _: &mut Window, cx: &mut Context<'a, Self>) -> impl IntoElement {
16132        let settings = ThemeSettings::get_global(cx);
16133
16134        let mut text_style = match self.mode {
16135            EditorMode::SingleLine { .. } | EditorMode::AutoHeight { .. } => TextStyle {
16136                color: cx.theme().colors().editor_foreground,
16137                font_family: settings.ui_font.family.clone(),
16138                font_features: settings.ui_font.features.clone(),
16139                font_fallbacks: settings.ui_font.fallbacks.clone(),
16140                font_size: rems(0.875).into(),
16141                font_weight: settings.ui_font.weight,
16142                line_height: relative(settings.buffer_line_height.value()),
16143                ..Default::default()
16144            },
16145            EditorMode::Full => TextStyle {
16146                color: cx.theme().colors().editor_foreground,
16147                font_family: settings.buffer_font.family.clone(),
16148                font_features: settings.buffer_font.features.clone(),
16149                font_fallbacks: settings.buffer_font.fallbacks.clone(),
16150                font_size: settings.buffer_font_size(cx).into(),
16151                font_weight: settings.buffer_font.weight,
16152                line_height: relative(settings.buffer_line_height.value()),
16153                ..Default::default()
16154            },
16155        };
16156        if let Some(text_style_refinement) = &self.text_style_refinement {
16157            text_style.refine(text_style_refinement)
16158        }
16159
16160        let background = match self.mode {
16161            EditorMode::SingleLine { .. } => cx.theme().system().transparent,
16162            EditorMode::AutoHeight { max_lines: _ } => cx.theme().system().transparent,
16163            EditorMode::Full => cx.theme().colors().editor_background,
16164        };
16165
16166        EditorElement::new(
16167            &cx.entity(),
16168            EditorStyle {
16169                background,
16170                local_player: cx.theme().players().local(),
16171                text: text_style,
16172                scrollbar_width: EditorElement::SCROLLBAR_WIDTH,
16173                syntax: cx.theme().syntax().clone(),
16174                status: cx.theme().status().clone(),
16175                inlay_hints_style: make_inlay_hints_style(cx),
16176                inline_completion_styles: make_suggestion_styles(cx),
16177                unnecessary_code_fade: ThemeSettings::get_global(cx).unnecessary_code_fade,
16178            },
16179        )
16180    }
16181}
16182
16183impl EntityInputHandler for Editor {
16184    fn text_for_range(
16185        &mut self,
16186        range_utf16: Range<usize>,
16187        adjusted_range: &mut Option<Range<usize>>,
16188        _: &mut Window,
16189        cx: &mut Context<Self>,
16190    ) -> Option<String> {
16191        let snapshot = self.buffer.read(cx).read(cx);
16192        let start = snapshot.clip_offset_utf16(OffsetUtf16(range_utf16.start), Bias::Left);
16193        let end = snapshot.clip_offset_utf16(OffsetUtf16(range_utf16.end), Bias::Right);
16194        if (start.0..end.0) != range_utf16 {
16195            adjusted_range.replace(start.0..end.0);
16196        }
16197        Some(snapshot.text_for_range(start..end).collect())
16198    }
16199
16200    fn selected_text_range(
16201        &mut self,
16202        ignore_disabled_input: bool,
16203        _: &mut Window,
16204        cx: &mut Context<Self>,
16205    ) -> Option<UTF16Selection> {
16206        // Prevent the IME menu from appearing when holding down an alphabetic key
16207        // while input is disabled.
16208        if !ignore_disabled_input && !self.input_enabled {
16209            return None;
16210        }
16211
16212        let selection = self.selections.newest::<OffsetUtf16>(cx);
16213        let range = selection.range();
16214
16215        Some(UTF16Selection {
16216            range: range.start.0..range.end.0,
16217            reversed: selection.reversed,
16218        })
16219    }
16220
16221    fn marked_text_range(&self, _: &mut Window, cx: &mut Context<Self>) -> Option<Range<usize>> {
16222        let snapshot = self.buffer.read(cx).read(cx);
16223        let range = self.text_highlights::<InputComposition>(cx)?.1.first()?;
16224        Some(range.start.to_offset_utf16(&snapshot).0..range.end.to_offset_utf16(&snapshot).0)
16225    }
16226
16227    fn unmark_text(&mut self, _: &mut Window, cx: &mut Context<Self>) {
16228        self.clear_highlights::<InputComposition>(cx);
16229        self.ime_transaction.take();
16230    }
16231
16232    fn replace_text_in_range(
16233        &mut self,
16234        range_utf16: Option<Range<usize>>,
16235        text: &str,
16236        window: &mut Window,
16237        cx: &mut Context<Self>,
16238    ) {
16239        if !self.input_enabled {
16240            cx.emit(EditorEvent::InputIgnored { text: text.into() });
16241            return;
16242        }
16243
16244        self.transact(window, cx, |this, window, cx| {
16245            let new_selected_ranges = if let Some(range_utf16) = range_utf16 {
16246                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
16247                Some(this.selection_replacement_ranges(range_utf16, cx))
16248            } else {
16249                this.marked_text_ranges(cx)
16250            };
16251
16252            let range_to_replace = new_selected_ranges.as_ref().and_then(|ranges_to_replace| {
16253                let newest_selection_id = this.selections.newest_anchor().id;
16254                this.selections
16255                    .all::<OffsetUtf16>(cx)
16256                    .iter()
16257                    .zip(ranges_to_replace.iter())
16258                    .find_map(|(selection, range)| {
16259                        if selection.id == newest_selection_id {
16260                            Some(
16261                                (range.start.0 as isize - selection.head().0 as isize)
16262                                    ..(range.end.0 as isize - selection.head().0 as isize),
16263                            )
16264                        } else {
16265                            None
16266                        }
16267                    })
16268            });
16269
16270            cx.emit(EditorEvent::InputHandled {
16271                utf16_range_to_replace: range_to_replace,
16272                text: text.into(),
16273            });
16274
16275            if let Some(new_selected_ranges) = new_selected_ranges {
16276                this.change_selections(None, window, cx, |selections| {
16277                    selections.select_ranges(new_selected_ranges)
16278                });
16279                this.backspace(&Default::default(), window, cx);
16280            }
16281
16282            this.handle_input(text, window, cx);
16283        });
16284
16285        if let Some(transaction) = self.ime_transaction {
16286            self.buffer.update(cx, |buffer, cx| {
16287                buffer.group_until_transaction(transaction, cx);
16288            });
16289        }
16290
16291        self.unmark_text(window, cx);
16292    }
16293
16294    fn replace_and_mark_text_in_range(
16295        &mut self,
16296        range_utf16: Option<Range<usize>>,
16297        text: &str,
16298        new_selected_range_utf16: Option<Range<usize>>,
16299        window: &mut Window,
16300        cx: &mut Context<Self>,
16301    ) {
16302        if !self.input_enabled {
16303            return;
16304        }
16305
16306        let transaction = self.transact(window, cx, |this, window, cx| {
16307            let ranges_to_replace = if let Some(mut marked_ranges) = this.marked_text_ranges(cx) {
16308                let snapshot = this.buffer.read(cx).read(cx);
16309                if let Some(relative_range_utf16) = range_utf16.as_ref() {
16310                    for marked_range in &mut marked_ranges {
16311                        marked_range.end.0 = marked_range.start.0 + relative_range_utf16.end;
16312                        marked_range.start.0 += relative_range_utf16.start;
16313                        marked_range.start =
16314                            snapshot.clip_offset_utf16(marked_range.start, Bias::Left);
16315                        marked_range.end =
16316                            snapshot.clip_offset_utf16(marked_range.end, Bias::Right);
16317                    }
16318                }
16319                Some(marked_ranges)
16320            } else if let Some(range_utf16) = range_utf16 {
16321                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
16322                Some(this.selection_replacement_ranges(range_utf16, cx))
16323            } else {
16324                None
16325            };
16326
16327            let range_to_replace = ranges_to_replace.as_ref().and_then(|ranges_to_replace| {
16328                let newest_selection_id = this.selections.newest_anchor().id;
16329                this.selections
16330                    .all::<OffsetUtf16>(cx)
16331                    .iter()
16332                    .zip(ranges_to_replace.iter())
16333                    .find_map(|(selection, range)| {
16334                        if selection.id == newest_selection_id {
16335                            Some(
16336                                (range.start.0 as isize - selection.head().0 as isize)
16337                                    ..(range.end.0 as isize - selection.head().0 as isize),
16338                            )
16339                        } else {
16340                            None
16341                        }
16342                    })
16343            });
16344
16345            cx.emit(EditorEvent::InputHandled {
16346                utf16_range_to_replace: range_to_replace,
16347                text: text.into(),
16348            });
16349
16350            if let Some(ranges) = ranges_to_replace {
16351                this.change_selections(None, window, cx, |s| s.select_ranges(ranges));
16352            }
16353
16354            let marked_ranges = {
16355                let snapshot = this.buffer.read(cx).read(cx);
16356                this.selections
16357                    .disjoint_anchors()
16358                    .iter()
16359                    .map(|selection| {
16360                        selection.start.bias_left(&snapshot)..selection.end.bias_right(&snapshot)
16361                    })
16362                    .collect::<Vec<_>>()
16363            };
16364
16365            if text.is_empty() {
16366                this.unmark_text(window, cx);
16367            } else {
16368                this.highlight_text::<InputComposition>(
16369                    marked_ranges.clone(),
16370                    HighlightStyle {
16371                        underline: Some(UnderlineStyle {
16372                            thickness: px(1.),
16373                            color: None,
16374                            wavy: false,
16375                        }),
16376                        ..Default::default()
16377                    },
16378                    cx,
16379                );
16380            }
16381
16382            // Disable auto-closing when composing text (i.e. typing a `"` on a Brazilian keyboard)
16383            let use_autoclose = this.use_autoclose;
16384            let use_auto_surround = this.use_auto_surround;
16385            this.set_use_autoclose(false);
16386            this.set_use_auto_surround(false);
16387            this.handle_input(text, window, cx);
16388            this.set_use_autoclose(use_autoclose);
16389            this.set_use_auto_surround(use_auto_surround);
16390
16391            if let Some(new_selected_range) = new_selected_range_utf16 {
16392                let snapshot = this.buffer.read(cx).read(cx);
16393                let new_selected_ranges = marked_ranges
16394                    .into_iter()
16395                    .map(|marked_range| {
16396                        let insertion_start = marked_range.start.to_offset_utf16(&snapshot).0;
16397                        let new_start = OffsetUtf16(new_selected_range.start + insertion_start);
16398                        let new_end = OffsetUtf16(new_selected_range.end + insertion_start);
16399                        snapshot.clip_offset_utf16(new_start, Bias::Left)
16400                            ..snapshot.clip_offset_utf16(new_end, Bias::Right)
16401                    })
16402                    .collect::<Vec<_>>();
16403
16404                drop(snapshot);
16405                this.change_selections(None, window, cx, |selections| {
16406                    selections.select_ranges(new_selected_ranges)
16407                });
16408            }
16409        });
16410
16411        self.ime_transaction = self.ime_transaction.or(transaction);
16412        if let Some(transaction) = self.ime_transaction {
16413            self.buffer.update(cx, |buffer, cx| {
16414                buffer.group_until_transaction(transaction, cx);
16415            });
16416        }
16417
16418        if self.text_highlights::<InputComposition>(cx).is_none() {
16419            self.ime_transaction.take();
16420        }
16421    }
16422
16423    fn bounds_for_range(
16424        &mut self,
16425        range_utf16: Range<usize>,
16426        element_bounds: gpui::Bounds<Pixels>,
16427        window: &mut Window,
16428        cx: &mut Context<Self>,
16429    ) -> Option<gpui::Bounds<Pixels>> {
16430        let text_layout_details = self.text_layout_details(window);
16431        let gpui::Size {
16432            width: em_width,
16433            height: line_height,
16434        } = self.character_size(window);
16435
16436        let snapshot = self.snapshot(window, cx);
16437        let scroll_position = snapshot.scroll_position();
16438        let scroll_left = scroll_position.x * em_width;
16439
16440        let start = OffsetUtf16(range_utf16.start).to_display_point(&snapshot);
16441        let x = snapshot.x_for_display_point(start, &text_layout_details) - scroll_left
16442            + self.gutter_dimensions.width
16443            + self.gutter_dimensions.margin;
16444        let y = line_height * (start.row().as_f32() - scroll_position.y);
16445
16446        Some(Bounds {
16447            origin: element_bounds.origin + point(x, y),
16448            size: size(em_width, line_height),
16449        })
16450    }
16451
16452    fn character_index_for_point(
16453        &mut self,
16454        point: gpui::Point<Pixels>,
16455        _window: &mut Window,
16456        _cx: &mut Context<Self>,
16457    ) -> Option<usize> {
16458        let position_map = self.last_position_map.as_ref()?;
16459        if !position_map.text_hitbox.contains(&point) {
16460            return None;
16461        }
16462        let display_point = position_map.point_for_position(point).previous_valid;
16463        let anchor = position_map
16464            .snapshot
16465            .display_point_to_anchor(display_point, Bias::Left);
16466        let utf16_offset = anchor.to_offset_utf16(&position_map.snapshot.buffer_snapshot);
16467        Some(utf16_offset.0)
16468    }
16469}
16470
16471trait SelectionExt {
16472    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
16473    fn spanned_rows(
16474        &self,
16475        include_end_if_at_line_start: bool,
16476        map: &DisplaySnapshot,
16477    ) -> Range<MultiBufferRow>;
16478}
16479
16480impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
16481    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
16482        let start = self
16483            .start
16484            .to_point(&map.buffer_snapshot)
16485            .to_display_point(map);
16486        let end = self
16487            .end
16488            .to_point(&map.buffer_snapshot)
16489            .to_display_point(map);
16490        if self.reversed {
16491            end..start
16492        } else {
16493            start..end
16494        }
16495    }
16496
16497    fn spanned_rows(
16498        &self,
16499        include_end_if_at_line_start: bool,
16500        map: &DisplaySnapshot,
16501    ) -> Range<MultiBufferRow> {
16502        let start = self.start.to_point(&map.buffer_snapshot);
16503        let mut end = self.end.to_point(&map.buffer_snapshot);
16504        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
16505            end.row -= 1;
16506        }
16507
16508        let buffer_start = map.prev_line_boundary(start).0;
16509        let buffer_end = map.next_line_boundary(end).0;
16510        MultiBufferRow(buffer_start.row)..MultiBufferRow(buffer_end.row + 1)
16511    }
16512}
16513
16514impl<T: InvalidationRegion> InvalidationStack<T> {
16515    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
16516    where
16517        S: Clone + ToOffset,
16518    {
16519        while let Some(region) = self.last() {
16520            let all_selections_inside_invalidation_ranges =
16521                if selections.len() == region.ranges().len() {
16522                    selections
16523                        .iter()
16524                        .zip(region.ranges().iter().map(|r| r.to_offset(buffer)))
16525                        .all(|(selection, invalidation_range)| {
16526                            let head = selection.head().to_offset(buffer);
16527                            invalidation_range.start <= head && invalidation_range.end >= head
16528                        })
16529                } else {
16530                    false
16531                };
16532
16533            if all_selections_inside_invalidation_ranges {
16534                break;
16535            } else {
16536                self.pop();
16537            }
16538        }
16539    }
16540}
16541
16542impl<T> Default for InvalidationStack<T> {
16543    fn default() -> Self {
16544        Self(Default::default())
16545    }
16546}
16547
16548impl<T> Deref for InvalidationStack<T> {
16549    type Target = Vec<T>;
16550
16551    fn deref(&self) -> &Self::Target {
16552        &self.0
16553    }
16554}
16555
16556impl<T> DerefMut for InvalidationStack<T> {
16557    fn deref_mut(&mut self) -> &mut Self::Target {
16558        &mut self.0
16559    }
16560}
16561
16562impl InvalidationRegion for SnippetState {
16563    fn ranges(&self) -> &[Range<Anchor>] {
16564        &self.ranges[self.active_index]
16565    }
16566}
16567
16568pub fn diagnostic_block_renderer(
16569    diagnostic: Diagnostic,
16570    max_message_rows: Option<u8>,
16571    allow_closing: bool,
16572    _is_valid: bool,
16573) -> RenderBlock {
16574    let (text_without_backticks, code_ranges) =
16575        highlight_diagnostic_message(&diagnostic, max_message_rows);
16576
16577    Arc::new(move |cx: &mut BlockContext| {
16578        let group_id: SharedString = cx.block_id.to_string().into();
16579
16580        let mut text_style = cx.window.text_style().clone();
16581        text_style.color = diagnostic_style(diagnostic.severity, cx.theme().status());
16582        let theme_settings = ThemeSettings::get_global(cx);
16583        text_style.font_family = theme_settings.buffer_font.family.clone();
16584        text_style.font_style = theme_settings.buffer_font.style;
16585        text_style.font_features = theme_settings.buffer_font.features.clone();
16586        text_style.font_weight = theme_settings.buffer_font.weight;
16587
16588        let multi_line_diagnostic = diagnostic.message.contains('\n');
16589
16590        let buttons = |diagnostic: &Diagnostic| {
16591            if multi_line_diagnostic {
16592                v_flex()
16593            } else {
16594                h_flex()
16595            }
16596            .when(allow_closing, |div| {
16597                div.children(diagnostic.is_primary.then(|| {
16598                    IconButton::new("close-block", IconName::XCircle)
16599                        .icon_color(Color::Muted)
16600                        .size(ButtonSize::Compact)
16601                        .style(ButtonStyle::Transparent)
16602                        .visible_on_hover(group_id.clone())
16603                        .on_click(move |_click, window, cx| {
16604                            window.dispatch_action(Box::new(Cancel), cx)
16605                        })
16606                        .tooltip(|window, cx| {
16607                            Tooltip::for_action("Close Diagnostics", &Cancel, window, cx)
16608                        })
16609                }))
16610            })
16611            .child(
16612                IconButton::new("copy-block", IconName::Copy)
16613                    .icon_color(Color::Muted)
16614                    .size(ButtonSize::Compact)
16615                    .style(ButtonStyle::Transparent)
16616                    .visible_on_hover(group_id.clone())
16617                    .on_click({
16618                        let message = diagnostic.message.clone();
16619                        move |_click, _, cx| {
16620                            cx.write_to_clipboard(ClipboardItem::new_string(message.clone()))
16621                        }
16622                    })
16623                    .tooltip(Tooltip::text("Copy diagnostic message")),
16624            )
16625        };
16626
16627        let icon_size = buttons(&diagnostic).into_any_element().layout_as_root(
16628            AvailableSpace::min_size(),
16629            cx.window,
16630            cx.app,
16631        );
16632
16633        h_flex()
16634            .id(cx.block_id)
16635            .group(group_id.clone())
16636            .relative()
16637            .size_full()
16638            .block_mouse_down()
16639            .pl(cx.gutter_dimensions.width)
16640            .w(cx.max_width - cx.gutter_dimensions.full_width())
16641            .child(
16642                div()
16643                    .flex()
16644                    .w(cx.anchor_x - cx.gutter_dimensions.width - icon_size.width)
16645                    .flex_shrink(),
16646            )
16647            .child(buttons(&diagnostic))
16648            .child(div().flex().flex_shrink_0().child(
16649                StyledText::new(text_without_backticks.clone()).with_highlights(
16650                    &text_style,
16651                    code_ranges.iter().map(|range| {
16652                        (
16653                            range.clone(),
16654                            HighlightStyle {
16655                                font_weight: Some(FontWeight::BOLD),
16656                                ..Default::default()
16657                            },
16658                        )
16659                    }),
16660                ),
16661            ))
16662            .into_any_element()
16663    })
16664}
16665
16666fn inline_completion_edit_text(
16667    current_snapshot: &BufferSnapshot,
16668    edits: &[(Range<Anchor>, String)],
16669    edit_preview: &EditPreview,
16670    include_deletions: bool,
16671    cx: &App,
16672) -> HighlightedText {
16673    let edits = edits
16674        .iter()
16675        .map(|(anchor, text)| {
16676            (
16677                anchor.start.text_anchor..anchor.end.text_anchor,
16678                text.clone(),
16679            )
16680        })
16681        .collect::<Vec<_>>();
16682
16683    edit_preview.highlight_edits(current_snapshot, &edits, include_deletions, cx)
16684}
16685
16686pub fn highlight_diagnostic_message(
16687    diagnostic: &Diagnostic,
16688    mut max_message_rows: Option<u8>,
16689) -> (SharedString, Vec<Range<usize>>) {
16690    let mut text_without_backticks = String::new();
16691    let mut code_ranges = Vec::new();
16692
16693    if let Some(source) = &diagnostic.source {
16694        text_without_backticks.push_str(source);
16695        code_ranges.push(0..source.len());
16696        text_without_backticks.push_str(": ");
16697    }
16698
16699    let mut prev_offset = 0;
16700    let mut in_code_block = false;
16701    let has_row_limit = max_message_rows.is_some();
16702    let mut newline_indices = diagnostic
16703        .message
16704        .match_indices('\n')
16705        .filter(|_| has_row_limit)
16706        .map(|(ix, _)| ix)
16707        .fuse()
16708        .peekable();
16709
16710    for (quote_ix, _) in diagnostic
16711        .message
16712        .match_indices('`')
16713        .chain([(diagnostic.message.len(), "")])
16714    {
16715        let mut first_newline_ix = None;
16716        let mut last_newline_ix = None;
16717        while let Some(newline_ix) = newline_indices.peek() {
16718            if *newline_ix < quote_ix {
16719                if first_newline_ix.is_none() {
16720                    first_newline_ix = Some(*newline_ix);
16721                }
16722                last_newline_ix = Some(*newline_ix);
16723
16724                if let Some(rows_left) = &mut max_message_rows {
16725                    if *rows_left == 0 {
16726                        break;
16727                    } else {
16728                        *rows_left -= 1;
16729                    }
16730                }
16731                let _ = newline_indices.next();
16732            } else {
16733                break;
16734            }
16735        }
16736        let prev_len = text_without_backticks.len();
16737        let new_text = &diagnostic.message[prev_offset..first_newline_ix.unwrap_or(quote_ix)];
16738        text_without_backticks.push_str(new_text);
16739        if in_code_block {
16740            code_ranges.push(prev_len..text_without_backticks.len());
16741        }
16742        prev_offset = last_newline_ix.unwrap_or(quote_ix) + 1;
16743        in_code_block = !in_code_block;
16744        if first_newline_ix.map_or(false, |newline_ix| newline_ix < quote_ix) {
16745            text_without_backticks.push_str("...");
16746            break;
16747        }
16748    }
16749
16750    (text_without_backticks.into(), code_ranges)
16751}
16752
16753fn diagnostic_style(severity: DiagnosticSeverity, colors: &StatusColors) -> Hsla {
16754    match severity {
16755        DiagnosticSeverity::ERROR => colors.error,
16756        DiagnosticSeverity::WARNING => colors.warning,
16757        DiagnosticSeverity::INFORMATION => colors.info,
16758        DiagnosticSeverity::HINT => colors.info,
16759        _ => colors.ignored,
16760    }
16761}
16762
16763pub fn styled_runs_for_code_label<'a>(
16764    label: &'a CodeLabel,
16765    syntax_theme: &'a theme::SyntaxTheme,
16766) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
16767    let fade_out = HighlightStyle {
16768        fade_out: Some(0.35),
16769        ..Default::default()
16770    };
16771
16772    let mut prev_end = label.filter_range.end;
16773    label
16774        .runs
16775        .iter()
16776        .enumerate()
16777        .flat_map(move |(ix, (range, highlight_id))| {
16778            let style = if let Some(style) = highlight_id.style(syntax_theme) {
16779                style
16780            } else {
16781                return Default::default();
16782            };
16783            let mut muted_style = style;
16784            muted_style.highlight(fade_out);
16785
16786            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
16787            if range.start >= label.filter_range.end {
16788                if range.start > prev_end {
16789                    runs.push((prev_end..range.start, fade_out));
16790                }
16791                runs.push((range.clone(), muted_style));
16792            } else if range.end <= label.filter_range.end {
16793                runs.push((range.clone(), style));
16794            } else {
16795                runs.push((range.start..label.filter_range.end, style));
16796                runs.push((label.filter_range.end..range.end, muted_style));
16797            }
16798            prev_end = cmp::max(prev_end, range.end);
16799
16800            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
16801                runs.push((prev_end..label.text.len(), fade_out));
16802            }
16803
16804            runs
16805        })
16806}
16807
16808pub(crate) fn split_words(text: &str) -> impl std::iter::Iterator<Item = &str> + '_ {
16809    let mut prev_index = 0;
16810    let mut prev_codepoint: Option<char> = None;
16811    text.char_indices()
16812        .chain([(text.len(), '\0')])
16813        .filter_map(move |(index, codepoint)| {
16814            let prev_codepoint = prev_codepoint.replace(codepoint)?;
16815            let is_boundary = index == text.len()
16816                || !prev_codepoint.is_uppercase() && codepoint.is_uppercase()
16817                || !prev_codepoint.is_alphanumeric() && codepoint.is_alphanumeric();
16818            if is_boundary {
16819                let chunk = &text[prev_index..index];
16820                prev_index = index;
16821                Some(chunk)
16822            } else {
16823                None
16824            }
16825        })
16826}
16827
16828pub trait RangeToAnchorExt: Sized {
16829    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor>;
16830
16831    fn to_display_points(self, snapshot: &EditorSnapshot) -> Range<DisplayPoint> {
16832        let anchor_range = self.to_anchors(&snapshot.buffer_snapshot);
16833        anchor_range.start.to_display_point(snapshot)..anchor_range.end.to_display_point(snapshot)
16834    }
16835}
16836
16837impl<T: ToOffset> RangeToAnchorExt for Range<T> {
16838    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor> {
16839        let start_offset = self.start.to_offset(snapshot);
16840        let end_offset = self.end.to_offset(snapshot);
16841        if start_offset == end_offset {
16842            snapshot.anchor_before(start_offset)..snapshot.anchor_before(end_offset)
16843        } else {
16844            snapshot.anchor_after(self.start)..snapshot.anchor_before(self.end)
16845        }
16846    }
16847}
16848
16849pub trait RowExt {
16850    fn as_f32(&self) -> f32;
16851
16852    fn next_row(&self) -> Self;
16853
16854    fn previous_row(&self) -> Self;
16855
16856    fn minus(&self, other: Self) -> u32;
16857}
16858
16859impl RowExt for DisplayRow {
16860    fn as_f32(&self) -> f32 {
16861        self.0 as f32
16862    }
16863
16864    fn next_row(&self) -> Self {
16865        Self(self.0 + 1)
16866    }
16867
16868    fn previous_row(&self) -> Self {
16869        Self(self.0.saturating_sub(1))
16870    }
16871
16872    fn minus(&self, other: Self) -> u32 {
16873        self.0 - other.0
16874    }
16875}
16876
16877impl RowExt for MultiBufferRow {
16878    fn as_f32(&self) -> f32 {
16879        self.0 as f32
16880    }
16881
16882    fn next_row(&self) -> Self {
16883        Self(self.0 + 1)
16884    }
16885
16886    fn previous_row(&self) -> Self {
16887        Self(self.0.saturating_sub(1))
16888    }
16889
16890    fn minus(&self, other: Self) -> u32 {
16891        self.0 - other.0
16892    }
16893}
16894
16895trait RowRangeExt {
16896    type Row;
16897
16898    fn len(&self) -> usize;
16899
16900    fn iter_rows(&self) -> impl DoubleEndedIterator<Item = Self::Row>;
16901}
16902
16903impl RowRangeExt for Range<MultiBufferRow> {
16904    type Row = MultiBufferRow;
16905
16906    fn len(&self) -> usize {
16907        (self.end.0 - self.start.0) as usize
16908    }
16909
16910    fn iter_rows(&self) -> impl DoubleEndedIterator<Item = MultiBufferRow> {
16911        (self.start.0..self.end.0).map(MultiBufferRow)
16912    }
16913}
16914
16915impl RowRangeExt for Range<DisplayRow> {
16916    type Row = DisplayRow;
16917
16918    fn len(&self) -> usize {
16919        (self.end.0 - self.start.0) as usize
16920    }
16921
16922    fn iter_rows(&self) -> impl DoubleEndedIterator<Item = DisplayRow> {
16923        (self.start.0..self.end.0).map(DisplayRow)
16924    }
16925}
16926
16927/// If select range has more than one line, we
16928/// just point the cursor to range.start.
16929fn collapse_multiline_range(range: Range<Point>) -> Range<Point> {
16930    if range.start.row == range.end.row {
16931        range
16932    } else {
16933        range.start..range.start
16934    }
16935}
16936pub struct KillRing(ClipboardItem);
16937impl Global for KillRing {}
16938
16939const UPDATE_DEBOUNCE: Duration = Duration::from_millis(50);
16940
16941fn all_edits_insertions_or_deletions(
16942    edits: &Vec<(Range<Anchor>, String)>,
16943    snapshot: &MultiBufferSnapshot,
16944) -> bool {
16945    let mut all_insertions = true;
16946    let mut all_deletions = true;
16947
16948    for (range, new_text) in edits.iter() {
16949        let range_is_empty = range.to_offset(&snapshot).is_empty();
16950        let text_is_empty = new_text.is_empty();
16951
16952        if range_is_empty != text_is_empty {
16953            if range_is_empty {
16954                all_deletions = false;
16955            } else {
16956                all_insertions = false;
16957            }
16958        } else {
16959            return false;
16960        }
16961
16962        if !all_insertions && !all_deletions {
16963            return false;
16964        }
16965    }
16966    all_insertions || all_deletions
16967}