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 blame_entry_tooltip;
   17mod blink_manager;
   18mod clangd_ext;
   19mod code_context_menus;
   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 hunk_diff;
   29mod indent_guides;
   30mod inlay_hint_cache;
   31pub mod items;
   32mod linked_editing_ranges;
   33mod lsp_ext;
   34mod mouse_context_menu;
   35pub mod movement;
   36mod persistence;
   37mod proposed_changes_editor;
   38mod rust_analyzer_ext;
   39pub mod scroll;
   40mod selections_collection;
   41pub mod tasks;
   42
   43#[cfg(test)]
   44mod editor_tests;
   45#[cfg(test)]
   46mod inline_completion_tests;
   47mod signature_help;
   48#[cfg(any(test, feature = "test-support"))]
   49pub mod test;
   50
   51use ::git::diff::DiffHunkStatus;
   52pub(crate) use actions::*;
   53pub use actions::{OpenExcerpts, OpenExcerptsSplit};
   54use aho_corasick::AhoCorasick;
   55use anyhow::{anyhow, Context as _, Result};
   56use blink_manager::BlinkManager;
   57use client::{Collaborator, ParticipantIndex};
   58use clock::ReplicaId;
   59use collections::{BTreeMap, Bound, HashMap, HashSet, VecDeque};
   60use convert_case::{Case, Casing};
   61use display_map::*;
   62pub use display_map::{DisplayPoint, FoldPlaceholder};
   63pub use editor_settings::{
   64    CurrentLineHighlight, EditorSettings, ScrollBeyondLastLine, SearchSettings, ShowScrollbar,
   65};
   66pub use editor_settings_controls::*;
   67use element::LineWithInvisibles;
   68pub use element::{
   69    CursorLayout, EditorElement, HighlightedRange, HighlightedRangeLine, PointForPosition,
   70};
   71use futures::{future, FutureExt};
   72use fuzzy::StringMatchCandidate;
   73use zed_predict_tos::ZedPredictTos;
   74
   75use code_context_menus::{
   76    AvailableCodeAction, CodeActionContents, CodeActionsItem, CodeActionsMenu, CodeContextMenu,
   77    CompletionEntry, CompletionsMenu, ContextMenuOrigin,
   78};
   79use git::blame::GitBlame;
   80use gpui::{
   81    div, impl_actions, point, prelude::*, px, relative, size, Action, AnyElement, AppContext,
   82    AsyncWindowContext, AvailableSpace, Bounds, ClipboardEntry, ClipboardItem, Context,
   83    DispatchPhase, ElementId, EventEmitter, FocusHandle, FocusOutEvent, FocusableView, FontId,
   84    FontWeight, Global, HighlightStyle, Hsla, InteractiveText, KeyContext, Model, ModelContext,
   85    MouseButton, PaintQuad, ParentElement, Pixels, Render, SharedString, Size, Styled, StyledText,
   86    Subscription, Task, TextStyle, TextStyleRefinement, UTF16Selection, UnderlineStyle,
   87    UniformListScrollHandle, View, ViewContext, ViewInputHandler, VisualContext, WeakFocusHandle,
   88    WeakView, WindowContext,
   89};
   90use highlight_matching_bracket::refresh_matching_bracket_highlights;
   91use hover_popover::{hide_hover, HoverState};
   92pub(crate) use hunk_diff::HoveredHunk;
   93use hunk_diff::{diff_hunk_to_display, DiffMap, DiffMapSnapshot};
   94use indent_guides::ActiveIndentGuidesState;
   95use inlay_hint_cache::{InlayHintCache, InlaySplice, InvalidationStrategy};
   96pub use inline_completion::Direction;
   97use inline_completion::{InlineCompletionProvider, InlineCompletionProviderHandle};
   98pub use items::MAX_TAB_TITLE_LEN;
   99use itertools::Itertools;
  100use language::{
  101    language_settings::{self, all_language_settings, language_settings, InlayHintSettings},
  102    markdown, point_from_lsp, AutoindentMode, BracketPair, Buffer, Capability, CharKind, CodeLabel,
  103    CursorShape, Diagnostic, Documentation, EditPreview, HighlightedEdits, IndentKind, IndentSize,
  104    Language, OffsetRangeExt, Point, Selection, SelectionGoal, TransactionId,
  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, ToOffset,
  127    ToPoint,
  128};
  129use multi_buffer::{
  130    ExpandExcerptDirection, MultiBufferDiffHunk, MultiBufferPoint, MultiBufferRow, ToOffsetUtf16,
  131};
  132use project::{
  133    buffer_store::BufferChangeSet,
  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::{ActiveTheme, PlayerColor, StatusColors, SyntaxTheme, ThemeColors, ThemeSettings};
  166use ui::{
  167    h_flex, prelude::*, ButtonSize, ButtonStyle, Disclosure, IconButton, IconName, IconSize,
  168    PopoverMenuHandle, Tooltip,
  169};
  170use util::{defer, maybe, post_inc, RangeExt, ResultExt, TryFutureExt};
  171use workspace::item::{ItemHandle, PreviewTabsSettings};
  172use workspace::notifications::{DetachAndPromptErr, NotificationId, NotifyTaskExt};
  173use workspace::{
  174    searchable::SearchEvent, ItemNavHistory, SplitDirection, ViewId, Workspace, WorkspaceId,
  175};
  176use workspace::{Item as WorkspaceItem, OpenInTerminal, OpenTerminal, TabBarSettings, Toast};
  177
  178use crate::hover_links::{find_url, find_url_from_range};
  179use crate::signature_help::{SignatureHelpHiddenBy, SignatureHelpState};
  180
  181pub const FILE_HEADER_HEIGHT: u32 = 2;
  182pub const MULTI_BUFFER_EXCERPT_HEADER_HEIGHT: u32 = 1;
  183pub const MULTI_BUFFER_EXCERPT_FOOTER_HEIGHT: u32 = 1;
  184pub const DEFAULT_MULTIBUFFER_CONTEXT: u32 = 2;
  185const CURSOR_BLINK_INTERVAL: Duration = Duration::from_millis(500);
  186const MAX_LINE_LEN: usize = 1024;
  187const MIN_NAVIGATION_HISTORY_ROW_DELTA: i64 = 10;
  188const MAX_SELECTION_HISTORY_LEN: usize = 1024;
  189pub(crate) const CURSORS_VISIBLE_FOR: Duration = Duration::from_millis(2000);
  190#[doc(hidden)]
  191pub const CODE_ACTIONS_DEBOUNCE_TIMEOUT: Duration = Duration::from_millis(250);
  192
  193pub(crate) const FORMAT_TIMEOUT: Duration = Duration::from_secs(2);
  194pub(crate) const SCROLL_CENTER_TOP_BOTTOM_DEBOUNCE_TIMEOUT: Duration = Duration::from_secs(1);
  195
  196pub fn render_parsed_markdown(
  197    element_id: impl Into<ElementId>,
  198    parsed: &language::ParsedMarkdown,
  199    editor_style: &EditorStyle,
  200    workspace: Option<WeakView<Workspace>>,
  201    cx: &mut WindowContext,
  202) -> InteractiveText {
  203    let code_span_background_color = cx
  204        .theme()
  205        .colors()
  206        .editor_document_highlight_read_background;
  207
  208    let highlights = gpui::combine_highlights(
  209        parsed.highlights.iter().filter_map(|(range, highlight)| {
  210            let highlight = highlight.to_highlight_style(&editor_style.syntax)?;
  211            Some((range.clone(), highlight))
  212        }),
  213        parsed
  214            .regions
  215            .iter()
  216            .zip(&parsed.region_ranges)
  217            .filter_map(|(region, range)| {
  218                if region.code {
  219                    Some((
  220                        range.clone(),
  221                        HighlightStyle {
  222                            background_color: Some(code_span_background_color),
  223                            ..Default::default()
  224                        },
  225                    ))
  226                } else {
  227                    None
  228                }
  229            }),
  230    );
  231
  232    let mut links = Vec::new();
  233    let mut link_ranges = Vec::new();
  234    for (range, region) in parsed.region_ranges.iter().zip(&parsed.regions) {
  235        if let Some(link) = region.link.clone() {
  236            links.push(link);
  237            link_ranges.push(range.clone());
  238        }
  239    }
  240
  241    InteractiveText::new(
  242        element_id,
  243        StyledText::new(parsed.text.clone()).with_highlights(&editor_style.text, highlights),
  244    )
  245    .on_click(link_ranges, move |clicked_range_ix, cx| {
  246        match &links[clicked_range_ix] {
  247            markdown::Link::Web { url } => cx.open_url(url),
  248            markdown::Link::Path { path } => {
  249                if let Some(workspace) = &workspace {
  250                    _ = workspace.update(cx, |workspace, cx| {
  251                        workspace.open_abs_path(path.clone(), false, cx).detach();
  252                    });
  253                }
  254            }
  255        }
  256    })
  257}
  258
  259#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
  260pub enum InlayId {
  261    InlineCompletion(usize),
  262    Hint(usize),
  263}
  264
  265impl InlayId {
  266    fn id(&self) -> usize {
  267        match self {
  268            Self::InlineCompletion(id) => *id,
  269            Self::Hint(id) => *id,
  270        }
  271    }
  272}
  273
  274enum DiffRowHighlight {}
  275enum DocumentHighlightRead {}
  276enum DocumentHighlightWrite {}
  277enum InputComposition {}
  278
  279#[derive(Debug, Copy, Clone, PartialEq, Eq)]
  280pub enum Navigated {
  281    Yes,
  282    No,
  283}
  284
  285impl Navigated {
  286    pub fn from_bool(yes: bool) -> Navigated {
  287        if yes {
  288            Navigated::Yes
  289        } else {
  290            Navigated::No
  291        }
  292    }
  293}
  294
  295pub fn init_settings(cx: &mut AppContext) {
  296    EditorSettings::register(cx);
  297}
  298
  299pub fn init(cx: &mut AppContext) {
  300    init_settings(cx);
  301
  302    workspace::register_project_item::<Editor>(cx);
  303    workspace::FollowableViewRegistry::register::<Editor>(cx);
  304    workspace::register_serializable_item::<Editor>(cx);
  305
  306    cx.observe_new_views(
  307        |workspace: &mut Workspace, _cx: &mut ViewContext<Workspace>| {
  308            workspace.register_action(Editor::new_file);
  309            workspace.register_action(Editor::new_file_vertical);
  310            workspace.register_action(Editor::new_file_horizontal);
  311        },
  312    )
  313    .detach();
  314
  315    cx.on_action(move |_: &workspace::NewFile, cx| {
  316        let app_state = workspace::AppState::global(cx);
  317        if let Some(app_state) = app_state.upgrade() {
  318            workspace::open_new(Default::default(), app_state, cx, |workspace, cx| {
  319                Editor::new_file(workspace, &Default::default(), cx)
  320            })
  321            .detach();
  322        }
  323    });
  324    cx.on_action(move |_: &workspace::NewWindow, cx| {
  325        let app_state = workspace::AppState::global(cx);
  326        if let Some(app_state) = app_state.upgrade() {
  327            workspace::open_new(Default::default(), app_state, cx, |workspace, cx| {
  328                Editor::new_file(workspace, &Default::default(), cx)
  329            })
  330            .detach();
  331        }
  332    });
  333    git::project_diff::init(cx);
  334}
  335
  336pub struct SearchWithinRange;
  337
  338trait InvalidationRegion {
  339    fn ranges(&self) -> &[Range<Anchor>];
  340}
  341
  342#[derive(Clone, Debug, PartialEq)]
  343pub enum SelectPhase {
  344    Begin {
  345        position: DisplayPoint,
  346        add: bool,
  347        click_count: usize,
  348    },
  349    BeginColumnar {
  350        position: DisplayPoint,
  351        reset: bool,
  352        goal_column: u32,
  353    },
  354    Extend {
  355        position: DisplayPoint,
  356        click_count: usize,
  357    },
  358    Update {
  359        position: DisplayPoint,
  360        goal_column: u32,
  361        scroll_delta: gpui::Point<f32>,
  362    },
  363    End,
  364}
  365
  366#[derive(Clone, Debug)]
  367pub enum SelectMode {
  368    Character,
  369    Word(Range<Anchor>),
  370    Line(Range<Anchor>),
  371    All,
  372}
  373
  374#[derive(Copy, Clone, PartialEq, Eq, Debug)]
  375pub enum EditorMode {
  376    SingleLine { auto_width: bool },
  377    AutoHeight { max_lines: usize },
  378    Full,
  379}
  380
  381#[derive(Copy, Clone, Debug)]
  382pub enum SoftWrap {
  383    /// Prefer not to wrap at all.
  384    ///
  385    /// Note: this is currently internal, as actually limited by [`crate::MAX_LINE_LEN`] until it wraps.
  386    /// The mode is used inside git diff hunks, where it's seems currently more useful to not wrap as much as possible.
  387    GitDiff,
  388    /// Prefer a single line generally, unless an overly long line is encountered.
  389    None,
  390    /// Soft wrap lines that exceed the editor width.
  391    EditorWidth,
  392    /// Soft wrap lines at the preferred line length.
  393    Column(u32),
  394    /// Soft wrap line at the preferred line length or the editor width (whichever is smaller).
  395    Bounded(u32),
  396}
  397
  398#[derive(Clone)]
  399pub struct EditorStyle {
  400    pub background: Hsla,
  401    pub local_player: PlayerColor,
  402    pub text: TextStyle,
  403    pub scrollbar_width: Pixels,
  404    pub syntax: Arc<SyntaxTheme>,
  405    pub status: StatusColors,
  406    pub inlay_hints_style: HighlightStyle,
  407    pub inline_completion_styles: InlineCompletionStyles,
  408    pub unnecessary_code_fade: f32,
  409}
  410
  411impl Default for EditorStyle {
  412    fn default() -> Self {
  413        Self {
  414            background: Hsla::default(),
  415            local_player: PlayerColor::default(),
  416            text: TextStyle::default(),
  417            scrollbar_width: Pixels::default(),
  418            syntax: Default::default(),
  419            // HACK: Status colors don't have a real default.
  420            // We should look into removing the status colors from the editor
  421            // style and retrieve them directly from the theme.
  422            status: StatusColors::dark(),
  423            inlay_hints_style: HighlightStyle::default(),
  424            inline_completion_styles: InlineCompletionStyles {
  425                insertion: HighlightStyle::default(),
  426                whitespace: HighlightStyle::default(),
  427            },
  428            unnecessary_code_fade: Default::default(),
  429        }
  430    }
  431}
  432
  433pub fn make_inlay_hints_style(cx: &WindowContext) -> HighlightStyle {
  434    let show_background = language_settings::language_settings(None, None, cx)
  435        .inlay_hints
  436        .show_background;
  437
  438    HighlightStyle {
  439        color: Some(cx.theme().status().hint),
  440        background_color: show_background.then(|| cx.theme().status().hint_background),
  441        ..HighlightStyle::default()
  442    }
  443}
  444
  445pub fn make_suggestion_styles(cx: &WindowContext) -> InlineCompletionStyles {
  446    InlineCompletionStyles {
  447        insertion: HighlightStyle {
  448            color: Some(cx.theme().status().predictive),
  449            ..HighlightStyle::default()
  450        },
  451        whitespace: HighlightStyle {
  452            background_color: Some(cx.theme().status().created_background),
  453            ..HighlightStyle::default()
  454        },
  455    }
  456}
  457
  458type CompletionId = usize;
  459
  460#[derive(Debug, Clone)]
  461enum InlineCompletionMenuHint {
  462    Loading,
  463    Loaded { text: InlineCompletionText },
  464    PendingTermsAcceptance,
  465    None,
  466}
  467
  468impl InlineCompletionMenuHint {
  469    pub fn label(&self) -> &'static str {
  470        match self {
  471            InlineCompletionMenuHint::Loading | InlineCompletionMenuHint::Loaded { .. } => {
  472                "Edit Prediction"
  473            }
  474            InlineCompletionMenuHint::PendingTermsAcceptance => "Accept Terms of Service",
  475            InlineCompletionMenuHint::None => "No Prediction",
  476        }
  477    }
  478}
  479
  480#[derive(Clone, Debug)]
  481enum InlineCompletionText {
  482    Move(SharedString),
  483    Edit(HighlightedEdits),
  484}
  485
  486pub(crate) enum EditDisplayMode {
  487    TabAccept,
  488    DiffPopover,
  489    Inline,
  490}
  491
  492enum InlineCompletion {
  493    Edit {
  494        edits: Vec<(Range<Anchor>, String)>,
  495        edit_preview: Option<EditPreview>,
  496        display_mode: EditDisplayMode,
  497        snapshot: BufferSnapshot,
  498    },
  499    Move(Anchor),
  500}
  501
  502struct InlineCompletionState {
  503    inlay_ids: Vec<InlayId>,
  504    completion: InlineCompletion,
  505    invalidation_range: Range<Anchor>,
  506}
  507
  508enum InlineCompletionHighlight {}
  509
  510#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Debug, Default)]
  511struct EditorActionId(usize);
  512
  513impl EditorActionId {
  514    pub fn post_inc(&mut self) -> Self {
  515        let answer = self.0;
  516
  517        *self = Self(answer + 1);
  518
  519        Self(answer)
  520    }
  521}
  522
  523// type GetFieldEditorTheme = dyn Fn(&theme::Theme) -> theme::FieldEditor;
  524// type OverrideTextStyle = dyn Fn(&EditorStyle) -> Option<HighlightStyle>;
  525
  526type BackgroundHighlight = (fn(&ThemeColors) -> Hsla, Arc<[Range<Anchor>]>);
  527type GutterHighlight = (fn(&AppContext) -> Hsla, Arc<[Range<Anchor>]>);
  528
  529#[derive(Default)]
  530struct ScrollbarMarkerState {
  531    scrollbar_size: Size<Pixels>,
  532    dirty: bool,
  533    markers: Arc<[PaintQuad]>,
  534    pending_refresh: Option<Task<Result<()>>>,
  535}
  536
  537impl ScrollbarMarkerState {
  538    fn should_refresh(&self, scrollbar_size: Size<Pixels>) -> bool {
  539        self.pending_refresh.is_none() && (self.scrollbar_size != scrollbar_size || self.dirty)
  540    }
  541}
  542
  543#[derive(Clone, Debug)]
  544struct RunnableTasks {
  545    templates: Vec<(TaskSourceKind, TaskTemplate)>,
  546    offset: MultiBufferOffset,
  547    // We need the column at which the task context evaluation should take place (when we're spawning it via gutter).
  548    column: u32,
  549    // Values of all named captures, including those starting with '_'
  550    extra_variables: HashMap<String, String>,
  551    // Full range of the tagged region. We use it to determine which `extra_variables` to grab for context resolution in e.g. a modal.
  552    context_range: Range<BufferOffset>,
  553}
  554
  555impl RunnableTasks {
  556    fn resolve<'a>(
  557        &'a self,
  558        cx: &'a task::TaskContext,
  559    ) -> impl Iterator<Item = (TaskSourceKind, ResolvedTask)> + 'a {
  560        self.templates.iter().filter_map(|(kind, template)| {
  561            template
  562                .resolve_task(&kind.to_id_base(), cx)
  563                .map(|task| (kind.clone(), task))
  564        })
  565    }
  566}
  567
  568#[derive(Clone)]
  569struct ResolvedTasks {
  570    templates: SmallVec<[(TaskSourceKind, ResolvedTask); 1]>,
  571    position: Anchor,
  572}
  573#[derive(Copy, Clone, Debug)]
  574struct MultiBufferOffset(usize);
  575#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
  576struct BufferOffset(usize);
  577
  578// Addons allow storing per-editor state in other crates (e.g. Vim)
  579pub trait Addon: 'static {
  580    fn extend_key_context(&self, _: &mut KeyContext, _: &AppContext) {}
  581
  582    fn to_any(&self) -> &dyn std::any::Any;
  583}
  584
  585#[derive(Debug, Copy, Clone, PartialEq, Eq)]
  586pub enum IsVimMode {
  587    Yes,
  588    No,
  589}
  590
  591/// Zed's primary text input `View`, allowing users to edit a [`MultiBuffer`]
  592///
  593/// See the [module level documentation](self) for more information.
  594pub struct Editor {
  595    focus_handle: FocusHandle,
  596    last_focused_descendant: Option<WeakFocusHandle>,
  597    /// The text buffer being edited
  598    buffer: Model<MultiBuffer>,
  599    /// Map of how text in the buffer should be displayed.
  600    /// Handles soft wraps, folds, fake inlay text insertions, etc.
  601    pub display_map: Model<DisplayMap>,
  602    pub selections: SelectionsCollection,
  603    pub scroll_manager: ScrollManager,
  604    /// When inline assist editors are linked, they all render cursors because
  605    /// typing enters text into each of them, even the ones that aren't focused.
  606    pub(crate) show_cursor_when_unfocused: bool,
  607    columnar_selection_tail: Option<Anchor>,
  608    add_selections_state: Option<AddSelectionsState>,
  609    select_next_state: Option<SelectNextState>,
  610    select_prev_state: Option<SelectNextState>,
  611    selection_history: SelectionHistory,
  612    autoclose_regions: Vec<AutocloseRegion>,
  613    snippet_stack: InvalidationStack<SnippetState>,
  614    select_larger_syntax_node_stack: Vec<Box<[Selection<usize>]>>,
  615    ime_transaction: Option<TransactionId>,
  616    active_diagnostics: Option<ActiveDiagnosticGroup>,
  617    soft_wrap_mode_override: Option<language_settings::SoftWrap>,
  618
  619    project: Option<Model<Project>>,
  620    semantics_provider: Option<Rc<dyn SemanticsProvider>>,
  621    completion_provider: Option<Box<dyn CompletionProvider>>,
  622    collaboration_hub: Option<Box<dyn CollaborationHub>>,
  623    blink_manager: Model<BlinkManager>,
  624    show_cursor_names: bool,
  625    hovered_cursors: HashMap<HoveredCursor, Task<()>>,
  626    pub show_local_selections: bool,
  627    mode: EditorMode,
  628    show_breadcrumbs: bool,
  629    show_gutter: bool,
  630    show_scrollbars: bool,
  631    show_line_numbers: Option<bool>,
  632    use_relative_line_numbers: Option<bool>,
  633    show_git_diff_gutter: Option<bool>,
  634    show_code_actions: Option<bool>,
  635    show_runnables: Option<bool>,
  636    show_wrap_guides: Option<bool>,
  637    show_indent_guides: Option<bool>,
  638    placeholder_text: Option<Arc<str>>,
  639    highlight_order: usize,
  640    highlighted_rows: HashMap<TypeId, Vec<RowHighlight>>,
  641    background_highlights: TreeMap<TypeId, BackgroundHighlight>,
  642    gutter_highlights: TreeMap<TypeId, GutterHighlight>,
  643    scrollbar_marker_state: ScrollbarMarkerState,
  644    active_indent_guides_state: ActiveIndentGuidesState,
  645    nav_history: Option<ItemNavHistory>,
  646    context_menu: RefCell<Option<CodeContextMenu>>,
  647    mouse_context_menu: Option<MouseContextMenu>,
  648    hunk_controls_menu_handle: PopoverMenuHandle<ui::ContextMenu>,
  649    completion_tasks: Vec<(CompletionId, Task<Option<()>>)>,
  650    signature_help_state: SignatureHelpState,
  651    auto_signature_help: Option<bool>,
  652    find_all_references_task_sources: Vec<Anchor>,
  653    next_completion_id: CompletionId,
  654    available_code_actions: Option<(Location, Rc<[AvailableCodeAction]>)>,
  655    code_actions_task: Option<Task<Result<()>>>,
  656    document_highlights_task: Option<Task<()>>,
  657    linked_editing_range_task: Option<Task<Option<()>>>,
  658    linked_edit_ranges: linked_editing_ranges::LinkedEditingRanges,
  659    pending_rename: Option<RenameState>,
  660    searchable: bool,
  661    cursor_shape: CursorShape,
  662    current_line_highlight: Option<CurrentLineHighlight>,
  663    collapse_matches: bool,
  664    autoindent_mode: Option<AutoindentMode>,
  665    workspace: Option<(WeakView<Workspace>, Option<WorkspaceId>)>,
  666    input_enabled: bool,
  667    use_modal_editing: bool,
  668    read_only: bool,
  669    leader_peer_id: Option<PeerId>,
  670    remote_id: Option<ViewId>,
  671    hover_state: HoverState,
  672    gutter_hovered: bool,
  673    hovered_link_state: Option<HoveredLinkState>,
  674    inline_completion_provider: Option<RegisteredInlineCompletionProvider>,
  675    code_action_providers: Vec<Rc<dyn CodeActionProvider>>,
  676    active_inline_completion: Option<InlineCompletionState>,
  677    // enable_inline_completions is a switch that Vim can use to disable
  678    // inline completions based on its mode.
  679    enable_inline_completions: bool,
  680    show_inline_completions_override: Option<bool>,
  681    inlay_hint_cache: InlayHintCache,
  682    diff_map: DiffMap,
  683    next_inlay_id: usize,
  684    _subscriptions: Vec<Subscription>,
  685    pixel_position_of_newest_cursor: Option<gpui::Point<Pixels>>,
  686    gutter_dimensions: GutterDimensions,
  687    style: Option<EditorStyle>,
  688    text_style_refinement: Option<TextStyleRefinement>,
  689    next_editor_action_id: EditorActionId,
  690    editor_actions: Rc<RefCell<BTreeMap<EditorActionId, Box<dyn Fn(&mut ViewContext<Self>)>>>>,
  691    use_autoclose: bool,
  692    use_auto_surround: bool,
  693    auto_replace_emoji_shortcode: bool,
  694    show_git_blame_gutter: bool,
  695    show_git_blame_inline: bool,
  696    show_git_blame_inline_delay_task: Option<Task<()>>,
  697    git_blame_inline_enabled: bool,
  698    serialize_dirty_buffers: bool,
  699    show_selection_menu: Option<bool>,
  700    blame: Option<Model<GitBlame>>,
  701    blame_subscription: Option<Subscription>,
  702    custom_context_menu: Option<
  703        Box<
  704            dyn 'static
  705                + Fn(&mut Self, DisplayPoint, &mut ViewContext<Self>) -> Option<View<ui::ContextMenu>>,
  706        >,
  707    >,
  708    last_bounds: Option<Bounds<Pixels>>,
  709    expect_bounds_change: Option<Bounds<Pixels>>,
  710    tasks: BTreeMap<(BufferId, BufferRow), RunnableTasks>,
  711    tasks_update_task: Option<Task<()>>,
  712    previous_search_ranges: Option<Arc<[Range<Anchor>]>>,
  713    breadcrumb_header: Option<String>,
  714    focused_block: Option<FocusedBlock>,
  715    next_scroll_position: NextScrollCursorCenterTopBottom,
  716    addons: HashMap<TypeId, Box<dyn Addon>>,
  717    registered_buffers: HashMap<BufferId, OpenLspBufferHandle>,
  718    selection_mark_mode: bool,
  719    toggle_fold_multiple_buffers: Task<()>,
  720    _scroll_cursor_center_top_bottom_task: Task<()>,
  721}
  722
  723#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)]
  724enum NextScrollCursorCenterTopBottom {
  725    #[default]
  726    Center,
  727    Top,
  728    Bottom,
  729}
  730
  731impl NextScrollCursorCenterTopBottom {
  732    fn next(&self) -> Self {
  733        match self {
  734            Self::Center => Self::Top,
  735            Self::Top => Self::Bottom,
  736            Self::Bottom => Self::Center,
  737        }
  738    }
  739}
  740
  741#[derive(Clone)]
  742pub struct EditorSnapshot {
  743    pub mode: EditorMode,
  744    show_gutter: bool,
  745    show_line_numbers: Option<bool>,
  746    show_git_diff_gutter: Option<bool>,
  747    show_code_actions: Option<bool>,
  748    show_runnables: Option<bool>,
  749    git_blame_gutter_max_author_length: Option<usize>,
  750    pub display_snapshot: DisplaySnapshot,
  751    pub placeholder_text: Option<Arc<str>>,
  752    diff_map: DiffMapSnapshot,
  753    is_focused: bool,
  754    scroll_anchor: ScrollAnchor,
  755    ongoing_scroll: OngoingScroll,
  756    current_line_highlight: CurrentLineHighlight,
  757    gutter_hovered: bool,
  758}
  759
  760const GIT_BLAME_MAX_AUTHOR_CHARS_DISPLAYED: usize = 20;
  761
  762#[derive(Default, Debug, Clone, Copy)]
  763pub struct GutterDimensions {
  764    pub left_padding: Pixels,
  765    pub right_padding: Pixels,
  766    pub width: Pixels,
  767    pub margin: Pixels,
  768    pub git_blame_entries_width: Option<Pixels>,
  769}
  770
  771impl GutterDimensions {
  772    /// The full width of the space taken up by the gutter.
  773    pub fn full_width(&self) -> Pixels {
  774        self.margin + self.width
  775    }
  776
  777    /// The width of the space reserved for the fold indicators,
  778    /// use alongside 'justify_end' and `gutter_width` to
  779    /// right align content with the line numbers
  780    pub fn fold_area_width(&self) -> Pixels {
  781        self.margin + self.right_padding
  782    }
  783}
  784
  785#[derive(Debug)]
  786pub struct RemoteSelection {
  787    pub replica_id: ReplicaId,
  788    pub selection: Selection<Anchor>,
  789    pub cursor_shape: CursorShape,
  790    pub peer_id: PeerId,
  791    pub line_mode: bool,
  792    pub participant_index: Option<ParticipantIndex>,
  793    pub user_name: Option<SharedString>,
  794}
  795
  796#[derive(Clone, Debug)]
  797struct SelectionHistoryEntry {
  798    selections: Arc<[Selection<Anchor>]>,
  799    select_next_state: Option<SelectNextState>,
  800    select_prev_state: Option<SelectNextState>,
  801    add_selections_state: Option<AddSelectionsState>,
  802}
  803
  804enum SelectionHistoryMode {
  805    Normal,
  806    Undoing,
  807    Redoing,
  808}
  809
  810#[derive(Clone, PartialEq, Eq, Hash)]
  811struct HoveredCursor {
  812    replica_id: u16,
  813    selection_id: usize,
  814}
  815
  816impl Default for SelectionHistoryMode {
  817    fn default() -> Self {
  818        Self::Normal
  819    }
  820}
  821
  822#[derive(Default)]
  823struct SelectionHistory {
  824    #[allow(clippy::type_complexity)]
  825    selections_by_transaction:
  826        HashMap<TransactionId, (Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)>,
  827    mode: SelectionHistoryMode,
  828    undo_stack: VecDeque<SelectionHistoryEntry>,
  829    redo_stack: VecDeque<SelectionHistoryEntry>,
  830}
  831
  832impl SelectionHistory {
  833    fn insert_transaction(
  834        &mut self,
  835        transaction_id: TransactionId,
  836        selections: Arc<[Selection<Anchor>]>,
  837    ) {
  838        self.selections_by_transaction
  839            .insert(transaction_id, (selections, None));
  840    }
  841
  842    #[allow(clippy::type_complexity)]
  843    fn transaction(
  844        &self,
  845        transaction_id: TransactionId,
  846    ) -> Option<&(Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)> {
  847        self.selections_by_transaction.get(&transaction_id)
  848    }
  849
  850    #[allow(clippy::type_complexity)]
  851    fn transaction_mut(
  852        &mut self,
  853        transaction_id: TransactionId,
  854    ) -> Option<&mut (Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)> {
  855        self.selections_by_transaction.get_mut(&transaction_id)
  856    }
  857
  858    fn push(&mut self, entry: SelectionHistoryEntry) {
  859        if !entry.selections.is_empty() {
  860            match self.mode {
  861                SelectionHistoryMode::Normal => {
  862                    self.push_undo(entry);
  863                    self.redo_stack.clear();
  864                }
  865                SelectionHistoryMode::Undoing => self.push_redo(entry),
  866                SelectionHistoryMode::Redoing => self.push_undo(entry),
  867            }
  868        }
  869    }
  870
  871    fn push_undo(&mut self, entry: SelectionHistoryEntry) {
  872        if self
  873            .undo_stack
  874            .back()
  875            .map_or(true, |e| e.selections != entry.selections)
  876        {
  877            self.undo_stack.push_back(entry);
  878            if self.undo_stack.len() > MAX_SELECTION_HISTORY_LEN {
  879                self.undo_stack.pop_front();
  880            }
  881        }
  882    }
  883
  884    fn push_redo(&mut self, entry: SelectionHistoryEntry) {
  885        if self
  886            .redo_stack
  887            .back()
  888            .map_or(true, |e| e.selections != entry.selections)
  889        {
  890            self.redo_stack.push_back(entry);
  891            if self.redo_stack.len() > MAX_SELECTION_HISTORY_LEN {
  892                self.redo_stack.pop_front();
  893            }
  894        }
  895    }
  896}
  897
  898struct RowHighlight {
  899    index: usize,
  900    range: Range<Anchor>,
  901    color: Hsla,
  902    should_autoscroll: bool,
  903}
  904
  905#[derive(Clone, Debug)]
  906struct AddSelectionsState {
  907    above: bool,
  908    stack: Vec<usize>,
  909}
  910
  911#[derive(Clone)]
  912struct SelectNextState {
  913    query: AhoCorasick,
  914    wordwise: bool,
  915    done: bool,
  916}
  917
  918impl std::fmt::Debug for SelectNextState {
  919    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  920        f.debug_struct(std::any::type_name::<Self>())
  921            .field("wordwise", &self.wordwise)
  922            .field("done", &self.done)
  923            .finish()
  924    }
  925}
  926
  927#[derive(Debug)]
  928struct AutocloseRegion {
  929    selection_id: usize,
  930    range: Range<Anchor>,
  931    pair: BracketPair,
  932}
  933
  934#[derive(Debug)]
  935struct SnippetState {
  936    ranges: Vec<Vec<Range<Anchor>>>,
  937    active_index: usize,
  938    choices: Vec<Option<Vec<String>>>,
  939}
  940
  941#[doc(hidden)]
  942pub struct RenameState {
  943    pub range: Range<Anchor>,
  944    pub old_name: Arc<str>,
  945    pub editor: View<Editor>,
  946    block_id: CustomBlockId,
  947}
  948
  949struct InvalidationStack<T>(Vec<T>);
  950
  951struct RegisteredInlineCompletionProvider {
  952    provider: Arc<dyn InlineCompletionProviderHandle>,
  953    _subscription: Subscription,
  954}
  955
  956#[derive(Debug)]
  957struct ActiveDiagnosticGroup {
  958    primary_range: Range<Anchor>,
  959    primary_message: String,
  960    group_id: usize,
  961    blocks: HashMap<CustomBlockId, Diagnostic>,
  962    is_valid: bool,
  963}
  964
  965#[derive(Serialize, Deserialize, Clone, Debug)]
  966pub struct ClipboardSelection {
  967    pub len: usize,
  968    pub is_entire_line: bool,
  969    pub first_line_indent: u32,
  970}
  971
  972#[derive(Debug)]
  973pub(crate) struct NavigationData {
  974    cursor_anchor: Anchor,
  975    cursor_position: Point,
  976    scroll_anchor: ScrollAnchor,
  977    scroll_top_row: u32,
  978}
  979
  980#[derive(Debug, Clone, Copy, PartialEq, Eq)]
  981pub enum GotoDefinitionKind {
  982    Symbol,
  983    Declaration,
  984    Type,
  985    Implementation,
  986}
  987
  988#[derive(Debug, Clone)]
  989enum InlayHintRefreshReason {
  990    Toggle(bool),
  991    SettingsChange(InlayHintSettings),
  992    NewLinesShown,
  993    BufferEdited(HashSet<Arc<Language>>),
  994    RefreshRequested,
  995    ExcerptsRemoved(Vec<ExcerptId>),
  996}
  997
  998impl InlayHintRefreshReason {
  999    fn description(&self) -> &'static str {
 1000        match self {
 1001            Self::Toggle(_) => "toggle",
 1002            Self::SettingsChange(_) => "settings change",
 1003            Self::NewLinesShown => "new lines shown",
 1004            Self::BufferEdited(_) => "buffer edited",
 1005            Self::RefreshRequested => "refresh requested",
 1006            Self::ExcerptsRemoved(_) => "excerpts removed",
 1007        }
 1008    }
 1009}
 1010
 1011pub enum FormatTarget {
 1012    Buffers,
 1013    Ranges(Vec<Range<MultiBufferPoint>>),
 1014}
 1015
 1016pub(crate) struct FocusedBlock {
 1017    id: BlockId,
 1018    focus_handle: WeakFocusHandle,
 1019}
 1020
 1021#[derive(Clone)]
 1022enum JumpData {
 1023    MultiBufferRow {
 1024        row: MultiBufferRow,
 1025        line_offset_from_top: u32,
 1026    },
 1027    MultiBufferPoint {
 1028        excerpt_id: ExcerptId,
 1029        position: Point,
 1030        anchor: text::Anchor,
 1031        line_offset_from_top: u32,
 1032    },
 1033}
 1034
 1035impl Editor {
 1036    pub fn single_line(cx: &mut ViewContext<Self>) -> Self {
 1037        let buffer = cx.new_model(|cx| Buffer::local("", cx));
 1038        let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
 1039        Self::new(
 1040            EditorMode::SingleLine { auto_width: false },
 1041            buffer,
 1042            None,
 1043            false,
 1044            cx,
 1045        )
 1046    }
 1047
 1048    pub fn multi_line(cx: &mut ViewContext<Self>) -> Self {
 1049        let buffer = cx.new_model(|cx| Buffer::local("", cx));
 1050        let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
 1051        Self::new(EditorMode::Full, buffer, None, false, cx)
 1052    }
 1053
 1054    pub fn auto_width(cx: &mut ViewContext<Self>) -> Self {
 1055        let buffer = cx.new_model(|cx| Buffer::local("", cx));
 1056        let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
 1057        Self::new(
 1058            EditorMode::SingleLine { auto_width: true },
 1059            buffer,
 1060            None,
 1061            false,
 1062            cx,
 1063        )
 1064    }
 1065
 1066    pub fn auto_height(max_lines: usize, cx: &mut ViewContext<Self>) -> Self {
 1067        let buffer = cx.new_model(|cx| Buffer::local("", cx));
 1068        let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
 1069        Self::new(
 1070            EditorMode::AutoHeight { max_lines },
 1071            buffer,
 1072            None,
 1073            false,
 1074            cx,
 1075        )
 1076    }
 1077
 1078    pub fn for_buffer(
 1079        buffer: Model<Buffer>,
 1080        project: Option<Model<Project>>,
 1081        cx: &mut ViewContext<Self>,
 1082    ) -> Self {
 1083        let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
 1084        Self::new(EditorMode::Full, buffer, project, false, cx)
 1085    }
 1086
 1087    pub fn for_multibuffer(
 1088        buffer: Model<MultiBuffer>,
 1089        project: Option<Model<Project>>,
 1090        show_excerpt_controls: bool,
 1091        cx: &mut ViewContext<Self>,
 1092    ) -> Self {
 1093        Self::new(EditorMode::Full, buffer, project, show_excerpt_controls, cx)
 1094    }
 1095
 1096    pub fn clone(&self, cx: &mut ViewContext<Self>) -> Self {
 1097        let show_excerpt_controls = self.display_map.read(cx).show_excerpt_controls();
 1098        let mut clone = Self::new(
 1099            self.mode,
 1100            self.buffer.clone(),
 1101            self.project.clone(),
 1102            show_excerpt_controls,
 1103            cx,
 1104        );
 1105        self.display_map.update(cx, |display_map, cx| {
 1106            let snapshot = display_map.snapshot(cx);
 1107            clone.display_map.update(cx, |display_map, cx| {
 1108                display_map.set_state(&snapshot, cx);
 1109            });
 1110        });
 1111        clone.selections.clone_state(&self.selections);
 1112        clone.scroll_manager.clone_state(&self.scroll_manager);
 1113        clone.searchable = self.searchable;
 1114        clone
 1115    }
 1116
 1117    pub fn new(
 1118        mode: EditorMode,
 1119        buffer: Model<MultiBuffer>,
 1120        project: Option<Model<Project>>,
 1121        show_excerpt_controls: bool,
 1122        cx: &mut ViewContext<Self>,
 1123    ) -> Self {
 1124        let style = cx.text_style();
 1125        let font_size = style.font_size.to_pixels(cx.rem_size());
 1126        let editor = cx.view().downgrade();
 1127        let fold_placeholder = FoldPlaceholder {
 1128            constrain_width: true,
 1129            render: Arc::new(move |fold_id, fold_range, cx| {
 1130                let editor = editor.clone();
 1131                div()
 1132                    .id(fold_id)
 1133                    .bg(cx.theme().colors().ghost_element_background)
 1134                    .hover(|style| style.bg(cx.theme().colors().ghost_element_hover))
 1135                    .active(|style| style.bg(cx.theme().colors().ghost_element_active))
 1136                    .rounded_sm()
 1137                    .size_full()
 1138                    .cursor_pointer()
 1139                    .child("")
 1140                    .on_mouse_down(MouseButton::Left, |_, cx| cx.stop_propagation())
 1141                    .on_click(move |_, cx| {
 1142                        editor
 1143                            .update(cx, |editor, cx| {
 1144                                editor.unfold_ranges(
 1145                                    &[fold_range.start..fold_range.end],
 1146                                    true,
 1147                                    false,
 1148                                    cx,
 1149                                );
 1150                                cx.stop_propagation();
 1151                            })
 1152                            .ok();
 1153                    })
 1154                    .into_any()
 1155            }),
 1156            merge_adjacent: true,
 1157            ..Default::default()
 1158        };
 1159        let display_map = cx.new_model(|cx| {
 1160            DisplayMap::new(
 1161                buffer.clone(),
 1162                style.font(),
 1163                font_size,
 1164                None,
 1165                show_excerpt_controls,
 1166                FILE_HEADER_HEIGHT,
 1167                MULTI_BUFFER_EXCERPT_HEADER_HEIGHT,
 1168                MULTI_BUFFER_EXCERPT_FOOTER_HEIGHT,
 1169                fold_placeholder,
 1170                cx,
 1171            )
 1172        });
 1173
 1174        let selections = SelectionsCollection::new(display_map.clone(), buffer.clone());
 1175
 1176        let blink_manager = cx.new_model(|cx| BlinkManager::new(CURSOR_BLINK_INTERVAL, cx));
 1177
 1178        let soft_wrap_mode_override = matches!(mode, EditorMode::SingleLine { .. })
 1179            .then(|| language_settings::SoftWrap::None);
 1180
 1181        let mut project_subscriptions = Vec::new();
 1182        if mode == EditorMode::Full {
 1183            if let Some(project) = project.as_ref() {
 1184                if buffer.read(cx).is_singleton() {
 1185                    project_subscriptions.push(cx.observe(project, |_, _, cx| {
 1186                        cx.emit(EditorEvent::TitleChanged);
 1187                    }));
 1188                }
 1189                project_subscriptions.push(cx.subscribe(project, |editor, _, event, cx| {
 1190                    if let project::Event::RefreshInlayHints = event {
 1191                        editor.refresh_inlay_hints(InlayHintRefreshReason::RefreshRequested, cx);
 1192                    } else if let project::Event::SnippetEdit(id, snippet_edits) = event {
 1193                        if let Some(buffer) = editor.buffer.read(cx).buffer(*id) {
 1194                            let focus_handle = editor.focus_handle(cx);
 1195                            if focus_handle.is_focused(cx) {
 1196                                let snapshot = buffer.read(cx).snapshot();
 1197                                for (range, snippet) in snippet_edits {
 1198                                    let editor_range =
 1199                                        language::range_from_lsp(*range).to_offset(&snapshot);
 1200                                    editor
 1201                                        .insert_snippet(&[editor_range], snippet.clone(), cx)
 1202                                        .ok();
 1203                                }
 1204                            }
 1205                        }
 1206                    }
 1207                }));
 1208                if let Some(task_inventory) = project
 1209                    .read(cx)
 1210                    .task_store()
 1211                    .read(cx)
 1212                    .task_inventory()
 1213                    .cloned()
 1214                {
 1215                    project_subscriptions.push(cx.observe(&task_inventory, |editor, _, cx| {
 1216                        editor.tasks_update_task = Some(editor.refresh_runnables(cx));
 1217                    }));
 1218                }
 1219            }
 1220        }
 1221
 1222        let buffer_snapshot = buffer.read(cx).snapshot(cx);
 1223
 1224        let inlay_hint_settings =
 1225            inlay_hint_settings(selections.newest_anchor().head(), &buffer_snapshot, cx);
 1226        let focus_handle = cx.focus_handle();
 1227        cx.on_focus(&focus_handle, Self::handle_focus).detach();
 1228        cx.on_focus_in(&focus_handle, Self::handle_focus_in)
 1229            .detach();
 1230        cx.on_focus_out(&focus_handle, Self::handle_focus_out)
 1231            .detach();
 1232        cx.on_blur(&focus_handle, Self::handle_blur).detach();
 1233
 1234        let show_indent_guides = if matches!(mode, EditorMode::SingleLine { .. }) {
 1235            Some(false)
 1236        } else {
 1237            None
 1238        };
 1239
 1240        let mut code_action_providers = Vec::new();
 1241        if let Some(project) = project.clone() {
 1242            get_unstaged_changes_for_buffers(&project, buffer.read(cx).all_buffers(), cx);
 1243            code_action_providers.push(Rc::new(project) as Rc<_>);
 1244        }
 1245
 1246        let mut this = Self {
 1247            focus_handle,
 1248            show_cursor_when_unfocused: false,
 1249            last_focused_descendant: None,
 1250            buffer: buffer.clone(),
 1251            display_map: display_map.clone(),
 1252            selections,
 1253            scroll_manager: ScrollManager::new(cx),
 1254            columnar_selection_tail: None,
 1255            add_selections_state: None,
 1256            select_next_state: None,
 1257            select_prev_state: None,
 1258            selection_history: Default::default(),
 1259            autoclose_regions: Default::default(),
 1260            snippet_stack: Default::default(),
 1261            select_larger_syntax_node_stack: Vec::new(),
 1262            ime_transaction: Default::default(),
 1263            active_diagnostics: None,
 1264            soft_wrap_mode_override,
 1265            completion_provider: project.clone().map(|project| Box::new(project) as _),
 1266            semantics_provider: project.clone().map(|project| Rc::new(project) as _),
 1267            collaboration_hub: project.clone().map(|project| Box::new(project) as _),
 1268            project,
 1269            blink_manager: blink_manager.clone(),
 1270            show_local_selections: true,
 1271            show_scrollbars: true,
 1272            mode,
 1273            show_breadcrumbs: EditorSettings::get_global(cx).toolbar.breadcrumbs,
 1274            show_gutter: mode == EditorMode::Full,
 1275            show_line_numbers: None,
 1276            use_relative_line_numbers: None,
 1277            show_git_diff_gutter: None,
 1278            show_code_actions: None,
 1279            show_runnables: None,
 1280            show_wrap_guides: None,
 1281            show_indent_guides,
 1282            placeholder_text: None,
 1283            highlight_order: 0,
 1284            highlighted_rows: HashMap::default(),
 1285            background_highlights: Default::default(),
 1286            gutter_highlights: TreeMap::default(),
 1287            scrollbar_marker_state: ScrollbarMarkerState::default(),
 1288            active_indent_guides_state: ActiveIndentGuidesState::default(),
 1289            nav_history: None,
 1290            context_menu: RefCell::new(None),
 1291            mouse_context_menu: None,
 1292            hunk_controls_menu_handle: PopoverMenuHandle::default(),
 1293            completion_tasks: Default::default(),
 1294            signature_help_state: SignatureHelpState::default(),
 1295            auto_signature_help: None,
 1296            find_all_references_task_sources: Vec::new(),
 1297            next_completion_id: 0,
 1298            next_inlay_id: 0,
 1299            code_action_providers,
 1300            available_code_actions: Default::default(),
 1301            code_actions_task: Default::default(),
 1302            document_highlights_task: Default::default(),
 1303            linked_editing_range_task: Default::default(),
 1304            pending_rename: Default::default(),
 1305            searchable: true,
 1306            cursor_shape: EditorSettings::get_global(cx)
 1307                .cursor_shape
 1308                .unwrap_or_default(),
 1309            current_line_highlight: None,
 1310            autoindent_mode: Some(AutoindentMode::EachLine),
 1311            collapse_matches: false,
 1312            workspace: None,
 1313            input_enabled: true,
 1314            use_modal_editing: mode == EditorMode::Full,
 1315            read_only: false,
 1316            use_autoclose: true,
 1317            use_auto_surround: true,
 1318            auto_replace_emoji_shortcode: false,
 1319            leader_peer_id: None,
 1320            remote_id: None,
 1321            hover_state: Default::default(),
 1322            hovered_link_state: Default::default(),
 1323            inline_completion_provider: None,
 1324            active_inline_completion: None,
 1325            inlay_hint_cache: InlayHintCache::new(inlay_hint_settings),
 1326            diff_map: DiffMap::default(),
 1327            gutter_hovered: false,
 1328            pixel_position_of_newest_cursor: None,
 1329            last_bounds: None,
 1330            expect_bounds_change: None,
 1331            gutter_dimensions: GutterDimensions::default(),
 1332            style: None,
 1333            show_cursor_names: false,
 1334            hovered_cursors: Default::default(),
 1335            next_editor_action_id: EditorActionId::default(),
 1336            editor_actions: Rc::default(),
 1337            show_inline_completions_override: None,
 1338            enable_inline_completions: true,
 1339            custom_context_menu: None,
 1340            show_git_blame_gutter: false,
 1341            show_git_blame_inline: false,
 1342            show_selection_menu: None,
 1343            show_git_blame_inline_delay_task: None,
 1344            git_blame_inline_enabled: ProjectSettings::get_global(cx).git.inline_blame_enabled(),
 1345            serialize_dirty_buffers: ProjectSettings::get_global(cx)
 1346                .session
 1347                .restore_unsaved_buffers,
 1348            blame: None,
 1349            blame_subscription: None,
 1350            tasks: Default::default(),
 1351            _subscriptions: vec![
 1352                cx.observe(&buffer, Self::on_buffer_changed),
 1353                cx.subscribe(&buffer, Self::on_buffer_event),
 1354                cx.observe(&display_map, Self::on_display_map_changed),
 1355                cx.observe(&blink_manager, |_, _, cx| cx.notify()),
 1356                cx.observe_global::<SettingsStore>(Self::settings_changed),
 1357                cx.observe_window_activation(|editor, cx| {
 1358                    let active = cx.is_window_active();
 1359                    editor.blink_manager.update(cx, |blink_manager, cx| {
 1360                        if active {
 1361                            blink_manager.enable(cx);
 1362                        } else {
 1363                            blink_manager.disable(cx);
 1364                        }
 1365                    });
 1366                }),
 1367            ],
 1368            tasks_update_task: None,
 1369            linked_edit_ranges: Default::default(),
 1370            previous_search_ranges: None,
 1371            breadcrumb_header: None,
 1372            focused_block: None,
 1373            next_scroll_position: NextScrollCursorCenterTopBottom::default(),
 1374            addons: HashMap::default(),
 1375            registered_buffers: HashMap::default(),
 1376            _scroll_cursor_center_top_bottom_task: Task::ready(()),
 1377            selection_mark_mode: false,
 1378            toggle_fold_multiple_buffers: Task::ready(()),
 1379            text_style_refinement: None,
 1380        };
 1381        this.tasks_update_task = Some(this.refresh_runnables(cx));
 1382        this._subscriptions.extend(project_subscriptions);
 1383
 1384        this.end_selection(cx);
 1385        this.scroll_manager.show_scrollbar(cx);
 1386
 1387        if mode == EditorMode::Full {
 1388            let should_auto_hide_scrollbars = cx.should_auto_hide_scrollbars();
 1389            cx.set_global(ScrollbarAutoHide(should_auto_hide_scrollbars));
 1390
 1391            if this.git_blame_inline_enabled {
 1392                this.git_blame_inline_enabled = true;
 1393                this.start_git_blame_inline(false, cx);
 1394            }
 1395
 1396            if let Some(buffer) = buffer.read(cx).as_singleton() {
 1397                if let Some(project) = this.project.as_ref() {
 1398                    let lsp_store = project.read(cx).lsp_store();
 1399                    let handle = lsp_store.update(cx, |lsp_store, cx| {
 1400                        lsp_store.register_buffer_with_language_servers(&buffer, cx)
 1401                    });
 1402                    this.registered_buffers
 1403                        .insert(buffer.read(cx).remote_id(), handle);
 1404                }
 1405            }
 1406        }
 1407
 1408        this.report_editor_event("Editor Opened", None, cx);
 1409        this
 1410    }
 1411
 1412    pub fn mouse_menu_is_focused(&self, cx: &WindowContext) -> bool {
 1413        self.mouse_context_menu
 1414            .as_ref()
 1415            .is_some_and(|menu| menu.context_menu.focus_handle(cx).is_focused(cx))
 1416    }
 1417
 1418    fn key_context(&self, cx: &ViewContext<Self>) -> KeyContext {
 1419        let mut key_context = KeyContext::new_with_defaults();
 1420        key_context.add("Editor");
 1421        let mode = match self.mode {
 1422            EditorMode::SingleLine { .. } => "single_line",
 1423            EditorMode::AutoHeight { .. } => "auto_height",
 1424            EditorMode::Full => "full",
 1425        };
 1426
 1427        if EditorSettings::jupyter_enabled(cx) {
 1428            key_context.add("jupyter");
 1429        }
 1430
 1431        key_context.set("mode", mode);
 1432        if self.pending_rename.is_some() {
 1433            key_context.add("renaming");
 1434        }
 1435        match self.context_menu.borrow().as_ref() {
 1436            Some(CodeContextMenu::Completions(_)) => {
 1437                key_context.add("menu");
 1438                key_context.add("showing_completions")
 1439            }
 1440            Some(CodeContextMenu::CodeActions(_)) => {
 1441                key_context.add("menu");
 1442                key_context.add("showing_code_actions")
 1443            }
 1444            None => {}
 1445        }
 1446
 1447        // Disable vim contexts when a sub-editor (e.g. rename/inline assistant) is focused.
 1448        if !self.focus_handle(cx).contains_focused(cx)
 1449            || (self.is_focused(cx) || self.mouse_menu_is_focused(cx))
 1450        {
 1451            for addon in self.addons.values() {
 1452                addon.extend_key_context(&mut key_context, cx)
 1453            }
 1454        }
 1455
 1456        if let Some(extension) = self
 1457            .buffer
 1458            .read(cx)
 1459            .as_singleton()
 1460            .and_then(|buffer| buffer.read(cx).file()?.path().extension()?.to_str())
 1461        {
 1462            key_context.set("extension", extension.to_string());
 1463        }
 1464
 1465        if self.has_active_inline_completion() {
 1466            key_context.add("copilot_suggestion");
 1467            key_context.add("inline_completion");
 1468        }
 1469
 1470        if self.selection_mark_mode {
 1471            key_context.add("selection_mode");
 1472        }
 1473
 1474        key_context
 1475    }
 1476
 1477    pub fn new_file(
 1478        workspace: &mut Workspace,
 1479        _: &workspace::NewFile,
 1480        cx: &mut ViewContext<Workspace>,
 1481    ) {
 1482        Self::new_in_workspace(workspace, cx).detach_and_prompt_err(
 1483            "Failed to create buffer",
 1484            cx,
 1485            |e, _| match e.error_code() {
 1486                ErrorCode::RemoteUpgradeRequired => Some(format!(
 1487                "The remote instance of Zed does not support this yet. It must be upgraded to {}",
 1488                e.error_tag("required").unwrap_or("the latest version")
 1489            )),
 1490                _ => None,
 1491            },
 1492        );
 1493    }
 1494
 1495    pub fn new_in_workspace(
 1496        workspace: &mut Workspace,
 1497        cx: &mut ViewContext<Workspace>,
 1498    ) -> Task<Result<View<Editor>>> {
 1499        let project = workspace.project().clone();
 1500        let create = project.update(cx, |project, cx| project.create_buffer(cx));
 1501
 1502        cx.spawn(|workspace, mut cx| async move {
 1503            let buffer = create.await?;
 1504            workspace.update(&mut cx, |workspace, cx| {
 1505                let editor =
 1506                    cx.new_view(|cx| Editor::for_buffer(buffer, Some(project.clone()), cx));
 1507                workspace.add_item_to_active_pane(Box::new(editor.clone()), None, true, cx);
 1508                editor
 1509            })
 1510        })
 1511    }
 1512
 1513    fn new_file_vertical(
 1514        workspace: &mut Workspace,
 1515        _: &workspace::NewFileSplitVertical,
 1516        cx: &mut ViewContext<Workspace>,
 1517    ) {
 1518        Self::new_file_in_direction(workspace, SplitDirection::vertical(cx), cx)
 1519    }
 1520
 1521    fn new_file_horizontal(
 1522        workspace: &mut Workspace,
 1523        _: &workspace::NewFileSplitHorizontal,
 1524        cx: &mut ViewContext<Workspace>,
 1525    ) {
 1526        Self::new_file_in_direction(workspace, SplitDirection::horizontal(cx), cx)
 1527    }
 1528
 1529    fn new_file_in_direction(
 1530        workspace: &mut Workspace,
 1531        direction: SplitDirection,
 1532        cx: &mut ViewContext<Workspace>,
 1533    ) {
 1534        let project = workspace.project().clone();
 1535        let create = project.update(cx, |project, cx| project.create_buffer(cx));
 1536
 1537        cx.spawn(|workspace, mut cx| async move {
 1538            let buffer = create.await?;
 1539            workspace.update(&mut cx, move |workspace, cx| {
 1540                workspace.split_item(
 1541                    direction,
 1542                    Box::new(
 1543                        cx.new_view(|cx| Editor::for_buffer(buffer, Some(project.clone()), cx)),
 1544                    ),
 1545                    cx,
 1546                )
 1547            })?;
 1548            anyhow::Ok(())
 1549        })
 1550        .detach_and_prompt_err("Failed to create buffer", cx, |e, _| match e.error_code() {
 1551            ErrorCode::RemoteUpgradeRequired => Some(format!(
 1552                "The remote instance of Zed does not support this yet. It must be upgraded to {}",
 1553                e.error_tag("required").unwrap_or("the latest version")
 1554            )),
 1555            _ => None,
 1556        });
 1557    }
 1558
 1559    pub fn leader_peer_id(&self) -> Option<PeerId> {
 1560        self.leader_peer_id
 1561    }
 1562
 1563    pub fn buffer(&self) -> &Model<MultiBuffer> {
 1564        &self.buffer
 1565    }
 1566
 1567    pub fn workspace(&self) -> Option<View<Workspace>> {
 1568        self.workspace.as_ref()?.0.upgrade()
 1569    }
 1570
 1571    pub fn title<'a>(&self, cx: &'a AppContext) -> Cow<'a, str> {
 1572        self.buffer().read(cx).title(cx)
 1573    }
 1574
 1575    pub fn snapshot(&mut self, cx: &mut WindowContext) -> EditorSnapshot {
 1576        let git_blame_gutter_max_author_length = self
 1577            .render_git_blame_gutter(cx)
 1578            .then(|| {
 1579                if let Some(blame) = self.blame.as_ref() {
 1580                    let max_author_length =
 1581                        blame.update(cx, |blame, cx| blame.max_author_length(cx));
 1582                    Some(max_author_length)
 1583                } else {
 1584                    None
 1585                }
 1586            })
 1587            .flatten();
 1588
 1589        EditorSnapshot {
 1590            mode: self.mode,
 1591            show_gutter: self.show_gutter,
 1592            show_line_numbers: self.show_line_numbers,
 1593            show_git_diff_gutter: self.show_git_diff_gutter,
 1594            show_code_actions: self.show_code_actions,
 1595            show_runnables: self.show_runnables,
 1596            git_blame_gutter_max_author_length,
 1597            display_snapshot: self.display_map.update(cx, |map, cx| map.snapshot(cx)),
 1598            scroll_anchor: self.scroll_manager.anchor(),
 1599            ongoing_scroll: self.scroll_manager.ongoing_scroll(),
 1600            placeholder_text: self.placeholder_text.clone(),
 1601            diff_map: self.diff_map.snapshot(),
 1602            is_focused: self.focus_handle.is_focused(cx),
 1603            current_line_highlight: self
 1604                .current_line_highlight
 1605                .unwrap_or_else(|| EditorSettings::get_global(cx).current_line_highlight),
 1606            gutter_hovered: self.gutter_hovered,
 1607        }
 1608    }
 1609
 1610    pub fn language_at<T: ToOffset>(&self, point: T, cx: &AppContext) -> Option<Arc<Language>> {
 1611        self.buffer.read(cx).language_at(point, cx)
 1612    }
 1613
 1614    pub fn file_at<T: ToOffset>(
 1615        &self,
 1616        point: T,
 1617        cx: &AppContext,
 1618    ) -> Option<Arc<dyn language::File>> {
 1619        self.buffer.read(cx).read(cx).file_at(point).cloned()
 1620    }
 1621
 1622    pub fn active_excerpt(
 1623        &self,
 1624        cx: &AppContext,
 1625    ) -> Option<(ExcerptId, Model<Buffer>, Range<text::Anchor>)> {
 1626        self.buffer
 1627            .read(cx)
 1628            .excerpt_containing(self.selections.newest_anchor().head(), cx)
 1629    }
 1630
 1631    pub fn mode(&self) -> EditorMode {
 1632        self.mode
 1633    }
 1634
 1635    pub fn collaboration_hub(&self) -> Option<&dyn CollaborationHub> {
 1636        self.collaboration_hub.as_deref()
 1637    }
 1638
 1639    pub fn set_collaboration_hub(&mut self, hub: Box<dyn CollaborationHub>) {
 1640        self.collaboration_hub = Some(hub);
 1641    }
 1642
 1643    pub fn set_custom_context_menu(
 1644        &mut self,
 1645        f: impl 'static
 1646            + Fn(&mut Self, DisplayPoint, &mut ViewContext<Self>) -> Option<View<ui::ContextMenu>>,
 1647    ) {
 1648        self.custom_context_menu = Some(Box::new(f))
 1649    }
 1650
 1651    pub fn set_completion_provider(&mut self, provider: Option<Box<dyn CompletionProvider>>) {
 1652        self.completion_provider = provider;
 1653    }
 1654
 1655    pub fn semantics_provider(&self) -> Option<Rc<dyn SemanticsProvider>> {
 1656        self.semantics_provider.clone()
 1657    }
 1658
 1659    pub fn set_semantics_provider(&mut self, provider: Option<Rc<dyn SemanticsProvider>>) {
 1660        self.semantics_provider = provider;
 1661    }
 1662
 1663    pub fn set_inline_completion_provider<T>(
 1664        &mut self,
 1665        provider: Option<Model<T>>,
 1666        cx: &mut ViewContext<Self>,
 1667    ) where
 1668        T: InlineCompletionProvider,
 1669    {
 1670        self.inline_completion_provider =
 1671            provider.map(|provider| RegisteredInlineCompletionProvider {
 1672                _subscription: cx.observe(&provider, |this, _, cx| {
 1673                    if this.focus_handle.is_focused(cx) {
 1674                        this.update_visible_inline_completion(cx);
 1675                    }
 1676                }),
 1677                provider: Arc::new(provider),
 1678            });
 1679        self.refresh_inline_completion(false, false, cx);
 1680    }
 1681
 1682    pub fn placeholder_text(&self, _cx: &WindowContext) -> Option<&str> {
 1683        self.placeholder_text.as_deref()
 1684    }
 1685
 1686    pub fn set_placeholder_text(
 1687        &mut self,
 1688        placeholder_text: impl Into<Arc<str>>,
 1689        cx: &mut ViewContext<Self>,
 1690    ) {
 1691        let placeholder_text = Some(placeholder_text.into());
 1692        if self.placeholder_text != placeholder_text {
 1693            self.placeholder_text = placeholder_text;
 1694            cx.notify();
 1695        }
 1696    }
 1697
 1698    pub fn set_cursor_shape(&mut self, cursor_shape: CursorShape, cx: &mut ViewContext<Self>) {
 1699        self.cursor_shape = cursor_shape;
 1700
 1701        // Disrupt blink for immediate user feedback that the cursor shape has changed
 1702        self.blink_manager.update(cx, BlinkManager::show_cursor);
 1703
 1704        cx.notify();
 1705    }
 1706
 1707    pub fn set_current_line_highlight(
 1708        &mut self,
 1709        current_line_highlight: Option<CurrentLineHighlight>,
 1710    ) {
 1711        self.current_line_highlight = current_line_highlight;
 1712    }
 1713
 1714    pub fn set_collapse_matches(&mut self, collapse_matches: bool) {
 1715        self.collapse_matches = collapse_matches;
 1716    }
 1717
 1718    pub fn register_buffers_with_language_servers(&mut self, cx: &mut ViewContext<Self>) {
 1719        let buffers = self.buffer.read(cx).all_buffers();
 1720        let Some(lsp_store) = self.lsp_store(cx) else {
 1721            return;
 1722        };
 1723        lsp_store.update(cx, |lsp_store, cx| {
 1724            for buffer in buffers {
 1725                self.registered_buffers
 1726                    .entry(buffer.read(cx).remote_id())
 1727                    .or_insert_with(|| {
 1728                        lsp_store.register_buffer_with_language_servers(&buffer, cx)
 1729                    });
 1730            }
 1731        })
 1732    }
 1733
 1734    pub fn range_for_match<T: std::marker::Copy>(&self, range: &Range<T>) -> Range<T> {
 1735        if self.collapse_matches {
 1736            return range.start..range.start;
 1737        }
 1738        range.clone()
 1739    }
 1740
 1741    pub fn set_clip_at_line_ends(&mut self, clip: bool, cx: &mut ViewContext<Self>) {
 1742        if self.display_map.read(cx).clip_at_line_ends != clip {
 1743            self.display_map
 1744                .update(cx, |map, _| map.clip_at_line_ends = clip);
 1745        }
 1746    }
 1747
 1748    pub fn set_input_enabled(&mut self, input_enabled: bool) {
 1749        self.input_enabled = input_enabled;
 1750    }
 1751
 1752    pub fn set_inline_completions_enabled(&mut self, enabled: bool, cx: &mut ViewContext<Self>) {
 1753        self.enable_inline_completions = enabled;
 1754        if !self.enable_inline_completions {
 1755            self.take_active_inline_completion(cx);
 1756            cx.notify();
 1757        }
 1758    }
 1759
 1760    pub fn set_autoindent(&mut self, autoindent: bool) {
 1761        if autoindent {
 1762            self.autoindent_mode = Some(AutoindentMode::EachLine);
 1763        } else {
 1764            self.autoindent_mode = None;
 1765        }
 1766    }
 1767
 1768    pub fn read_only(&self, cx: &AppContext) -> bool {
 1769        self.read_only || self.buffer.read(cx).read_only()
 1770    }
 1771
 1772    pub fn set_read_only(&mut self, read_only: bool) {
 1773        self.read_only = read_only;
 1774    }
 1775
 1776    pub fn set_use_autoclose(&mut self, autoclose: bool) {
 1777        self.use_autoclose = autoclose;
 1778    }
 1779
 1780    pub fn set_use_auto_surround(&mut self, auto_surround: bool) {
 1781        self.use_auto_surround = auto_surround;
 1782    }
 1783
 1784    pub fn set_auto_replace_emoji_shortcode(&mut self, auto_replace: bool) {
 1785        self.auto_replace_emoji_shortcode = auto_replace;
 1786    }
 1787
 1788    pub fn toggle_inline_completions(
 1789        &mut self,
 1790        _: &ToggleInlineCompletions,
 1791        cx: &mut ViewContext<Self>,
 1792    ) {
 1793        if self.show_inline_completions_override.is_some() {
 1794            self.set_show_inline_completions(None, cx);
 1795        } else {
 1796            let cursor = self.selections.newest_anchor().head();
 1797            if let Some((buffer, cursor_buffer_position)) =
 1798                self.buffer.read(cx).text_anchor_for_position(cursor, cx)
 1799            {
 1800                let show_inline_completions =
 1801                    !self.should_show_inline_completions(&buffer, cursor_buffer_position, cx);
 1802                self.set_show_inline_completions(Some(show_inline_completions), cx);
 1803            }
 1804        }
 1805    }
 1806
 1807    pub fn set_show_inline_completions(
 1808        &mut self,
 1809        show_inline_completions: Option<bool>,
 1810        cx: &mut ViewContext<Self>,
 1811    ) {
 1812        self.show_inline_completions_override = show_inline_completions;
 1813        self.refresh_inline_completion(false, true, cx);
 1814    }
 1815
 1816    pub fn inline_completions_enabled(&self, cx: &AppContext) -> bool {
 1817        let cursor = self.selections.newest_anchor().head();
 1818        if let Some((buffer, buffer_position)) =
 1819            self.buffer.read(cx).text_anchor_for_position(cursor, cx)
 1820        {
 1821            self.should_show_inline_completions(&buffer, buffer_position, cx)
 1822        } else {
 1823            false
 1824        }
 1825    }
 1826
 1827    fn should_show_inline_completions(
 1828        &self,
 1829        buffer: &Model<Buffer>,
 1830        buffer_position: language::Anchor,
 1831        cx: &AppContext,
 1832    ) -> bool {
 1833        if !self.snippet_stack.is_empty() {
 1834            return false;
 1835        }
 1836
 1837        if self.inline_completions_disabled_in_scope(buffer, buffer_position, cx) {
 1838            return false;
 1839        }
 1840
 1841        if let Some(provider) = self.inline_completion_provider() {
 1842            if let Some(show_inline_completions) = self.show_inline_completions_override {
 1843                show_inline_completions
 1844            } else {
 1845                self.mode == EditorMode::Full && provider.is_enabled(buffer, buffer_position, cx)
 1846            }
 1847        } else {
 1848            false
 1849        }
 1850    }
 1851
 1852    fn inline_completions_disabled_in_scope(
 1853        &self,
 1854        buffer: &Model<Buffer>,
 1855        buffer_position: language::Anchor,
 1856        cx: &AppContext,
 1857    ) -> bool {
 1858        let snapshot = buffer.read(cx).snapshot();
 1859        let settings = snapshot.settings_at(buffer_position, cx);
 1860
 1861        let Some(scope) = snapshot.language_scope_at(buffer_position) else {
 1862            return false;
 1863        };
 1864
 1865        scope.override_name().map_or(false, |scope_name| {
 1866            settings
 1867                .inline_completions_disabled_in
 1868                .iter()
 1869                .any(|s| s == scope_name)
 1870        })
 1871    }
 1872
 1873    pub fn set_use_modal_editing(&mut self, to: bool) {
 1874        self.use_modal_editing = to;
 1875    }
 1876
 1877    pub fn use_modal_editing(&self) -> bool {
 1878        self.use_modal_editing
 1879    }
 1880
 1881    fn selections_did_change(
 1882        &mut self,
 1883        local: bool,
 1884        old_cursor_position: &Anchor,
 1885        show_completions: bool,
 1886        cx: &mut ViewContext<Self>,
 1887    ) {
 1888        cx.invalidate_character_coordinates();
 1889
 1890        // Copy selections to primary selection buffer
 1891        #[cfg(any(target_os = "linux", target_os = "freebsd"))]
 1892        if local {
 1893            let selections = self.selections.all::<usize>(cx);
 1894            let buffer_handle = self.buffer.read(cx).read(cx);
 1895
 1896            let mut text = String::new();
 1897            for (index, selection) in selections.iter().enumerate() {
 1898                let text_for_selection = buffer_handle
 1899                    .text_for_range(selection.start..selection.end)
 1900                    .collect::<String>();
 1901
 1902                text.push_str(&text_for_selection);
 1903                if index != selections.len() - 1 {
 1904                    text.push('\n');
 1905                }
 1906            }
 1907
 1908            if !text.is_empty() {
 1909                cx.write_to_primary(ClipboardItem::new_string(text));
 1910            }
 1911        }
 1912
 1913        if self.focus_handle.is_focused(cx) && self.leader_peer_id.is_none() {
 1914            self.buffer.update(cx, |buffer, cx| {
 1915                buffer.set_active_selections(
 1916                    &self.selections.disjoint_anchors(),
 1917                    self.selections.line_mode,
 1918                    self.cursor_shape,
 1919                    cx,
 1920                )
 1921            });
 1922        }
 1923        let display_map = self
 1924            .display_map
 1925            .update(cx, |display_map, cx| display_map.snapshot(cx));
 1926        let buffer = &display_map.buffer_snapshot;
 1927        self.add_selections_state = None;
 1928        self.select_next_state = None;
 1929        self.select_prev_state = None;
 1930        self.select_larger_syntax_node_stack.clear();
 1931        self.invalidate_autoclose_regions(&self.selections.disjoint_anchors(), buffer);
 1932        self.snippet_stack
 1933            .invalidate(&self.selections.disjoint_anchors(), buffer);
 1934        self.take_rename(false, cx);
 1935
 1936        let new_cursor_position = self.selections.newest_anchor().head();
 1937
 1938        self.push_to_nav_history(
 1939            *old_cursor_position,
 1940            Some(new_cursor_position.to_point(buffer)),
 1941            cx,
 1942        );
 1943
 1944        if local {
 1945            let new_cursor_position = self.selections.newest_anchor().head();
 1946            let mut context_menu = self.context_menu.borrow_mut();
 1947            let completion_menu = match context_menu.as_ref() {
 1948                Some(CodeContextMenu::Completions(menu)) => Some(menu),
 1949                _ => {
 1950                    *context_menu = None;
 1951                    None
 1952                }
 1953            };
 1954
 1955            if let Some(completion_menu) = completion_menu {
 1956                let cursor_position = new_cursor_position.to_offset(buffer);
 1957                let (word_range, kind) =
 1958                    buffer.surrounding_word(completion_menu.initial_position, true);
 1959                if kind == Some(CharKind::Word)
 1960                    && word_range.to_inclusive().contains(&cursor_position)
 1961                {
 1962                    let mut completion_menu = completion_menu.clone();
 1963                    drop(context_menu);
 1964
 1965                    let query = Self::completion_query(buffer, cursor_position);
 1966                    cx.spawn(move |this, mut cx| async move {
 1967                        completion_menu
 1968                            .filter(query.as_deref(), cx.background_executor().clone())
 1969                            .await;
 1970
 1971                        this.update(&mut cx, |this, cx| {
 1972                            let mut context_menu = this.context_menu.borrow_mut();
 1973                            let Some(CodeContextMenu::Completions(menu)) = context_menu.as_ref()
 1974                            else {
 1975                                return;
 1976                            };
 1977
 1978                            if menu.id > completion_menu.id {
 1979                                return;
 1980                            }
 1981
 1982                            *context_menu = Some(CodeContextMenu::Completions(completion_menu));
 1983                            drop(context_menu);
 1984                            cx.notify();
 1985                        })
 1986                    })
 1987                    .detach();
 1988
 1989                    if show_completions {
 1990                        self.show_completions(&ShowCompletions { trigger: None }, cx);
 1991                    }
 1992                } else {
 1993                    drop(context_menu);
 1994                    self.hide_context_menu(cx);
 1995                }
 1996            } else {
 1997                drop(context_menu);
 1998            }
 1999
 2000            hide_hover(self, cx);
 2001
 2002            if old_cursor_position.to_display_point(&display_map).row()
 2003                != new_cursor_position.to_display_point(&display_map).row()
 2004            {
 2005                self.available_code_actions.take();
 2006            }
 2007            self.refresh_code_actions(cx);
 2008            self.refresh_document_highlights(cx);
 2009            refresh_matching_bracket_highlights(self, cx);
 2010            self.update_visible_inline_completion(cx);
 2011            linked_editing_ranges::refresh_linked_ranges(self, cx);
 2012            if self.git_blame_inline_enabled {
 2013                self.start_inline_blame_timer(cx);
 2014            }
 2015        }
 2016
 2017        self.blink_manager.update(cx, BlinkManager::pause_blinking);
 2018        cx.emit(EditorEvent::SelectionsChanged { local });
 2019
 2020        if self.selections.disjoint_anchors().len() == 1 {
 2021            cx.emit(SearchEvent::ActiveMatchChanged)
 2022        }
 2023        cx.notify();
 2024    }
 2025
 2026    pub fn change_selections<R>(
 2027        &mut self,
 2028        autoscroll: Option<Autoscroll>,
 2029        cx: &mut ViewContext<Self>,
 2030        change: impl FnOnce(&mut MutableSelectionsCollection<'_>) -> R,
 2031    ) -> R {
 2032        self.change_selections_inner(autoscroll, true, cx, change)
 2033    }
 2034
 2035    pub fn change_selections_inner<R>(
 2036        &mut self,
 2037        autoscroll: Option<Autoscroll>,
 2038        request_completions: bool,
 2039        cx: &mut ViewContext<Self>,
 2040        change: impl FnOnce(&mut MutableSelectionsCollection<'_>) -> R,
 2041    ) -> R {
 2042        let old_cursor_position = self.selections.newest_anchor().head();
 2043        self.push_to_selection_history();
 2044
 2045        let (changed, result) = self.selections.change_with(cx, change);
 2046
 2047        if changed {
 2048            if let Some(autoscroll) = autoscroll {
 2049                self.request_autoscroll(autoscroll, cx);
 2050            }
 2051            self.selections_did_change(true, &old_cursor_position, request_completions, cx);
 2052
 2053            if self.should_open_signature_help_automatically(
 2054                &old_cursor_position,
 2055                self.signature_help_state.backspace_pressed(),
 2056                cx,
 2057            ) {
 2058                self.show_signature_help(&ShowSignatureHelp, cx);
 2059            }
 2060            self.signature_help_state.set_backspace_pressed(false);
 2061        }
 2062
 2063        result
 2064    }
 2065
 2066    pub fn edit<I, S, T>(&mut self, edits: I, cx: &mut ViewContext<Self>)
 2067    where
 2068        I: IntoIterator<Item = (Range<S>, T)>,
 2069        S: ToOffset,
 2070        T: Into<Arc<str>>,
 2071    {
 2072        if self.read_only(cx) {
 2073            return;
 2074        }
 2075
 2076        self.buffer
 2077            .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
 2078    }
 2079
 2080    pub fn edit_with_autoindent<I, S, T>(&mut self, edits: I, cx: &mut ViewContext<Self>)
 2081    where
 2082        I: IntoIterator<Item = (Range<S>, T)>,
 2083        S: ToOffset,
 2084        T: Into<Arc<str>>,
 2085    {
 2086        if self.read_only(cx) {
 2087            return;
 2088        }
 2089
 2090        self.buffer.update(cx, |buffer, cx| {
 2091            buffer.edit(edits, self.autoindent_mode.clone(), cx)
 2092        });
 2093    }
 2094
 2095    pub fn edit_with_block_indent<I, S, T>(
 2096        &mut self,
 2097        edits: I,
 2098        original_indent_columns: Vec<u32>,
 2099        cx: &mut ViewContext<Self>,
 2100    ) where
 2101        I: IntoIterator<Item = (Range<S>, T)>,
 2102        S: ToOffset,
 2103        T: Into<Arc<str>>,
 2104    {
 2105        if self.read_only(cx) {
 2106            return;
 2107        }
 2108
 2109        self.buffer.update(cx, |buffer, cx| {
 2110            buffer.edit(
 2111                edits,
 2112                Some(AutoindentMode::Block {
 2113                    original_indent_columns,
 2114                }),
 2115                cx,
 2116            )
 2117        });
 2118    }
 2119
 2120    fn select(&mut self, phase: SelectPhase, cx: &mut ViewContext<Self>) {
 2121        self.hide_context_menu(cx);
 2122
 2123        match phase {
 2124            SelectPhase::Begin {
 2125                position,
 2126                add,
 2127                click_count,
 2128            } => self.begin_selection(position, add, click_count, cx),
 2129            SelectPhase::BeginColumnar {
 2130                position,
 2131                goal_column,
 2132                reset,
 2133            } => self.begin_columnar_selection(position, goal_column, reset, cx),
 2134            SelectPhase::Extend {
 2135                position,
 2136                click_count,
 2137            } => self.extend_selection(position, click_count, cx),
 2138            SelectPhase::Update {
 2139                position,
 2140                goal_column,
 2141                scroll_delta,
 2142            } => self.update_selection(position, goal_column, scroll_delta, cx),
 2143            SelectPhase::End => self.end_selection(cx),
 2144        }
 2145    }
 2146
 2147    fn extend_selection(
 2148        &mut self,
 2149        position: DisplayPoint,
 2150        click_count: usize,
 2151        cx: &mut ViewContext<Self>,
 2152    ) {
 2153        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 2154        let tail = self.selections.newest::<usize>(cx).tail();
 2155        self.begin_selection(position, false, click_count, cx);
 2156
 2157        let position = position.to_offset(&display_map, Bias::Left);
 2158        let tail_anchor = display_map.buffer_snapshot.anchor_before(tail);
 2159
 2160        let mut pending_selection = self
 2161            .selections
 2162            .pending_anchor()
 2163            .expect("extend_selection not called with pending selection");
 2164        if position >= tail {
 2165            pending_selection.start = tail_anchor;
 2166        } else {
 2167            pending_selection.end = tail_anchor;
 2168            pending_selection.reversed = true;
 2169        }
 2170
 2171        let mut pending_mode = self.selections.pending_mode().unwrap();
 2172        match &mut pending_mode {
 2173            SelectMode::Word(range) | SelectMode::Line(range) => *range = tail_anchor..tail_anchor,
 2174            _ => {}
 2175        }
 2176
 2177        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 2178            s.set_pending(pending_selection, pending_mode)
 2179        });
 2180    }
 2181
 2182    fn begin_selection(
 2183        &mut self,
 2184        position: DisplayPoint,
 2185        add: bool,
 2186        click_count: usize,
 2187        cx: &mut ViewContext<Self>,
 2188    ) {
 2189        if !self.focus_handle.is_focused(cx) {
 2190            self.last_focused_descendant = None;
 2191            cx.focus(&self.focus_handle);
 2192        }
 2193
 2194        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 2195        let buffer = &display_map.buffer_snapshot;
 2196        let newest_selection = self.selections.newest_anchor().clone();
 2197        let position = display_map.clip_point(position, Bias::Left);
 2198
 2199        let start;
 2200        let end;
 2201        let mode;
 2202        let mut auto_scroll;
 2203        match click_count {
 2204            1 => {
 2205                start = buffer.anchor_before(position.to_point(&display_map));
 2206                end = start;
 2207                mode = SelectMode::Character;
 2208                auto_scroll = true;
 2209            }
 2210            2 => {
 2211                let range = movement::surrounding_word(&display_map, position);
 2212                start = buffer.anchor_before(range.start.to_point(&display_map));
 2213                end = buffer.anchor_before(range.end.to_point(&display_map));
 2214                mode = SelectMode::Word(start..end);
 2215                auto_scroll = true;
 2216            }
 2217            3 => {
 2218                let position = display_map
 2219                    .clip_point(position, Bias::Left)
 2220                    .to_point(&display_map);
 2221                let line_start = display_map.prev_line_boundary(position).0;
 2222                let next_line_start = buffer.clip_point(
 2223                    display_map.next_line_boundary(position).0 + Point::new(1, 0),
 2224                    Bias::Left,
 2225                );
 2226                start = buffer.anchor_before(line_start);
 2227                end = buffer.anchor_before(next_line_start);
 2228                mode = SelectMode::Line(start..end);
 2229                auto_scroll = true;
 2230            }
 2231            _ => {
 2232                start = buffer.anchor_before(0);
 2233                end = buffer.anchor_before(buffer.len());
 2234                mode = SelectMode::All;
 2235                auto_scroll = false;
 2236            }
 2237        }
 2238        auto_scroll &= EditorSettings::get_global(cx).autoscroll_on_clicks;
 2239
 2240        let point_to_delete: Option<usize> = {
 2241            let selected_points: Vec<Selection<Point>> =
 2242                self.selections.disjoint_in_range(start..end, cx);
 2243
 2244            if !add || click_count > 1 {
 2245                None
 2246            } else if !selected_points.is_empty() {
 2247                Some(selected_points[0].id)
 2248            } else {
 2249                let clicked_point_already_selected =
 2250                    self.selections.disjoint.iter().find(|selection| {
 2251                        selection.start.to_point(buffer) == start.to_point(buffer)
 2252                            || selection.end.to_point(buffer) == end.to_point(buffer)
 2253                    });
 2254
 2255                clicked_point_already_selected.map(|selection| selection.id)
 2256            }
 2257        };
 2258
 2259        let selections_count = self.selections.count();
 2260
 2261        self.change_selections(auto_scroll.then(Autoscroll::newest), cx, |s| {
 2262            if let Some(point_to_delete) = point_to_delete {
 2263                s.delete(point_to_delete);
 2264
 2265                if selections_count == 1 {
 2266                    s.set_pending_anchor_range(start..end, mode);
 2267                }
 2268            } else {
 2269                if !add {
 2270                    s.clear_disjoint();
 2271                } else if click_count > 1 {
 2272                    s.delete(newest_selection.id)
 2273                }
 2274
 2275                s.set_pending_anchor_range(start..end, mode);
 2276            }
 2277        });
 2278    }
 2279
 2280    fn begin_columnar_selection(
 2281        &mut self,
 2282        position: DisplayPoint,
 2283        goal_column: u32,
 2284        reset: bool,
 2285        cx: &mut ViewContext<Self>,
 2286    ) {
 2287        if !self.focus_handle.is_focused(cx) {
 2288            self.last_focused_descendant = None;
 2289            cx.focus(&self.focus_handle);
 2290        }
 2291
 2292        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 2293
 2294        if reset {
 2295            let pointer_position = display_map
 2296                .buffer_snapshot
 2297                .anchor_before(position.to_point(&display_map));
 2298
 2299            self.change_selections(Some(Autoscroll::newest()), cx, |s| {
 2300                s.clear_disjoint();
 2301                s.set_pending_anchor_range(
 2302                    pointer_position..pointer_position,
 2303                    SelectMode::Character,
 2304                );
 2305            });
 2306        }
 2307
 2308        let tail = self.selections.newest::<Point>(cx).tail();
 2309        self.columnar_selection_tail = Some(display_map.buffer_snapshot.anchor_before(tail));
 2310
 2311        if !reset {
 2312            self.select_columns(
 2313                tail.to_display_point(&display_map),
 2314                position,
 2315                goal_column,
 2316                &display_map,
 2317                cx,
 2318            );
 2319        }
 2320    }
 2321
 2322    fn update_selection(
 2323        &mut self,
 2324        position: DisplayPoint,
 2325        goal_column: u32,
 2326        scroll_delta: gpui::Point<f32>,
 2327        cx: &mut ViewContext<Self>,
 2328    ) {
 2329        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 2330
 2331        if let Some(tail) = self.columnar_selection_tail.as_ref() {
 2332            let tail = tail.to_display_point(&display_map);
 2333            self.select_columns(tail, position, goal_column, &display_map, cx);
 2334        } else if let Some(mut pending) = self.selections.pending_anchor() {
 2335            let buffer = self.buffer.read(cx).snapshot(cx);
 2336            let head;
 2337            let tail;
 2338            let mode = self.selections.pending_mode().unwrap();
 2339            match &mode {
 2340                SelectMode::Character => {
 2341                    head = position.to_point(&display_map);
 2342                    tail = pending.tail().to_point(&buffer);
 2343                }
 2344                SelectMode::Word(original_range) => {
 2345                    let original_display_range = original_range.start.to_display_point(&display_map)
 2346                        ..original_range.end.to_display_point(&display_map);
 2347                    let original_buffer_range = original_display_range.start.to_point(&display_map)
 2348                        ..original_display_range.end.to_point(&display_map);
 2349                    if movement::is_inside_word(&display_map, position)
 2350                        || original_display_range.contains(&position)
 2351                    {
 2352                        let word_range = movement::surrounding_word(&display_map, position);
 2353                        if word_range.start < original_display_range.start {
 2354                            head = word_range.start.to_point(&display_map);
 2355                        } else {
 2356                            head = word_range.end.to_point(&display_map);
 2357                        }
 2358                    } else {
 2359                        head = position.to_point(&display_map);
 2360                    }
 2361
 2362                    if head <= original_buffer_range.start {
 2363                        tail = original_buffer_range.end;
 2364                    } else {
 2365                        tail = original_buffer_range.start;
 2366                    }
 2367                }
 2368                SelectMode::Line(original_range) => {
 2369                    let original_range = original_range.to_point(&display_map.buffer_snapshot);
 2370
 2371                    let position = display_map
 2372                        .clip_point(position, Bias::Left)
 2373                        .to_point(&display_map);
 2374                    let line_start = display_map.prev_line_boundary(position).0;
 2375                    let next_line_start = buffer.clip_point(
 2376                        display_map.next_line_boundary(position).0 + Point::new(1, 0),
 2377                        Bias::Left,
 2378                    );
 2379
 2380                    if line_start < original_range.start {
 2381                        head = line_start
 2382                    } else {
 2383                        head = next_line_start
 2384                    }
 2385
 2386                    if head <= original_range.start {
 2387                        tail = original_range.end;
 2388                    } else {
 2389                        tail = original_range.start;
 2390                    }
 2391                }
 2392                SelectMode::All => {
 2393                    return;
 2394                }
 2395            };
 2396
 2397            if head < tail {
 2398                pending.start = buffer.anchor_before(head);
 2399                pending.end = buffer.anchor_before(tail);
 2400                pending.reversed = true;
 2401            } else {
 2402                pending.start = buffer.anchor_before(tail);
 2403                pending.end = buffer.anchor_before(head);
 2404                pending.reversed = false;
 2405            }
 2406
 2407            self.change_selections(None, cx, |s| {
 2408                s.set_pending(pending, mode);
 2409            });
 2410        } else {
 2411            log::error!("update_selection dispatched with no pending selection");
 2412            return;
 2413        }
 2414
 2415        self.apply_scroll_delta(scroll_delta, cx);
 2416        cx.notify();
 2417    }
 2418
 2419    fn end_selection(&mut self, cx: &mut ViewContext<Self>) {
 2420        self.columnar_selection_tail.take();
 2421        if self.selections.pending_anchor().is_some() {
 2422            let selections = self.selections.all::<usize>(cx);
 2423            self.change_selections(None, cx, |s| {
 2424                s.select(selections);
 2425                s.clear_pending();
 2426            });
 2427        }
 2428    }
 2429
 2430    fn select_columns(
 2431        &mut self,
 2432        tail: DisplayPoint,
 2433        head: DisplayPoint,
 2434        goal_column: u32,
 2435        display_map: &DisplaySnapshot,
 2436        cx: &mut ViewContext<Self>,
 2437    ) {
 2438        let start_row = cmp::min(tail.row(), head.row());
 2439        let end_row = cmp::max(tail.row(), head.row());
 2440        let start_column = cmp::min(tail.column(), goal_column);
 2441        let end_column = cmp::max(tail.column(), goal_column);
 2442        let reversed = start_column < tail.column();
 2443
 2444        let selection_ranges = (start_row.0..=end_row.0)
 2445            .map(DisplayRow)
 2446            .filter_map(|row| {
 2447                if start_column <= display_map.line_len(row) && !display_map.is_block_line(row) {
 2448                    let start = display_map
 2449                        .clip_point(DisplayPoint::new(row, start_column), Bias::Left)
 2450                        .to_point(display_map);
 2451                    let end = display_map
 2452                        .clip_point(DisplayPoint::new(row, end_column), Bias::Right)
 2453                        .to_point(display_map);
 2454                    if reversed {
 2455                        Some(end..start)
 2456                    } else {
 2457                        Some(start..end)
 2458                    }
 2459                } else {
 2460                    None
 2461                }
 2462            })
 2463            .collect::<Vec<_>>();
 2464
 2465        self.change_selections(None, cx, |s| {
 2466            s.select_ranges(selection_ranges);
 2467        });
 2468        cx.notify();
 2469    }
 2470
 2471    pub fn has_pending_nonempty_selection(&self) -> bool {
 2472        let pending_nonempty_selection = match self.selections.pending_anchor() {
 2473            Some(Selection { start, end, .. }) => start != end,
 2474            None => false,
 2475        };
 2476
 2477        pending_nonempty_selection
 2478            || (self.columnar_selection_tail.is_some() && self.selections.disjoint.len() > 1)
 2479    }
 2480
 2481    pub fn has_pending_selection(&self) -> bool {
 2482        self.selections.pending_anchor().is_some() || self.columnar_selection_tail.is_some()
 2483    }
 2484
 2485    pub fn cancel(&mut self, _: &Cancel, cx: &mut ViewContext<Self>) {
 2486        self.selection_mark_mode = false;
 2487
 2488        if self.clear_expanded_diff_hunks(cx) {
 2489            cx.notify();
 2490            return;
 2491        }
 2492        if self.dismiss_menus_and_popups(true, cx) {
 2493            return;
 2494        }
 2495
 2496        if self.mode == EditorMode::Full
 2497            && self.change_selections(Some(Autoscroll::fit()), cx, |s| s.try_cancel())
 2498        {
 2499            return;
 2500        }
 2501
 2502        cx.propagate();
 2503    }
 2504
 2505    pub fn dismiss_menus_and_popups(
 2506        &mut self,
 2507        should_report_inline_completion_event: bool,
 2508        cx: &mut ViewContext<Self>,
 2509    ) -> bool {
 2510        if self.take_rename(false, cx).is_some() {
 2511            return true;
 2512        }
 2513
 2514        if hide_hover(self, cx) {
 2515            return true;
 2516        }
 2517
 2518        if self.hide_signature_help(cx, SignatureHelpHiddenBy::Escape) {
 2519            return true;
 2520        }
 2521
 2522        if self.hide_context_menu(cx).is_some() {
 2523            if self.show_inline_completions_in_menu(cx) && self.has_active_inline_completion() {
 2524                self.update_visible_inline_completion(cx);
 2525            }
 2526            return true;
 2527        }
 2528
 2529        if self.mouse_context_menu.take().is_some() {
 2530            return true;
 2531        }
 2532
 2533        if self.discard_inline_completion(should_report_inline_completion_event, cx) {
 2534            return true;
 2535        }
 2536
 2537        if self.snippet_stack.pop().is_some() {
 2538            return true;
 2539        }
 2540
 2541        if self.mode == EditorMode::Full && self.active_diagnostics.is_some() {
 2542            self.dismiss_diagnostics(cx);
 2543            return true;
 2544        }
 2545
 2546        false
 2547    }
 2548
 2549    fn linked_editing_ranges_for(
 2550        &self,
 2551        selection: Range<text::Anchor>,
 2552        cx: &AppContext,
 2553    ) -> Option<HashMap<Model<Buffer>, Vec<Range<text::Anchor>>>> {
 2554        if self.linked_edit_ranges.is_empty() {
 2555            return None;
 2556        }
 2557        let ((base_range, linked_ranges), buffer_snapshot, buffer) =
 2558            selection.end.buffer_id.and_then(|end_buffer_id| {
 2559                if selection.start.buffer_id != Some(end_buffer_id) {
 2560                    return None;
 2561                }
 2562                let buffer = self.buffer.read(cx).buffer(end_buffer_id)?;
 2563                let snapshot = buffer.read(cx).snapshot();
 2564                self.linked_edit_ranges
 2565                    .get(end_buffer_id, selection.start..selection.end, &snapshot)
 2566                    .map(|ranges| (ranges, snapshot, buffer))
 2567            })?;
 2568        use text::ToOffset as TO;
 2569        // find offset from the start of current range to current cursor position
 2570        let start_byte_offset = TO::to_offset(&base_range.start, &buffer_snapshot);
 2571
 2572        let start_offset = TO::to_offset(&selection.start, &buffer_snapshot);
 2573        let start_difference = start_offset - start_byte_offset;
 2574        let end_offset = TO::to_offset(&selection.end, &buffer_snapshot);
 2575        let end_difference = end_offset - start_byte_offset;
 2576        // Current range has associated linked ranges.
 2577        let mut linked_edits = HashMap::<_, Vec<_>>::default();
 2578        for range in linked_ranges.iter() {
 2579            let start_offset = TO::to_offset(&range.start, &buffer_snapshot);
 2580            let end_offset = start_offset + end_difference;
 2581            let start_offset = start_offset + start_difference;
 2582            if start_offset > buffer_snapshot.len() || end_offset > buffer_snapshot.len() {
 2583                continue;
 2584            }
 2585            if self.selections.disjoint_anchor_ranges().any(|s| {
 2586                if s.start.buffer_id != selection.start.buffer_id
 2587                    || s.end.buffer_id != selection.end.buffer_id
 2588                {
 2589                    return false;
 2590                }
 2591                TO::to_offset(&s.start.text_anchor, &buffer_snapshot) <= end_offset
 2592                    && TO::to_offset(&s.end.text_anchor, &buffer_snapshot) >= start_offset
 2593            }) {
 2594                continue;
 2595            }
 2596            let start = buffer_snapshot.anchor_after(start_offset);
 2597            let end = buffer_snapshot.anchor_after(end_offset);
 2598            linked_edits
 2599                .entry(buffer.clone())
 2600                .or_default()
 2601                .push(start..end);
 2602        }
 2603        Some(linked_edits)
 2604    }
 2605
 2606    pub fn handle_input(&mut self, text: &str, cx: &mut ViewContext<Self>) {
 2607        let text: Arc<str> = text.into();
 2608
 2609        if self.read_only(cx) {
 2610            return;
 2611        }
 2612
 2613        let selections = self.selections.all_adjusted(cx);
 2614        let mut bracket_inserted = false;
 2615        let mut edits = Vec::new();
 2616        let mut linked_edits = HashMap::<_, Vec<_>>::default();
 2617        let mut new_selections = Vec::with_capacity(selections.len());
 2618        let mut new_autoclose_regions = Vec::new();
 2619        let snapshot = self.buffer.read(cx).read(cx);
 2620
 2621        for (selection, autoclose_region) in
 2622            self.selections_with_autoclose_regions(selections, &snapshot)
 2623        {
 2624            if let Some(scope) = snapshot.language_scope_at(selection.head()) {
 2625                // Determine if the inserted text matches the opening or closing
 2626                // bracket of any of this language's bracket pairs.
 2627                let mut bracket_pair = None;
 2628                let mut is_bracket_pair_start = false;
 2629                let mut is_bracket_pair_end = false;
 2630                if !text.is_empty() {
 2631                    // `text` can be empty when a user is using IME (e.g. Chinese Wubi Simplified)
 2632                    //  and they are removing the character that triggered IME popup.
 2633                    for (pair, enabled) in scope.brackets() {
 2634                        if !pair.close && !pair.surround {
 2635                            continue;
 2636                        }
 2637
 2638                        if enabled && pair.start.ends_with(text.as_ref()) {
 2639                            let prefix_len = pair.start.len() - text.len();
 2640                            let preceding_text_matches_prefix = prefix_len == 0
 2641                                || (selection.start.column >= (prefix_len as u32)
 2642                                    && snapshot.contains_str_at(
 2643                                        Point::new(
 2644                                            selection.start.row,
 2645                                            selection.start.column - (prefix_len as u32),
 2646                                        ),
 2647                                        &pair.start[..prefix_len],
 2648                                    ));
 2649                            if preceding_text_matches_prefix {
 2650                                bracket_pair = Some(pair.clone());
 2651                                is_bracket_pair_start = true;
 2652                                break;
 2653                            }
 2654                        }
 2655                        if pair.end.as_str() == text.as_ref() {
 2656                            bracket_pair = Some(pair.clone());
 2657                            is_bracket_pair_end = true;
 2658                            break;
 2659                        }
 2660                    }
 2661                }
 2662
 2663                if let Some(bracket_pair) = bracket_pair {
 2664                    let snapshot_settings = snapshot.settings_at(selection.start, cx);
 2665                    let autoclose = self.use_autoclose && snapshot_settings.use_autoclose;
 2666                    let auto_surround =
 2667                        self.use_auto_surround && snapshot_settings.use_auto_surround;
 2668                    if selection.is_empty() {
 2669                        if is_bracket_pair_start {
 2670                            // If the inserted text is a suffix of an opening bracket and the
 2671                            // selection is preceded by the rest of the opening bracket, then
 2672                            // insert the closing bracket.
 2673                            let following_text_allows_autoclose = snapshot
 2674                                .chars_at(selection.start)
 2675                                .next()
 2676                                .map_or(true, |c| scope.should_autoclose_before(c));
 2677
 2678                            let is_closing_quote = if bracket_pair.end == bracket_pair.start
 2679                                && bracket_pair.start.len() == 1
 2680                            {
 2681                                let target = bracket_pair.start.chars().next().unwrap();
 2682                                let current_line_count = snapshot
 2683                                    .reversed_chars_at(selection.start)
 2684                                    .take_while(|&c| c != '\n')
 2685                                    .filter(|&c| c == target)
 2686                                    .count();
 2687                                current_line_count % 2 == 1
 2688                            } else {
 2689                                false
 2690                            };
 2691
 2692                            if autoclose
 2693                                && bracket_pair.close
 2694                                && following_text_allows_autoclose
 2695                                && !is_closing_quote
 2696                            {
 2697                                let anchor = snapshot.anchor_before(selection.end);
 2698                                new_selections.push((selection.map(|_| anchor), text.len()));
 2699                                new_autoclose_regions.push((
 2700                                    anchor,
 2701                                    text.len(),
 2702                                    selection.id,
 2703                                    bracket_pair.clone(),
 2704                                ));
 2705                                edits.push((
 2706                                    selection.range(),
 2707                                    format!("{}{}", text, bracket_pair.end).into(),
 2708                                ));
 2709                                bracket_inserted = true;
 2710                                continue;
 2711                            }
 2712                        }
 2713
 2714                        if let Some(region) = autoclose_region {
 2715                            // If the selection is followed by an auto-inserted closing bracket,
 2716                            // then don't insert that closing bracket again; just move the selection
 2717                            // past the closing bracket.
 2718                            let should_skip = selection.end == region.range.end.to_point(&snapshot)
 2719                                && text.as_ref() == region.pair.end.as_str();
 2720                            if should_skip {
 2721                                let anchor = snapshot.anchor_after(selection.end);
 2722                                new_selections
 2723                                    .push((selection.map(|_| anchor), region.pair.end.len()));
 2724                                continue;
 2725                            }
 2726                        }
 2727
 2728                        let always_treat_brackets_as_autoclosed = snapshot
 2729                            .settings_at(selection.start, cx)
 2730                            .always_treat_brackets_as_autoclosed;
 2731                        if always_treat_brackets_as_autoclosed
 2732                            && is_bracket_pair_end
 2733                            && snapshot.contains_str_at(selection.end, text.as_ref())
 2734                        {
 2735                            // Otherwise, when `always_treat_brackets_as_autoclosed` is set to `true
 2736                            // and the inserted text is a closing bracket and the selection is followed
 2737                            // by the closing bracket then move the selection past the closing bracket.
 2738                            let anchor = snapshot.anchor_after(selection.end);
 2739                            new_selections.push((selection.map(|_| anchor), text.len()));
 2740                            continue;
 2741                        }
 2742                    }
 2743                    // If an opening bracket is 1 character long and is typed while
 2744                    // text is selected, then surround that text with the bracket pair.
 2745                    else if auto_surround
 2746                        && bracket_pair.surround
 2747                        && is_bracket_pair_start
 2748                        && bracket_pair.start.chars().count() == 1
 2749                    {
 2750                        edits.push((selection.start..selection.start, text.clone()));
 2751                        edits.push((
 2752                            selection.end..selection.end,
 2753                            bracket_pair.end.as_str().into(),
 2754                        ));
 2755                        bracket_inserted = true;
 2756                        new_selections.push((
 2757                            Selection {
 2758                                id: selection.id,
 2759                                start: snapshot.anchor_after(selection.start),
 2760                                end: snapshot.anchor_before(selection.end),
 2761                                reversed: selection.reversed,
 2762                                goal: selection.goal,
 2763                            },
 2764                            0,
 2765                        ));
 2766                        continue;
 2767                    }
 2768                }
 2769            }
 2770
 2771            if self.auto_replace_emoji_shortcode
 2772                && selection.is_empty()
 2773                && text.as_ref().ends_with(':')
 2774            {
 2775                if let Some(possible_emoji_short_code) =
 2776                    Self::find_possible_emoji_shortcode_at_position(&snapshot, selection.start)
 2777                {
 2778                    if !possible_emoji_short_code.is_empty() {
 2779                        if let Some(emoji) = emojis::get_by_shortcode(&possible_emoji_short_code) {
 2780                            let emoji_shortcode_start = Point::new(
 2781                                selection.start.row,
 2782                                selection.start.column - possible_emoji_short_code.len() as u32 - 1,
 2783                            );
 2784
 2785                            // Remove shortcode from buffer
 2786                            edits.push((
 2787                                emoji_shortcode_start..selection.start,
 2788                                "".to_string().into(),
 2789                            ));
 2790                            new_selections.push((
 2791                                Selection {
 2792                                    id: selection.id,
 2793                                    start: snapshot.anchor_after(emoji_shortcode_start),
 2794                                    end: snapshot.anchor_before(selection.start),
 2795                                    reversed: selection.reversed,
 2796                                    goal: selection.goal,
 2797                                },
 2798                                0,
 2799                            ));
 2800
 2801                            // Insert emoji
 2802                            let selection_start_anchor = snapshot.anchor_after(selection.start);
 2803                            new_selections.push((selection.map(|_| selection_start_anchor), 0));
 2804                            edits.push((selection.start..selection.end, emoji.to_string().into()));
 2805
 2806                            continue;
 2807                        }
 2808                    }
 2809                }
 2810            }
 2811
 2812            // If not handling any auto-close operation, then just replace the selected
 2813            // text with the given input and move the selection to the end of the
 2814            // newly inserted text.
 2815            let anchor = snapshot.anchor_after(selection.end);
 2816            if !self.linked_edit_ranges.is_empty() {
 2817                let start_anchor = snapshot.anchor_before(selection.start);
 2818
 2819                let is_word_char = text.chars().next().map_or(true, |char| {
 2820                    let classifier = snapshot.char_classifier_at(start_anchor.to_offset(&snapshot));
 2821                    classifier.is_word(char)
 2822                });
 2823
 2824                if is_word_char {
 2825                    if let Some(ranges) = self
 2826                        .linked_editing_ranges_for(start_anchor.text_anchor..anchor.text_anchor, cx)
 2827                    {
 2828                        for (buffer, edits) in ranges {
 2829                            linked_edits
 2830                                .entry(buffer.clone())
 2831                                .or_default()
 2832                                .extend(edits.into_iter().map(|range| (range, text.clone())));
 2833                        }
 2834                    }
 2835                }
 2836            }
 2837
 2838            new_selections.push((selection.map(|_| anchor), 0));
 2839            edits.push((selection.start..selection.end, text.clone()));
 2840        }
 2841
 2842        drop(snapshot);
 2843
 2844        self.transact(cx, |this, cx| {
 2845            this.buffer.update(cx, |buffer, cx| {
 2846                buffer.edit(edits, this.autoindent_mode.clone(), cx);
 2847            });
 2848            for (buffer, edits) in linked_edits {
 2849                buffer.update(cx, |buffer, cx| {
 2850                    let snapshot = buffer.snapshot();
 2851                    let edits = edits
 2852                        .into_iter()
 2853                        .map(|(range, text)| {
 2854                            use text::ToPoint as TP;
 2855                            let end_point = TP::to_point(&range.end, &snapshot);
 2856                            let start_point = TP::to_point(&range.start, &snapshot);
 2857                            (start_point..end_point, text)
 2858                        })
 2859                        .sorted_by_key(|(range, _)| range.start)
 2860                        .collect::<Vec<_>>();
 2861                    buffer.edit(edits, None, cx);
 2862                })
 2863            }
 2864            let new_anchor_selections = new_selections.iter().map(|e| &e.0);
 2865            let new_selection_deltas = new_selections.iter().map(|e| e.1);
 2866            let map = this.display_map.update(cx, |map, cx| map.snapshot(cx));
 2867            let new_selections = resolve_selections::<usize, _>(new_anchor_selections, &map)
 2868                .zip(new_selection_deltas)
 2869                .map(|(selection, delta)| Selection {
 2870                    id: selection.id,
 2871                    start: selection.start + delta,
 2872                    end: selection.end + delta,
 2873                    reversed: selection.reversed,
 2874                    goal: SelectionGoal::None,
 2875                })
 2876                .collect::<Vec<_>>();
 2877
 2878            let mut i = 0;
 2879            for (position, delta, selection_id, pair) in new_autoclose_regions {
 2880                let position = position.to_offset(&map.buffer_snapshot) + delta;
 2881                let start = map.buffer_snapshot.anchor_before(position);
 2882                let end = map.buffer_snapshot.anchor_after(position);
 2883                while let Some(existing_state) = this.autoclose_regions.get(i) {
 2884                    match existing_state.range.start.cmp(&start, &map.buffer_snapshot) {
 2885                        Ordering::Less => i += 1,
 2886                        Ordering::Greater => break,
 2887                        Ordering::Equal => {
 2888                            match end.cmp(&existing_state.range.end, &map.buffer_snapshot) {
 2889                                Ordering::Less => i += 1,
 2890                                Ordering::Equal => break,
 2891                                Ordering::Greater => break,
 2892                            }
 2893                        }
 2894                    }
 2895                }
 2896                this.autoclose_regions.insert(
 2897                    i,
 2898                    AutocloseRegion {
 2899                        selection_id,
 2900                        range: start..end,
 2901                        pair,
 2902                    },
 2903                );
 2904            }
 2905
 2906            let had_active_inline_completion = this.has_active_inline_completion();
 2907            this.change_selections_inner(Some(Autoscroll::fit()), false, cx, |s| {
 2908                s.select(new_selections)
 2909            });
 2910
 2911            if !bracket_inserted {
 2912                if let Some(on_type_format_task) =
 2913                    this.trigger_on_type_formatting(text.to_string(), cx)
 2914                {
 2915                    on_type_format_task.detach_and_log_err(cx);
 2916                }
 2917            }
 2918
 2919            let editor_settings = EditorSettings::get_global(cx);
 2920            if bracket_inserted
 2921                && (editor_settings.auto_signature_help
 2922                    || editor_settings.show_signature_help_after_edits)
 2923            {
 2924                this.show_signature_help(&ShowSignatureHelp, cx);
 2925            }
 2926
 2927            let trigger_in_words =
 2928                this.show_inline_completions_in_menu(cx) || !had_active_inline_completion;
 2929            this.trigger_completion_on_input(&text, trigger_in_words, cx);
 2930            linked_editing_ranges::refresh_linked_ranges(this, cx);
 2931            this.refresh_inline_completion(true, false, cx);
 2932        });
 2933    }
 2934
 2935    fn find_possible_emoji_shortcode_at_position(
 2936        snapshot: &MultiBufferSnapshot,
 2937        position: Point,
 2938    ) -> Option<String> {
 2939        let mut chars = Vec::new();
 2940        let mut found_colon = false;
 2941        for char in snapshot.reversed_chars_at(position).take(100) {
 2942            // Found a possible emoji shortcode in the middle of the buffer
 2943            if found_colon {
 2944                if char.is_whitespace() {
 2945                    chars.reverse();
 2946                    return Some(chars.iter().collect());
 2947                }
 2948                // If the previous character is not a whitespace, we are in the middle of a word
 2949                // and we only want to complete the shortcode if the word is made up of other emojis
 2950                let mut containing_word = String::new();
 2951                for ch in snapshot
 2952                    .reversed_chars_at(position)
 2953                    .skip(chars.len() + 1)
 2954                    .take(100)
 2955                {
 2956                    if ch.is_whitespace() {
 2957                        break;
 2958                    }
 2959                    containing_word.push(ch);
 2960                }
 2961                let containing_word = containing_word.chars().rev().collect::<String>();
 2962                if util::word_consists_of_emojis(containing_word.as_str()) {
 2963                    chars.reverse();
 2964                    return Some(chars.iter().collect());
 2965                }
 2966            }
 2967
 2968            if char.is_whitespace() || !char.is_ascii() {
 2969                return None;
 2970            }
 2971            if char == ':' {
 2972                found_colon = true;
 2973            } else {
 2974                chars.push(char);
 2975            }
 2976        }
 2977        // Found a possible emoji shortcode at the beginning of the buffer
 2978        chars.reverse();
 2979        Some(chars.iter().collect())
 2980    }
 2981
 2982    pub fn newline(&mut self, _: &Newline, cx: &mut ViewContext<Self>) {
 2983        self.transact(cx, |this, cx| {
 2984            let (edits, selection_fixup_info): (Vec<_>, Vec<_>) = {
 2985                let selections = this.selections.all::<usize>(cx);
 2986                let multi_buffer = this.buffer.read(cx);
 2987                let buffer = multi_buffer.snapshot(cx);
 2988                selections
 2989                    .iter()
 2990                    .map(|selection| {
 2991                        let start_point = selection.start.to_point(&buffer);
 2992                        let mut indent =
 2993                            buffer.indent_size_for_line(MultiBufferRow(start_point.row));
 2994                        indent.len = cmp::min(indent.len, start_point.column);
 2995                        let start = selection.start;
 2996                        let end = selection.end;
 2997                        let selection_is_empty = start == end;
 2998                        let language_scope = buffer.language_scope_at(start);
 2999                        let (comment_delimiter, insert_extra_newline) = if let Some(language) =
 3000                            &language_scope
 3001                        {
 3002                            let leading_whitespace_len = buffer
 3003                                .reversed_chars_at(start)
 3004                                .take_while(|c| c.is_whitespace() && *c != '\n')
 3005                                .map(|c| c.len_utf8())
 3006                                .sum::<usize>();
 3007
 3008                            let trailing_whitespace_len = buffer
 3009                                .chars_at(end)
 3010                                .take_while(|c| c.is_whitespace() && *c != '\n')
 3011                                .map(|c| c.len_utf8())
 3012                                .sum::<usize>();
 3013
 3014                            let insert_extra_newline =
 3015                                language.brackets().any(|(pair, enabled)| {
 3016                                    let pair_start = pair.start.trim_end();
 3017                                    let pair_end = pair.end.trim_start();
 3018
 3019                                    enabled
 3020                                        && pair.newline
 3021                                        && buffer.contains_str_at(
 3022                                            end + trailing_whitespace_len,
 3023                                            pair_end,
 3024                                        )
 3025                                        && buffer.contains_str_at(
 3026                                            (start - leading_whitespace_len)
 3027                                                .saturating_sub(pair_start.len()),
 3028                                            pair_start,
 3029                                        )
 3030                                });
 3031
 3032                            // Comment extension on newline is allowed only for cursor selections
 3033                            let comment_delimiter = maybe!({
 3034                                if !selection_is_empty {
 3035                                    return None;
 3036                                }
 3037
 3038                                if !multi_buffer.settings_at(0, cx).extend_comment_on_newline {
 3039                                    return None;
 3040                                }
 3041
 3042                                let delimiters = language.line_comment_prefixes();
 3043                                let max_len_of_delimiter =
 3044                                    delimiters.iter().map(|delimiter| delimiter.len()).max()?;
 3045                                let (snapshot, range) =
 3046                                    buffer.buffer_line_for_row(MultiBufferRow(start_point.row))?;
 3047
 3048                                let mut index_of_first_non_whitespace = 0;
 3049                                let comment_candidate = snapshot
 3050                                    .chars_for_range(range)
 3051                                    .skip_while(|c| {
 3052                                        let should_skip = c.is_whitespace();
 3053                                        if should_skip {
 3054                                            index_of_first_non_whitespace += 1;
 3055                                        }
 3056                                        should_skip
 3057                                    })
 3058                                    .take(max_len_of_delimiter)
 3059                                    .collect::<String>();
 3060                                let comment_prefix = delimiters.iter().find(|comment_prefix| {
 3061                                    comment_candidate.starts_with(comment_prefix.as_ref())
 3062                                })?;
 3063                                let cursor_is_placed_after_comment_marker =
 3064                                    index_of_first_non_whitespace + comment_prefix.len()
 3065                                        <= start_point.column as usize;
 3066                                if cursor_is_placed_after_comment_marker {
 3067                                    Some(comment_prefix.clone())
 3068                                } else {
 3069                                    None
 3070                                }
 3071                            });
 3072                            (comment_delimiter, insert_extra_newline)
 3073                        } else {
 3074                            (None, false)
 3075                        };
 3076
 3077                        let capacity_for_delimiter = comment_delimiter
 3078                            .as_deref()
 3079                            .map(str::len)
 3080                            .unwrap_or_default();
 3081                        let mut new_text =
 3082                            String::with_capacity(1 + capacity_for_delimiter + indent.len as usize);
 3083                        new_text.push('\n');
 3084                        new_text.extend(indent.chars());
 3085                        if let Some(delimiter) = &comment_delimiter {
 3086                            new_text.push_str(delimiter);
 3087                        }
 3088                        if insert_extra_newline {
 3089                            new_text = new_text.repeat(2);
 3090                        }
 3091
 3092                        let anchor = buffer.anchor_after(end);
 3093                        let new_selection = selection.map(|_| anchor);
 3094                        (
 3095                            (start..end, new_text),
 3096                            (insert_extra_newline, new_selection),
 3097                        )
 3098                    })
 3099                    .unzip()
 3100            };
 3101
 3102            this.edit_with_autoindent(edits, cx);
 3103            let buffer = this.buffer.read(cx).snapshot(cx);
 3104            let new_selections = selection_fixup_info
 3105                .into_iter()
 3106                .map(|(extra_newline_inserted, new_selection)| {
 3107                    let mut cursor = new_selection.end.to_point(&buffer);
 3108                    if extra_newline_inserted {
 3109                        cursor.row -= 1;
 3110                        cursor.column = buffer.line_len(MultiBufferRow(cursor.row));
 3111                    }
 3112                    new_selection.map(|_| cursor)
 3113                })
 3114                .collect();
 3115
 3116            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(new_selections));
 3117            this.refresh_inline_completion(true, false, cx);
 3118        });
 3119    }
 3120
 3121    pub fn newline_above(&mut self, _: &NewlineAbove, cx: &mut ViewContext<Self>) {
 3122        let buffer = self.buffer.read(cx);
 3123        let snapshot = buffer.snapshot(cx);
 3124
 3125        let mut edits = Vec::new();
 3126        let mut rows = Vec::new();
 3127
 3128        for (rows_inserted, selection) in self.selections.all_adjusted(cx).into_iter().enumerate() {
 3129            let cursor = selection.head();
 3130            let row = cursor.row;
 3131
 3132            let start_of_line = snapshot.clip_point(Point::new(row, 0), Bias::Left);
 3133
 3134            let newline = "\n".to_string();
 3135            edits.push((start_of_line..start_of_line, newline));
 3136
 3137            rows.push(row + rows_inserted as u32);
 3138        }
 3139
 3140        self.transact(cx, |editor, cx| {
 3141            editor.edit(edits, cx);
 3142
 3143            editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
 3144                let mut index = 0;
 3145                s.move_cursors_with(|map, _, _| {
 3146                    let row = rows[index];
 3147                    index += 1;
 3148
 3149                    let point = Point::new(row, 0);
 3150                    let boundary = map.next_line_boundary(point).1;
 3151                    let clipped = map.clip_point(boundary, Bias::Left);
 3152
 3153                    (clipped, SelectionGoal::None)
 3154                });
 3155            });
 3156
 3157            let mut indent_edits = Vec::new();
 3158            let multibuffer_snapshot = editor.buffer.read(cx).snapshot(cx);
 3159            for row in rows {
 3160                let indents = multibuffer_snapshot.suggested_indents(row..row + 1, cx);
 3161                for (row, indent) in indents {
 3162                    if indent.len == 0 {
 3163                        continue;
 3164                    }
 3165
 3166                    let text = match indent.kind {
 3167                        IndentKind::Space => " ".repeat(indent.len as usize),
 3168                        IndentKind::Tab => "\t".repeat(indent.len as usize),
 3169                    };
 3170                    let point = Point::new(row.0, 0);
 3171                    indent_edits.push((point..point, text));
 3172                }
 3173            }
 3174            editor.edit(indent_edits, cx);
 3175        });
 3176    }
 3177
 3178    pub fn newline_below(&mut self, _: &NewlineBelow, cx: &mut ViewContext<Self>) {
 3179        let buffer = self.buffer.read(cx);
 3180        let snapshot = buffer.snapshot(cx);
 3181
 3182        let mut edits = Vec::new();
 3183        let mut rows = Vec::new();
 3184        let mut rows_inserted = 0;
 3185
 3186        for selection in self.selections.all_adjusted(cx) {
 3187            let cursor = selection.head();
 3188            let row = cursor.row;
 3189
 3190            let point = Point::new(row + 1, 0);
 3191            let start_of_line = snapshot.clip_point(point, Bias::Left);
 3192
 3193            let newline = "\n".to_string();
 3194            edits.push((start_of_line..start_of_line, newline));
 3195
 3196            rows_inserted += 1;
 3197            rows.push(row + rows_inserted);
 3198        }
 3199
 3200        self.transact(cx, |editor, cx| {
 3201            editor.edit(edits, cx);
 3202
 3203            editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
 3204                let mut index = 0;
 3205                s.move_cursors_with(|map, _, _| {
 3206                    let row = rows[index];
 3207                    index += 1;
 3208
 3209                    let point = Point::new(row, 0);
 3210                    let boundary = map.next_line_boundary(point).1;
 3211                    let clipped = map.clip_point(boundary, Bias::Left);
 3212
 3213                    (clipped, SelectionGoal::None)
 3214                });
 3215            });
 3216
 3217            let mut indent_edits = Vec::new();
 3218            let multibuffer_snapshot = editor.buffer.read(cx).snapshot(cx);
 3219            for row in rows {
 3220                let indents = multibuffer_snapshot.suggested_indents(row..row + 1, cx);
 3221                for (row, indent) in indents {
 3222                    if indent.len == 0 {
 3223                        continue;
 3224                    }
 3225
 3226                    let text = match indent.kind {
 3227                        IndentKind::Space => " ".repeat(indent.len as usize),
 3228                        IndentKind::Tab => "\t".repeat(indent.len as usize),
 3229                    };
 3230                    let point = Point::new(row.0, 0);
 3231                    indent_edits.push((point..point, text));
 3232                }
 3233            }
 3234            editor.edit(indent_edits, cx);
 3235        });
 3236    }
 3237
 3238    pub fn insert(&mut self, text: &str, cx: &mut ViewContext<Self>) {
 3239        let autoindent = text.is_empty().not().then(|| AutoindentMode::Block {
 3240            original_indent_columns: Vec::new(),
 3241        });
 3242        self.insert_with_autoindent_mode(text, autoindent, cx);
 3243    }
 3244
 3245    fn insert_with_autoindent_mode(
 3246        &mut self,
 3247        text: &str,
 3248        autoindent_mode: Option<AutoindentMode>,
 3249        cx: &mut ViewContext<Self>,
 3250    ) {
 3251        if self.read_only(cx) {
 3252            return;
 3253        }
 3254
 3255        let text: Arc<str> = text.into();
 3256        self.transact(cx, |this, cx| {
 3257            let old_selections = this.selections.all_adjusted(cx);
 3258            let selection_anchors = this.buffer.update(cx, |buffer, cx| {
 3259                let anchors = {
 3260                    let snapshot = buffer.read(cx);
 3261                    old_selections
 3262                        .iter()
 3263                        .map(|s| {
 3264                            let anchor = snapshot.anchor_after(s.head());
 3265                            s.map(|_| anchor)
 3266                        })
 3267                        .collect::<Vec<_>>()
 3268                };
 3269                buffer.edit(
 3270                    old_selections
 3271                        .iter()
 3272                        .map(|s| (s.start..s.end, text.clone())),
 3273                    autoindent_mode,
 3274                    cx,
 3275                );
 3276                anchors
 3277            });
 3278
 3279            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 3280                s.select_anchors(selection_anchors);
 3281            })
 3282        });
 3283    }
 3284
 3285    fn trigger_completion_on_input(
 3286        &mut self,
 3287        text: &str,
 3288        trigger_in_words: bool,
 3289        cx: &mut ViewContext<Self>,
 3290    ) {
 3291        if self.is_completion_trigger(text, trigger_in_words, cx) {
 3292            self.show_completions(
 3293                &ShowCompletions {
 3294                    trigger: Some(text.to_owned()).filter(|x| !x.is_empty()),
 3295                },
 3296                cx,
 3297            );
 3298        } else {
 3299            self.hide_context_menu(cx);
 3300        }
 3301    }
 3302
 3303    fn is_completion_trigger(
 3304        &self,
 3305        text: &str,
 3306        trigger_in_words: bool,
 3307        cx: &mut ViewContext<Self>,
 3308    ) -> bool {
 3309        let position = self.selections.newest_anchor().head();
 3310        let multibuffer = self.buffer.read(cx);
 3311        let Some(buffer) = position
 3312            .buffer_id
 3313            .and_then(|buffer_id| multibuffer.buffer(buffer_id).clone())
 3314        else {
 3315            return false;
 3316        };
 3317
 3318        if let Some(completion_provider) = &self.completion_provider {
 3319            completion_provider.is_completion_trigger(
 3320                &buffer,
 3321                position.text_anchor,
 3322                text,
 3323                trigger_in_words,
 3324                cx,
 3325            )
 3326        } else {
 3327            false
 3328        }
 3329    }
 3330
 3331    /// If any empty selections is touching the start of its innermost containing autoclose
 3332    /// region, expand it to select the brackets.
 3333    fn select_autoclose_pair(&mut self, cx: &mut ViewContext<Self>) {
 3334        let selections = self.selections.all::<usize>(cx);
 3335        let buffer = self.buffer.read(cx).read(cx);
 3336        let new_selections = self
 3337            .selections_with_autoclose_regions(selections, &buffer)
 3338            .map(|(mut selection, region)| {
 3339                if !selection.is_empty() {
 3340                    return selection;
 3341                }
 3342
 3343                if let Some(region) = region {
 3344                    let mut range = region.range.to_offset(&buffer);
 3345                    if selection.start == range.start && range.start >= region.pair.start.len() {
 3346                        range.start -= region.pair.start.len();
 3347                        if buffer.contains_str_at(range.start, &region.pair.start)
 3348                            && buffer.contains_str_at(range.end, &region.pair.end)
 3349                        {
 3350                            range.end += region.pair.end.len();
 3351                            selection.start = range.start;
 3352                            selection.end = range.end;
 3353
 3354                            return selection;
 3355                        }
 3356                    }
 3357                }
 3358
 3359                let always_treat_brackets_as_autoclosed = buffer
 3360                    .settings_at(selection.start, cx)
 3361                    .always_treat_brackets_as_autoclosed;
 3362
 3363                if !always_treat_brackets_as_autoclosed {
 3364                    return selection;
 3365                }
 3366
 3367                if let Some(scope) = buffer.language_scope_at(selection.start) {
 3368                    for (pair, enabled) in scope.brackets() {
 3369                        if !enabled || !pair.close {
 3370                            continue;
 3371                        }
 3372
 3373                        if buffer.contains_str_at(selection.start, &pair.end) {
 3374                            let pair_start_len = pair.start.len();
 3375                            if buffer.contains_str_at(
 3376                                selection.start.saturating_sub(pair_start_len),
 3377                                &pair.start,
 3378                            ) {
 3379                                selection.start -= pair_start_len;
 3380                                selection.end += pair.end.len();
 3381
 3382                                return selection;
 3383                            }
 3384                        }
 3385                    }
 3386                }
 3387
 3388                selection
 3389            })
 3390            .collect();
 3391
 3392        drop(buffer);
 3393        self.change_selections(None, cx, |selections| selections.select(new_selections));
 3394    }
 3395
 3396    /// Iterate the given selections, and for each one, find the smallest surrounding
 3397    /// autoclose region. This uses the ordering of the selections and the autoclose
 3398    /// regions to avoid repeated comparisons.
 3399    fn selections_with_autoclose_regions<'a, D: ToOffset + Clone>(
 3400        &'a self,
 3401        selections: impl IntoIterator<Item = Selection<D>>,
 3402        buffer: &'a MultiBufferSnapshot,
 3403    ) -> impl Iterator<Item = (Selection<D>, Option<&'a AutocloseRegion>)> {
 3404        let mut i = 0;
 3405        let mut regions = self.autoclose_regions.as_slice();
 3406        selections.into_iter().map(move |selection| {
 3407            let range = selection.start.to_offset(buffer)..selection.end.to_offset(buffer);
 3408
 3409            let mut enclosing = None;
 3410            while let Some(pair_state) = regions.get(i) {
 3411                if pair_state.range.end.to_offset(buffer) < range.start {
 3412                    regions = &regions[i + 1..];
 3413                    i = 0;
 3414                } else if pair_state.range.start.to_offset(buffer) > range.end {
 3415                    break;
 3416                } else {
 3417                    if pair_state.selection_id == selection.id {
 3418                        enclosing = Some(pair_state);
 3419                    }
 3420                    i += 1;
 3421                }
 3422            }
 3423
 3424            (selection, enclosing)
 3425        })
 3426    }
 3427
 3428    /// Remove any autoclose regions that no longer contain their selection.
 3429    fn invalidate_autoclose_regions(
 3430        &mut self,
 3431        mut selections: &[Selection<Anchor>],
 3432        buffer: &MultiBufferSnapshot,
 3433    ) {
 3434        self.autoclose_regions.retain(|state| {
 3435            let mut i = 0;
 3436            while let Some(selection) = selections.get(i) {
 3437                if selection.end.cmp(&state.range.start, buffer).is_lt() {
 3438                    selections = &selections[1..];
 3439                    continue;
 3440                }
 3441                if selection.start.cmp(&state.range.end, buffer).is_gt() {
 3442                    break;
 3443                }
 3444                if selection.id == state.selection_id {
 3445                    return true;
 3446                } else {
 3447                    i += 1;
 3448                }
 3449            }
 3450            false
 3451        });
 3452    }
 3453
 3454    fn completion_query(buffer: &MultiBufferSnapshot, position: impl ToOffset) -> Option<String> {
 3455        let offset = position.to_offset(buffer);
 3456        let (word_range, kind) = buffer.surrounding_word(offset, true);
 3457        if offset > word_range.start && kind == Some(CharKind::Word) {
 3458            Some(
 3459                buffer
 3460                    .text_for_range(word_range.start..offset)
 3461                    .collect::<String>(),
 3462            )
 3463        } else {
 3464            None
 3465        }
 3466    }
 3467
 3468    pub fn toggle_inlay_hints(&mut self, _: &ToggleInlayHints, cx: &mut ViewContext<Self>) {
 3469        self.refresh_inlay_hints(
 3470            InlayHintRefreshReason::Toggle(!self.inlay_hint_cache.enabled),
 3471            cx,
 3472        );
 3473    }
 3474
 3475    pub fn inlay_hints_enabled(&self) -> bool {
 3476        self.inlay_hint_cache.enabled
 3477    }
 3478
 3479    fn refresh_inlay_hints(&mut self, reason: InlayHintRefreshReason, cx: &mut ViewContext<Self>) {
 3480        if self.semantics_provider.is_none() || self.mode != EditorMode::Full {
 3481            return;
 3482        }
 3483
 3484        let reason_description = reason.description();
 3485        let ignore_debounce = matches!(
 3486            reason,
 3487            InlayHintRefreshReason::SettingsChange(_)
 3488                | InlayHintRefreshReason::Toggle(_)
 3489                | InlayHintRefreshReason::ExcerptsRemoved(_)
 3490        );
 3491        let (invalidate_cache, required_languages) = match reason {
 3492            InlayHintRefreshReason::Toggle(enabled) => {
 3493                self.inlay_hint_cache.enabled = enabled;
 3494                if enabled {
 3495                    (InvalidationStrategy::RefreshRequested, None)
 3496                } else {
 3497                    self.inlay_hint_cache.clear();
 3498                    self.splice_inlays(
 3499                        self.visible_inlay_hints(cx)
 3500                            .iter()
 3501                            .map(|inlay| inlay.id)
 3502                            .collect(),
 3503                        Vec::new(),
 3504                        cx,
 3505                    );
 3506                    return;
 3507                }
 3508            }
 3509            InlayHintRefreshReason::SettingsChange(new_settings) => {
 3510                match self.inlay_hint_cache.update_settings(
 3511                    &self.buffer,
 3512                    new_settings,
 3513                    self.visible_inlay_hints(cx),
 3514                    cx,
 3515                ) {
 3516                    ControlFlow::Break(Some(InlaySplice {
 3517                        to_remove,
 3518                        to_insert,
 3519                    })) => {
 3520                        self.splice_inlays(to_remove, to_insert, cx);
 3521                        return;
 3522                    }
 3523                    ControlFlow::Break(None) => return,
 3524                    ControlFlow::Continue(()) => (InvalidationStrategy::RefreshRequested, None),
 3525                }
 3526            }
 3527            InlayHintRefreshReason::ExcerptsRemoved(excerpts_removed) => {
 3528                if let Some(InlaySplice {
 3529                    to_remove,
 3530                    to_insert,
 3531                }) = self.inlay_hint_cache.remove_excerpts(excerpts_removed)
 3532                {
 3533                    self.splice_inlays(to_remove, to_insert, cx);
 3534                }
 3535                return;
 3536            }
 3537            InlayHintRefreshReason::NewLinesShown => (InvalidationStrategy::None, None),
 3538            InlayHintRefreshReason::BufferEdited(buffer_languages) => {
 3539                (InvalidationStrategy::BufferEdited, Some(buffer_languages))
 3540            }
 3541            InlayHintRefreshReason::RefreshRequested => {
 3542                (InvalidationStrategy::RefreshRequested, None)
 3543            }
 3544        };
 3545
 3546        if let Some(InlaySplice {
 3547            to_remove,
 3548            to_insert,
 3549        }) = self.inlay_hint_cache.spawn_hint_refresh(
 3550            reason_description,
 3551            self.excerpts_for_inlay_hints_query(required_languages.as_ref(), cx),
 3552            invalidate_cache,
 3553            ignore_debounce,
 3554            cx,
 3555        ) {
 3556            self.splice_inlays(to_remove, to_insert, cx);
 3557        }
 3558    }
 3559
 3560    fn visible_inlay_hints(&self, cx: &ViewContext<Editor>) -> Vec<Inlay> {
 3561        self.display_map
 3562            .read(cx)
 3563            .current_inlays()
 3564            .filter(move |inlay| matches!(inlay.id, InlayId::Hint(_)))
 3565            .cloned()
 3566            .collect()
 3567    }
 3568
 3569    pub fn excerpts_for_inlay_hints_query(
 3570        &self,
 3571        restrict_to_languages: Option<&HashSet<Arc<Language>>>,
 3572        cx: &mut ViewContext<Editor>,
 3573    ) -> HashMap<ExcerptId, (Model<Buffer>, clock::Global, Range<usize>)> {
 3574        let Some(project) = self.project.as_ref() else {
 3575            return HashMap::default();
 3576        };
 3577        let project = project.read(cx);
 3578        let multi_buffer = self.buffer().read(cx);
 3579        let multi_buffer_snapshot = multi_buffer.snapshot(cx);
 3580        let multi_buffer_visible_start = self
 3581            .scroll_manager
 3582            .anchor()
 3583            .anchor
 3584            .to_point(&multi_buffer_snapshot);
 3585        let multi_buffer_visible_end = multi_buffer_snapshot.clip_point(
 3586            multi_buffer_visible_start
 3587                + Point::new(self.visible_line_count().unwrap_or(0.).ceil() as u32, 0),
 3588            Bias::Left,
 3589        );
 3590        let multi_buffer_visible_range = multi_buffer_visible_start..multi_buffer_visible_end;
 3591        multi_buffer_snapshot
 3592            .range_to_buffer_ranges(multi_buffer_visible_range)
 3593            .into_iter()
 3594            .filter(|(_, excerpt_visible_range)| !excerpt_visible_range.is_empty())
 3595            .filter_map(|(excerpt, excerpt_visible_range)| {
 3596                let buffer_file = project::File::from_dyn(excerpt.buffer().file())?;
 3597                let buffer_worktree = project.worktree_for_id(buffer_file.worktree_id(cx), cx)?;
 3598                let worktree_entry = buffer_worktree
 3599                    .read(cx)
 3600                    .entry_for_id(buffer_file.project_entry_id(cx)?)?;
 3601                if worktree_entry.is_ignored {
 3602                    return None;
 3603                }
 3604
 3605                let language = excerpt.buffer().language()?;
 3606                if let Some(restrict_to_languages) = restrict_to_languages {
 3607                    if !restrict_to_languages.contains(language) {
 3608                        return None;
 3609                    }
 3610                }
 3611                Some((
 3612                    excerpt.id(),
 3613                    (
 3614                        multi_buffer.buffer(excerpt.buffer_id()).unwrap(),
 3615                        excerpt.buffer().version().clone(),
 3616                        excerpt_visible_range,
 3617                    ),
 3618                ))
 3619            })
 3620            .collect()
 3621    }
 3622
 3623    pub fn text_layout_details(&self, cx: &WindowContext) -> TextLayoutDetails {
 3624        TextLayoutDetails {
 3625            text_system: cx.text_system().clone(),
 3626            editor_style: self.style.clone().unwrap(),
 3627            rem_size: cx.rem_size(),
 3628            scroll_anchor: self.scroll_manager.anchor(),
 3629            visible_rows: self.visible_line_count(),
 3630            vertical_scroll_margin: self.scroll_manager.vertical_scroll_margin,
 3631        }
 3632    }
 3633
 3634    pub fn splice_inlays(
 3635        &self,
 3636        to_remove: Vec<InlayId>,
 3637        to_insert: Vec<Inlay>,
 3638        cx: &mut ViewContext<Self>,
 3639    ) {
 3640        self.display_map.update(cx, |display_map, cx| {
 3641            display_map.splice_inlays(to_remove, to_insert, cx)
 3642        });
 3643        cx.notify();
 3644    }
 3645
 3646    fn trigger_on_type_formatting(
 3647        &self,
 3648        input: String,
 3649        cx: &mut ViewContext<Self>,
 3650    ) -> Option<Task<Result<()>>> {
 3651        if input.len() != 1 {
 3652            return None;
 3653        }
 3654
 3655        let project = self.project.as_ref()?;
 3656        let position = self.selections.newest_anchor().head();
 3657        let (buffer, buffer_position) = self
 3658            .buffer
 3659            .read(cx)
 3660            .text_anchor_for_position(position, cx)?;
 3661
 3662        let settings = language_settings::language_settings(
 3663            buffer
 3664                .read(cx)
 3665                .language_at(buffer_position)
 3666                .map(|l| l.name()),
 3667            buffer.read(cx).file(),
 3668            cx,
 3669        );
 3670        if !settings.use_on_type_format {
 3671            return None;
 3672        }
 3673
 3674        // OnTypeFormatting returns a list of edits, no need to pass them between Zed instances,
 3675        // hence we do LSP request & edit on host side only — add formats to host's history.
 3676        let push_to_lsp_host_history = true;
 3677        // If this is not the host, append its history with new edits.
 3678        let push_to_client_history = project.read(cx).is_via_collab();
 3679
 3680        let on_type_formatting = project.update(cx, |project, cx| {
 3681            project.on_type_format(
 3682                buffer.clone(),
 3683                buffer_position,
 3684                input,
 3685                push_to_lsp_host_history,
 3686                cx,
 3687            )
 3688        });
 3689        Some(cx.spawn(|editor, mut cx| async move {
 3690            if let Some(transaction) = on_type_formatting.await? {
 3691                if push_to_client_history {
 3692                    buffer
 3693                        .update(&mut cx, |buffer, _| {
 3694                            buffer.push_transaction(transaction, Instant::now());
 3695                        })
 3696                        .ok();
 3697                }
 3698                editor.update(&mut cx, |editor, cx| {
 3699                    editor.refresh_document_highlights(cx);
 3700                })?;
 3701            }
 3702            Ok(())
 3703        }))
 3704    }
 3705
 3706    pub fn show_completions(&mut self, options: &ShowCompletions, cx: &mut ViewContext<Self>) {
 3707        if self.pending_rename.is_some() {
 3708            return;
 3709        }
 3710
 3711        let Some(provider) = self.completion_provider.as_ref() else {
 3712            return;
 3713        };
 3714
 3715        if !self.snippet_stack.is_empty() && self.context_menu.borrow().as_ref().is_some() {
 3716            return;
 3717        }
 3718
 3719        let position = self.selections.newest_anchor().head();
 3720        let (buffer, buffer_position) =
 3721            if let Some(output) = self.buffer.read(cx).text_anchor_for_position(position, cx) {
 3722                output
 3723            } else {
 3724                return;
 3725            };
 3726        let show_completion_documentation = buffer
 3727            .read(cx)
 3728            .snapshot()
 3729            .settings_at(buffer_position, cx)
 3730            .show_completion_documentation;
 3731
 3732        let query = Self::completion_query(&self.buffer.read(cx).read(cx), position);
 3733
 3734        let trigger_kind = match &options.trigger {
 3735            Some(trigger) if buffer.read(cx).completion_triggers().contains(trigger) => {
 3736                CompletionTriggerKind::TRIGGER_CHARACTER
 3737            }
 3738            _ => CompletionTriggerKind::INVOKED,
 3739        };
 3740        let completion_context = CompletionContext {
 3741            trigger_character: options.trigger.as_ref().and_then(|trigger| {
 3742                if trigger_kind == CompletionTriggerKind::TRIGGER_CHARACTER {
 3743                    Some(String::from(trigger))
 3744                } else {
 3745                    None
 3746                }
 3747            }),
 3748            trigger_kind,
 3749        };
 3750        let completions = provider.completions(&buffer, buffer_position, completion_context, cx);
 3751        let sort_completions = provider.sort_completions();
 3752
 3753        let id = post_inc(&mut self.next_completion_id);
 3754        let task = cx.spawn(|editor, mut cx| {
 3755            async move {
 3756                editor.update(&mut cx, |this, _| {
 3757                    this.completion_tasks.retain(|(task_id, _)| *task_id >= id);
 3758                })?;
 3759                let completions = completions.await.log_err();
 3760                let menu = if let Some(completions) = completions {
 3761                    let mut menu = CompletionsMenu::new(
 3762                        id,
 3763                        sort_completions,
 3764                        show_completion_documentation,
 3765                        position,
 3766                        buffer.clone(),
 3767                        completions.into(),
 3768                    );
 3769
 3770                    menu.filter(query.as_deref(), cx.background_executor().clone())
 3771                        .await;
 3772
 3773                    menu.visible().then_some(menu)
 3774                } else {
 3775                    None
 3776                };
 3777
 3778                editor.update(&mut cx, |editor, cx| {
 3779                    match editor.context_menu.borrow().as_ref() {
 3780                        None => {}
 3781                        Some(CodeContextMenu::Completions(prev_menu)) => {
 3782                            if prev_menu.id > id {
 3783                                return;
 3784                            }
 3785                        }
 3786                        _ => return,
 3787                    }
 3788
 3789                    if editor.focus_handle.is_focused(cx) && menu.is_some() {
 3790                        let mut menu = menu.unwrap();
 3791                        menu.resolve_visible_completions(editor.completion_provider.as_deref(), cx);
 3792
 3793                        if editor.show_inline_completions_in_menu(cx) {
 3794                            if let Some(hint) = editor.inline_completion_menu_hint(cx) {
 3795                                menu.show_inline_completion_hint(hint);
 3796                            }
 3797                        } else {
 3798                            editor.discard_inline_completion(false, cx);
 3799                        }
 3800
 3801                        *editor.context_menu.borrow_mut() =
 3802                            Some(CodeContextMenu::Completions(menu));
 3803
 3804                        cx.notify();
 3805                    } else if editor.completion_tasks.len() <= 1 {
 3806                        // If there are no more completion tasks and the last menu was
 3807                        // empty, we should hide it.
 3808                        let was_hidden = editor.hide_context_menu(cx).is_none();
 3809                        // If it was already hidden and we don't show inline
 3810                        // completions in the menu, we should also show the
 3811                        // inline-completion when available.
 3812                        if was_hidden && editor.show_inline_completions_in_menu(cx) {
 3813                            editor.update_visible_inline_completion(cx);
 3814                        }
 3815                    }
 3816                })?;
 3817
 3818                Ok::<_, anyhow::Error>(())
 3819            }
 3820            .log_err()
 3821        });
 3822
 3823        self.completion_tasks.push((id, task));
 3824    }
 3825
 3826    pub fn confirm_completion(
 3827        &mut self,
 3828        action: &ConfirmCompletion,
 3829        cx: &mut ViewContext<Self>,
 3830    ) -> Option<Task<Result<()>>> {
 3831        self.do_completion(action.item_ix, CompletionIntent::Complete, cx)
 3832    }
 3833
 3834    pub fn compose_completion(
 3835        &mut self,
 3836        action: &ComposeCompletion,
 3837        cx: &mut ViewContext<Self>,
 3838    ) -> Option<Task<Result<()>>> {
 3839        self.do_completion(action.item_ix, CompletionIntent::Compose, cx)
 3840    }
 3841
 3842    fn toggle_zed_predict_tos(&mut self, cx: &mut ViewContext<Self>) {
 3843        let (Some(workspace), Some(project)) = (self.workspace(), self.project.as_ref()) else {
 3844            return;
 3845        };
 3846
 3847        ZedPredictTos::toggle(workspace, project.read(cx).user_store().clone(), cx);
 3848    }
 3849
 3850    fn do_completion(
 3851        &mut self,
 3852        item_ix: Option<usize>,
 3853        intent: CompletionIntent,
 3854        cx: &mut ViewContext<Editor>,
 3855    ) -> Option<Task<std::result::Result<(), anyhow::Error>>> {
 3856        use language::ToOffset as _;
 3857
 3858        {
 3859            let context_menu = self.context_menu.borrow();
 3860            if let CodeContextMenu::Completions(menu) = context_menu.as_ref()? {
 3861                let entries = menu.entries.borrow();
 3862                let entry = entries.get(item_ix.unwrap_or(menu.selected_item));
 3863                match entry {
 3864                    Some(CompletionEntry::InlineCompletionHint(
 3865                        InlineCompletionMenuHint::Loading,
 3866                    )) => return Some(Task::ready(Ok(()))),
 3867                    Some(CompletionEntry::InlineCompletionHint(InlineCompletionMenuHint::None)) => {
 3868                        drop(entries);
 3869                        drop(context_menu);
 3870                        self.context_menu_next(&Default::default(), cx);
 3871                        return Some(Task::ready(Ok(())));
 3872                    }
 3873                    Some(CompletionEntry::InlineCompletionHint(
 3874                        InlineCompletionMenuHint::PendingTermsAcceptance,
 3875                    )) => {
 3876                        drop(entries);
 3877                        drop(context_menu);
 3878                        self.toggle_zed_predict_tos(cx);
 3879                        return Some(Task::ready(Ok(())));
 3880                    }
 3881                    _ => {}
 3882                }
 3883            }
 3884        }
 3885
 3886        let completions_menu =
 3887            if let CodeContextMenu::Completions(menu) = self.hide_context_menu(cx)? {
 3888                menu
 3889            } else {
 3890                return None;
 3891            };
 3892
 3893        let entries = completions_menu.entries.borrow();
 3894        let mat = entries.get(item_ix.unwrap_or(completions_menu.selected_item))?;
 3895        let mat = match mat {
 3896            CompletionEntry::InlineCompletionHint(_) => {
 3897                self.accept_inline_completion(&AcceptInlineCompletion, cx);
 3898                cx.stop_propagation();
 3899                return Some(Task::ready(Ok(())));
 3900            }
 3901            CompletionEntry::Match(mat) => {
 3902                if self.show_inline_completions_in_menu(cx) {
 3903                    self.discard_inline_completion(true, cx);
 3904                }
 3905                mat
 3906            }
 3907        };
 3908        let candidate_id = mat.candidate_id;
 3909        drop(entries);
 3910
 3911        let buffer_handle = completions_menu.buffer;
 3912        let completion = completions_menu
 3913            .completions
 3914            .borrow()
 3915            .get(candidate_id)?
 3916            .clone();
 3917        cx.stop_propagation();
 3918
 3919        let snippet;
 3920        let text;
 3921
 3922        if completion.is_snippet() {
 3923            snippet = Some(Snippet::parse(&completion.new_text).log_err()?);
 3924            text = snippet.as_ref().unwrap().text.clone();
 3925        } else {
 3926            snippet = None;
 3927            text = completion.new_text.clone();
 3928        };
 3929        let selections = self.selections.all::<usize>(cx);
 3930        let buffer = buffer_handle.read(cx);
 3931        let old_range = completion.old_range.to_offset(buffer);
 3932        let old_text = buffer.text_for_range(old_range.clone()).collect::<String>();
 3933
 3934        let newest_selection = self.selections.newest_anchor();
 3935        if newest_selection.start.buffer_id != Some(buffer_handle.read(cx).remote_id()) {
 3936            return None;
 3937        }
 3938
 3939        let lookbehind = newest_selection
 3940            .start
 3941            .text_anchor
 3942            .to_offset(buffer)
 3943            .saturating_sub(old_range.start);
 3944        let lookahead = old_range
 3945            .end
 3946            .saturating_sub(newest_selection.end.text_anchor.to_offset(buffer));
 3947        let mut common_prefix_len = old_text
 3948            .bytes()
 3949            .zip(text.bytes())
 3950            .take_while(|(a, b)| a == b)
 3951            .count();
 3952
 3953        let snapshot = self.buffer.read(cx).snapshot(cx);
 3954        let mut range_to_replace: Option<Range<isize>> = None;
 3955        let mut ranges = Vec::new();
 3956        let mut linked_edits = HashMap::<_, Vec<_>>::default();
 3957        for selection in &selections {
 3958            if snapshot.contains_str_at(selection.start.saturating_sub(lookbehind), &old_text) {
 3959                let start = selection.start.saturating_sub(lookbehind);
 3960                let end = selection.end + lookahead;
 3961                if selection.id == newest_selection.id {
 3962                    range_to_replace = Some(
 3963                        ((start + common_prefix_len) as isize - selection.start as isize)
 3964                            ..(end as isize - selection.start as isize),
 3965                    );
 3966                }
 3967                ranges.push(start + common_prefix_len..end);
 3968            } else {
 3969                common_prefix_len = 0;
 3970                ranges.clear();
 3971                ranges.extend(selections.iter().map(|s| {
 3972                    if s.id == newest_selection.id {
 3973                        range_to_replace = Some(
 3974                            old_range.start.to_offset_utf16(&snapshot).0 as isize
 3975                                - selection.start as isize
 3976                                ..old_range.end.to_offset_utf16(&snapshot).0 as isize
 3977                                    - selection.start as isize,
 3978                        );
 3979                        old_range.clone()
 3980                    } else {
 3981                        s.start..s.end
 3982                    }
 3983                }));
 3984                break;
 3985            }
 3986            if !self.linked_edit_ranges.is_empty() {
 3987                let start_anchor = snapshot.anchor_before(selection.head());
 3988                let end_anchor = snapshot.anchor_after(selection.tail());
 3989                if let Some(ranges) = self
 3990                    .linked_editing_ranges_for(start_anchor.text_anchor..end_anchor.text_anchor, cx)
 3991                {
 3992                    for (buffer, edits) in ranges {
 3993                        linked_edits.entry(buffer.clone()).or_default().extend(
 3994                            edits
 3995                                .into_iter()
 3996                                .map(|range| (range, text[common_prefix_len..].to_owned())),
 3997                        );
 3998                    }
 3999                }
 4000            }
 4001        }
 4002        let text = &text[common_prefix_len..];
 4003
 4004        cx.emit(EditorEvent::InputHandled {
 4005            utf16_range_to_replace: range_to_replace,
 4006            text: text.into(),
 4007        });
 4008
 4009        self.transact(cx, |this, cx| {
 4010            if let Some(mut snippet) = snippet {
 4011                snippet.text = text.to_string();
 4012                for tabstop in snippet
 4013                    .tabstops
 4014                    .iter_mut()
 4015                    .flat_map(|tabstop| tabstop.ranges.iter_mut())
 4016                {
 4017                    tabstop.start -= common_prefix_len as isize;
 4018                    tabstop.end -= common_prefix_len as isize;
 4019                }
 4020
 4021                this.insert_snippet(&ranges, snippet, cx).log_err();
 4022            } else {
 4023                this.buffer.update(cx, |buffer, cx| {
 4024                    buffer.edit(
 4025                        ranges.iter().map(|range| (range.clone(), text)),
 4026                        this.autoindent_mode.clone(),
 4027                        cx,
 4028                    );
 4029                });
 4030            }
 4031            for (buffer, edits) in linked_edits {
 4032                buffer.update(cx, |buffer, cx| {
 4033                    let snapshot = buffer.snapshot();
 4034                    let edits = edits
 4035                        .into_iter()
 4036                        .map(|(range, text)| {
 4037                            use text::ToPoint as TP;
 4038                            let end_point = TP::to_point(&range.end, &snapshot);
 4039                            let start_point = TP::to_point(&range.start, &snapshot);
 4040                            (start_point..end_point, text)
 4041                        })
 4042                        .sorted_by_key(|(range, _)| range.start)
 4043                        .collect::<Vec<_>>();
 4044                    buffer.edit(edits, None, cx);
 4045                })
 4046            }
 4047
 4048            this.refresh_inline_completion(true, false, cx);
 4049        });
 4050
 4051        let show_new_completions_on_confirm = completion
 4052            .confirm
 4053            .as_ref()
 4054            .map_or(false, |confirm| confirm(intent, cx));
 4055        if show_new_completions_on_confirm {
 4056            self.show_completions(&ShowCompletions { trigger: None }, cx);
 4057        }
 4058
 4059        let provider = self.completion_provider.as_ref()?;
 4060        drop(completion);
 4061        let apply_edits = provider.apply_additional_edits_for_completion(
 4062            buffer_handle,
 4063            completions_menu.completions.clone(),
 4064            candidate_id,
 4065            true,
 4066            cx,
 4067        );
 4068
 4069        let editor_settings = EditorSettings::get_global(cx);
 4070        if editor_settings.show_signature_help_after_edits || editor_settings.auto_signature_help {
 4071            // After the code completion is finished, users often want to know what signatures are needed.
 4072            // so we should automatically call signature_help
 4073            self.show_signature_help(&ShowSignatureHelp, cx);
 4074        }
 4075
 4076        Some(cx.foreground_executor().spawn(async move {
 4077            apply_edits.await?;
 4078            Ok(())
 4079        }))
 4080    }
 4081
 4082    pub fn toggle_code_actions(&mut self, action: &ToggleCodeActions, cx: &mut ViewContext<Self>) {
 4083        let mut context_menu = self.context_menu.borrow_mut();
 4084        if let Some(CodeContextMenu::CodeActions(code_actions)) = context_menu.as_ref() {
 4085            if code_actions.deployed_from_indicator == action.deployed_from_indicator {
 4086                // Toggle if we're selecting the same one
 4087                *context_menu = None;
 4088                cx.notify();
 4089                return;
 4090            } else {
 4091                // Otherwise, clear it and start a new one
 4092                *context_menu = None;
 4093                cx.notify();
 4094            }
 4095        }
 4096        drop(context_menu);
 4097        let snapshot = self.snapshot(cx);
 4098        let deployed_from_indicator = action.deployed_from_indicator;
 4099        let mut task = self.code_actions_task.take();
 4100        let action = action.clone();
 4101        cx.spawn(|editor, mut cx| async move {
 4102            while let Some(prev_task) = task {
 4103                prev_task.await.log_err();
 4104                task = editor.update(&mut cx, |this, _| this.code_actions_task.take())?;
 4105            }
 4106
 4107            let spawned_test_task = editor.update(&mut cx, |editor, cx| {
 4108                if editor.focus_handle.is_focused(cx) {
 4109                    let multibuffer_point = action
 4110                        .deployed_from_indicator
 4111                        .map(|row| DisplayPoint::new(row, 0).to_point(&snapshot))
 4112                        .unwrap_or_else(|| editor.selections.newest::<Point>(cx).head());
 4113                    let (buffer, buffer_row) = snapshot
 4114                        .buffer_snapshot
 4115                        .buffer_line_for_row(MultiBufferRow(multibuffer_point.row))
 4116                        .and_then(|(buffer_snapshot, range)| {
 4117                            editor
 4118                                .buffer
 4119                                .read(cx)
 4120                                .buffer(buffer_snapshot.remote_id())
 4121                                .map(|buffer| (buffer, range.start.row))
 4122                        })?;
 4123                    let (_, code_actions) = editor
 4124                        .available_code_actions
 4125                        .clone()
 4126                        .and_then(|(location, code_actions)| {
 4127                            let snapshot = location.buffer.read(cx).snapshot();
 4128                            let point_range = location.range.to_point(&snapshot);
 4129                            let point_range = point_range.start.row..=point_range.end.row;
 4130                            if point_range.contains(&buffer_row) {
 4131                                Some((location, code_actions))
 4132                            } else {
 4133                                None
 4134                            }
 4135                        })
 4136                        .unzip();
 4137                    let buffer_id = buffer.read(cx).remote_id();
 4138                    let tasks = editor
 4139                        .tasks
 4140                        .get(&(buffer_id, buffer_row))
 4141                        .map(|t| Arc::new(t.to_owned()));
 4142                    if tasks.is_none() && code_actions.is_none() {
 4143                        return None;
 4144                    }
 4145
 4146                    editor.completion_tasks.clear();
 4147                    editor.discard_inline_completion(false, cx);
 4148                    let task_context =
 4149                        tasks
 4150                            .as_ref()
 4151                            .zip(editor.project.clone())
 4152                            .map(|(tasks, project)| {
 4153                                Self::build_tasks_context(&project, &buffer, buffer_row, tasks, cx)
 4154                            });
 4155
 4156                    Some(cx.spawn(|editor, mut cx| async move {
 4157                        let task_context = match task_context {
 4158                            Some(task_context) => task_context.await,
 4159                            None => None,
 4160                        };
 4161                        let resolved_tasks =
 4162                            tasks.zip(task_context).map(|(tasks, task_context)| {
 4163                                Rc::new(ResolvedTasks {
 4164                                    templates: tasks.resolve(&task_context).collect(),
 4165                                    position: snapshot.buffer_snapshot.anchor_before(Point::new(
 4166                                        multibuffer_point.row,
 4167                                        tasks.column,
 4168                                    )),
 4169                                })
 4170                            });
 4171                        let spawn_straight_away = resolved_tasks
 4172                            .as_ref()
 4173                            .map_or(false, |tasks| tasks.templates.len() == 1)
 4174                            && code_actions
 4175                                .as_ref()
 4176                                .map_or(true, |actions| actions.is_empty());
 4177                        if let Ok(task) = editor.update(&mut cx, |editor, cx| {
 4178                            *editor.context_menu.borrow_mut() =
 4179                                Some(CodeContextMenu::CodeActions(CodeActionsMenu {
 4180                                    buffer,
 4181                                    actions: CodeActionContents {
 4182                                        tasks: resolved_tasks,
 4183                                        actions: code_actions,
 4184                                    },
 4185                                    selected_item: Default::default(),
 4186                                    scroll_handle: UniformListScrollHandle::default(),
 4187                                    deployed_from_indicator,
 4188                                }));
 4189                            if spawn_straight_away {
 4190                                if let Some(task) = editor.confirm_code_action(
 4191                                    &ConfirmCodeAction { item_ix: Some(0) },
 4192                                    cx,
 4193                                ) {
 4194                                    cx.notify();
 4195                                    return task;
 4196                                }
 4197                            }
 4198                            cx.notify();
 4199                            Task::ready(Ok(()))
 4200                        }) {
 4201                            task.await
 4202                        } else {
 4203                            Ok(())
 4204                        }
 4205                    }))
 4206                } else {
 4207                    Some(Task::ready(Ok(())))
 4208                }
 4209            })?;
 4210            if let Some(task) = spawned_test_task {
 4211                task.await?;
 4212            }
 4213
 4214            Ok::<_, anyhow::Error>(())
 4215        })
 4216        .detach_and_log_err(cx);
 4217    }
 4218
 4219    pub fn confirm_code_action(
 4220        &mut self,
 4221        action: &ConfirmCodeAction,
 4222        cx: &mut ViewContext<Self>,
 4223    ) -> Option<Task<Result<()>>> {
 4224        let actions_menu = if let CodeContextMenu::CodeActions(menu) = self.hide_context_menu(cx)? {
 4225            menu
 4226        } else {
 4227            return None;
 4228        };
 4229        let action_ix = action.item_ix.unwrap_or(actions_menu.selected_item);
 4230        let action = actions_menu.actions.get(action_ix)?;
 4231        let title = action.label();
 4232        let buffer = actions_menu.buffer;
 4233        let workspace = self.workspace()?;
 4234
 4235        match action {
 4236            CodeActionsItem::Task(task_source_kind, resolved_task) => {
 4237                workspace.update(cx, |workspace, cx| {
 4238                    workspace::tasks::schedule_resolved_task(
 4239                        workspace,
 4240                        task_source_kind,
 4241                        resolved_task,
 4242                        false,
 4243                        cx,
 4244                    );
 4245
 4246                    Some(Task::ready(Ok(())))
 4247                })
 4248            }
 4249            CodeActionsItem::CodeAction {
 4250                excerpt_id,
 4251                action,
 4252                provider,
 4253            } => {
 4254                let apply_code_action =
 4255                    provider.apply_code_action(buffer, action, excerpt_id, true, cx);
 4256                let workspace = workspace.downgrade();
 4257                Some(cx.spawn(|editor, cx| async move {
 4258                    let project_transaction = apply_code_action.await?;
 4259                    Self::open_project_transaction(
 4260                        &editor,
 4261                        workspace,
 4262                        project_transaction,
 4263                        title,
 4264                        cx,
 4265                    )
 4266                    .await
 4267                }))
 4268            }
 4269        }
 4270    }
 4271
 4272    pub async fn open_project_transaction(
 4273        this: &WeakView<Editor>,
 4274        workspace: WeakView<Workspace>,
 4275        transaction: ProjectTransaction,
 4276        title: String,
 4277        mut cx: AsyncWindowContext,
 4278    ) -> Result<()> {
 4279        let mut entries = transaction.0.into_iter().collect::<Vec<_>>();
 4280        cx.update(|cx| {
 4281            entries.sort_unstable_by_key(|(buffer, _)| {
 4282                buffer.read(cx).file().map(|f| f.path().clone())
 4283            });
 4284        })?;
 4285
 4286        // If the project transaction's edits are all contained within this editor, then
 4287        // avoid opening a new editor to display them.
 4288
 4289        if let Some((buffer, transaction)) = entries.first() {
 4290            if entries.len() == 1 {
 4291                let excerpt = this.update(&mut cx, |editor, cx| {
 4292                    editor
 4293                        .buffer()
 4294                        .read(cx)
 4295                        .excerpt_containing(editor.selections.newest_anchor().head(), cx)
 4296                })?;
 4297                if let Some((_, excerpted_buffer, excerpt_range)) = excerpt {
 4298                    if excerpted_buffer == *buffer {
 4299                        let all_edits_within_excerpt = buffer.read_with(&cx, |buffer, _| {
 4300                            let excerpt_range = excerpt_range.to_offset(buffer);
 4301                            buffer
 4302                                .edited_ranges_for_transaction::<usize>(transaction)
 4303                                .all(|range| {
 4304                                    excerpt_range.start <= range.start
 4305                                        && excerpt_range.end >= range.end
 4306                                })
 4307                        })?;
 4308
 4309                        if all_edits_within_excerpt {
 4310                            return Ok(());
 4311                        }
 4312                    }
 4313                }
 4314            }
 4315        } else {
 4316            return Ok(());
 4317        }
 4318
 4319        let mut ranges_to_highlight = Vec::new();
 4320        let excerpt_buffer = cx.new_model(|cx| {
 4321            let mut multibuffer = MultiBuffer::new(Capability::ReadWrite).with_title(title);
 4322            for (buffer_handle, transaction) in &entries {
 4323                let buffer = buffer_handle.read(cx);
 4324                ranges_to_highlight.extend(
 4325                    multibuffer.push_excerpts_with_context_lines(
 4326                        buffer_handle.clone(),
 4327                        buffer
 4328                            .edited_ranges_for_transaction::<usize>(transaction)
 4329                            .collect(),
 4330                        DEFAULT_MULTIBUFFER_CONTEXT,
 4331                        cx,
 4332                    ),
 4333                );
 4334            }
 4335            multibuffer.push_transaction(entries.iter().map(|(b, t)| (b, t)), cx);
 4336            multibuffer
 4337        })?;
 4338
 4339        workspace.update(&mut cx, |workspace, cx| {
 4340            let project = workspace.project().clone();
 4341            let editor =
 4342                cx.new_view(|cx| Editor::for_multibuffer(excerpt_buffer, Some(project), true, cx));
 4343            workspace.add_item_to_active_pane(Box::new(editor.clone()), None, true, cx);
 4344            editor.update(cx, |editor, cx| {
 4345                editor.highlight_background::<Self>(
 4346                    &ranges_to_highlight,
 4347                    |theme| theme.editor_highlighted_line_background,
 4348                    cx,
 4349                );
 4350            });
 4351        })?;
 4352
 4353        Ok(())
 4354    }
 4355
 4356    pub fn clear_code_action_providers(&mut self) {
 4357        self.code_action_providers.clear();
 4358        self.available_code_actions.take();
 4359    }
 4360
 4361    pub fn add_code_action_provider(
 4362        &mut self,
 4363        provider: Rc<dyn CodeActionProvider>,
 4364        cx: &mut ViewContext<Self>,
 4365    ) {
 4366        if self
 4367            .code_action_providers
 4368            .iter()
 4369            .any(|existing_provider| existing_provider.id() == provider.id())
 4370        {
 4371            return;
 4372        }
 4373
 4374        self.code_action_providers.push(provider);
 4375        self.refresh_code_actions(cx);
 4376    }
 4377
 4378    pub fn remove_code_action_provider(&mut self, id: Arc<str>, cx: &mut ViewContext<Self>) {
 4379        self.code_action_providers
 4380            .retain(|provider| provider.id() != id);
 4381        self.refresh_code_actions(cx);
 4382    }
 4383
 4384    fn refresh_code_actions(&mut self, cx: &mut ViewContext<Self>) -> Option<()> {
 4385        let buffer = self.buffer.read(cx);
 4386        let newest_selection = self.selections.newest_anchor().clone();
 4387        let (start_buffer, start) = buffer.text_anchor_for_position(newest_selection.start, cx)?;
 4388        let (end_buffer, end) = buffer.text_anchor_for_position(newest_selection.end, cx)?;
 4389        if start_buffer != end_buffer {
 4390            return None;
 4391        }
 4392
 4393        self.code_actions_task = Some(cx.spawn(|this, mut cx| async move {
 4394            cx.background_executor()
 4395                .timer(CODE_ACTIONS_DEBOUNCE_TIMEOUT)
 4396                .await;
 4397
 4398            let (providers, tasks) = this.update(&mut cx, |this, cx| {
 4399                let providers = this.code_action_providers.clone();
 4400                let tasks = this
 4401                    .code_action_providers
 4402                    .iter()
 4403                    .map(|provider| provider.code_actions(&start_buffer, start..end, cx))
 4404                    .collect::<Vec<_>>();
 4405                (providers, tasks)
 4406            })?;
 4407
 4408            let mut actions = Vec::new();
 4409            for (provider, provider_actions) in
 4410                providers.into_iter().zip(future::join_all(tasks).await)
 4411            {
 4412                if let Some(provider_actions) = provider_actions.log_err() {
 4413                    actions.extend(provider_actions.into_iter().map(|action| {
 4414                        AvailableCodeAction {
 4415                            excerpt_id: newest_selection.start.excerpt_id,
 4416                            action,
 4417                            provider: provider.clone(),
 4418                        }
 4419                    }));
 4420                }
 4421            }
 4422
 4423            this.update(&mut cx, |this, cx| {
 4424                this.available_code_actions = if actions.is_empty() {
 4425                    None
 4426                } else {
 4427                    Some((
 4428                        Location {
 4429                            buffer: start_buffer,
 4430                            range: start..end,
 4431                        },
 4432                        actions.into(),
 4433                    ))
 4434                };
 4435                cx.notify();
 4436            })
 4437        }));
 4438        None
 4439    }
 4440
 4441    fn start_inline_blame_timer(&mut self, cx: &mut ViewContext<Self>) {
 4442        if let Some(delay) = ProjectSettings::get_global(cx).git.inline_blame_delay() {
 4443            self.show_git_blame_inline = false;
 4444
 4445            self.show_git_blame_inline_delay_task = Some(cx.spawn(|this, mut cx| async move {
 4446                cx.background_executor().timer(delay).await;
 4447
 4448                this.update(&mut cx, |this, cx| {
 4449                    this.show_git_blame_inline = true;
 4450                    cx.notify();
 4451                })
 4452                .log_err();
 4453            }));
 4454        }
 4455    }
 4456
 4457    fn refresh_document_highlights(&mut self, cx: &mut ViewContext<Self>) -> Option<()> {
 4458        if self.pending_rename.is_some() {
 4459            return None;
 4460        }
 4461
 4462        let provider = self.semantics_provider.clone()?;
 4463        let buffer = self.buffer.read(cx);
 4464        let newest_selection = self.selections.newest_anchor().clone();
 4465        let cursor_position = newest_selection.head();
 4466        let (cursor_buffer, cursor_buffer_position) =
 4467            buffer.text_anchor_for_position(cursor_position, cx)?;
 4468        let (tail_buffer, _) = buffer.text_anchor_for_position(newest_selection.tail(), cx)?;
 4469        if cursor_buffer != tail_buffer {
 4470            return None;
 4471        }
 4472        let debounce = EditorSettings::get_global(cx).lsp_highlight_debounce;
 4473        self.document_highlights_task = Some(cx.spawn(|this, mut cx| async move {
 4474            cx.background_executor()
 4475                .timer(Duration::from_millis(debounce))
 4476                .await;
 4477
 4478            let highlights = if let Some(highlights) = cx
 4479                .update(|cx| {
 4480                    provider.document_highlights(&cursor_buffer, cursor_buffer_position, cx)
 4481                })
 4482                .ok()
 4483                .flatten()
 4484            {
 4485                highlights.await.log_err()
 4486            } else {
 4487                None
 4488            };
 4489
 4490            if let Some(highlights) = highlights {
 4491                this.update(&mut cx, |this, cx| {
 4492                    if this.pending_rename.is_some() {
 4493                        return;
 4494                    }
 4495
 4496                    let buffer_id = cursor_position.buffer_id;
 4497                    let buffer = this.buffer.read(cx);
 4498                    if !buffer
 4499                        .text_anchor_for_position(cursor_position, cx)
 4500                        .map_or(false, |(buffer, _)| buffer == cursor_buffer)
 4501                    {
 4502                        return;
 4503                    }
 4504
 4505                    let cursor_buffer_snapshot = cursor_buffer.read(cx);
 4506                    let mut write_ranges = Vec::new();
 4507                    let mut read_ranges = Vec::new();
 4508                    for highlight in highlights {
 4509                        for (excerpt_id, excerpt_range) in
 4510                            buffer.excerpts_for_buffer(&cursor_buffer, cx)
 4511                        {
 4512                            let start = highlight
 4513                                .range
 4514                                .start
 4515                                .max(&excerpt_range.context.start, cursor_buffer_snapshot);
 4516                            let end = highlight
 4517                                .range
 4518                                .end
 4519                                .min(&excerpt_range.context.end, cursor_buffer_snapshot);
 4520                            if start.cmp(&end, cursor_buffer_snapshot).is_ge() {
 4521                                continue;
 4522                            }
 4523
 4524                            let range = Anchor {
 4525                                buffer_id,
 4526                                excerpt_id,
 4527                                text_anchor: start,
 4528                            }..Anchor {
 4529                                buffer_id,
 4530                                excerpt_id,
 4531                                text_anchor: end,
 4532                            };
 4533                            if highlight.kind == lsp::DocumentHighlightKind::WRITE {
 4534                                write_ranges.push(range);
 4535                            } else {
 4536                                read_ranges.push(range);
 4537                            }
 4538                        }
 4539                    }
 4540
 4541                    this.highlight_background::<DocumentHighlightRead>(
 4542                        &read_ranges,
 4543                        |theme| theme.editor_document_highlight_read_background,
 4544                        cx,
 4545                    );
 4546                    this.highlight_background::<DocumentHighlightWrite>(
 4547                        &write_ranges,
 4548                        |theme| theme.editor_document_highlight_write_background,
 4549                        cx,
 4550                    );
 4551                    cx.notify();
 4552                })
 4553                .log_err();
 4554            }
 4555        }));
 4556        None
 4557    }
 4558
 4559    pub fn refresh_inline_completion(
 4560        &mut self,
 4561        debounce: bool,
 4562        user_requested: bool,
 4563        cx: &mut ViewContext<Self>,
 4564    ) -> Option<()> {
 4565        let provider = self.inline_completion_provider()?;
 4566        let cursor = self.selections.newest_anchor().head();
 4567        let (buffer, cursor_buffer_position) =
 4568            self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
 4569
 4570        if !user_requested
 4571            && (!self.enable_inline_completions
 4572                || !self.should_show_inline_completions(&buffer, cursor_buffer_position, cx)
 4573                || !self.is_focused(cx)
 4574                || buffer.read(cx).is_empty())
 4575        {
 4576            self.discard_inline_completion(false, cx);
 4577            return None;
 4578        }
 4579
 4580        self.update_visible_inline_completion(cx);
 4581        provider.refresh(buffer, cursor_buffer_position, debounce, cx);
 4582        Some(())
 4583    }
 4584
 4585    fn cycle_inline_completion(
 4586        &mut self,
 4587        direction: Direction,
 4588        cx: &mut ViewContext<Self>,
 4589    ) -> Option<()> {
 4590        let provider = self.inline_completion_provider()?;
 4591        let cursor = self.selections.newest_anchor().head();
 4592        let (buffer, cursor_buffer_position) =
 4593            self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
 4594        if !self.enable_inline_completions
 4595            || !self.should_show_inline_completions(&buffer, cursor_buffer_position, cx)
 4596        {
 4597            return None;
 4598        }
 4599
 4600        provider.cycle(buffer, cursor_buffer_position, direction, cx);
 4601        self.update_visible_inline_completion(cx);
 4602
 4603        Some(())
 4604    }
 4605
 4606    pub fn show_inline_completion(&mut self, _: &ShowInlineCompletion, cx: &mut ViewContext<Self>) {
 4607        if !self.has_active_inline_completion() {
 4608            self.refresh_inline_completion(false, true, cx);
 4609            return;
 4610        }
 4611
 4612        self.update_visible_inline_completion(cx);
 4613    }
 4614
 4615    pub fn display_cursor_names(&mut self, _: &DisplayCursorNames, cx: &mut ViewContext<Self>) {
 4616        self.show_cursor_names(cx);
 4617    }
 4618
 4619    fn show_cursor_names(&mut self, cx: &mut ViewContext<Self>) {
 4620        self.show_cursor_names = true;
 4621        cx.notify();
 4622        cx.spawn(|this, mut cx| async move {
 4623            cx.background_executor().timer(CURSORS_VISIBLE_FOR).await;
 4624            this.update(&mut cx, |this, cx| {
 4625                this.show_cursor_names = false;
 4626                cx.notify()
 4627            })
 4628            .ok()
 4629        })
 4630        .detach();
 4631    }
 4632
 4633    pub fn next_inline_completion(&mut self, _: &NextInlineCompletion, cx: &mut ViewContext<Self>) {
 4634        if self.has_active_inline_completion() {
 4635            self.cycle_inline_completion(Direction::Next, cx);
 4636        } else {
 4637            let is_copilot_disabled = self.refresh_inline_completion(false, true, cx).is_none();
 4638            if is_copilot_disabled {
 4639                cx.propagate();
 4640            }
 4641        }
 4642    }
 4643
 4644    pub fn previous_inline_completion(
 4645        &mut self,
 4646        _: &PreviousInlineCompletion,
 4647        cx: &mut ViewContext<Self>,
 4648    ) {
 4649        if self.has_active_inline_completion() {
 4650            self.cycle_inline_completion(Direction::Prev, cx);
 4651        } else {
 4652            let is_copilot_disabled = self.refresh_inline_completion(false, true, cx).is_none();
 4653            if is_copilot_disabled {
 4654                cx.propagate();
 4655            }
 4656        }
 4657    }
 4658
 4659    pub fn accept_inline_completion(
 4660        &mut self,
 4661        _: &AcceptInlineCompletion,
 4662        cx: &mut ViewContext<Self>,
 4663    ) {
 4664        let buffer = self.buffer.read(cx);
 4665        let snapshot = buffer.snapshot(cx);
 4666        let selection = self.selections.newest_adjusted(cx);
 4667        let cursor = selection.head();
 4668        let current_indent = snapshot.indent_size_for_line(MultiBufferRow(cursor.row));
 4669        let suggested_indents = snapshot.suggested_indents([cursor.row], cx);
 4670        if let Some(suggested_indent) = suggested_indents.get(&MultiBufferRow(cursor.row)).copied()
 4671        {
 4672            if cursor.column < suggested_indent.len
 4673                && cursor.column <= current_indent.len
 4674                && current_indent.len <= suggested_indent.len
 4675            {
 4676                self.tab(&Default::default(), cx);
 4677                return;
 4678            }
 4679        }
 4680
 4681        if self.show_inline_completions_in_menu(cx) {
 4682            self.hide_context_menu(cx);
 4683        }
 4684
 4685        let Some(active_inline_completion) = self.active_inline_completion.as_ref() else {
 4686            return;
 4687        };
 4688
 4689        self.report_inline_completion_event(true, cx);
 4690
 4691        match &active_inline_completion.completion {
 4692            InlineCompletion::Move(position) => {
 4693                let position = *position;
 4694                self.change_selections(Some(Autoscroll::newest()), cx, |selections| {
 4695                    selections.select_anchor_ranges([position..position]);
 4696                });
 4697            }
 4698            InlineCompletion::Edit { edits, .. } => {
 4699                if let Some(provider) = self.inline_completion_provider() {
 4700                    provider.accept(cx);
 4701                }
 4702
 4703                let snapshot = self.buffer.read(cx).snapshot(cx);
 4704                let last_edit_end = edits.last().unwrap().0.end.bias_right(&snapshot);
 4705
 4706                self.buffer.update(cx, |buffer, cx| {
 4707                    buffer.edit(edits.iter().cloned(), None, cx)
 4708                });
 4709
 4710                self.change_selections(None, cx, |s| {
 4711                    s.select_anchor_ranges([last_edit_end..last_edit_end])
 4712                });
 4713
 4714                self.update_visible_inline_completion(cx);
 4715                if self.active_inline_completion.is_none() {
 4716                    self.refresh_inline_completion(true, true, cx);
 4717                }
 4718
 4719                cx.notify();
 4720            }
 4721        }
 4722    }
 4723
 4724    pub fn accept_partial_inline_completion(
 4725        &mut self,
 4726        _: &AcceptPartialInlineCompletion,
 4727        cx: &mut ViewContext<Self>,
 4728    ) {
 4729        let Some(active_inline_completion) = self.active_inline_completion.as_ref() else {
 4730            return;
 4731        };
 4732        if self.selections.count() != 1 {
 4733            return;
 4734        }
 4735
 4736        self.report_inline_completion_event(true, cx);
 4737
 4738        match &active_inline_completion.completion {
 4739            InlineCompletion::Move(position) => {
 4740                let position = *position;
 4741                self.change_selections(Some(Autoscroll::newest()), cx, |selections| {
 4742                    selections.select_anchor_ranges([position..position]);
 4743                });
 4744            }
 4745            InlineCompletion::Edit { edits, .. } => {
 4746                // Find an insertion that starts at the cursor position.
 4747                let snapshot = self.buffer.read(cx).snapshot(cx);
 4748                let cursor_offset = self.selections.newest::<usize>(cx).head();
 4749                let insertion = edits.iter().find_map(|(range, text)| {
 4750                    let range = range.to_offset(&snapshot);
 4751                    if range.is_empty() && range.start == cursor_offset {
 4752                        Some(text)
 4753                    } else {
 4754                        None
 4755                    }
 4756                });
 4757
 4758                if let Some(text) = insertion {
 4759                    let mut partial_completion = text
 4760                        .chars()
 4761                        .by_ref()
 4762                        .take_while(|c| c.is_alphabetic())
 4763                        .collect::<String>();
 4764                    if partial_completion.is_empty() {
 4765                        partial_completion = text
 4766                            .chars()
 4767                            .by_ref()
 4768                            .take_while(|c| c.is_whitespace() || !c.is_alphabetic())
 4769                            .collect::<String>();
 4770                    }
 4771
 4772                    cx.emit(EditorEvent::InputHandled {
 4773                        utf16_range_to_replace: None,
 4774                        text: partial_completion.clone().into(),
 4775                    });
 4776
 4777                    self.insert_with_autoindent_mode(&partial_completion, None, cx);
 4778
 4779                    self.refresh_inline_completion(true, true, cx);
 4780                    cx.notify();
 4781                } else {
 4782                    self.accept_inline_completion(&Default::default(), cx);
 4783                }
 4784            }
 4785        }
 4786    }
 4787
 4788    fn discard_inline_completion(
 4789        &mut self,
 4790        should_report_inline_completion_event: bool,
 4791        cx: &mut ViewContext<Self>,
 4792    ) -> bool {
 4793        if should_report_inline_completion_event {
 4794            self.report_inline_completion_event(false, cx);
 4795        }
 4796
 4797        if let Some(provider) = self.inline_completion_provider() {
 4798            provider.discard(cx);
 4799        }
 4800
 4801        self.take_active_inline_completion(cx).is_some()
 4802    }
 4803
 4804    fn report_inline_completion_event(&self, accepted: bool, cx: &AppContext) {
 4805        let Some(provider) = self.inline_completion_provider() else {
 4806            return;
 4807        };
 4808
 4809        let Some((_, buffer, _)) = self
 4810            .buffer
 4811            .read(cx)
 4812            .excerpt_containing(self.selections.newest_anchor().head(), cx)
 4813        else {
 4814            return;
 4815        };
 4816
 4817        let extension = buffer
 4818            .read(cx)
 4819            .file()
 4820            .and_then(|file| Some(file.path().extension()?.to_string_lossy().to_string()));
 4821
 4822        let event_type = match accepted {
 4823            true => "Inline Completion Accepted",
 4824            false => "Inline Completion Discarded",
 4825        };
 4826        telemetry::event!(
 4827            event_type,
 4828            provider = provider.name(),
 4829            suggestion_accepted = accepted,
 4830            file_extension = extension,
 4831        );
 4832    }
 4833
 4834    pub fn has_active_inline_completion(&self) -> bool {
 4835        self.active_inline_completion.is_some()
 4836    }
 4837
 4838    fn take_active_inline_completion(
 4839        &mut self,
 4840        cx: &mut ViewContext<Self>,
 4841    ) -> Option<InlineCompletion> {
 4842        let active_inline_completion = self.active_inline_completion.take()?;
 4843        self.splice_inlays(active_inline_completion.inlay_ids, Default::default(), cx);
 4844        self.clear_highlights::<InlineCompletionHighlight>(cx);
 4845        Some(active_inline_completion.completion)
 4846    }
 4847
 4848    fn update_visible_inline_completion(&mut self, cx: &mut ViewContext<Self>) -> Option<()> {
 4849        let selection = self.selections.newest_anchor();
 4850        let cursor = selection.head();
 4851        let multibuffer = self.buffer.read(cx).snapshot(cx);
 4852        let offset_selection = selection.map(|endpoint| endpoint.to_offset(&multibuffer));
 4853        let excerpt_id = cursor.excerpt_id;
 4854
 4855        let completions_menu_has_precedence = !self.show_inline_completions_in_menu(cx)
 4856            && (self.context_menu.borrow().is_some()
 4857                || (!self.completion_tasks.is_empty() && !self.has_active_inline_completion()));
 4858        if completions_menu_has_precedence
 4859            || !offset_selection.is_empty()
 4860            || !self.enable_inline_completions
 4861            || self
 4862                .active_inline_completion
 4863                .as_ref()
 4864                .map_or(false, |completion| {
 4865                    let invalidation_range = completion.invalidation_range.to_offset(&multibuffer);
 4866                    let invalidation_range = invalidation_range.start..=invalidation_range.end;
 4867                    !invalidation_range.contains(&offset_selection.head())
 4868                })
 4869        {
 4870            self.discard_inline_completion(false, cx);
 4871            return None;
 4872        }
 4873
 4874        self.take_active_inline_completion(cx);
 4875        let provider = self.inline_completion_provider()?;
 4876
 4877        let (buffer, cursor_buffer_position) =
 4878            self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
 4879
 4880        let inline_completion = provider.suggest(&buffer, cursor_buffer_position, cx)?;
 4881        let edits = inline_completion
 4882            .edits
 4883            .into_iter()
 4884            .flat_map(|(range, new_text)| {
 4885                let start = multibuffer.anchor_in_excerpt(excerpt_id, range.start)?;
 4886                let end = multibuffer.anchor_in_excerpt(excerpt_id, range.end)?;
 4887                Some((start..end, new_text))
 4888            })
 4889            .collect::<Vec<_>>();
 4890        if edits.is_empty() {
 4891            return None;
 4892        }
 4893
 4894        let first_edit_start = edits.first().unwrap().0.start;
 4895        let first_edit_start_point = first_edit_start.to_point(&multibuffer);
 4896        let edit_start_row = first_edit_start_point.row.saturating_sub(2);
 4897
 4898        let last_edit_end = edits.last().unwrap().0.end;
 4899        let last_edit_end_point = last_edit_end.to_point(&multibuffer);
 4900        let edit_end_row = cmp::min(multibuffer.max_point().row, last_edit_end_point.row + 2);
 4901
 4902        let cursor_row = cursor.to_point(&multibuffer).row;
 4903
 4904        let mut inlay_ids = Vec::new();
 4905        let invalidation_row_range;
 4906        let completion = if cursor_row < edit_start_row {
 4907            invalidation_row_range = cursor_row..edit_end_row;
 4908            InlineCompletion::Move(first_edit_start)
 4909        } else if cursor_row > edit_end_row {
 4910            invalidation_row_range = edit_start_row..cursor_row;
 4911            InlineCompletion::Move(first_edit_start)
 4912        } else {
 4913            if edits
 4914                .iter()
 4915                .all(|(range, _)| range.to_offset(&multibuffer).is_empty())
 4916            {
 4917                let mut inlays = Vec::new();
 4918                for (range, new_text) in &edits {
 4919                    let inlay = Inlay::inline_completion(
 4920                        post_inc(&mut self.next_inlay_id),
 4921                        range.start,
 4922                        new_text.as_str(),
 4923                    );
 4924                    inlay_ids.push(inlay.id);
 4925                    inlays.push(inlay);
 4926                }
 4927
 4928                self.splice_inlays(vec![], inlays, cx);
 4929            } else {
 4930                let background_color = cx.theme().status().deleted_background;
 4931                self.highlight_text::<InlineCompletionHighlight>(
 4932                    edits.iter().map(|(range, _)| range.clone()).collect(),
 4933                    HighlightStyle {
 4934                        background_color: Some(background_color),
 4935                        ..Default::default()
 4936                    },
 4937                    cx,
 4938                );
 4939            }
 4940
 4941            invalidation_row_range = edit_start_row..edit_end_row;
 4942
 4943            let display_mode = if all_edits_insertions_or_deletions(&edits, &multibuffer) {
 4944                if provider.show_tab_accept_marker()
 4945                    && first_edit_start_point.row == last_edit_end_point.row
 4946                    && !edits.iter().any(|(_, edit)| edit.contains('\n'))
 4947                {
 4948                    EditDisplayMode::TabAccept
 4949                } else {
 4950                    EditDisplayMode::Inline
 4951                }
 4952            } else {
 4953                EditDisplayMode::DiffPopover
 4954            };
 4955
 4956            let snapshot = multibuffer.buffer_for_excerpt(excerpt_id).cloned()?;
 4957
 4958            InlineCompletion::Edit {
 4959                edits,
 4960                edit_preview: inline_completion.edit_preview,
 4961                display_mode,
 4962                snapshot,
 4963            }
 4964        };
 4965
 4966        let invalidation_range = multibuffer
 4967            .anchor_before(Point::new(invalidation_row_range.start, 0))
 4968            ..multibuffer.anchor_after(Point::new(
 4969                invalidation_row_range.end,
 4970                multibuffer.line_len(MultiBufferRow(invalidation_row_range.end)),
 4971            ));
 4972
 4973        self.active_inline_completion = Some(InlineCompletionState {
 4974            inlay_ids,
 4975            completion,
 4976            invalidation_range,
 4977        });
 4978
 4979        if self.show_inline_completions_in_menu(cx) && self.has_active_completions_menu() {
 4980            if let Some(hint) = self.inline_completion_menu_hint(cx) {
 4981                match self.context_menu.borrow_mut().as_mut() {
 4982                    Some(CodeContextMenu::Completions(menu)) => {
 4983                        menu.show_inline_completion_hint(hint);
 4984                    }
 4985                    _ => {}
 4986                }
 4987            }
 4988        }
 4989
 4990        cx.notify();
 4991
 4992        Some(())
 4993    }
 4994
 4995    fn inline_completion_menu_hint(
 4996        &mut self,
 4997        cx: &mut ViewContext<Self>,
 4998    ) -> Option<InlineCompletionMenuHint> {
 4999        let provider = self.inline_completion_provider()?;
 5000        if self.has_active_inline_completion() {
 5001            let editor_snapshot = self.snapshot(cx);
 5002
 5003            let text = match &self.active_inline_completion.as_ref()?.completion {
 5004                InlineCompletion::Edit {
 5005                    edits,
 5006                    edit_preview,
 5007                    display_mode: _,
 5008                    snapshot,
 5009                } => edit_preview
 5010                    .as_ref()
 5011                    .and_then(|edit_preview| {
 5012                        inline_completion_edit_text(&snapshot, &edits, edit_preview, true, cx)
 5013                    })
 5014                    .map(InlineCompletionText::Edit),
 5015                InlineCompletion::Move(target) => {
 5016                    let target_point =
 5017                        target.to_point(&editor_snapshot.display_snapshot.buffer_snapshot);
 5018                    let target_line = target_point.row + 1;
 5019                    Some(InlineCompletionText::Move(
 5020                        format!("Jump to edit in line {}", target_line).into(),
 5021                    ))
 5022                }
 5023            };
 5024
 5025            Some(InlineCompletionMenuHint::Loaded { text: text? })
 5026        } else if provider.is_refreshing(cx) {
 5027            Some(InlineCompletionMenuHint::Loading)
 5028        } else if provider.needs_terms_acceptance(cx) {
 5029            Some(InlineCompletionMenuHint::PendingTermsAcceptance)
 5030        } else {
 5031            Some(InlineCompletionMenuHint::None)
 5032        }
 5033    }
 5034
 5035    pub fn inline_completion_provider(&self) -> Option<Arc<dyn InlineCompletionProviderHandle>> {
 5036        Some(self.inline_completion_provider.as_ref()?.provider.clone())
 5037    }
 5038
 5039    fn show_inline_completions_in_menu(&self, cx: &AppContext) -> bool {
 5040        EditorSettings::get_global(cx).show_inline_completions_in_menu
 5041            && self
 5042                .inline_completion_provider()
 5043                .map_or(false, |provider| provider.show_completions_in_menu())
 5044    }
 5045
 5046    fn render_code_actions_indicator(
 5047        &self,
 5048        _style: &EditorStyle,
 5049        row: DisplayRow,
 5050        is_active: bool,
 5051        cx: &mut ViewContext<Self>,
 5052    ) -> Option<IconButton> {
 5053        if self.available_code_actions.is_some() {
 5054            Some(
 5055                IconButton::new("code_actions_indicator", ui::IconName::Bolt)
 5056                    .shape(ui::IconButtonShape::Square)
 5057                    .icon_size(IconSize::XSmall)
 5058                    .icon_color(Color::Muted)
 5059                    .toggle_state(is_active)
 5060                    .tooltip({
 5061                        let focus_handle = self.focus_handle.clone();
 5062                        move |cx| {
 5063                            Tooltip::for_action_in(
 5064                                "Toggle Code Actions",
 5065                                &ToggleCodeActions {
 5066                                    deployed_from_indicator: None,
 5067                                },
 5068                                &focus_handle,
 5069                                cx,
 5070                            )
 5071                        }
 5072                    })
 5073                    .on_click(cx.listener(move |editor, _e, cx| {
 5074                        editor.focus(cx);
 5075                        editor.toggle_code_actions(
 5076                            &ToggleCodeActions {
 5077                                deployed_from_indicator: Some(row),
 5078                            },
 5079                            cx,
 5080                        );
 5081                    })),
 5082            )
 5083        } else {
 5084            None
 5085        }
 5086    }
 5087
 5088    fn clear_tasks(&mut self) {
 5089        self.tasks.clear()
 5090    }
 5091
 5092    fn insert_tasks(&mut self, key: (BufferId, BufferRow), value: RunnableTasks) {
 5093        if self.tasks.insert(key, value).is_some() {
 5094            // This case should hopefully be rare, but just in case...
 5095            log::error!("multiple different run targets found on a single line, only the last target will be rendered")
 5096        }
 5097    }
 5098
 5099    fn build_tasks_context(
 5100        project: &Model<Project>,
 5101        buffer: &Model<Buffer>,
 5102        buffer_row: u32,
 5103        tasks: &Arc<RunnableTasks>,
 5104        cx: &mut ViewContext<Self>,
 5105    ) -> Task<Option<task::TaskContext>> {
 5106        let position = Point::new(buffer_row, tasks.column);
 5107        let range_start = buffer.read(cx).anchor_at(position, Bias::Right);
 5108        let location = Location {
 5109            buffer: buffer.clone(),
 5110            range: range_start..range_start,
 5111        };
 5112        // Fill in the environmental variables from the tree-sitter captures
 5113        let mut captured_task_variables = TaskVariables::default();
 5114        for (capture_name, value) in tasks.extra_variables.clone() {
 5115            captured_task_variables.insert(
 5116                task::VariableName::Custom(capture_name.into()),
 5117                value.clone(),
 5118            );
 5119        }
 5120        project.update(cx, |project, cx| {
 5121            project.task_store().update(cx, |task_store, cx| {
 5122                task_store.task_context_for_location(captured_task_variables, location, cx)
 5123            })
 5124        })
 5125    }
 5126
 5127    pub fn spawn_nearest_task(&mut self, action: &SpawnNearestTask, cx: &mut ViewContext<Self>) {
 5128        let Some((workspace, _)) = self.workspace.clone() else {
 5129            return;
 5130        };
 5131        let Some(project) = self.project.clone() else {
 5132            return;
 5133        };
 5134
 5135        // Try to find a closest, enclosing node using tree-sitter that has a
 5136        // task
 5137        let Some((buffer, buffer_row, tasks)) = self
 5138            .find_enclosing_node_task(cx)
 5139            // Or find the task that's closest in row-distance.
 5140            .or_else(|| self.find_closest_task(cx))
 5141        else {
 5142            return;
 5143        };
 5144
 5145        let reveal_strategy = action.reveal;
 5146        let task_context = Self::build_tasks_context(&project, &buffer, buffer_row, &tasks, cx);
 5147        cx.spawn(|_, mut cx| async move {
 5148            let context = task_context.await?;
 5149            let (task_source_kind, mut resolved_task) = tasks.resolve(&context).next()?;
 5150
 5151            let resolved = resolved_task.resolved.as_mut()?;
 5152            resolved.reveal = reveal_strategy;
 5153
 5154            workspace
 5155                .update(&mut cx, |workspace, cx| {
 5156                    workspace::tasks::schedule_resolved_task(
 5157                        workspace,
 5158                        task_source_kind,
 5159                        resolved_task,
 5160                        false,
 5161                        cx,
 5162                    );
 5163                })
 5164                .ok()
 5165        })
 5166        .detach();
 5167    }
 5168
 5169    fn find_closest_task(
 5170        &mut self,
 5171        cx: &mut ViewContext<Self>,
 5172    ) -> Option<(Model<Buffer>, u32, Arc<RunnableTasks>)> {
 5173        let cursor_row = self.selections.newest_adjusted(cx).head().row;
 5174
 5175        let ((buffer_id, row), tasks) = self
 5176            .tasks
 5177            .iter()
 5178            .min_by_key(|((_, row), _)| cursor_row.abs_diff(*row))?;
 5179
 5180        let buffer = self.buffer.read(cx).buffer(*buffer_id)?;
 5181        let tasks = Arc::new(tasks.to_owned());
 5182        Some((buffer, *row, tasks))
 5183    }
 5184
 5185    fn find_enclosing_node_task(
 5186        &mut self,
 5187        cx: &mut ViewContext<Self>,
 5188    ) -> Option<(Model<Buffer>, u32, Arc<RunnableTasks>)> {
 5189        let snapshot = self.buffer.read(cx).snapshot(cx);
 5190        let offset = self.selections.newest::<usize>(cx).head();
 5191        let excerpt = snapshot.excerpt_containing(offset..offset)?;
 5192        let buffer_id = excerpt.buffer().remote_id();
 5193
 5194        let layer = excerpt.buffer().syntax_layer_at(offset)?;
 5195        let mut cursor = layer.node().walk();
 5196
 5197        while cursor.goto_first_child_for_byte(offset).is_some() {
 5198            if cursor.node().end_byte() == offset {
 5199                cursor.goto_next_sibling();
 5200            }
 5201        }
 5202
 5203        // Ascend to the smallest ancestor that contains the range and has a task.
 5204        loop {
 5205            let node = cursor.node();
 5206            let node_range = node.byte_range();
 5207            let symbol_start_row = excerpt.buffer().offset_to_point(node.start_byte()).row;
 5208
 5209            // Check if this node contains our offset
 5210            if node_range.start <= offset && node_range.end >= offset {
 5211                // If it contains offset, check for task
 5212                if let Some(tasks) = self.tasks.get(&(buffer_id, symbol_start_row)) {
 5213                    let buffer = self.buffer.read(cx).buffer(buffer_id)?;
 5214                    return Some((buffer, symbol_start_row, Arc::new(tasks.to_owned())));
 5215                }
 5216            }
 5217
 5218            if !cursor.goto_parent() {
 5219                break;
 5220            }
 5221        }
 5222        None
 5223    }
 5224
 5225    fn render_run_indicator(
 5226        &self,
 5227        _style: &EditorStyle,
 5228        is_active: bool,
 5229        row: DisplayRow,
 5230        cx: &mut ViewContext<Self>,
 5231    ) -> IconButton {
 5232        IconButton::new(("run_indicator", row.0 as usize), ui::IconName::Play)
 5233            .shape(ui::IconButtonShape::Square)
 5234            .icon_size(IconSize::XSmall)
 5235            .icon_color(Color::Muted)
 5236            .toggle_state(is_active)
 5237            .on_click(cx.listener(move |editor, _e, cx| {
 5238                editor.focus(cx);
 5239                editor.toggle_code_actions(
 5240                    &ToggleCodeActions {
 5241                        deployed_from_indicator: Some(row),
 5242                    },
 5243                    cx,
 5244                );
 5245            }))
 5246    }
 5247
 5248    #[cfg(any(feature = "test-support", test))]
 5249    pub fn context_menu_visible(&self) -> bool {
 5250        self.context_menu
 5251            .borrow()
 5252            .as_ref()
 5253            .map_or(false, |menu| menu.visible())
 5254    }
 5255
 5256    #[cfg(feature = "test-support")]
 5257    pub fn context_menu_contains_inline_completion(&self) -> bool {
 5258        self.context_menu
 5259            .borrow()
 5260            .as_ref()
 5261            .map_or(false, |menu| match menu {
 5262                CodeContextMenu::Completions(menu) => {
 5263                    menu.entries.borrow().first().map_or(false, |entry| {
 5264                        matches!(entry, CompletionEntry::InlineCompletionHint(_))
 5265                    })
 5266                }
 5267                CodeContextMenu::CodeActions(_) => false,
 5268            })
 5269    }
 5270
 5271    fn context_menu_origin(&self, cursor_position: DisplayPoint) -> Option<ContextMenuOrigin> {
 5272        self.context_menu
 5273            .borrow()
 5274            .as_ref()
 5275            .map(|menu| menu.origin(cursor_position))
 5276    }
 5277
 5278    fn render_context_menu(
 5279        &self,
 5280        style: &EditorStyle,
 5281        max_height_in_lines: u32,
 5282        y_flipped: bool,
 5283        cx: &mut ViewContext<Editor>,
 5284    ) -> Option<AnyElement> {
 5285        self.context_menu.borrow().as_ref().and_then(|menu| {
 5286            if menu.visible() {
 5287                Some(menu.render(style, max_height_in_lines, y_flipped, cx))
 5288            } else {
 5289                None
 5290            }
 5291        })
 5292    }
 5293
 5294    fn render_context_menu_aside(
 5295        &self,
 5296        style: &EditorStyle,
 5297        max_size: Size<Pixels>,
 5298        cx: &mut ViewContext<Editor>,
 5299    ) -> Option<AnyElement> {
 5300        self.context_menu.borrow().as_ref().and_then(|menu| {
 5301            if menu.visible() {
 5302                menu.render_aside(
 5303                    style,
 5304                    max_size,
 5305                    self.workspace.as_ref().map(|(w, _)| w.clone()),
 5306                    cx,
 5307                )
 5308            } else {
 5309                None
 5310            }
 5311        })
 5312    }
 5313
 5314    fn hide_context_menu(&mut self, cx: &mut ViewContext<Self>) -> Option<CodeContextMenu> {
 5315        cx.notify();
 5316        self.completion_tasks.clear();
 5317        let context_menu = self.context_menu.borrow_mut().take();
 5318        if context_menu.is_some() && !self.show_inline_completions_in_menu(cx) {
 5319            self.update_visible_inline_completion(cx);
 5320        }
 5321        context_menu
 5322    }
 5323
 5324    fn show_snippet_choices(
 5325        &mut self,
 5326        choices: &Vec<String>,
 5327        selection: Range<Anchor>,
 5328        cx: &mut ViewContext<Self>,
 5329    ) {
 5330        if selection.start.buffer_id.is_none() {
 5331            return;
 5332        }
 5333        let buffer_id = selection.start.buffer_id.unwrap();
 5334        let buffer = self.buffer().read(cx).buffer(buffer_id);
 5335        let id = post_inc(&mut self.next_completion_id);
 5336
 5337        if let Some(buffer) = buffer {
 5338            *self.context_menu.borrow_mut() = Some(CodeContextMenu::Completions(
 5339                CompletionsMenu::new_snippet_choices(id, true, choices, selection, buffer),
 5340            ));
 5341        }
 5342    }
 5343
 5344    pub fn insert_snippet(
 5345        &mut self,
 5346        insertion_ranges: &[Range<usize>],
 5347        snippet: Snippet,
 5348        cx: &mut ViewContext<Self>,
 5349    ) -> Result<()> {
 5350        struct Tabstop<T> {
 5351            is_end_tabstop: bool,
 5352            ranges: Vec<Range<T>>,
 5353            choices: Option<Vec<String>>,
 5354        }
 5355
 5356        let tabstops = self.buffer.update(cx, |buffer, cx| {
 5357            let snippet_text: Arc<str> = snippet.text.clone().into();
 5358            buffer.edit(
 5359                insertion_ranges
 5360                    .iter()
 5361                    .cloned()
 5362                    .map(|range| (range, snippet_text.clone())),
 5363                Some(AutoindentMode::EachLine),
 5364                cx,
 5365            );
 5366
 5367            let snapshot = &*buffer.read(cx);
 5368            let snippet = &snippet;
 5369            snippet
 5370                .tabstops
 5371                .iter()
 5372                .map(|tabstop| {
 5373                    let is_end_tabstop = tabstop.ranges.first().map_or(false, |tabstop| {
 5374                        tabstop.is_empty() && tabstop.start == snippet.text.len() as isize
 5375                    });
 5376                    let mut tabstop_ranges = tabstop
 5377                        .ranges
 5378                        .iter()
 5379                        .flat_map(|tabstop_range| {
 5380                            let mut delta = 0_isize;
 5381                            insertion_ranges.iter().map(move |insertion_range| {
 5382                                let insertion_start = insertion_range.start as isize + delta;
 5383                                delta +=
 5384                                    snippet.text.len() as isize - insertion_range.len() as isize;
 5385
 5386                                let start = ((insertion_start + tabstop_range.start) as usize)
 5387                                    .min(snapshot.len());
 5388                                let end = ((insertion_start + tabstop_range.end) as usize)
 5389                                    .min(snapshot.len());
 5390                                snapshot.anchor_before(start)..snapshot.anchor_after(end)
 5391                            })
 5392                        })
 5393                        .collect::<Vec<_>>();
 5394                    tabstop_ranges.sort_unstable_by(|a, b| a.start.cmp(&b.start, snapshot));
 5395
 5396                    Tabstop {
 5397                        is_end_tabstop,
 5398                        ranges: tabstop_ranges,
 5399                        choices: tabstop.choices.clone(),
 5400                    }
 5401                })
 5402                .collect::<Vec<_>>()
 5403        });
 5404        if let Some(tabstop) = tabstops.first() {
 5405            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5406                s.select_ranges(tabstop.ranges.iter().cloned());
 5407            });
 5408
 5409            if let Some(choices) = &tabstop.choices {
 5410                if let Some(selection) = tabstop.ranges.first() {
 5411                    self.show_snippet_choices(choices, selection.clone(), cx)
 5412                }
 5413            }
 5414
 5415            // If we're already at the last tabstop and it's at the end of the snippet,
 5416            // we're done, we don't need to keep the state around.
 5417            if !tabstop.is_end_tabstop {
 5418                let choices = tabstops
 5419                    .iter()
 5420                    .map(|tabstop| tabstop.choices.clone())
 5421                    .collect();
 5422
 5423                let ranges = tabstops
 5424                    .into_iter()
 5425                    .map(|tabstop| tabstop.ranges)
 5426                    .collect::<Vec<_>>();
 5427
 5428                self.snippet_stack.push(SnippetState {
 5429                    active_index: 0,
 5430                    ranges,
 5431                    choices,
 5432                });
 5433            }
 5434
 5435            // Check whether the just-entered snippet ends with an auto-closable bracket.
 5436            if self.autoclose_regions.is_empty() {
 5437                let snapshot = self.buffer.read(cx).snapshot(cx);
 5438                for selection in &mut self.selections.all::<Point>(cx) {
 5439                    let selection_head = selection.head();
 5440                    let Some(scope) = snapshot.language_scope_at(selection_head) else {
 5441                        continue;
 5442                    };
 5443
 5444                    let mut bracket_pair = None;
 5445                    let next_chars = snapshot.chars_at(selection_head).collect::<String>();
 5446                    let prev_chars = snapshot
 5447                        .reversed_chars_at(selection_head)
 5448                        .collect::<String>();
 5449                    for (pair, enabled) in scope.brackets() {
 5450                        if enabled
 5451                            && pair.close
 5452                            && prev_chars.starts_with(pair.start.as_str())
 5453                            && next_chars.starts_with(pair.end.as_str())
 5454                        {
 5455                            bracket_pair = Some(pair.clone());
 5456                            break;
 5457                        }
 5458                    }
 5459                    if let Some(pair) = bracket_pair {
 5460                        let start = snapshot.anchor_after(selection_head);
 5461                        let end = snapshot.anchor_after(selection_head);
 5462                        self.autoclose_regions.push(AutocloseRegion {
 5463                            selection_id: selection.id,
 5464                            range: start..end,
 5465                            pair,
 5466                        });
 5467                    }
 5468                }
 5469            }
 5470        }
 5471        Ok(())
 5472    }
 5473
 5474    pub fn move_to_next_snippet_tabstop(&mut self, cx: &mut ViewContext<Self>) -> bool {
 5475        self.move_to_snippet_tabstop(Bias::Right, cx)
 5476    }
 5477
 5478    pub fn move_to_prev_snippet_tabstop(&mut self, cx: &mut ViewContext<Self>) -> bool {
 5479        self.move_to_snippet_tabstop(Bias::Left, cx)
 5480    }
 5481
 5482    pub fn move_to_snippet_tabstop(&mut self, bias: Bias, cx: &mut ViewContext<Self>) -> bool {
 5483        if let Some(mut snippet) = self.snippet_stack.pop() {
 5484            match bias {
 5485                Bias::Left => {
 5486                    if snippet.active_index > 0 {
 5487                        snippet.active_index -= 1;
 5488                    } else {
 5489                        self.snippet_stack.push(snippet);
 5490                        return false;
 5491                    }
 5492                }
 5493                Bias::Right => {
 5494                    if snippet.active_index + 1 < snippet.ranges.len() {
 5495                        snippet.active_index += 1;
 5496                    } else {
 5497                        self.snippet_stack.push(snippet);
 5498                        return false;
 5499                    }
 5500                }
 5501            }
 5502            if let Some(current_ranges) = snippet.ranges.get(snippet.active_index) {
 5503                self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5504                    s.select_anchor_ranges(current_ranges.iter().cloned())
 5505                });
 5506
 5507                if let Some(choices) = &snippet.choices[snippet.active_index] {
 5508                    if let Some(selection) = current_ranges.first() {
 5509                        self.show_snippet_choices(&choices, selection.clone(), cx);
 5510                    }
 5511                }
 5512
 5513                // If snippet state is not at the last tabstop, push it back on the stack
 5514                if snippet.active_index + 1 < snippet.ranges.len() {
 5515                    self.snippet_stack.push(snippet);
 5516                }
 5517                return true;
 5518            }
 5519        }
 5520
 5521        false
 5522    }
 5523
 5524    pub fn clear(&mut self, cx: &mut ViewContext<Self>) {
 5525        self.transact(cx, |this, cx| {
 5526            this.select_all(&SelectAll, cx);
 5527            this.insert("", cx);
 5528        });
 5529    }
 5530
 5531    pub fn backspace(&mut self, _: &Backspace, cx: &mut ViewContext<Self>) {
 5532        self.transact(cx, |this, cx| {
 5533            this.select_autoclose_pair(cx);
 5534            let mut linked_ranges = HashMap::<_, Vec<_>>::default();
 5535            if !this.linked_edit_ranges.is_empty() {
 5536                let selections = this.selections.all::<MultiBufferPoint>(cx);
 5537                let snapshot = this.buffer.read(cx).snapshot(cx);
 5538
 5539                for selection in selections.iter() {
 5540                    let selection_start = snapshot.anchor_before(selection.start).text_anchor;
 5541                    let selection_end = snapshot.anchor_after(selection.end).text_anchor;
 5542                    if selection_start.buffer_id != selection_end.buffer_id {
 5543                        continue;
 5544                    }
 5545                    if let Some(ranges) =
 5546                        this.linked_editing_ranges_for(selection_start..selection_end, cx)
 5547                    {
 5548                        for (buffer, entries) in ranges {
 5549                            linked_ranges.entry(buffer).or_default().extend(entries);
 5550                        }
 5551                    }
 5552                }
 5553            }
 5554
 5555            let mut selections = this.selections.all::<MultiBufferPoint>(cx);
 5556            if !this.selections.line_mode {
 5557                let display_map = this.display_map.update(cx, |map, cx| map.snapshot(cx));
 5558                for selection in &mut selections {
 5559                    if selection.is_empty() {
 5560                        let old_head = selection.head();
 5561                        let mut new_head =
 5562                            movement::left(&display_map, old_head.to_display_point(&display_map))
 5563                                .to_point(&display_map);
 5564                        if let Some((buffer, line_buffer_range)) = display_map
 5565                            .buffer_snapshot
 5566                            .buffer_line_for_row(MultiBufferRow(old_head.row))
 5567                        {
 5568                            let indent_size =
 5569                                buffer.indent_size_for_line(line_buffer_range.start.row);
 5570                            let indent_len = match indent_size.kind {
 5571                                IndentKind::Space => {
 5572                                    buffer.settings_at(line_buffer_range.start, cx).tab_size
 5573                                }
 5574                                IndentKind::Tab => NonZeroU32::new(1).unwrap(),
 5575                            };
 5576                            if old_head.column <= indent_size.len && old_head.column > 0 {
 5577                                let indent_len = indent_len.get();
 5578                                new_head = cmp::min(
 5579                                    new_head,
 5580                                    MultiBufferPoint::new(
 5581                                        old_head.row,
 5582                                        ((old_head.column - 1) / indent_len) * indent_len,
 5583                                    ),
 5584                                );
 5585                            }
 5586                        }
 5587
 5588                        selection.set_head(new_head, SelectionGoal::None);
 5589                    }
 5590                }
 5591            }
 5592
 5593            this.signature_help_state.set_backspace_pressed(true);
 5594            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
 5595            this.insert("", cx);
 5596            let empty_str: Arc<str> = Arc::from("");
 5597            for (buffer, edits) in linked_ranges {
 5598                let snapshot = buffer.read(cx).snapshot();
 5599                use text::ToPoint as TP;
 5600
 5601                let edits = edits
 5602                    .into_iter()
 5603                    .map(|range| {
 5604                        let end_point = TP::to_point(&range.end, &snapshot);
 5605                        let mut start_point = TP::to_point(&range.start, &snapshot);
 5606
 5607                        if end_point == start_point {
 5608                            let offset = text::ToOffset::to_offset(&range.start, &snapshot)
 5609                                .saturating_sub(1);
 5610                            start_point =
 5611                                snapshot.clip_point(TP::to_point(&offset, &snapshot), Bias::Left);
 5612                        };
 5613
 5614                        (start_point..end_point, empty_str.clone())
 5615                    })
 5616                    .sorted_by_key(|(range, _)| range.start)
 5617                    .collect::<Vec<_>>();
 5618                buffer.update(cx, |this, cx| {
 5619                    this.edit(edits, None, cx);
 5620                })
 5621            }
 5622            this.refresh_inline_completion(true, false, cx);
 5623            linked_editing_ranges::refresh_linked_ranges(this, cx);
 5624        });
 5625    }
 5626
 5627    pub fn delete(&mut self, _: &Delete, cx: &mut ViewContext<Self>) {
 5628        self.transact(cx, |this, cx| {
 5629            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5630                let line_mode = s.line_mode;
 5631                s.move_with(|map, selection| {
 5632                    if selection.is_empty() && !line_mode {
 5633                        let cursor = movement::right(map, selection.head());
 5634                        selection.end = cursor;
 5635                        selection.reversed = true;
 5636                        selection.goal = SelectionGoal::None;
 5637                    }
 5638                })
 5639            });
 5640            this.insert("", cx);
 5641            this.refresh_inline_completion(true, false, cx);
 5642        });
 5643    }
 5644
 5645    pub fn tab_prev(&mut self, _: &TabPrev, cx: &mut ViewContext<Self>) {
 5646        if self.move_to_prev_snippet_tabstop(cx) {
 5647            return;
 5648        }
 5649
 5650        self.outdent(&Outdent, cx);
 5651    }
 5652
 5653    pub fn tab(&mut self, _: &Tab, cx: &mut ViewContext<Self>) {
 5654        if self.move_to_next_snippet_tabstop(cx) || self.read_only(cx) {
 5655            return;
 5656        }
 5657
 5658        let mut selections = self.selections.all_adjusted(cx);
 5659        let buffer = self.buffer.read(cx);
 5660        let snapshot = buffer.snapshot(cx);
 5661        let rows_iter = selections.iter().map(|s| s.head().row);
 5662        let suggested_indents = snapshot.suggested_indents(rows_iter, cx);
 5663
 5664        let mut edits = Vec::new();
 5665        let mut prev_edited_row = 0;
 5666        let mut row_delta = 0;
 5667        for selection in &mut selections {
 5668            if selection.start.row != prev_edited_row {
 5669                row_delta = 0;
 5670            }
 5671            prev_edited_row = selection.end.row;
 5672
 5673            // If the selection is non-empty, then increase the indentation of the selected lines.
 5674            if !selection.is_empty() {
 5675                row_delta =
 5676                    Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
 5677                continue;
 5678            }
 5679
 5680            // If the selection is empty and the cursor is in the leading whitespace before the
 5681            // suggested indentation, then auto-indent the line.
 5682            let cursor = selection.head();
 5683            let current_indent = snapshot.indent_size_for_line(MultiBufferRow(cursor.row));
 5684            if let Some(suggested_indent) =
 5685                suggested_indents.get(&MultiBufferRow(cursor.row)).copied()
 5686            {
 5687                if cursor.column < suggested_indent.len
 5688                    && cursor.column <= current_indent.len
 5689                    && current_indent.len <= suggested_indent.len
 5690                {
 5691                    selection.start = Point::new(cursor.row, suggested_indent.len);
 5692                    selection.end = selection.start;
 5693                    if row_delta == 0 {
 5694                        edits.extend(Buffer::edit_for_indent_size_adjustment(
 5695                            cursor.row,
 5696                            current_indent,
 5697                            suggested_indent,
 5698                        ));
 5699                        row_delta = suggested_indent.len - current_indent.len;
 5700                    }
 5701                    continue;
 5702                }
 5703            }
 5704
 5705            // Otherwise, insert a hard or soft tab.
 5706            let settings = buffer.settings_at(cursor, cx);
 5707            let tab_size = if settings.hard_tabs {
 5708                IndentSize::tab()
 5709            } else {
 5710                let tab_size = settings.tab_size.get();
 5711                let char_column = snapshot
 5712                    .text_for_range(Point::new(cursor.row, 0)..cursor)
 5713                    .flat_map(str::chars)
 5714                    .count()
 5715                    + row_delta as usize;
 5716                let chars_to_next_tab_stop = tab_size - (char_column as u32 % tab_size);
 5717                IndentSize::spaces(chars_to_next_tab_stop)
 5718            };
 5719            selection.start = Point::new(cursor.row, cursor.column + row_delta + tab_size.len);
 5720            selection.end = selection.start;
 5721            edits.push((cursor..cursor, tab_size.chars().collect::<String>()));
 5722            row_delta += tab_size.len;
 5723        }
 5724
 5725        self.transact(cx, |this, cx| {
 5726            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
 5727            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
 5728            this.refresh_inline_completion(true, false, cx);
 5729        });
 5730    }
 5731
 5732    pub fn indent(&mut self, _: &Indent, cx: &mut ViewContext<Self>) {
 5733        if self.read_only(cx) {
 5734            return;
 5735        }
 5736        let mut selections = self.selections.all::<Point>(cx);
 5737        let mut prev_edited_row = 0;
 5738        let mut row_delta = 0;
 5739        let mut edits = Vec::new();
 5740        let buffer = self.buffer.read(cx);
 5741        let snapshot = buffer.snapshot(cx);
 5742        for selection in &mut selections {
 5743            if selection.start.row != prev_edited_row {
 5744                row_delta = 0;
 5745            }
 5746            prev_edited_row = selection.end.row;
 5747
 5748            row_delta =
 5749                Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
 5750        }
 5751
 5752        self.transact(cx, |this, cx| {
 5753            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
 5754            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
 5755        });
 5756    }
 5757
 5758    fn indent_selection(
 5759        buffer: &MultiBuffer,
 5760        snapshot: &MultiBufferSnapshot,
 5761        selection: &mut Selection<Point>,
 5762        edits: &mut Vec<(Range<Point>, String)>,
 5763        delta_for_start_row: u32,
 5764        cx: &AppContext,
 5765    ) -> u32 {
 5766        let settings = buffer.settings_at(selection.start, cx);
 5767        let tab_size = settings.tab_size.get();
 5768        let indent_kind = if settings.hard_tabs {
 5769            IndentKind::Tab
 5770        } else {
 5771            IndentKind::Space
 5772        };
 5773        let mut start_row = selection.start.row;
 5774        let mut end_row = selection.end.row + 1;
 5775
 5776        // If a selection ends at the beginning of a line, don't indent
 5777        // that last line.
 5778        if selection.end.column == 0 && selection.end.row > selection.start.row {
 5779            end_row -= 1;
 5780        }
 5781
 5782        // Avoid re-indenting a row that has already been indented by a
 5783        // previous selection, but still update this selection's column
 5784        // to reflect that indentation.
 5785        if delta_for_start_row > 0 {
 5786            start_row += 1;
 5787            selection.start.column += delta_for_start_row;
 5788            if selection.end.row == selection.start.row {
 5789                selection.end.column += delta_for_start_row;
 5790            }
 5791        }
 5792
 5793        let mut delta_for_end_row = 0;
 5794        let has_multiple_rows = start_row + 1 != end_row;
 5795        for row in start_row..end_row {
 5796            let current_indent = snapshot.indent_size_for_line(MultiBufferRow(row));
 5797            let indent_delta = match (current_indent.kind, indent_kind) {
 5798                (IndentKind::Space, IndentKind::Space) => {
 5799                    let columns_to_next_tab_stop = tab_size - (current_indent.len % tab_size);
 5800                    IndentSize::spaces(columns_to_next_tab_stop)
 5801                }
 5802                (IndentKind::Tab, IndentKind::Space) => IndentSize::spaces(tab_size),
 5803                (_, IndentKind::Tab) => IndentSize::tab(),
 5804            };
 5805
 5806            let start = if has_multiple_rows || current_indent.len < selection.start.column {
 5807                0
 5808            } else {
 5809                selection.start.column
 5810            };
 5811            let row_start = Point::new(row, start);
 5812            edits.push((
 5813                row_start..row_start,
 5814                indent_delta.chars().collect::<String>(),
 5815            ));
 5816
 5817            // Update this selection's endpoints to reflect the indentation.
 5818            if row == selection.start.row {
 5819                selection.start.column += indent_delta.len;
 5820            }
 5821            if row == selection.end.row {
 5822                selection.end.column += indent_delta.len;
 5823                delta_for_end_row = indent_delta.len;
 5824            }
 5825        }
 5826
 5827        if selection.start.row == selection.end.row {
 5828            delta_for_start_row + delta_for_end_row
 5829        } else {
 5830            delta_for_end_row
 5831        }
 5832    }
 5833
 5834    pub fn outdent(&mut self, _: &Outdent, cx: &mut ViewContext<Self>) {
 5835        if self.read_only(cx) {
 5836            return;
 5837        }
 5838        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 5839        let selections = self.selections.all::<Point>(cx);
 5840        let mut deletion_ranges = Vec::new();
 5841        let mut last_outdent = None;
 5842        {
 5843            let buffer = self.buffer.read(cx);
 5844            let snapshot = buffer.snapshot(cx);
 5845            for selection in &selections {
 5846                let settings = buffer.settings_at(selection.start, cx);
 5847                let tab_size = settings.tab_size.get();
 5848                let mut rows = selection.spanned_rows(false, &display_map);
 5849
 5850                // Avoid re-outdenting a row that has already been outdented by a
 5851                // previous selection.
 5852                if let Some(last_row) = last_outdent {
 5853                    if last_row == rows.start {
 5854                        rows.start = rows.start.next_row();
 5855                    }
 5856                }
 5857                let has_multiple_rows = rows.len() > 1;
 5858                for row in rows.iter_rows() {
 5859                    let indent_size = snapshot.indent_size_for_line(row);
 5860                    if indent_size.len > 0 {
 5861                        let deletion_len = match indent_size.kind {
 5862                            IndentKind::Space => {
 5863                                let columns_to_prev_tab_stop = indent_size.len % tab_size;
 5864                                if columns_to_prev_tab_stop == 0 {
 5865                                    tab_size
 5866                                } else {
 5867                                    columns_to_prev_tab_stop
 5868                                }
 5869                            }
 5870                            IndentKind::Tab => 1,
 5871                        };
 5872                        let start = if has_multiple_rows
 5873                            || deletion_len > selection.start.column
 5874                            || indent_size.len < selection.start.column
 5875                        {
 5876                            0
 5877                        } else {
 5878                            selection.start.column - deletion_len
 5879                        };
 5880                        deletion_ranges.push(
 5881                            Point::new(row.0, start)..Point::new(row.0, start + deletion_len),
 5882                        );
 5883                        last_outdent = Some(row);
 5884                    }
 5885                }
 5886            }
 5887        }
 5888
 5889        self.transact(cx, |this, cx| {
 5890            this.buffer.update(cx, |buffer, cx| {
 5891                let empty_str: Arc<str> = Arc::default();
 5892                buffer.edit(
 5893                    deletion_ranges
 5894                        .into_iter()
 5895                        .map(|range| (range, empty_str.clone())),
 5896                    None,
 5897                    cx,
 5898                );
 5899            });
 5900            let selections = this.selections.all::<usize>(cx);
 5901            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
 5902        });
 5903    }
 5904
 5905    pub fn autoindent(&mut self, _: &AutoIndent, cx: &mut ViewContext<Self>) {
 5906        if self.read_only(cx) {
 5907            return;
 5908        }
 5909        let selections = self
 5910            .selections
 5911            .all::<usize>(cx)
 5912            .into_iter()
 5913            .map(|s| s.range());
 5914
 5915        self.transact(cx, |this, cx| {
 5916            this.buffer.update(cx, |buffer, cx| {
 5917                buffer.autoindent_ranges(selections, cx);
 5918            });
 5919            let selections = this.selections.all::<usize>(cx);
 5920            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
 5921        });
 5922    }
 5923
 5924    pub fn delete_line(&mut self, _: &DeleteLine, cx: &mut ViewContext<Self>) {
 5925        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 5926        let selections = self.selections.all::<Point>(cx);
 5927
 5928        let mut new_cursors = Vec::new();
 5929        let mut edit_ranges = Vec::new();
 5930        let mut selections = selections.iter().peekable();
 5931        while let Some(selection) = selections.next() {
 5932            let mut rows = selection.spanned_rows(false, &display_map);
 5933            let goal_display_column = selection.head().to_display_point(&display_map).column();
 5934
 5935            // Accumulate contiguous regions of rows that we want to delete.
 5936            while let Some(next_selection) = selections.peek() {
 5937                let next_rows = next_selection.spanned_rows(false, &display_map);
 5938                if next_rows.start <= rows.end {
 5939                    rows.end = next_rows.end;
 5940                    selections.next().unwrap();
 5941                } else {
 5942                    break;
 5943                }
 5944            }
 5945
 5946            let buffer = &display_map.buffer_snapshot;
 5947            let mut edit_start = Point::new(rows.start.0, 0).to_offset(buffer);
 5948            let edit_end;
 5949            let cursor_buffer_row;
 5950            if buffer.max_point().row >= rows.end.0 {
 5951                // If there's a line after the range, delete the \n from the end of the row range
 5952                // and position the cursor on the next line.
 5953                edit_end = Point::new(rows.end.0, 0).to_offset(buffer);
 5954                cursor_buffer_row = rows.end;
 5955            } else {
 5956                // If there isn't a line after the range, delete the \n from the line before the
 5957                // start of the row range and position the cursor there.
 5958                edit_start = edit_start.saturating_sub(1);
 5959                edit_end = buffer.len();
 5960                cursor_buffer_row = rows.start.previous_row();
 5961            }
 5962
 5963            let mut cursor = Point::new(cursor_buffer_row.0, 0).to_display_point(&display_map);
 5964            *cursor.column_mut() =
 5965                cmp::min(goal_display_column, display_map.line_len(cursor.row()));
 5966
 5967            new_cursors.push((
 5968                selection.id,
 5969                buffer.anchor_after(cursor.to_point(&display_map)),
 5970            ));
 5971            edit_ranges.push(edit_start..edit_end);
 5972        }
 5973
 5974        self.transact(cx, |this, cx| {
 5975            let buffer = this.buffer.update(cx, |buffer, cx| {
 5976                let empty_str: Arc<str> = Arc::default();
 5977                buffer.edit(
 5978                    edit_ranges
 5979                        .into_iter()
 5980                        .map(|range| (range, empty_str.clone())),
 5981                    None,
 5982                    cx,
 5983                );
 5984                buffer.snapshot(cx)
 5985            });
 5986            let new_selections = new_cursors
 5987                .into_iter()
 5988                .map(|(id, cursor)| {
 5989                    let cursor = cursor.to_point(&buffer);
 5990                    Selection {
 5991                        id,
 5992                        start: cursor,
 5993                        end: cursor,
 5994                        reversed: false,
 5995                        goal: SelectionGoal::None,
 5996                    }
 5997                })
 5998                .collect();
 5999
 6000            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6001                s.select(new_selections);
 6002            });
 6003        });
 6004    }
 6005
 6006    pub fn join_lines_impl(&mut self, insert_whitespace: bool, cx: &mut ViewContext<Self>) {
 6007        if self.read_only(cx) {
 6008            return;
 6009        }
 6010        let mut row_ranges = Vec::<Range<MultiBufferRow>>::new();
 6011        for selection in self.selections.all::<Point>(cx) {
 6012            let start = MultiBufferRow(selection.start.row);
 6013            // Treat single line selections as if they include the next line. Otherwise this action
 6014            // would do nothing for single line selections individual cursors.
 6015            let end = if selection.start.row == selection.end.row {
 6016                MultiBufferRow(selection.start.row + 1)
 6017            } else {
 6018                MultiBufferRow(selection.end.row)
 6019            };
 6020
 6021            if let Some(last_row_range) = row_ranges.last_mut() {
 6022                if start <= last_row_range.end {
 6023                    last_row_range.end = end;
 6024                    continue;
 6025                }
 6026            }
 6027            row_ranges.push(start..end);
 6028        }
 6029
 6030        let snapshot = self.buffer.read(cx).snapshot(cx);
 6031        let mut cursor_positions = Vec::new();
 6032        for row_range in &row_ranges {
 6033            let anchor = snapshot.anchor_before(Point::new(
 6034                row_range.end.previous_row().0,
 6035                snapshot.line_len(row_range.end.previous_row()),
 6036            ));
 6037            cursor_positions.push(anchor..anchor);
 6038        }
 6039
 6040        self.transact(cx, |this, cx| {
 6041            for row_range in row_ranges.into_iter().rev() {
 6042                for row in row_range.iter_rows().rev() {
 6043                    let end_of_line = Point::new(row.0, snapshot.line_len(row));
 6044                    let next_line_row = row.next_row();
 6045                    let indent = snapshot.indent_size_for_line(next_line_row);
 6046                    let start_of_next_line = Point::new(next_line_row.0, indent.len);
 6047
 6048                    let replace =
 6049                        if snapshot.line_len(next_line_row) > indent.len && insert_whitespace {
 6050                            " "
 6051                        } else {
 6052                            ""
 6053                        };
 6054
 6055                    this.buffer.update(cx, |buffer, cx| {
 6056                        buffer.edit([(end_of_line..start_of_next_line, replace)], None, cx)
 6057                    });
 6058                }
 6059            }
 6060
 6061            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6062                s.select_anchor_ranges(cursor_positions)
 6063            });
 6064        });
 6065    }
 6066
 6067    pub fn join_lines(&mut self, _: &JoinLines, cx: &mut ViewContext<Self>) {
 6068        self.join_lines_impl(true, cx);
 6069    }
 6070
 6071    pub fn sort_lines_case_sensitive(
 6072        &mut self,
 6073        _: &SortLinesCaseSensitive,
 6074        cx: &mut ViewContext<Self>,
 6075    ) {
 6076        self.manipulate_lines(cx, |lines| lines.sort())
 6077    }
 6078
 6079    pub fn sort_lines_case_insensitive(
 6080        &mut self,
 6081        _: &SortLinesCaseInsensitive,
 6082        cx: &mut ViewContext<Self>,
 6083    ) {
 6084        self.manipulate_lines(cx, |lines| lines.sort_by_key(|line| line.to_lowercase()))
 6085    }
 6086
 6087    pub fn unique_lines_case_insensitive(
 6088        &mut self,
 6089        _: &UniqueLinesCaseInsensitive,
 6090        cx: &mut ViewContext<Self>,
 6091    ) {
 6092        self.manipulate_lines(cx, |lines| {
 6093            let mut seen = HashSet::default();
 6094            lines.retain(|line| seen.insert(line.to_lowercase()));
 6095        })
 6096    }
 6097
 6098    pub fn unique_lines_case_sensitive(
 6099        &mut self,
 6100        _: &UniqueLinesCaseSensitive,
 6101        cx: &mut ViewContext<Self>,
 6102    ) {
 6103        self.manipulate_lines(cx, |lines| {
 6104            let mut seen = HashSet::default();
 6105            lines.retain(|line| seen.insert(*line));
 6106        })
 6107    }
 6108
 6109    pub fn revert_file(&mut self, _: &RevertFile, cx: &mut ViewContext<Self>) {
 6110        let mut revert_changes = HashMap::default();
 6111        let snapshot = self.snapshot(cx);
 6112        for hunk in hunks_for_ranges(
 6113            Some(Point::zero()..snapshot.buffer_snapshot.max_point()).into_iter(),
 6114            &snapshot,
 6115        ) {
 6116            self.prepare_revert_change(&mut revert_changes, &hunk, cx);
 6117        }
 6118        if !revert_changes.is_empty() {
 6119            self.transact(cx, |editor, cx| {
 6120                editor.revert(revert_changes, cx);
 6121            });
 6122        }
 6123    }
 6124
 6125    pub fn reload_file(&mut self, _: &ReloadFile, cx: &mut ViewContext<Self>) {
 6126        let Some(project) = self.project.clone() else {
 6127            return;
 6128        };
 6129        self.reload(project, cx).detach_and_notify_err(cx);
 6130    }
 6131
 6132    pub fn revert_selected_hunks(&mut self, _: &RevertSelectedHunks, cx: &mut ViewContext<Self>) {
 6133        let revert_changes = self.gather_revert_changes(&self.selections.all(cx), cx);
 6134        if !revert_changes.is_empty() {
 6135            self.transact(cx, |editor, cx| {
 6136                editor.revert(revert_changes, cx);
 6137            });
 6138        }
 6139    }
 6140
 6141    fn revert_hunk(&mut self, hunk: HoveredHunk, cx: &mut ViewContext<Editor>) {
 6142        let snapshot = self.buffer.read(cx).read(cx);
 6143        if let Some(hunk) = crate::hunk_diff::to_diff_hunk(&hunk, &snapshot) {
 6144            drop(snapshot);
 6145            let mut revert_changes = HashMap::default();
 6146            self.prepare_revert_change(&mut revert_changes, &hunk, cx);
 6147            if !revert_changes.is_empty() {
 6148                self.revert(revert_changes, cx)
 6149            }
 6150        }
 6151    }
 6152
 6153    pub fn open_active_item_in_terminal(&mut self, _: &OpenInTerminal, cx: &mut ViewContext<Self>) {
 6154        if let Some(working_directory) = self.active_excerpt(cx).and_then(|(_, buffer, _)| {
 6155            let project_path = buffer.read(cx).project_path(cx)?;
 6156            let project = self.project.as_ref()?.read(cx);
 6157            let entry = project.entry_for_path(&project_path, cx)?;
 6158            let parent = match &entry.canonical_path {
 6159                Some(canonical_path) => canonical_path.to_path_buf(),
 6160                None => project.absolute_path(&project_path, cx)?,
 6161            }
 6162            .parent()?
 6163            .to_path_buf();
 6164            Some(parent)
 6165        }) {
 6166            cx.dispatch_action(OpenTerminal { working_directory }.boxed_clone());
 6167        }
 6168    }
 6169
 6170    fn gather_revert_changes(
 6171        &mut self,
 6172        selections: &[Selection<Point>],
 6173        cx: &mut ViewContext<Editor>,
 6174    ) -> HashMap<BufferId, Vec<(Range<text::Anchor>, Rope)>> {
 6175        let mut revert_changes = HashMap::default();
 6176        let snapshot = self.snapshot(cx);
 6177        for hunk in hunks_for_selections(&snapshot, selections) {
 6178            self.prepare_revert_change(&mut revert_changes, &hunk, cx);
 6179        }
 6180        revert_changes
 6181    }
 6182
 6183    pub fn prepare_revert_change(
 6184        &mut self,
 6185        revert_changes: &mut HashMap<BufferId, Vec<(Range<text::Anchor>, Rope)>>,
 6186        hunk: &MultiBufferDiffHunk,
 6187        cx: &AppContext,
 6188    ) -> Option<()> {
 6189        let buffer = self.buffer.read(cx).buffer(hunk.buffer_id)?;
 6190        let buffer = buffer.read(cx);
 6191        let change_set = &self.diff_map.diff_bases.get(&hunk.buffer_id)?.change_set;
 6192        let original_text = change_set
 6193            .read(cx)
 6194            .base_text
 6195            .as_ref()?
 6196            .read(cx)
 6197            .as_rope()
 6198            .slice(hunk.diff_base_byte_range.clone());
 6199        let buffer_snapshot = buffer.snapshot();
 6200        let buffer_revert_changes = revert_changes.entry(buffer.remote_id()).or_default();
 6201        if let Err(i) = buffer_revert_changes.binary_search_by(|probe| {
 6202            probe
 6203                .0
 6204                .start
 6205                .cmp(&hunk.buffer_range.start, &buffer_snapshot)
 6206                .then(probe.0.end.cmp(&hunk.buffer_range.end, &buffer_snapshot))
 6207        }) {
 6208            buffer_revert_changes.insert(i, (hunk.buffer_range.clone(), original_text));
 6209            Some(())
 6210        } else {
 6211            None
 6212        }
 6213    }
 6214
 6215    pub fn reverse_lines(&mut self, _: &ReverseLines, cx: &mut ViewContext<Self>) {
 6216        self.manipulate_lines(cx, |lines| lines.reverse())
 6217    }
 6218
 6219    pub fn shuffle_lines(&mut self, _: &ShuffleLines, cx: &mut ViewContext<Self>) {
 6220        self.manipulate_lines(cx, |lines| lines.shuffle(&mut thread_rng()))
 6221    }
 6222
 6223    fn manipulate_lines<Fn>(&mut self, cx: &mut ViewContext<Self>, mut callback: Fn)
 6224    where
 6225        Fn: FnMut(&mut Vec<&str>),
 6226    {
 6227        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 6228        let buffer = self.buffer.read(cx).snapshot(cx);
 6229
 6230        let mut edits = Vec::new();
 6231
 6232        let selections = self.selections.all::<Point>(cx);
 6233        let mut selections = selections.iter().peekable();
 6234        let mut contiguous_row_selections = Vec::new();
 6235        let mut new_selections = Vec::new();
 6236        let mut added_lines = 0;
 6237        let mut removed_lines = 0;
 6238
 6239        while let Some(selection) = selections.next() {
 6240            let (start_row, end_row) = consume_contiguous_rows(
 6241                &mut contiguous_row_selections,
 6242                selection,
 6243                &display_map,
 6244                &mut selections,
 6245            );
 6246
 6247            let start_point = Point::new(start_row.0, 0);
 6248            let end_point = Point::new(
 6249                end_row.previous_row().0,
 6250                buffer.line_len(end_row.previous_row()),
 6251            );
 6252            let text = buffer
 6253                .text_for_range(start_point..end_point)
 6254                .collect::<String>();
 6255
 6256            let mut lines = text.split('\n').collect_vec();
 6257
 6258            let lines_before = lines.len();
 6259            callback(&mut lines);
 6260            let lines_after = lines.len();
 6261
 6262            edits.push((start_point..end_point, lines.join("\n")));
 6263
 6264            // Selections must change based on added and removed line count
 6265            let start_row =
 6266                MultiBufferRow(start_point.row + added_lines as u32 - removed_lines as u32);
 6267            let end_row = MultiBufferRow(start_row.0 + lines_after.saturating_sub(1) as u32);
 6268            new_selections.push(Selection {
 6269                id: selection.id,
 6270                start: start_row,
 6271                end: end_row,
 6272                goal: SelectionGoal::None,
 6273                reversed: selection.reversed,
 6274            });
 6275
 6276            if lines_after > lines_before {
 6277                added_lines += lines_after - lines_before;
 6278            } else if lines_before > lines_after {
 6279                removed_lines += lines_before - lines_after;
 6280            }
 6281        }
 6282
 6283        self.transact(cx, |this, cx| {
 6284            let buffer = this.buffer.update(cx, |buffer, cx| {
 6285                buffer.edit(edits, None, cx);
 6286                buffer.snapshot(cx)
 6287            });
 6288
 6289            // Recalculate offsets on newly edited buffer
 6290            let new_selections = new_selections
 6291                .iter()
 6292                .map(|s| {
 6293                    let start_point = Point::new(s.start.0, 0);
 6294                    let end_point = Point::new(s.end.0, buffer.line_len(s.end));
 6295                    Selection {
 6296                        id: s.id,
 6297                        start: buffer.point_to_offset(start_point),
 6298                        end: buffer.point_to_offset(end_point),
 6299                        goal: s.goal,
 6300                        reversed: s.reversed,
 6301                    }
 6302                })
 6303                .collect();
 6304
 6305            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6306                s.select(new_selections);
 6307            });
 6308
 6309            this.request_autoscroll(Autoscroll::fit(), cx);
 6310        });
 6311    }
 6312
 6313    pub fn convert_to_upper_case(&mut self, _: &ConvertToUpperCase, cx: &mut ViewContext<Self>) {
 6314        self.manipulate_text(cx, |text| text.to_uppercase())
 6315    }
 6316
 6317    pub fn convert_to_lower_case(&mut self, _: &ConvertToLowerCase, cx: &mut ViewContext<Self>) {
 6318        self.manipulate_text(cx, |text| text.to_lowercase())
 6319    }
 6320
 6321    pub fn convert_to_title_case(&mut self, _: &ConvertToTitleCase, cx: &mut ViewContext<Self>) {
 6322        self.manipulate_text(cx, |text| {
 6323            text.split('\n')
 6324                .map(|line| line.to_case(Case::Title))
 6325                .join("\n")
 6326        })
 6327    }
 6328
 6329    pub fn convert_to_snake_case(&mut self, _: &ConvertToSnakeCase, cx: &mut ViewContext<Self>) {
 6330        self.manipulate_text(cx, |text| text.to_case(Case::Snake))
 6331    }
 6332
 6333    pub fn convert_to_kebab_case(&mut self, _: &ConvertToKebabCase, cx: &mut ViewContext<Self>) {
 6334        self.manipulate_text(cx, |text| text.to_case(Case::Kebab))
 6335    }
 6336
 6337    pub fn convert_to_upper_camel_case(
 6338        &mut self,
 6339        _: &ConvertToUpperCamelCase,
 6340        cx: &mut ViewContext<Self>,
 6341    ) {
 6342        self.manipulate_text(cx, |text| {
 6343            text.split('\n')
 6344                .map(|line| line.to_case(Case::UpperCamel))
 6345                .join("\n")
 6346        })
 6347    }
 6348
 6349    pub fn convert_to_lower_camel_case(
 6350        &mut self,
 6351        _: &ConvertToLowerCamelCase,
 6352        cx: &mut ViewContext<Self>,
 6353    ) {
 6354        self.manipulate_text(cx, |text| text.to_case(Case::Camel))
 6355    }
 6356
 6357    pub fn convert_to_opposite_case(
 6358        &mut self,
 6359        _: &ConvertToOppositeCase,
 6360        cx: &mut ViewContext<Self>,
 6361    ) {
 6362        self.manipulate_text(cx, |text| {
 6363            text.chars()
 6364                .fold(String::with_capacity(text.len()), |mut t, c| {
 6365                    if c.is_uppercase() {
 6366                        t.extend(c.to_lowercase());
 6367                    } else {
 6368                        t.extend(c.to_uppercase());
 6369                    }
 6370                    t
 6371                })
 6372        })
 6373    }
 6374
 6375    fn manipulate_text<Fn>(&mut self, cx: &mut ViewContext<Self>, mut callback: Fn)
 6376    where
 6377        Fn: FnMut(&str) -> String,
 6378    {
 6379        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 6380        let buffer = self.buffer.read(cx).snapshot(cx);
 6381
 6382        let mut new_selections = Vec::new();
 6383        let mut edits = Vec::new();
 6384        let mut selection_adjustment = 0i32;
 6385
 6386        for selection in self.selections.all::<usize>(cx) {
 6387            let selection_is_empty = selection.is_empty();
 6388
 6389            let (start, end) = if selection_is_empty {
 6390                let word_range = movement::surrounding_word(
 6391                    &display_map,
 6392                    selection.start.to_display_point(&display_map),
 6393                );
 6394                let start = word_range.start.to_offset(&display_map, Bias::Left);
 6395                let end = word_range.end.to_offset(&display_map, Bias::Left);
 6396                (start, end)
 6397            } else {
 6398                (selection.start, selection.end)
 6399            };
 6400
 6401            let text = buffer.text_for_range(start..end).collect::<String>();
 6402            let old_length = text.len() as i32;
 6403            let text = callback(&text);
 6404
 6405            new_selections.push(Selection {
 6406                start: (start as i32 - selection_adjustment) as usize,
 6407                end: ((start + text.len()) as i32 - selection_adjustment) as usize,
 6408                goal: SelectionGoal::None,
 6409                ..selection
 6410            });
 6411
 6412            selection_adjustment += old_length - text.len() as i32;
 6413
 6414            edits.push((start..end, text));
 6415        }
 6416
 6417        self.transact(cx, |this, cx| {
 6418            this.buffer.update(cx, |buffer, cx| {
 6419                buffer.edit(edits, None, cx);
 6420            });
 6421
 6422            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6423                s.select(new_selections);
 6424            });
 6425
 6426            this.request_autoscroll(Autoscroll::fit(), cx);
 6427        });
 6428    }
 6429
 6430    pub fn duplicate(&mut self, upwards: bool, whole_lines: bool, cx: &mut ViewContext<Self>) {
 6431        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 6432        let buffer = &display_map.buffer_snapshot;
 6433        let selections = self.selections.all::<Point>(cx);
 6434
 6435        let mut edits = Vec::new();
 6436        let mut selections_iter = selections.iter().peekable();
 6437        while let Some(selection) = selections_iter.next() {
 6438            let mut rows = selection.spanned_rows(false, &display_map);
 6439            // duplicate line-wise
 6440            if whole_lines || selection.start == selection.end {
 6441                // Avoid duplicating the same lines twice.
 6442                while let Some(next_selection) = selections_iter.peek() {
 6443                    let next_rows = next_selection.spanned_rows(false, &display_map);
 6444                    if next_rows.start < rows.end {
 6445                        rows.end = next_rows.end;
 6446                        selections_iter.next().unwrap();
 6447                    } else {
 6448                        break;
 6449                    }
 6450                }
 6451
 6452                // Copy the text from the selected row region and splice it either at the start
 6453                // or end of the region.
 6454                let start = Point::new(rows.start.0, 0);
 6455                let end = Point::new(
 6456                    rows.end.previous_row().0,
 6457                    buffer.line_len(rows.end.previous_row()),
 6458                );
 6459                let text = buffer
 6460                    .text_for_range(start..end)
 6461                    .chain(Some("\n"))
 6462                    .collect::<String>();
 6463                let insert_location = if upwards {
 6464                    Point::new(rows.end.0, 0)
 6465                } else {
 6466                    start
 6467                };
 6468                edits.push((insert_location..insert_location, text));
 6469            } else {
 6470                // duplicate character-wise
 6471                let start = selection.start;
 6472                let end = selection.end;
 6473                let text = buffer.text_for_range(start..end).collect::<String>();
 6474                edits.push((selection.end..selection.end, text));
 6475            }
 6476        }
 6477
 6478        self.transact(cx, |this, cx| {
 6479            this.buffer.update(cx, |buffer, cx| {
 6480                buffer.edit(edits, None, cx);
 6481            });
 6482
 6483            this.request_autoscroll(Autoscroll::fit(), cx);
 6484        });
 6485    }
 6486
 6487    pub fn duplicate_line_up(&mut self, _: &DuplicateLineUp, cx: &mut ViewContext<Self>) {
 6488        self.duplicate(true, true, cx);
 6489    }
 6490
 6491    pub fn duplicate_line_down(&mut self, _: &DuplicateLineDown, cx: &mut ViewContext<Self>) {
 6492        self.duplicate(false, true, cx);
 6493    }
 6494
 6495    pub fn duplicate_selection(&mut self, _: &DuplicateSelection, cx: &mut ViewContext<Self>) {
 6496        self.duplicate(false, false, cx);
 6497    }
 6498
 6499    pub fn move_line_up(&mut self, _: &MoveLineUp, cx: &mut ViewContext<Self>) {
 6500        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 6501        let buffer = self.buffer.read(cx).snapshot(cx);
 6502
 6503        let mut edits = Vec::new();
 6504        let mut unfold_ranges = Vec::new();
 6505        let mut refold_creases = Vec::new();
 6506
 6507        let selections = self.selections.all::<Point>(cx);
 6508        let mut selections = selections.iter().peekable();
 6509        let mut contiguous_row_selections = Vec::new();
 6510        let mut new_selections = Vec::new();
 6511
 6512        while let Some(selection) = selections.next() {
 6513            // Find all the selections that span a contiguous row range
 6514            let (start_row, end_row) = consume_contiguous_rows(
 6515                &mut contiguous_row_selections,
 6516                selection,
 6517                &display_map,
 6518                &mut selections,
 6519            );
 6520
 6521            // Move the text spanned by the row range to be before the line preceding the row range
 6522            if start_row.0 > 0 {
 6523                let range_to_move = Point::new(
 6524                    start_row.previous_row().0,
 6525                    buffer.line_len(start_row.previous_row()),
 6526                )
 6527                    ..Point::new(
 6528                        end_row.previous_row().0,
 6529                        buffer.line_len(end_row.previous_row()),
 6530                    );
 6531                let insertion_point = display_map
 6532                    .prev_line_boundary(Point::new(start_row.previous_row().0, 0))
 6533                    .0;
 6534
 6535                // Don't move lines across excerpts
 6536                if buffer
 6537                    .excerpt_boundaries_in_range((
 6538                        Bound::Excluded(insertion_point),
 6539                        Bound::Included(range_to_move.end),
 6540                    ))
 6541                    .next()
 6542                    .is_none()
 6543                {
 6544                    let text = buffer
 6545                        .text_for_range(range_to_move.clone())
 6546                        .flat_map(|s| s.chars())
 6547                        .skip(1)
 6548                        .chain(['\n'])
 6549                        .collect::<String>();
 6550
 6551                    edits.push((
 6552                        buffer.anchor_after(range_to_move.start)
 6553                            ..buffer.anchor_before(range_to_move.end),
 6554                        String::new(),
 6555                    ));
 6556                    let insertion_anchor = buffer.anchor_after(insertion_point);
 6557                    edits.push((insertion_anchor..insertion_anchor, text));
 6558
 6559                    let row_delta = range_to_move.start.row - insertion_point.row + 1;
 6560
 6561                    // Move selections up
 6562                    new_selections.extend(contiguous_row_selections.drain(..).map(
 6563                        |mut selection| {
 6564                            selection.start.row -= row_delta;
 6565                            selection.end.row -= row_delta;
 6566                            selection
 6567                        },
 6568                    ));
 6569
 6570                    // Move folds up
 6571                    unfold_ranges.push(range_to_move.clone());
 6572                    for fold in display_map.folds_in_range(
 6573                        buffer.anchor_before(range_to_move.start)
 6574                            ..buffer.anchor_after(range_to_move.end),
 6575                    ) {
 6576                        let mut start = fold.range.start.to_point(&buffer);
 6577                        let mut end = fold.range.end.to_point(&buffer);
 6578                        start.row -= row_delta;
 6579                        end.row -= row_delta;
 6580                        refold_creases.push(Crease::simple(start..end, fold.placeholder.clone()));
 6581                    }
 6582                }
 6583            }
 6584
 6585            // If we didn't move line(s), preserve the existing selections
 6586            new_selections.append(&mut contiguous_row_selections);
 6587        }
 6588
 6589        self.transact(cx, |this, cx| {
 6590            this.unfold_ranges(&unfold_ranges, true, true, cx);
 6591            this.buffer.update(cx, |buffer, cx| {
 6592                for (range, text) in edits {
 6593                    buffer.edit([(range, text)], None, cx);
 6594                }
 6595            });
 6596            this.fold_creases(refold_creases, true, cx);
 6597            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6598                s.select(new_selections);
 6599            })
 6600        });
 6601    }
 6602
 6603    pub fn move_line_down(&mut self, _: &MoveLineDown, cx: &mut ViewContext<Self>) {
 6604        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 6605        let buffer = self.buffer.read(cx).snapshot(cx);
 6606
 6607        let mut edits = Vec::new();
 6608        let mut unfold_ranges = Vec::new();
 6609        let mut refold_creases = Vec::new();
 6610
 6611        let selections = self.selections.all::<Point>(cx);
 6612        let mut selections = selections.iter().peekable();
 6613        let mut contiguous_row_selections = Vec::new();
 6614        let mut new_selections = Vec::new();
 6615
 6616        while let Some(selection) = selections.next() {
 6617            // Find all the selections that span a contiguous row range
 6618            let (start_row, end_row) = consume_contiguous_rows(
 6619                &mut contiguous_row_selections,
 6620                selection,
 6621                &display_map,
 6622                &mut selections,
 6623            );
 6624
 6625            // Move the text spanned by the row range to be after the last line of the row range
 6626            if end_row.0 <= buffer.max_point().row {
 6627                let range_to_move =
 6628                    MultiBufferPoint::new(start_row.0, 0)..MultiBufferPoint::new(end_row.0, 0);
 6629                let insertion_point = display_map
 6630                    .next_line_boundary(MultiBufferPoint::new(end_row.0, 0))
 6631                    .0;
 6632
 6633                // Don't move lines across excerpt boundaries
 6634                if buffer
 6635                    .excerpt_boundaries_in_range((
 6636                        Bound::Excluded(range_to_move.start),
 6637                        Bound::Included(insertion_point),
 6638                    ))
 6639                    .next()
 6640                    .is_none()
 6641                {
 6642                    let mut text = String::from("\n");
 6643                    text.extend(buffer.text_for_range(range_to_move.clone()));
 6644                    text.pop(); // Drop trailing newline
 6645                    edits.push((
 6646                        buffer.anchor_after(range_to_move.start)
 6647                            ..buffer.anchor_before(range_to_move.end),
 6648                        String::new(),
 6649                    ));
 6650                    let insertion_anchor = buffer.anchor_after(insertion_point);
 6651                    edits.push((insertion_anchor..insertion_anchor, text));
 6652
 6653                    let row_delta = insertion_point.row - range_to_move.end.row + 1;
 6654
 6655                    // Move selections down
 6656                    new_selections.extend(contiguous_row_selections.drain(..).map(
 6657                        |mut selection| {
 6658                            selection.start.row += row_delta;
 6659                            selection.end.row += row_delta;
 6660                            selection
 6661                        },
 6662                    ));
 6663
 6664                    // Move folds down
 6665                    unfold_ranges.push(range_to_move.clone());
 6666                    for fold in display_map.folds_in_range(
 6667                        buffer.anchor_before(range_to_move.start)
 6668                            ..buffer.anchor_after(range_to_move.end),
 6669                    ) {
 6670                        let mut start = fold.range.start.to_point(&buffer);
 6671                        let mut end = fold.range.end.to_point(&buffer);
 6672                        start.row += row_delta;
 6673                        end.row += row_delta;
 6674                        refold_creases.push(Crease::simple(start..end, fold.placeholder.clone()));
 6675                    }
 6676                }
 6677            }
 6678
 6679            // If we didn't move line(s), preserve the existing selections
 6680            new_selections.append(&mut contiguous_row_selections);
 6681        }
 6682
 6683        self.transact(cx, |this, cx| {
 6684            this.unfold_ranges(&unfold_ranges, true, true, cx);
 6685            this.buffer.update(cx, |buffer, cx| {
 6686                for (range, text) in edits {
 6687                    buffer.edit([(range, text)], None, cx);
 6688                }
 6689            });
 6690            this.fold_creases(refold_creases, true, cx);
 6691            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(new_selections));
 6692        });
 6693    }
 6694
 6695    pub fn transpose(&mut self, _: &Transpose, cx: &mut ViewContext<Self>) {
 6696        let text_layout_details = &self.text_layout_details(cx);
 6697        self.transact(cx, |this, cx| {
 6698            let edits = this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6699                let mut edits: Vec<(Range<usize>, String)> = Default::default();
 6700                let line_mode = s.line_mode;
 6701                s.move_with(|display_map, selection| {
 6702                    if !selection.is_empty() || line_mode {
 6703                        return;
 6704                    }
 6705
 6706                    let mut head = selection.head();
 6707                    let mut transpose_offset = head.to_offset(display_map, Bias::Right);
 6708                    if head.column() == display_map.line_len(head.row()) {
 6709                        transpose_offset = display_map
 6710                            .buffer_snapshot
 6711                            .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
 6712                    }
 6713
 6714                    if transpose_offset == 0 {
 6715                        return;
 6716                    }
 6717
 6718                    *head.column_mut() += 1;
 6719                    head = display_map.clip_point(head, Bias::Right);
 6720                    let goal = SelectionGoal::HorizontalPosition(
 6721                        display_map
 6722                            .x_for_display_point(head, text_layout_details)
 6723                            .into(),
 6724                    );
 6725                    selection.collapse_to(head, goal);
 6726
 6727                    let transpose_start = display_map
 6728                        .buffer_snapshot
 6729                        .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
 6730                    if edits.last().map_or(true, |e| e.0.end <= transpose_start) {
 6731                        let transpose_end = display_map
 6732                            .buffer_snapshot
 6733                            .clip_offset(transpose_offset + 1, Bias::Right);
 6734                        if let Some(ch) =
 6735                            display_map.buffer_snapshot.chars_at(transpose_start).next()
 6736                        {
 6737                            edits.push((transpose_start..transpose_offset, String::new()));
 6738                            edits.push((transpose_end..transpose_end, ch.to_string()));
 6739                        }
 6740                    }
 6741                });
 6742                edits
 6743            });
 6744            this.buffer
 6745                .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
 6746            let selections = this.selections.all::<usize>(cx);
 6747            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6748                s.select(selections);
 6749            });
 6750        });
 6751    }
 6752
 6753    pub fn rewrap(&mut self, _: &Rewrap, cx: &mut ViewContext<Self>) {
 6754        self.rewrap_impl(IsVimMode::No, cx)
 6755    }
 6756
 6757    pub fn rewrap_impl(&mut self, is_vim_mode: IsVimMode, cx: &mut ViewContext<Self>) {
 6758        let buffer = self.buffer.read(cx).snapshot(cx);
 6759        let selections = self.selections.all::<Point>(cx);
 6760        let mut selections = selections.iter().peekable();
 6761
 6762        let mut edits = Vec::new();
 6763        let mut rewrapped_row_ranges = Vec::<RangeInclusive<u32>>::new();
 6764
 6765        while let Some(selection) = selections.next() {
 6766            let mut start_row = selection.start.row;
 6767            let mut end_row = selection.end.row;
 6768
 6769            // Skip selections that overlap with a range that has already been rewrapped.
 6770            let selection_range = start_row..end_row;
 6771            if rewrapped_row_ranges
 6772                .iter()
 6773                .any(|range| range.overlaps(&selection_range))
 6774            {
 6775                continue;
 6776            }
 6777
 6778            let mut should_rewrap = is_vim_mode == IsVimMode::Yes;
 6779
 6780            if let Some(language_scope) = buffer.language_scope_at(selection.head()) {
 6781                match language_scope.language_name().0.as_ref() {
 6782                    "Markdown" | "Plain Text" => {
 6783                        should_rewrap = true;
 6784                    }
 6785                    _ => {}
 6786                }
 6787            }
 6788
 6789            let tab_size = buffer.settings_at(selection.head(), cx).tab_size;
 6790
 6791            // Since not all lines in the selection may be at the same indent
 6792            // level, choose the indent size that is the most common between all
 6793            // of the lines.
 6794            //
 6795            // If there is a tie, we use the deepest indent.
 6796            let (indent_size, indent_end) = {
 6797                let mut indent_size_occurrences = HashMap::default();
 6798                let mut rows_by_indent_size = HashMap::<IndentSize, Vec<u32>>::default();
 6799
 6800                for row in start_row..=end_row {
 6801                    let indent = buffer.indent_size_for_line(MultiBufferRow(row));
 6802                    rows_by_indent_size.entry(indent).or_default().push(row);
 6803                    *indent_size_occurrences.entry(indent).or_insert(0) += 1;
 6804                }
 6805
 6806                let indent_size = indent_size_occurrences
 6807                    .into_iter()
 6808                    .max_by_key(|(indent, count)| (*count, indent.len_with_expanded_tabs(tab_size)))
 6809                    .map(|(indent, _)| indent)
 6810                    .unwrap_or_default();
 6811                let row = rows_by_indent_size[&indent_size][0];
 6812                let indent_end = Point::new(row, indent_size.len);
 6813
 6814                (indent_size, indent_end)
 6815            };
 6816
 6817            let mut line_prefix = indent_size.chars().collect::<String>();
 6818
 6819            if let Some(comment_prefix) =
 6820                buffer
 6821                    .language_scope_at(selection.head())
 6822                    .and_then(|language| {
 6823                        language
 6824                            .line_comment_prefixes()
 6825                            .iter()
 6826                            .find(|prefix| buffer.contains_str_at(indent_end, prefix))
 6827                            .cloned()
 6828                    })
 6829            {
 6830                line_prefix.push_str(&comment_prefix);
 6831                should_rewrap = true;
 6832            }
 6833
 6834            if !should_rewrap {
 6835                continue;
 6836            }
 6837
 6838            if selection.is_empty() {
 6839                'expand_upwards: while start_row > 0 {
 6840                    let prev_row = start_row - 1;
 6841                    if buffer.contains_str_at(Point::new(prev_row, 0), &line_prefix)
 6842                        && buffer.line_len(MultiBufferRow(prev_row)) as usize > line_prefix.len()
 6843                    {
 6844                        start_row = prev_row;
 6845                    } else {
 6846                        break 'expand_upwards;
 6847                    }
 6848                }
 6849
 6850                'expand_downwards: while end_row < buffer.max_point().row {
 6851                    let next_row = end_row + 1;
 6852                    if buffer.contains_str_at(Point::new(next_row, 0), &line_prefix)
 6853                        && buffer.line_len(MultiBufferRow(next_row)) as usize > line_prefix.len()
 6854                    {
 6855                        end_row = next_row;
 6856                    } else {
 6857                        break 'expand_downwards;
 6858                    }
 6859                }
 6860            }
 6861
 6862            let start = Point::new(start_row, 0);
 6863            let end = Point::new(end_row, buffer.line_len(MultiBufferRow(end_row)));
 6864            let selection_text = buffer.text_for_range(start..end).collect::<String>();
 6865            let Some(lines_without_prefixes) = selection_text
 6866                .lines()
 6867                .map(|line| {
 6868                    line.strip_prefix(&line_prefix)
 6869                        .or_else(|| line.trim_start().strip_prefix(&line_prefix.trim_start()))
 6870                        .ok_or_else(|| {
 6871                            anyhow!("line did not start with prefix {line_prefix:?}: {line:?}")
 6872                        })
 6873                })
 6874                .collect::<Result<Vec<_>, _>>()
 6875                .log_err()
 6876            else {
 6877                continue;
 6878            };
 6879
 6880            let wrap_column = buffer
 6881                .settings_at(Point::new(start_row, 0), cx)
 6882                .preferred_line_length as usize;
 6883            let wrapped_text = wrap_with_prefix(
 6884                line_prefix,
 6885                lines_without_prefixes.join(" "),
 6886                wrap_column,
 6887                tab_size,
 6888            );
 6889
 6890            // TODO: should always use char-based diff while still supporting cursor behavior that
 6891            // matches vim.
 6892            let diff = match is_vim_mode {
 6893                IsVimMode::Yes => TextDiff::from_lines(&selection_text, &wrapped_text),
 6894                IsVimMode::No => TextDiff::from_chars(&selection_text, &wrapped_text),
 6895            };
 6896            let mut offset = start.to_offset(&buffer);
 6897            let mut moved_since_edit = true;
 6898
 6899            for change in diff.iter_all_changes() {
 6900                let value = change.value();
 6901                match change.tag() {
 6902                    ChangeTag::Equal => {
 6903                        offset += value.len();
 6904                        moved_since_edit = true;
 6905                    }
 6906                    ChangeTag::Delete => {
 6907                        let start = buffer.anchor_after(offset);
 6908                        let end = buffer.anchor_before(offset + value.len());
 6909
 6910                        if moved_since_edit {
 6911                            edits.push((start..end, String::new()));
 6912                        } else {
 6913                            edits.last_mut().unwrap().0.end = end;
 6914                        }
 6915
 6916                        offset += value.len();
 6917                        moved_since_edit = false;
 6918                    }
 6919                    ChangeTag::Insert => {
 6920                        if moved_since_edit {
 6921                            let anchor = buffer.anchor_after(offset);
 6922                            edits.push((anchor..anchor, value.to_string()));
 6923                        } else {
 6924                            edits.last_mut().unwrap().1.push_str(value);
 6925                        }
 6926
 6927                        moved_since_edit = false;
 6928                    }
 6929                }
 6930            }
 6931
 6932            rewrapped_row_ranges.push(start_row..=end_row);
 6933        }
 6934
 6935        self.buffer
 6936            .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
 6937    }
 6938
 6939    pub fn cut_common(&mut self, cx: &mut ViewContext<Self>) -> ClipboardItem {
 6940        let mut text = String::new();
 6941        let buffer = self.buffer.read(cx).snapshot(cx);
 6942        let mut selections = self.selections.all::<Point>(cx);
 6943        let mut clipboard_selections = Vec::with_capacity(selections.len());
 6944        {
 6945            let max_point = buffer.max_point();
 6946            let mut is_first = true;
 6947            for selection in &mut selections {
 6948                let is_entire_line = selection.is_empty() || self.selections.line_mode;
 6949                if is_entire_line {
 6950                    selection.start = Point::new(selection.start.row, 0);
 6951                    if !selection.is_empty() && selection.end.column == 0 {
 6952                        selection.end = cmp::min(max_point, selection.end);
 6953                    } else {
 6954                        selection.end = cmp::min(max_point, Point::new(selection.end.row + 1, 0));
 6955                    }
 6956                    selection.goal = SelectionGoal::None;
 6957                }
 6958                if is_first {
 6959                    is_first = false;
 6960                } else {
 6961                    text += "\n";
 6962                }
 6963                let mut len = 0;
 6964                for chunk in buffer.text_for_range(selection.start..selection.end) {
 6965                    text.push_str(chunk);
 6966                    len += chunk.len();
 6967                }
 6968                clipboard_selections.push(ClipboardSelection {
 6969                    len,
 6970                    is_entire_line,
 6971                    first_line_indent: buffer
 6972                        .indent_size_for_line(MultiBufferRow(selection.start.row))
 6973                        .len,
 6974                });
 6975            }
 6976        }
 6977
 6978        self.transact(cx, |this, cx| {
 6979            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6980                s.select(selections);
 6981            });
 6982            this.insert("", cx);
 6983        });
 6984        ClipboardItem::new_string_with_json_metadata(text, clipboard_selections)
 6985    }
 6986
 6987    pub fn cut(&mut self, _: &Cut, cx: &mut ViewContext<Self>) {
 6988        let item = self.cut_common(cx);
 6989        cx.write_to_clipboard(item);
 6990    }
 6991
 6992    pub fn kill_ring_cut(&mut self, _: &KillRingCut, cx: &mut ViewContext<Self>) {
 6993        self.change_selections(None, cx, |s| {
 6994            s.move_with(|snapshot, sel| {
 6995                if sel.is_empty() {
 6996                    sel.end = DisplayPoint::new(sel.end.row(), snapshot.line_len(sel.end.row()))
 6997                }
 6998            });
 6999        });
 7000        let item = self.cut_common(cx);
 7001        cx.set_global(KillRing(item))
 7002    }
 7003
 7004    pub fn kill_ring_yank(&mut self, _: &KillRingYank, cx: &mut ViewContext<Self>) {
 7005        let (text, metadata) = if let Some(KillRing(item)) = cx.try_global() {
 7006            if let Some(ClipboardEntry::String(kill_ring)) = item.entries().first() {
 7007                (kill_ring.text().to_string(), kill_ring.metadata_json())
 7008            } else {
 7009                return;
 7010            }
 7011        } else {
 7012            return;
 7013        };
 7014        self.do_paste(&text, metadata, false, cx);
 7015    }
 7016
 7017    pub fn copy(&mut self, _: &Copy, cx: &mut ViewContext<Self>) {
 7018        let selections = self.selections.all::<Point>(cx);
 7019        let buffer = self.buffer.read(cx).read(cx);
 7020        let mut text = String::new();
 7021
 7022        let mut clipboard_selections = Vec::with_capacity(selections.len());
 7023        {
 7024            let max_point = buffer.max_point();
 7025            let mut is_first = true;
 7026            for selection in selections.iter() {
 7027                let mut start = selection.start;
 7028                let mut end = selection.end;
 7029                let is_entire_line = selection.is_empty() || self.selections.line_mode;
 7030                if is_entire_line {
 7031                    start = Point::new(start.row, 0);
 7032                    end = cmp::min(max_point, Point::new(end.row + 1, 0));
 7033                }
 7034                if is_first {
 7035                    is_first = false;
 7036                } else {
 7037                    text += "\n";
 7038                }
 7039                let mut len = 0;
 7040                for chunk in buffer.text_for_range(start..end) {
 7041                    text.push_str(chunk);
 7042                    len += chunk.len();
 7043                }
 7044                clipboard_selections.push(ClipboardSelection {
 7045                    len,
 7046                    is_entire_line,
 7047                    first_line_indent: buffer.indent_size_for_line(MultiBufferRow(start.row)).len,
 7048                });
 7049            }
 7050        }
 7051
 7052        cx.write_to_clipboard(ClipboardItem::new_string_with_json_metadata(
 7053            text,
 7054            clipboard_selections,
 7055        ));
 7056    }
 7057
 7058    pub fn do_paste(
 7059        &mut self,
 7060        text: &String,
 7061        clipboard_selections: Option<Vec<ClipboardSelection>>,
 7062        handle_entire_lines: bool,
 7063        cx: &mut ViewContext<Self>,
 7064    ) {
 7065        if self.read_only(cx) {
 7066            return;
 7067        }
 7068
 7069        let clipboard_text = Cow::Borrowed(text);
 7070
 7071        self.transact(cx, |this, cx| {
 7072            if let Some(mut clipboard_selections) = clipboard_selections {
 7073                let old_selections = this.selections.all::<usize>(cx);
 7074                let all_selections_were_entire_line =
 7075                    clipboard_selections.iter().all(|s| s.is_entire_line);
 7076                let first_selection_indent_column =
 7077                    clipboard_selections.first().map(|s| s.first_line_indent);
 7078                if clipboard_selections.len() != old_selections.len() {
 7079                    clipboard_selections.drain(..);
 7080                }
 7081                let cursor_offset = this.selections.last::<usize>(cx).head();
 7082                let mut auto_indent_on_paste = true;
 7083
 7084                this.buffer.update(cx, |buffer, cx| {
 7085                    let snapshot = buffer.read(cx);
 7086                    auto_indent_on_paste =
 7087                        snapshot.settings_at(cursor_offset, cx).auto_indent_on_paste;
 7088
 7089                    let mut start_offset = 0;
 7090                    let mut edits = Vec::new();
 7091                    let mut original_indent_columns = Vec::new();
 7092                    for (ix, selection) in old_selections.iter().enumerate() {
 7093                        let to_insert;
 7094                        let entire_line;
 7095                        let original_indent_column;
 7096                        if let Some(clipboard_selection) = clipboard_selections.get(ix) {
 7097                            let end_offset = start_offset + clipboard_selection.len;
 7098                            to_insert = &clipboard_text[start_offset..end_offset];
 7099                            entire_line = clipboard_selection.is_entire_line;
 7100                            start_offset = end_offset + 1;
 7101                            original_indent_column = Some(clipboard_selection.first_line_indent);
 7102                        } else {
 7103                            to_insert = clipboard_text.as_str();
 7104                            entire_line = all_selections_were_entire_line;
 7105                            original_indent_column = first_selection_indent_column
 7106                        }
 7107
 7108                        // If the corresponding selection was empty when this slice of the
 7109                        // clipboard text was written, then the entire line containing the
 7110                        // selection was copied. If this selection is also currently empty,
 7111                        // then paste the line before the current line of the buffer.
 7112                        let range = if selection.is_empty() && handle_entire_lines && entire_line {
 7113                            let column = selection.start.to_point(&snapshot).column as usize;
 7114                            let line_start = selection.start - column;
 7115                            line_start..line_start
 7116                        } else {
 7117                            selection.range()
 7118                        };
 7119
 7120                        edits.push((range, to_insert));
 7121                        original_indent_columns.extend(original_indent_column);
 7122                    }
 7123                    drop(snapshot);
 7124
 7125                    buffer.edit(
 7126                        edits,
 7127                        if auto_indent_on_paste {
 7128                            Some(AutoindentMode::Block {
 7129                                original_indent_columns,
 7130                            })
 7131                        } else {
 7132                            None
 7133                        },
 7134                        cx,
 7135                    );
 7136                });
 7137
 7138                let selections = this.selections.all::<usize>(cx);
 7139                this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
 7140            } else {
 7141                this.insert(&clipboard_text, cx);
 7142            }
 7143        });
 7144    }
 7145
 7146    pub fn paste(&mut self, _: &Paste, cx: &mut ViewContext<Self>) {
 7147        if let Some(item) = cx.read_from_clipboard() {
 7148            let entries = item.entries();
 7149
 7150            match entries.first() {
 7151                // For now, we only support applying metadata if there's one string. In the future, we can incorporate all the selections
 7152                // of all the pasted entries.
 7153                Some(ClipboardEntry::String(clipboard_string)) if entries.len() == 1 => self
 7154                    .do_paste(
 7155                        clipboard_string.text(),
 7156                        clipboard_string.metadata_json::<Vec<ClipboardSelection>>(),
 7157                        true,
 7158                        cx,
 7159                    ),
 7160                _ => self.do_paste(&item.text().unwrap_or_default(), None, true, cx),
 7161            }
 7162        }
 7163    }
 7164
 7165    pub fn undo(&mut self, _: &Undo, cx: &mut ViewContext<Self>) {
 7166        if self.read_only(cx) {
 7167            return;
 7168        }
 7169
 7170        if let Some(transaction_id) = self.buffer.update(cx, |buffer, cx| buffer.undo(cx)) {
 7171            if let Some((selections, _)) =
 7172                self.selection_history.transaction(transaction_id).cloned()
 7173            {
 7174                self.change_selections(None, cx, |s| {
 7175                    s.select_anchors(selections.to_vec());
 7176                });
 7177            }
 7178            self.request_autoscroll(Autoscroll::fit(), cx);
 7179            self.unmark_text(cx);
 7180            self.refresh_inline_completion(true, false, cx);
 7181            cx.emit(EditorEvent::Edited { transaction_id });
 7182            cx.emit(EditorEvent::TransactionUndone { transaction_id });
 7183        }
 7184    }
 7185
 7186    pub fn redo(&mut self, _: &Redo, cx: &mut ViewContext<Self>) {
 7187        if self.read_only(cx) {
 7188            return;
 7189        }
 7190
 7191        if let Some(transaction_id) = self.buffer.update(cx, |buffer, cx| buffer.redo(cx)) {
 7192            if let Some((_, Some(selections))) =
 7193                self.selection_history.transaction(transaction_id).cloned()
 7194            {
 7195                self.change_selections(None, cx, |s| {
 7196                    s.select_anchors(selections.to_vec());
 7197                });
 7198            }
 7199            self.request_autoscroll(Autoscroll::fit(), cx);
 7200            self.unmark_text(cx);
 7201            self.refresh_inline_completion(true, false, cx);
 7202            cx.emit(EditorEvent::Edited { transaction_id });
 7203        }
 7204    }
 7205
 7206    pub fn finalize_last_transaction(&mut self, cx: &mut ViewContext<Self>) {
 7207        self.buffer
 7208            .update(cx, |buffer, cx| buffer.finalize_last_transaction(cx));
 7209    }
 7210
 7211    pub fn group_until_transaction(&mut self, tx_id: TransactionId, cx: &mut ViewContext<Self>) {
 7212        self.buffer
 7213            .update(cx, |buffer, cx| buffer.group_until_transaction(tx_id, cx));
 7214    }
 7215
 7216    pub fn move_left(&mut self, _: &MoveLeft, cx: &mut ViewContext<Self>) {
 7217        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7218            let line_mode = s.line_mode;
 7219            s.move_with(|map, selection| {
 7220                let cursor = if selection.is_empty() && !line_mode {
 7221                    movement::left(map, selection.start)
 7222                } else {
 7223                    selection.start
 7224                };
 7225                selection.collapse_to(cursor, SelectionGoal::None);
 7226            });
 7227        })
 7228    }
 7229
 7230    pub fn select_left(&mut self, _: &SelectLeft, cx: &mut ViewContext<Self>) {
 7231        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7232            s.move_heads_with(|map, head, _| (movement::left(map, head), SelectionGoal::None));
 7233        })
 7234    }
 7235
 7236    pub fn move_right(&mut self, _: &MoveRight, cx: &mut ViewContext<Self>) {
 7237        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7238            let line_mode = s.line_mode;
 7239            s.move_with(|map, selection| {
 7240                let cursor = if selection.is_empty() && !line_mode {
 7241                    movement::right(map, selection.end)
 7242                } else {
 7243                    selection.end
 7244                };
 7245                selection.collapse_to(cursor, SelectionGoal::None)
 7246            });
 7247        })
 7248    }
 7249
 7250    pub fn select_right(&mut self, _: &SelectRight, cx: &mut ViewContext<Self>) {
 7251        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7252            s.move_heads_with(|map, head, _| (movement::right(map, head), SelectionGoal::None));
 7253        })
 7254    }
 7255
 7256    pub fn move_up(&mut self, _: &MoveUp, cx: &mut ViewContext<Self>) {
 7257        if self.take_rename(true, cx).is_some() {
 7258            return;
 7259        }
 7260
 7261        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 7262            cx.propagate();
 7263            return;
 7264        }
 7265
 7266        let text_layout_details = &self.text_layout_details(cx);
 7267        let selection_count = self.selections.count();
 7268        let first_selection = self.selections.first_anchor();
 7269
 7270        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7271            let line_mode = s.line_mode;
 7272            s.move_with(|map, selection| {
 7273                if !selection.is_empty() && !line_mode {
 7274                    selection.goal = SelectionGoal::None;
 7275                }
 7276                let (cursor, goal) = movement::up(
 7277                    map,
 7278                    selection.start,
 7279                    selection.goal,
 7280                    false,
 7281                    text_layout_details,
 7282                );
 7283                selection.collapse_to(cursor, goal);
 7284            });
 7285        });
 7286
 7287        if selection_count == 1 && first_selection.range() == self.selections.first_anchor().range()
 7288        {
 7289            cx.propagate();
 7290        }
 7291    }
 7292
 7293    pub fn move_up_by_lines(&mut self, action: &MoveUpByLines, cx: &mut ViewContext<Self>) {
 7294        if self.take_rename(true, cx).is_some() {
 7295            return;
 7296        }
 7297
 7298        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 7299            cx.propagate();
 7300            return;
 7301        }
 7302
 7303        let text_layout_details = &self.text_layout_details(cx);
 7304
 7305        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7306            let line_mode = s.line_mode;
 7307            s.move_with(|map, selection| {
 7308                if !selection.is_empty() && !line_mode {
 7309                    selection.goal = SelectionGoal::None;
 7310                }
 7311                let (cursor, goal) = movement::up_by_rows(
 7312                    map,
 7313                    selection.start,
 7314                    action.lines,
 7315                    selection.goal,
 7316                    false,
 7317                    text_layout_details,
 7318                );
 7319                selection.collapse_to(cursor, goal);
 7320            });
 7321        })
 7322    }
 7323
 7324    pub fn move_down_by_lines(&mut self, action: &MoveDownByLines, cx: &mut ViewContext<Self>) {
 7325        if self.take_rename(true, cx).is_some() {
 7326            return;
 7327        }
 7328
 7329        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 7330            cx.propagate();
 7331            return;
 7332        }
 7333
 7334        let text_layout_details = &self.text_layout_details(cx);
 7335
 7336        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7337            let line_mode = s.line_mode;
 7338            s.move_with(|map, selection| {
 7339                if !selection.is_empty() && !line_mode {
 7340                    selection.goal = SelectionGoal::None;
 7341                }
 7342                let (cursor, goal) = movement::down_by_rows(
 7343                    map,
 7344                    selection.start,
 7345                    action.lines,
 7346                    selection.goal,
 7347                    false,
 7348                    text_layout_details,
 7349                );
 7350                selection.collapse_to(cursor, goal);
 7351            });
 7352        })
 7353    }
 7354
 7355    pub fn select_down_by_lines(&mut self, action: &SelectDownByLines, cx: &mut ViewContext<Self>) {
 7356        let text_layout_details = &self.text_layout_details(cx);
 7357        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7358            s.move_heads_with(|map, head, goal| {
 7359                movement::down_by_rows(map, head, action.lines, goal, false, text_layout_details)
 7360            })
 7361        })
 7362    }
 7363
 7364    pub fn select_up_by_lines(&mut self, action: &SelectUpByLines, cx: &mut ViewContext<Self>) {
 7365        let text_layout_details = &self.text_layout_details(cx);
 7366        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7367            s.move_heads_with(|map, head, goal| {
 7368                movement::up_by_rows(map, head, action.lines, goal, false, text_layout_details)
 7369            })
 7370        })
 7371    }
 7372
 7373    pub fn select_page_up(&mut self, _: &SelectPageUp, cx: &mut ViewContext<Self>) {
 7374        let Some(row_count) = self.visible_row_count() else {
 7375            return;
 7376        };
 7377
 7378        let text_layout_details = &self.text_layout_details(cx);
 7379
 7380        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7381            s.move_heads_with(|map, head, goal| {
 7382                movement::up_by_rows(map, head, row_count, goal, false, text_layout_details)
 7383            })
 7384        })
 7385    }
 7386
 7387    pub fn move_page_up(&mut self, action: &MovePageUp, cx: &mut ViewContext<Self>) {
 7388        if self.take_rename(true, cx).is_some() {
 7389            return;
 7390        }
 7391
 7392        if self
 7393            .context_menu
 7394            .borrow_mut()
 7395            .as_mut()
 7396            .map(|menu| menu.select_first(self.completion_provider.as_deref(), cx))
 7397            .unwrap_or(false)
 7398        {
 7399            return;
 7400        }
 7401
 7402        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 7403            cx.propagate();
 7404            return;
 7405        }
 7406
 7407        let Some(row_count) = self.visible_row_count() else {
 7408            return;
 7409        };
 7410
 7411        let autoscroll = if action.center_cursor {
 7412            Autoscroll::center()
 7413        } else {
 7414            Autoscroll::fit()
 7415        };
 7416
 7417        let text_layout_details = &self.text_layout_details(cx);
 7418
 7419        self.change_selections(Some(autoscroll), cx, |s| {
 7420            let line_mode = s.line_mode;
 7421            s.move_with(|map, selection| {
 7422                if !selection.is_empty() && !line_mode {
 7423                    selection.goal = SelectionGoal::None;
 7424                }
 7425                let (cursor, goal) = movement::up_by_rows(
 7426                    map,
 7427                    selection.end,
 7428                    row_count,
 7429                    selection.goal,
 7430                    false,
 7431                    text_layout_details,
 7432                );
 7433                selection.collapse_to(cursor, goal);
 7434            });
 7435        });
 7436    }
 7437
 7438    pub fn select_up(&mut self, _: &SelectUp, cx: &mut ViewContext<Self>) {
 7439        let text_layout_details = &self.text_layout_details(cx);
 7440        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7441            s.move_heads_with(|map, head, goal| {
 7442                movement::up(map, head, goal, false, text_layout_details)
 7443            })
 7444        })
 7445    }
 7446
 7447    pub fn move_down(&mut self, _: &MoveDown, cx: &mut ViewContext<Self>) {
 7448        self.take_rename(true, cx);
 7449
 7450        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 7451            cx.propagate();
 7452            return;
 7453        }
 7454
 7455        let text_layout_details = &self.text_layout_details(cx);
 7456        let selection_count = self.selections.count();
 7457        let first_selection = self.selections.first_anchor();
 7458
 7459        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7460            let line_mode = s.line_mode;
 7461            s.move_with(|map, selection| {
 7462                if !selection.is_empty() && !line_mode {
 7463                    selection.goal = SelectionGoal::None;
 7464                }
 7465                let (cursor, goal) = movement::down(
 7466                    map,
 7467                    selection.end,
 7468                    selection.goal,
 7469                    false,
 7470                    text_layout_details,
 7471                );
 7472                selection.collapse_to(cursor, goal);
 7473            });
 7474        });
 7475
 7476        if selection_count == 1 && first_selection.range() == self.selections.first_anchor().range()
 7477        {
 7478            cx.propagate();
 7479        }
 7480    }
 7481
 7482    pub fn select_page_down(&mut self, _: &SelectPageDown, cx: &mut ViewContext<Self>) {
 7483        let Some(row_count) = self.visible_row_count() else {
 7484            return;
 7485        };
 7486
 7487        let text_layout_details = &self.text_layout_details(cx);
 7488
 7489        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7490            s.move_heads_with(|map, head, goal| {
 7491                movement::down_by_rows(map, head, row_count, goal, false, text_layout_details)
 7492            })
 7493        })
 7494    }
 7495
 7496    pub fn move_page_down(&mut self, action: &MovePageDown, cx: &mut ViewContext<Self>) {
 7497        if self.take_rename(true, cx).is_some() {
 7498            return;
 7499        }
 7500
 7501        if self
 7502            .context_menu
 7503            .borrow_mut()
 7504            .as_mut()
 7505            .map(|menu| menu.select_last(self.completion_provider.as_deref(), cx))
 7506            .unwrap_or(false)
 7507        {
 7508            return;
 7509        }
 7510
 7511        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 7512            cx.propagate();
 7513            return;
 7514        }
 7515
 7516        let Some(row_count) = self.visible_row_count() else {
 7517            return;
 7518        };
 7519
 7520        let autoscroll = if action.center_cursor {
 7521            Autoscroll::center()
 7522        } else {
 7523            Autoscroll::fit()
 7524        };
 7525
 7526        let text_layout_details = &self.text_layout_details(cx);
 7527        self.change_selections(Some(autoscroll), cx, |s| {
 7528            let line_mode = s.line_mode;
 7529            s.move_with(|map, selection| {
 7530                if !selection.is_empty() && !line_mode {
 7531                    selection.goal = SelectionGoal::None;
 7532                }
 7533                let (cursor, goal) = movement::down_by_rows(
 7534                    map,
 7535                    selection.end,
 7536                    row_count,
 7537                    selection.goal,
 7538                    false,
 7539                    text_layout_details,
 7540                );
 7541                selection.collapse_to(cursor, goal);
 7542            });
 7543        });
 7544    }
 7545
 7546    pub fn select_down(&mut self, _: &SelectDown, cx: &mut ViewContext<Self>) {
 7547        let text_layout_details = &self.text_layout_details(cx);
 7548        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7549            s.move_heads_with(|map, head, goal| {
 7550                movement::down(map, head, goal, false, text_layout_details)
 7551            })
 7552        });
 7553    }
 7554
 7555    pub fn context_menu_first(&mut self, _: &ContextMenuFirst, cx: &mut ViewContext<Self>) {
 7556        if let Some(context_menu) = self.context_menu.borrow_mut().as_mut() {
 7557            context_menu.select_first(self.completion_provider.as_deref(), cx);
 7558        }
 7559    }
 7560
 7561    pub fn context_menu_prev(&mut self, _: &ContextMenuPrev, cx: &mut ViewContext<Self>) {
 7562        if let Some(context_menu) = self.context_menu.borrow_mut().as_mut() {
 7563            context_menu.select_prev(self.completion_provider.as_deref(), cx);
 7564        }
 7565    }
 7566
 7567    pub fn context_menu_next(&mut self, _: &ContextMenuNext, cx: &mut ViewContext<Self>) {
 7568        if let Some(context_menu) = self.context_menu.borrow_mut().as_mut() {
 7569            context_menu.select_next(self.completion_provider.as_deref(), cx);
 7570        }
 7571    }
 7572
 7573    pub fn context_menu_last(&mut self, _: &ContextMenuLast, cx: &mut ViewContext<Self>) {
 7574        if let Some(context_menu) = self.context_menu.borrow_mut().as_mut() {
 7575            context_menu.select_last(self.completion_provider.as_deref(), cx);
 7576        }
 7577    }
 7578
 7579    pub fn move_to_previous_word_start(
 7580        &mut self,
 7581        _: &MoveToPreviousWordStart,
 7582        cx: &mut ViewContext<Self>,
 7583    ) {
 7584        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7585            s.move_cursors_with(|map, head, _| {
 7586                (
 7587                    movement::previous_word_start(map, head),
 7588                    SelectionGoal::None,
 7589                )
 7590            });
 7591        })
 7592    }
 7593
 7594    pub fn move_to_previous_subword_start(
 7595        &mut self,
 7596        _: &MoveToPreviousSubwordStart,
 7597        cx: &mut ViewContext<Self>,
 7598    ) {
 7599        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7600            s.move_cursors_with(|map, head, _| {
 7601                (
 7602                    movement::previous_subword_start(map, head),
 7603                    SelectionGoal::None,
 7604                )
 7605            });
 7606        })
 7607    }
 7608
 7609    pub fn select_to_previous_word_start(
 7610        &mut self,
 7611        _: &SelectToPreviousWordStart,
 7612        cx: &mut ViewContext<Self>,
 7613    ) {
 7614        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7615            s.move_heads_with(|map, head, _| {
 7616                (
 7617                    movement::previous_word_start(map, head),
 7618                    SelectionGoal::None,
 7619                )
 7620            });
 7621        })
 7622    }
 7623
 7624    pub fn select_to_previous_subword_start(
 7625        &mut self,
 7626        _: &SelectToPreviousSubwordStart,
 7627        cx: &mut ViewContext<Self>,
 7628    ) {
 7629        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7630            s.move_heads_with(|map, head, _| {
 7631                (
 7632                    movement::previous_subword_start(map, head),
 7633                    SelectionGoal::None,
 7634                )
 7635            });
 7636        })
 7637    }
 7638
 7639    pub fn delete_to_previous_word_start(
 7640        &mut self,
 7641        action: &DeleteToPreviousWordStart,
 7642        cx: &mut ViewContext<Self>,
 7643    ) {
 7644        self.transact(cx, |this, cx| {
 7645            this.select_autoclose_pair(cx);
 7646            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7647                let line_mode = s.line_mode;
 7648                s.move_with(|map, selection| {
 7649                    if selection.is_empty() && !line_mode {
 7650                        let cursor = if action.ignore_newlines {
 7651                            movement::previous_word_start(map, selection.head())
 7652                        } else {
 7653                            movement::previous_word_start_or_newline(map, selection.head())
 7654                        };
 7655                        selection.set_head(cursor, SelectionGoal::None);
 7656                    }
 7657                });
 7658            });
 7659            this.insert("", cx);
 7660        });
 7661    }
 7662
 7663    pub fn delete_to_previous_subword_start(
 7664        &mut self,
 7665        _: &DeleteToPreviousSubwordStart,
 7666        cx: &mut ViewContext<Self>,
 7667    ) {
 7668        self.transact(cx, |this, cx| {
 7669            this.select_autoclose_pair(cx);
 7670            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7671                let line_mode = s.line_mode;
 7672                s.move_with(|map, selection| {
 7673                    if selection.is_empty() && !line_mode {
 7674                        let cursor = movement::previous_subword_start(map, selection.head());
 7675                        selection.set_head(cursor, SelectionGoal::None);
 7676                    }
 7677                });
 7678            });
 7679            this.insert("", cx);
 7680        });
 7681    }
 7682
 7683    pub fn move_to_next_word_end(&mut self, _: &MoveToNextWordEnd, cx: &mut ViewContext<Self>) {
 7684        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7685            s.move_cursors_with(|map, head, _| {
 7686                (movement::next_word_end(map, head), SelectionGoal::None)
 7687            });
 7688        })
 7689    }
 7690
 7691    pub fn move_to_next_subword_end(
 7692        &mut self,
 7693        _: &MoveToNextSubwordEnd,
 7694        cx: &mut ViewContext<Self>,
 7695    ) {
 7696        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7697            s.move_cursors_with(|map, head, _| {
 7698                (movement::next_subword_end(map, head), SelectionGoal::None)
 7699            });
 7700        })
 7701    }
 7702
 7703    pub fn select_to_next_word_end(&mut self, _: &SelectToNextWordEnd, cx: &mut ViewContext<Self>) {
 7704        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7705            s.move_heads_with(|map, head, _| {
 7706                (movement::next_word_end(map, head), SelectionGoal::None)
 7707            });
 7708        })
 7709    }
 7710
 7711    pub fn select_to_next_subword_end(
 7712        &mut self,
 7713        _: &SelectToNextSubwordEnd,
 7714        cx: &mut ViewContext<Self>,
 7715    ) {
 7716        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7717            s.move_heads_with(|map, head, _| {
 7718                (movement::next_subword_end(map, head), SelectionGoal::None)
 7719            });
 7720        })
 7721    }
 7722
 7723    pub fn delete_to_next_word_end(
 7724        &mut self,
 7725        action: &DeleteToNextWordEnd,
 7726        cx: &mut ViewContext<Self>,
 7727    ) {
 7728        self.transact(cx, |this, cx| {
 7729            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7730                let line_mode = s.line_mode;
 7731                s.move_with(|map, selection| {
 7732                    if selection.is_empty() && !line_mode {
 7733                        let cursor = if action.ignore_newlines {
 7734                            movement::next_word_end(map, selection.head())
 7735                        } else {
 7736                            movement::next_word_end_or_newline(map, selection.head())
 7737                        };
 7738                        selection.set_head(cursor, SelectionGoal::None);
 7739                    }
 7740                });
 7741            });
 7742            this.insert("", cx);
 7743        });
 7744    }
 7745
 7746    pub fn delete_to_next_subword_end(
 7747        &mut self,
 7748        _: &DeleteToNextSubwordEnd,
 7749        cx: &mut ViewContext<Self>,
 7750    ) {
 7751        self.transact(cx, |this, cx| {
 7752            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7753                s.move_with(|map, selection| {
 7754                    if selection.is_empty() {
 7755                        let cursor = movement::next_subword_end(map, selection.head());
 7756                        selection.set_head(cursor, SelectionGoal::None);
 7757                    }
 7758                });
 7759            });
 7760            this.insert("", cx);
 7761        });
 7762    }
 7763
 7764    pub fn move_to_beginning_of_line(
 7765        &mut self,
 7766        action: &MoveToBeginningOfLine,
 7767        cx: &mut ViewContext<Self>,
 7768    ) {
 7769        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7770            s.move_cursors_with(|map, head, _| {
 7771                (
 7772                    movement::indented_line_beginning(map, head, action.stop_at_soft_wraps),
 7773                    SelectionGoal::None,
 7774                )
 7775            });
 7776        })
 7777    }
 7778
 7779    pub fn select_to_beginning_of_line(
 7780        &mut self,
 7781        action: &SelectToBeginningOfLine,
 7782        cx: &mut ViewContext<Self>,
 7783    ) {
 7784        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7785            s.move_heads_with(|map, head, _| {
 7786                (
 7787                    movement::indented_line_beginning(map, head, action.stop_at_soft_wraps),
 7788                    SelectionGoal::None,
 7789                )
 7790            });
 7791        });
 7792    }
 7793
 7794    pub fn delete_to_beginning_of_line(
 7795        &mut self,
 7796        _: &DeleteToBeginningOfLine,
 7797        cx: &mut ViewContext<Self>,
 7798    ) {
 7799        self.transact(cx, |this, cx| {
 7800            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7801                s.move_with(|_, selection| {
 7802                    selection.reversed = true;
 7803                });
 7804            });
 7805
 7806            this.select_to_beginning_of_line(
 7807                &SelectToBeginningOfLine {
 7808                    stop_at_soft_wraps: false,
 7809                },
 7810                cx,
 7811            );
 7812            this.backspace(&Backspace, cx);
 7813        });
 7814    }
 7815
 7816    pub fn move_to_end_of_line(&mut self, action: &MoveToEndOfLine, cx: &mut ViewContext<Self>) {
 7817        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7818            s.move_cursors_with(|map, head, _| {
 7819                (
 7820                    movement::line_end(map, head, action.stop_at_soft_wraps),
 7821                    SelectionGoal::None,
 7822                )
 7823            });
 7824        })
 7825    }
 7826
 7827    pub fn select_to_end_of_line(
 7828        &mut self,
 7829        action: &SelectToEndOfLine,
 7830        cx: &mut ViewContext<Self>,
 7831    ) {
 7832        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7833            s.move_heads_with(|map, head, _| {
 7834                (
 7835                    movement::line_end(map, head, action.stop_at_soft_wraps),
 7836                    SelectionGoal::None,
 7837                )
 7838            });
 7839        })
 7840    }
 7841
 7842    pub fn delete_to_end_of_line(&mut self, _: &DeleteToEndOfLine, cx: &mut ViewContext<Self>) {
 7843        self.transact(cx, |this, cx| {
 7844            this.select_to_end_of_line(
 7845                &SelectToEndOfLine {
 7846                    stop_at_soft_wraps: false,
 7847                },
 7848                cx,
 7849            );
 7850            this.delete(&Delete, cx);
 7851        });
 7852    }
 7853
 7854    pub fn cut_to_end_of_line(&mut self, _: &CutToEndOfLine, cx: &mut ViewContext<Self>) {
 7855        self.transact(cx, |this, cx| {
 7856            this.select_to_end_of_line(
 7857                &SelectToEndOfLine {
 7858                    stop_at_soft_wraps: false,
 7859                },
 7860                cx,
 7861            );
 7862            this.cut(&Cut, cx);
 7863        });
 7864    }
 7865
 7866    pub fn move_to_start_of_paragraph(
 7867        &mut self,
 7868        _: &MoveToStartOfParagraph,
 7869        cx: &mut ViewContext<Self>,
 7870    ) {
 7871        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 7872            cx.propagate();
 7873            return;
 7874        }
 7875
 7876        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7877            s.move_with(|map, selection| {
 7878                selection.collapse_to(
 7879                    movement::start_of_paragraph(map, selection.head(), 1),
 7880                    SelectionGoal::None,
 7881                )
 7882            });
 7883        })
 7884    }
 7885
 7886    pub fn move_to_end_of_paragraph(
 7887        &mut self,
 7888        _: &MoveToEndOfParagraph,
 7889        cx: &mut ViewContext<Self>,
 7890    ) {
 7891        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 7892            cx.propagate();
 7893            return;
 7894        }
 7895
 7896        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7897            s.move_with(|map, selection| {
 7898                selection.collapse_to(
 7899                    movement::end_of_paragraph(map, selection.head(), 1),
 7900                    SelectionGoal::None,
 7901                )
 7902            });
 7903        })
 7904    }
 7905
 7906    pub fn select_to_start_of_paragraph(
 7907        &mut self,
 7908        _: &SelectToStartOfParagraph,
 7909        cx: &mut ViewContext<Self>,
 7910    ) {
 7911        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 7912            cx.propagate();
 7913            return;
 7914        }
 7915
 7916        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7917            s.move_heads_with(|map, head, _| {
 7918                (
 7919                    movement::start_of_paragraph(map, head, 1),
 7920                    SelectionGoal::None,
 7921                )
 7922            });
 7923        })
 7924    }
 7925
 7926    pub fn select_to_end_of_paragraph(
 7927        &mut self,
 7928        _: &SelectToEndOfParagraph,
 7929        cx: &mut ViewContext<Self>,
 7930    ) {
 7931        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 7932            cx.propagate();
 7933            return;
 7934        }
 7935
 7936        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7937            s.move_heads_with(|map, head, _| {
 7938                (
 7939                    movement::end_of_paragraph(map, head, 1),
 7940                    SelectionGoal::None,
 7941                )
 7942            });
 7943        })
 7944    }
 7945
 7946    pub fn move_to_beginning(&mut self, _: &MoveToBeginning, cx: &mut ViewContext<Self>) {
 7947        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 7948            cx.propagate();
 7949            return;
 7950        }
 7951
 7952        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7953            s.select_ranges(vec![0..0]);
 7954        });
 7955    }
 7956
 7957    pub fn select_to_beginning(&mut self, _: &SelectToBeginning, cx: &mut ViewContext<Self>) {
 7958        let mut selection = self.selections.last::<Point>(cx);
 7959        selection.set_head(Point::zero(), SelectionGoal::None);
 7960
 7961        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7962            s.select(vec![selection]);
 7963        });
 7964    }
 7965
 7966    pub fn move_to_end(&mut self, _: &MoveToEnd, cx: &mut ViewContext<Self>) {
 7967        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 7968            cx.propagate();
 7969            return;
 7970        }
 7971
 7972        let cursor = self.buffer.read(cx).read(cx).len();
 7973        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7974            s.select_ranges(vec![cursor..cursor])
 7975        });
 7976    }
 7977
 7978    pub fn set_nav_history(&mut self, nav_history: Option<ItemNavHistory>) {
 7979        self.nav_history = nav_history;
 7980    }
 7981
 7982    pub fn nav_history(&self) -> Option<&ItemNavHistory> {
 7983        self.nav_history.as_ref()
 7984    }
 7985
 7986    fn push_to_nav_history(
 7987        &mut self,
 7988        cursor_anchor: Anchor,
 7989        new_position: Option<Point>,
 7990        cx: &mut ViewContext<Self>,
 7991    ) {
 7992        if let Some(nav_history) = self.nav_history.as_mut() {
 7993            let buffer = self.buffer.read(cx).read(cx);
 7994            let cursor_position = cursor_anchor.to_point(&buffer);
 7995            let scroll_state = self.scroll_manager.anchor();
 7996            let scroll_top_row = scroll_state.top_row(&buffer);
 7997            drop(buffer);
 7998
 7999            if let Some(new_position) = new_position {
 8000                let row_delta = (new_position.row as i64 - cursor_position.row as i64).abs();
 8001                if row_delta < MIN_NAVIGATION_HISTORY_ROW_DELTA {
 8002                    return;
 8003                }
 8004            }
 8005
 8006            nav_history.push(
 8007                Some(NavigationData {
 8008                    cursor_anchor,
 8009                    cursor_position,
 8010                    scroll_anchor: scroll_state,
 8011                    scroll_top_row,
 8012                }),
 8013                cx,
 8014            );
 8015        }
 8016    }
 8017
 8018    pub fn select_to_end(&mut self, _: &SelectToEnd, cx: &mut ViewContext<Self>) {
 8019        let buffer = self.buffer.read(cx).snapshot(cx);
 8020        let mut selection = self.selections.first::<usize>(cx);
 8021        selection.set_head(buffer.len(), SelectionGoal::None);
 8022        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 8023            s.select(vec![selection]);
 8024        });
 8025    }
 8026
 8027    pub fn select_all(&mut self, _: &SelectAll, cx: &mut ViewContext<Self>) {
 8028        let end = self.buffer.read(cx).read(cx).len();
 8029        self.change_selections(None, cx, |s| {
 8030            s.select_ranges(vec![0..end]);
 8031        });
 8032    }
 8033
 8034    pub fn select_line(&mut self, _: &SelectLine, cx: &mut ViewContext<Self>) {
 8035        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8036        let mut selections = self.selections.all::<Point>(cx);
 8037        let max_point = display_map.buffer_snapshot.max_point();
 8038        for selection in &mut selections {
 8039            let rows = selection.spanned_rows(true, &display_map);
 8040            selection.start = Point::new(rows.start.0, 0);
 8041            selection.end = cmp::min(max_point, Point::new(rows.end.0, 0));
 8042            selection.reversed = false;
 8043        }
 8044        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 8045            s.select(selections);
 8046        });
 8047    }
 8048
 8049    pub fn split_selection_into_lines(
 8050        &mut self,
 8051        _: &SplitSelectionIntoLines,
 8052        cx: &mut ViewContext<Self>,
 8053    ) {
 8054        let mut to_unfold = Vec::new();
 8055        let mut new_selection_ranges = Vec::new();
 8056        {
 8057            let selections = self.selections.all::<Point>(cx);
 8058            let buffer = self.buffer.read(cx).read(cx);
 8059            for selection in selections {
 8060                for row in selection.start.row..selection.end.row {
 8061                    let cursor = Point::new(row, buffer.line_len(MultiBufferRow(row)));
 8062                    new_selection_ranges.push(cursor..cursor);
 8063                }
 8064                new_selection_ranges.push(selection.end..selection.end);
 8065                to_unfold.push(selection.start..selection.end);
 8066            }
 8067        }
 8068        self.unfold_ranges(&to_unfold, true, true, cx);
 8069        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 8070            s.select_ranges(new_selection_ranges);
 8071        });
 8072    }
 8073
 8074    pub fn add_selection_above(&mut self, _: &AddSelectionAbove, cx: &mut ViewContext<Self>) {
 8075        self.add_selection(true, cx);
 8076    }
 8077
 8078    pub fn add_selection_below(&mut self, _: &AddSelectionBelow, cx: &mut ViewContext<Self>) {
 8079        self.add_selection(false, cx);
 8080    }
 8081
 8082    fn add_selection(&mut self, above: bool, cx: &mut ViewContext<Self>) {
 8083        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8084        let mut selections = self.selections.all::<Point>(cx);
 8085        let text_layout_details = self.text_layout_details(cx);
 8086        let mut state = self.add_selections_state.take().unwrap_or_else(|| {
 8087            let oldest_selection = selections.iter().min_by_key(|s| s.id).unwrap().clone();
 8088            let range = oldest_selection.display_range(&display_map).sorted();
 8089
 8090            let start_x = display_map.x_for_display_point(range.start, &text_layout_details);
 8091            let end_x = display_map.x_for_display_point(range.end, &text_layout_details);
 8092            let positions = start_x.min(end_x)..start_x.max(end_x);
 8093
 8094            selections.clear();
 8095            let mut stack = Vec::new();
 8096            for row in range.start.row().0..=range.end.row().0 {
 8097                if let Some(selection) = self.selections.build_columnar_selection(
 8098                    &display_map,
 8099                    DisplayRow(row),
 8100                    &positions,
 8101                    oldest_selection.reversed,
 8102                    &text_layout_details,
 8103                ) {
 8104                    stack.push(selection.id);
 8105                    selections.push(selection);
 8106                }
 8107            }
 8108
 8109            if above {
 8110                stack.reverse();
 8111            }
 8112
 8113            AddSelectionsState { above, stack }
 8114        });
 8115
 8116        let last_added_selection = *state.stack.last().unwrap();
 8117        let mut new_selections = Vec::new();
 8118        if above == state.above {
 8119            let end_row = if above {
 8120                DisplayRow(0)
 8121            } else {
 8122                display_map.max_point().row()
 8123            };
 8124
 8125            'outer: for selection in selections {
 8126                if selection.id == last_added_selection {
 8127                    let range = selection.display_range(&display_map).sorted();
 8128                    debug_assert_eq!(range.start.row(), range.end.row());
 8129                    let mut row = range.start.row();
 8130                    let positions =
 8131                        if let SelectionGoal::HorizontalRange { start, end } = selection.goal {
 8132                            px(start)..px(end)
 8133                        } else {
 8134                            let start_x =
 8135                                display_map.x_for_display_point(range.start, &text_layout_details);
 8136                            let end_x =
 8137                                display_map.x_for_display_point(range.end, &text_layout_details);
 8138                            start_x.min(end_x)..start_x.max(end_x)
 8139                        };
 8140
 8141                    while row != end_row {
 8142                        if above {
 8143                            row.0 -= 1;
 8144                        } else {
 8145                            row.0 += 1;
 8146                        }
 8147
 8148                        if let Some(new_selection) = self.selections.build_columnar_selection(
 8149                            &display_map,
 8150                            row,
 8151                            &positions,
 8152                            selection.reversed,
 8153                            &text_layout_details,
 8154                        ) {
 8155                            state.stack.push(new_selection.id);
 8156                            if above {
 8157                                new_selections.push(new_selection);
 8158                                new_selections.push(selection);
 8159                            } else {
 8160                                new_selections.push(selection);
 8161                                new_selections.push(new_selection);
 8162                            }
 8163
 8164                            continue 'outer;
 8165                        }
 8166                    }
 8167                }
 8168
 8169                new_selections.push(selection);
 8170            }
 8171        } else {
 8172            new_selections = selections;
 8173            new_selections.retain(|s| s.id != last_added_selection);
 8174            state.stack.pop();
 8175        }
 8176
 8177        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 8178            s.select(new_selections);
 8179        });
 8180        if state.stack.len() > 1 {
 8181            self.add_selections_state = Some(state);
 8182        }
 8183    }
 8184
 8185    pub fn select_next_match_internal(
 8186        &mut self,
 8187        display_map: &DisplaySnapshot,
 8188        replace_newest: bool,
 8189        autoscroll: Option<Autoscroll>,
 8190        cx: &mut ViewContext<Self>,
 8191    ) -> Result<()> {
 8192        fn select_next_match_ranges(
 8193            this: &mut Editor,
 8194            range: Range<usize>,
 8195            replace_newest: bool,
 8196            auto_scroll: Option<Autoscroll>,
 8197            cx: &mut ViewContext<Editor>,
 8198        ) {
 8199            this.unfold_ranges(&[range.clone()], false, true, cx);
 8200            this.change_selections(auto_scroll, cx, |s| {
 8201                if replace_newest {
 8202                    s.delete(s.newest_anchor().id);
 8203                }
 8204                s.insert_range(range.clone());
 8205            });
 8206        }
 8207
 8208        let buffer = &display_map.buffer_snapshot;
 8209        let mut selections = self.selections.all::<usize>(cx);
 8210        if let Some(mut select_next_state) = self.select_next_state.take() {
 8211            let query = &select_next_state.query;
 8212            if !select_next_state.done {
 8213                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
 8214                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
 8215                let mut next_selected_range = None;
 8216
 8217                let bytes_after_last_selection =
 8218                    buffer.bytes_in_range(last_selection.end..buffer.len());
 8219                let bytes_before_first_selection = buffer.bytes_in_range(0..first_selection.start);
 8220                let query_matches = query
 8221                    .stream_find_iter(bytes_after_last_selection)
 8222                    .map(|result| (last_selection.end, result))
 8223                    .chain(
 8224                        query
 8225                            .stream_find_iter(bytes_before_first_selection)
 8226                            .map(|result| (0, result)),
 8227                    );
 8228
 8229                for (start_offset, query_match) in query_matches {
 8230                    let query_match = query_match.unwrap(); // can only fail due to I/O
 8231                    let offset_range =
 8232                        start_offset + query_match.start()..start_offset + query_match.end();
 8233                    let display_range = offset_range.start.to_display_point(display_map)
 8234                        ..offset_range.end.to_display_point(display_map);
 8235
 8236                    if !select_next_state.wordwise
 8237                        || (!movement::is_inside_word(display_map, display_range.start)
 8238                            && !movement::is_inside_word(display_map, display_range.end))
 8239                    {
 8240                        // TODO: This is n^2, because we might check all the selections
 8241                        if !selections
 8242                            .iter()
 8243                            .any(|selection| selection.range().overlaps(&offset_range))
 8244                        {
 8245                            next_selected_range = Some(offset_range);
 8246                            break;
 8247                        }
 8248                    }
 8249                }
 8250
 8251                if let Some(next_selected_range) = next_selected_range {
 8252                    select_next_match_ranges(
 8253                        self,
 8254                        next_selected_range,
 8255                        replace_newest,
 8256                        autoscroll,
 8257                        cx,
 8258                    );
 8259                } else {
 8260                    select_next_state.done = true;
 8261                }
 8262            }
 8263
 8264            self.select_next_state = Some(select_next_state);
 8265        } else {
 8266            let mut only_carets = true;
 8267            let mut same_text_selected = true;
 8268            let mut selected_text = None;
 8269
 8270            let mut selections_iter = selections.iter().peekable();
 8271            while let Some(selection) = selections_iter.next() {
 8272                if selection.start != selection.end {
 8273                    only_carets = false;
 8274                }
 8275
 8276                if same_text_selected {
 8277                    if selected_text.is_none() {
 8278                        selected_text =
 8279                            Some(buffer.text_for_range(selection.range()).collect::<String>());
 8280                    }
 8281
 8282                    if let Some(next_selection) = selections_iter.peek() {
 8283                        if next_selection.range().len() == selection.range().len() {
 8284                            let next_selected_text = buffer
 8285                                .text_for_range(next_selection.range())
 8286                                .collect::<String>();
 8287                            if Some(next_selected_text) != selected_text {
 8288                                same_text_selected = false;
 8289                                selected_text = None;
 8290                            }
 8291                        } else {
 8292                            same_text_selected = false;
 8293                            selected_text = None;
 8294                        }
 8295                    }
 8296                }
 8297            }
 8298
 8299            if only_carets {
 8300                for selection in &mut selections {
 8301                    let word_range = movement::surrounding_word(
 8302                        display_map,
 8303                        selection.start.to_display_point(display_map),
 8304                    );
 8305                    selection.start = word_range.start.to_offset(display_map, Bias::Left);
 8306                    selection.end = word_range.end.to_offset(display_map, Bias::Left);
 8307                    selection.goal = SelectionGoal::None;
 8308                    selection.reversed = false;
 8309                    select_next_match_ranges(
 8310                        self,
 8311                        selection.start..selection.end,
 8312                        replace_newest,
 8313                        autoscroll,
 8314                        cx,
 8315                    );
 8316                }
 8317
 8318                if selections.len() == 1 {
 8319                    let selection = selections
 8320                        .last()
 8321                        .expect("ensured that there's only one selection");
 8322                    let query = buffer
 8323                        .text_for_range(selection.start..selection.end)
 8324                        .collect::<String>();
 8325                    let is_empty = query.is_empty();
 8326                    let select_state = SelectNextState {
 8327                        query: AhoCorasick::new(&[query])?,
 8328                        wordwise: true,
 8329                        done: is_empty,
 8330                    };
 8331                    self.select_next_state = Some(select_state);
 8332                } else {
 8333                    self.select_next_state = None;
 8334                }
 8335            } else if let Some(selected_text) = selected_text {
 8336                self.select_next_state = Some(SelectNextState {
 8337                    query: AhoCorasick::new(&[selected_text])?,
 8338                    wordwise: false,
 8339                    done: false,
 8340                });
 8341                self.select_next_match_internal(display_map, replace_newest, autoscroll, cx)?;
 8342            }
 8343        }
 8344        Ok(())
 8345    }
 8346
 8347    pub fn select_all_matches(
 8348        &mut self,
 8349        _action: &SelectAllMatches,
 8350        cx: &mut ViewContext<Self>,
 8351    ) -> Result<()> {
 8352        self.push_to_selection_history();
 8353        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8354
 8355        self.select_next_match_internal(&display_map, false, None, cx)?;
 8356        let Some(select_next_state) = self.select_next_state.as_mut() else {
 8357            return Ok(());
 8358        };
 8359        if select_next_state.done {
 8360            return Ok(());
 8361        }
 8362
 8363        let mut new_selections = self.selections.all::<usize>(cx);
 8364
 8365        let buffer = &display_map.buffer_snapshot;
 8366        let query_matches = select_next_state
 8367            .query
 8368            .stream_find_iter(buffer.bytes_in_range(0..buffer.len()));
 8369
 8370        for query_match in query_matches {
 8371            let query_match = query_match.unwrap(); // can only fail due to I/O
 8372            let offset_range = query_match.start()..query_match.end();
 8373            let display_range = offset_range.start.to_display_point(&display_map)
 8374                ..offset_range.end.to_display_point(&display_map);
 8375
 8376            if !select_next_state.wordwise
 8377                || (!movement::is_inside_word(&display_map, display_range.start)
 8378                    && !movement::is_inside_word(&display_map, display_range.end))
 8379            {
 8380                self.selections.change_with(cx, |selections| {
 8381                    new_selections.push(Selection {
 8382                        id: selections.new_selection_id(),
 8383                        start: offset_range.start,
 8384                        end: offset_range.end,
 8385                        reversed: false,
 8386                        goal: SelectionGoal::None,
 8387                    });
 8388                });
 8389            }
 8390        }
 8391
 8392        new_selections.sort_by_key(|selection| selection.start);
 8393        let mut ix = 0;
 8394        while ix + 1 < new_selections.len() {
 8395            let current_selection = &new_selections[ix];
 8396            let next_selection = &new_selections[ix + 1];
 8397            if current_selection.range().overlaps(&next_selection.range()) {
 8398                if current_selection.id < next_selection.id {
 8399                    new_selections.remove(ix + 1);
 8400                } else {
 8401                    new_selections.remove(ix);
 8402                }
 8403            } else {
 8404                ix += 1;
 8405            }
 8406        }
 8407
 8408        select_next_state.done = true;
 8409        self.unfold_ranges(
 8410            &new_selections
 8411                .iter()
 8412                .map(|selection| selection.range())
 8413                .collect::<Vec<_>>(),
 8414            false,
 8415            false,
 8416            cx,
 8417        );
 8418        self.change_selections(Some(Autoscroll::fit()), cx, |selections| {
 8419            selections.select(new_selections)
 8420        });
 8421
 8422        Ok(())
 8423    }
 8424
 8425    pub fn select_next(&mut self, action: &SelectNext, cx: &mut ViewContext<Self>) -> Result<()> {
 8426        self.push_to_selection_history();
 8427        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8428        self.select_next_match_internal(
 8429            &display_map,
 8430            action.replace_newest,
 8431            Some(Autoscroll::newest()),
 8432            cx,
 8433        )?;
 8434        Ok(())
 8435    }
 8436
 8437    pub fn select_previous(
 8438        &mut self,
 8439        action: &SelectPrevious,
 8440        cx: &mut ViewContext<Self>,
 8441    ) -> Result<()> {
 8442        self.push_to_selection_history();
 8443        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8444        let buffer = &display_map.buffer_snapshot;
 8445        let mut selections = self.selections.all::<usize>(cx);
 8446        if let Some(mut select_prev_state) = self.select_prev_state.take() {
 8447            let query = &select_prev_state.query;
 8448            if !select_prev_state.done {
 8449                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
 8450                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
 8451                let mut next_selected_range = None;
 8452                // When we're iterating matches backwards, the oldest match will actually be the furthest one in the buffer.
 8453                let bytes_before_last_selection =
 8454                    buffer.reversed_bytes_in_range(0..last_selection.start);
 8455                let bytes_after_first_selection =
 8456                    buffer.reversed_bytes_in_range(first_selection.end..buffer.len());
 8457                let query_matches = query
 8458                    .stream_find_iter(bytes_before_last_selection)
 8459                    .map(|result| (last_selection.start, result))
 8460                    .chain(
 8461                        query
 8462                            .stream_find_iter(bytes_after_first_selection)
 8463                            .map(|result| (buffer.len(), result)),
 8464                    );
 8465                for (end_offset, query_match) in query_matches {
 8466                    let query_match = query_match.unwrap(); // can only fail due to I/O
 8467                    let offset_range =
 8468                        end_offset - query_match.end()..end_offset - query_match.start();
 8469                    let display_range = offset_range.start.to_display_point(&display_map)
 8470                        ..offset_range.end.to_display_point(&display_map);
 8471
 8472                    if !select_prev_state.wordwise
 8473                        || (!movement::is_inside_word(&display_map, display_range.start)
 8474                            && !movement::is_inside_word(&display_map, display_range.end))
 8475                    {
 8476                        next_selected_range = Some(offset_range);
 8477                        break;
 8478                    }
 8479                }
 8480
 8481                if let Some(next_selected_range) = next_selected_range {
 8482                    self.unfold_ranges(&[next_selected_range.clone()], false, true, cx);
 8483                    self.change_selections(Some(Autoscroll::newest()), cx, |s| {
 8484                        if action.replace_newest {
 8485                            s.delete(s.newest_anchor().id);
 8486                        }
 8487                        s.insert_range(next_selected_range);
 8488                    });
 8489                } else {
 8490                    select_prev_state.done = true;
 8491                }
 8492            }
 8493
 8494            self.select_prev_state = Some(select_prev_state);
 8495        } else {
 8496            let mut only_carets = true;
 8497            let mut same_text_selected = true;
 8498            let mut selected_text = None;
 8499
 8500            let mut selections_iter = selections.iter().peekable();
 8501            while let Some(selection) = selections_iter.next() {
 8502                if selection.start != selection.end {
 8503                    only_carets = false;
 8504                }
 8505
 8506                if same_text_selected {
 8507                    if selected_text.is_none() {
 8508                        selected_text =
 8509                            Some(buffer.text_for_range(selection.range()).collect::<String>());
 8510                    }
 8511
 8512                    if let Some(next_selection) = selections_iter.peek() {
 8513                        if next_selection.range().len() == selection.range().len() {
 8514                            let next_selected_text = buffer
 8515                                .text_for_range(next_selection.range())
 8516                                .collect::<String>();
 8517                            if Some(next_selected_text) != selected_text {
 8518                                same_text_selected = false;
 8519                                selected_text = None;
 8520                            }
 8521                        } else {
 8522                            same_text_selected = false;
 8523                            selected_text = None;
 8524                        }
 8525                    }
 8526                }
 8527            }
 8528
 8529            if only_carets {
 8530                for selection in &mut selections {
 8531                    let word_range = movement::surrounding_word(
 8532                        &display_map,
 8533                        selection.start.to_display_point(&display_map),
 8534                    );
 8535                    selection.start = word_range.start.to_offset(&display_map, Bias::Left);
 8536                    selection.end = word_range.end.to_offset(&display_map, Bias::Left);
 8537                    selection.goal = SelectionGoal::None;
 8538                    selection.reversed = false;
 8539                }
 8540                if selections.len() == 1 {
 8541                    let selection = selections
 8542                        .last()
 8543                        .expect("ensured that there's only one selection");
 8544                    let query = buffer
 8545                        .text_for_range(selection.start..selection.end)
 8546                        .collect::<String>();
 8547                    let is_empty = query.is_empty();
 8548                    let select_state = SelectNextState {
 8549                        query: AhoCorasick::new(&[query.chars().rev().collect::<String>()])?,
 8550                        wordwise: true,
 8551                        done: is_empty,
 8552                    };
 8553                    self.select_prev_state = Some(select_state);
 8554                } else {
 8555                    self.select_prev_state = None;
 8556                }
 8557
 8558                self.unfold_ranges(
 8559                    &selections.iter().map(|s| s.range()).collect::<Vec<_>>(),
 8560                    false,
 8561                    true,
 8562                    cx,
 8563                );
 8564                self.change_selections(Some(Autoscroll::newest()), cx, |s| {
 8565                    s.select(selections);
 8566                });
 8567            } else if let Some(selected_text) = selected_text {
 8568                self.select_prev_state = Some(SelectNextState {
 8569                    query: AhoCorasick::new(&[selected_text.chars().rev().collect::<String>()])?,
 8570                    wordwise: false,
 8571                    done: false,
 8572                });
 8573                self.select_previous(action, cx)?;
 8574            }
 8575        }
 8576        Ok(())
 8577    }
 8578
 8579    pub fn toggle_comments(&mut self, action: &ToggleComments, cx: &mut ViewContext<Self>) {
 8580        if self.read_only(cx) {
 8581            return;
 8582        }
 8583        let text_layout_details = &self.text_layout_details(cx);
 8584        self.transact(cx, |this, cx| {
 8585            let mut selections = this.selections.all::<MultiBufferPoint>(cx);
 8586            let mut edits = Vec::new();
 8587            let mut selection_edit_ranges = Vec::new();
 8588            let mut last_toggled_row = None;
 8589            let snapshot = this.buffer.read(cx).read(cx);
 8590            let empty_str: Arc<str> = Arc::default();
 8591            let mut suffixes_inserted = Vec::new();
 8592            let ignore_indent = action.ignore_indent;
 8593
 8594            fn comment_prefix_range(
 8595                snapshot: &MultiBufferSnapshot,
 8596                row: MultiBufferRow,
 8597                comment_prefix: &str,
 8598                comment_prefix_whitespace: &str,
 8599                ignore_indent: bool,
 8600            ) -> Range<Point> {
 8601                let indent_size = if ignore_indent {
 8602                    0
 8603                } else {
 8604                    snapshot.indent_size_for_line(row).len
 8605                };
 8606
 8607                let start = Point::new(row.0, indent_size);
 8608
 8609                let mut line_bytes = snapshot
 8610                    .bytes_in_range(start..snapshot.max_point())
 8611                    .flatten()
 8612                    .copied();
 8613
 8614                // If this line currently begins with the line comment prefix, then record
 8615                // the range containing the prefix.
 8616                if line_bytes
 8617                    .by_ref()
 8618                    .take(comment_prefix.len())
 8619                    .eq(comment_prefix.bytes())
 8620                {
 8621                    // Include any whitespace that matches the comment prefix.
 8622                    let matching_whitespace_len = line_bytes
 8623                        .zip(comment_prefix_whitespace.bytes())
 8624                        .take_while(|(a, b)| a == b)
 8625                        .count() as u32;
 8626                    let end = Point::new(
 8627                        start.row,
 8628                        start.column + comment_prefix.len() as u32 + matching_whitespace_len,
 8629                    );
 8630                    start..end
 8631                } else {
 8632                    start..start
 8633                }
 8634            }
 8635
 8636            fn comment_suffix_range(
 8637                snapshot: &MultiBufferSnapshot,
 8638                row: MultiBufferRow,
 8639                comment_suffix: &str,
 8640                comment_suffix_has_leading_space: bool,
 8641            ) -> Range<Point> {
 8642                let end = Point::new(row.0, snapshot.line_len(row));
 8643                let suffix_start_column = end.column.saturating_sub(comment_suffix.len() as u32);
 8644
 8645                let mut line_end_bytes = snapshot
 8646                    .bytes_in_range(Point::new(end.row, suffix_start_column.saturating_sub(1))..end)
 8647                    .flatten()
 8648                    .copied();
 8649
 8650                let leading_space_len = if suffix_start_column > 0
 8651                    && line_end_bytes.next() == Some(b' ')
 8652                    && comment_suffix_has_leading_space
 8653                {
 8654                    1
 8655                } else {
 8656                    0
 8657                };
 8658
 8659                // If this line currently begins with the line comment prefix, then record
 8660                // the range containing the prefix.
 8661                if line_end_bytes.by_ref().eq(comment_suffix.bytes()) {
 8662                    let start = Point::new(end.row, suffix_start_column - leading_space_len);
 8663                    start..end
 8664                } else {
 8665                    end..end
 8666                }
 8667            }
 8668
 8669            // TODO: Handle selections that cross excerpts
 8670            for selection in &mut selections {
 8671                let start_column = snapshot
 8672                    .indent_size_for_line(MultiBufferRow(selection.start.row))
 8673                    .len;
 8674                let language = if let Some(language) =
 8675                    snapshot.language_scope_at(Point::new(selection.start.row, start_column))
 8676                {
 8677                    language
 8678                } else {
 8679                    continue;
 8680                };
 8681
 8682                selection_edit_ranges.clear();
 8683
 8684                // If multiple selections contain a given row, avoid processing that
 8685                // row more than once.
 8686                let mut start_row = MultiBufferRow(selection.start.row);
 8687                if last_toggled_row == Some(start_row) {
 8688                    start_row = start_row.next_row();
 8689                }
 8690                let end_row =
 8691                    if selection.end.row > selection.start.row && selection.end.column == 0 {
 8692                        MultiBufferRow(selection.end.row - 1)
 8693                    } else {
 8694                        MultiBufferRow(selection.end.row)
 8695                    };
 8696                last_toggled_row = Some(end_row);
 8697
 8698                if start_row > end_row {
 8699                    continue;
 8700                }
 8701
 8702                // If the language has line comments, toggle those.
 8703                let mut full_comment_prefixes = language.line_comment_prefixes().to_vec();
 8704
 8705                // If ignore_indent is set, trim spaces from the right side of all full_comment_prefixes
 8706                if ignore_indent {
 8707                    full_comment_prefixes = full_comment_prefixes
 8708                        .into_iter()
 8709                        .map(|s| Arc::from(s.trim_end()))
 8710                        .collect();
 8711                }
 8712
 8713                if !full_comment_prefixes.is_empty() {
 8714                    let first_prefix = full_comment_prefixes
 8715                        .first()
 8716                        .expect("prefixes is non-empty");
 8717                    let prefix_trimmed_lengths = full_comment_prefixes
 8718                        .iter()
 8719                        .map(|p| p.trim_end_matches(' ').len())
 8720                        .collect::<SmallVec<[usize; 4]>>();
 8721
 8722                    let mut all_selection_lines_are_comments = true;
 8723
 8724                    for row in start_row.0..=end_row.0 {
 8725                        let row = MultiBufferRow(row);
 8726                        if start_row < end_row && snapshot.is_line_blank(row) {
 8727                            continue;
 8728                        }
 8729
 8730                        let prefix_range = full_comment_prefixes
 8731                            .iter()
 8732                            .zip(prefix_trimmed_lengths.iter().copied())
 8733                            .map(|(prefix, trimmed_prefix_len)| {
 8734                                comment_prefix_range(
 8735                                    snapshot.deref(),
 8736                                    row,
 8737                                    &prefix[..trimmed_prefix_len],
 8738                                    &prefix[trimmed_prefix_len..],
 8739                                    ignore_indent,
 8740                                )
 8741                            })
 8742                            .max_by_key(|range| range.end.column - range.start.column)
 8743                            .expect("prefixes is non-empty");
 8744
 8745                        if prefix_range.is_empty() {
 8746                            all_selection_lines_are_comments = false;
 8747                        }
 8748
 8749                        selection_edit_ranges.push(prefix_range);
 8750                    }
 8751
 8752                    if all_selection_lines_are_comments {
 8753                        edits.extend(
 8754                            selection_edit_ranges
 8755                                .iter()
 8756                                .cloned()
 8757                                .map(|range| (range, empty_str.clone())),
 8758                        );
 8759                    } else {
 8760                        let min_column = selection_edit_ranges
 8761                            .iter()
 8762                            .map(|range| range.start.column)
 8763                            .min()
 8764                            .unwrap_or(0);
 8765                        edits.extend(selection_edit_ranges.iter().map(|range| {
 8766                            let position = Point::new(range.start.row, min_column);
 8767                            (position..position, first_prefix.clone())
 8768                        }));
 8769                    }
 8770                } else if let Some((full_comment_prefix, comment_suffix)) =
 8771                    language.block_comment_delimiters()
 8772                {
 8773                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
 8774                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
 8775                    let prefix_range = comment_prefix_range(
 8776                        snapshot.deref(),
 8777                        start_row,
 8778                        comment_prefix,
 8779                        comment_prefix_whitespace,
 8780                        ignore_indent,
 8781                    );
 8782                    let suffix_range = comment_suffix_range(
 8783                        snapshot.deref(),
 8784                        end_row,
 8785                        comment_suffix.trim_start_matches(' '),
 8786                        comment_suffix.starts_with(' '),
 8787                    );
 8788
 8789                    if prefix_range.is_empty() || suffix_range.is_empty() {
 8790                        edits.push((
 8791                            prefix_range.start..prefix_range.start,
 8792                            full_comment_prefix.clone(),
 8793                        ));
 8794                        edits.push((suffix_range.end..suffix_range.end, comment_suffix.clone()));
 8795                        suffixes_inserted.push((end_row, comment_suffix.len()));
 8796                    } else {
 8797                        edits.push((prefix_range, empty_str.clone()));
 8798                        edits.push((suffix_range, empty_str.clone()));
 8799                    }
 8800                } else {
 8801                    continue;
 8802                }
 8803            }
 8804
 8805            drop(snapshot);
 8806            this.buffer.update(cx, |buffer, cx| {
 8807                buffer.edit(edits, None, cx);
 8808            });
 8809
 8810            // Adjust selections so that they end before any comment suffixes that
 8811            // were inserted.
 8812            let mut suffixes_inserted = suffixes_inserted.into_iter().peekable();
 8813            let mut selections = this.selections.all::<Point>(cx);
 8814            let snapshot = this.buffer.read(cx).read(cx);
 8815            for selection in &mut selections {
 8816                while let Some((row, suffix_len)) = suffixes_inserted.peek().copied() {
 8817                    match row.cmp(&MultiBufferRow(selection.end.row)) {
 8818                        Ordering::Less => {
 8819                            suffixes_inserted.next();
 8820                            continue;
 8821                        }
 8822                        Ordering::Greater => break,
 8823                        Ordering::Equal => {
 8824                            if selection.end.column == snapshot.line_len(row) {
 8825                                if selection.is_empty() {
 8826                                    selection.start.column -= suffix_len as u32;
 8827                                }
 8828                                selection.end.column -= suffix_len as u32;
 8829                            }
 8830                            break;
 8831                        }
 8832                    }
 8833                }
 8834            }
 8835
 8836            drop(snapshot);
 8837            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
 8838
 8839            let selections = this.selections.all::<Point>(cx);
 8840            let selections_on_single_row = selections.windows(2).all(|selections| {
 8841                selections[0].start.row == selections[1].start.row
 8842                    && selections[0].end.row == selections[1].end.row
 8843                    && selections[0].start.row == selections[0].end.row
 8844            });
 8845            let selections_selecting = selections
 8846                .iter()
 8847                .any(|selection| selection.start != selection.end);
 8848            let advance_downwards = action.advance_downwards
 8849                && selections_on_single_row
 8850                && !selections_selecting
 8851                && !matches!(this.mode, EditorMode::SingleLine { .. });
 8852
 8853            if advance_downwards {
 8854                let snapshot = this.buffer.read(cx).snapshot(cx);
 8855
 8856                this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 8857                    s.move_cursors_with(|display_snapshot, display_point, _| {
 8858                        let mut point = display_point.to_point(display_snapshot);
 8859                        point.row += 1;
 8860                        point = snapshot.clip_point(point, Bias::Left);
 8861                        let display_point = point.to_display_point(display_snapshot);
 8862                        let goal = SelectionGoal::HorizontalPosition(
 8863                            display_snapshot
 8864                                .x_for_display_point(display_point, text_layout_details)
 8865                                .into(),
 8866                        );
 8867                        (display_point, goal)
 8868                    })
 8869                });
 8870            }
 8871        });
 8872    }
 8873
 8874    pub fn select_enclosing_symbol(
 8875        &mut self,
 8876        _: &SelectEnclosingSymbol,
 8877        cx: &mut ViewContext<Self>,
 8878    ) {
 8879        let buffer = self.buffer.read(cx).snapshot(cx);
 8880        let old_selections = self.selections.all::<usize>(cx).into_boxed_slice();
 8881
 8882        fn update_selection(
 8883            selection: &Selection<usize>,
 8884            buffer_snap: &MultiBufferSnapshot,
 8885        ) -> Option<Selection<usize>> {
 8886            let cursor = selection.head();
 8887            let (_buffer_id, symbols) = buffer_snap.symbols_containing(cursor, None)?;
 8888            for symbol in symbols.iter().rev() {
 8889                let start = symbol.range.start.to_offset(buffer_snap);
 8890                let end = symbol.range.end.to_offset(buffer_snap);
 8891                let new_range = start..end;
 8892                if start < selection.start || end > selection.end {
 8893                    return Some(Selection {
 8894                        id: selection.id,
 8895                        start: new_range.start,
 8896                        end: new_range.end,
 8897                        goal: SelectionGoal::None,
 8898                        reversed: selection.reversed,
 8899                    });
 8900                }
 8901            }
 8902            None
 8903        }
 8904
 8905        let mut selected_larger_symbol = false;
 8906        let new_selections = old_selections
 8907            .iter()
 8908            .map(|selection| match update_selection(selection, &buffer) {
 8909                Some(new_selection) => {
 8910                    if new_selection.range() != selection.range() {
 8911                        selected_larger_symbol = true;
 8912                    }
 8913                    new_selection
 8914                }
 8915                None => selection.clone(),
 8916            })
 8917            .collect::<Vec<_>>();
 8918
 8919        if selected_larger_symbol {
 8920            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 8921                s.select(new_selections);
 8922            });
 8923        }
 8924    }
 8925
 8926    pub fn select_larger_syntax_node(
 8927        &mut self,
 8928        _: &SelectLargerSyntaxNode,
 8929        cx: &mut ViewContext<Self>,
 8930    ) {
 8931        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8932        let buffer = self.buffer.read(cx).snapshot(cx);
 8933        let old_selections = self.selections.all::<usize>(cx).into_boxed_slice();
 8934
 8935        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
 8936        let mut selected_larger_node = false;
 8937        let new_selections = old_selections
 8938            .iter()
 8939            .map(|selection| {
 8940                let old_range = selection.start..selection.end;
 8941                let mut new_range = old_range.clone();
 8942                let mut new_node = None;
 8943                while let Some((node, containing_range)) = buffer.syntax_ancestor(new_range.clone())
 8944                {
 8945                    new_node = Some(node);
 8946                    new_range = containing_range;
 8947                    if !display_map.intersects_fold(new_range.start)
 8948                        && !display_map.intersects_fold(new_range.end)
 8949                    {
 8950                        break;
 8951                    }
 8952                }
 8953
 8954                if let Some(node) = new_node {
 8955                    // Log the ancestor, to support using this action as a way to explore TreeSitter
 8956                    // nodes. Parent and grandparent are also logged because this operation will not
 8957                    // visit nodes that have the same range as their parent.
 8958                    log::info!("Node: {node:?}");
 8959                    let parent = node.parent();
 8960                    log::info!("Parent: {parent:?}");
 8961                    let grandparent = parent.and_then(|x| x.parent());
 8962                    log::info!("Grandparent: {grandparent:?}");
 8963                }
 8964
 8965                selected_larger_node |= new_range != old_range;
 8966                Selection {
 8967                    id: selection.id,
 8968                    start: new_range.start,
 8969                    end: new_range.end,
 8970                    goal: SelectionGoal::None,
 8971                    reversed: selection.reversed,
 8972                }
 8973            })
 8974            .collect::<Vec<_>>();
 8975
 8976        if selected_larger_node {
 8977            stack.push(old_selections);
 8978            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 8979                s.select(new_selections);
 8980            });
 8981        }
 8982        self.select_larger_syntax_node_stack = stack;
 8983    }
 8984
 8985    pub fn select_smaller_syntax_node(
 8986        &mut self,
 8987        _: &SelectSmallerSyntaxNode,
 8988        cx: &mut ViewContext<Self>,
 8989    ) {
 8990        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
 8991        if let Some(selections) = stack.pop() {
 8992            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 8993                s.select(selections.to_vec());
 8994            });
 8995        }
 8996        self.select_larger_syntax_node_stack = stack;
 8997    }
 8998
 8999    fn refresh_runnables(&mut self, cx: &mut ViewContext<Self>) -> Task<()> {
 9000        if !EditorSettings::get_global(cx).gutter.runnables {
 9001            self.clear_tasks();
 9002            return Task::ready(());
 9003        }
 9004        let project = self.project.as_ref().map(Model::downgrade);
 9005        cx.spawn(|this, mut cx| async move {
 9006            cx.background_executor().timer(UPDATE_DEBOUNCE).await;
 9007            let Some(project) = project.and_then(|p| p.upgrade()) else {
 9008                return;
 9009            };
 9010            let Ok(display_snapshot) = this.update(&mut cx, |this, cx| {
 9011                this.display_map.update(cx, |map, cx| map.snapshot(cx))
 9012            }) else {
 9013                return;
 9014            };
 9015
 9016            let hide_runnables = project
 9017                .update(&mut cx, |project, cx| {
 9018                    // Do not display any test indicators in non-dev server remote projects.
 9019                    project.is_via_collab() && project.ssh_connection_string(cx).is_none()
 9020                })
 9021                .unwrap_or(true);
 9022            if hide_runnables {
 9023                return;
 9024            }
 9025            let new_rows =
 9026                cx.background_executor()
 9027                    .spawn({
 9028                        let snapshot = display_snapshot.clone();
 9029                        async move {
 9030                            Self::fetch_runnable_ranges(&snapshot, Anchor::min()..Anchor::max())
 9031                        }
 9032                    })
 9033                    .await;
 9034            let rows = Self::runnable_rows(project, display_snapshot, new_rows, cx.clone());
 9035
 9036            this.update(&mut cx, |this, _| {
 9037                this.clear_tasks();
 9038                for (key, value) in rows {
 9039                    this.insert_tasks(key, value);
 9040                }
 9041            })
 9042            .ok();
 9043        })
 9044    }
 9045    fn fetch_runnable_ranges(
 9046        snapshot: &DisplaySnapshot,
 9047        range: Range<Anchor>,
 9048    ) -> Vec<language::RunnableRange> {
 9049        snapshot.buffer_snapshot.runnable_ranges(range).collect()
 9050    }
 9051
 9052    fn runnable_rows(
 9053        project: Model<Project>,
 9054        snapshot: DisplaySnapshot,
 9055        runnable_ranges: Vec<RunnableRange>,
 9056        mut cx: AsyncWindowContext,
 9057    ) -> Vec<((BufferId, u32), RunnableTasks)> {
 9058        runnable_ranges
 9059            .into_iter()
 9060            .filter_map(|mut runnable| {
 9061                let tasks = cx
 9062                    .update(|cx| Self::templates_with_tags(&project, &mut runnable.runnable, cx))
 9063                    .ok()?;
 9064                if tasks.is_empty() {
 9065                    return None;
 9066                }
 9067
 9068                let point = runnable.run_range.start.to_point(&snapshot.buffer_snapshot);
 9069
 9070                let row = snapshot
 9071                    .buffer_snapshot
 9072                    .buffer_line_for_row(MultiBufferRow(point.row))?
 9073                    .1
 9074                    .start
 9075                    .row;
 9076
 9077                let context_range =
 9078                    BufferOffset(runnable.full_range.start)..BufferOffset(runnable.full_range.end);
 9079                Some((
 9080                    (runnable.buffer_id, row),
 9081                    RunnableTasks {
 9082                        templates: tasks,
 9083                        offset: MultiBufferOffset(runnable.run_range.start),
 9084                        context_range,
 9085                        column: point.column,
 9086                        extra_variables: runnable.extra_captures,
 9087                    },
 9088                ))
 9089            })
 9090            .collect()
 9091    }
 9092
 9093    fn templates_with_tags(
 9094        project: &Model<Project>,
 9095        runnable: &mut Runnable,
 9096        cx: &WindowContext,
 9097    ) -> Vec<(TaskSourceKind, TaskTemplate)> {
 9098        let (inventory, worktree_id, file) = project.read_with(cx, |project, cx| {
 9099            let (worktree_id, file) = project
 9100                .buffer_for_id(runnable.buffer, cx)
 9101                .and_then(|buffer| buffer.read(cx).file())
 9102                .map(|file| (file.worktree_id(cx), file.clone()))
 9103                .unzip();
 9104
 9105            (
 9106                project.task_store().read(cx).task_inventory().cloned(),
 9107                worktree_id,
 9108                file,
 9109            )
 9110        });
 9111
 9112        let tags = mem::take(&mut runnable.tags);
 9113        let mut tags: Vec<_> = tags
 9114            .into_iter()
 9115            .flat_map(|tag| {
 9116                let tag = tag.0.clone();
 9117                inventory
 9118                    .as_ref()
 9119                    .into_iter()
 9120                    .flat_map(|inventory| {
 9121                        inventory.read(cx).list_tasks(
 9122                            file.clone(),
 9123                            Some(runnable.language.clone()),
 9124                            worktree_id,
 9125                            cx,
 9126                        )
 9127                    })
 9128                    .filter(move |(_, template)| {
 9129                        template.tags.iter().any(|source_tag| source_tag == &tag)
 9130                    })
 9131            })
 9132            .sorted_by_key(|(kind, _)| kind.to_owned())
 9133            .collect();
 9134        if let Some((leading_tag_source, _)) = tags.first() {
 9135            // Strongest source wins; if we have worktree tag binding, prefer that to
 9136            // global and language bindings;
 9137            // if we have a global binding, prefer that to language binding.
 9138            let first_mismatch = tags
 9139                .iter()
 9140                .position(|(tag_source, _)| tag_source != leading_tag_source);
 9141            if let Some(index) = first_mismatch {
 9142                tags.truncate(index);
 9143            }
 9144        }
 9145
 9146        tags
 9147    }
 9148
 9149    pub fn move_to_enclosing_bracket(
 9150        &mut self,
 9151        _: &MoveToEnclosingBracket,
 9152        cx: &mut ViewContext<Self>,
 9153    ) {
 9154        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 9155            s.move_offsets_with(|snapshot, selection| {
 9156                let Some(enclosing_bracket_ranges) =
 9157                    snapshot.enclosing_bracket_ranges(selection.start..selection.end)
 9158                else {
 9159                    return;
 9160                };
 9161
 9162                let mut best_length = usize::MAX;
 9163                let mut best_inside = false;
 9164                let mut best_in_bracket_range = false;
 9165                let mut best_destination = None;
 9166                for (open, close) in enclosing_bracket_ranges {
 9167                    let close = close.to_inclusive();
 9168                    let length = close.end() - open.start;
 9169                    let inside = selection.start >= open.end && selection.end <= *close.start();
 9170                    let in_bracket_range = open.to_inclusive().contains(&selection.head())
 9171                        || close.contains(&selection.head());
 9172
 9173                    // If best is next to a bracket and current isn't, skip
 9174                    if !in_bracket_range && best_in_bracket_range {
 9175                        continue;
 9176                    }
 9177
 9178                    // Prefer smaller lengths unless best is inside and current isn't
 9179                    if length > best_length && (best_inside || !inside) {
 9180                        continue;
 9181                    }
 9182
 9183                    best_length = length;
 9184                    best_inside = inside;
 9185                    best_in_bracket_range = in_bracket_range;
 9186                    best_destination = Some(
 9187                        if close.contains(&selection.start) && close.contains(&selection.end) {
 9188                            if inside {
 9189                                open.end
 9190                            } else {
 9191                                open.start
 9192                            }
 9193                        } else if inside {
 9194                            *close.start()
 9195                        } else {
 9196                            *close.end()
 9197                        },
 9198                    );
 9199                }
 9200
 9201                if let Some(destination) = best_destination {
 9202                    selection.collapse_to(destination, SelectionGoal::None);
 9203                }
 9204            })
 9205        });
 9206    }
 9207
 9208    pub fn undo_selection(&mut self, _: &UndoSelection, cx: &mut ViewContext<Self>) {
 9209        self.end_selection(cx);
 9210        self.selection_history.mode = SelectionHistoryMode::Undoing;
 9211        if let Some(entry) = self.selection_history.undo_stack.pop_back() {
 9212            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
 9213            self.select_next_state = entry.select_next_state;
 9214            self.select_prev_state = entry.select_prev_state;
 9215            self.add_selections_state = entry.add_selections_state;
 9216            self.request_autoscroll(Autoscroll::newest(), cx);
 9217        }
 9218        self.selection_history.mode = SelectionHistoryMode::Normal;
 9219    }
 9220
 9221    pub fn redo_selection(&mut self, _: &RedoSelection, cx: &mut ViewContext<Self>) {
 9222        self.end_selection(cx);
 9223        self.selection_history.mode = SelectionHistoryMode::Redoing;
 9224        if let Some(entry) = self.selection_history.redo_stack.pop_back() {
 9225            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
 9226            self.select_next_state = entry.select_next_state;
 9227            self.select_prev_state = entry.select_prev_state;
 9228            self.add_selections_state = entry.add_selections_state;
 9229            self.request_autoscroll(Autoscroll::newest(), cx);
 9230        }
 9231        self.selection_history.mode = SelectionHistoryMode::Normal;
 9232    }
 9233
 9234    pub fn expand_excerpts(&mut self, action: &ExpandExcerpts, cx: &mut ViewContext<Self>) {
 9235        self.expand_excerpts_for_direction(action.lines, ExpandExcerptDirection::UpAndDown, cx)
 9236    }
 9237
 9238    pub fn expand_excerpts_down(
 9239        &mut self,
 9240        action: &ExpandExcerptsDown,
 9241        cx: &mut ViewContext<Self>,
 9242    ) {
 9243        self.expand_excerpts_for_direction(action.lines, ExpandExcerptDirection::Down, cx)
 9244    }
 9245
 9246    pub fn expand_excerpts_up(&mut self, action: &ExpandExcerptsUp, cx: &mut ViewContext<Self>) {
 9247        self.expand_excerpts_for_direction(action.lines, ExpandExcerptDirection::Up, cx)
 9248    }
 9249
 9250    pub fn expand_excerpts_for_direction(
 9251        &mut self,
 9252        lines: u32,
 9253        direction: ExpandExcerptDirection,
 9254        cx: &mut ViewContext<Self>,
 9255    ) {
 9256        let selections = self.selections.disjoint_anchors();
 9257
 9258        let lines = if lines == 0 {
 9259            EditorSettings::get_global(cx).expand_excerpt_lines
 9260        } else {
 9261            lines
 9262        };
 9263
 9264        self.buffer.update(cx, |buffer, cx| {
 9265            let snapshot = buffer.snapshot(cx);
 9266            let mut excerpt_ids = selections
 9267                .iter()
 9268                .flat_map(|selection| {
 9269                    snapshot
 9270                        .excerpts_for_range(selection.range())
 9271                        .map(|excerpt| excerpt.id())
 9272                })
 9273                .collect::<Vec<_>>();
 9274            excerpt_ids.sort();
 9275            excerpt_ids.dedup();
 9276            buffer.expand_excerpts(excerpt_ids, lines, direction, cx)
 9277        })
 9278    }
 9279
 9280    pub fn expand_excerpt(
 9281        &mut self,
 9282        excerpt: ExcerptId,
 9283        direction: ExpandExcerptDirection,
 9284        cx: &mut ViewContext<Self>,
 9285    ) {
 9286        let lines = EditorSettings::get_global(cx).expand_excerpt_lines;
 9287        self.buffer.update(cx, |buffer, cx| {
 9288            buffer.expand_excerpts([excerpt], lines, direction, cx)
 9289        })
 9290    }
 9291
 9292    fn go_to_diagnostic(&mut self, _: &GoToDiagnostic, cx: &mut ViewContext<Self>) {
 9293        self.go_to_diagnostic_impl(Direction::Next, cx)
 9294    }
 9295
 9296    fn go_to_prev_diagnostic(&mut self, _: &GoToPrevDiagnostic, cx: &mut ViewContext<Self>) {
 9297        self.go_to_diagnostic_impl(Direction::Prev, cx)
 9298    }
 9299
 9300    pub fn go_to_diagnostic_impl(&mut self, direction: Direction, cx: &mut ViewContext<Self>) {
 9301        let buffer = self.buffer.read(cx).snapshot(cx);
 9302        let selection = self.selections.newest::<usize>(cx);
 9303
 9304        // If there is an active Diagnostic Popover jump to its diagnostic instead.
 9305        if direction == Direction::Next {
 9306            if let Some(popover) = self.hover_state.diagnostic_popover.as_ref() {
 9307                self.activate_diagnostics(popover.group_id(), cx);
 9308                if let Some(active_diagnostics) = self.active_diagnostics.as_ref() {
 9309                    let primary_range_start = active_diagnostics.primary_range.start;
 9310                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 9311                        let mut new_selection = s.newest_anchor().clone();
 9312                        new_selection.collapse_to(primary_range_start, SelectionGoal::None);
 9313                        s.select_anchors(vec![new_selection.clone()]);
 9314                    });
 9315                    self.refresh_inline_completion(false, true, cx);
 9316                }
 9317                return;
 9318            }
 9319        }
 9320
 9321        let mut active_primary_range = self.active_diagnostics.as_ref().map(|active_diagnostics| {
 9322            active_diagnostics
 9323                .primary_range
 9324                .to_offset(&buffer)
 9325                .to_inclusive()
 9326        });
 9327        let mut search_start = if let Some(active_primary_range) = active_primary_range.as_ref() {
 9328            if active_primary_range.contains(&selection.head()) {
 9329                *active_primary_range.start()
 9330            } else {
 9331                selection.head()
 9332            }
 9333        } else {
 9334            selection.head()
 9335        };
 9336        let snapshot = self.snapshot(cx);
 9337        loop {
 9338            let diagnostics = if direction == Direction::Prev {
 9339                buffer.diagnostics_in_range(0..search_start, true)
 9340            } else {
 9341                buffer.diagnostics_in_range(search_start..buffer.len(), false)
 9342            }
 9343            .filter(|diagnostic| !snapshot.intersects_fold(diagnostic.range.start));
 9344            let search_start_anchor = buffer.anchor_after(search_start);
 9345            let group = diagnostics
 9346                // relies on diagnostics_in_range to return diagnostics with the same starting range to
 9347                // be sorted in a stable way
 9348                // skip until we are at current active diagnostic, if it exists
 9349                .skip_while(|entry| {
 9350                    let is_in_range = match direction {
 9351                        Direction::Prev => {
 9352                            entry.range.start.cmp(&search_start_anchor, &buffer).is_ge()
 9353                        }
 9354                        Direction::Next => {
 9355                            entry.range.start.cmp(&search_start_anchor, &buffer).is_le()
 9356                        }
 9357                    };
 9358                    is_in_range
 9359                        && self
 9360                            .active_diagnostics
 9361                            .as_ref()
 9362                            .is_some_and(|a| a.group_id != entry.diagnostic.group_id)
 9363                })
 9364                .find_map(|entry| {
 9365                    if entry.diagnostic.is_primary
 9366                        && entry.diagnostic.severity <= DiagnosticSeverity::WARNING
 9367                        && !(entry.range.start == entry.range.end)
 9368                        // if we match with the active diagnostic, skip it
 9369                        && Some(entry.diagnostic.group_id)
 9370                            != self.active_diagnostics.as_ref().map(|d| d.group_id)
 9371                    {
 9372                        Some((entry.range, entry.diagnostic.group_id))
 9373                    } else {
 9374                        None
 9375                    }
 9376                });
 9377
 9378            if let Some((primary_range, group_id)) = group {
 9379                self.activate_diagnostics(group_id, cx);
 9380                let primary_range = primary_range.to_offset(&buffer);
 9381                if self.active_diagnostics.is_some() {
 9382                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 9383                        s.select(vec![Selection {
 9384                            id: selection.id,
 9385                            start: primary_range.start,
 9386                            end: primary_range.start,
 9387                            reversed: false,
 9388                            goal: SelectionGoal::None,
 9389                        }]);
 9390                    });
 9391                    self.refresh_inline_completion(false, true, cx);
 9392                }
 9393                break;
 9394            } else {
 9395                // Cycle around to the start of the buffer, potentially moving back to the start of
 9396                // the currently active diagnostic.
 9397                active_primary_range.take();
 9398                if direction == Direction::Prev {
 9399                    if search_start == buffer.len() {
 9400                        break;
 9401                    } else {
 9402                        search_start = buffer.len();
 9403                    }
 9404                } else if search_start == 0 {
 9405                    break;
 9406                } else {
 9407                    search_start = 0;
 9408                }
 9409            }
 9410        }
 9411    }
 9412
 9413    fn go_to_next_hunk(&mut self, _: &GoToHunk, cx: &mut ViewContext<Self>) {
 9414        let snapshot = self.snapshot(cx);
 9415        let selection = self.selections.newest::<Point>(cx);
 9416        self.go_to_hunk_after_position(&snapshot, selection.head(), cx);
 9417    }
 9418
 9419    fn go_to_hunk_after_position(
 9420        &mut self,
 9421        snapshot: &EditorSnapshot,
 9422        position: Point,
 9423        cx: &mut ViewContext<Editor>,
 9424    ) -> Option<MultiBufferDiffHunk> {
 9425        for (ix, position) in [position, Point::zero()].into_iter().enumerate() {
 9426            if let Some(hunk) = self.go_to_next_hunk_in_direction(
 9427                snapshot,
 9428                position,
 9429                ix > 0,
 9430                snapshot.diff_map.diff_hunks_in_range(
 9431                    position + Point::new(1, 0)..snapshot.buffer_snapshot.max_point(),
 9432                    &snapshot.buffer_snapshot,
 9433                ),
 9434                cx,
 9435            ) {
 9436                return Some(hunk);
 9437            }
 9438        }
 9439        None
 9440    }
 9441
 9442    fn go_to_prev_hunk(&mut self, _: &GoToPrevHunk, cx: &mut ViewContext<Self>) {
 9443        let snapshot = self.snapshot(cx);
 9444        let selection = self.selections.newest::<Point>(cx);
 9445        self.go_to_hunk_before_position(&snapshot, selection.head(), cx);
 9446    }
 9447
 9448    fn go_to_hunk_before_position(
 9449        &mut self,
 9450        snapshot: &EditorSnapshot,
 9451        position: Point,
 9452        cx: &mut ViewContext<Editor>,
 9453    ) -> Option<MultiBufferDiffHunk> {
 9454        for (ix, position) in [position, snapshot.buffer_snapshot.max_point()]
 9455            .into_iter()
 9456            .enumerate()
 9457        {
 9458            if let Some(hunk) = self.go_to_next_hunk_in_direction(
 9459                snapshot,
 9460                position,
 9461                ix > 0,
 9462                snapshot
 9463                    .diff_map
 9464                    .diff_hunks_in_range_rev(Point::zero()..position, &snapshot.buffer_snapshot),
 9465                cx,
 9466            ) {
 9467                return Some(hunk);
 9468            }
 9469        }
 9470        None
 9471    }
 9472
 9473    fn go_to_next_hunk_in_direction(
 9474        &mut self,
 9475        snapshot: &DisplaySnapshot,
 9476        initial_point: Point,
 9477        is_wrapped: bool,
 9478        hunks: impl Iterator<Item = MultiBufferDiffHunk>,
 9479        cx: &mut ViewContext<Editor>,
 9480    ) -> Option<MultiBufferDiffHunk> {
 9481        let display_point = initial_point.to_display_point(snapshot);
 9482        let mut hunks = hunks
 9483            .map(|hunk| (diff_hunk_to_display(&hunk, snapshot), hunk))
 9484            .filter(|(display_hunk, _)| {
 9485                is_wrapped || !display_hunk.contains_display_row(display_point.row())
 9486            })
 9487            .dedup();
 9488
 9489        if let Some((display_hunk, hunk)) = hunks.next() {
 9490            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 9491                let row = display_hunk.start_display_row();
 9492                let point = DisplayPoint::new(row, 0);
 9493                s.select_display_ranges([point..point]);
 9494            });
 9495
 9496            Some(hunk)
 9497        } else {
 9498            None
 9499        }
 9500    }
 9501
 9502    pub fn go_to_definition(
 9503        &mut self,
 9504        _: &GoToDefinition,
 9505        cx: &mut ViewContext<Self>,
 9506    ) -> Task<Result<Navigated>> {
 9507        let definition = self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, false, cx);
 9508        cx.spawn(|editor, mut cx| async move {
 9509            if definition.await? == Navigated::Yes {
 9510                return Ok(Navigated::Yes);
 9511            }
 9512            match editor.update(&mut cx, |editor, cx| {
 9513                editor.find_all_references(&FindAllReferences, cx)
 9514            })? {
 9515                Some(references) => references.await,
 9516                None => Ok(Navigated::No),
 9517            }
 9518        })
 9519    }
 9520
 9521    pub fn go_to_declaration(
 9522        &mut self,
 9523        _: &GoToDeclaration,
 9524        cx: &mut ViewContext<Self>,
 9525    ) -> Task<Result<Navigated>> {
 9526        self.go_to_definition_of_kind(GotoDefinitionKind::Declaration, false, cx)
 9527    }
 9528
 9529    pub fn go_to_declaration_split(
 9530        &mut self,
 9531        _: &GoToDeclaration,
 9532        cx: &mut ViewContext<Self>,
 9533    ) -> Task<Result<Navigated>> {
 9534        self.go_to_definition_of_kind(GotoDefinitionKind::Declaration, true, cx)
 9535    }
 9536
 9537    pub fn go_to_implementation(
 9538        &mut self,
 9539        _: &GoToImplementation,
 9540        cx: &mut ViewContext<Self>,
 9541    ) -> Task<Result<Navigated>> {
 9542        self.go_to_definition_of_kind(GotoDefinitionKind::Implementation, false, cx)
 9543    }
 9544
 9545    pub fn go_to_implementation_split(
 9546        &mut self,
 9547        _: &GoToImplementationSplit,
 9548        cx: &mut ViewContext<Self>,
 9549    ) -> Task<Result<Navigated>> {
 9550        self.go_to_definition_of_kind(GotoDefinitionKind::Implementation, true, cx)
 9551    }
 9552
 9553    pub fn go_to_type_definition(
 9554        &mut self,
 9555        _: &GoToTypeDefinition,
 9556        cx: &mut ViewContext<Self>,
 9557    ) -> Task<Result<Navigated>> {
 9558        self.go_to_definition_of_kind(GotoDefinitionKind::Type, false, cx)
 9559    }
 9560
 9561    pub fn go_to_definition_split(
 9562        &mut self,
 9563        _: &GoToDefinitionSplit,
 9564        cx: &mut ViewContext<Self>,
 9565    ) -> Task<Result<Navigated>> {
 9566        self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, true, cx)
 9567    }
 9568
 9569    pub fn go_to_type_definition_split(
 9570        &mut self,
 9571        _: &GoToTypeDefinitionSplit,
 9572        cx: &mut ViewContext<Self>,
 9573    ) -> Task<Result<Navigated>> {
 9574        self.go_to_definition_of_kind(GotoDefinitionKind::Type, true, cx)
 9575    }
 9576
 9577    fn go_to_definition_of_kind(
 9578        &mut self,
 9579        kind: GotoDefinitionKind,
 9580        split: bool,
 9581        cx: &mut ViewContext<Self>,
 9582    ) -> Task<Result<Navigated>> {
 9583        let Some(provider) = self.semantics_provider.clone() else {
 9584            return Task::ready(Ok(Navigated::No));
 9585        };
 9586        let head = self.selections.newest::<usize>(cx).head();
 9587        let buffer = self.buffer.read(cx);
 9588        let (buffer, head) = if let Some(text_anchor) = buffer.text_anchor_for_position(head, cx) {
 9589            text_anchor
 9590        } else {
 9591            return Task::ready(Ok(Navigated::No));
 9592        };
 9593
 9594        let Some(definitions) = provider.definitions(&buffer, head, kind, cx) else {
 9595            return Task::ready(Ok(Navigated::No));
 9596        };
 9597
 9598        cx.spawn(|editor, mut cx| async move {
 9599            let definitions = definitions.await?;
 9600            let navigated = editor
 9601                .update(&mut cx, |editor, cx| {
 9602                    editor.navigate_to_hover_links(
 9603                        Some(kind),
 9604                        definitions
 9605                            .into_iter()
 9606                            .filter(|location| {
 9607                                hover_links::exclude_link_to_position(&buffer, &head, location, cx)
 9608                            })
 9609                            .map(HoverLink::Text)
 9610                            .collect::<Vec<_>>(),
 9611                        split,
 9612                        cx,
 9613                    )
 9614                })?
 9615                .await?;
 9616            anyhow::Ok(navigated)
 9617        })
 9618    }
 9619
 9620    pub fn open_url(&mut self, _: &OpenUrl, cx: &mut ViewContext<Self>) {
 9621        let selection = self.selections.newest_anchor();
 9622        let head = selection.head();
 9623        let tail = selection.tail();
 9624
 9625        let Some((buffer, start_position)) =
 9626            self.buffer.read(cx).text_anchor_for_position(head, cx)
 9627        else {
 9628            return;
 9629        };
 9630
 9631        let end_position = if head != tail {
 9632            let Some((_, pos)) = self.buffer.read(cx).text_anchor_for_position(tail, cx) else {
 9633                return;
 9634            };
 9635            Some(pos)
 9636        } else {
 9637            None
 9638        };
 9639
 9640        let url_finder = cx.spawn(|editor, mut cx| async move {
 9641            let url = if let Some(end_pos) = end_position {
 9642                find_url_from_range(&buffer, start_position..end_pos, cx.clone())
 9643            } else {
 9644                find_url(&buffer, start_position, cx.clone()).map(|(_, url)| url)
 9645            };
 9646
 9647            if let Some(url) = url {
 9648                editor.update(&mut cx, |_, cx| {
 9649                    cx.open_url(&url);
 9650                })
 9651            } else {
 9652                Ok(())
 9653            }
 9654        });
 9655
 9656        url_finder.detach();
 9657    }
 9658
 9659    pub fn open_selected_filename(&mut self, _: &OpenSelectedFilename, cx: &mut ViewContext<Self>) {
 9660        let Some(workspace) = self.workspace() else {
 9661            return;
 9662        };
 9663
 9664        let position = self.selections.newest_anchor().head();
 9665
 9666        let Some((buffer, buffer_position)) =
 9667            self.buffer.read(cx).text_anchor_for_position(position, cx)
 9668        else {
 9669            return;
 9670        };
 9671
 9672        let project = self.project.clone();
 9673
 9674        cx.spawn(|_, mut cx| async move {
 9675            let result = find_file(&buffer, project, buffer_position, &mut cx).await;
 9676
 9677            if let Some((_, path)) = result {
 9678                workspace
 9679                    .update(&mut cx, |workspace, cx| {
 9680                        workspace.open_resolved_path(path, cx)
 9681                    })?
 9682                    .await?;
 9683            }
 9684            anyhow::Ok(())
 9685        })
 9686        .detach();
 9687    }
 9688
 9689    pub(crate) fn navigate_to_hover_links(
 9690        &mut self,
 9691        kind: Option<GotoDefinitionKind>,
 9692        mut definitions: Vec<HoverLink>,
 9693        split: bool,
 9694        cx: &mut ViewContext<Editor>,
 9695    ) -> Task<Result<Navigated>> {
 9696        // If there is one definition, just open it directly
 9697        if definitions.len() == 1 {
 9698            let definition = definitions.pop().unwrap();
 9699
 9700            enum TargetTaskResult {
 9701                Location(Option<Location>),
 9702                AlreadyNavigated,
 9703            }
 9704
 9705            let target_task = match definition {
 9706                HoverLink::Text(link) => {
 9707                    Task::ready(anyhow::Ok(TargetTaskResult::Location(Some(link.target))))
 9708                }
 9709                HoverLink::InlayHint(lsp_location, server_id) => {
 9710                    let computation = self.compute_target_location(lsp_location, server_id, cx);
 9711                    cx.background_executor().spawn(async move {
 9712                        let location = computation.await?;
 9713                        Ok(TargetTaskResult::Location(location))
 9714                    })
 9715                }
 9716                HoverLink::Url(url) => {
 9717                    cx.open_url(&url);
 9718                    Task::ready(Ok(TargetTaskResult::AlreadyNavigated))
 9719                }
 9720                HoverLink::File(path) => {
 9721                    if let Some(workspace) = self.workspace() {
 9722                        cx.spawn(|_, mut cx| async move {
 9723                            workspace
 9724                                .update(&mut cx, |workspace, cx| {
 9725                                    workspace.open_resolved_path(path, cx)
 9726                                })?
 9727                                .await
 9728                                .map(|_| TargetTaskResult::AlreadyNavigated)
 9729                        })
 9730                    } else {
 9731                        Task::ready(Ok(TargetTaskResult::Location(None)))
 9732                    }
 9733                }
 9734            };
 9735            cx.spawn(|editor, mut cx| async move {
 9736                let target = match target_task.await.context("target resolution task")? {
 9737                    TargetTaskResult::AlreadyNavigated => return Ok(Navigated::Yes),
 9738                    TargetTaskResult::Location(None) => return Ok(Navigated::No),
 9739                    TargetTaskResult::Location(Some(target)) => target,
 9740                };
 9741
 9742                editor.update(&mut cx, |editor, cx| {
 9743                    let Some(workspace) = editor.workspace() else {
 9744                        return Navigated::No;
 9745                    };
 9746                    let pane = workspace.read(cx).active_pane().clone();
 9747
 9748                    let range = target.range.to_offset(target.buffer.read(cx));
 9749                    let range = editor.range_for_match(&range);
 9750
 9751                    if Some(&target.buffer) == editor.buffer.read(cx).as_singleton().as_ref() {
 9752                        let buffer = target.buffer.read(cx);
 9753                        let range = check_multiline_range(buffer, range);
 9754                        editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
 9755                            s.select_ranges([range]);
 9756                        });
 9757                    } else {
 9758                        cx.window_context().defer(move |cx| {
 9759                            let target_editor: View<Self> =
 9760                                workspace.update(cx, |workspace, cx| {
 9761                                    let pane = if split {
 9762                                        workspace.adjacent_pane(cx)
 9763                                    } else {
 9764                                        workspace.active_pane().clone()
 9765                                    };
 9766
 9767                                    workspace.open_project_item(
 9768                                        pane,
 9769                                        target.buffer.clone(),
 9770                                        true,
 9771                                        true,
 9772                                        cx,
 9773                                    )
 9774                                });
 9775                            target_editor.update(cx, |target_editor, cx| {
 9776                                // When selecting a definition in a different buffer, disable the nav history
 9777                                // to avoid creating a history entry at the previous cursor location.
 9778                                pane.update(cx, |pane, _| pane.disable_history());
 9779                                let buffer = target.buffer.read(cx);
 9780                                let range = check_multiline_range(buffer, range);
 9781                                target_editor.change_selections(
 9782                                    Some(Autoscroll::focused()),
 9783                                    cx,
 9784                                    |s| {
 9785                                        s.select_ranges([range]);
 9786                                    },
 9787                                );
 9788                                pane.update(cx, |pane, _| pane.enable_history());
 9789                            });
 9790                        });
 9791                    }
 9792                    Navigated::Yes
 9793                })
 9794            })
 9795        } else if !definitions.is_empty() {
 9796            cx.spawn(|editor, mut cx| async move {
 9797                let (title, location_tasks, workspace) = editor
 9798                    .update(&mut cx, |editor, cx| {
 9799                        let tab_kind = match kind {
 9800                            Some(GotoDefinitionKind::Implementation) => "Implementations",
 9801                            _ => "Definitions",
 9802                        };
 9803                        let title = definitions
 9804                            .iter()
 9805                            .find_map(|definition| match definition {
 9806                                HoverLink::Text(link) => link.origin.as_ref().map(|origin| {
 9807                                    let buffer = origin.buffer.read(cx);
 9808                                    format!(
 9809                                        "{} for {}",
 9810                                        tab_kind,
 9811                                        buffer
 9812                                            .text_for_range(origin.range.clone())
 9813                                            .collect::<String>()
 9814                                    )
 9815                                }),
 9816                                HoverLink::InlayHint(_, _) => None,
 9817                                HoverLink::Url(_) => None,
 9818                                HoverLink::File(_) => None,
 9819                            })
 9820                            .unwrap_or(tab_kind.to_string());
 9821                        let location_tasks = definitions
 9822                            .into_iter()
 9823                            .map(|definition| match definition {
 9824                                HoverLink::Text(link) => Task::ready(Ok(Some(link.target))),
 9825                                HoverLink::InlayHint(lsp_location, server_id) => {
 9826                                    editor.compute_target_location(lsp_location, server_id, cx)
 9827                                }
 9828                                HoverLink::Url(_) => Task::ready(Ok(None)),
 9829                                HoverLink::File(_) => Task::ready(Ok(None)),
 9830                            })
 9831                            .collect::<Vec<_>>();
 9832                        (title, location_tasks, editor.workspace().clone())
 9833                    })
 9834                    .context("location tasks preparation")?;
 9835
 9836                let locations = future::join_all(location_tasks)
 9837                    .await
 9838                    .into_iter()
 9839                    .filter_map(|location| location.transpose())
 9840                    .collect::<Result<_>>()
 9841                    .context("location tasks")?;
 9842
 9843                let Some(workspace) = workspace else {
 9844                    return Ok(Navigated::No);
 9845                };
 9846                let opened = workspace
 9847                    .update(&mut cx, |workspace, cx| {
 9848                        Self::open_locations_in_multibuffer(workspace, locations, title, split, cx)
 9849                    })
 9850                    .ok();
 9851
 9852                anyhow::Ok(Navigated::from_bool(opened.is_some()))
 9853            })
 9854        } else {
 9855            Task::ready(Ok(Navigated::No))
 9856        }
 9857    }
 9858
 9859    fn compute_target_location(
 9860        &self,
 9861        lsp_location: lsp::Location,
 9862        server_id: LanguageServerId,
 9863        cx: &mut ViewContext<Self>,
 9864    ) -> Task<anyhow::Result<Option<Location>>> {
 9865        let Some(project) = self.project.clone() else {
 9866            return Task::ready(Ok(None));
 9867        };
 9868
 9869        cx.spawn(move |editor, mut cx| async move {
 9870            let location_task = editor.update(&mut cx, |_, cx| {
 9871                project.update(cx, |project, cx| {
 9872                    let language_server_name = project
 9873                        .language_server_statuses(cx)
 9874                        .find(|(id, _)| server_id == *id)
 9875                        .map(|(_, status)| LanguageServerName::from(status.name.as_str()));
 9876                    language_server_name.map(|language_server_name| {
 9877                        project.open_local_buffer_via_lsp(
 9878                            lsp_location.uri.clone(),
 9879                            server_id,
 9880                            language_server_name,
 9881                            cx,
 9882                        )
 9883                    })
 9884                })
 9885            })?;
 9886            let location = match location_task {
 9887                Some(task) => Some({
 9888                    let target_buffer_handle = task.await.context("open local buffer")?;
 9889                    let range = target_buffer_handle.update(&mut cx, |target_buffer, _| {
 9890                        let target_start = target_buffer
 9891                            .clip_point_utf16(point_from_lsp(lsp_location.range.start), Bias::Left);
 9892                        let target_end = target_buffer
 9893                            .clip_point_utf16(point_from_lsp(lsp_location.range.end), Bias::Left);
 9894                        target_buffer.anchor_after(target_start)
 9895                            ..target_buffer.anchor_before(target_end)
 9896                    })?;
 9897                    Location {
 9898                        buffer: target_buffer_handle,
 9899                        range,
 9900                    }
 9901                }),
 9902                None => None,
 9903            };
 9904            Ok(location)
 9905        })
 9906    }
 9907
 9908    pub fn find_all_references(
 9909        &mut self,
 9910        _: &FindAllReferences,
 9911        cx: &mut ViewContext<Self>,
 9912    ) -> Option<Task<Result<Navigated>>> {
 9913        let selection = self.selections.newest::<usize>(cx);
 9914        let multi_buffer = self.buffer.read(cx);
 9915        let head = selection.head();
 9916
 9917        let multi_buffer_snapshot = multi_buffer.snapshot(cx);
 9918        let head_anchor = multi_buffer_snapshot.anchor_at(
 9919            head,
 9920            if head < selection.tail() {
 9921                Bias::Right
 9922            } else {
 9923                Bias::Left
 9924            },
 9925        );
 9926
 9927        match self
 9928            .find_all_references_task_sources
 9929            .binary_search_by(|anchor| anchor.cmp(&head_anchor, &multi_buffer_snapshot))
 9930        {
 9931            Ok(_) => {
 9932                log::info!(
 9933                    "Ignoring repeated FindAllReferences invocation with the position of already running task"
 9934                );
 9935                return None;
 9936            }
 9937            Err(i) => {
 9938                self.find_all_references_task_sources.insert(i, head_anchor);
 9939            }
 9940        }
 9941
 9942        let (buffer, head) = multi_buffer.text_anchor_for_position(head, cx)?;
 9943        let workspace = self.workspace()?;
 9944        let project = workspace.read(cx).project().clone();
 9945        let references = project.update(cx, |project, cx| project.references(&buffer, head, cx));
 9946        Some(cx.spawn(|editor, mut cx| async move {
 9947            let _cleanup = defer({
 9948                let mut cx = cx.clone();
 9949                move || {
 9950                    let _ = editor.update(&mut cx, |editor, _| {
 9951                        if let Ok(i) =
 9952                            editor
 9953                                .find_all_references_task_sources
 9954                                .binary_search_by(|anchor| {
 9955                                    anchor.cmp(&head_anchor, &multi_buffer_snapshot)
 9956                                })
 9957                        {
 9958                            editor.find_all_references_task_sources.remove(i);
 9959                        }
 9960                    });
 9961                }
 9962            });
 9963
 9964            let locations = references.await?;
 9965            if locations.is_empty() {
 9966                return anyhow::Ok(Navigated::No);
 9967            }
 9968
 9969            workspace.update(&mut cx, |workspace, cx| {
 9970                let title = locations
 9971                    .first()
 9972                    .as_ref()
 9973                    .map(|location| {
 9974                        let buffer = location.buffer.read(cx);
 9975                        format!(
 9976                            "References to `{}`",
 9977                            buffer
 9978                                .text_for_range(location.range.clone())
 9979                                .collect::<String>()
 9980                        )
 9981                    })
 9982                    .unwrap();
 9983                Self::open_locations_in_multibuffer(workspace, locations, title, false, cx);
 9984                Navigated::Yes
 9985            })
 9986        }))
 9987    }
 9988
 9989    /// Opens a multibuffer with the given project locations in it
 9990    pub fn open_locations_in_multibuffer(
 9991        workspace: &mut Workspace,
 9992        mut locations: Vec<Location>,
 9993        title: String,
 9994        split: bool,
 9995        cx: &mut ViewContext<Workspace>,
 9996    ) {
 9997        // If there are multiple definitions, open them in a multibuffer
 9998        locations.sort_by_key(|location| location.buffer.read(cx).remote_id());
 9999        let mut locations = locations.into_iter().peekable();
10000        let mut ranges_to_highlight = Vec::new();
10001        let capability = workspace.project().read(cx).capability();
10002
10003        let excerpt_buffer = cx.new_model(|cx| {
10004            let mut multibuffer = MultiBuffer::new(capability);
10005            while let Some(location) = locations.next() {
10006                let buffer = location.buffer.read(cx);
10007                let mut ranges_for_buffer = Vec::new();
10008                let range = location.range.to_offset(buffer);
10009                ranges_for_buffer.push(range.clone());
10010
10011                while let Some(next_location) = locations.peek() {
10012                    if next_location.buffer == location.buffer {
10013                        ranges_for_buffer.push(next_location.range.to_offset(buffer));
10014                        locations.next();
10015                    } else {
10016                        break;
10017                    }
10018                }
10019
10020                ranges_for_buffer.sort_by_key(|range| (range.start, Reverse(range.end)));
10021                ranges_to_highlight.extend(multibuffer.push_excerpts_with_context_lines(
10022                    location.buffer.clone(),
10023                    ranges_for_buffer,
10024                    DEFAULT_MULTIBUFFER_CONTEXT,
10025                    cx,
10026                ))
10027            }
10028
10029            multibuffer.with_title(title)
10030        });
10031
10032        let editor = cx.new_view(|cx| {
10033            Editor::for_multibuffer(excerpt_buffer, Some(workspace.project().clone()), true, cx)
10034        });
10035        editor.update(cx, |editor, cx| {
10036            if let Some(first_range) = ranges_to_highlight.first() {
10037                editor.change_selections(None, cx, |selections| {
10038                    selections.clear_disjoint();
10039                    selections.select_anchor_ranges(std::iter::once(first_range.clone()));
10040                });
10041            }
10042            editor.highlight_background::<Self>(
10043                &ranges_to_highlight,
10044                |theme| theme.editor_highlighted_line_background,
10045                cx,
10046            );
10047            editor.register_buffers_with_language_servers(cx);
10048        });
10049
10050        let item = Box::new(editor);
10051        let item_id = item.item_id();
10052
10053        if split {
10054            workspace.split_item(SplitDirection::Right, item.clone(), cx);
10055        } else {
10056            let destination_index = workspace.active_pane().update(cx, |pane, cx| {
10057                if PreviewTabsSettings::get_global(cx).enable_preview_from_code_navigation {
10058                    pane.close_current_preview_item(cx)
10059                } else {
10060                    None
10061                }
10062            });
10063            workspace.add_item_to_active_pane(item.clone(), destination_index, true, cx);
10064        }
10065        workspace.active_pane().update(cx, |pane, cx| {
10066            pane.set_preview_item_id(Some(item_id), cx);
10067        });
10068    }
10069
10070    pub fn rename(&mut self, _: &Rename, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
10071        use language::ToOffset as _;
10072
10073        let provider = self.semantics_provider.clone()?;
10074        let selection = self.selections.newest_anchor().clone();
10075        let (cursor_buffer, cursor_buffer_position) = self
10076            .buffer
10077            .read(cx)
10078            .text_anchor_for_position(selection.head(), cx)?;
10079        let (tail_buffer, cursor_buffer_position_end) = self
10080            .buffer
10081            .read(cx)
10082            .text_anchor_for_position(selection.tail(), cx)?;
10083        if tail_buffer != cursor_buffer {
10084            return None;
10085        }
10086
10087        let snapshot = cursor_buffer.read(cx).snapshot();
10088        let cursor_buffer_offset = cursor_buffer_position.to_offset(&snapshot);
10089        let cursor_buffer_offset_end = cursor_buffer_position_end.to_offset(&snapshot);
10090        let prepare_rename = provider
10091            .range_for_rename(&cursor_buffer, cursor_buffer_position, cx)
10092            .unwrap_or_else(|| Task::ready(Ok(None)));
10093        drop(snapshot);
10094
10095        Some(cx.spawn(|this, mut cx| async move {
10096            let rename_range = if let Some(range) = prepare_rename.await? {
10097                Some(range)
10098            } else {
10099                this.update(&mut cx, |this, cx| {
10100                    let buffer = this.buffer.read(cx).snapshot(cx);
10101                    let mut buffer_highlights = this
10102                        .document_highlights_for_position(selection.head(), &buffer)
10103                        .filter(|highlight| {
10104                            highlight.start.excerpt_id == selection.head().excerpt_id
10105                                && highlight.end.excerpt_id == selection.head().excerpt_id
10106                        });
10107                    buffer_highlights
10108                        .next()
10109                        .map(|highlight| highlight.start.text_anchor..highlight.end.text_anchor)
10110                })?
10111            };
10112            if let Some(rename_range) = rename_range {
10113                this.update(&mut cx, |this, cx| {
10114                    let snapshot = cursor_buffer.read(cx).snapshot();
10115                    let rename_buffer_range = rename_range.to_offset(&snapshot);
10116                    let cursor_offset_in_rename_range =
10117                        cursor_buffer_offset.saturating_sub(rename_buffer_range.start);
10118                    let cursor_offset_in_rename_range_end =
10119                        cursor_buffer_offset_end.saturating_sub(rename_buffer_range.start);
10120
10121                    this.take_rename(false, cx);
10122                    let buffer = this.buffer.read(cx).read(cx);
10123                    let cursor_offset = selection.head().to_offset(&buffer);
10124                    let rename_start = cursor_offset.saturating_sub(cursor_offset_in_rename_range);
10125                    let rename_end = rename_start + rename_buffer_range.len();
10126                    let range = buffer.anchor_before(rename_start)..buffer.anchor_after(rename_end);
10127                    let mut old_highlight_id = None;
10128                    let old_name: Arc<str> = buffer
10129                        .chunks(rename_start..rename_end, true)
10130                        .map(|chunk| {
10131                            if old_highlight_id.is_none() {
10132                                old_highlight_id = chunk.syntax_highlight_id;
10133                            }
10134                            chunk.text
10135                        })
10136                        .collect::<String>()
10137                        .into();
10138
10139                    drop(buffer);
10140
10141                    // Position the selection in the rename editor so that it matches the current selection.
10142                    this.show_local_selections = false;
10143                    let rename_editor = cx.new_view(|cx| {
10144                        let mut editor = Editor::single_line(cx);
10145                        editor.buffer.update(cx, |buffer, cx| {
10146                            buffer.edit([(0..0, old_name.clone())], None, cx)
10147                        });
10148                        let rename_selection_range = match cursor_offset_in_rename_range
10149                            .cmp(&cursor_offset_in_rename_range_end)
10150                        {
10151                            Ordering::Equal => {
10152                                editor.select_all(&SelectAll, cx);
10153                                return editor;
10154                            }
10155                            Ordering::Less => {
10156                                cursor_offset_in_rename_range..cursor_offset_in_rename_range_end
10157                            }
10158                            Ordering::Greater => {
10159                                cursor_offset_in_rename_range_end..cursor_offset_in_rename_range
10160                            }
10161                        };
10162                        if rename_selection_range.end > old_name.len() {
10163                            editor.select_all(&SelectAll, cx);
10164                        } else {
10165                            editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
10166                                s.select_ranges([rename_selection_range]);
10167                            });
10168                        }
10169                        editor
10170                    });
10171                    cx.subscribe(&rename_editor, |_, _, e: &EditorEvent, cx| {
10172                        if e == &EditorEvent::Focused {
10173                            cx.emit(EditorEvent::FocusedIn)
10174                        }
10175                    })
10176                    .detach();
10177
10178                    let write_highlights =
10179                        this.clear_background_highlights::<DocumentHighlightWrite>(cx);
10180                    let read_highlights =
10181                        this.clear_background_highlights::<DocumentHighlightRead>(cx);
10182                    let ranges = write_highlights
10183                        .iter()
10184                        .flat_map(|(_, ranges)| ranges.iter())
10185                        .chain(read_highlights.iter().flat_map(|(_, ranges)| ranges.iter()))
10186                        .cloned()
10187                        .collect();
10188
10189                    this.highlight_text::<Rename>(
10190                        ranges,
10191                        HighlightStyle {
10192                            fade_out: Some(0.6),
10193                            ..Default::default()
10194                        },
10195                        cx,
10196                    );
10197                    let rename_focus_handle = rename_editor.focus_handle(cx);
10198                    cx.focus(&rename_focus_handle);
10199                    let block_id = this.insert_blocks(
10200                        [BlockProperties {
10201                            style: BlockStyle::Flex,
10202                            placement: BlockPlacement::Below(range.start),
10203                            height: 1,
10204                            render: Arc::new({
10205                                let rename_editor = rename_editor.clone();
10206                                move |cx: &mut BlockContext| {
10207                                    let mut text_style = cx.editor_style.text.clone();
10208                                    if let Some(highlight_style) = old_highlight_id
10209                                        .and_then(|h| h.style(&cx.editor_style.syntax))
10210                                    {
10211                                        text_style = text_style.highlight(highlight_style);
10212                                    }
10213                                    div()
10214                                        .block_mouse_down()
10215                                        .pl(cx.anchor_x)
10216                                        .child(EditorElement::new(
10217                                            &rename_editor,
10218                                            EditorStyle {
10219                                                background: cx.theme().system().transparent,
10220                                                local_player: cx.editor_style.local_player,
10221                                                text: text_style,
10222                                                scrollbar_width: cx.editor_style.scrollbar_width,
10223                                                syntax: cx.editor_style.syntax.clone(),
10224                                                status: cx.editor_style.status.clone(),
10225                                                inlay_hints_style: HighlightStyle {
10226                                                    font_weight: Some(FontWeight::BOLD),
10227                                                    ..make_inlay_hints_style(cx)
10228                                                },
10229                                                inline_completion_styles: make_suggestion_styles(
10230                                                    cx,
10231                                                ),
10232                                                ..EditorStyle::default()
10233                                            },
10234                                        ))
10235                                        .into_any_element()
10236                                }
10237                            }),
10238                            priority: 0,
10239                        }],
10240                        Some(Autoscroll::fit()),
10241                        cx,
10242                    )[0];
10243                    this.pending_rename = Some(RenameState {
10244                        range,
10245                        old_name,
10246                        editor: rename_editor,
10247                        block_id,
10248                    });
10249                })?;
10250            }
10251
10252            Ok(())
10253        }))
10254    }
10255
10256    pub fn confirm_rename(
10257        &mut self,
10258        _: &ConfirmRename,
10259        cx: &mut ViewContext<Self>,
10260    ) -> Option<Task<Result<()>>> {
10261        let rename = self.take_rename(false, cx)?;
10262        let workspace = self.workspace()?.downgrade();
10263        let (buffer, start) = self
10264            .buffer
10265            .read(cx)
10266            .text_anchor_for_position(rename.range.start, cx)?;
10267        let (end_buffer, _) = self
10268            .buffer
10269            .read(cx)
10270            .text_anchor_for_position(rename.range.end, cx)?;
10271        if buffer != end_buffer {
10272            return None;
10273        }
10274
10275        let old_name = rename.old_name;
10276        let new_name = rename.editor.read(cx).text(cx);
10277
10278        let rename = self.semantics_provider.as_ref()?.perform_rename(
10279            &buffer,
10280            start,
10281            new_name.clone(),
10282            cx,
10283        )?;
10284
10285        Some(cx.spawn(|editor, mut cx| async move {
10286            let project_transaction = rename.await?;
10287            Self::open_project_transaction(
10288                &editor,
10289                workspace,
10290                project_transaction,
10291                format!("Rename: {}{}", old_name, new_name),
10292                cx.clone(),
10293            )
10294            .await?;
10295
10296            editor.update(&mut cx, |editor, cx| {
10297                editor.refresh_document_highlights(cx);
10298            })?;
10299            Ok(())
10300        }))
10301    }
10302
10303    fn take_rename(
10304        &mut self,
10305        moving_cursor: bool,
10306        cx: &mut ViewContext<Self>,
10307    ) -> Option<RenameState> {
10308        let rename = self.pending_rename.take()?;
10309        if rename.editor.focus_handle(cx).is_focused(cx) {
10310            cx.focus(&self.focus_handle);
10311        }
10312
10313        self.remove_blocks(
10314            [rename.block_id].into_iter().collect(),
10315            Some(Autoscroll::fit()),
10316            cx,
10317        );
10318        self.clear_highlights::<Rename>(cx);
10319        self.show_local_selections = true;
10320
10321        if moving_cursor {
10322            let cursor_in_rename_editor = rename.editor.update(cx, |editor, cx| {
10323                editor.selections.newest::<usize>(cx).head()
10324            });
10325
10326            // Update the selection to match the position of the selection inside
10327            // the rename editor.
10328            let snapshot = self.buffer.read(cx).read(cx);
10329            let rename_range = rename.range.to_offset(&snapshot);
10330            let cursor_in_editor = snapshot
10331                .clip_offset(rename_range.start + cursor_in_rename_editor, Bias::Left)
10332                .min(rename_range.end);
10333            drop(snapshot);
10334
10335            self.change_selections(None, cx, |s| {
10336                s.select_ranges(vec![cursor_in_editor..cursor_in_editor])
10337            });
10338        } else {
10339            self.refresh_document_highlights(cx);
10340        }
10341
10342        Some(rename)
10343    }
10344
10345    pub fn pending_rename(&self) -> Option<&RenameState> {
10346        self.pending_rename.as_ref()
10347    }
10348
10349    fn format(&mut self, _: &Format, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
10350        let project = match &self.project {
10351            Some(project) => project.clone(),
10352            None => return None,
10353        };
10354
10355        Some(self.perform_format(project, FormatTrigger::Manual, FormatTarget::Buffers, cx))
10356    }
10357
10358    fn format_selections(
10359        &mut self,
10360        _: &FormatSelections,
10361        cx: &mut ViewContext<Self>,
10362    ) -> Option<Task<Result<()>>> {
10363        let project = match &self.project {
10364            Some(project) => project.clone(),
10365            None => return None,
10366        };
10367
10368        let ranges = self
10369            .selections
10370            .all_adjusted(cx)
10371            .into_iter()
10372            .map(|selection| selection.range())
10373            .collect_vec();
10374
10375        Some(self.perform_format(
10376            project,
10377            FormatTrigger::Manual,
10378            FormatTarget::Ranges(ranges),
10379            cx,
10380        ))
10381    }
10382
10383    fn perform_format(
10384        &mut self,
10385        project: Model<Project>,
10386        trigger: FormatTrigger,
10387        target: FormatTarget,
10388        cx: &mut ViewContext<Self>,
10389    ) -> Task<Result<()>> {
10390        let buffer = self.buffer.clone();
10391        let (buffers, target) = match target {
10392            FormatTarget::Buffers => {
10393                let mut buffers = buffer.read(cx).all_buffers();
10394                if trigger == FormatTrigger::Save {
10395                    buffers.retain(|buffer| buffer.read(cx).is_dirty());
10396                }
10397                (buffers, LspFormatTarget::Buffers)
10398            }
10399            FormatTarget::Ranges(selection_ranges) => {
10400                let multi_buffer = buffer.read(cx);
10401                let snapshot = multi_buffer.read(cx);
10402                let mut buffers = HashSet::default();
10403                let mut buffer_id_to_ranges: BTreeMap<BufferId, Vec<Range<text::Anchor>>> =
10404                    BTreeMap::new();
10405                for selection_range in selection_ranges {
10406                    for (excerpt, buffer_range) in snapshot.range_to_buffer_ranges(selection_range)
10407                    {
10408                        let buffer_id = excerpt.buffer_id();
10409                        let start = excerpt.buffer().anchor_before(buffer_range.start);
10410                        let end = excerpt.buffer().anchor_after(buffer_range.end);
10411                        buffers.insert(multi_buffer.buffer(buffer_id).unwrap());
10412                        buffer_id_to_ranges
10413                            .entry(buffer_id)
10414                            .and_modify(|buffer_ranges| buffer_ranges.push(start..end))
10415                            .or_insert_with(|| vec![start..end]);
10416                    }
10417                }
10418                (buffers, LspFormatTarget::Ranges(buffer_id_to_ranges))
10419            }
10420        };
10421
10422        let mut timeout = cx.background_executor().timer(FORMAT_TIMEOUT).fuse();
10423        let format = project.update(cx, |project, cx| {
10424            project.format(buffers, target, true, trigger, cx)
10425        });
10426
10427        cx.spawn(|_, mut cx| async move {
10428            let transaction = futures::select_biased! {
10429                () = timeout => {
10430                    log::warn!("timed out waiting for formatting");
10431                    None
10432                }
10433                transaction = format.log_err().fuse() => transaction,
10434            };
10435
10436            buffer
10437                .update(&mut cx, |buffer, cx| {
10438                    if let Some(transaction) = transaction {
10439                        if !buffer.is_singleton() {
10440                            buffer.push_transaction(&transaction.0, cx);
10441                        }
10442                    }
10443
10444                    cx.notify();
10445                })
10446                .ok();
10447
10448            Ok(())
10449        })
10450    }
10451
10452    fn restart_language_server(&mut self, _: &RestartLanguageServer, cx: &mut ViewContext<Self>) {
10453        if let Some(project) = self.project.clone() {
10454            self.buffer.update(cx, |multi_buffer, cx| {
10455                project.update(cx, |project, cx| {
10456                    project.restart_language_servers_for_buffers(multi_buffer.all_buffers(), cx);
10457                });
10458            })
10459        }
10460    }
10461
10462    fn cancel_language_server_work(
10463        &mut self,
10464        _: &actions::CancelLanguageServerWork,
10465        cx: &mut ViewContext<Self>,
10466    ) {
10467        if let Some(project) = self.project.clone() {
10468            self.buffer.update(cx, |multi_buffer, cx| {
10469                project.update(cx, |project, cx| {
10470                    project.cancel_language_server_work_for_buffers(multi_buffer.all_buffers(), cx);
10471                });
10472            })
10473        }
10474    }
10475
10476    fn show_character_palette(&mut self, _: &ShowCharacterPalette, cx: &mut ViewContext<Self>) {
10477        cx.show_character_palette();
10478    }
10479
10480    fn refresh_active_diagnostics(&mut self, cx: &mut ViewContext<Editor>) {
10481        if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
10482            let buffer = self.buffer.read(cx).snapshot(cx);
10483            let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
10484            let is_valid = buffer
10485                .diagnostics_in_range(active_diagnostics.primary_range.clone(), false)
10486                .any(|entry| {
10487                    let range = entry.range.to_offset(&buffer);
10488                    entry.diagnostic.is_primary
10489                        && !range.is_empty()
10490                        && range.start == primary_range_start
10491                        && entry.diagnostic.message == active_diagnostics.primary_message
10492                });
10493
10494            if is_valid != active_diagnostics.is_valid {
10495                active_diagnostics.is_valid = is_valid;
10496                let mut new_styles = HashMap::default();
10497                for (block_id, diagnostic) in &active_diagnostics.blocks {
10498                    new_styles.insert(
10499                        *block_id,
10500                        diagnostic_block_renderer(diagnostic.clone(), None, true, is_valid),
10501                    );
10502                }
10503                self.display_map.update(cx, |display_map, _cx| {
10504                    display_map.replace_blocks(new_styles)
10505                });
10506            }
10507        }
10508    }
10509
10510    fn activate_diagnostics(&mut self, group_id: usize, cx: &mut ViewContext<Self>) {
10511        self.dismiss_diagnostics(cx);
10512        let snapshot = self.snapshot(cx);
10513        self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
10514            let buffer = self.buffer.read(cx).snapshot(cx);
10515
10516            let mut primary_range = None;
10517            let mut primary_message = None;
10518            let mut group_end = Point::zero();
10519            let diagnostic_group = buffer
10520                .diagnostic_group(group_id)
10521                .filter_map(|entry| {
10522                    let start = entry.range.start.to_point(&buffer);
10523                    let end = entry.range.end.to_point(&buffer);
10524                    if snapshot.is_line_folded(MultiBufferRow(start.row))
10525                        && (start.row == end.row
10526                            || snapshot.is_line_folded(MultiBufferRow(end.row)))
10527                    {
10528                        return None;
10529                    }
10530                    if end > group_end {
10531                        group_end = end;
10532                    }
10533                    if entry.diagnostic.is_primary {
10534                        primary_range = Some(entry.range.clone());
10535                        primary_message = Some(entry.diagnostic.message.clone());
10536                    }
10537                    Some(entry)
10538                })
10539                .collect::<Vec<_>>();
10540            let primary_range = primary_range?;
10541            let primary_message = primary_message?;
10542
10543            let blocks = display_map
10544                .insert_blocks(
10545                    diagnostic_group.iter().map(|entry| {
10546                        let diagnostic = entry.diagnostic.clone();
10547                        let message_height = diagnostic.message.matches('\n').count() as u32 + 1;
10548                        BlockProperties {
10549                            style: BlockStyle::Fixed,
10550                            placement: BlockPlacement::Below(
10551                                buffer.anchor_after(entry.range.start),
10552                            ),
10553                            height: message_height,
10554                            render: diagnostic_block_renderer(diagnostic, None, true, true),
10555                            priority: 0,
10556                        }
10557                    }),
10558                    cx,
10559                )
10560                .into_iter()
10561                .zip(diagnostic_group.into_iter().map(|entry| entry.diagnostic))
10562                .collect();
10563
10564            Some(ActiveDiagnosticGroup {
10565                primary_range,
10566                primary_message,
10567                group_id,
10568                blocks,
10569                is_valid: true,
10570            })
10571        });
10572    }
10573
10574    fn dismiss_diagnostics(&mut self, cx: &mut ViewContext<Self>) {
10575        if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
10576            self.display_map.update(cx, |display_map, cx| {
10577                display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx);
10578            });
10579            cx.notify();
10580        }
10581    }
10582
10583    pub fn set_selections_from_remote(
10584        &mut self,
10585        selections: Vec<Selection<Anchor>>,
10586        pending_selection: Option<Selection<Anchor>>,
10587        cx: &mut ViewContext<Self>,
10588    ) {
10589        let old_cursor_position = self.selections.newest_anchor().head();
10590        self.selections.change_with(cx, |s| {
10591            s.select_anchors(selections);
10592            if let Some(pending_selection) = pending_selection {
10593                s.set_pending(pending_selection, SelectMode::Character);
10594            } else {
10595                s.clear_pending();
10596            }
10597        });
10598        self.selections_did_change(false, &old_cursor_position, true, cx);
10599    }
10600
10601    fn push_to_selection_history(&mut self) {
10602        self.selection_history.push(SelectionHistoryEntry {
10603            selections: self.selections.disjoint_anchors(),
10604            select_next_state: self.select_next_state.clone(),
10605            select_prev_state: self.select_prev_state.clone(),
10606            add_selections_state: self.add_selections_state.clone(),
10607        });
10608    }
10609
10610    pub fn transact(
10611        &mut self,
10612        cx: &mut ViewContext<Self>,
10613        update: impl FnOnce(&mut Self, &mut ViewContext<Self>),
10614    ) -> Option<TransactionId> {
10615        self.start_transaction_at(Instant::now(), cx);
10616        update(self, cx);
10617        self.end_transaction_at(Instant::now(), cx)
10618    }
10619
10620    pub fn start_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
10621        self.end_selection(cx);
10622        if let Some(tx_id) = self
10623            .buffer
10624            .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx))
10625        {
10626            self.selection_history
10627                .insert_transaction(tx_id, self.selections.disjoint_anchors());
10628            cx.emit(EditorEvent::TransactionBegun {
10629                transaction_id: tx_id,
10630            })
10631        }
10632    }
10633
10634    pub fn end_transaction_at(
10635        &mut self,
10636        now: Instant,
10637        cx: &mut ViewContext<Self>,
10638    ) -> Option<TransactionId> {
10639        if let Some(transaction_id) = self
10640            .buffer
10641            .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
10642        {
10643            if let Some((_, end_selections)) =
10644                self.selection_history.transaction_mut(transaction_id)
10645            {
10646                *end_selections = Some(self.selections.disjoint_anchors());
10647            } else {
10648                log::error!("unexpectedly ended a transaction that wasn't started by this editor");
10649            }
10650
10651            cx.emit(EditorEvent::Edited { transaction_id });
10652            Some(transaction_id)
10653        } else {
10654            None
10655        }
10656    }
10657
10658    pub fn set_mark(&mut self, _: &actions::SetMark, cx: &mut ViewContext<Self>) {
10659        if self.selection_mark_mode {
10660            self.change_selections(None, cx, |s| {
10661                s.move_with(|_, sel| {
10662                    sel.collapse_to(sel.head(), SelectionGoal::None);
10663                });
10664            })
10665        }
10666        self.selection_mark_mode = true;
10667        cx.notify();
10668    }
10669
10670    pub fn swap_selection_ends(
10671        &mut self,
10672        _: &actions::SwapSelectionEnds,
10673        cx: &mut ViewContext<Self>,
10674    ) {
10675        self.change_selections(None, cx, |s| {
10676            s.move_with(|_, sel| {
10677                if sel.start != sel.end {
10678                    sel.reversed = !sel.reversed
10679                }
10680            });
10681        });
10682        self.request_autoscroll(Autoscroll::newest(), cx);
10683        cx.notify();
10684    }
10685
10686    pub fn toggle_fold(&mut self, _: &actions::ToggleFold, cx: &mut ViewContext<Self>) {
10687        if self.is_singleton(cx) {
10688            let selection = self.selections.newest::<Point>(cx);
10689
10690            let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
10691            let range = if selection.is_empty() {
10692                let point = selection.head().to_display_point(&display_map);
10693                let start = DisplayPoint::new(point.row(), 0).to_point(&display_map);
10694                let end = DisplayPoint::new(point.row(), display_map.line_len(point.row()))
10695                    .to_point(&display_map);
10696                start..end
10697            } else {
10698                selection.range()
10699            };
10700            if display_map.folds_in_range(range).next().is_some() {
10701                self.unfold_lines(&Default::default(), cx)
10702            } else {
10703                self.fold(&Default::default(), cx)
10704            }
10705        } else {
10706            let multi_buffer_snapshot = self.buffer.read(cx).snapshot(cx);
10707            let mut toggled_buffers = HashSet::default();
10708            for (_, buffer_snapshot, _) in
10709                multi_buffer_snapshot.excerpts_in_ranges(self.selections.disjoint_anchor_ranges())
10710            {
10711                let buffer_id = buffer_snapshot.remote_id();
10712                if toggled_buffers.insert(buffer_id) {
10713                    if self.buffer_folded(buffer_id, cx) {
10714                        self.unfold_buffer(buffer_id, cx);
10715                    } else {
10716                        self.fold_buffer(buffer_id, cx);
10717                    }
10718                }
10719            }
10720        }
10721    }
10722
10723    pub fn toggle_fold_recursive(
10724        &mut self,
10725        _: &actions::ToggleFoldRecursive,
10726        cx: &mut ViewContext<Self>,
10727    ) {
10728        let selection = self.selections.newest::<Point>(cx);
10729
10730        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
10731        let range = if selection.is_empty() {
10732            let point = selection.head().to_display_point(&display_map);
10733            let start = DisplayPoint::new(point.row(), 0).to_point(&display_map);
10734            let end = DisplayPoint::new(point.row(), display_map.line_len(point.row()))
10735                .to_point(&display_map);
10736            start..end
10737        } else {
10738            selection.range()
10739        };
10740        if display_map.folds_in_range(range).next().is_some() {
10741            self.unfold_recursive(&Default::default(), cx)
10742        } else {
10743            self.fold_recursive(&Default::default(), cx)
10744        }
10745    }
10746
10747    pub fn fold(&mut self, _: &actions::Fold, cx: &mut ViewContext<Self>) {
10748        if self.is_singleton(cx) {
10749            let mut to_fold = Vec::new();
10750            let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
10751            let selections = self.selections.all_adjusted(cx);
10752
10753            for selection in selections {
10754                let range = selection.range().sorted();
10755                let buffer_start_row = range.start.row;
10756
10757                if range.start.row != range.end.row {
10758                    let mut found = false;
10759                    let mut row = range.start.row;
10760                    while row <= range.end.row {
10761                        if let Some(crease) = display_map.crease_for_buffer_row(MultiBufferRow(row))
10762                        {
10763                            found = true;
10764                            row = crease.range().end.row + 1;
10765                            to_fold.push(crease);
10766                        } else {
10767                            row += 1
10768                        }
10769                    }
10770                    if found {
10771                        continue;
10772                    }
10773                }
10774
10775                for row in (0..=range.start.row).rev() {
10776                    if let Some(crease) = display_map.crease_for_buffer_row(MultiBufferRow(row)) {
10777                        if crease.range().end.row >= buffer_start_row {
10778                            to_fold.push(crease);
10779                            if row <= range.start.row {
10780                                break;
10781                            }
10782                        }
10783                    }
10784                }
10785            }
10786
10787            self.fold_creases(to_fold, true, cx);
10788        } else {
10789            let multi_buffer_snapshot = self.buffer.read(cx).snapshot(cx);
10790            let mut folded_buffers = HashSet::default();
10791            for (_, buffer_snapshot, _) in
10792                multi_buffer_snapshot.excerpts_in_ranges(self.selections.disjoint_anchor_ranges())
10793            {
10794                let buffer_id = buffer_snapshot.remote_id();
10795                if folded_buffers.insert(buffer_id) {
10796                    self.fold_buffer(buffer_id, cx);
10797                }
10798            }
10799        }
10800    }
10801
10802    fn fold_at_level(&mut self, fold_at: &FoldAtLevel, cx: &mut ViewContext<Self>) {
10803        if !self.buffer.read(cx).is_singleton() {
10804            return;
10805        }
10806
10807        let fold_at_level = fold_at.level;
10808        let snapshot = self.buffer.read(cx).snapshot(cx);
10809        let mut to_fold = Vec::new();
10810        let mut stack = vec![(0, snapshot.max_row().0, 1)];
10811
10812        while let Some((mut start_row, end_row, current_level)) = stack.pop() {
10813            while start_row < end_row {
10814                match self
10815                    .snapshot(cx)
10816                    .crease_for_buffer_row(MultiBufferRow(start_row))
10817                {
10818                    Some(crease) => {
10819                        let nested_start_row = crease.range().start.row + 1;
10820                        let nested_end_row = crease.range().end.row;
10821
10822                        if current_level < fold_at_level {
10823                            stack.push((nested_start_row, nested_end_row, current_level + 1));
10824                        } else if current_level == fold_at_level {
10825                            to_fold.push(crease);
10826                        }
10827
10828                        start_row = nested_end_row + 1;
10829                    }
10830                    None => start_row += 1,
10831                }
10832            }
10833        }
10834
10835        self.fold_creases(to_fold, true, cx);
10836    }
10837
10838    pub fn fold_all(&mut self, _: &actions::FoldAll, cx: &mut ViewContext<Self>) {
10839        if self.buffer.read(cx).is_singleton() {
10840            let mut fold_ranges = Vec::new();
10841            let snapshot = self.buffer.read(cx).snapshot(cx);
10842
10843            for row in 0..snapshot.max_row().0 {
10844                if let Some(foldable_range) =
10845                    self.snapshot(cx).crease_for_buffer_row(MultiBufferRow(row))
10846                {
10847                    fold_ranges.push(foldable_range);
10848                }
10849            }
10850
10851            self.fold_creases(fold_ranges, true, cx);
10852        } else {
10853            self.toggle_fold_multiple_buffers = cx.spawn(|editor, mut cx| async move {
10854                editor
10855                    .update(&mut cx, |editor, cx| {
10856                        for buffer_id in editor.buffer.read(cx).excerpt_buffer_ids() {
10857                            editor.fold_buffer(buffer_id, cx);
10858                        }
10859                    })
10860                    .ok();
10861            });
10862        }
10863    }
10864
10865    pub fn fold_function_bodies(
10866        &mut self,
10867        _: &actions::FoldFunctionBodies,
10868        cx: &mut ViewContext<Self>,
10869    ) {
10870        let snapshot = self.buffer.read(cx).snapshot(cx);
10871        let Some((_, _, buffer)) = snapshot.as_singleton() else {
10872            return;
10873        };
10874        let creases = buffer
10875            .function_body_fold_ranges(0..buffer.len())
10876            .map(|range| Crease::simple(range, self.display_map.read(cx).fold_placeholder.clone()))
10877            .collect();
10878
10879        self.fold_creases(creases, true, cx);
10880    }
10881
10882    pub fn fold_recursive(&mut self, _: &actions::FoldRecursive, cx: &mut ViewContext<Self>) {
10883        let mut to_fold = Vec::new();
10884        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
10885        let selections = self.selections.all_adjusted(cx);
10886
10887        for selection in selections {
10888            let range = selection.range().sorted();
10889            let buffer_start_row = range.start.row;
10890
10891            if range.start.row != range.end.row {
10892                let mut found = false;
10893                for row in range.start.row..=range.end.row {
10894                    if let Some(crease) = display_map.crease_for_buffer_row(MultiBufferRow(row)) {
10895                        found = true;
10896                        to_fold.push(crease);
10897                    }
10898                }
10899                if found {
10900                    continue;
10901                }
10902            }
10903
10904            for row in (0..=range.start.row).rev() {
10905                if let Some(crease) = display_map.crease_for_buffer_row(MultiBufferRow(row)) {
10906                    if crease.range().end.row >= buffer_start_row {
10907                        to_fold.push(crease);
10908                    } else {
10909                        break;
10910                    }
10911                }
10912            }
10913        }
10914
10915        self.fold_creases(to_fold, true, cx);
10916    }
10917
10918    pub fn fold_at(&mut self, fold_at: &FoldAt, cx: &mut ViewContext<Self>) {
10919        let buffer_row = fold_at.buffer_row;
10920        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
10921
10922        if let Some(crease) = display_map.crease_for_buffer_row(buffer_row) {
10923            let autoscroll = self
10924                .selections
10925                .all::<Point>(cx)
10926                .iter()
10927                .any(|selection| crease.range().overlaps(&selection.range()));
10928
10929            self.fold_creases(vec![crease], autoscroll, cx);
10930        }
10931    }
10932
10933    pub fn unfold_lines(&mut self, _: &UnfoldLines, cx: &mut ViewContext<Self>) {
10934        if self.is_singleton(cx) {
10935            let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
10936            let buffer = &display_map.buffer_snapshot;
10937            let selections = self.selections.all::<Point>(cx);
10938            let ranges = selections
10939                .iter()
10940                .map(|s| {
10941                    let range = s.display_range(&display_map).sorted();
10942                    let mut start = range.start.to_point(&display_map);
10943                    let mut end = range.end.to_point(&display_map);
10944                    start.column = 0;
10945                    end.column = buffer.line_len(MultiBufferRow(end.row));
10946                    start..end
10947                })
10948                .collect::<Vec<_>>();
10949
10950            self.unfold_ranges(&ranges, true, true, cx);
10951        } else {
10952            let multi_buffer_snapshot = self.buffer.read(cx).snapshot(cx);
10953            let mut unfolded_buffers = HashSet::default();
10954            for (_, buffer_snapshot, _) in
10955                multi_buffer_snapshot.excerpts_in_ranges(self.selections.disjoint_anchor_ranges())
10956            {
10957                let buffer_id = buffer_snapshot.remote_id();
10958                if unfolded_buffers.insert(buffer_id) {
10959                    self.unfold_buffer(buffer_id, cx);
10960                }
10961            }
10962        }
10963    }
10964
10965    pub fn unfold_recursive(&mut self, _: &UnfoldRecursive, cx: &mut ViewContext<Self>) {
10966        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
10967        let selections = self.selections.all::<Point>(cx);
10968        let ranges = selections
10969            .iter()
10970            .map(|s| {
10971                let mut range = s.display_range(&display_map).sorted();
10972                *range.start.column_mut() = 0;
10973                *range.end.column_mut() = display_map.line_len(range.end.row());
10974                let start = range.start.to_point(&display_map);
10975                let end = range.end.to_point(&display_map);
10976                start..end
10977            })
10978            .collect::<Vec<_>>();
10979
10980        self.unfold_ranges(&ranges, true, true, cx);
10981    }
10982
10983    pub fn unfold_at(&mut self, unfold_at: &UnfoldAt, cx: &mut ViewContext<Self>) {
10984        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
10985
10986        let intersection_range = Point::new(unfold_at.buffer_row.0, 0)
10987            ..Point::new(
10988                unfold_at.buffer_row.0,
10989                display_map.buffer_snapshot.line_len(unfold_at.buffer_row),
10990            );
10991
10992        let autoscroll = self
10993            .selections
10994            .all::<Point>(cx)
10995            .iter()
10996            .any(|selection| RangeExt::overlaps(&selection.range(), &intersection_range));
10997
10998        self.unfold_ranges(&[intersection_range], true, autoscroll, cx)
10999    }
11000
11001    pub fn unfold_all(&mut self, _: &actions::UnfoldAll, cx: &mut ViewContext<Self>) {
11002        if self.buffer.read(cx).is_singleton() {
11003            let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
11004            self.unfold_ranges(&[0..display_map.buffer_snapshot.len()], true, true, cx);
11005        } else {
11006            self.toggle_fold_multiple_buffers = cx.spawn(|editor, mut cx| async move {
11007                editor
11008                    .update(&mut cx, |editor, cx| {
11009                        for buffer_id in editor.buffer.read(cx).excerpt_buffer_ids() {
11010                            editor.unfold_buffer(buffer_id, cx);
11011                        }
11012                    })
11013                    .ok();
11014            });
11015        }
11016    }
11017
11018    pub fn fold_selected_ranges(&mut self, _: &FoldSelectedRanges, cx: &mut ViewContext<Self>) {
11019        let selections = self.selections.all::<Point>(cx);
11020        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
11021        let line_mode = self.selections.line_mode;
11022        let ranges = selections
11023            .into_iter()
11024            .map(|s| {
11025                if line_mode {
11026                    let start = Point::new(s.start.row, 0);
11027                    let end = Point::new(
11028                        s.end.row,
11029                        display_map
11030                            .buffer_snapshot
11031                            .line_len(MultiBufferRow(s.end.row)),
11032                    );
11033                    Crease::simple(start..end, display_map.fold_placeholder.clone())
11034                } else {
11035                    Crease::simple(s.start..s.end, display_map.fold_placeholder.clone())
11036                }
11037            })
11038            .collect::<Vec<_>>();
11039        self.fold_creases(ranges, true, cx);
11040    }
11041
11042    pub fn fold_ranges<T: ToOffset + Clone>(
11043        &mut self,
11044        ranges: Vec<Range<T>>,
11045        auto_scroll: bool,
11046        cx: &mut ViewContext<Self>,
11047    ) {
11048        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
11049        let ranges = ranges
11050            .into_iter()
11051            .map(|r| Crease::simple(r, display_map.fold_placeholder.clone()))
11052            .collect::<Vec<_>>();
11053        self.fold_creases(ranges, auto_scroll, cx);
11054    }
11055
11056    pub fn fold_creases<T: ToOffset + Clone>(
11057        &mut self,
11058        creases: Vec<Crease<T>>,
11059        auto_scroll: bool,
11060        cx: &mut ViewContext<Self>,
11061    ) {
11062        if creases.is_empty() {
11063            return;
11064        }
11065
11066        let mut buffers_affected = HashSet::default();
11067        let multi_buffer = self.buffer().read(cx);
11068        for crease in &creases {
11069            if let Some((_, buffer, _)) =
11070                multi_buffer.excerpt_containing(crease.range().start.clone(), cx)
11071            {
11072                buffers_affected.insert(buffer.read(cx).remote_id());
11073            };
11074        }
11075
11076        self.display_map.update(cx, |map, cx| map.fold(creases, cx));
11077
11078        if auto_scroll {
11079            self.request_autoscroll(Autoscroll::fit(), cx);
11080        }
11081
11082        for buffer_id in buffers_affected {
11083            Self::sync_expanded_diff_hunks(&mut self.diff_map, buffer_id, cx);
11084        }
11085
11086        cx.notify();
11087
11088        if let Some(active_diagnostics) = self.active_diagnostics.take() {
11089            // Clear diagnostics block when folding a range that contains it.
11090            let snapshot = self.snapshot(cx);
11091            if snapshot.intersects_fold(active_diagnostics.primary_range.start) {
11092                drop(snapshot);
11093                self.active_diagnostics = Some(active_diagnostics);
11094                self.dismiss_diagnostics(cx);
11095            } else {
11096                self.active_diagnostics = Some(active_diagnostics);
11097            }
11098        }
11099
11100        self.scrollbar_marker_state.dirty = true;
11101    }
11102
11103    /// Removes any folds whose ranges intersect any of the given ranges.
11104    pub fn unfold_ranges<T: ToOffset + Clone>(
11105        &mut self,
11106        ranges: &[Range<T>],
11107        inclusive: bool,
11108        auto_scroll: bool,
11109        cx: &mut ViewContext<Self>,
11110    ) {
11111        self.remove_folds_with(ranges, auto_scroll, cx, |map, cx| {
11112            map.unfold_intersecting(ranges.iter().cloned(), inclusive, cx)
11113        });
11114    }
11115
11116    pub fn fold_buffer(&mut self, buffer_id: BufferId, cx: &mut ViewContext<Self>) {
11117        if self.buffer().read(cx).is_singleton() || self.buffer_folded(buffer_id, cx) {
11118            return;
11119        }
11120        let Some(buffer) = self.buffer().read(cx).buffer(buffer_id) else {
11121            return;
11122        };
11123        let folded_excerpts = self.buffer().read(cx).excerpts_for_buffer(&buffer, cx);
11124        self.display_map
11125            .update(cx, |display_map, cx| display_map.fold_buffer(buffer_id, cx));
11126        cx.emit(EditorEvent::BufferFoldToggled {
11127            ids: folded_excerpts.iter().map(|&(id, _)| id).collect(),
11128            folded: true,
11129        });
11130        cx.notify();
11131    }
11132
11133    pub fn unfold_buffer(&mut self, buffer_id: BufferId, cx: &mut ViewContext<Self>) {
11134        if self.buffer().read(cx).is_singleton() || !self.buffer_folded(buffer_id, cx) {
11135            return;
11136        }
11137        let Some(buffer) = self.buffer().read(cx).buffer(buffer_id) else {
11138            return;
11139        };
11140        let unfolded_excerpts = self.buffer().read(cx).excerpts_for_buffer(&buffer, cx);
11141        self.display_map.update(cx, |display_map, cx| {
11142            display_map.unfold_buffer(buffer_id, cx);
11143        });
11144        cx.emit(EditorEvent::BufferFoldToggled {
11145            ids: unfolded_excerpts.iter().map(|&(id, _)| id).collect(),
11146            folded: false,
11147        });
11148        cx.notify();
11149    }
11150
11151    pub fn buffer_folded(&self, buffer: BufferId, cx: &AppContext) -> bool {
11152        self.display_map.read(cx).buffer_folded(buffer)
11153    }
11154
11155    /// Removes any folds with the given ranges.
11156    pub fn remove_folds_with_type<T: ToOffset + Clone>(
11157        &mut self,
11158        ranges: &[Range<T>],
11159        type_id: TypeId,
11160        auto_scroll: bool,
11161        cx: &mut ViewContext<Self>,
11162    ) {
11163        self.remove_folds_with(ranges, auto_scroll, cx, |map, cx| {
11164            map.remove_folds_with_type(ranges.iter().cloned(), type_id, cx)
11165        });
11166    }
11167
11168    fn remove_folds_with<T: ToOffset + Clone>(
11169        &mut self,
11170        ranges: &[Range<T>],
11171        auto_scroll: bool,
11172        cx: &mut ViewContext<Self>,
11173        update: impl FnOnce(&mut DisplayMap, &mut ModelContext<DisplayMap>),
11174    ) {
11175        if ranges.is_empty() {
11176            return;
11177        }
11178
11179        let mut buffers_affected = HashSet::default();
11180        let multi_buffer = self.buffer().read(cx);
11181        for range in ranges {
11182            if let Some((_, buffer, _)) = multi_buffer.excerpt_containing(range.start.clone(), cx) {
11183                buffers_affected.insert(buffer.read(cx).remote_id());
11184            };
11185        }
11186
11187        self.display_map.update(cx, update);
11188
11189        if auto_scroll {
11190            self.request_autoscroll(Autoscroll::fit(), cx);
11191        }
11192
11193        for buffer_id in buffers_affected {
11194            Self::sync_expanded_diff_hunks(&mut self.diff_map, buffer_id, cx);
11195        }
11196
11197        cx.notify();
11198        self.scrollbar_marker_state.dirty = true;
11199        self.active_indent_guides_state.dirty = true;
11200    }
11201
11202    pub fn default_fold_placeholder(&self, cx: &AppContext) -> FoldPlaceholder {
11203        self.display_map.read(cx).fold_placeholder.clone()
11204    }
11205
11206    pub fn set_gutter_hovered(&mut self, hovered: bool, cx: &mut ViewContext<Self>) {
11207        if hovered != self.gutter_hovered {
11208            self.gutter_hovered = hovered;
11209            cx.notify();
11210        }
11211    }
11212
11213    pub fn insert_blocks(
11214        &mut self,
11215        blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
11216        autoscroll: Option<Autoscroll>,
11217        cx: &mut ViewContext<Self>,
11218    ) -> Vec<CustomBlockId> {
11219        let blocks = self
11220            .display_map
11221            .update(cx, |display_map, cx| display_map.insert_blocks(blocks, cx));
11222        if let Some(autoscroll) = autoscroll {
11223            self.request_autoscroll(autoscroll, cx);
11224        }
11225        cx.notify();
11226        blocks
11227    }
11228
11229    pub fn resize_blocks(
11230        &mut self,
11231        heights: HashMap<CustomBlockId, u32>,
11232        autoscroll: Option<Autoscroll>,
11233        cx: &mut ViewContext<Self>,
11234    ) {
11235        self.display_map
11236            .update(cx, |display_map, cx| display_map.resize_blocks(heights, cx));
11237        if let Some(autoscroll) = autoscroll {
11238            self.request_autoscroll(autoscroll, cx);
11239        }
11240        cx.notify();
11241    }
11242
11243    pub fn replace_blocks(
11244        &mut self,
11245        renderers: HashMap<CustomBlockId, RenderBlock>,
11246        autoscroll: Option<Autoscroll>,
11247        cx: &mut ViewContext<Self>,
11248    ) {
11249        self.display_map
11250            .update(cx, |display_map, _cx| display_map.replace_blocks(renderers));
11251        if let Some(autoscroll) = autoscroll {
11252            self.request_autoscroll(autoscroll, cx);
11253        }
11254        cx.notify();
11255    }
11256
11257    pub fn remove_blocks(
11258        &mut self,
11259        block_ids: HashSet<CustomBlockId>,
11260        autoscroll: Option<Autoscroll>,
11261        cx: &mut ViewContext<Self>,
11262    ) {
11263        self.display_map.update(cx, |display_map, cx| {
11264            display_map.remove_blocks(block_ids, cx)
11265        });
11266        if let Some(autoscroll) = autoscroll {
11267            self.request_autoscroll(autoscroll, cx);
11268        }
11269        cx.notify();
11270    }
11271
11272    pub fn row_for_block(
11273        &self,
11274        block_id: CustomBlockId,
11275        cx: &mut ViewContext<Self>,
11276    ) -> Option<DisplayRow> {
11277        self.display_map
11278            .update(cx, |map, cx| map.row_for_block(block_id, cx))
11279    }
11280
11281    pub(crate) fn set_focused_block(&mut self, focused_block: FocusedBlock) {
11282        self.focused_block = Some(focused_block);
11283    }
11284
11285    pub(crate) fn take_focused_block(&mut self) -> Option<FocusedBlock> {
11286        self.focused_block.take()
11287    }
11288
11289    pub fn insert_creases(
11290        &mut self,
11291        creases: impl IntoIterator<Item = Crease<Anchor>>,
11292        cx: &mut ViewContext<Self>,
11293    ) -> Vec<CreaseId> {
11294        self.display_map
11295            .update(cx, |map, cx| map.insert_creases(creases, cx))
11296    }
11297
11298    pub fn remove_creases(
11299        &mut self,
11300        ids: impl IntoIterator<Item = CreaseId>,
11301        cx: &mut ViewContext<Self>,
11302    ) {
11303        self.display_map
11304            .update(cx, |map, cx| map.remove_creases(ids, cx));
11305    }
11306
11307    pub fn longest_row(&self, cx: &mut AppContext) -> DisplayRow {
11308        self.display_map
11309            .update(cx, |map, cx| map.snapshot(cx))
11310            .longest_row()
11311    }
11312
11313    pub fn max_point(&self, cx: &mut AppContext) -> DisplayPoint {
11314        self.display_map
11315            .update(cx, |map, cx| map.snapshot(cx))
11316            .max_point()
11317    }
11318
11319    pub fn text(&self, cx: &AppContext) -> String {
11320        self.buffer.read(cx).read(cx).text()
11321    }
11322
11323    pub fn text_option(&self, cx: &AppContext) -> Option<String> {
11324        let text = self.text(cx);
11325        let text = text.trim();
11326
11327        if text.is_empty() {
11328            return None;
11329        }
11330
11331        Some(text.to_string())
11332    }
11333
11334    pub fn set_text(&mut self, text: impl Into<Arc<str>>, cx: &mut ViewContext<Self>) {
11335        self.transact(cx, |this, cx| {
11336            this.buffer
11337                .read(cx)
11338                .as_singleton()
11339                .expect("you can only call set_text on editors for singleton buffers")
11340                .update(cx, |buffer, cx| buffer.set_text(text, cx));
11341        });
11342    }
11343
11344    pub fn display_text(&self, cx: &mut AppContext) -> String {
11345        self.display_map
11346            .update(cx, |map, cx| map.snapshot(cx))
11347            .text()
11348    }
11349
11350    pub fn wrap_guides(&self, cx: &AppContext) -> SmallVec<[(usize, bool); 2]> {
11351        let mut wrap_guides = smallvec::smallvec![];
11352
11353        if self.show_wrap_guides == Some(false) {
11354            return wrap_guides;
11355        }
11356
11357        let settings = self.buffer.read(cx).settings_at(0, cx);
11358        if settings.show_wrap_guides {
11359            if let SoftWrap::Column(soft_wrap) = self.soft_wrap_mode(cx) {
11360                wrap_guides.push((soft_wrap as usize, true));
11361            } else if let SoftWrap::Bounded(soft_wrap) = self.soft_wrap_mode(cx) {
11362                wrap_guides.push((soft_wrap as usize, true));
11363            }
11364            wrap_guides.extend(settings.wrap_guides.iter().map(|guide| (*guide, false)))
11365        }
11366
11367        wrap_guides
11368    }
11369
11370    pub fn soft_wrap_mode(&self, cx: &AppContext) -> SoftWrap {
11371        let settings = self.buffer.read(cx).settings_at(0, cx);
11372        let mode = self.soft_wrap_mode_override.unwrap_or(settings.soft_wrap);
11373        match mode {
11374            language_settings::SoftWrap::PreferLine | language_settings::SoftWrap::None => {
11375                SoftWrap::None
11376            }
11377            language_settings::SoftWrap::EditorWidth => SoftWrap::EditorWidth,
11378            language_settings::SoftWrap::PreferredLineLength => {
11379                SoftWrap::Column(settings.preferred_line_length)
11380            }
11381            language_settings::SoftWrap::Bounded => {
11382                SoftWrap::Bounded(settings.preferred_line_length)
11383            }
11384        }
11385    }
11386
11387    pub fn set_soft_wrap_mode(
11388        &mut self,
11389        mode: language_settings::SoftWrap,
11390        cx: &mut ViewContext<Self>,
11391    ) {
11392        self.soft_wrap_mode_override = Some(mode);
11393        cx.notify();
11394    }
11395
11396    pub fn set_text_style_refinement(&mut self, style: TextStyleRefinement) {
11397        self.text_style_refinement = Some(style);
11398    }
11399
11400    /// called by the Element so we know what style we were most recently rendered with.
11401    pub(crate) fn set_style(&mut self, style: EditorStyle, cx: &mut ViewContext<Self>) {
11402        let rem_size = cx.rem_size();
11403        self.display_map.update(cx, |map, cx| {
11404            map.set_font(
11405                style.text.font(),
11406                style.text.font_size.to_pixels(rem_size),
11407                cx,
11408            )
11409        });
11410        self.style = Some(style);
11411    }
11412
11413    pub fn style(&self) -> Option<&EditorStyle> {
11414        self.style.as_ref()
11415    }
11416
11417    // Called by the element. This method is not designed to be called outside of the editor
11418    // element's layout code because it does not notify when rewrapping is computed synchronously.
11419    pub(crate) fn set_wrap_width(&self, width: Option<Pixels>, cx: &mut AppContext) -> bool {
11420        self.display_map
11421            .update(cx, |map, cx| map.set_wrap_width(width, cx))
11422    }
11423
11424    pub fn toggle_soft_wrap(&mut self, _: &ToggleSoftWrap, cx: &mut ViewContext<Self>) {
11425        if self.soft_wrap_mode_override.is_some() {
11426            self.soft_wrap_mode_override.take();
11427        } else {
11428            let soft_wrap = match self.soft_wrap_mode(cx) {
11429                SoftWrap::GitDiff => return,
11430                SoftWrap::None => language_settings::SoftWrap::EditorWidth,
11431                SoftWrap::EditorWidth | SoftWrap::Column(_) | SoftWrap::Bounded(_) => {
11432                    language_settings::SoftWrap::None
11433                }
11434            };
11435            self.soft_wrap_mode_override = Some(soft_wrap);
11436        }
11437        cx.notify();
11438    }
11439
11440    pub fn toggle_tab_bar(&mut self, _: &ToggleTabBar, cx: &mut ViewContext<Self>) {
11441        let Some(workspace) = self.workspace() else {
11442            return;
11443        };
11444        let fs = workspace.read(cx).app_state().fs.clone();
11445        let current_show = TabBarSettings::get_global(cx).show;
11446        update_settings_file::<TabBarSettings>(fs, cx, move |setting, _| {
11447            setting.show = Some(!current_show);
11448        });
11449    }
11450
11451    pub fn toggle_indent_guides(&mut self, _: &ToggleIndentGuides, cx: &mut ViewContext<Self>) {
11452        let currently_enabled = self.should_show_indent_guides().unwrap_or_else(|| {
11453            self.buffer
11454                .read(cx)
11455                .settings_at(0, cx)
11456                .indent_guides
11457                .enabled
11458        });
11459        self.show_indent_guides = Some(!currently_enabled);
11460        cx.notify();
11461    }
11462
11463    fn should_show_indent_guides(&self) -> Option<bool> {
11464        self.show_indent_guides
11465    }
11466
11467    pub fn toggle_line_numbers(&mut self, _: &ToggleLineNumbers, cx: &mut ViewContext<Self>) {
11468        let mut editor_settings = EditorSettings::get_global(cx).clone();
11469        editor_settings.gutter.line_numbers = !editor_settings.gutter.line_numbers;
11470        EditorSettings::override_global(editor_settings, cx);
11471    }
11472
11473    pub fn should_use_relative_line_numbers(&self, cx: &WindowContext) -> bool {
11474        self.use_relative_line_numbers
11475            .unwrap_or(EditorSettings::get_global(cx).relative_line_numbers)
11476    }
11477
11478    pub fn toggle_relative_line_numbers(
11479        &mut self,
11480        _: &ToggleRelativeLineNumbers,
11481        cx: &mut ViewContext<Self>,
11482    ) {
11483        let is_relative = self.should_use_relative_line_numbers(cx);
11484        self.set_relative_line_number(Some(!is_relative), cx)
11485    }
11486
11487    pub fn set_relative_line_number(
11488        &mut self,
11489        is_relative: Option<bool>,
11490        cx: &mut ViewContext<Self>,
11491    ) {
11492        self.use_relative_line_numbers = is_relative;
11493        cx.notify();
11494    }
11495
11496    pub fn set_show_gutter(&mut self, show_gutter: bool, cx: &mut ViewContext<Self>) {
11497        self.show_gutter = show_gutter;
11498        cx.notify();
11499    }
11500
11501    pub fn set_show_scrollbars(&mut self, show_scrollbars: bool, cx: &mut ViewContext<Self>) {
11502        self.show_scrollbars = show_scrollbars;
11503        cx.notify();
11504    }
11505
11506    pub fn set_show_line_numbers(&mut self, show_line_numbers: bool, cx: &mut ViewContext<Self>) {
11507        self.show_line_numbers = Some(show_line_numbers);
11508        cx.notify();
11509    }
11510
11511    pub fn set_show_git_diff_gutter(
11512        &mut self,
11513        show_git_diff_gutter: bool,
11514        cx: &mut ViewContext<Self>,
11515    ) {
11516        self.show_git_diff_gutter = Some(show_git_diff_gutter);
11517        cx.notify();
11518    }
11519
11520    pub fn set_show_code_actions(&mut self, show_code_actions: bool, cx: &mut ViewContext<Self>) {
11521        self.show_code_actions = Some(show_code_actions);
11522        cx.notify();
11523    }
11524
11525    pub fn set_show_runnables(&mut self, show_runnables: bool, cx: &mut ViewContext<Self>) {
11526        self.show_runnables = Some(show_runnables);
11527        cx.notify();
11528    }
11529
11530    pub fn set_masked(&mut self, masked: bool, cx: &mut ViewContext<Self>) {
11531        if self.display_map.read(cx).masked != masked {
11532            self.display_map.update(cx, |map, _| map.masked = masked);
11533        }
11534        cx.notify()
11535    }
11536
11537    pub fn set_show_wrap_guides(&mut self, show_wrap_guides: bool, cx: &mut ViewContext<Self>) {
11538        self.show_wrap_guides = Some(show_wrap_guides);
11539        cx.notify();
11540    }
11541
11542    pub fn set_show_indent_guides(&mut self, show_indent_guides: bool, cx: &mut ViewContext<Self>) {
11543        self.show_indent_guides = Some(show_indent_guides);
11544        cx.notify();
11545    }
11546
11547    pub fn working_directory(&self, cx: &WindowContext) -> Option<PathBuf> {
11548        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
11549            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
11550                if let Some(dir) = file.abs_path(cx).parent() {
11551                    return Some(dir.to_owned());
11552                }
11553            }
11554
11555            if let Some(project_path) = buffer.read(cx).project_path(cx) {
11556                return Some(project_path.path.to_path_buf());
11557            }
11558        }
11559
11560        None
11561    }
11562
11563    fn target_file<'a>(&self, cx: &'a AppContext) -> Option<&'a dyn language::LocalFile> {
11564        self.active_excerpt(cx)?
11565            .1
11566            .read(cx)
11567            .file()
11568            .and_then(|f| f.as_local())
11569    }
11570
11571    fn target_file_abs_path(&self, cx: &mut ViewContext<Self>) -> Option<PathBuf> {
11572        self.active_excerpt(cx).and_then(|(_, buffer, _)| {
11573            let project_path = buffer.read(cx).project_path(cx)?;
11574            let project = self.project.as_ref()?.read(cx);
11575            project.absolute_path(&project_path, cx)
11576        })
11577    }
11578
11579    fn target_file_path(&self, cx: &mut ViewContext<Self>) -> Option<PathBuf> {
11580        self.active_excerpt(cx).and_then(|(_, buffer, _)| {
11581            let project_path = buffer.read(cx).project_path(cx)?;
11582            let project = self.project.as_ref()?.read(cx);
11583            let entry = project.entry_for_path(&project_path, cx)?;
11584            let path = entry.path.to_path_buf();
11585            Some(path)
11586        })
11587    }
11588
11589    pub fn reveal_in_finder(&mut self, _: &RevealInFileManager, cx: &mut ViewContext<Self>) {
11590        if let Some(target) = self.target_file(cx) {
11591            cx.reveal_path(&target.abs_path(cx));
11592        }
11593    }
11594
11595    pub fn copy_path(&mut self, _: &CopyPath, cx: &mut ViewContext<Self>) {
11596        if let Some(path) = self.target_file_abs_path(cx) {
11597            if let Some(path) = path.to_str() {
11598                cx.write_to_clipboard(ClipboardItem::new_string(path.to_string()));
11599            }
11600        }
11601    }
11602
11603    pub fn copy_relative_path(&mut self, _: &CopyRelativePath, cx: &mut ViewContext<Self>) {
11604        if let Some(path) = self.target_file_path(cx) {
11605            if let Some(path) = path.to_str() {
11606                cx.write_to_clipboard(ClipboardItem::new_string(path.to_string()));
11607            }
11608        }
11609    }
11610
11611    pub fn toggle_git_blame(&mut self, _: &ToggleGitBlame, cx: &mut ViewContext<Self>) {
11612        self.show_git_blame_gutter = !self.show_git_blame_gutter;
11613
11614        if self.show_git_blame_gutter && !self.has_blame_entries(cx) {
11615            self.start_git_blame(true, cx);
11616        }
11617
11618        cx.notify();
11619    }
11620
11621    pub fn toggle_git_blame_inline(
11622        &mut self,
11623        _: &ToggleGitBlameInline,
11624        cx: &mut ViewContext<Self>,
11625    ) {
11626        self.toggle_git_blame_inline_internal(true, cx);
11627        cx.notify();
11628    }
11629
11630    pub fn git_blame_inline_enabled(&self) -> bool {
11631        self.git_blame_inline_enabled
11632    }
11633
11634    pub fn toggle_selection_menu(&mut self, _: &ToggleSelectionMenu, cx: &mut ViewContext<Self>) {
11635        self.show_selection_menu = self
11636            .show_selection_menu
11637            .map(|show_selections_menu| !show_selections_menu)
11638            .or_else(|| Some(!EditorSettings::get_global(cx).toolbar.selections_menu));
11639
11640        cx.notify();
11641    }
11642
11643    pub fn selection_menu_enabled(&self, cx: &AppContext) -> bool {
11644        self.show_selection_menu
11645            .unwrap_or_else(|| EditorSettings::get_global(cx).toolbar.selections_menu)
11646    }
11647
11648    fn start_git_blame(&mut self, user_triggered: bool, cx: &mut ViewContext<Self>) {
11649        if let Some(project) = self.project.as_ref() {
11650            let Some(buffer) = self.buffer().read(cx).as_singleton() else {
11651                return;
11652            };
11653
11654            if buffer.read(cx).file().is_none() {
11655                return;
11656            }
11657
11658            let focused = self.focus_handle(cx).contains_focused(cx);
11659
11660            let project = project.clone();
11661            let blame =
11662                cx.new_model(|cx| GitBlame::new(buffer, project, user_triggered, focused, cx));
11663            self.blame_subscription = Some(cx.observe(&blame, |_, _, cx| cx.notify()));
11664            self.blame = Some(blame);
11665        }
11666    }
11667
11668    fn toggle_git_blame_inline_internal(
11669        &mut self,
11670        user_triggered: bool,
11671        cx: &mut ViewContext<Self>,
11672    ) {
11673        if self.git_blame_inline_enabled {
11674            self.git_blame_inline_enabled = false;
11675            self.show_git_blame_inline = false;
11676            self.show_git_blame_inline_delay_task.take();
11677        } else {
11678            self.git_blame_inline_enabled = true;
11679            self.start_git_blame_inline(user_triggered, cx);
11680        }
11681
11682        cx.notify();
11683    }
11684
11685    fn start_git_blame_inline(&mut self, user_triggered: bool, cx: &mut ViewContext<Self>) {
11686        self.start_git_blame(user_triggered, cx);
11687
11688        if ProjectSettings::get_global(cx)
11689            .git
11690            .inline_blame_delay()
11691            .is_some()
11692        {
11693            self.start_inline_blame_timer(cx);
11694        } else {
11695            self.show_git_blame_inline = true
11696        }
11697    }
11698
11699    pub fn blame(&self) -> Option<&Model<GitBlame>> {
11700        self.blame.as_ref()
11701    }
11702
11703    pub fn show_git_blame_gutter(&self) -> bool {
11704        self.show_git_blame_gutter
11705    }
11706
11707    pub fn render_git_blame_gutter(&mut self, cx: &mut WindowContext) -> bool {
11708        self.show_git_blame_gutter && self.has_blame_entries(cx)
11709    }
11710
11711    pub fn render_git_blame_inline(&mut self, cx: &mut WindowContext) -> bool {
11712        self.show_git_blame_inline
11713            && self.focus_handle.is_focused(cx)
11714            && !self.newest_selection_head_on_empty_line(cx)
11715            && self.has_blame_entries(cx)
11716    }
11717
11718    fn has_blame_entries(&self, cx: &mut WindowContext) -> bool {
11719        self.blame()
11720            .map_or(false, |blame| blame.read(cx).has_generated_entries())
11721    }
11722
11723    fn newest_selection_head_on_empty_line(&mut self, cx: &mut WindowContext) -> bool {
11724        let cursor_anchor = self.selections.newest_anchor().head();
11725
11726        let snapshot = self.buffer.read(cx).snapshot(cx);
11727        let buffer_row = MultiBufferRow(cursor_anchor.to_point(&snapshot).row);
11728
11729        snapshot.line_len(buffer_row) == 0
11730    }
11731
11732    fn get_permalink_to_line(&mut self, cx: &mut ViewContext<Self>) -> Task<Result<url::Url>> {
11733        let buffer_and_selection = maybe!({
11734            let selection = self.selections.newest::<Point>(cx);
11735            let selection_range = selection.range();
11736
11737            let (buffer, selection) = if let Some(buffer) = self.buffer().read(cx).as_singleton() {
11738                (buffer, selection_range.start.row..selection_range.end.row)
11739            } else {
11740                let multi_buffer = self.buffer().read(cx);
11741                let multi_buffer_snapshot = multi_buffer.snapshot(cx);
11742                let buffer_ranges = multi_buffer_snapshot.range_to_buffer_ranges(selection_range);
11743
11744                let (excerpt, range) = if selection.reversed {
11745                    buffer_ranges.first()
11746                } else {
11747                    buffer_ranges.last()
11748                }?;
11749
11750                let snapshot = excerpt.buffer();
11751                let selection = text::ToPoint::to_point(&range.start, &snapshot).row
11752                    ..text::ToPoint::to_point(&range.end, &snapshot).row;
11753                (
11754                    multi_buffer.buffer(excerpt.buffer_id()).unwrap().clone(),
11755                    selection,
11756                )
11757            };
11758
11759            Some((buffer, selection))
11760        });
11761
11762        let Some((buffer, selection)) = buffer_and_selection else {
11763            return Task::ready(Err(anyhow!("failed to determine buffer and selection")));
11764        };
11765
11766        let Some(project) = self.project.as_ref() else {
11767            return Task::ready(Err(anyhow!("editor does not have project")));
11768        };
11769
11770        project.update(cx, |project, cx| {
11771            project.get_permalink_to_line(&buffer, selection, cx)
11772        })
11773    }
11774
11775    pub fn copy_permalink_to_line(&mut self, _: &CopyPermalinkToLine, cx: &mut ViewContext<Self>) {
11776        let permalink_task = self.get_permalink_to_line(cx);
11777        let workspace = self.workspace();
11778
11779        cx.spawn(|_, mut cx| async move {
11780            match permalink_task.await {
11781                Ok(permalink) => {
11782                    cx.update(|cx| {
11783                        cx.write_to_clipboard(ClipboardItem::new_string(permalink.to_string()));
11784                    })
11785                    .ok();
11786                }
11787                Err(err) => {
11788                    let message = format!("Failed to copy permalink: {err}");
11789
11790                    Err::<(), anyhow::Error>(err).log_err();
11791
11792                    if let Some(workspace) = workspace {
11793                        workspace
11794                            .update(&mut cx, |workspace, cx| {
11795                                struct CopyPermalinkToLine;
11796
11797                                workspace.show_toast(
11798                                    Toast::new(
11799                                        NotificationId::unique::<CopyPermalinkToLine>(),
11800                                        message,
11801                                    ),
11802                                    cx,
11803                                )
11804                            })
11805                            .ok();
11806                    }
11807                }
11808            }
11809        })
11810        .detach();
11811    }
11812
11813    pub fn copy_file_location(&mut self, _: &CopyFileLocation, cx: &mut ViewContext<Self>) {
11814        let selection = self.selections.newest::<Point>(cx).start.row + 1;
11815        if let Some(file) = self.target_file(cx) {
11816            if let Some(path) = file.path().to_str() {
11817                cx.write_to_clipboard(ClipboardItem::new_string(format!("{path}:{selection}")));
11818            }
11819        }
11820    }
11821
11822    pub fn open_permalink_to_line(&mut self, _: &OpenPermalinkToLine, cx: &mut ViewContext<Self>) {
11823        let permalink_task = self.get_permalink_to_line(cx);
11824        let workspace = self.workspace();
11825
11826        cx.spawn(|_, mut cx| async move {
11827            match permalink_task.await {
11828                Ok(permalink) => {
11829                    cx.update(|cx| {
11830                        cx.open_url(permalink.as_ref());
11831                    })
11832                    .ok();
11833                }
11834                Err(err) => {
11835                    let message = format!("Failed to open permalink: {err}");
11836
11837                    Err::<(), anyhow::Error>(err).log_err();
11838
11839                    if let Some(workspace) = workspace {
11840                        workspace
11841                            .update(&mut cx, |workspace, cx| {
11842                                struct OpenPermalinkToLine;
11843
11844                                workspace.show_toast(
11845                                    Toast::new(
11846                                        NotificationId::unique::<OpenPermalinkToLine>(),
11847                                        message,
11848                                    ),
11849                                    cx,
11850                                )
11851                            })
11852                            .ok();
11853                    }
11854                }
11855            }
11856        })
11857        .detach();
11858    }
11859
11860    pub fn insert_uuid_v4(&mut self, _: &InsertUuidV4, cx: &mut ViewContext<Self>) {
11861        self.insert_uuid(UuidVersion::V4, cx);
11862    }
11863
11864    pub fn insert_uuid_v7(&mut self, _: &InsertUuidV7, cx: &mut ViewContext<Self>) {
11865        self.insert_uuid(UuidVersion::V7, cx);
11866    }
11867
11868    fn insert_uuid(&mut self, version: UuidVersion, cx: &mut ViewContext<Self>) {
11869        self.transact(cx, |this, cx| {
11870            let edits = this
11871                .selections
11872                .all::<Point>(cx)
11873                .into_iter()
11874                .map(|selection| {
11875                    let uuid = match version {
11876                        UuidVersion::V4 => uuid::Uuid::new_v4(),
11877                        UuidVersion::V7 => uuid::Uuid::now_v7(),
11878                    };
11879
11880                    (selection.range(), uuid.to_string())
11881                });
11882            this.edit(edits, cx);
11883            this.refresh_inline_completion(true, false, cx);
11884        });
11885    }
11886
11887    /// Adds a row highlight for the given range. If a row has multiple highlights, the
11888    /// last highlight added will be used.
11889    ///
11890    /// If the range ends at the beginning of a line, then that line will not be highlighted.
11891    pub fn highlight_rows<T: 'static>(
11892        &mut self,
11893        range: Range<Anchor>,
11894        color: Hsla,
11895        should_autoscroll: bool,
11896        cx: &mut ViewContext<Self>,
11897    ) {
11898        let snapshot = self.buffer().read(cx).snapshot(cx);
11899        let row_highlights = self.highlighted_rows.entry(TypeId::of::<T>()).or_default();
11900        let ix = row_highlights.binary_search_by(|highlight| {
11901            Ordering::Equal
11902                .then_with(|| highlight.range.start.cmp(&range.start, &snapshot))
11903                .then_with(|| highlight.range.end.cmp(&range.end, &snapshot))
11904        });
11905
11906        if let Err(mut ix) = ix {
11907            let index = post_inc(&mut self.highlight_order);
11908
11909            // If this range intersects with the preceding highlight, then merge it with
11910            // the preceding highlight. Otherwise insert a new highlight.
11911            let mut merged = false;
11912            if ix > 0 {
11913                let prev_highlight = &mut row_highlights[ix - 1];
11914                if prev_highlight
11915                    .range
11916                    .end
11917                    .cmp(&range.start, &snapshot)
11918                    .is_ge()
11919                {
11920                    ix -= 1;
11921                    if prev_highlight.range.end.cmp(&range.end, &snapshot).is_lt() {
11922                        prev_highlight.range.end = range.end;
11923                    }
11924                    merged = true;
11925                    prev_highlight.index = index;
11926                    prev_highlight.color = color;
11927                    prev_highlight.should_autoscroll = should_autoscroll;
11928                }
11929            }
11930
11931            if !merged {
11932                row_highlights.insert(
11933                    ix,
11934                    RowHighlight {
11935                        range: range.clone(),
11936                        index,
11937                        color,
11938                        should_autoscroll,
11939                    },
11940                );
11941            }
11942
11943            // If any of the following highlights intersect with this one, merge them.
11944            while let Some(next_highlight) = row_highlights.get(ix + 1) {
11945                let highlight = &row_highlights[ix];
11946                if next_highlight
11947                    .range
11948                    .start
11949                    .cmp(&highlight.range.end, &snapshot)
11950                    .is_le()
11951                {
11952                    if next_highlight
11953                        .range
11954                        .end
11955                        .cmp(&highlight.range.end, &snapshot)
11956                        .is_gt()
11957                    {
11958                        row_highlights[ix].range.end = next_highlight.range.end;
11959                    }
11960                    row_highlights.remove(ix + 1);
11961                } else {
11962                    break;
11963                }
11964            }
11965        }
11966    }
11967
11968    /// Remove any highlighted row ranges of the given type that intersect the
11969    /// given ranges.
11970    pub fn remove_highlighted_rows<T: 'static>(
11971        &mut self,
11972        ranges_to_remove: Vec<Range<Anchor>>,
11973        cx: &mut ViewContext<Self>,
11974    ) {
11975        let snapshot = self.buffer().read(cx).snapshot(cx);
11976        let row_highlights = self.highlighted_rows.entry(TypeId::of::<T>()).or_default();
11977        let mut ranges_to_remove = ranges_to_remove.iter().peekable();
11978        row_highlights.retain(|highlight| {
11979            while let Some(range_to_remove) = ranges_to_remove.peek() {
11980                match range_to_remove.end.cmp(&highlight.range.start, &snapshot) {
11981                    Ordering::Less | Ordering::Equal => {
11982                        ranges_to_remove.next();
11983                    }
11984                    Ordering::Greater => {
11985                        match range_to_remove.start.cmp(&highlight.range.end, &snapshot) {
11986                            Ordering::Less | Ordering::Equal => {
11987                                return false;
11988                            }
11989                            Ordering::Greater => break,
11990                        }
11991                    }
11992                }
11993            }
11994
11995            true
11996        })
11997    }
11998
11999    /// Clear all anchor ranges for a certain highlight context type, so no corresponding rows will be highlighted.
12000    pub fn clear_row_highlights<T: 'static>(&mut self) {
12001        self.highlighted_rows.remove(&TypeId::of::<T>());
12002    }
12003
12004    /// For a highlight given context type, gets all anchor ranges that will be used for row highlighting.
12005    pub fn highlighted_rows<T: 'static>(&self) -> impl '_ + Iterator<Item = (Range<Anchor>, Hsla)> {
12006        self.highlighted_rows
12007            .get(&TypeId::of::<T>())
12008            .map_or(&[] as &[_], |vec| vec.as_slice())
12009            .iter()
12010            .map(|highlight| (highlight.range.clone(), highlight.color))
12011    }
12012
12013    /// Merges all anchor ranges for all context types ever set, picking the last highlight added in case of a row conflict.
12014    /// Returns a map of display rows that are highlighted and their corresponding highlight color.
12015    /// Allows to ignore certain kinds of highlights.
12016    pub fn highlighted_display_rows(
12017        &mut self,
12018        cx: &mut WindowContext,
12019    ) -> BTreeMap<DisplayRow, Hsla> {
12020        let snapshot = self.snapshot(cx);
12021        let mut used_highlight_orders = HashMap::default();
12022        self.highlighted_rows
12023            .iter()
12024            .flat_map(|(_, highlighted_rows)| highlighted_rows.iter())
12025            .fold(
12026                BTreeMap::<DisplayRow, Hsla>::new(),
12027                |mut unique_rows, highlight| {
12028                    let start = highlight.range.start.to_display_point(&snapshot);
12029                    let end = highlight.range.end.to_display_point(&snapshot);
12030                    let start_row = start.row().0;
12031                    let end_row = if highlight.range.end.text_anchor != text::Anchor::MAX
12032                        && end.column() == 0
12033                    {
12034                        end.row().0.saturating_sub(1)
12035                    } else {
12036                        end.row().0
12037                    };
12038                    for row in start_row..=end_row {
12039                        let used_index =
12040                            used_highlight_orders.entry(row).or_insert(highlight.index);
12041                        if highlight.index >= *used_index {
12042                            *used_index = highlight.index;
12043                            unique_rows.insert(DisplayRow(row), highlight.color);
12044                        }
12045                    }
12046                    unique_rows
12047                },
12048            )
12049    }
12050
12051    pub fn highlighted_display_row_for_autoscroll(
12052        &self,
12053        snapshot: &DisplaySnapshot,
12054    ) -> Option<DisplayRow> {
12055        self.highlighted_rows
12056            .values()
12057            .flat_map(|highlighted_rows| highlighted_rows.iter())
12058            .filter_map(|highlight| {
12059                if highlight.should_autoscroll {
12060                    Some(highlight.range.start.to_display_point(snapshot).row())
12061                } else {
12062                    None
12063                }
12064            })
12065            .min()
12066    }
12067
12068    pub fn set_search_within_ranges(
12069        &mut self,
12070        ranges: &[Range<Anchor>],
12071        cx: &mut ViewContext<Self>,
12072    ) {
12073        self.highlight_background::<SearchWithinRange>(
12074            ranges,
12075            |colors| colors.editor_document_highlight_read_background,
12076            cx,
12077        )
12078    }
12079
12080    pub fn set_breadcrumb_header(&mut self, new_header: String) {
12081        self.breadcrumb_header = Some(new_header);
12082    }
12083
12084    pub fn clear_search_within_ranges(&mut self, cx: &mut ViewContext<Self>) {
12085        self.clear_background_highlights::<SearchWithinRange>(cx);
12086    }
12087
12088    pub fn highlight_background<T: 'static>(
12089        &mut self,
12090        ranges: &[Range<Anchor>],
12091        color_fetcher: fn(&ThemeColors) -> Hsla,
12092        cx: &mut ViewContext<Self>,
12093    ) {
12094        self.background_highlights
12095            .insert(TypeId::of::<T>(), (color_fetcher, Arc::from(ranges)));
12096        self.scrollbar_marker_state.dirty = true;
12097        cx.notify();
12098    }
12099
12100    pub fn clear_background_highlights<T: 'static>(
12101        &mut self,
12102        cx: &mut ViewContext<Self>,
12103    ) -> Option<BackgroundHighlight> {
12104        let text_highlights = self.background_highlights.remove(&TypeId::of::<T>())?;
12105        if !text_highlights.1.is_empty() {
12106            self.scrollbar_marker_state.dirty = true;
12107            cx.notify();
12108        }
12109        Some(text_highlights)
12110    }
12111
12112    pub fn highlight_gutter<T: 'static>(
12113        &mut self,
12114        ranges: &[Range<Anchor>],
12115        color_fetcher: fn(&AppContext) -> Hsla,
12116        cx: &mut ViewContext<Self>,
12117    ) {
12118        self.gutter_highlights
12119            .insert(TypeId::of::<T>(), (color_fetcher, Arc::from(ranges)));
12120        cx.notify();
12121    }
12122
12123    pub fn clear_gutter_highlights<T: 'static>(
12124        &mut self,
12125        cx: &mut ViewContext<Self>,
12126    ) -> Option<GutterHighlight> {
12127        cx.notify();
12128        self.gutter_highlights.remove(&TypeId::of::<T>())
12129    }
12130
12131    #[cfg(feature = "test-support")]
12132    pub fn all_text_background_highlights(
12133        &mut self,
12134        cx: &mut ViewContext<Self>,
12135    ) -> Vec<(Range<DisplayPoint>, Hsla)> {
12136        let snapshot = self.snapshot(cx);
12137        let buffer = &snapshot.buffer_snapshot;
12138        let start = buffer.anchor_before(0);
12139        let end = buffer.anchor_after(buffer.len());
12140        let theme = cx.theme().colors();
12141        self.background_highlights_in_range(start..end, &snapshot, theme)
12142    }
12143
12144    #[cfg(feature = "test-support")]
12145    pub fn search_background_highlights(
12146        &mut self,
12147        cx: &mut ViewContext<Self>,
12148    ) -> Vec<Range<Point>> {
12149        let snapshot = self.buffer().read(cx).snapshot(cx);
12150
12151        let highlights = self
12152            .background_highlights
12153            .get(&TypeId::of::<items::BufferSearchHighlights>());
12154
12155        if let Some((_color, ranges)) = highlights {
12156            ranges
12157                .iter()
12158                .map(|range| range.start.to_point(&snapshot)..range.end.to_point(&snapshot))
12159                .collect_vec()
12160        } else {
12161            vec![]
12162        }
12163    }
12164
12165    fn document_highlights_for_position<'a>(
12166        &'a self,
12167        position: Anchor,
12168        buffer: &'a MultiBufferSnapshot,
12169    ) -> impl 'a + Iterator<Item = &'a Range<Anchor>> {
12170        let read_highlights = self
12171            .background_highlights
12172            .get(&TypeId::of::<DocumentHighlightRead>())
12173            .map(|h| &h.1);
12174        let write_highlights = self
12175            .background_highlights
12176            .get(&TypeId::of::<DocumentHighlightWrite>())
12177            .map(|h| &h.1);
12178        let left_position = position.bias_left(buffer);
12179        let right_position = position.bias_right(buffer);
12180        read_highlights
12181            .into_iter()
12182            .chain(write_highlights)
12183            .flat_map(move |ranges| {
12184                let start_ix = match ranges.binary_search_by(|probe| {
12185                    let cmp = probe.end.cmp(&left_position, buffer);
12186                    if cmp.is_ge() {
12187                        Ordering::Greater
12188                    } else {
12189                        Ordering::Less
12190                    }
12191                }) {
12192                    Ok(i) | Err(i) => i,
12193                };
12194
12195                ranges[start_ix..]
12196                    .iter()
12197                    .take_while(move |range| range.start.cmp(&right_position, buffer).is_le())
12198            })
12199    }
12200
12201    pub fn has_background_highlights<T: 'static>(&self) -> bool {
12202        self.background_highlights
12203            .get(&TypeId::of::<T>())
12204            .map_or(false, |(_, highlights)| !highlights.is_empty())
12205    }
12206
12207    pub fn background_highlights_in_range(
12208        &self,
12209        search_range: Range<Anchor>,
12210        display_snapshot: &DisplaySnapshot,
12211        theme: &ThemeColors,
12212    ) -> Vec<(Range<DisplayPoint>, Hsla)> {
12213        let mut results = Vec::new();
12214        for (color_fetcher, ranges) in self.background_highlights.values() {
12215            let color = color_fetcher(theme);
12216            let start_ix = match ranges.binary_search_by(|probe| {
12217                let cmp = probe
12218                    .end
12219                    .cmp(&search_range.start, &display_snapshot.buffer_snapshot);
12220                if cmp.is_gt() {
12221                    Ordering::Greater
12222                } else {
12223                    Ordering::Less
12224                }
12225            }) {
12226                Ok(i) | Err(i) => i,
12227            };
12228            for range in &ranges[start_ix..] {
12229                if range
12230                    .start
12231                    .cmp(&search_range.end, &display_snapshot.buffer_snapshot)
12232                    .is_ge()
12233                {
12234                    break;
12235                }
12236
12237                let start = range.start.to_display_point(display_snapshot);
12238                let end = range.end.to_display_point(display_snapshot);
12239                results.push((start..end, color))
12240            }
12241        }
12242        results
12243    }
12244
12245    pub fn background_highlight_row_ranges<T: 'static>(
12246        &self,
12247        search_range: Range<Anchor>,
12248        display_snapshot: &DisplaySnapshot,
12249        count: usize,
12250    ) -> Vec<RangeInclusive<DisplayPoint>> {
12251        let mut results = Vec::new();
12252        let Some((_, ranges)) = self.background_highlights.get(&TypeId::of::<T>()) else {
12253            return vec![];
12254        };
12255
12256        let start_ix = match ranges.binary_search_by(|probe| {
12257            let cmp = probe
12258                .end
12259                .cmp(&search_range.start, &display_snapshot.buffer_snapshot);
12260            if cmp.is_gt() {
12261                Ordering::Greater
12262            } else {
12263                Ordering::Less
12264            }
12265        }) {
12266            Ok(i) | Err(i) => i,
12267        };
12268        let mut push_region = |start: Option<Point>, end: Option<Point>| {
12269            if let (Some(start_display), Some(end_display)) = (start, end) {
12270                results.push(
12271                    start_display.to_display_point(display_snapshot)
12272                        ..=end_display.to_display_point(display_snapshot),
12273                );
12274            }
12275        };
12276        let mut start_row: Option<Point> = None;
12277        let mut end_row: Option<Point> = None;
12278        if ranges.len() > count {
12279            return Vec::new();
12280        }
12281        for range in &ranges[start_ix..] {
12282            if range
12283                .start
12284                .cmp(&search_range.end, &display_snapshot.buffer_snapshot)
12285                .is_ge()
12286            {
12287                break;
12288            }
12289            let end = range.end.to_point(&display_snapshot.buffer_snapshot);
12290            if let Some(current_row) = &end_row {
12291                if end.row == current_row.row {
12292                    continue;
12293                }
12294            }
12295            let start = range.start.to_point(&display_snapshot.buffer_snapshot);
12296            if start_row.is_none() {
12297                assert_eq!(end_row, None);
12298                start_row = Some(start);
12299                end_row = Some(end);
12300                continue;
12301            }
12302            if let Some(current_end) = end_row.as_mut() {
12303                if start.row > current_end.row + 1 {
12304                    push_region(start_row, end_row);
12305                    start_row = Some(start);
12306                    end_row = Some(end);
12307                } else {
12308                    // Merge two hunks.
12309                    *current_end = end;
12310                }
12311            } else {
12312                unreachable!();
12313            }
12314        }
12315        // We might still have a hunk that was not rendered (if there was a search hit on the last line)
12316        push_region(start_row, end_row);
12317        results
12318    }
12319
12320    pub fn gutter_highlights_in_range(
12321        &self,
12322        search_range: Range<Anchor>,
12323        display_snapshot: &DisplaySnapshot,
12324        cx: &AppContext,
12325    ) -> Vec<(Range<DisplayPoint>, Hsla)> {
12326        let mut results = Vec::new();
12327        for (color_fetcher, ranges) in self.gutter_highlights.values() {
12328            let color = color_fetcher(cx);
12329            let start_ix = match ranges.binary_search_by(|probe| {
12330                let cmp = probe
12331                    .end
12332                    .cmp(&search_range.start, &display_snapshot.buffer_snapshot);
12333                if cmp.is_gt() {
12334                    Ordering::Greater
12335                } else {
12336                    Ordering::Less
12337                }
12338            }) {
12339                Ok(i) | Err(i) => i,
12340            };
12341            for range in &ranges[start_ix..] {
12342                if range
12343                    .start
12344                    .cmp(&search_range.end, &display_snapshot.buffer_snapshot)
12345                    .is_ge()
12346                {
12347                    break;
12348                }
12349
12350                let start = range.start.to_display_point(display_snapshot);
12351                let end = range.end.to_display_point(display_snapshot);
12352                results.push((start..end, color))
12353            }
12354        }
12355        results
12356    }
12357
12358    /// Get the text ranges corresponding to the redaction query
12359    pub fn redacted_ranges(
12360        &self,
12361        search_range: Range<Anchor>,
12362        display_snapshot: &DisplaySnapshot,
12363        cx: &WindowContext,
12364    ) -> Vec<Range<DisplayPoint>> {
12365        display_snapshot
12366            .buffer_snapshot
12367            .redacted_ranges(search_range, |file| {
12368                if let Some(file) = file {
12369                    file.is_private()
12370                        && EditorSettings::get(
12371                            Some(SettingsLocation {
12372                                worktree_id: file.worktree_id(cx),
12373                                path: file.path().as_ref(),
12374                            }),
12375                            cx,
12376                        )
12377                        .redact_private_values
12378                } else {
12379                    false
12380                }
12381            })
12382            .map(|range| {
12383                range.start.to_display_point(display_snapshot)
12384                    ..range.end.to_display_point(display_snapshot)
12385            })
12386            .collect()
12387    }
12388
12389    pub fn highlight_text<T: 'static>(
12390        &mut self,
12391        ranges: Vec<Range<Anchor>>,
12392        style: HighlightStyle,
12393        cx: &mut ViewContext<Self>,
12394    ) {
12395        self.display_map.update(cx, |map, _| {
12396            map.highlight_text(TypeId::of::<T>(), ranges, style)
12397        });
12398        cx.notify();
12399    }
12400
12401    pub(crate) fn highlight_inlays<T: 'static>(
12402        &mut self,
12403        highlights: Vec<InlayHighlight>,
12404        style: HighlightStyle,
12405        cx: &mut ViewContext<Self>,
12406    ) {
12407        self.display_map.update(cx, |map, _| {
12408            map.highlight_inlays(TypeId::of::<T>(), highlights, style)
12409        });
12410        cx.notify();
12411    }
12412
12413    pub fn text_highlights<'a, T: 'static>(
12414        &'a self,
12415        cx: &'a AppContext,
12416    ) -> Option<(HighlightStyle, &'a [Range<Anchor>])> {
12417        self.display_map.read(cx).text_highlights(TypeId::of::<T>())
12418    }
12419
12420    pub fn clear_highlights<T: 'static>(&mut self, cx: &mut ViewContext<Self>) {
12421        let cleared = self
12422            .display_map
12423            .update(cx, |map, _| map.clear_highlights(TypeId::of::<T>()));
12424        if cleared {
12425            cx.notify();
12426        }
12427    }
12428
12429    pub fn show_local_cursors(&self, cx: &WindowContext) -> bool {
12430        (self.read_only(cx) || self.blink_manager.read(cx).visible())
12431            && self.focus_handle.is_focused(cx)
12432    }
12433
12434    pub fn set_show_cursor_when_unfocused(&mut self, is_enabled: bool, cx: &mut ViewContext<Self>) {
12435        self.show_cursor_when_unfocused = is_enabled;
12436        cx.notify();
12437    }
12438
12439    pub fn lsp_store(&self, cx: &AppContext) -> Option<Model<LspStore>> {
12440        self.project
12441            .as_ref()
12442            .map(|project| project.read(cx).lsp_store())
12443    }
12444
12445    fn on_buffer_changed(&mut self, _: Model<MultiBuffer>, cx: &mut ViewContext<Self>) {
12446        cx.notify();
12447    }
12448
12449    fn on_buffer_event(
12450        &mut self,
12451        multibuffer: Model<MultiBuffer>,
12452        event: &multi_buffer::Event,
12453        cx: &mut ViewContext<Self>,
12454    ) {
12455        match event {
12456            multi_buffer::Event::Edited {
12457                singleton_buffer_edited,
12458                edited_buffer: buffer_edited,
12459            } => {
12460                self.scrollbar_marker_state.dirty = true;
12461                self.active_indent_guides_state.dirty = true;
12462                self.refresh_active_diagnostics(cx);
12463                self.refresh_code_actions(cx);
12464                if self.has_active_inline_completion() {
12465                    self.update_visible_inline_completion(cx);
12466                }
12467                if let Some(buffer) = buffer_edited {
12468                    let buffer_id = buffer.read(cx).remote_id();
12469                    if !self.registered_buffers.contains_key(&buffer_id) {
12470                        if let Some(lsp_store) = self.lsp_store(cx) {
12471                            lsp_store.update(cx, |lsp_store, cx| {
12472                                self.registered_buffers.insert(
12473                                    buffer_id,
12474                                    lsp_store.register_buffer_with_language_servers(&buffer, cx),
12475                                );
12476                            })
12477                        }
12478                    }
12479                }
12480                cx.emit(EditorEvent::BufferEdited);
12481                cx.emit(SearchEvent::MatchesInvalidated);
12482                if *singleton_buffer_edited {
12483                    if let Some(project) = &self.project {
12484                        let project = project.read(cx);
12485                        #[allow(clippy::mutable_key_type)]
12486                        let languages_affected = multibuffer
12487                            .read(cx)
12488                            .all_buffers()
12489                            .into_iter()
12490                            .filter_map(|buffer| {
12491                                let buffer = buffer.read(cx);
12492                                let language = buffer.language()?;
12493                                if project.is_local()
12494                                    && project
12495                                        .language_servers_for_local_buffer(buffer, cx)
12496                                        .count()
12497                                        == 0
12498                                {
12499                                    None
12500                                } else {
12501                                    Some(language)
12502                                }
12503                            })
12504                            .cloned()
12505                            .collect::<HashSet<_>>();
12506                        if !languages_affected.is_empty() {
12507                            self.refresh_inlay_hints(
12508                                InlayHintRefreshReason::BufferEdited(languages_affected),
12509                                cx,
12510                            );
12511                        }
12512                    }
12513                }
12514
12515                let Some(project) = &self.project else { return };
12516                let (telemetry, is_via_ssh) = {
12517                    let project = project.read(cx);
12518                    let telemetry = project.client().telemetry().clone();
12519                    let is_via_ssh = project.is_via_ssh();
12520                    (telemetry, is_via_ssh)
12521                };
12522                refresh_linked_ranges(self, cx);
12523                telemetry.log_edit_event("editor", is_via_ssh);
12524            }
12525            multi_buffer::Event::ExcerptsAdded {
12526                buffer,
12527                predecessor,
12528                excerpts,
12529            } => {
12530                self.tasks_update_task = Some(self.refresh_runnables(cx));
12531                let buffer_id = buffer.read(cx).remote_id();
12532                if !self.diff_map.diff_bases.contains_key(&buffer_id) {
12533                    if let Some(project) = &self.project {
12534                        get_unstaged_changes_for_buffers(project, [buffer.clone()], cx);
12535                    }
12536                }
12537                cx.emit(EditorEvent::ExcerptsAdded {
12538                    buffer: buffer.clone(),
12539                    predecessor: *predecessor,
12540                    excerpts: excerpts.clone(),
12541                });
12542                self.refresh_inlay_hints(InlayHintRefreshReason::NewLinesShown, cx);
12543            }
12544            multi_buffer::Event::ExcerptsRemoved { ids } => {
12545                self.refresh_inlay_hints(InlayHintRefreshReason::ExcerptsRemoved(ids.clone()), cx);
12546                let buffer = self.buffer.read(cx);
12547                self.registered_buffers
12548                    .retain(|buffer_id, _| buffer.buffer(*buffer_id).is_some());
12549                cx.emit(EditorEvent::ExcerptsRemoved { ids: ids.clone() })
12550            }
12551            multi_buffer::Event::ExcerptsEdited { ids } => {
12552                cx.emit(EditorEvent::ExcerptsEdited { ids: ids.clone() })
12553            }
12554            multi_buffer::Event::ExcerptsExpanded { ids } => {
12555                self.refresh_inlay_hints(InlayHintRefreshReason::NewLinesShown, cx);
12556                cx.emit(EditorEvent::ExcerptsExpanded { ids: ids.clone() })
12557            }
12558            multi_buffer::Event::Reparsed(buffer_id) => {
12559                self.tasks_update_task = Some(self.refresh_runnables(cx));
12560
12561                cx.emit(EditorEvent::Reparsed(*buffer_id));
12562            }
12563            multi_buffer::Event::LanguageChanged(buffer_id) => {
12564                linked_editing_ranges::refresh_linked_ranges(self, cx);
12565                cx.emit(EditorEvent::Reparsed(*buffer_id));
12566                cx.notify();
12567            }
12568            multi_buffer::Event::DirtyChanged => cx.emit(EditorEvent::DirtyChanged),
12569            multi_buffer::Event::Saved => cx.emit(EditorEvent::Saved),
12570            multi_buffer::Event::FileHandleChanged | multi_buffer::Event::Reloaded => {
12571                cx.emit(EditorEvent::TitleChanged)
12572            }
12573            // multi_buffer::Event::DiffBaseChanged => {
12574            //     self.scrollbar_marker_state.dirty = true;
12575            //     cx.emit(EditorEvent::DiffBaseChanged);
12576            //     cx.notify();
12577            // }
12578            multi_buffer::Event::Closed => cx.emit(EditorEvent::Closed),
12579            multi_buffer::Event::DiagnosticsUpdated => {
12580                self.refresh_active_diagnostics(cx);
12581                self.scrollbar_marker_state.dirty = true;
12582                cx.notify();
12583            }
12584            _ => {}
12585        };
12586    }
12587
12588    fn on_display_map_changed(&mut self, _: Model<DisplayMap>, cx: &mut ViewContext<Self>) {
12589        cx.notify();
12590    }
12591
12592    fn settings_changed(&mut self, cx: &mut ViewContext<Self>) {
12593        self.tasks_update_task = Some(self.refresh_runnables(cx));
12594        self.refresh_inline_completion(true, false, cx);
12595        self.refresh_inlay_hints(
12596            InlayHintRefreshReason::SettingsChange(inlay_hint_settings(
12597                self.selections.newest_anchor().head(),
12598                &self.buffer.read(cx).snapshot(cx),
12599                cx,
12600            )),
12601            cx,
12602        );
12603
12604        let old_cursor_shape = self.cursor_shape;
12605
12606        {
12607            let editor_settings = EditorSettings::get_global(cx);
12608            self.scroll_manager.vertical_scroll_margin = editor_settings.vertical_scroll_margin;
12609            self.show_breadcrumbs = editor_settings.toolbar.breadcrumbs;
12610            self.cursor_shape = editor_settings.cursor_shape.unwrap_or_default();
12611        }
12612
12613        if old_cursor_shape != self.cursor_shape {
12614            cx.emit(EditorEvent::CursorShapeChanged);
12615        }
12616
12617        let project_settings = ProjectSettings::get_global(cx);
12618        self.serialize_dirty_buffers = project_settings.session.restore_unsaved_buffers;
12619
12620        if self.mode == EditorMode::Full {
12621            let inline_blame_enabled = project_settings.git.inline_blame_enabled();
12622            if self.git_blame_inline_enabled != inline_blame_enabled {
12623                self.toggle_git_blame_inline_internal(false, cx);
12624            }
12625        }
12626
12627        cx.notify();
12628    }
12629
12630    pub fn set_searchable(&mut self, searchable: bool) {
12631        self.searchable = searchable;
12632    }
12633
12634    pub fn searchable(&self) -> bool {
12635        self.searchable
12636    }
12637
12638    fn open_proposed_changes_editor(
12639        &mut self,
12640        _: &OpenProposedChangesEditor,
12641        cx: &mut ViewContext<Self>,
12642    ) {
12643        let Some(workspace) = self.workspace() else {
12644            cx.propagate();
12645            return;
12646        };
12647
12648        let selections = self.selections.all::<usize>(cx);
12649        let multi_buffer = self.buffer.read(cx);
12650        let multi_buffer_snapshot = multi_buffer.snapshot(cx);
12651        let mut new_selections_by_buffer = HashMap::default();
12652        for selection in selections {
12653            for (excerpt, range) in
12654                multi_buffer_snapshot.range_to_buffer_ranges(selection.start..selection.end)
12655            {
12656                let mut range = range.to_point(excerpt.buffer());
12657                range.start.column = 0;
12658                range.end.column = excerpt.buffer().line_len(range.end.row);
12659                new_selections_by_buffer
12660                    .entry(multi_buffer.buffer(excerpt.buffer_id()).unwrap())
12661                    .or_insert(Vec::new())
12662                    .push(range)
12663            }
12664        }
12665
12666        let proposed_changes_buffers = new_selections_by_buffer
12667            .into_iter()
12668            .map(|(buffer, ranges)| ProposedChangeLocation { buffer, ranges })
12669            .collect::<Vec<_>>();
12670        let proposed_changes_editor = cx.new_view(|cx| {
12671            ProposedChangesEditor::new(
12672                "Proposed changes",
12673                proposed_changes_buffers,
12674                self.project.clone(),
12675                cx,
12676            )
12677        });
12678
12679        cx.window_context().defer(move |cx| {
12680            workspace.update(cx, |workspace, cx| {
12681                workspace.active_pane().update(cx, |pane, cx| {
12682                    pane.add_item(Box::new(proposed_changes_editor), true, true, None, cx);
12683                });
12684            });
12685        });
12686    }
12687
12688    pub fn open_excerpts_in_split(&mut self, _: &OpenExcerptsSplit, cx: &mut ViewContext<Self>) {
12689        self.open_excerpts_common(None, true, cx)
12690    }
12691
12692    pub fn open_excerpts(&mut self, _: &OpenExcerpts, cx: &mut ViewContext<Self>) {
12693        self.open_excerpts_common(None, false, cx)
12694    }
12695
12696    fn open_excerpts_common(
12697        &mut self,
12698        jump_data: Option<JumpData>,
12699        split: bool,
12700        cx: &mut ViewContext<Self>,
12701    ) {
12702        let Some(workspace) = self.workspace() else {
12703            cx.propagate();
12704            return;
12705        };
12706
12707        if self.buffer.read(cx).is_singleton() {
12708            cx.propagate();
12709            return;
12710        }
12711
12712        let mut new_selections_by_buffer = HashMap::default();
12713        match &jump_data {
12714            Some(JumpData::MultiBufferPoint {
12715                excerpt_id,
12716                position,
12717                anchor,
12718                line_offset_from_top,
12719            }) => {
12720                let multi_buffer_snapshot = self.buffer.read(cx).snapshot(cx);
12721                if let Some(buffer) = multi_buffer_snapshot
12722                    .buffer_id_for_excerpt(*excerpt_id)
12723                    .and_then(|buffer_id| self.buffer.read(cx).buffer(buffer_id))
12724                {
12725                    let buffer_snapshot = buffer.read(cx).snapshot();
12726                    let jump_to_point = if buffer_snapshot.can_resolve(anchor) {
12727                        language::ToPoint::to_point(anchor, &buffer_snapshot)
12728                    } else {
12729                        buffer_snapshot.clip_point(*position, Bias::Left)
12730                    };
12731                    let jump_to_offset = buffer_snapshot.point_to_offset(jump_to_point);
12732                    new_selections_by_buffer.insert(
12733                        buffer,
12734                        (
12735                            vec![jump_to_offset..jump_to_offset],
12736                            Some(*line_offset_from_top),
12737                        ),
12738                    );
12739                }
12740            }
12741            Some(JumpData::MultiBufferRow {
12742                row,
12743                line_offset_from_top,
12744            }) => {
12745                let point = MultiBufferPoint::new(row.0, 0);
12746                if let Some((buffer, buffer_point, _)) =
12747                    self.buffer.read(cx).point_to_buffer_point(point, cx)
12748                {
12749                    let buffer_offset = buffer.read(cx).point_to_offset(buffer_point);
12750                    new_selections_by_buffer
12751                        .entry(buffer)
12752                        .or_insert((Vec::new(), Some(*line_offset_from_top)))
12753                        .0
12754                        .push(buffer_offset..buffer_offset)
12755                }
12756            }
12757            None => {
12758                let selections = self.selections.all::<usize>(cx);
12759                let multi_buffer = self.buffer.read(cx);
12760                for selection in selections {
12761                    for (excerpt, mut range) in multi_buffer
12762                        .snapshot(cx)
12763                        .range_to_buffer_ranges(selection.range())
12764                    {
12765                        // When editing branch buffers, jump to the corresponding location
12766                        // in their base buffer.
12767                        let mut buffer_handle = multi_buffer.buffer(excerpt.buffer_id()).unwrap();
12768                        let buffer = buffer_handle.read(cx);
12769                        if let Some(base_buffer) = buffer.base_buffer() {
12770                            range = buffer.range_to_version(range, &base_buffer.read(cx).version());
12771                            buffer_handle = base_buffer;
12772                        }
12773
12774                        if selection.reversed {
12775                            mem::swap(&mut range.start, &mut range.end);
12776                        }
12777                        new_selections_by_buffer
12778                            .entry(buffer_handle)
12779                            .or_insert((Vec::new(), None))
12780                            .0
12781                            .push(range)
12782                    }
12783                }
12784            }
12785        }
12786
12787        if new_selections_by_buffer.is_empty() {
12788            return;
12789        }
12790
12791        // We defer the pane interaction because we ourselves are a workspace item
12792        // and activating a new item causes the pane to call a method on us reentrantly,
12793        // which panics if we're on the stack.
12794        cx.window_context().defer(move |cx| {
12795            workspace.update(cx, |workspace, cx| {
12796                let pane = if split {
12797                    workspace.adjacent_pane(cx)
12798                } else {
12799                    workspace.active_pane().clone()
12800                };
12801
12802                for (buffer, (ranges, scroll_offset)) in new_selections_by_buffer {
12803                    let editor = buffer
12804                        .read(cx)
12805                        .file()
12806                        .is_none()
12807                        .then(|| {
12808                            // Handle file-less buffers separately: those are not really the project items, so won't have a project path or entity id,
12809                            // so `workspace.open_project_item` will never find them, always opening a new editor.
12810                            // Instead, we try to activate the existing editor in the pane first.
12811                            let (editor, pane_item_index) =
12812                                pane.read(cx).items().enumerate().find_map(|(i, item)| {
12813                                    let editor = item.downcast::<Editor>()?;
12814                                    let singleton_buffer =
12815                                        editor.read(cx).buffer().read(cx).as_singleton()?;
12816                                    if singleton_buffer == buffer {
12817                                        Some((editor, i))
12818                                    } else {
12819                                        None
12820                                    }
12821                                })?;
12822                            pane.update(cx, |pane, cx| {
12823                                pane.activate_item(pane_item_index, true, true, cx)
12824                            });
12825                            Some(editor)
12826                        })
12827                        .flatten()
12828                        .unwrap_or_else(|| {
12829                            workspace.open_project_item::<Self>(
12830                                pane.clone(),
12831                                buffer,
12832                                true,
12833                                true,
12834                                cx,
12835                            )
12836                        });
12837
12838                    editor.update(cx, |editor, cx| {
12839                        let autoscroll = match scroll_offset {
12840                            Some(scroll_offset) => Autoscroll::top_relative(scroll_offset as usize),
12841                            None => Autoscroll::newest(),
12842                        };
12843                        let nav_history = editor.nav_history.take();
12844                        editor.change_selections(Some(autoscroll), cx, |s| {
12845                            s.select_ranges(ranges);
12846                        });
12847                        editor.nav_history = nav_history;
12848                    });
12849                }
12850            })
12851        });
12852    }
12853
12854    fn marked_text_ranges(&self, cx: &AppContext) -> Option<Vec<Range<OffsetUtf16>>> {
12855        let snapshot = self.buffer.read(cx).read(cx);
12856        let (_, ranges) = self.text_highlights::<InputComposition>(cx)?;
12857        Some(
12858            ranges
12859                .iter()
12860                .map(move |range| {
12861                    range.start.to_offset_utf16(&snapshot)..range.end.to_offset_utf16(&snapshot)
12862                })
12863                .collect(),
12864        )
12865    }
12866
12867    fn selection_replacement_ranges(
12868        &self,
12869        range: Range<OffsetUtf16>,
12870        cx: &mut AppContext,
12871    ) -> Vec<Range<OffsetUtf16>> {
12872        let selections = self.selections.all::<OffsetUtf16>(cx);
12873        let newest_selection = selections
12874            .iter()
12875            .max_by_key(|selection| selection.id)
12876            .unwrap();
12877        let start_delta = range.start.0 as isize - newest_selection.start.0 as isize;
12878        let end_delta = range.end.0 as isize - newest_selection.end.0 as isize;
12879        let snapshot = self.buffer.read(cx).read(cx);
12880        selections
12881            .into_iter()
12882            .map(|mut selection| {
12883                selection.start.0 =
12884                    (selection.start.0 as isize).saturating_add(start_delta) as usize;
12885                selection.end.0 = (selection.end.0 as isize).saturating_add(end_delta) as usize;
12886                snapshot.clip_offset_utf16(selection.start, Bias::Left)
12887                    ..snapshot.clip_offset_utf16(selection.end, Bias::Right)
12888            })
12889            .collect()
12890    }
12891
12892    fn report_editor_event(
12893        &self,
12894        event_type: &'static str,
12895        file_extension: Option<String>,
12896        cx: &AppContext,
12897    ) {
12898        if cfg!(any(test, feature = "test-support")) {
12899            return;
12900        }
12901
12902        let Some(project) = &self.project else { return };
12903
12904        // If None, we are in a file without an extension
12905        let file = self
12906            .buffer
12907            .read(cx)
12908            .as_singleton()
12909            .and_then(|b| b.read(cx).file());
12910        let file_extension = file_extension.or(file
12911            .as_ref()
12912            .and_then(|file| Path::new(file.file_name(cx)).extension())
12913            .and_then(|e| e.to_str())
12914            .map(|a| a.to_string()));
12915
12916        let vim_mode = cx
12917            .global::<SettingsStore>()
12918            .raw_user_settings()
12919            .get("vim_mode")
12920            == Some(&serde_json::Value::Bool(true));
12921
12922        let copilot_enabled = all_language_settings(file, cx).inline_completions.provider
12923            == language::language_settings::InlineCompletionProvider::Copilot;
12924        let copilot_enabled_for_language = self
12925            .buffer
12926            .read(cx)
12927            .settings_at(0, cx)
12928            .show_inline_completions;
12929
12930        let project = project.read(cx);
12931        telemetry::event!(
12932            event_type,
12933            file_extension,
12934            vim_mode,
12935            copilot_enabled,
12936            copilot_enabled_for_language,
12937            is_via_ssh = project.is_via_ssh(),
12938        );
12939    }
12940
12941    /// Copy the highlighted chunks to the clipboard as JSON. The format is an array of lines,
12942    /// with each line being an array of {text, highlight} objects.
12943    fn copy_highlight_json(&mut self, _: &CopyHighlightJson, cx: &mut ViewContext<Self>) {
12944        let Some(buffer) = self.buffer.read(cx).as_singleton() else {
12945            return;
12946        };
12947
12948        #[derive(Serialize)]
12949        struct Chunk<'a> {
12950            text: String,
12951            highlight: Option<&'a str>,
12952        }
12953
12954        let snapshot = buffer.read(cx).snapshot();
12955        let range = self
12956            .selected_text_range(false, cx)
12957            .and_then(|selection| {
12958                if selection.range.is_empty() {
12959                    None
12960                } else {
12961                    Some(selection.range)
12962                }
12963            })
12964            .unwrap_or_else(|| 0..snapshot.len());
12965
12966        let chunks = snapshot.chunks(range, true);
12967        let mut lines = Vec::new();
12968        let mut line: VecDeque<Chunk> = VecDeque::new();
12969
12970        let Some(style) = self.style.as_ref() else {
12971            return;
12972        };
12973
12974        for chunk in chunks {
12975            let highlight = chunk
12976                .syntax_highlight_id
12977                .and_then(|id| id.name(&style.syntax));
12978            let mut chunk_lines = chunk.text.split('\n').peekable();
12979            while let Some(text) = chunk_lines.next() {
12980                let mut merged_with_last_token = false;
12981                if let Some(last_token) = line.back_mut() {
12982                    if last_token.highlight == highlight {
12983                        last_token.text.push_str(text);
12984                        merged_with_last_token = true;
12985                    }
12986                }
12987
12988                if !merged_with_last_token {
12989                    line.push_back(Chunk {
12990                        text: text.into(),
12991                        highlight,
12992                    });
12993                }
12994
12995                if chunk_lines.peek().is_some() {
12996                    if line.len() > 1 && line.front().unwrap().text.is_empty() {
12997                        line.pop_front();
12998                    }
12999                    if line.len() > 1 && line.back().unwrap().text.is_empty() {
13000                        line.pop_back();
13001                    }
13002
13003                    lines.push(mem::take(&mut line));
13004                }
13005            }
13006        }
13007
13008        let Some(lines) = serde_json::to_string_pretty(&lines).log_err() else {
13009            return;
13010        };
13011        cx.write_to_clipboard(ClipboardItem::new_string(lines));
13012    }
13013
13014    pub fn open_context_menu(&mut self, _: &OpenContextMenu, cx: &mut ViewContext<Self>) {
13015        self.request_autoscroll(Autoscroll::newest(), cx);
13016        let position = self.selections.newest_display(cx).start;
13017        mouse_context_menu::deploy_context_menu(self, None, position, cx);
13018    }
13019
13020    pub fn inlay_hint_cache(&self) -> &InlayHintCache {
13021        &self.inlay_hint_cache
13022    }
13023
13024    pub fn replay_insert_event(
13025        &mut self,
13026        text: &str,
13027        relative_utf16_range: Option<Range<isize>>,
13028        cx: &mut ViewContext<Self>,
13029    ) {
13030        if !self.input_enabled {
13031            cx.emit(EditorEvent::InputIgnored { text: text.into() });
13032            return;
13033        }
13034        if let Some(relative_utf16_range) = relative_utf16_range {
13035            let selections = self.selections.all::<OffsetUtf16>(cx);
13036            self.change_selections(None, cx, |s| {
13037                let new_ranges = selections.into_iter().map(|range| {
13038                    let start = OffsetUtf16(
13039                        range
13040                            .head()
13041                            .0
13042                            .saturating_add_signed(relative_utf16_range.start),
13043                    );
13044                    let end = OffsetUtf16(
13045                        range
13046                            .head()
13047                            .0
13048                            .saturating_add_signed(relative_utf16_range.end),
13049                    );
13050                    start..end
13051                });
13052                s.select_ranges(new_ranges);
13053            });
13054        }
13055
13056        self.handle_input(text, cx);
13057    }
13058
13059    pub fn supports_inlay_hints(&self, cx: &AppContext) -> bool {
13060        let Some(provider) = self.semantics_provider.as_ref() else {
13061            return false;
13062        };
13063
13064        let mut supports = false;
13065        self.buffer().read(cx).for_each_buffer(|buffer| {
13066            supports |= provider.supports_inlay_hints(buffer, cx);
13067        });
13068        supports
13069    }
13070
13071    pub fn focus(&self, cx: &mut WindowContext) {
13072        cx.focus(&self.focus_handle)
13073    }
13074
13075    pub fn is_focused(&self, cx: &WindowContext) -> bool {
13076        self.focus_handle.is_focused(cx)
13077    }
13078
13079    fn handle_focus(&mut self, cx: &mut ViewContext<Self>) {
13080        cx.emit(EditorEvent::Focused);
13081
13082        if let Some(descendant) = self
13083            .last_focused_descendant
13084            .take()
13085            .and_then(|descendant| descendant.upgrade())
13086        {
13087            cx.focus(&descendant);
13088        } else {
13089            if let Some(blame) = self.blame.as_ref() {
13090                blame.update(cx, GitBlame::focus)
13091            }
13092
13093            self.blink_manager.update(cx, BlinkManager::enable);
13094            self.show_cursor_names(cx);
13095            self.buffer.update(cx, |buffer, cx| {
13096                buffer.finalize_last_transaction(cx);
13097                if self.leader_peer_id.is_none() {
13098                    buffer.set_active_selections(
13099                        &self.selections.disjoint_anchors(),
13100                        self.selections.line_mode,
13101                        self.cursor_shape,
13102                        cx,
13103                    );
13104                }
13105            });
13106        }
13107    }
13108
13109    fn handle_focus_in(&mut self, cx: &mut ViewContext<Self>) {
13110        cx.emit(EditorEvent::FocusedIn)
13111    }
13112
13113    fn handle_focus_out(&mut self, event: FocusOutEvent, _cx: &mut ViewContext<Self>) {
13114        if event.blurred != self.focus_handle {
13115            self.last_focused_descendant = Some(event.blurred);
13116        }
13117    }
13118
13119    pub fn handle_blur(&mut self, cx: &mut ViewContext<Self>) {
13120        self.blink_manager.update(cx, BlinkManager::disable);
13121        self.buffer
13122            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
13123
13124        if let Some(blame) = self.blame.as_ref() {
13125            blame.update(cx, GitBlame::blur)
13126        }
13127        if !self.hover_state.focused(cx) {
13128            hide_hover(self, cx);
13129        }
13130
13131        self.hide_context_menu(cx);
13132        cx.emit(EditorEvent::Blurred);
13133        cx.notify();
13134    }
13135
13136    pub fn register_action<A: Action>(
13137        &mut self,
13138        listener: impl Fn(&A, &mut WindowContext) + 'static,
13139    ) -> Subscription {
13140        let id = self.next_editor_action_id.post_inc();
13141        let listener = Arc::new(listener);
13142        self.editor_actions.borrow_mut().insert(
13143            id,
13144            Box::new(move |cx| {
13145                let cx = cx.window_context();
13146                let listener = listener.clone();
13147                cx.on_action(TypeId::of::<A>(), move |action, phase, cx| {
13148                    let action = action.downcast_ref().unwrap();
13149                    if phase == DispatchPhase::Bubble {
13150                        listener(action, cx)
13151                    }
13152                })
13153            }),
13154        );
13155
13156        let editor_actions = self.editor_actions.clone();
13157        Subscription::new(move || {
13158            editor_actions.borrow_mut().remove(&id);
13159        })
13160    }
13161
13162    pub fn file_header_size(&self) -> u32 {
13163        FILE_HEADER_HEIGHT
13164    }
13165
13166    pub fn revert(
13167        &mut self,
13168        revert_changes: HashMap<BufferId, Vec<(Range<text::Anchor>, Rope)>>,
13169        cx: &mut ViewContext<Self>,
13170    ) {
13171        self.buffer().update(cx, |multi_buffer, cx| {
13172            for (buffer_id, changes) in revert_changes {
13173                if let Some(buffer) = multi_buffer.buffer(buffer_id) {
13174                    buffer.update(cx, |buffer, cx| {
13175                        buffer.edit(
13176                            changes.into_iter().map(|(range, text)| {
13177                                (range, text.to_string().map(Arc::<str>::from))
13178                            }),
13179                            None,
13180                            cx,
13181                        );
13182                    });
13183                }
13184            }
13185        });
13186        self.change_selections(None, cx, |selections| selections.refresh());
13187    }
13188
13189    pub fn to_pixel_point(
13190        &mut self,
13191        source: multi_buffer::Anchor,
13192        editor_snapshot: &EditorSnapshot,
13193        cx: &mut ViewContext<Self>,
13194    ) -> Option<gpui::Point<Pixels>> {
13195        let source_point = source.to_display_point(editor_snapshot);
13196        self.display_to_pixel_point(source_point, editor_snapshot, cx)
13197    }
13198
13199    pub fn display_to_pixel_point(
13200        &self,
13201        source: DisplayPoint,
13202        editor_snapshot: &EditorSnapshot,
13203        cx: &WindowContext,
13204    ) -> Option<gpui::Point<Pixels>> {
13205        let line_height = self.style()?.text.line_height_in_pixels(cx.rem_size());
13206        let text_layout_details = self.text_layout_details(cx);
13207        let scroll_top = text_layout_details
13208            .scroll_anchor
13209            .scroll_position(editor_snapshot)
13210            .y;
13211
13212        if source.row().as_f32() < scroll_top.floor() {
13213            return None;
13214        }
13215        let source_x = editor_snapshot.x_for_display_point(source, &text_layout_details);
13216        let source_y = line_height * (source.row().as_f32() - scroll_top);
13217        Some(gpui::Point::new(source_x, source_y))
13218    }
13219
13220    pub fn has_active_completions_menu(&self) -> bool {
13221        self.context_menu.borrow().as_ref().map_or(false, |menu| {
13222            menu.visible() && matches!(menu, CodeContextMenu::Completions(_))
13223        })
13224    }
13225
13226    pub fn register_addon<T: Addon>(&mut self, instance: T) {
13227        self.addons
13228            .insert(std::any::TypeId::of::<T>(), Box::new(instance));
13229    }
13230
13231    pub fn unregister_addon<T: Addon>(&mut self) {
13232        self.addons.remove(&std::any::TypeId::of::<T>());
13233    }
13234
13235    pub fn addon<T: Addon>(&self) -> Option<&T> {
13236        let type_id = std::any::TypeId::of::<T>();
13237        self.addons
13238            .get(&type_id)
13239            .and_then(|item| item.to_any().downcast_ref::<T>())
13240    }
13241
13242    pub fn add_change_set(
13243        &mut self,
13244        change_set: Model<BufferChangeSet>,
13245        cx: &mut ViewContext<Self>,
13246    ) {
13247        self.diff_map.add_change_set(change_set, cx);
13248    }
13249
13250    fn character_size(&self, cx: &mut ViewContext<Self>) -> gpui::Point<Pixels> {
13251        let text_layout_details = self.text_layout_details(cx);
13252        let style = &text_layout_details.editor_style;
13253        let font_id = cx.text_system().resolve_font(&style.text.font());
13254        let font_size = style.text.font_size.to_pixels(cx.rem_size());
13255        let line_height = style.text.line_height_in_pixels(cx.rem_size());
13256
13257        let em_width = cx
13258            .text_system()
13259            .typographic_bounds(font_id, font_size, 'm')
13260            .unwrap()
13261            .size
13262            .width;
13263
13264        gpui::Point::new(em_width, line_height)
13265    }
13266}
13267
13268fn get_unstaged_changes_for_buffers(
13269    project: &Model<Project>,
13270    buffers: impl IntoIterator<Item = Model<Buffer>>,
13271    cx: &mut ViewContext<Editor>,
13272) {
13273    let mut tasks = Vec::new();
13274    project.update(cx, |project, cx| {
13275        for buffer in buffers {
13276            tasks.push(project.open_unstaged_changes(buffer.clone(), cx))
13277        }
13278    });
13279    cx.spawn(|this, mut cx| async move {
13280        let change_sets = futures::future::join_all(tasks).await;
13281        this.update(&mut cx, |this, cx| {
13282            for change_set in change_sets {
13283                if let Some(change_set) = change_set.log_err() {
13284                    this.diff_map.add_change_set(change_set, cx);
13285                }
13286            }
13287        })
13288        .ok();
13289    })
13290    .detach();
13291}
13292
13293fn char_len_with_expanded_tabs(offset: usize, text: &str, tab_size: NonZeroU32) -> usize {
13294    let tab_size = tab_size.get() as usize;
13295    let mut width = offset;
13296
13297    for ch in text.chars() {
13298        width += if ch == '\t' {
13299            tab_size - (width % tab_size)
13300        } else {
13301            1
13302        };
13303    }
13304
13305    width - offset
13306}
13307
13308#[cfg(test)]
13309mod tests {
13310    use super::*;
13311
13312    #[test]
13313    fn test_string_size_with_expanded_tabs() {
13314        let nz = |val| NonZeroU32::new(val).unwrap();
13315        assert_eq!(char_len_with_expanded_tabs(0, "", nz(4)), 0);
13316        assert_eq!(char_len_with_expanded_tabs(0, "hello", nz(4)), 5);
13317        assert_eq!(char_len_with_expanded_tabs(0, "\thello", nz(4)), 9);
13318        assert_eq!(char_len_with_expanded_tabs(0, "abc\tab", nz(4)), 6);
13319        assert_eq!(char_len_with_expanded_tabs(0, "hello\t", nz(4)), 8);
13320        assert_eq!(char_len_with_expanded_tabs(0, "\t\t", nz(8)), 16);
13321        assert_eq!(char_len_with_expanded_tabs(0, "x\t", nz(8)), 8);
13322        assert_eq!(char_len_with_expanded_tabs(7, "x\t", nz(8)), 9);
13323    }
13324}
13325
13326/// Tokenizes a string into runs of text that should stick together, or that is whitespace.
13327struct WordBreakingTokenizer<'a> {
13328    input: &'a str,
13329}
13330
13331impl<'a> WordBreakingTokenizer<'a> {
13332    fn new(input: &'a str) -> Self {
13333        Self { input }
13334    }
13335}
13336
13337fn is_char_ideographic(ch: char) -> bool {
13338    use unicode_script::Script::*;
13339    use unicode_script::UnicodeScript;
13340    matches!(ch.script(), Han | Tangut | Yi)
13341}
13342
13343fn is_grapheme_ideographic(text: &str) -> bool {
13344    text.chars().any(is_char_ideographic)
13345}
13346
13347fn is_grapheme_whitespace(text: &str) -> bool {
13348    text.chars().any(|x| x.is_whitespace())
13349}
13350
13351fn should_stay_with_preceding_ideograph(text: &str) -> bool {
13352    text.chars().next().map_or(false, |ch| {
13353        matches!(ch, '。' | '、' | ',' | '?' | '!' | ':' | ';' | '…')
13354    })
13355}
13356
13357#[derive(PartialEq, Eq, Debug, Clone, Copy)]
13358struct WordBreakToken<'a> {
13359    token: &'a str,
13360    grapheme_len: usize,
13361    is_whitespace: bool,
13362}
13363
13364impl<'a> Iterator for WordBreakingTokenizer<'a> {
13365    /// Yields a span, the count of graphemes in the token, and whether it was
13366    /// whitespace. Note that it also breaks at word boundaries.
13367    type Item = WordBreakToken<'a>;
13368
13369    fn next(&mut self) -> Option<Self::Item> {
13370        use unicode_segmentation::UnicodeSegmentation;
13371        if self.input.is_empty() {
13372            return None;
13373        }
13374
13375        let mut iter = self.input.graphemes(true).peekable();
13376        let mut offset = 0;
13377        let mut graphemes = 0;
13378        if let Some(first_grapheme) = iter.next() {
13379            let is_whitespace = is_grapheme_whitespace(first_grapheme);
13380            offset += first_grapheme.len();
13381            graphemes += 1;
13382            if is_grapheme_ideographic(first_grapheme) && !is_whitespace {
13383                if let Some(grapheme) = iter.peek().copied() {
13384                    if should_stay_with_preceding_ideograph(grapheme) {
13385                        offset += grapheme.len();
13386                        graphemes += 1;
13387                    }
13388                }
13389            } else {
13390                let mut words = self.input[offset..].split_word_bound_indices().peekable();
13391                let mut next_word_bound = words.peek().copied();
13392                if next_word_bound.map_or(false, |(i, _)| i == 0) {
13393                    next_word_bound = words.next();
13394                }
13395                while let Some(grapheme) = iter.peek().copied() {
13396                    if next_word_bound.map_or(false, |(i, _)| i == offset) {
13397                        break;
13398                    };
13399                    if is_grapheme_whitespace(grapheme) != is_whitespace {
13400                        break;
13401                    };
13402                    offset += grapheme.len();
13403                    graphemes += 1;
13404                    iter.next();
13405                }
13406            }
13407            let token = &self.input[..offset];
13408            self.input = &self.input[offset..];
13409            if is_whitespace {
13410                Some(WordBreakToken {
13411                    token: " ",
13412                    grapheme_len: 1,
13413                    is_whitespace: true,
13414                })
13415            } else {
13416                Some(WordBreakToken {
13417                    token,
13418                    grapheme_len: graphemes,
13419                    is_whitespace: false,
13420                })
13421            }
13422        } else {
13423            None
13424        }
13425    }
13426}
13427
13428#[test]
13429fn test_word_breaking_tokenizer() {
13430    let tests: &[(&str, &[(&str, usize, bool)])] = &[
13431        ("", &[]),
13432        ("  ", &[(" ", 1, true)]),
13433        ("Ʒ", &[("Ʒ", 1, false)]),
13434        ("Ǽ", &[("Ǽ", 1, false)]),
13435        ("", &[("", 1, false)]),
13436        ("⋑⋑", &[("⋑⋑", 2, false)]),
13437        (
13438            "原理,进而",
13439            &[
13440                ("", 1, false),
13441                ("理,", 2, false),
13442                ("", 1, false),
13443                ("", 1, false),
13444            ],
13445        ),
13446        (
13447            "hello world",
13448            &[("hello", 5, false), (" ", 1, true), ("world", 5, false)],
13449        ),
13450        (
13451            "hello, world",
13452            &[("hello,", 6, false), (" ", 1, true), ("world", 5, false)],
13453        ),
13454        (
13455            "  hello world",
13456            &[
13457                (" ", 1, true),
13458                ("hello", 5, false),
13459                (" ", 1, true),
13460                ("world", 5, false),
13461            ],
13462        ),
13463        (
13464            "这是什么 \n 钢笔",
13465            &[
13466                ("", 1, false),
13467                ("", 1, false),
13468                ("", 1, false),
13469                ("", 1, false),
13470                (" ", 1, true),
13471                ("", 1, false),
13472                ("", 1, false),
13473            ],
13474        ),
13475        (" mutton", &[(" ", 1, true), ("mutton", 6, false)]),
13476    ];
13477
13478    for (input, result) in tests {
13479        assert_eq!(
13480            WordBreakingTokenizer::new(input).collect::<Vec<_>>(),
13481            result
13482                .iter()
13483                .copied()
13484                .map(|(token, grapheme_len, is_whitespace)| WordBreakToken {
13485                    token,
13486                    grapheme_len,
13487                    is_whitespace,
13488                })
13489                .collect::<Vec<_>>()
13490        );
13491    }
13492}
13493
13494fn wrap_with_prefix(
13495    line_prefix: String,
13496    unwrapped_text: String,
13497    wrap_column: usize,
13498    tab_size: NonZeroU32,
13499) -> String {
13500    let line_prefix_len = char_len_with_expanded_tabs(0, &line_prefix, tab_size);
13501    let mut wrapped_text = String::new();
13502    let mut current_line = line_prefix.clone();
13503
13504    let tokenizer = WordBreakingTokenizer::new(&unwrapped_text);
13505    let mut current_line_len = line_prefix_len;
13506    for WordBreakToken {
13507        token,
13508        grapheme_len,
13509        is_whitespace,
13510    } in tokenizer
13511    {
13512        if current_line_len + grapheme_len > wrap_column && current_line_len != line_prefix_len {
13513            wrapped_text.push_str(current_line.trim_end());
13514            wrapped_text.push('\n');
13515            current_line.truncate(line_prefix.len());
13516            current_line_len = line_prefix_len;
13517            if !is_whitespace {
13518                current_line.push_str(token);
13519                current_line_len += grapheme_len;
13520            }
13521        } else if !is_whitespace {
13522            current_line.push_str(token);
13523            current_line_len += grapheme_len;
13524        } else if current_line_len != line_prefix_len {
13525            current_line.push(' ');
13526            current_line_len += 1;
13527        }
13528    }
13529
13530    if !current_line.is_empty() {
13531        wrapped_text.push_str(&current_line);
13532    }
13533    wrapped_text
13534}
13535
13536#[test]
13537fn test_wrap_with_prefix() {
13538    assert_eq!(
13539        wrap_with_prefix(
13540            "# ".to_string(),
13541            "abcdefg".to_string(),
13542            4,
13543            NonZeroU32::new(4).unwrap()
13544        ),
13545        "# abcdefg"
13546    );
13547    assert_eq!(
13548        wrap_with_prefix(
13549            "".to_string(),
13550            "\thello world".to_string(),
13551            8,
13552            NonZeroU32::new(4).unwrap()
13553        ),
13554        "hello\nworld"
13555    );
13556    assert_eq!(
13557        wrap_with_prefix(
13558            "// ".to_string(),
13559            "xx \nyy zz aa bb cc".to_string(),
13560            12,
13561            NonZeroU32::new(4).unwrap()
13562        ),
13563        "// xx yy zz\n// aa bb cc"
13564    );
13565    assert_eq!(
13566        wrap_with_prefix(
13567            String::new(),
13568            "这是什么 \n 钢笔".to_string(),
13569            3,
13570            NonZeroU32::new(4).unwrap()
13571        ),
13572        "这是什\n么 钢\n"
13573    );
13574}
13575
13576fn hunks_for_selections(
13577    snapshot: &EditorSnapshot,
13578    selections: &[Selection<Point>],
13579) -> Vec<MultiBufferDiffHunk> {
13580    hunks_for_ranges(
13581        selections.iter().map(|selection| selection.range()),
13582        snapshot,
13583    )
13584}
13585
13586pub fn hunks_for_ranges(
13587    ranges: impl Iterator<Item = Range<Point>>,
13588    snapshot: &EditorSnapshot,
13589) -> Vec<MultiBufferDiffHunk> {
13590    let mut hunks = Vec::new();
13591    let mut processed_buffer_rows: HashMap<BufferId, HashSet<Range<text::Anchor>>> =
13592        HashMap::default();
13593    for query_range in ranges {
13594        let query_rows =
13595            MultiBufferRow(query_range.start.row)..MultiBufferRow(query_range.end.row + 1);
13596        for hunk in snapshot.diff_map.diff_hunks_in_range(
13597            Point::new(query_rows.start.0, 0)..Point::new(query_rows.end.0, 0),
13598            &snapshot.buffer_snapshot,
13599        ) {
13600            // Deleted hunk is an empty row range, no caret can be placed there and Zed allows to revert it
13601            // when the caret is just above or just below the deleted hunk.
13602            let allow_adjacent = hunk_status(&hunk) == DiffHunkStatus::Removed;
13603            let related_to_selection = if allow_adjacent {
13604                hunk.row_range.overlaps(&query_rows)
13605                    || hunk.row_range.start == query_rows.end
13606                    || hunk.row_range.end == query_rows.start
13607            } else {
13608                hunk.row_range.overlaps(&query_rows)
13609            };
13610            if related_to_selection {
13611                if !processed_buffer_rows
13612                    .entry(hunk.buffer_id)
13613                    .or_default()
13614                    .insert(hunk.buffer_range.start..hunk.buffer_range.end)
13615                {
13616                    continue;
13617                }
13618                hunks.push(hunk);
13619            }
13620        }
13621    }
13622
13623    hunks
13624}
13625
13626pub trait CollaborationHub {
13627    fn collaborators<'a>(&self, cx: &'a AppContext) -> &'a HashMap<PeerId, Collaborator>;
13628    fn user_participant_indices<'a>(
13629        &self,
13630        cx: &'a AppContext,
13631    ) -> &'a HashMap<u64, ParticipantIndex>;
13632    fn user_names(&self, cx: &AppContext) -> HashMap<u64, SharedString>;
13633}
13634
13635impl CollaborationHub for Model<Project> {
13636    fn collaborators<'a>(&self, cx: &'a AppContext) -> &'a HashMap<PeerId, Collaborator> {
13637        self.read(cx).collaborators()
13638    }
13639
13640    fn user_participant_indices<'a>(
13641        &self,
13642        cx: &'a AppContext,
13643    ) -> &'a HashMap<u64, ParticipantIndex> {
13644        self.read(cx).user_store().read(cx).participant_indices()
13645    }
13646
13647    fn user_names(&self, cx: &AppContext) -> HashMap<u64, SharedString> {
13648        let this = self.read(cx);
13649        let user_ids = this.collaborators().values().map(|c| c.user_id);
13650        this.user_store().read_with(cx, |user_store, cx| {
13651            user_store.participant_names(user_ids, cx)
13652        })
13653    }
13654}
13655
13656pub trait SemanticsProvider {
13657    fn hover(
13658        &self,
13659        buffer: &Model<Buffer>,
13660        position: text::Anchor,
13661        cx: &mut AppContext,
13662    ) -> Option<Task<Vec<project::Hover>>>;
13663
13664    fn inlay_hints(
13665        &self,
13666        buffer_handle: Model<Buffer>,
13667        range: Range<text::Anchor>,
13668        cx: &mut AppContext,
13669    ) -> Option<Task<anyhow::Result<Vec<InlayHint>>>>;
13670
13671    fn resolve_inlay_hint(
13672        &self,
13673        hint: InlayHint,
13674        buffer_handle: Model<Buffer>,
13675        server_id: LanguageServerId,
13676        cx: &mut AppContext,
13677    ) -> Option<Task<anyhow::Result<InlayHint>>>;
13678
13679    fn supports_inlay_hints(&self, buffer: &Model<Buffer>, cx: &AppContext) -> bool;
13680
13681    fn document_highlights(
13682        &self,
13683        buffer: &Model<Buffer>,
13684        position: text::Anchor,
13685        cx: &mut AppContext,
13686    ) -> Option<Task<Result<Vec<DocumentHighlight>>>>;
13687
13688    fn definitions(
13689        &self,
13690        buffer: &Model<Buffer>,
13691        position: text::Anchor,
13692        kind: GotoDefinitionKind,
13693        cx: &mut AppContext,
13694    ) -> Option<Task<Result<Vec<LocationLink>>>>;
13695
13696    fn range_for_rename(
13697        &self,
13698        buffer: &Model<Buffer>,
13699        position: text::Anchor,
13700        cx: &mut AppContext,
13701    ) -> Option<Task<Result<Option<Range<text::Anchor>>>>>;
13702
13703    fn perform_rename(
13704        &self,
13705        buffer: &Model<Buffer>,
13706        position: text::Anchor,
13707        new_name: String,
13708        cx: &mut AppContext,
13709    ) -> Option<Task<Result<ProjectTransaction>>>;
13710}
13711
13712pub trait CompletionProvider {
13713    fn completions(
13714        &self,
13715        buffer: &Model<Buffer>,
13716        buffer_position: text::Anchor,
13717        trigger: CompletionContext,
13718        cx: &mut ViewContext<Editor>,
13719    ) -> Task<Result<Vec<Completion>>>;
13720
13721    fn resolve_completions(
13722        &self,
13723        buffer: Model<Buffer>,
13724        completion_indices: Vec<usize>,
13725        completions: Rc<RefCell<Box<[Completion]>>>,
13726        cx: &mut ViewContext<Editor>,
13727    ) -> Task<Result<bool>>;
13728
13729    fn apply_additional_edits_for_completion(
13730        &self,
13731        _buffer: Model<Buffer>,
13732        _completions: Rc<RefCell<Box<[Completion]>>>,
13733        _completion_index: usize,
13734        _push_to_history: bool,
13735        _cx: &mut ViewContext<Editor>,
13736    ) -> Task<Result<Option<language::Transaction>>> {
13737        Task::ready(Ok(None))
13738    }
13739
13740    fn is_completion_trigger(
13741        &self,
13742        buffer: &Model<Buffer>,
13743        position: language::Anchor,
13744        text: &str,
13745        trigger_in_words: bool,
13746        cx: &mut ViewContext<Editor>,
13747    ) -> bool;
13748
13749    fn sort_completions(&self) -> bool {
13750        true
13751    }
13752}
13753
13754pub trait CodeActionProvider {
13755    fn id(&self) -> Arc<str>;
13756
13757    fn code_actions(
13758        &self,
13759        buffer: &Model<Buffer>,
13760        range: Range<text::Anchor>,
13761        cx: &mut WindowContext,
13762    ) -> Task<Result<Vec<CodeAction>>>;
13763
13764    fn apply_code_action(
13765        &self,
13766        buffer_handle: Model<Buffer>,
13767        action: CodeAction,
13768        excerpt_id: ExcerptId,
13769        push_to_history: bool,
13770        cx: &mut WindowContext,
13771    ) -> Task<Result<ProjectTransaction>>;
13772}
13773
13774impl CodeActionProvider for Model<Project> {
13775    fn id(&self) -> Arc<str> {
13776        "project".into()
13777    }
13778
13779    fn code_actions(
13780        &self,
13781        buffer: &Model<Buffer>,
13782        range: Range<text::Anchor>,
13783        cx: &mut WindowContext,
13784    ) -> Task<Result<Vec<CodeAction>>> {
13785        self.update(cx, |project, cx| {
13786            project.code_actions(buffer, range, None, cx)
13787        })
13788    }
13789
13790    fn apply_code_action(
13791        &self,
13792        buffer_handle: Model<Buffer>,
13793        action: CodeAction,
13794        _excerpt_id: ExcerptId,
13795        push_to_history: bool,
13796        cx: &mut WindowContext,
13797    ) -> Task<Result<ProjectTransaction>> {
13798        self.update(cx, |project, cx| {
13799            project.apply_code_action(buffer_handle, action, push_to_history, cx)
13800        })
13801    }
13802}
13803
13804fn snippet_completions(
13805    project: &Project,
13806    buffer: &Model<Buffer>,
13807    buffer_position: text::Anchor,
13808    cx: &mut AppContext,
13809) -> Task<Result<Vec<Completion>>> {
13810    let language = buffer.read(cx).language_at(buffer_position);
13811    let language_name = language.as_ref().map(|language| language.lsp_id());
13812    let snippet_store = project.snippets().read(cx);
13813    let snippets = snippet_store.snippets_for(language_name, cx);
13814
13815    if snippets.is_empty() {
13816        return Task::ready(Ok(vec![]));
13817    }
13818    let snapshot = buffer.read(cx).text_snapshot();
13819    let chars: String = snapshot
13820        .reversed_chars_for_range(text::Anchor::MIN..buffer_position)
13821        .collect();
13822
13823    let scope = language.map(|language| language.default_scope());
13824    let executor = cx.background_executor().clone();
13825
13826    cx.background_executor().spawn(async move {
13827        let classifier = CharClassifier::new(scope).for_completion(true);
13828        let mut last_word = chars
13829            .chars()
13830            .take_while(|c| classifier.is_word(*c))
13831            .collect::<String>();
13832        last_word = last_word.chars().rev().collect();
13833
13834        if last_word.is_empty() {
13835            return Ok(vec![]);
13836        }
13837
13838        let as_offset = text::ToOffset::to_offset(&buffer_position, &snapshot);
13839        let to_lsp = |point: &text::Anchor| {
13840            let end = text::ToPointUtf16::to_point_utf16(point, &snapshot);
13841            point_to_lsp(end)
13842        };
13843        let lsp_end = to_lsp(&buffer_position);
13844
13845        let candidates = snippets
13846            .iter()
13847            .enumerate()
13848            .flat_map(|(ix, snippet)| {
13849                snippet
13850                    .prefix
13851                    .iter()
13852                    .map(move |prefix| StringMatchCandidate::new(ix, &prefix))
13853            })
13854            .collect::<Vec<StringMatchCandidate>>();
13855
13856        let mut matches = fuzzy::match_strings(
13857            &candidates,
13858            &last_word,
13859            last_word.chars().any(|c| c.is_uppercase()),
13860            100,
13861            &Default::default(),
13862            executor,
13863        )
13864        .await;
13865
13866        // Remove all candidates where the query's start does not match the start of any word in the candidate
13867        if let Some(query_start) = last_word.chars().next() {
13868            matches.retain(|string_match| {
13869                split_words(&string_match.string).any(|word| {
13870                    // Check that the first codepoint of the word as lowercase matches the first
13871                    // codepoint of the query as lowercase
13872                    word.chars()
13873                        .flat_map(|codepoint| codepoint.to_lowercase())
13874                        .zip(query_start.to_lowercase())
13875                        .all(|(word_cp, query_cp)| word_cp == query_cp)
13876                })
13877            });
13878        }
13879
13880        let matched_strings = matches
13881            .into_iter()
13882            .map(|m| m.string)
13883            .collect::<HashSet<_>>();
13884
13885        let result: Vec<Completion> = snippets
13886            .into_iter()
13887            .filter_map(|snippet| {
13888                let matching_prefix = snippet
13889                    .prefix
13890                    .iter()
13891                    .find(|prefix| matched_strings.contains(*prefix))?;
13892                let start = as_offset - last_word.len();
13893                let start = snapshot.anchor_before(start);
13894                let range = start..buffer_position;
13895                let lsp_start = to_lsp(&start);
13896                let lsp_range = lsp::Range {
13897                    start: lsp_start,
13898                    end: lsp_end,
13899                };
13900                Some(Completion {
13901                    old_range: range,
13902                    new_text: snippet.body.clone(),
13903                    resolved: false,
13904                    label: CodeLabel {
13905                        text: matching_prefix.clone(),
13906                        runs: vec![],
13907                        filter_range: 0..matching_prefix.len(),
13908                    },
13909                    server_id: LanguageServerId(usize::MAX),
13910                    documentation: snippet.description.clone().map(Documentation::SingleLine),
13911                    lsp_completion: lsp::CompletionItem {
13912                        label: snippet.prefix.first().unwrap().clone(),
13913                        kind: Some(CompletionItemKind::SNIPPET),
13914                        label_details: snippet.description.as_ref().map(|description| {
13915                            lsp::CompletionItemLabelDetails {
13916                                detail: Some(description.clone()),
13917                                description: None,
13918                            }
13919                        }),
13920                        insert_text_format: Some(InsertTextFormat::SNIPPET),
13921                        text_edit: Some(lsp::CompletionTextEdit::InsertAndReplace(
13922                            lsp::InsertReplaceEdit {
13923                                new_text: snippet.body.clone(),
13924                                insert: lsp_range,
13925                                replace: lsp_range,
13926                            },
13927                        )),
13928                        filter_text: Some(snippet.body.clone()),
13929                        sort_text: Some(char::MAX.to_string()),
13930                        ..Default::default()
13931                    },
13932                    confirm: None,
13933                })
13934            })
13935            .collect();
13936
13937        Ok(result)
13938    })
13939}
13940
13941impl CompletionProvider for Model<Project> {
13942    fn completions(
13943        &self,
13944        buffer: &Model<Buffer>,
13945        buffer_position: text::Anchor,
13946        options: CompletionContext,
13947        cx: &mut ViewContext<Editor>,
13948    ) -> Task<Result<Vec<Completion>>> {
13949        self.update(cx, |project, cx| {
13950            let snippets = snippet_completions(project, buffer, buffer_position, cx);
13951            let project_completions = project.completions(buffer, buffer_position, options, cx);
13952            cx.background_executor().spawn(async move {
13953                let mut completions = project_completions.await?;
13954                let snippets_completions = snippets.await?;
13955                completions.extend(snippets_completions);
13956                Ok(completions)
13957            })
13958        })
13959    }
13960
13961    fn resolve_completions(
13962        &self,
13963        buffer: Model<Buffer>,
13964        completion_indices: Vec<usize>,
13965        completions: Rc<RefCell<Box<[Completion]>>>,
13966        cx: &mut ViewContext<Editor>,
13967    ) -> Task<Result<bool>> {
13968        self.update(cx, |project, cx| {
13969            project.lsp_store().update(cx, |lsp_store, cx| {
13970                lsp_store.resolve_completions(buffer, completion_indices, completions, cx)
13971            })
13972        })
13973    }
13974
13975    fn apply_additional_edits_for_completion(
13976        &self,
13977        buffer: Model<Buffer>,
13978        completions: Rc<RefCell<Box<[Completion]>>>,
13979        completion_index: usize,
13980        push_to_history: bool,
13981        cx: &mut ViewContext<Editor>,
13982    ) -> Task<Result<Option<language::Transaction>>> {
13983        self.update(cx, |project, cx| {
13984            project.lsp_store().update(cx, |lsp_store, cx| {
13985                lsp_store.apply_additional_edits_for_completion(
13986                    buffer,
13987                    completions,
13988                    completion_index,
13989                    push_to_history,
13990                    cx,
13991                )
13992            })
13993        })
13994    }
13995
13996    fn is_completion_trigger(
13997        &self,
13998        buffer: &Model<Buffer>,
13999        position: language::Anchor,
14000        text: &str,
14001        trigger_in_words: bool,
14002        cx: &mut ViewContext<Editor>,
14003    ) -> bool {
14004        let mut chars = text.chars();
14005        let char = if let Some(char) = chars.next() {
14006            char
14007        } else {
14008            return false;
14009        };
14010        if chars.next().is_some() {
14011            return false;
14012        }
14013
14014        let buffer = buffer.read(cx);
14015        let snapshot = buffer.snapshot();
14016        if !snapshot.settings_at(position, cx).show_completions_on_input {
14017            return false;
14018        }
14019        let classifier = snapshot.char_classifier_at(position).for_completion(true);
14020        if trigger_in_words && classifier.is_word(char) {
14021            return true;
14022        }
14023
14024        buffer.completion_triggers().contains(text)
14025    }
14026}
14027
14028impl SemanticsProvider for Model<Project> {
14029    fn hover(
14030        &self,
14031        buffer: &Model<Buffer>,
14032        position: text::Anchor,
14033        cx: &mut AppContext,
14034    ) -> Option<Task<Vec<project::Hover>>> {
14035        Some(self.update(cx, |project, cx| project.hover(buffer, position, cx)))
14036    }
14037
14038    fn document_highlights(
14039        &self,
14040        buffer: &Model<Buffer>,
14041        position: text::Anchor,
14042        cx: &mut AppContext,
14043    ) -> Option<Task<Result<Vec<DocumentHighlight>>>> {
14044        Some(self.update(cx, |project, cx| {
14045            project.document_highlights(buffer, position, cx)
14046        }))
14047    }
14048
14049    fn definitions(
14050        &self,
14051        buffer: &Model<Buffer>,
14052        position: text::Anchor,
14053        kind: GotoDefinitionKind,
14054        cx: &mut AppContext,
14055    ) -> Option<Task<Result<Vec<LocationLink>>>> {
14056        Some(self.update(cx, |project, cx| match kind {
14057            GotoDefinitionKind::Symbol => project.definition(&buffer, position, cx),
14058            GotoDefinitionKind::Declaration => project.declaration(&buffer, position, cx),
14059            GotoDefinitionKind::Type => project.type_definition(&buffer, position, cx),
14060            GotoDefinitionKind::Implementation => project.implementation(&buffer, position, cx),
14061        }))
14062    }
14063
14064    fn supports_inlay_hints(&self, buffer: &Model<Buffer>, cx: &AppContext) -> bool {
14065        // TODO: make this work for remote projects
14066        self.read(cx)
14067            .language_servers_for_local_buffer(buffer.read(cx), cx)
14068            .any(
14069                |(_, server)| match server.capabilities().inlay_hint_provider {
14070                    Some(lsp::OneOf::Left(enabled)) => enabled,
14071                    Some(lsp::OneOf::Right(_)) => true,
14072                    None => false,
14073                },
14074            )
14075    }
14076
14077    fn inlay_hints(
14078        &self,
14079        buffer_handle: Model<Buffer>,
14080        range: Range<text::Anchor>,
14081        cx: &mut AppContext,
14082    ) -> Option<Task<anyhow::Result<Vec<InlayHint>>>> {
14083        Some(self.update(cx, |project, cx| {
14084            project.inlay_hints(buffer_handle, range, cx)
14085        }))
14086    }
14087
14088    fn resolve_inlay_hint(
14089        &self,
14090        hint: InlayHint,
14091        buffer_handle: Model<Buffer>,
14092        server_id: LanguageServerId,
14093        cx: &mut AppContext,
14094    ) -> Option<Task<anyhow::Result<InlayHint>>> {
14095        Some(self.update(cx, |project, cx| {
14096            project.resolve_inlay_hint(hint, buffer_handle, server_id, cx)
14097        }))
14098    }
14099
14100    fn range_for_rename(
14101        &self,
14102        buffer: &Model<Buffer>,
14103        position: text::Anchor,
14104        cx: &mut AppContext,
14105    ) -> Option<Task<Result<Option<Range<text::Anchor>>>>> {
14106        Some(self.update(cx, |project, cx| {
14107            let buffer = buffer.clone();
14108            let task = project.prepare_rename(buffer.clone(), position, cx);
14109            cx.spawn(|_, mut cx| async move {
14110                Ok(match task.await? {
14111                    PrepareRenameResponse::Success(range) => Some(range),
14112                    PrepareRenameResponse::InvalidPosition => None,
14113                    PrepareRenameResponse::OnlyUnpreparedRenameSupported => {
14114                        // Fallback on using TreeSitter info to determine identifier range
14115                        buffer.update(&mut cx, |buffer, _| {
14116                            let snapshot = buffer.snapshot();
14117                            let (range, kind) = snapshot.surrounding_word(position);
14118                            if kind != Some(CharKind::Word) {
14119                                return None;
14120                            }
14121                            Some(
14122                                snapshot.anchor_before(range.start)
14123                                    ..snapshot.anchor_after(range.end),
14124                            )
14125                        })?
14126                    }
14127                })
14128            })
14129        }))
14130    }
14131
14132    fn perform_rename(
14133        &self,
14134        buffer: &Model<Buffer>,
14135        position: text::Anchor,
14136        new_name: String,
14137        cx: &mut AppContext,
14138    ) -> Option<Task<Result<ProjectTransaction>>> {
14139        Some(self.update(cx, |project, cx| {
14140            project.perform_rename(buffer.clone(), position, new_name, cx)
14141        }))
14142    }
14143}
14144
14145fn inlay_hint_settings(
14146    location: Anchor,
14147    snapshot: &MultiBufferSnapshot,
14148    cx: &mut ViewContext<Editor>,
14149) -> InlayHintSettings {
14150    let file = snapshot.file_at(location);
14151    let language = snapshot.language_at(location).map(|l| l.name());
14152    language_settings(language, file, cx).inlay_hints
14153}
14154
14155fn consume_contiguous_rows(
14156    contiguous_row_selections: &mut Vec<Selection<Point>>,
14157    selection: &Selection<Point>,
14158    display_map: &DisplaySnapshot,
14159    selections: &mut Peekable<std::slice::Iter<Selection<Point>>>,
14160) -> (MultiBufferRow, MultiBufferRow) {
14161    contiguous_row_selections.push(selection.clone());
14162    let start_row = MultiBufferRow(selection.start.row);
14163    let mut end_row = ending_row(selection, display_map);
14164
14165    while let Some(next_selection) = selections.peek() {
14166        if next_selection.start.row <= end_row.0 {
14167            end_row = ending_row(next_selection, display_map);
14168            contiguous_row_selections.push(selections.next().unwrap().clone());
14169        } else {
14170            break;
14171        }
14172    }
14173    (start_row, end_row)
14174}
14175
14176fn ending_row(next_selection: &Selection<Point>, display_map: &DisplaySnapshot) -> MultiBufferRow {
14177    if next_selection.end.column > 0 || next_selection.is_empty() {
14178        MultiBufferRow(display_map.next_line_boundary(next_selection.end).0.row + 1)
14179    } else {
14180        MultiBufferRow(next_selection.end.row)
14181    }
14182}
14183
14184impl EditorSnapshot {
14185    pub fn remote_selections_in_range<'a>(
14186        &'a self,
14187        range: &'a Range<Anchor>,
14188        collaboration_hub: &dyn CollaborationHub,
14189        cx: &'a AppContext,
14190    ) -> impl 'a + Iterator<Item = RemoteSelection> {
14191        let participant_names = collaboration_hub.user_names(cx);
14192        let participant_indices = collaboration_hub.user_participant_indices(cx);
14193        let collaborators_by_peer_id = collaboration_hub.collaborators(cx);
14194        let collaborators_by_replica_id = collaborators_by_peer_id
14195            .iter()
14196            .map(|(_, collaborator)| (collaborator.replica_id, collaborator))
14197            .collect::<HashMap<_, _>>();
14198        self.buffer_snapshot
14199            .selections_in_range(range, false)
14200            .filter_map(move |(replica_id, line_mode, cursor_shape, selection)| {
14201                let collaborator = collaborators_by_replica_id.get(&replica_id)?;
14202                let participant_index = participant_indices.get(&collaborator.user_id).copied();
14203                let user_name = participant_names.get(&collaborator.user_id).cloned();
14204                Some(RemoteSelection {
14205                    replica_id,
14206                    selection,
14207                    cursor_shape,
14208                    line_mode,
14209                    participant_index,
14210                    peer_id: collaborator.peer_id,
14211                    user_name,
14212                })
14213            })
14214    }
14215
14216    pub fn language_at<T: ToOffset>(&self, position: T) -> Option<&Arc<Language>> {
14217        self.display_snapshot.buffer_snapshot.language_at(position)
14218    }
14219
14220    pub fn is_focused(&self) -> bool {
14221        self.is_focused
14222    }
14223
14224    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
14225        self.placeholder_text.as_ref()
14226    }
14227
14228    pub fn scroll_position(&self) -> gpui::Point<f32> {
14229        self.scroll_anchor.scroll_position(&self.display_snapshot)
14230    }
14231
14232    fn gutter_dimensions(
14233        &self,
14234        font_id: FontId,
14235        font_size: Pixels,
14236        em_width: Pixels,
14237        em_advance: Pixels,
14238        max_line_number_width: Pixels,
14239        cx: &AppContext,
14240    ) -> GutterDimensions {
14241        if !self.show_gutter {
14242            return GutterDimensions::default();
14243        }
14244        let descent = cx.text_system().descent(font_id, font_size);
14245
14246        let show_git_gutter = self.show_git_diff_gutter.unwrap_or_else(|| {
14247            matches!(
14248                ProjectSettings::get_global(cx).git.git_gutter,
14249                Some(GitGutterSetting::TrackedFiles)
14250            )
14251        });
14252        let gutter_settings = EditorSettings::get_global(cx).gutter;
14253        let show_line_numbers = self
14254            .show_line_numbers
14255            .unwrap_or(gutter_settings.line_numbers);
14256        let line_gutter_width = if show_line_numbers {
14257            // Avoid flicker-like gutter resizes when the line number gains another digit and only resize the gutter on files with N*10^5 lines.
14258            let min_width_for_number_on_gutter = em_advance * 4.0;
14259            max_line_number_width.max(min_width_for_number_on_gutter)
14260        } else {
14261            0.0.into()
14262        };
14263
14264        let show_code_actions = self
14265            .show_code_actions
14266            .unwrap_or(gutter_settings.code_actions);
14267
14268        let show_runnables = self.show_runnables.unwrap_or(gutter_settings.runnables);
14269
14270        let git_blame_entries_width =
14271            self.git_blame_gutter_max_author_length
14272                .map(|max_author_length| {
14273                    // Length of the author name, but also space for the commit hash,
14274                    // the spacing and the timestamp.
14275                    let max_char_count = max_author_length
14276                        .min(GIT_BLAME_MAX_AUTHOR_CHARS_DISPLAYED)
14277                        + 7 // length of commit sha
14278                        + 14 // length of max relative timestamp ("60 minutes ago")
14279                        + 4; // gaps and margins
14280
14281                    em_advance * max_char_count
14282                });
14283
14284        let mut left_padding = git_blame_entries_width.unwrap_or(Pixels::ZERO);
14285        left_padding += if show_code_actions || show_runnables {
14286            em_width * 3.0
14287        } else if show_git_gutter && show_line_numbers {
14288            em_width * 2.0
14289        } else if show_git_gutter || show_line_numbers {
14290            em_width
14291        } else {
14292            px(0.)
14293        };
14294
14295        let right_padding = if gutter_settings.folds && show_line_numbers {
14296            em_width * 4.0
14297        } else if gutter_settings.folds {
14298            em_width * 3.0
14299        } else if show_line_numbers {
14300            em_width
14301        } else {
14302            px(0.)
14303        };
14304
14305        GutterDimensions {
14306            left_padding,
14307            right_padding,
14308            width: line_gutter_width + left_padding + right_padding,
14309            margin: -descent,
14310            git_blame_entries_width,
14311        }
14312    }
14313
14314    pub fn render_crease_toggle(
14315        &self,
14316        buffer_row: MultiBufferRow,
14317        row_contains_cursor: bool,
14318        editor: View<Editor>,
14319        cx: &mut WindowContext,
14320    ) -> Option<AnyElement> {
14321        let folded = self.is_line_folded(buffer_row);
14322        let mut is_foldable = false;
14323
14324        if let Some(crease) = self
14325            .crease_snapshot
14326            .query_row(buffer_row, &self.buffer_snapshot)
14327        {
14328            is_foldable = true;
14329            match crease {
14330                Crease::Inline { render_toggle, .. } | Crease::Block { render_toggle, .. } => {
14331                    if let Some(render_toggle) = render_toggle {
14332                        let toggle_callback = Arc::new(move |folded, cx: &mut WindowContext| {
14333                            if folded {
14334                                editor.update(cx, |editor, cx| {
14335                                    editor.fold_at(&crate::FoldAt { buffer_row }, cx)
14336                                });
14337                            } else {
14338                                editor.update(cx, |editor, cx| {
14339                                    editor.unfold_at(&crate::UnfoldAt { buffer_row }, cx)
14340                                });
14341                            }
14342                        });
14343                        return Some((render_toggle)(buffer_row, folded, toggle_callback, cx));
14344                    }
14345                }
14346            }
14347        }
14348
14349        is_foldable |= self.starts_indent(buffer_row);
14350
14351        if folded || (is_foldable && (row_contains_cursor || self.gutter_hovered)) {
14352            Some(
14353                Disclosure::new(("gutter_crease", buffer_row.0), !folded)
14354                    .toggle_state(folded)
14355                    .on_click(cx.listener_for(&editor, move |this, _e, cx| {
14356                        if folded {
14357                            this.unfold_at(&UnfoldAt { buffer_row }, cx);
14358                        } else {
14359                            this.fold_at(&FoldAt { buffer_row }, cx);
14360                        }
14361                    }))
14362                    .into_any_element(),
14363            )
14364        } else {
14365            None
14366        }
14367    }
14368
14369    pub fn render_crease_trailer(
14370        &self,
14371        buffer_row: MultiBufferRow,
14372        cx: &mut WindowContext,
14373    ) -> Option<AnyElement> {
14374        let folded = self.is_line_folded(buffer_row);
14375        if let Crease::Inline { render_trailer, .. } = self
14376            .crease_snapshot
14377            .query_row(buffer_row, &self.buffer_snapshot)?
14378        {
14379            let render_trailer = render_trailer.as_ref()?;
14380            Some(render_trailer(buffer_row, folded, cx))
14381        } else {
14382            None
14383        }
14384    }
14385}
14386
14387impl Deref for EditorSnapshot {
14388    type Target = DisplaySnapshot;
14389
14390    fn deref(&self) -> &Self::Target {
14391        &self.display_snapshot
14392    }
14393}
14394
14395#[derive(Clone, Debug, PartialEq, Eq)]
14396pub enum EditorEvent {
14397    InputIgnored {
14398        text: Arc<str>,
14399    },
14400    InputHandled {
14401        utf16_range_to_replace: Option<Range<isize>>,
14402        text: Arc<str>,
14403    },
14404    ExcerptsAdded {
14405        buffer: Model<Buffer>,
14406        predecessor: ExcerptId,
14407        excerpts: Vec<(ExcerptId, ExcerptRange<language::Anchor>)>,
14408    },
14409    ExcerptsRemoved {
14410        ids: Vec<ExcerptId>,
14411    },
14412    BufferFoldToggled {
14413        ids: Vec<ExcerptId>,
14414        folded: bool,
14415    },
14416    ExcerptsEdited {
14417        ids: Vec<ExcerptId>,
14418    },
14419    ExcerptsExpanded {
14420        ids: Vec<ExcerptId>,
14421    },
14422    BufferEdited,
14423    Edited {
14424        transaction_id: clock::Lamport,
14425    },
14426    Reparsed(BufferId),
14427    Focused,
14428    FocusedIn,
14429    Blurred,
14430    DirtyChanged,
14431    Saved,
14432    TitleChanged,
14433    DiffBaseChanged,
14434    SelectionsChanged {
14435        local: bool,
14436    },
14437    ScrollPositionChanged {
14438        local: bool,
14439        autoscroll: bool,
14440    },
14441    Closed,
14442    TransactionUndone {
14443        transaction_id: clock::Lamport,
14444    },
14445    TransactionBegun {
14446        transaction_id: clock::Lamport,
14447    },
14448    Reloaded,
14449    CursorShapeChanged,
14450}
14451
14452impl EventEmitter<EditorEvent> for Editor {}
14453
14454impl FocusableView for Editor {
14455    fn focus_handle(&self, _cx: &AppContext) -> FocusHandle {
14456        self.focus_handle.clone()
14457    }
14458}
14459
14460impl Render for Editor {
14461    fn render<'a>(&mut self, cx: &mut ViewContext<'a, Self>) -> impl IntoElement {
14462        let settings = ThemeSettings::get_global(cx);
14463
14464        let mut text_style = match self.mode {
14465            EditorMode::SingleLine { .. } | EditorMode::AutoHeight { .. } => TextStyle {
14466                color: cx.theme().colors().editor_foreground,
14467                font_family: settings.ui_font.family.clone(),
14468                font_features: settings.ui_font.features.clone(),
14469                font_fallbacks: settings.ui_font.fallbacks.clone(),
14470                font_size: rems(0.875).into(),
14471                font_weight: settings.ui_font.weight,
14472                line_height: relative(settings.buffer_line_height.value()),
14473                ..Default::default()
14474            },
14475            EditorMode::Full => TextStyle {
14476                color: cx.theme().colors().editor_foreground,
14477                font_family: settings.buffer_font.family.clone(),
14478                font_features: settings.buffer_font.features.clone(),
14479                font_fallbacks: settings.buffer_font.fallbacks.clone(),
14480                font_size: settings.buffer_font_size().into(),
14481                font_weight: settings.buffer_font.weight,
14482                line_height: relative(settings.buffer_line_height.value()),
14483                ..Default::default()
14484            },
14485        };
14486        if let Some(text_style_refinement) = &self.text_style_refinement {
14487            text_style.refine(text_style_refinement)
14488        }
14489
14490        let background = match self.mode {
14491            EditorMode::SingleLine { .. } => cx.theme().system().transparent,
14492            EditorMode::AutoHeight { max_lines: _ } => cx.theme().system().transparent,
14493            EditorMode::Full => cx.theme().colors().editor_background,
14494        };
14495
14496        EditorElement::new(
14497            cx.view(),
14498            EditorStyle {
14499                background,
14500                local_player: cx.theme().players().local(),
14501                text: text_style,
14502                scrollbar_width: EditorElement::SCROLLBAR_WIDTH,
14503                syntax: cx.theme().syntax().clone(),
14504                status: cx.theme().status().clone(),
14505                inlay_hints_style: make_inlay_hints_style(cx),
14506                inline_completion_styles: make_suggestion_styles(cx),
14507                unnecessary_code_fade: ThemeSettings::get_global(cx).unnecessary_code_fade,
14508            },
14509        )
14510    }
14511}
14512
14513impl ViewInputHandler for Editor {
14514    fn text_for_range(
14515        &mut self,
14516        range_utf16: Range<usize>,
14517        adjusted_range: &mut Option<Range<usize>>,
14518        cx: &mut ViewContext<Self>,
14519    ) -> Option<String> {
14520        let snapshot = self.buffer.read(cx).read(cx);
14521        let start = snapshot.clip_offset_utf16(OffsetUtf16(range_utf16.start), Bias::Left);
14522        let end = snapshot.clip_offset_utf16(OffsetUtf16(range_utf16.end), Bias::Right);
14523        if (start.0..end.0) != range_utf16 {
14524            adjusted_range.replace(start.0..end.0);
14525        }
14526        Some(snapshot.text_for_range(start..end).collect())
14527    }
14528
14529    fn selected_text_range(
14530        &mut self,
14531        ignore_disabled_input: bool,
14532        cx: &mut ViewContext<Self>,
14533    ) -> Option<UTF16Selection> {
14534        // Prevent the IME menu from appearing when holding down an alphabetic key
14535        // while input is disabled.
14536        if !ignore_disabled_input && !self.input_enabled {
14537            return None;
14538        }
14539
14540        let selection = self.selections.newest::<OffsetUtf16>(cx);
14541        let range = selection.range();
14542
14543        Some(UTF16Selection {
14544            range: range.start.0..range.end.0,
14545            reversed: selection.reversed,
14546        })
14547    }
14548
14549    fn marked_text_range(&self, cx: &mut ViewContext<Self>) -> Option<Range<usize>> {
14550        let snapshot = self.buffer.read(cx).read(cx);
14551        let range = self.text_highlights::<InputComposition>(cx)?.1.first()?;
14552        Some(range.start.to_offset_utf16(&snapshot).0..range.end.to_offset_utf16(&snapshot).0)
14553    }
14554
14555    fn unmark_text(&mut self, cx: &mut ViewContext<Self>) {
14556        self.clear_highlights::<InputComposition>(cx);
14557        self.ime_transaction.take();
14558    }
14559
14560    fn replace_text_in_range(
14561        &mut self,
14562        range_utf16: Option<Range<usize>>,
14563        text: &str,
14564        cx: &mut ViewContext<Self>,
14565    ) {
14566        if !self.input_enabled {
14567            cx.emit(EditorEvent::InputIgnored { text: text.into() });
14568            return;
14569        }
14570
14571        self.transact(cx, |this, cx| {
14572            let new_selected_ranges = if let Some(range_utf16) = range_utf16 {
14573                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
14574                Some(this.selection_replacement_ranges(range_utf16, cx))
14575            } else {
14576                this.marked_text_ranges(cx)
14577            };
14578
14579            let range_to_replace = new_selected_ranges.as_ref().and_then(|ranges_to_replace| {
14580                let newest_selection_id = this.selections.newest_anchor().id;
14581                this.selections
14582                    .all::<OffsetUtf16>(cx)
14583                    .iter()
14584                    .zip(ranges_to_replace.iter())
14585                    .find_map(|(selection, range)| {
14586                        if selection.id == newest_selection_id {
14587                            Some(
14588                                (range.start.0 as isize - selection.head().0 as isize)
14589                                    ..(range.end.0 as isize - selection.head().0 as isize),
14590                            )
14591                        } else {
14592                            None
14593                        }
14594                    })
14595            });
14596
14597            cx.emit(EditorEvent::InputHandled {
14598                utf16_range_to_replace: range_to_replace,
14599                text: text.into(),
14600            });
14601
14602            if let Some(new_selected_ranges) = new_selected_ranges {
14603                this.change_selections(None, cx, |selections| {
14604                    selections.select_ranges(new_selected_ranges)
14605                });
14606                this.backspace(&Default::default(), cx);
14607            }
14608
14609            this.handle_input(text, cx);
14610        });
14611
14612        if let Some(transaction) = self.ime_transaction {
14613            self.buffer.update(cx, |buffer, cx| {
14614                buffer.group_until_transaction(transaction, cx);
14615            });
14616        }
14617
14618        self.unmark_text(cx);
14619    }
14620
14621    fn replace_and_mark_text_in_range(
14622        &mut self,
14623        range_utf16: Option<Range<usize>>,
14624        text: &str,
14625        new_selected_range_utf16: Option<Range<usize>>,
14626        cx: &mut ViewContext<Self>,
14627    ) {
14628        if !self.input_enabled {
14629            return;
14630        }
14631
14632        let transaction = self.transact(cx, |this, cx| {
14633            let ranges_to_replace = if let Some(mut marked_ranges) = this.marked_text_ranges(cx) {
14634                let snapshot = this.buffer.read(cx).read(cx);
14635                if let Some(relative_range_utf16) = range_utf16.as_ref() {
14636                    for marked_range in &mut marked_ranges {
14637                        marked_range.end.0 = marked_range.start.0 + relative_range_utf16.end;
14638                        marked_range.start.0 += relative_range_utf16.start;
14639                        marked_range.start =
14640                            snapshot.clip_offset_utf16(marked_range.start, Bias::Left);
14641                        marked_range.end =
14642                            snapshot.clip_offset_utf16(marked_range.end, Bias::Right);
14643                    }
14644                }
14645                Some(marked_ranges)
14646            } else if let Some(range_utf16) = range_utf16 {
14647                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
14648                Some(this.selection_replacement_ranges(range_utf16, cx))
14649            } else {
14650                None
14651            };
14652
14653            let range_to_replace = ranges_to_replace.as_ref().and_then(|ranges_to_replace| {
14654                let newest_selection_id = this.selections.newest_anchor().id;
14655                this.selections
14656                    .all::<OffsetUtf16>(cx)
14657                    .iter()
14658                    .zip(ranges_to_replace.iter())
14659                    .find_map(|(selection, range)| {
14660                        if selection.id == newest_selection_id {
14661                            Some(
14662                                (range.start.0 as isize - selection.head().0 as isize)
14663                                    ..(range.end.0 as isize - selection.head().0 as isize),
14664                            )
14665                        } else {
14666                            None
14667                        }
14668                    })
14669            });
14670
14671            cx.emit(EditorEvent::InputHandled {
14672                utf16_range_to_replace: range_to_replace,
14673                text: text.into(),
14674            });
14675
14676            if let Some(ranges) = ranges_to_replace {
14677                this.change_selections(None, cx, |s| s.select_ranges(ranges));
14678            }
14679
14680            let marked_ranges = {
14681                let snapshot = this.buffer.read(cx).read(cx);
14682                this.selections
14683                    .disjoint_anchors()
14684                    .iter()
14685                    .map(|selection| {
14686                        selection.start.bias_left(&snapshot)..selection.end.bias_right(&snapshot)
14687                    })
14688                    .collect::<Vec<_>>()
14689            };
14690
14691            if text.is_empty() {
14692                this.unmark_text(cx);
14693            } else {
14694                this.highlight_text::<InputComposition>(
14695                    marked_ranges.clone(),
14696                    HighlightStyle {
14697                        underline: Some(UnderlineStyle {
14698                            thickness: px(1.),
14699                            color: None,
14700                            wavy: false,
14701                        }),
14702                        ..Default::default()
14703                    },
14704                    cx,
14705                );
14706            }
14707
14708            // Disable auto-closing when composing text (i.e. typing a `"` on a Brazilian keyboard)
14709            let use_autoclose = this.use_autoclose;
14710            let use_auto_surround = this.use_auto_surround;
14711            this.set_use_autoclose(false);
14712            this.set_use_auto_surround(false);
14713            this.handle_input(text, cx);
14714            this.set_use_autoclose(use_autoclose);
14715            this.set_use_auto_surround(use_auto_surround);
14716
14717            if let Some(new_selected_range) = new_selected_range_utf16 {
14718                let snapshot = this.buffer.read(cx).read(cx);
14719                let new_selected_ranges = marked_ranges
14720                    .into_iter()
14721                    .map(|marked_range| {
14722                        let insertion_start = marked_range.start.to_offset_utf16(&snapshot).0;
14723                        let new_start = OffsetUtf16(new_selected_range.start + insertion_start);
14724                        let new_end = OffsetUtf16(new_selected_range.end + insertion_start);
14725                        snapshot.clip_offset_utf16(new_start, Bias::Left)
14726                            ..snapshot.clip_offset_utf16(new_end, Bias::Right)
14727                    })
14728                    .collect::<Vec<_>>();
14729
14730                drop(snapshot);
14731                this.change_selections(None, cx, |selections| {
14732                    selections.select_ranges(new_selected_ranges)
14733                });
14734            }
14735        });
14736
14737        self.ime_transaction = self.ime_transaction.or(transaction);
14738        if let Some(transaction) = self.ime_transaction {
14739            self.buffer.update(cx, |buffer, cx| {
14740                buffer.group_until_transaction(transaction, cx);
14741            });
14742        }
14743
14744        if self.text_highlights::<InputComposition>(cx).is_none() {
14745            self.ime_transaction.take();
14746        }
14747    }
14748
14749    fn bounds_for_range(
14750        &mut self,
14751        range_utf16: Range<usize>,
14752        element_bounds: gpui::Bounds<Pixels>,
14753        cx: &mut ViewContext<Self>,
14754    ) -> Option<gpui::Bounds<Pixels>> {
14755        let text_layout_details = self.text_layout_details(cx);
14756        let gpui::Point {
14757            x: em_width,
14758            y: line_height,
14759        } = self.character_size(cx);
14760
14761        let snapshot = self.snapshot(cx);
14762        let scroll_position = snapshot.scroll_position();
14763        let scroll_left = scroll_position.x * em_width;
14764
14765        let start = OffsetUtf16(range_utf16.start).to_display_point(&snapshot);
14766        let x = snapshot.x_for_display_point(start, &text_layout_details) - scroll_left
14767            + self.gutter_dimensions.width
14768            + self.gutter_dimensions.margin;
14769        let y = line_height * (start.row().as_f32() - scroll_position.y);
14770
14771        Some(Bounds {
14772            origin: element_bounds.origin + point(x, y),
14773            size: size(em_width, line_height),
14774        })
14775    }
14776}
14777
14778trait SelectionExt {
14779    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
14780    fn spanned_rows(
14781        &self,
14782        include_end_if_at_line_start: bool,
14783        map: &DisplaySnapshot,
14784    ) -> Range<MultiBufferRow>;
14785}
14786
14787impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
14788    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
14789        let start = self
14790            .start
14791            .to_point(&map.buffer_snapshot)
14792            .to_display_point(map);
14793        let end = self
14794            .end
14795            .to_point(&map.buffer_snapshot)
14796            .to_display_point(map);
14797        if self.reversed {
14798            end..start
14799        } else {
14800            start..end
14801        }
14802    }
14803
14804    fn spanned_rows(
14805        &self,
14806        include_end_if_at_line_start: bool,
14807        map: &DisplaySnapshot,
14808    ) -> Range<MultiBufferRow> {
14809        let start = self.start.to_point(&map.buffer_snapshot);
14810        let mut end = self.end.to_point(&map.buffer_snapshot);
14811        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
14812            end.row -= 1;
14813        }
14814
14815        let buffer_start = map.prev_line_boundary(start).0;
14816        let buffer_end = map.next_line_boundary(end).0;
14817        MultiBufferRow(buffer_start.row)..MultiBufferRow(buffer_end.row + 1)
14818    }
14819}
14820
14821impl<T: InvalidationRegion> InvalidationStack<T> {
14822    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
14823    where
14824        S: Clone + ToOffset,
14825    {
14826        while let Some(region) = self.last() {
14827            let all_selections_inside_invalidation_ranges =
14828                if selections.len() == region.ranges().len() {
14829                    selections
14830                        .iter()
14831                        .zip(region.ranges().iter().map(|r| r.to_offset(buffer)))
14832                        .all(|(selection, invalidation_range)| {
14833                            let head = selection.head().to_offset(buffer);
14834                            invalidation_range.start <= head && invalidation_range.end >= head
14835                        })
14836                } else {
14837                    false
14838                };
14839
14840            if all_selections_inside_invalidation_ranges {
14841                break;
14842            } else {
14843                self.pop();
14844            }
14845        }
14846    }
14847}
14848
14849impl<T> Default for InvalidationStack<T> {
14850    fn default() -> Self {
14851        Self(Default::default())
14852    }
14853}
14854
14855impl<T> Deref for InvalidationStack<T> {
14856    type Target = Vec<T>;
14857
14858    fn deref(&self) -> &Self::Target {
14859        &self.0
14860    }
14861}
14862
14863impl<T> DerefMut for InvalidationStack<T> {
14864    fn deref_mut(&mut self) -> &mut Self::Target {
14865        &mut self.0
14866    }
14867}
14868
14869impl InvalidationRegion for SnippetState {
14870    fn ranges(&self) -> &[Range<Anchor>] {
14871        &self.ranges[self.active_index]
14872    }
14873}
14874
14875pub fn diagnostic_block_renderer(
14876    diagnostic: Diagnostic,
14877    max_message_rows: Option<u8>,
14878    allow_closing: bool,
14879    _is_valid: bool,
14880) -> RenderBlock {
14881    let (text_without_backticks, code_ranges) =
14882        highlight_diagnostic_message(&diagnostic, max_message_rows);
14883
14884    Arc::new(move |cx: &mut BlockContext| {
14885        let group_id: SharedString = cx.block_id.to_string().into();
14886
14887        let mut text_style = cx.text_style().clone();
14888        text_style.color = diagnostic_style(diagnostic.severity, cx.theme().status());
14889        let theme_settings = ThemeSettings::get_global(cx);
14890        text_style.font_family = theme_settings.buffer_font.family.clone();
14891        text_style.font_style = theme_settings.buffer_font.style;
14892        text_style.font_features = theme_settings.buffer_font.features.clone();
14893        text_style.font_weight = theme_settings.buffer_font.weight;
14894
14895        let multi_line_diagnostic = diagnostic.message.contains('\n');
14896
14897        let buttons = |diagnostic: &Diagnostic| {
14898            if multi_line_diagnostic {
14899                v_flex()
14900            } else {
14901                h_flex()
14902            }
14903            .when(allow_closing, |div| {
14904                div.children(diagnostic.is_primary.then(|| {
14905                    IconButton::new("close-block", IconName::XCircle)
14906                        .icon_color(Color::Muted)
14907                        .size(ButtonSize::Compact)
14908                        .style(ButtonStyle::Transparent)
14909                        .visible_on_hover(group_id.clone())
14910                        .on_click(move |_click, cx| cx.dispatch_action(Box::new(Cancel)))
14911                        .tooltip(|cx| Tooltip::for_action("Close Diagnostics", &Cancel, cx))
14912                }))
14913            })
14914            .child(
14915                IconButton::new("copy-block", IconName::Copy)
14916                    .icon_color(Color::Muted)
14917                    .size(ButtonSize::Compact)
14918                    .style(ButtonStyle::Transparent)
14919                    .visible_on_hover(group_id.clone())
14920                    .on_click({
14921                        let message = diagnostic.message.clone();
14922                        move |_click, cx| {
14923                            cx.write_to_clipboard(ClipboardItem::new_string(message.clone()))
14924                        }
14925                    })
14926                    .tooltip(|cx| Tooltip::text("Copy diagnostic message", cx)),
14927            )
14928        };
14929
14930        let icon_size = buttons(&diagnostic)
14931            .into_any_element()
14932            .layout_as_root(AvailableSpace::min_size(), cx);
14933
14934        h_flex()
14935            .id(cx.block_id)
14936            .group(group_id.clone())
14937            .relative()
14938            .size_full()
14939            .block_mouse_down()
14940            .pl(cx.gutter_dimensions.width)
14941            .w(cx.max_width - cx.gutter_dimensions.full_width())
14942            .child(
14943                div()
14944                    .flex()
14945                    .w(cx.anchor_x - cx.gutter_dimensions.width - icon_size.width)
14946                    .flex_shrink(),
14947            )
14948            .child(buttons(&diagnostic))
14949            .child(div().flex().flex_shrink_0().child(
14950                StyledText::new(text_without_backticks.clone()).with_highlights(
14951                    &text_style,
14952                    code_ranges.iter().map(|range| {
14953                        (
14954                            range.clone(),
14955                            HighlightStyle {
14956                                font_weight: Some(FontWeight::BOLD),
14957                                ..Default::default()
14958                            },
14959                        )
14960                    }),
14961                ),
14962            ))
14963            .into_any_element()
14964    })
14965}
14966
14967fn inline_completion_edit_text(
14968    current_snapshot: &BufferSnapshot,
14969    edits: &[(Range<Anchor>, String)],
14970    edit_preview: &EditPreview,
14971    include_deletions: bool,
14972    cx: &WindowContext,
14973) -> Option<HighlightedEdits> {
14974    let edits = edits
14975        .iter()
14976        .map(|(anchor, text)| {
14977            (
14978                anchor.start.text_anchor..anchor.end.text_anchor,
14979                text.clone(),
14980            )
14981        })
14982        .collect::<Vec<_>>();
14983
14984    Some(edit_preview.highlight_edits(current_snapshot, &edits, include_deletions, cx))
14985}
14986
14987pub fn highlight_diagnostic_message(
14988    diagnostic: &Diagnostic,
14989    mut max_message_rows: Option<u8>,
14990) -> (SharedString, Vec<Range<usize>>) {
14991    let mut text_without_backticks = String::new();
14992    let mut code_ranges = Vec::new();
14993
14994    if let Some(source) = &diagnostic.source {
14995        text_without_backticks.push_str(source);
14996        code_ranges.push(0..source.len());
14997        text_without_backticks.push_str(": ");
14998    }
14999
15000    let mut prev_offset = 0;
15001    let mut in_code_block = false;
15002    let has_row_limit = max_message_rows.is_some();
15003    let mut newline_indices = diagnostic
15004        .message
15005        .match_indices('\n')
15006        .filter(|_| has_row_limit)
15007        .map(|(ix, _)| ix)
15008        .fuse()
15009        .peekable();
15010
15011    for (quote_ix, _) in diagnostic
15012        .message
15013        .match_indices('`')
15014        .chain([(diagnostic.message.len(), "")])
15015    {
15016        let mut first_newline_ix = None;
15017        let mut last_newline_ix = None;
15018        while let Some(newline_ix) = newline_indices.peek() {
15019            if *newline_ix < quote_ix {
15020                if first_newline_ix.is_none() {
15021                    first_newline_ix = Some(*newline_ix);
15022                }
15023                last_newline_ix = Some(*newline_ix);
15024
15025                if let Some(rows_left) = &mut max_message_rows {
15026                    if *rows_left == 0 {
15027                        break;
15028                    } else {
15029                        *rows_left -= 1;
15030                    }
15031                }
15032                let _ = newline_indices.next();
15033            } else {
15034                break;
15035            }
15036        }
15037        let prev_len = text_without_backticks.len();
15038        let new_text = &diagnostic.message[prev_offset..first_newline_ix.unwrap_or(quote_ix)];
15039        text_without_backticks.push_str(new_text);
15040        if in_code_block {
15041            code_ranges.push(prev_len..text_without_backticks.len());
15042        }
15043        prev_offset = last_newline_ix.unwrap_or(quote_ix) + 1;
15044        in_code_block = !in_code_block;
15045        if first_newline_ix.map_or(false, |newline_ix| newline_ix < quote_ix) {
15046            text_without_backticks.push_str("...");
15047            break;
15048        }
15049    }
15050
15051    (text_without_backticks.into(), code_ranges)
15052}
15053
15054fn diagnostic_style(severity: DiagnosticSeverity, colors: &StatusColors) -> Hsla {
15055    match severity {
15056        DiagnosticSeverity::ERROR => colors.error,
15057        DiagnosticSeverity::WARNING => colors.warning,
15058        DiagnosticSeverity::INFORMATION => colors.info,
15059        DiagnosticSeverity::HINT => colors.info,
15060        _ => colors.ignored,
15061    }
15062}
15063
15064pub fn styled_runs_for_code_label<'a>(
15065    label: &'a CodeLabel,
15066    syntax_theme: &'a theme::SyntaxTheme,
15067) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
15068    let fade_out = HighlightStyle {
15069        fade_out: Some(0.35),
15070        ..Default::default()
15071    };
15072
15073    let mut prev_end = label.filter_range.end;
15074    label
15075        .runs
15076        .iter()
15077        .enumerate()
15078        .flat_map(move |(ix, (range, highlight_id))| {
15079            let style = if let Some(style) = highlight_id.style(syntax_theme) {
15080                style
15081            } else {
15082                return Default::default();
15083            };
15084            let mut muted_style = style;
15085            muted_style.highlight(fade_out);
15086
15087            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
15088            if range.start >= label.filter_range.end {
15089                if range.start > prev_end {
15090                    runs.push((prev_end..range.start, fade_out));
15091                }
15092                runs.push((range.clone(), muted_style));
15093            } else if range.end <= label.filter_range.end {
15094                runs.push((range.clone(), style));
15095            } else {
15096                runs.push((range.start..label.filter_range.end, style));
15097                runs.push((label.filter_range.end..range.end, muted_style));
15098            }
15099            prev_end = cmp::max(prev_end, range.end);
15100
15101            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
15102                runs.push((prev_end..label.text.len(), fade_out));
15103            }
15104
15105            runs
15106        })
15107}
15108
15109pub(crate) fn split_words(text: &str) -> impl std::iter::Iterator<Item = &str> + '_ {
15110    let mut prev_index = 0;
15111    let mut prev_codepoint: Option<char> = None;
15112    text.char_indices()
15113        .chain([(text.len(), '\0')])
15114        .filter_map(move |(index, codepoint)| {
15115            let prev_codepoint = prev_codepoint.replace(codepoint)?;
15116            let is_boundary = index == text.len()
15117                || !prev_codepoint.is_uppercase() && codepoint.is_uppercase()
15118                || !prev_codepoint.is_alphanumeric() && codepoint.is_alphanumeric();
15119            if is_boundary {
15120                let chunk = &text[prev_index..index];
15121                prev_index = index;
15122                Some(chunk)
15123            } else {
15124                None
15125            }
15126        })
15127}
15128
15129pub trait RangeToAnchorExt: Sized {
15130    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor>;
15131
15132    fn to_display_points(self, snapshot: &EditorSnapshot) -> Range<DisplayPoint> {
15133        let anchor_range = self.to_anchors(&snapshot.buffer_snapshot);
15134        anchor_range.start.to_display_point(snapshot)..anchor_range.end.to_display_point(snapshot)
15135    }
15136}
15137
15138impl<T: ToOffset> RangeToAnchorExt for Range<T> {
15139    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor> {
15140        let start_offset = self.start.to_offset(snapshot);
15141        let end_offset = self.end.to_offset(snapshot);
15142        if start_offset == end_offset {
15143            snapshot.anchor_before(start_offset)..snapshot.anchor_before(end_offset)
15144        } else {
15145            snapshot.anchor_after(self.start)..snapshot.anchor_before(self.end)
15146        }
15147    }
15148}
15149
15150pub trait RowExt {
15151    fn as_f32(&self) -> f32;
15152
15153    fn next_row(&self) -> Self;
15154
15155    fn previous_row(&self) -> Self;
15156
15157    fn minus(&self, other: Self) -> u32;
15158}
15159
15160impl RowExt for DisplayRow {
15161    fn as_f32(&self) -> f32 {
15162        self.0 as f32
15163    }
15164
15165    fn next_row(&self) -> Self {
15166        Self(self.0 + 1)
15167    }
15168
15169    fn previous_row(&self) -> Self {
15170        Self(self.0.saturating_sub(1))
15171    }
15172
15173    fn minus(&self, other: Self) -> u32 {
15174        self.0 - other.0
15175    }
15176}
15177
15178impl RowExt for MultiBufferRow {
15179    fn as_f32(&self) -> f32 {
15180        self.0 as f32
15181    }
15182
15183    fn next_row(&self) -> Self {
15184        Self(self.0 + 1)
15185    }
15186
15187    fn previous_row(&self) -> Self {
15188        Self(self.0.saturating_sub(1))
15189    }
15190
15191    fn minus(&self, other: Self) -> u32 {
15192        self.0 - other.0
15193    }
15194}
15195
15196trait RowRangeExt {
15197    type Row;
15198
15199    fn len(&self) -> usize;
15200
15201    fn iter_rows(&self) -> impl DoubleEndedIterator<Item = Self::Row>;
15202}
15203
15204impl RowRangeExt for Range<MultiBufferRow> {
15205    type Row = MultiBufferRow;
15206
15207    fn len(&self) -> usize {
15208        (self.end.0 - self.start.0) as usize
15209    }
15210
15211    fn iter_rows(&self) -> impl DoubleEndedIterator<Item = MultiBufferRow> {
15212        (self.start.0..self.end.0).map(MultiBufferRow)
15213    }
15214}
15215
15216impl RowRangeExt for Range<DisplayRow> {
15217    type Row = DisplayRow;
15218
15219    fn len(&self) -> usize {
15220        (self.end.0 - self.start.0) as usize
15221    }
15222
15223    fn iter_rows(&self) -> impl DoubleEndedIterator<Item = DisplayRow> {
15224        (self.start.0..self.end.0).map(DisplayRow)
15225    }
15226}
15227
15228fn hunk_status(hunk: &MultiBufferDiffHunk) -> DiffHunkStatus {
15229    if hunk.diff_base_byte_range.is_empty() {
15230        DiffHunkStatus::Added
15231    } else if hunk.row_range.is_empty() {
15232        DiffHunkStatus::Removed
15233    } else {
15234        DiffHunkStatus::Modified
15235    }
15236}
15237
15238/// If select range has more than one line, we
15239/// just point the cursor to range.start.
15240fn check_multiline_range(buffer: &Buffer, range: Range<usize>) -> Range<usize> {
15241    if buffer.offset_to_point(range.start).row == buffer.offset_to_point(range.end).row {
15242        range
15243    } else {
15244        range.start..range.start
15245    }
15246}
15247pub struct KillRing(ClipboardItem);
15248impl Global for KillRing {}
15249
15250const UPDATE_DEBOUNCE: Duration = Duration::from_millis(50);
15251
15252fn all_edits_insertions_or_deletions(
15253    edits: &Vec<(Range<Anchor>, String)>,
15254    snapshot: &MultiBufferSnapshot,
15255) -> bool {
15256    let mut all_insertions = true;
15257    let mut all_deletions = true;
15258
15259    for (range, new_text) in edits.iter() {
15260        let range_is_empty = range.to_offset(&snapshot).is_empty();
15261        let text_is_empty = new_text.is_empty();
15262
15263        if range_is_empty != text_is_empty {
15264            if range_is_empty {
15265                all_deletions = false;
15266            } else {
15267                all_insertions = false;
15268            }
15269        } else {
15270            return false;
15271        }
15272
15273        if !all_insertions && !all_deletions {
15274            return false;
15275        }
15276    }
15277    all_insertions || all_deletions
15278}