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
  510pub enum MenuInlineCompletionsPolicy {
  511    Never,
  512    ByProvider,
  513}
  514
  515#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Debug, Default)]
  516struct EditorActionId(usize);
  517
  518impl EditorActionId {
  519    pub fn post_inc(&mut self) -> Self {
  520        let answer = self.0;
  521
  522        *self = Self(answer + 1);
  523
  524        Self(answer)
  525    }
  526}
  527
  528// type GetFieldEditorTheme = dyn Fn(&theme::Theme) -> theme::FieldEditor;
  529// type OverrideTextStyle = dyn Fn(&EditorStyle) -> Option<HighlightStyle>;
  530
  531type BackgroundHighlight = (fn(&ThemeColors) -> Hsla, Arc<[Range<Anchor>]>);
  532type GutterHighlight = (fn(&AppContext) -> Hsla, Arc<[Range<Anchor>]>);
  533
  534#[derive(Default)]
  535struct ScrollbarMarkerState {
  536    scrollbar_size: Size<Pixels>,
  537    dirty: bool,
  538    markers: Arc<[PaintQuad]>,
  539    pending_refresh: Option<Task<Result<()>>>,
  540}
  541
  542impl ScrollbarMarkerState {
  543    fn should_refresh(&self, scrollbar_size: Size<Pixels>) -> bool {
  544        self.pending_refresh.is_none() && (self.scrollbar_size != scrollbar_size || self.dirty)
  545    }
  546}
  547
  548#[derive(Clone, Debug)]
  549struct RunnableTasks {
  550    templates: Vec<(TaskSourceKind, TaskTemplate)>,
  551    offset: MultiBufferOffset,
  552    // We need the column at which the task context evaluation should take place (when we're spawning it via gutter).
  553    column: u32,
  554    // Values of all named captures, including those starting with '_'
  555    extra_variables: HashMap<String, String>,
  556    // Full range of the tagged region. We use it to determine which `extra_variables` to grab for context resolution in e.g. a modal.
  557    context_range: Range<BufferOffset>,
  558}
  559
  560impl RunnableTasks {
  561    fn resolve<'a>(
  562        &'a self,
  563        cx: &'a task::TaskContext,
  564    ) -> impl Iterator<Item = (TaskSourceKind, ResolvedTask)> + 'a {
  565        self.templates.iter().filter_map(|(kind, template)| {
  566            template
  567                .resolve_task(&kind.to_id_base(), cx)
  568                .map(|task| (kind.clone(), task))
  569        })
  570    }
  571}
  572
  573#[derive(Clone)]
  574struct ResolvedTasks {
  575    templates: SmallVec<[(TaskSourceKind, ResolvedTask); 1]>,
  576    position: Anchor,
  577}
  578#[derive(Copy, Clone, Debug)]
  579struct MultiBufferOffset(usize);
  580#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
  581struct BufferOffset(usize);
  582
  583// Addons allow storing per-editor state in other crates (e.g. Vim)
  584pub trait Addon: 'static {
  585    fn extend_key_context(&self, _: &mut KeyContext, _: &AppContext) {}
  586
  587    fn to_any(&self) -> &dyn std::any::Any;
  588}
  589
  590#[derive(Debug, Copy, Clone, PartialEq, Eq)]
  591pub enum IsVimMode {
  592    Yes,
  593    No,
  594}
  595
  596/// Zed's primary text input `View`, allowing users to edit a [`MultiBuffer`]
  597///
  598/// See the [module level documentation](self) for more information.
  599pub struct Editor {
  600    focus_handle: FocusHandle,
  601    last_focused_descendant: Option<WeakFocusHandle>,
  602    /// The text buffer being edited
  603    buffer: Model<MultiBuffer>,
  604    /// Map of how text in the buffer should be displayed.
  605    /// Handles soft wraps, folds, fake inlay text insertions, etc.
  606    pub display_map: Model<DisplayMap>,
  607    pub selections: SelectionsCollection,
  608    pub scroll_manager: ScrollManager,
  609    /// When inline assist editors are linked, they all render cursors because
  610    /// typing enters text into each of them, even the ones that aren't focused.
  611    pub(crate) show_cursor_when_unfocused: bool,
  612    columnar_selection_tail: Option<Anchor>,
  613    add_selections_state: Option<AddSelectionsState>,
  614    select_next_state: Option<SelectNextState>,
  615    select_prev_state: Option<SelectNextState>,
  616    selection_history: SelectionHistory,
  617    autoclose_regions: Vec<AutocloseRegion>,
  618    snippet_stack: InvalidationStack<SnippetState>,
  619    select_larger_syntax_node_stack: Vec<Box<[Selection<usize>]>>,
  620    ime_transaction: Option<TransactionId>,
  621    active_diagnostics: Option<ActiveDiagnosticGroup>,
  622    soft_wrap_mode_override: Option<language_settings::SoftWrap>,
  623
  624    project: Option<Model<Project>>,
  625    semantics_provider: Option<Rc<dyn SemanticsProvider>>,
  626    completion_provider: Option<Box<dyn CompletionProvider>>,
  627    collaboration_hub: Option<Box<dyn CollaborationHub>>,
  628    blink_manager: Model<BlinkManager>,
  629    show_cursor_names: bool,
  630    hovered_cursors: HashMap<HoveredCursor, Task<()>>,
  631    pub show_local_selections: bool,
  632    mode: EditorMode,
  633    show_breadcrumbs: bool,
  634    show_gutter: bool,
  635    show_scrollbars: bool,
  636    show_line_numbers: Option<bool>,
  637    use_relative_line_numbers: Option<bool>,
  638    show_git_diff_gutter: Option<bool>,
  639    show_code_actions: Option<bool>,
  640    show_runnables: Option<bool>,
  641    show_wrap_guides: Option<bool>,
  642    show_indent_guides: Option<bool>,
  643    placeholder_text: Option<Arc<str>>,
  644    highlight_order: usize,
  645    highlighted_rows: HashMap<TypeId, Vec<RowHighlight>>,
  646    background_highlights: TreeMap<TypeId, BackgroundHighlight>,
  647    gutter_highlights: TreeMap<TypeId, GutterHighlight>,
  648    scrollbar_marker_state: ScrollbarMarkerState,
  649    active_indent_guides_state: ActiveIndentGuidesState,
  650    nav_history: Option<ItemNavHistory>,
  651    context_menu: RefCell<Option<CodeContextMenu>>,
  652    mouse_context_menu: Option<MouseContextMenu>,
  653    hunk_controls_menu_handle: PopoverMenuHandle<ui::ContextMenu>,
  654    completion_tasks: Vec<(CompletionId, Task<Option<()>>)>,
  655    signature_help_state: SignatureHelpState,
  656    auto_signature_help: Option<bool>,
  657    find_all_references_task_sources: Vec<Anchor>,
  658    next_completion_id: CompletionId,
  659    available_code_actions: Option<(Location, Rc<[AvailableCodeAction]>)>,
  660    code_actions_task: Option<Task<Result<()>>>,
  661    document_highlights_task: Option<Task<()>>,
  662    linked_editing_range_task: Option<Task<Option<()>>>,
  663    linked_edit_ranges: linked_editing_ranges::LinkedEditingRanges,
  664    pending_rename: Option<RenameState>,
  665    searchable: bool,
  666    cursor_shape: CursorShape,
  667    current_line_highlight: Option<CurrentLineHighlight>,
  668    collapse_matches: bool,
  669    autoindent_mode: Option<AutoindentMode>,
  670    workspace: Option<(WeakView<Workspace>, Option<WorkspaceId>)>,
  671    input_enabled: bool,
  672    use_modal_editing: bool,
  673    read_only: bool,
  674    leader_peer_id: Option<PeerId>,
  675    remote_id: Option<ViewId>,
  676    hover_state: HoverState,
  677    gutter_hovered: bool,
  678    hovered_link_state: Option<HoveredLinkState>,
  679    inline_completion_provider: Option<RegisteredInlineCompletionProvider>,
  680    code_action_providers: Vec<Rc<dyn CodeActionProvider>>,
  681    active_inline_completion: Option<InlineCompletionState>,
  682    // enable_inline_completions is a switch that Vim can use to disable
  683    // inline completions based on its mode.
  684    enable_inline_completions: bool,
  685    show_inline_completions_override: Option<bool>,
  686    menu_inline_completions_policy: MenuInlineCompletionsPolicy,
  687    inlay_hint_cache: InlayHintCache,
  688    diff_map: DiffMap,
  689    next_inlay_id: usize,
  690    _subscriptions: Vec<Subscription>,
  691    pixel_position_of_newest_cursor: Option<gpui::Point<Pixels>>,
  692    gutter_dimensions: GutterDimensions,
  693    style: Option<EditorStyle>,
  694    text_style_refinement: Option<TextStyleRefinement>,
  695    next_editor_action_id: EditorActionId,
  696    editor_actions: Rc<RefCell<BTreeMap<EditorActionId, Box<dyn Fn(&mut ViewContext<Self>)>>>>,
  697    use_autoclose: bool,
  698    use_auto_surround: bool,
  699    auto_replace_emoji_shortcode: bool,
  700    show_git_blame_gutter: bool,
  701    show_git_blame_inline: bool,
  702    show_git_blame_inline_delay_task: Option<Task<()>>,
  703    git_blame_inline_enabled: bool,
  704    serialize_dirty_buffers: bool,
  705    show_selection_menu: Option<bool>,
  706    blame: Option<Model<GitBlame>>,
  707    blame_subscription: Option<Subscription>,
  708    custom_context_menu: Option<
  709        Box<
  710            dyn 'static
  711                + Fn(&mut Self, DisplayPoint, &mut ViewContext<Self>) -> Option<View<ui::ContextMenu>>,
  712        >,
  713    >,
  714    last_bounds: Option<Bounds<Pixels>>,
  715    expect_bounds_change: Option<Bounds<Pixels>>,
  716    tasks: BTreeMap<(BufferId, BufferRow), RunnableTasks>,
  717    tasks_update_task: Option<Task<()>>,
  718    previous_search_ranges: Option<Arc<[Range<Anchor>]>>,
  719    breadcrumb_header: Option<String>,
  720    focused_block: Option<FocusedBlock>,
  721    next_scroll_position: NextScrollCursorCenterTopBottom,
  722    addons: HashMap<TypeId, Box<dyn Addon>>,
  723    registered_buffers: HashMap<BufferId, OpenLspBufferHandle>,
  724    selection_mark_mode: bool,
  725    toggle_fold_multiple_buffers: Task<()>,
  726    _scroll_cursor_center_top_bottom_task: Task<()>,
  727}
  728
  729#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)]
  730enum NextScrollCursorCenterTopBottom {
  731    #[default]
  732    Center,
  733    Top,
  734    Bottom,
  735}
  736
  737impl NextScrollCursorCenterTopBottom {
  738    fn next(&self) -> Self {
  739        match self {
  740            Self::Center => Self::Top,
  741            Self::Top => Self::Bottom,
  742            Self::Bottom => Self::Center,
  743        }
  744    }
  745}
  746
  747#[derive(Clone)]
  748pub struct EditorSnapshot {
  749    pub mode: EditorMode,
  750    show_gutter: bool,
  751    show_line_numbers: Option<bool>,
  752    show_git_diff_gutter: Option<bool>,
  753    show_code_actions: Option<bool>,
  754    show_runnables: Option<bool>,
  755    git_blame_gutter_max_author_length: Option<usize>,
  756    pub display_snapshot: DisplaySnapshot,
  757    pub placeholder_text: Option<Arc<str>>,
  758    diff_map: DiffMapSnapshot,
  759    is_focused: bool,
  760    scroll_anchor: ScrollAnchor,
  761    ongoing_scroll: OngoingScroll,
  762    current_line_highlight: CurrentLineHighlight,
  763    gutter_hovered: bool,
  764}
  765
  766const GIT_BLAME_MAX_AUTHOR_CHARS_DISPLAYED: usize = 20;
  767
  768#[derive(Default, Debug, Clone, Copy)]
  769pub struct GutterDimensions {
  770    pub left_padding: Pixels,
  771    pub right_padding: Pixels,
  772    pub width: Pixels,
  773    pub margin: Pixels,
  774    pub git_blame_entries_width: Option<Pixels>,
  775}
  776
  777impl GutterDimensions {
  778    /// The full width of the space taken up by the gutter.
  779    pub fn full_width(&self) -> Pixels {
  780        self.margin + self.width
  781    }
  782
  783    /// The width of the space reserved for the fold indicators,
  784    /// use alongside 'justify_end' and `gutter_width` to
  785    /// right align content with the line numbers
  786    pub fn fold_area_width(&self) -> Pixels {
  787        self.margin + self.right_padding
  788    }
  789}
  790
  791#[derive(Debug)]
  792pub struct RemoteSelection {
  793    pub replica_id: ReplicaId,
  794    pub selection: Selection<Anchor>,
  795    pub cursor_shape: CursorShape,
  796    pub peer_id: PeerId,
  797    pub line_mode: bool,
  798    pub participant_index: Option<ParticipantIndex>,
  799    pub user_name: Option<SharedString>,
  800}
  801
  802#[derive(Clone, Debug)]
  803struct SelectionHistoryEntry {
  804    selections: Arc<[Selection<Anchor>]>,
  805    select_next_state: Option<SelectNextState>,
  806    select_prev_state: Option<SelectNextState>,
  807    add_selections_state: Option<AddSelectionsState>,
  808}
  809
  810enum SelectionHistoryMode {
  811    Normal,
  812    Undoing,
  813    Redoing,
  814}
  815
  816#[derive(Clone, PartialEq, Eq, Hash)]
  817struct HoveredCursor {
  818    replica_id: u16,
  819    selection_id: usize,
  820}
  821
  822impl Default for SelectionHistoryMode {
  823    fn default() -> Self {
  824        Self::Normal
  825    }
  826}
  827
  828#[derive(Default)]
  829struct SelectionHistory {
  830    #[allow(clippy::type_complexity)]
  831    selections_by_transaction:
  832        HashMap<TransactionId, (Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)>,
  833    mode: SelectionHistoryMode,
  834    undo_stack: VecDeque<SelectionHistoryEntry>,
  835    redo_stack: VecDeque<SelectionHistoryEntry>,
  836}
  837
  838impl SelectionHistory {
  839    fn insert_transaction(
  840        &mut self,
  841        transaction_id: TransactionId,
  842        selections: Arc<[Selection<Anchor>]>,
  843    ) {
  844        self.selections_by_transaction
  845            .insert(transaction_id, (selections, None));
  846    }
  847
  848    #[allow(clippy::type_complexity)]
  849    fn transaction(
  850        &self,
  851        transaction_id: TransactionId,
  852    ) -> Option<&(Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)> {
  853        self.selections_by_transaction.get(&transaction_id)
  854    }
  855
  856    #[allow(clippy::type_complexity)]
  857    fn transaction_mut(
  858        &mut self,
  859        transaction_id: TransactionId,
  860    ) -> Option<&mut (Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)> {
  861        self.selections_by_transaction.get_mut(&transaction_id)
  862    }
  863
  864    fn push(&mut self, entry: SelectionHistoryEntry) {
  865        if !entry.selections.is_empty() {
  866            match self.mode {
  867                SelectionHistoryMode::Normal => {
  868                    self.push_undo(entry);
  869                    self.redo_stack.clear();
  870                }
  871                SelectionHistoryMode::Undoing => self.push_redo(entry),
  872                SelectionHistoryMode::Redoing => self.push_undo(entry),
  873            }
  874        }
  875    }
  876
  877    fn push_undo(&mut self, entry: SelectionHistoryEntry) {
  878        if self
  879            .undo_stack
  880            .back()
  881            .map_or(true, |e| e.selections != entry.selections)
  882        {
  883            self.undo_stack.push_back(entry);
  884            if self.undo_stack.len() > MAX_SELECTION_HISTORY_LEN {
  885                self.undo_stack.pop_front();
  886            }
  887        }
  888    }
  889
  890    fn push_redo(&mut self, entry: SelectionHistoryEntry) {
  891        if self
  892            .redo_stack
  893            .back()
  894            .map_or(true, |e| e.selections != entry.selections)
  895        {
  896            self.redo_stack.push_back(entry);
  897            if self.redo_stack.len() > MAX_SELECTION_HISTORY_LEN {
  898                self.redo_stack.pop_front();
  899            }
  900        }
  901    }
  902}
  903
  904struct RowHighlight {
  905    index: usize,
  906    range: Range<Anchor>,
  907    color: Hsla,
  908    should_autoscroll: bool,
  909}
  910
  911#[derive(Clone, Debug)]
  912struct AddSelectionsState {
  913    above: bool,
  914    stack: Vec<usize>,
  915}
  916
  917#[derive(Clone)]
  918struct SelectNextState {
  919    query: AhoCorasick,
  920    wordwise: bool,
  921    done: bool,
  922}
  923
  924impl std::fmt::Debug for SelectNextState {
  925    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  926        f.debug_struct(std::any::type_name::<Self>())
  927            .field("wordwise", &self.wordwise)
  928            .field("done", &self.done)
  929            .finish()
  930    }
  931}
  932
  933#[derive(Debug)]
  934struct AutocloseRegion {
  935    selection_id: usize,
  936    range: Range<Anchor>,
  937    pair: BracketPair,
  938}
  939
  940#[derive(Debug)]
  941struct SnippetState {
  942    ranges: Vec<Vec<Range<Anchor>>>,
  943    active_index: usize,
  944    choices: Vec<Option<Vec<String>>>,
  945}
  946
  947#[doc(hidden)]
  948pub struct RenameState {
  949    pub range: Range<Anchor>,
  950    pub old_name: Arc<str>,
  951    pub editor: View<Editor>,
  952    block_id: CustomBlockId,
  953}
  954
  955struct InvalidationStack<T>(Vec<T>);
  956
  957struct RegisteredInlineCompletionProvider {
  958    provider: Arc<dyn InlineCompletionProviderHandle>,
  959    _subscription: Subscription,
  960}
  961
  962#[derive(Debug)]
  963struct ActiveDiagnosticGroup {
  964    primary_range: Range<Anchor>,
  965    primary_message: String,
  966    group_id: usize,
  967    blocks: HashMap<CustomBlockId, Diagnostic>,
  968    is_valid: bool,
  969}
  970
  971#[derive(Serialize, Deserialize, Clone, Debug)]
  972pub struct ClipboardSelection {
  973    pub len: usize,
  974    pub is_entire_line: bool,
  975    pub first_line_indent: u32,
  976}
  977
  978#[derive(Debug)]
  979pub(crate) struct NavigationData {
  980    cursor_anchor: Anchor,
  981    cursor_position: Point,
  982    scroll_anchor: ScrollAnchor,
  983    scroll_top_row: u32,
  984}
  985
  986#[derive(Debug, Clone, Copy, PartialEq, Eq)]
  987pub enum GotoDefinitionKind {
  988    Symbol,
  989    Declaration,
  990    Type,
  991    Implementation,
  992}
  993
  994#[derive(Debug, Clone)]
  995enum InlayHintRefreshReason {
  996    Toggle(bool),
  997    SettingsChange(InlayHintSettings),
  998    NewLinesShown,
  999    BufferEdited(HashSet<Arc<Language>>),
 1000    RefreshRequested,
 1001    ExcerptsRemoved(Vec<ExcerptId>),
 1002}
 1003
 1004impl InlayHintRefreshReason {
 1005    fn description(&self) -> &'static str {
 1006        match self {
 1007            Self::Toggle(_) => "toggle",
 1008            Self::SettingsChange(_) => "settings change",
 1009            Self::NewLinesShown => "new lines shown",
 1010            Self::BufferEdited(_) => "buffer edited",
 1011            Self::RefreshRequested => "refresh requested",
 1012            Self::ExcerptsRemoved(_) => "excerpts removed",
 1013        }
 1014    }
 1015}
 1016
 1017pub enum FormatTarget {
 1018    Buffers,
 1019    Ranges(Vec<Range<MultiBufferPoint>>),
 1020}
 1021
 1022pub(crate) struct FocusedBlock {
 1023    id: BlockId,
 1024    focus_handle: WeakFocusHandle,
 1025}
 1026
 1027#[derive(Clone)]
 1028enum JumpData {
 1029    MultiBufferRow {
 1030        row: MultiBufferRow,
 1031        line_offset_from_top: u32,
 1032    },
 1033    MultiBufferPoint {
 1034        excerpt_id: ExcerptId,
 1035        position: Point,
 1036        anchor: text::Anchor,
 1037        line_offset_from_top: u32,
 1038    },
 1039}
 1040
 1041impl Editor {
 1042    pub fn single_line(cx: &mut ViewContext<Self>) -> Self {
 1043        let buffer = cx.new_model(|cx| Buffer::local("", cx));
 1044        let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
 1045        Self::new(
 1046            EditorMode::SingleLine { auto_width: false },
 1047            buffer,
 1048            None,
 1049            false,
 1050            cx,
 1051        )
 1052    }
 1053
 1054    pub fn multi_line(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(EditorMode::Full, buffer, None, false, cx)
 1058    }
 1059
 1060    pub fn auto_width(cx: &mut ViewContext<Self>) -> Self {
 1061        let buffer = cx.new_model(|cx| Buffer::local("", cx));
 1062        let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
 1063        Self::new(
 1064            EditorMode::SingleLine { auto_width: true },
 1065            buffer,
 1066            None,
 1067            false,
 1068            cx,
 1069        )
 1070    }
 1071
 1072    pub fn auto_height(max_lines: usize, cx: &mut ViewContext<Self>) -> Self {
 1073        let buffer = cx.new_model(|cx| Buffer::local("", cx));
 1074        let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
 1075        Self::new(
 1076            EditorMode::AutoHeight { max_lines },
 1077            buffer,
 1078            None,
 1079            false,
 1080            cx,
 1081        )
 1082    }
 1083
 1084    pub fn for_buffer(
 1085        buffer: Model<Buffer>,
 1086        project: Option<Model<Project>>,
 1087        cx: &mut ViewContext<Self>,
 1088    ) -> Self {
 1089        let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
 1090        Self::new(EditorMode::Full, buffer, project, false, cx)
 1091    }
 1092
 1093    pub fn for_multibuffer(
 1094        buffer: Model<MultiBuffer>,
 1095        project: Option<Model<Project>>,
 1096        show_excerpt_controls: bool,
 1097        cx: &mut ViewContext<Self>,
 1098    ) -> Self {
 1099        Self::new(EditorMode::Full, buffer, project, show_excerpt_controls, cx)
 1100    }
 1101
 1102    pub fn clone(&self, cx: &mut ViewContext<Self>) -> Self {
 1103        let show_excerpt_controls = self.display_map.read(cx).show_excerpt_controls();
 1104        let mut clone = Self::new(
 1105            self.mode,
 1106            self.buffer.clone(),
 1107            self.project.clone(),
 1108            show_excerpt_controls,
 1109            cx,
 1110        );
 1111        self.display_map.update(cx, |display_map, cx| {
 1112            let snapshot = display_map.snapshot(cx);
 1113            clone.display_map.update(cx, |display_map, cx| {
 1114                display_map.set_state(&snapshot, cx);
 1115            });
 1116        });
 1117        clone.selections.clone_state(&self.selections);
 1118        clone.scroll_manager.clone_state(&self.scroll_manager);
 1119        clone.searchable = self.searchable;
 1120        clone
 1121    }
 1122
 1123    pub fn new(
 1124        mode: EditorMode,
 1125        buffer: Model<MultiBuffer>,
 1126        project: Option<Model<Project>>,
 1127        show_excerpt_controls: bool,
 1128        cx: &mut ViewContext<Self>,
 1129    ) -> Self {
 1130        let style = cx.text_style();
 1131        let font_size = style.font_size.to_pixels(cx.rem_size());
 1132        let editor = cx.view().downgrade();
 1133        let fold_placeholder = FoldPlaceholder {
 1134            constrain_width: true,
 1135            render: Arc::new(move |fold_id, fold_range, cx| {
 1136                let editor = editor.clone();
 1137                div()
 1138                    .id(fold_id)
 1139                    .bg(cx.theme().colors().ghost_element_background)
 1140                    .hover(|style| style.bg(cx.theme().colors().ghost_element_hover))
 1141                    .active(|style| style.bg(cx.theme().colors().ghost_element_active))
 1142                    .rounded_sm()
 1143                    .size_full()
 1144                    .cursor_pointer()
 1145                    .child("")
 1146                    .on_mouse_down(MouseButton::Left, |_, cx| cx.stop_propagation())
 1147                    .on_click(move |_, cx| {
 1148                        editor
 1149                            .update(cx, |editor, cx| {
 1150                                editor.unfold_ranges(
 1151                                    &[fold_range.start..fold_range.end],
 1152                                    true,
 1153                                    false,
 1154                                    cx,
 1155                                );
 1156                                cx.stop_propagation();
 1157                            })
 1158                            .ok();
 1159                    })
 1160                    .into_any()
 1161            }),
 1162            merge_adjacent: true,
 1163            ..Default::default()
 1164        };
 1165        let display_map = cx.new_model(|cx| {
 1166            DisplayMap::new(
 1167                buffer.clone(),
 1168                style.font(),
 1169                font_size,
 1170                None,
 1171                show_excerpt_controls,
 1172                FILE_HEADER_HEIGHT,
 1173                MULTI_BUFFER_EXCERPT_HEADER_HEIGHT,
 1174                MULTI_BUFFER_EXCERPT_FOOTER_HEIGHT,
 1175                fold_placeholder,
 1176                cx,
 1177            )
 1178        });
 1179
 1180        let selections = SelectionsCollection::new(display_map.clone(), buffer.clone());
 1181
 1182        let blink_manager = cx.new_model(|cx| BlinkManager::new(CURSOR_BLINK_INTERVAL, cx));
 1183
 1184        let soft_wrap_mode_override = matches!(mode, EditorMode::SingleLine { .. })
 1185            .then(|| language_settings::SoftWrap::None);
 1186
 1187        let mut project_subscriptions = Vec::new();
 1188        if mode == EditorMode::Full {
 1189            if let Some(project) = project.as_ref() {
 1190                if buffer.read(cx).is_singleton() {
 1191                    project_subscriptions.push(cx.observe(project, |_, _, cx| {
 1192                        cx.emit(EditorEvent::TitleChanged);
 1193                    }));
 1194                }
 1195                project_subscriptions.push(cx.subscribe(project, |editor, _, event, cx| {
 1196                    if let project::Event::RefreshInlayHints = event {
 1197                        editor.refresh_inlay_hints(InlayHintRefreshReason::RefreshRequested, cx);
 1198                    } else if let project::Event::SnippetEdit(id, snippet_edits) = event {
 1199                        if let Some(buffer) = editor.buffer.read(cx).buffer(*id) {
 1200                            let focus_handle = editor.focus_handle(cx);
 1201                            if focus_handle.is_focused(cx) {
 1202                                let snapshot = buffer.read(cx).snapshot();
 1203                                for (range, snippet) in snippet_edits {
 1204                                    let editor_range =
 1205                                        language::range_from_lsp(*range).to_offset(&snapshot);
 1206                                    editor
 1207                                        .insert_snippet(&[editor_range], snippet.clone(), cx)
 1208                                        .ok();
 1209                                }
 1210                            }
 1211                        }
 1212                    }
 1213                }));
 1214                if let Some(task_inventory) = project
 1215                    .read(cx)
 1216                    .task_store()
 1217                    .read(cx)
 1218                    .task_inventory()
 1219                    .cloned()
 1220                {
 1221                    project_subscriptions.push(cx.observe(&task_inventory, |editor, _, cx| {
 1222                        editor.tasks_update_task = Some(editor.refresh_runnables(cx));
 1223                    }));
 1224                }
 1225            }
 1226        }
 1227
 1228        let buffer_snapshot = buffer.read(cx).snapshot(cx);
 1229
 1230        let inlay_hint_settings =
 1231            inlay_hint_settings(selections.newest_anchor().head(), &buffer_snapshot, cx);
 1232        let focus_handle = cx.focus_handle();
 1233        cx.on_focus(&focus_handle, Self::handle_focus).detach();
 1234        cx.on_focus_in(&focus_handle, Self::handle_focus_in)
 1235            .detach();
 1236        cx.on_focus_out(&focus_handle, Self::handle_focus_out)
 1237            .detach();
 1238        cx.on_blur(&focus_handle, Self::handle_blur).detach();
 1239
 1240        let show_indent_guides = if matches!(mode, EditorMode::SingleLine { .. }) {
 1241            Some(false)
 1242        } else {
 1243            None
 1244        };
 1245
 1246        let mut code_action_providers = Vec::new();
 1247        if let Some(project) = project.clone() {
 1248            get_unstaged_changes_for_buffers(&project, buffer.read(cx).all_buffers(), cx);
 1249            code_action_providers.push(Rc::new(project) as Rc<_>);
 1250        }
 1251
 1252        let mut this = Self {
 1253            focus_handle,
 1254            show_cursor_when_unfocused: false,
 1255            last_focused_descendant: None,
 1256            buffer: buffer.clone(),
 1257            display_map: display_map.clone(),
 1258            selections,
 1259            scroll_manager: ScrollManager::new(cx),
 1260            columnar_selection_tail: None,
 1261            add_selections_state: None,
 1262            select_next_state: None,
 1263            select_prev_state: None,
 1264            selection_history: Default::default(),
 1265            autoclose_regions: Default::default(),
 1266            snippet_stack: Default::default(),
 1267            select_larger_syntax_node_stack: Vec::new(),
 1268            ime_transaction: Default::default(),
 1269            active_diagnostics: None,
 1270            soft_wrap_mode_override,
 1271            completion_provider: project.clone().map(|project| Box::new(project) as _),
 1272            semantics_provider: project.clone().map(|project| Rc::new(project) as _),
 1273            collaboration_hub: project.clone().map(|project| Box::new(project) as _),
 1274            project,
 1275            blink_manager: blink_manager.clone(),
 1276            show_local_selections: true,
 1277            show_scrollbars: true,
 1278            mode,
 1279            show_breadcrumbs: EditorSettings::get_global(cx).toolbar.breadcrumbs,
 1280            show_gutter: mode == EditorMode::Full,
 1281            show_line_numbers: None,
 1282            use_relative_line_numbers: None,
 1283            show_git_diff_gutter: None,
 1284            show_code_actions: None,
 1285            show_runnables: None,
 1286            show_wrap_guides: None,
 1287            show_indent_guides,
 1288            placeholder_text: None,
 1289            highlight_order: 0,
 1290            highlighted_rows: HashMap::default(),
 1291            background_highlights: Default::default(),
 1292            gutter_highlights: TreeMap::default(),
 1293            scrollbar_marker_state: ScrollbarMarkerState::default(),
 1294            active_indent_guides_state: ActiveIndentGuidesState::default(),
 1295            nav_history: None,
 1296            context_menu: RefCell::new(None),
 1297            mouse_context_menu: None,
 1298            hunk_controls_menu_handle: PopoverMenuHandle::default(),
 1299            completion_tasks: Default::default(),
 1300            signature_help_state: SignatureHelpState::default(),
 1301            auto_signature_help: None,
 1302            find_all_references_task_sources: Vec::new(),
 1303            next_completion_id: 0,
 1304            next_inlay_id: 0,
 1305            code_action_providers,
 1306            available_code_actions: Default::default(),
 1307            code_actions_task: Default::default(),
 1308            document_highlights_task: Default::default(),
 1309            linked_editing_range_task: Default::default(),
 1310            pending_rename: Default::default(),
 1311            searchable: true,
 1312            cursor_shape: EditorSettings::get_global(cx)
 1313                .cursor_shape
 1314                .unwrap_or_default(),
 1315            current_line_highlight: None,
 1316            autoindent_mode: Some(AutoindentMode::EachLine),
 1317            collapse_matches: false,
 1318            workspace: None,
 1319            input_enabled: true,
 1320            use_modal_editing: mode == EditorMode::Full,
 1321            read_only: false,
 1322            use_autoclose: true,
 1323            use_auto_surround: true,
 1324            auto_replace_emoji_shortcode: false,
 1325            leader_peer_id: None,
 1326            remote_id: None,
 1327            hover_state: Default::default(),
 1328            hovered_link_state: Default::default(),
 1329            inline_completion_provider: None,
 1330            active_inline_completion: None,
 1331            inlay_hint_cache: InlayHintCache::new(inlay_hint_settings),
 1332            diff_map: DiffMap::default(),
 1333            gutter_hovered: false,
 1334            pixel_position_of_newest_cursor: None,
 1335            last_bounds: None,
 1336            expect_bounds_change: None,
 1337            gutter_dimensions: GutterDimensions::default(),
 1338            style: None,
 1339            show_cursor_names: false,
 1340            hovered_cursors: Default::default(),
 1341            next_editor_action_id: EditorActionId::default(),
 1342            editor_actions: Rc::default(),
 1343            show_inline_completions_override: None,
 1344            enable_inline_completions: true,
 1345            menu_inline_completions_policy: MenuInlineCompletionsPolicy::ByProvider,
 1346            custom_context_menu: None,
 1347            show_git_blame_gutter: false,
 1348            show_git_blame_inline: false,
 1349            show_selection_menu: None,
 1350            show_git_blame_inline_delay_task: None,
 1351            git_blame_inline_enabled: ProjectSettings::get_global(cx).git.inline_blame_enabled(),
 1352            serialize_dirty_buffers: ProjectSettings::get_global(cx)
 1353                .session
 1354                .restore_unsaved_buffers,
 1355            blame: None,
 1356            blame_subscription: None,
 1357            tasks: Default::default(),
 1358            _subscriptions: vec![
 1359                cx.observe(&buffer, Self::on_buffer_changed),
 1360                cx.subscribe(&buffer, Self::on_buffer_event),
 1361                cx.observe(&display_map, Self::on_display_map_changed),
 1362                cx.observe(&blink_manager, |_, _, cx| cx.notify()),
 1363                cx.observe_global::<SettingsStore>(Self::settings_changed),
 1364                cx.observe_window_activation(|editor, cx| {
 1365                    let active = cx.is_window_active();
 1366                    editor.blink_manager.update(cx, |blink_manager, cx| {
 1367                        if active {
 1368                            blink_manager.enable(cx);
 1369                        } else {
 1370                            blink_manager.disable(cx);
 1371                        }
 1372                    });
 1373                }),
 1374            ],
 1375            tasks_update_task: None,
 1376            linked_edit_ranges: Default::default(),
 1377            previous_search_ranges: None,
 1378            breadcrumb_header: None,
 1379            focused_block: None,
 1380            next_scroll_position: NextScrollCursorCenterTopBottom::default(),
 1381            addons: HashMap::default(),
 1382            registered_buffers: HashMap::default(),
 1383            _scroll_cursor_center_top_bottom_task: Task::ready(()),
 1384            selection_mark_mode: false,
 1385            toggle_fold_multiple_buffers: Task::ready(()),
 1386            text_style_refinement: None,
 1387        };
 1388        this.tasks_update_task = Some(this.refresh_runnables(cx));
 1389        this._subscriptions.extend(project_subscriptions);
 1390
 1391        this.end_selection(cx);
 1392        this.scroll_manager.show_scrollbar(cx);
 1393
 1394        if mode == EditorMode::Full {
 1395            let should_auto_hide_scrollbars = cx.should_auto_hide_scrollbars();
 1396            cx.set_global(ScrollbarAutoHide(should_auto_hide_scrollbars));
 1397
 1398            if this.git_blame_inline_enabled {
 1399                this.git_blame_inline_enabled = true;
 1400                this.start_git_blame_inline(false, cx);
 1401            }
 1402
 1403            if let Some(buffer) = buffer.read(cx).as_singleton() {
 1404                if let Some(project) = this.project.as_ref() {
 1405                    let lsp_store = project.read(cx).lsp_store();
 1406                    let handle = lsp_store.update(cx, |lsp_store, cx| {
 1407                        lsp_store.register_buffer_with_language_servers(&buffer, cx)
 1408                    });
 1409                    this.registered_buffers
 1410                        .insert(buffer.read(cx).remote_id(), handle);
 1411                }
 1412            }
 1413        }
 1414
 1415        this.report_editor_event("Editor Opened", None, cx);
 1416        this
 1417    }
 1418
 1419    pub fn mouse_menu_is_focused(&self, cx: &WindowContext) -> bool {
 1420        self.mouse_context_menu
 1421            .as_ref()
 1422            .is_some_and(|menu| menu.context_menu.focus_handle(cx).is_focused(cx))
 1423    }
 1424
 1425    fn key_context(&self, cx: &ViewContext<Self>) -> KeyContext {
 1426        let mut key_context = KeyContext::new_with_defaults();
 1427        key_context.add("Editor");
 1428        let mode = match self.mode {
 1429            EditorMode::SingleLine { .. } => "single_line",
 1430            EditorMode::AutoHeight { .. } => "auto_height",
 1431            EditorMode::Full => "full",
 1432        };
 1433
 1434        if EditorSettings::jupyter_enabled(cx) {
 1435            key_context.add("jupyter");
 1436        }
 1437
 1438        key_context.set("mode", mode);
 1439        if self.pending_rename.is_some() {
 1440            key_context.add("renaming");
 1441        }
 1442        match self.context_menu.borrow().as_ref() {
 1443            Some(CodeContextMenu::Completions(_)) => {
 1444                key_context.add("menu");
 1445                key_context.add("showing_completions")
 1446            }
 1447            Some(CodeContextMenu::CodeActions(_)) => {
 1448                key_context.add("menu");
 1449                key_context.add("showing_code_actions")
 1450            }
 1451            None => {}
 1452        }
 1453
 1454        // Disable vim contexts when a sub-editor (e.g. rename/inline assistant) is focused.
 1455        if !self.focus_handle(cx).contains_focused(cx)
 1456            || (self.is_focused(cx) || self.mouse_menu_is_focused(cx))
 1457        {
 1458            for addon in self.addons.values() {
 1459                addon.extend_key_context(&mut key_context, cx)
 1460            }
 1461        }
 1462
 1463        if let Some(extension) = self
 1464            .buffer
 1465            .read(cx)
 1466            .as_singleton()
 1467            .and_then(|buffer| buffer.read(cx).file()?.path().extension()?.to_str())
 1468        {
 1469            key_context.set("extension", extension.to_string());
 1470        }
 1471
 1472        if self.has_active_inline_completion() {
 1473            key_context.add("copilot_suggestion");
 1474            key_context.add("inline_completion");
 1475        }
 1476
 1477        if self.selection_mark_mode {
 1478            key_context.add("selection_mode");
 1479        }
 1480
 1481        key_context
 1482    }
 1483
 1484    pub fn new_file(
 1485        workspace: &mut Workspace,
 1486        _: &workspace::NewFile,
 1487        cx: &mut ViewContext<Workspace>,
 1488    ) {
 1489        Self::new_in_workspace(workspace, cx).detach_and_prompt_err(
 1490            "Failed to create buffer",
 1491            cx,
 1492            |e, _| match e.error_code() {
 1493                ErrorCode::RemoteUpgradeRequired => Some(format!(
 1494                "The remote instance of Zed does not support this yet. It must be upgraded to {}",
 1495                e.error_tag("required").unwrap_or("the latest version")
 1496            )),
 1497                _ => None,
 1498            },
 1499        );
 1500    }
 1501
 1502    pub fn new_in_workspace(
 1503        workspace: &mut Workspace,
 1504        cx: &mut ViewContext<Workspace>,
 1505    ) -> Task<Result<View<Editor>>> {
 1506        let project = workspace.project().clone();
 1507        let create = project.update(cx, |project, cx| project.create_buffer(cx));
 1508
 1509        cx.spawn(|workspace, mut cx| async move {
 1510            let buffer = create.await?;
 1511            workspace.update(&mut cx, |workspace, cx| {
 1512                let editor =
 1513                    cx.new_view(|cx| Editor::for_buffer(buffer, Some(project.clone()), cx));
 1514                workspace.add_item_to_active_pane(Box::new(editor.clone()), None, true, cx);
 1515                editor
 1516            })
 1517        })
 1518    }
 1519
 1520    fn new_file_vertical(
 1521        workspace: &mut Workspace,
 1522        _: &workspace::NewFileSplitVertical,
 1523        cx: &mut ViewContext<Workspace>,
 1524    ) {
 1525        Self::new_file_in_direction(workspace, SplitDirection::vertical(cx), cx)
 1526    }
 1527
 1528    fn new_file_horizontal(
 1529        workspace: &mut Workspace,
 1530        _: &workspace::NewFileSplitHorizontal,
 1531        cx: &mut ViewContext<Workspace>,
 1532    ) {
 1533        Self::new_file_in_direction(workspace, SplitDirection::horizontal(cx), cx)
 1534    }
 1535
 1536    fn new_file_in_direction(
 1537        workspace: &mut Workspace,
 1538        direction: SplitDirection,
 1539        cx: &mut ViewContext<Workspace>,
 1540    ) {
 1541        let project = workspace.project().clone();
 1542        let create = project.update(cx, |project, cx| project.create_buffer(cx));
 1543
 1544        cx.spawn(|workspace, mut cx| async move {
 1545            let buffer = create.await?;
 1546            workspace.update(&mut cx, move |workspace, cx| {
 1547                workspace.split_item(
 1548                    direction,
 1549                    Box::new(
 1550                        cx.new_view(|cx| Editor::for_buffer(buffer, Some(project.clone()), cx)),
 1551                    ),
 1552                    cx,
 1553                )
 1554            })?;
 1555            anyhow::Ok(())
 1556        })
 1557        .detach_and_prompt_err("Failed to create buffer", cx, |e, _| match e.error_code() {
 1558            ErrorCode::RemoteUpgradeRequired => Some(format!(
 1559                "The remote instance of Zed does not support this yet. It must be upgraded to {}",
 1560                e.error_tag("required").unwrap_or("the latest version")
 1561            )),
 1562            _ => None,
 1563        });
 1564    }
 1565
 1566    pub fn leader_peer_id(&self) -> Option<PeerId> {
 1567        self.leader_peer_id
 1568    }
 1569
 1570    pub fn buffer(&self) -> &Model<MultiBuffer> {
 1571        &self.buffer
 1572    }
 1573
 1574    pub fn workspace(&self) -> Option<View<Workspace>> {
 1575        self.workspace.as_ref()?.0.upgrade()
 1576    }
 1577
 1578    pub fn title<'a>(&self, cx: &'a AppContext) -> Cow<'a, str> {
 1579        self.buffer().read(cx).title(cx)
 1580    }
 1581
 1582    pub fn snapshot(&self, cx: &mut WindowContext) -> EditorSnapshot {
 1583        let git_blame_gutter_max_author_length = self
 1584            .render_git_blame_gutter(cx)
 1585            .then(|| {
 1586                if let Some(blame) = self.blame.as_ref() {
 1587                    let max_author_length =
 1588                        blame.update(cx, |blame, cx| blame.max_author_length(cx));
 1589                    Some(max_author_length)
 1590                } else {
 1591                    None
 1592                }
 1593            })
 1594            .flatten();
 1595
 1596        EditorSnapshot {
 1597            mode: self.mode,
 1598            show_gutter: self.show_gutter,
 1599            show_line_numbers: self.show_line_numbers,
 1600            show_git_diff_gutter: self.show_git_diff_gutter,
 1601            show_code_actions: self.show_code_actions,
 1602            show_runnables: self.show_runnables,
 1603            git_blame_gutter_max_author_length,
 1604            display_snapshot: self.display_map.update(cx, |map, cx| map.snapshot(cx)),
 1605            scroll_anchor: self.scroll_manager.anchor(),
 1606            ongoing_scroll: self.scroll_manager.ongoing_scroll(),
 1607            placeholder_text: self.placeholder_text.clone(),
 1608            diff_map: self.diff_map.snapshot(),
 1609            is_focused: self.focus_handle.is_focused(cx),
 1610            current_line_highlight: self
 1611                .current_line_highlight
 1612                .unwrap_or_else(|| EditorSettings::get_global(cx).current_line_highlight),
 1613            gutter_hovered: self.gutter_hovered,
 1614        }
 1615    }
 1616
 1617    pub fn language_at<T: ToOffset>(&self, point: T, cx: &AppContext) -> Option<Arc<Language>> {
 1618        self.buffer.read(cx).language_at(point, cx)
 1619    }
 1620
 1621    pub fn file_at<T: ToOffset>(
 1622        &self,
 1623        point: T,
 1624        cx: &AppContext,
 1625    ) -> Option<Arc<dyn language::File>> {
 1626        self.buffer.read(cx).read(cx).file_at(point).cloned()
 1627    }
 1628
 1629    pub fn active_excerpt(
 1630        &self,
 1631        cx: &AppContext,
 1632    ) -> Option<(ExcerptId, Model<Buffer>, Range<text::Anchor>)> {
 1633        self.buffer
 1634            .read(cx)
 1635            .excerpt_containing(self.selections.newest_anchor().head(), cx)
 1636    }
 1637
 1638    pub fn mode(&self) -> EditorMode {
 1639        self.mode
 1640    }
 1641
 1642    pub fn collaboration_hub(&self) -> Option<&dyn CollaborationHub> {
 1643        self.collaboration_hub.as_deref()
 1644    }
 1645
 1646    pub fn set_collaboration_hub(&mut self, hub: Box<dyn CollaborationHub>) {
 1647        self.collaboration_hub = Some(hub);
 1648    }
 1649
 1650    pub fn set_custom_context_menu(
 1651        &mut self,
 1652        f: impl 'static
 1653            + Fn(&mut Self, DisplayPoint, &mut ViewContext<Self>) -> Option<View<ui::ContextMenu>>,
 1654    ) {
 1655        self.custom_context_menu = Some(Box::new(f))
 1656    }
 1657
 1658    pub fn set_completion_provider(&mut self, provider: Option<Box<dyn CompletionProvider>>) {
 1659        self.completion_provider = provider;
 1660    }
 1661
 1662    pub fn semantics_provider(&self) -> Option<Rc<dyn SemanticsProvider>> {
 1663        self.semantics_provider.clone()
 1664    }
 1665
 1666    pub fn set_semantics_provider(&mut self, provider: Option<Rc<dyn SemanticsProvider>>) {
 1667        self.semantics_provider = provider;
 1668    }
 1669
 1670    pub fn set_inline_completion_provider<T>(
 1671        &mut self,
 1672        provider: Option<Model<T>>,
 1673        cx: &mut ViewContext<Self>,
 1674    ) where
 1675        T: InlineCompletionProvider,
 1676    {
 1677        self.inline_completion_provider =
 1678            provider.map(|provider| RegisteredInlineCompletionProvider {
 1679                _subscription: cx.observe(&provider, |this, _, cx| {
 1680                    if this.focus_handle.is_focused(cx) {
 1681                        this.update_visible_inline_completion(cx);
 1682                    }
 1683                }),
 1684                provider: Arc::new(provider),
 1685            });
 1686        self.refresh_inline_completion(false, false, cx);
 1687    }
 1688
 1689    pub fn placeholder_text(&self, _cx: &WindowContext) -> Option<&str> {
 1690        self.placeholder_text.as_deref()
 1691    }
 1692
 1693    pub fn set_placeholder_text(
 1694        &mut self,
 1695        placeholder_text: impl Into<Arc<str>>,
 1696        cx: &mut ViewContext<Self>,
 1697    ) {
 1698        let placeholder_text = Some(placeholder_text.into());
 1699        if self.placeholder_text != placeholder_text {
 1700            self.placeholder_text = placeholder_text;
 1701            cx.notify();
 1702        }
 1703    }
 1704
 1705    pub fn set_cursor_shape(&mut self, cursor_shape: CursorShape, cx: &mut ViewContext<Self>) {
 1706        self.cursor_shape = cursor_shape;
 1707
 1708        // Disrupt blink for immediate user feedback that the cursor shape has changed
 1709        self.blink_manager.update(cx, BlinkManager::show_cursor);
 1710
 1711        cx.notify();
 1712    }
 1713
 1714    pub fn set_current_line_highlight(
 1715        &mut self,
 1716        current_line_highlight: Option<CurrentLineHighlight>,
 1717    ) {
 1718        self.current_line_highlight = current_line_highlight;
 1719    }
 1720
 1721    pub fn set_collapse_matches(&mut self, collapse_matches: bool) {
 1722        self.collapse_matches = collapse_matches;
 1723    }
 1724
 1725    pub fn register_buffers_with_language_servers(&mut self, cx: &mut ViewContext<Self>) {
 1726        let buffers = self.buffer.read(cx).all_buffers();
 1727        let Some(lsp_store) = self.lsp_store(cx) else {
 1728            return;
 1729        };
 1730        lsp_store.update(cx, |lsp_store, cx| {
 1731            for buffer in buffers {
 1732                self.registered_buffers
 1733                    .entry(buffer.read(cx).remote_id())
 1734                    .or_insert_with(|| {
 1735                        lsp_store.register_buffer_with_language_servers(&buffer, cx)
 1736                    });
 1737            }
 1738        })
 1739    }
 1740
 1741    pub fn range_for_match<T: std::marker::Copy>(&self, range: &Range<T>) -> Range<T> {
 1742        if self.collapse_matches {
 1743            return range.start..range.start;
 1744        }
 1745        range.clone()
 1746    }
 1747
 1748    pub fn set_clip_at_line_ends(&mut self, clip: bool, cx: &mut ViewContext<Self>) {
 1749        if self.display_map.read(cx).clip_at_line_ends != clip {
 1750            self.display_map
 1751                .update(cx, |map, _| map.clip_at_line_ends = clip);
 1752        }
 1753    }
 1754
 1755    pub fn set_input_enabled(&mut self, input_enabled: bool) {
 1756        self.input_enabled = input_enabled;
 1757    }
 1758
 1759    pub fn set_inline_completions_enabled(&mut self, enabled: bool, cx: &mut ViewContext<Self>) {
 1760        self.enable_inline_completions = enabled;
 1761        if !self.enable_inline_completions {
 1762            self.take_active_inline_completion(cx);
 1763            cx.notify();
 1764        }
 1765    }
 1766
 1767    pub fn set_menu_inline_completions_policy(&mut self, value: MenuInlineCompletionsPolicy) {
 1768        self.menu_inline_completions_policy = value;
 1769    }
 1770
 1771    pub fn set_autoindent(&mut self, autoindent: bool) {
 1772        if autoindent {
 1773            self.autoindent_mode = Some(AutoindentMode::EachLine);
 1774        } else {
 1775            self.autoindent_mode = None;
 1776        }
 1777    }
 1778
 1779    pub fn read_only(&self, cx: &AppContext) -> bool {
 1780        self.read_only || self.buffer.read(cx).read_only()
 1781    }
 1782
 1783    pub fn set_read_only(&mut self, read_only: bool) {
 1784        self.read_only = read_only;
 1785    }
 1786
 1787    pub fn set_use_autoclose(&mut self, autoclose: bool) {
 1788        self.use_autoclose = autoclose;
 1789    }
 1790
 1791    pub fn set_use_auto_surround(&mut self, auto_surround: bool) {
 1792        self.use_auto_surround = auto_surround;
 1793    }
 1794
 1795    pub fn set_auto_replace_emoji_shortcode(&mut self, auto_replace: bool) {
 1796        self.auto_replace_emoji_shortcode = auto_replace;
 1797    }
 1798
 1799    pub fn toggle_inline_completions(
 1800        &mut self,
 1801        _: &ToggleInlineCompletions,
 1802        cx: &mut ViewContext<Self>,
 1803    ) {
 1804        if self.show_inline_completions_override.is_some() {
 1805            self.set_show_inline_completions(None, cx);
 1806        } else {
 1807            let cursor = self.selections.newest_anchor().head();
 1808            if let Some((buffer, cursor_buffer_position)) =
 1809                self.buffer.read(cx).text_anchor_for_position(cursor, cx)
 1810            {
 1811                let show_inline_completions =
 1812                    !self.should_show_inline_completions(&buffer, cursor_buffer_position, cx);
 1813                self.set_show_inline_completions(Some(show_inline_completions), cx);
 1814            }
 1815        }
 1816    }
 1817
 1818    pub fn set_show_inline_completions(
 1819        &mut self,
 1820        show_inline_completions: Option<bool>,
 1821        cx: &mut ViewContext<Self>,
 1822    ) {
 1823        self.show_inline_completions_override = show_inline_completions;
 1824        self.refresh_inline_completion(false, true, cx);
 1825    }
 1826
 1827    pub fn inline_completions_enabled(&self, cx: &AppContext) -> bool {
 1828        let cursor = self.selections.newest_anchor().head();
 1829        if let Some((buffer, buffer_position)) =
 1830            self.buffer.read(cx).text_anchor_for_position(cursor, cx)
 1831        {
 1832            self.should_show_inline_completions(&buffer, buffer_position, cx)
 1833        } else {
 1834            false
 1835        }
 1836    }
 1837
 1838    fn should_show_inline_completions(
 1839        &self,
 1840        buffer: &Model<Buffer>,
 1841        buffer_position: language::Anchor,
 1842        cx: &AppContext,
 1843    ) -> bool {
 1844        if !self.snippet_stack.is_empty() {
 1845            return false;
 1846        }
 1847
 1848        if self.inline_completions_disabled_in_scope(buffer, buffer_position, cx) {
 1849            return false;
 1850        }
 1851
 1852        if let Some(provider) = self.inline_completion_provider() {
 1853            if let Some(show_inline_completions) = self.show_inline_completions_override {
 1854                show_inline_completions
 1855            } else {
 1856                self.mode == EditorMode::Full && provider.is_enabled(buffer, buffer_position, cx)
 1857            }
 1858        } else {
 1859            false
 1860        }
 1861    }
 1862
 1863    fn inline_completions_disabled_in_scope(
 1864        &self,
 1865        buffer: &Model<Buffer>,
 1866        buffer_position: language::Anchor,
 1867        cx: &AppContext,
 1868    ) -> bool {
 1869        let snapshot = buffer.read(cx).snapshot();
 1870        let settings = snapshot.settings_at(buffer_position, cx);
 1871
 1872        let Some(scope) = snapshot.language_scope_at(buffer_position) else {
 1873            return false;
 1874        };
 1875
 1876        scope.override_name().map_or(false, |scope_name| {
 1877            settings
 1878                .inline_completions_disabled_in
 1879                .iter()
 1880                .any(|s| s == scope_name)
 1881        })
 1882    }
 1883
 1884    pub fn set_use_modal_editing(&mut self, to: bool) {
 1885        self.use_modal_editing = to;
 1886    }
 1887
 1888    pub fn use_modal_editing(&self) -> bool {
 1889        self.use_modal_editing
 1890    }
 1891
 1892    fn selections_did_change(
 1893        &mut self,
 1894        local: bool,
 1895        old_cursor_position: &Anchor,
 1896        show_completions: bool,
 1897        cx: &mut ViewContext<Self>,
 1898    ) {
 1899        cx.invalidate_character_coordinates();
 1900
 1901        // Copy selections to primary selection buffer
 1902        #[cfg(any(target_os = "linux", target_os = "freebsd"))]
 1903        if local {
 1904            let selections = self.selections.all::<usize>(cx);
 1905            let buffer_handle = self.buffer.read(cx).read(cx);
 1906
 1907            let mut text = String::new();
 1908            for (index, selection) in selections.iter().enumerate() {
 1909                let text_for_selection = buffer_handle
 1910                    .text_for_range(selection.start..selection.end)
 1911                    .collect::<String>();
 1912
 1913                text.push_str(&text_for_selection);
 1914                if index != selections.len() - 1 {
 1915                    text.push('\n');
 1916                }
 1917            }
 1918
 1919            if !text.is_empty() {
 1920                cx.write_to_primary(ClipboardItem::new_string(text));
 1921            }
 1922        }
 1923
 1924        if self.focus_handle.is_focused(cx) && self.leader_peer_id.is_none() {
 1925            self.buffer.update(cx, |buffer, cx| {
 1926                buffer.set_active_selections(
 1927                    &self.selections.disjoint_anchors(),
 1928                    self.selections.line_mode,
 1929                    self.cursor_shape,
 1930                    cx,
 1931                )
 1932            });
 1933        }
 1934        let display_map = self
 1935            .display_map
 1936            .update(cx, |display_map, cx| display_map.snapshot(cx));
 1937        let buffer = &display_map.buffer_snapshot;
 1938        self.add_selections_state = None;
 1939        self.select_next_state = None;
 1940        self.select_prev_state = None;
 1941        self.select_larger_syntax_node_stack.clear();
 1942        self.invalidate_autoclose_regions(&self.selections.disjoint_anchors(), buffer);
 1943        self.snippet_stack
 1944            .invalidate(&self.selections.disjoint_anchors(), buffer);
 1945        self.take_rename(false, cx);
 1946
 1947        let new_cursor_position = self.selections.newest_anchor().head();
 1948
 1949        self.push_to_nav_history(
 1950            *old_cursor_position,
 1951            Some(new_cursor_position.to_point(buffer)),
 1952            cx,
 1953        );
 1954
 1955        if local {
 1956            let new_cursor_position = self.selections.newest_anchor().head();
 1957            let mut context_menu = self.context_menu.borrow_mut();
 1958            let completion_menu = match context_menu.as_ref() {
 1959                Some(CodeContextMenu::Completions(menu)) => Some(menu),
 1960                _ => {
 1961                    *context_menu = None;
 1962                    None
 1963                }
 1964            };
 1965
 1966            if let Some(completion_menu) = completion_menu {
 1967                let cursor_position = new_cursor_position.to_offset(buffer);
 1968                let (word_range, kind) =
 1969                    buffer.surrounding_word(completion_menu.initial_position, true);
 1970                if kind == Some(CharKind::Word)
 1971                    && word_range.to_inclusive().contains(&cursor_position)
 1972                {
 1973                    let mut completion_menu = completion_menu.clone();
 1974                    drop(context_menu);
 1975
 1976                    let query = Self::completion_query(buffer, cursor_position);
 1977                    cx.spawn(move |this, mut cx| async move {
 1978                        completion_menu
 1979                            .filter(query.as_deref(), cx.background_executor().clone())
 1980                            .await;
 1981
 1982                        this.update(&mut cx, |this, cx| {
 1983                            let mut context_menu = this.context_menu.borrow_mut();
 1984                            let Some(CodeContextMenu::Completions(menu)) = context_menu.as_ref()
 1985                            else {
 1986                                return;
 1987                            };
 1988
 1989                            if menu.id > completion_menu.id {
 1990                                return;
 1991                            }
 1992
 1993                            *context_menu = Some(CodeContextMenu::Completions(completion_menu));
 1994                            drop(context_menu);
 1995                            cx.notify();
 1996                        })
 1997                    })
 1998                    .detach();
 1999
 2000                    if show_completions {
 2001                        self.show_completions(&ShowCompletions { trigger: None }, cx);
 2002                    }
 2003                } else {
 2004                    drop(context_menu);
 2005                    self.hide_context_menu(cx);
 2006                }
 2007            } else {
 2008                drop(context_menu);
 2009            }
 2010
 2011            hide_hover(self, cx);
 2012
 2013            if old_cursor_position.to_display_point(&display_map).row()
 2014                != new_cursor_position.to_display_point(&display_map).row()
 2015            {
 2016                self.available_code_actions.take();
 2017            }
 2018            self.refresh_code_actions(cx);
 2019            self.refresh_document_highlights(cx);
 2020            refresh_matching_bracket_highlights(self, cx);
 2021            self.update_visible_inline_completion(cx);
 2022            linked_editing_ranges::refresh_linked_ranges(self, cx);
 2023            if self.git_blame_inline_enabled {
 2024                self.start_inline_blame_timer(cx);
 2025            }
 2026        }
 2027
 2028        self.blink_manager.update(cx, BlinkManager::pause_blinking);
 2029        cx.emit(EditorEvent::SelectionsChanged { local });
 2030
 2031        if self.selections.disjoint_anchors().len() == 1 {
 2032            cx.emit(SearchEvent::ActiveMatchChanged)
 2033        }
 2034        cx.notify();
 2035    }
 2036
 2037    pub fn change_selections<R>(
 2038        &mut self,
 2039        autoscroll: Option<Autoscroll>,
 2040        cx: &mut ViewContext<Self>,
 2041        change: impl FnOnce(&mut MutableSelectionsCollection<'_>) -> R,
 2042    ) -> R {
 2043        self.change_selections_inner(autoscroll, true, cx, change)
 2044    }
 2045
 2046    pub fn change_selections_inner<R>(
 2047        &mut self,
 2048        autoscroll: Option<Autoscroll>,
 2049        request_completions: bool,
 2050        cx: &mut ViewContext<Self>,
 2051        change: impl FnOnce(&mut MutableSelectionsCollection<'_>) -> R,
 2052    ) -> R {
 2053        let old_cursor_position = self.selections.newest_anchor().head();
 2054        self.push_to_selection_history();
 2055
 2056        let (changed, result) = self.selections.change_with(cx, change);
 2057
 2058        if changed {
 2059            if let Some(autoscroll) = autoscroll {
 2060                self.request_autoscroll(autoscroll, cx);
 2061            }
 2062            self.selections_did_change(true, &old_cursor_position, request_completions, cx);
 2063
 2064            if self.should_open_signature_help_automatically(
 2065                &old_cursor_position,
 2066                self.signature_help_state.backspace_pressed(),
 2067                cx,
 2068            ) {
 2069                self.show_signature_help(&ShowSignatureHelp, cx);
 2070            }
 2071            self.signature_help_state.set_backspace_pressed(false);
 2072        }
 2073
 2074        result
 2075    }
 2076
 2077    pub fn edit<I, S, T>(&mut self, edits: I, cx: &mut ViewContext<Self>)
 2078    where
 2079        I: IntoIterator<Item = (Range<S>, T)>,
 2080        S: ToOffset,
 2081        T: Into<Arc<str>>,
 2082    {
 2083        if self.read_only(cx) {
 2084            return;
 2085        }
 2086
 2087        self.buffer
 2088            .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
 2089    }
 2090
 2091    pub fn edit_with_autoindent<I, S, T>(&mut self, edits: I, cx: &mut ViewContext<Self>)
 2092    where
 2093        I: IntoIterator<Item = (Range<S>, T)>,
 2094        S: ToOffset,
 2095        T: Into<Arc<str>>,
 2096    {
 2097        if self.read_only(cx) {
 2098            return;
 2099        }
 2100
 2101        self.buffer.update(cx, |buffer, cx| {
 2102            buffer.edit(edits, self.autoindent_mode.clone(), cx)
 2103        });
 2104    }
 2105
 2106    pub fn edit_with_block_indent<I, S, T>(
 2107        &mut self,
 2108        edits: I,
 2109        original_indent_columns: Vec<u32>,
 2110        cx: &mut ViewContext<Self>,
 2111    ) where
 2112        I: IntoIterator<Item = (Range<S>, T)>,
 2113        S: ToOffset,
 2114        T: Into<Arc<str>>,
 2115    {
 2116        if self.read_only(cx) {
 2117            return;
 2118        }
 2119
 2120        self.buffer.update(cx, |buffer, cx| {
 2121            buffer.edit(
 2122                edits,
 2123                Some(AutoindentMode::Block {
 2124                    original_indent_columns,
 2125                }),
 2126                cx,
 2127            )
 2128        });
 2129    }
 2130
 2131    fn select(&mut self, phase: SelectPhase, cx: &mut ViewContext<Self>) {
 2132        self.hide_context_menu(cx);
 2133
 2134        match phase {
 2135            SelectPhase::Begin {
 2136                position,
 2137                add,
 2138                click_count,
 2139            } => self.begin_selection(position, add, click_count, cx),
 2140            SelectPhase::BeginColumnar {
 2141                position,
 2142                goal_column,
 2143                reset,
 2144            } => self.begin_columnar_selection(position, goal_column, reset, cx),
 2145            SelectPhase::Extend {
 2146                position,
 2147                click_count,
 2148            } => self.extend_selection(position, click_count, cx),
 2149            SelectPhase::Update {
 2150                position,
 2151                goal_column,
 2152                scroll_delta,
 2153            } => self.update_selection(position, goal_column, scroll_delta, cx),
 2154            SelectPhase::End => self.end_selection(cx),
 2155        }
 2156    }
 2157
 2158    fn extend_selection(
 2159        &mut self,
 2160        position: DisplayPoint,
 2161        click_count: usize,
 2162        cx: &mut ViewContext<Self>,
 2163    ) {
 2164        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 2165        let tail = self.selections.newest::<usize>(cx).tail();
 2166        self.begin_selection(position, false, click_count, cx);
 2167
 2168        let position = position.to_offset(&display_map, Bias::Left);
 2169        let tail_anchor = display_map.buffer_snapshot.anchor_before(tail);
 2170
 2171        let mut pending_selection = self
 2172            .selections
 2173            .pending_anchor()
 2174            .expect("extend_selection not called with pending selection");
 2175        if position >= tail {
 2176            pending_selection.start = tail_anchor;
 2177        } else {
 2178            pending_selection.end = tail_anchor;
 2179            pending_selection.reversed = true;
 2180        }
 2181
 2182        let mut pending_mode = self.selections.pending_mode().unwrap();
 2183        match &mut pending_mode {
 2184            SelectMode::Word(range) | SelectMode::Line(range) => *range = tail_anchor..tail_anchor,
 2185            _ => {}
 2186        }
 2187
 2188        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 2189            s.set_pending(pending_selection, pending_mode)
 2190        });
 2191    }
 2192
 2193    fn begin_selection(
 2194        &mut self,
 2195        position: DisplayPoint,
 2196        add: bool,
 2197        click_count: usize,
 2198        cx: &mut ViewContext<Self>,
 2199    ) {
 2200        if !self.focus_handle.is_focused(cx) {
 2201            self.last_focused_descendant = None;
 2202            cx.focus(&self.focus_handle);
 2203        }
 2204
 2205        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 2206        let buffer = &display_map.buffer_snapshot;
 2207        let newest_selection = self.selections.newest_anchor().clone();
 2208        let position = display_map.clip_point(position, Bias::Left);
 2209
 2210        let start;
 2211        let end;
 2212        let mode;
 2213        let mut auto_scroll;
 2214        match click_count {
 2215            1 => {
 2216                start = buffer.anchor_before(position.to_point(&display_map));
 2217                end = start;
 2218                mode = SelectMode::Character;
 2219                auto_scroll = true;
 2220            }
 2221            2 => {
 2222                let range = movement::surrounding_word(&display_map, position);
 2223                start = buffer.anchor_before(range.start.to_point(&display_map));
 2224                end = buffer.anchor_before(range.end.to_point(&display_map));
 2225                mode = SelectMode::Word(start..end);
 2226                auto_scroll = true;
 2227            }
 2228            3 => {
 2229                let position = display_map
 2230                    .clip_point(position, Bias::Left)
 2231                    .to_point(&display_map);
 2232                let line_start = display_map.prev_line_boundary(position).0;
 2233                let next_line_start = buffer.clip_point(
 2234                    display_map.next_line_boundary(position).0 + Point::new(1, 0),
 2235                    Bias::Left,
 2236                );
 2237                start = buffer.anchor_before(line_start);
 2238                end = buffer.anchor_before(next_line_start);
 2239                mode = SelectMode::Line(start..end);
 2240                auto_scroll = true;
 2241            }
 2242            _ => {
 2243                start = buffer.anchor_before(0);
 2244                end = buffer.anchor_before(buffer.len());
 2245                mode = SelectMode::All;
 2246                auto_scroll = false;
 2247            }
 2248        }
 2249        auto_scroll &= EditorSettings::get_global(cx).autoscroll_on_clicks;
 2250
 2251        let point_to_delete: Option<usize> = {
 2252            let selected_points: Vec<Selection<Point>> =
 2253                self.selections.disjoint_in_range(start..end, cx);
 2254
 2255            if !add || click_count > 1 {
 2256                None
 2257            } else if !selected_points.is_empty() {
 2258                Some(selected_points[0].id)
 2259            } else {
 2260                let clicked_point_already_selected =
 2261                    self.selections.disjoint.iter().find(|selection| {
 2262                        selection.start.to_point(buffer) == start.to_point(buffer)
 2263                            || selection.end.to_point(buffer) == end.to_point(buffer)
 2264                    });
 2265
 2266                clicked_point_already_selected.map(|selection| selection.id)
 2267            }
 2268        };
 2269
 2270        let selections_count = self.selections.count();
 2271
 2272        self.change_selections(auto_scroll.then(Autoscroll::newest), cx, |s| {
 2273            if let Some(point_to_delete) = point_to_delete {
 2274                s.delete(point_to_delete);
 2275
 2276                if selections_count == 1 {
 2277                    s.set_pending_anchor_range(start..end, mode);
 2278                }
 2279            } else {
 2280                if !add {
 2281                    s.clear_disjoint();
 2282                } else if click_count > 1 {
 2283                    s.delete(newest_selection.id)
 2284                }
 2285
 2286                s.set_pending_anchor_range(start..end, mode);
 2287            }
 2288        });
 2289    }
 2290
 2291    fn begin_columnar_selection(
 2292        &mut self,
 2293        position: DisplayPoint,
 2294        goal_column: u32,
 2295        reset: bool,
 2296        cx: &mut ViewContext<Self>,
 2297    ) {
 2298        if !self.focus_handle.is_focused(cx) {
 2299            self.last_focused_descendant = None;
 2300            cx.focus(&self.focus_handle);
 2301        }
 2302
 2303        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 2304
 2305        if reset {
 2306            let pointer_position = display_map
 2307                .buffer_snapshot
 2308                .anchor_before(position.to_point(&display_map));
 2309
 2310            self.change_selections(Some(Autoscroll::newest()), cx, |s| {
 2311                s.clear_disjoint();
 2312                s.set_pending_anchor_range(
 2313                    pointer_position..pointer_position,
 2314                    SelectMode::Character,
 2315                );
 2316            });
 2317        }
 2318
 2319        let tail = self.selections.newest::<Point>(cx).tail();
 2320        self.columnar_selection_tail = Some(display_map.buffer_snapshot.anchor_before(tail));
 2321
 2322        if !reset {
 2323            self.select_columns(
 2324                tail.to_display_point(&display_map),
 2325                position,
 2326                goal_column,
 2327                &display_map,
 2328                cx,
 2329            );
 2330        }
 2331    }
 2332
 2333    fn update_selection(
 2334        &mut self,
 2335        position: DisplayPoint,
 2336        goal_column: u32,
 2337        scroll_delta: gpui::Point<f32>,
 2338        cx: &mut ViewContext<Self>,
 2339    ) {
 2340        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 2341
 2342        if let Some(tail) = self.columnar_selection_tail.as_ref() {
 2343            let tail = tail.to_display_point(&display_map);
 2344            self.select_columns(tail, position, goal_column, &display_map, cx);
 2345        } else if let Some(mut pending) = self.selections.pending_anchor() {
 2346            let buffer = self.buffer.read(cx).snapshot(cx);
 2347            let head;
 2348            let tail;
 2349            let mode = self.selections.pending_mode().unwrap();
 2350            match &mode {
 2351                SelectMode::Character => {
 2352                    head = position.to_point(&display_map);
 2353                    tail = pending.tail().to_point(&buffer);
 2354                }
 2355                SelectMode::Word(original_range) => {
 2356                    let original_display_range = original_range.start.to_display_point(&display_map)
 2357                        ..original_range.end.to_display_point(&display_map);
 2358                    let original_buffer_range = original_display_range.start.to_point(&display_map)
 2359                        ..original_display_range.end.to_point(&display_map);
 2360                    if movement::is_inside_word(&display_map, position)
 2361                        || original_display_range.contains(&position)
 2362                    {
 2363                        let word_range = movement::surrounding_word(&display_map, position);
 2364                        if word_range.start < original_display_range.start {
 2365                            head = word_range.start.to_point(&display_map);
 2366                        } else {
 2367                            head = word_range.end.to_point(&display_map);
 2368                        }
 2369                    } else {
 2370                        head = position.to_point(&display_map);
 2371                    }
 2372
 2373                    if head <= original_buffer_range.start {
 2374                        tail = original_buffer_range.end;
 2375                    } else {
 2376                        tail = original_buffer_range.start;
 2377                    }
 2378                }
 2379                SelectMode::Line(original_range) => {
 2380                    let original_range = original_range.to_point(&display_map.buffer_snapshot);
 2381
 2382                    let position = display_map
 2383                        .clip_point(position, Bias::Left)
 2384                        .to_point(&display_map);
 2385                    let line_start = display_map.prev_line_boundary(position).0;
 2386                    let next_line_start = buffer.clip_point(
 2387                        display_map.next_line_boundary(position).0 + Point::new(1, 0),
 2388                        Bias::Left,
 2389                    );
 2390
 2391                    if line_start < original_range.start {
 2392                        head = line_start
 2393                    } else {
 2394                        head = next_line_start
 2395                    }
 2396
 2397                    if head <= original_range.start {
 2398                        tail = original_range.end;
 2399                    } else {
 2400                        tail = original_range.start;
 2401                    }
 2402                }
 2403                SelectMode::All => {
 2404                    return;
 2405                }
 2406            };
 2407
 2408            if head < tail {
 2409                pending.start = buffer.anchor_before(head);
 2410                pending.end = buffer.anchor_before(tail);
 2411                pending.reversed = true;
 2412            } else {
 2413                pending.start = buffer.anchor_before(tail);
 2414                pending.end = buffer.anchor_before(head);
 2415                pending.reversed = false;
 2416            }
 2417
 2418            self.change_selections(None, cx, |s| {
 2419                s.set_pending(pending, mode);
 2420            });
 2421        } else {
 2422            log::error!("update_selection dispatched with no pending selection");
 2423            return;
 2424        }
 2425
 2426        self.apply_scroll_delta(scroll_delta, cx);
 2427        cx.notify();
 2428    }
 2429
 2430    fn end_selection(&mut self, cx: &mut ViewContext<Self>) {
 2431        self.columnar_selection_tail.take();
 2432        if self.selections.pending_anchor().is_some() {
 2433            let selections = self.selections.all::<usize>(cx);
 2434            self.change_selections(None, cx, |s| {
 2435                s.select(selections);
 2436                s.clear_pending();
 2437            });
 2438        }
 2439    }
 2440
 2441    fn select_columns(
 2442        &mut self,
 2443        tail: DisplayPoint,
 2444        head: DisplayPoint,
 2445        goal_column: u32,
 2446        display_map: &DisplaySnapshot,
 2447        cx: &mut ViewContext<Self>,
 2448    ) {
 2449        let start_row = cmp::min(tail.row(), head.row());
 2450        let end_row = cmp::max(tail.row(), head.row());
 2451        let start_column = cmp::min(tail.column(), goal_column);
 2452        let end_column = cmp::max(tail.column(), goal_column);
 2453        let reversed = start_column < tail.column();
 2454
 2455        let selection_ranges = (start_row.0..=end_row.0)
 2456            .map(DisplayRow)
 2457            .filter_map(|row| {
 2458                if start_column <= display_map.line_len(row) && !display_map.is_block_line(row) {
 2459                    let start = display_map
 2460                        .clip_point(DisplayPoint::new(row, start_column), Bias::Left)
 2461                        .to_point(display_map);
 2462                    let end = display_map
 2463                        .clip_point(DisplayPoint::new(row, end_column), Bias::Right)
 2464                        .to_point(display_map);
 2465                    if reversed {
 2466                        Some(end..start)
 2467                    } else {
 2468                        Some(start..end)
 2469                    }
 2470                } else {
 2471                    None
 2472                }
 2473            })
 2474            .collect::<Vec<_>>();
 2475
 2476        self.change_selections(None, cx, |s| {
 2477            s.select_ranges(selection_ranges);
 2478        });
 2479        cx.notify();
 2480    }
 2481
 2482    pub fn has_pending_nonempty_selection(&self) -> bool {
 2483        let pending_nonempty_selection = match self.selections.pending_anchor() {
 2484            Some(Selection { start, end, .. }) => start != end,
 2485            None => false,
 2486        };
 2487
 2488        pending_nonempty_selection
 2489            || (self.columnar_selection_tail.is_some() && self.selections.disjoint.len() > 1)
 2490    }
 2491
 2492    pub fn has_pending_selection(&self) -> bool {
 2493        self.selections.pending_anchor().is_some() || self.columnar_selection_tail.is_some()
 2494    }
 2495
 2496    pub fn cancel(&mut self, _: &Cancel, cx: &mut ViewContext<Self>) {
 2497        self.selection_mark_mode = false;
 2498
 2499        if self.clear_expanded_diff_hunks(cx) {
 2500            cx.notify();
 2501            return;
 2502        }
 2503        if self.dismiss_menus_and_popups(true, cx) {
 2504            return;
 2505        }
 2506
 2507        if self.mode == EditorMode::Full
 2508            && self.change_selections(Some(Autoscroll::fit()), cx, |s| s.try_cancel())
 2509        {
 2510            return;
 2511        }
 2512
 2513        cx.propagate();
 2514    }
 2515
 2516    pub fn dismiss_menus_and_popups(
 2517        &mut self,
 2518        should_report_inline_completion_event: bool,
 2519        cx: &mut ViewContext<Self>,
 2520    ) -> bool {
 2521        if self.take_rename(false, cx).is_some() {
 2522            return true;
 2523        }
 2524
 2525        if hide_hover(self, cx) {
 2526            return true;
 2527        }
 2528
 2529        if self.hide_signature_help(cx, SignatureHelpHiddenBy::Escape) {
 2530            return true;
 2531        }
 2532
 2533        if self.hide_context_menu(cx).is_some() {
 2534            if self.show_inline_completions_in_menu(cx) && self.has_active_inline_completion() {
 2535                self.update_visible_inline_completion(cx);
 2536            }
 2537            return true;
 2538        }
 2539
 2540        if self.mouse_context_menu.take().is_some() {
 2541            return true;
 2542        }
 2543
 2544        if self.discard_inline_completion(should_report_inline_completion_event, cx) {
 2545            return true;
 2546        }
 2547
 2548        if self.snippet_stack.pop().is_some() {
 2549            return true;
 2550        }
 2551
 2552        if self.mode == EditorMode::Full && self.active_diagnostics.is_some() {
 2553            self.dismiss_diagnostics(cx);
 2554            return true;
 2555        }
 2556
 2557        false
 2558    }
 2559
 2560    fn linked_editing_ranges_for(
 2561        &self,
 2562        selection: Range<text::Anchor>,
 2563        cx: &AppContext,
 2564    ) -> Option<HashMap<Model<Buffer>, Vec<Range<text::Anchor>>>> {
 2565        if self.linked_edit_ranges.is_empty() {
 2566            return None;
 2567        }
 2568        let ((base_range, linked_ranges), buffer_snapshot, buffer) =
 2569            selection.end.buffer_id.and_then(|end_buffer_id| {
 2570                if selection.start.buffer_id != Some(end_buffer_id) {
 2571                    return None;
 2572                }
 2573                let buffer = self.buffer.read(cx).buffer(end_buffer_id)?;
 2574                let snapshot = buffer.read(cx).snapshot();
 2575                self.linked_edit_ranges
 2576                    .get(end_buffer_id, selection.start..selection.end, &snapshot)
 2577                    .map(|ranges| (ranges, snapshot, buffer))
 2578            })?;
 2579        use text::ToOffset as TO;
 2580        // find offset from the start of current range to current cursor position
 2581        let start_byte_offset = TO::to_offset(&base_range.start, &buffer_snapshot);
 2582
 2583        let start_offset = TO::to_offset(&selection.start, &buffer_snapshot);
 2584        let start_difference = start_offset - start_byte_offset;
 2585        let end_offset = TO::to_offset(&selection.end, &buffer_snapshot);
 2586        let end_difference = end_offset - start_byte_offset;
 2587        // Current range has associated linked ranges.
 2588        let mut linked_edits = HashMap::<_, Vec<_>>::default();
 2589        for range in linked_ranges.iter() {
 2590            let start_offset = TO::to_offset(&range.start, &buffer_snapshot);
 2591            let end_offset = start_offset + end_difference;
 2592            let start_offset = start_offset + start_difference;
 2593            if start_offset > buffer_snapshot.len() || end_offset > buffer_snapshot.len() {
 2594                continue;
 2595            }
 2596            if self.selections.disjoint_anchor_ranges().any(|s| {
 2597                if s.start.buffer_id != selection.start.buffer_id
 2598                    || s.end.buffer_id != selection.end.buffer_id
 2599                {
 2600                    return false;
 2601                }
 2602                TO::to_offset(&s.start.text_anchor, &buffer_snapshot) <= end_offset
 2603                    && TO::to_offset(&s.end.text_anchor, &buffer_snapshot) >= start_offset
 2604            }) {
 2605                continue;
 2606            }
 2607            let start = buffer_snapshot.anchor_after(start_offset);
 2608            let end = buffer_snapshot.anchor_after(end_offset);
 2609            linked_edits
 2610                .entry(buffer.clone())
 2611                .or_default()
 2612                .push(start..end);
 2613        }
 2614        Some(linked_edits)
 2615    }
 2616
 2617    pub fn handle_input(&mut self, text: &str, cx: &mut ViewContext<Self>) {
 2618        let text: Arc<str> = text.into();
 2619
 2620        if self.read_only(cx) {
 2621            return;
 2622        }
 2623
 2624        let selections = self.selections.all_adjusted(cx);
 2625        let mut bracket_inserted = false;
 2626        let mut edits = Vec::new();
 2627        let mut linked_edits = HashMap::<_, Vec<_>>::default();
 2628        let mut new_selections = Vec::with_capacity(selections.len());
 2629        let mut new_autoclose_regions = Vec::new();
 2630        let snapshot = self.buffer.read(cx).read(cx);
 2631
 2632        for (selection, autoclose_region) in
 2633            self.selections_with_autoclose_regions(selections, &snapshot)
 2634        {
 2635            if let Some(scope) = snapshot.language_scope_at(selection.head()) {
 2636                // Determine if the inserted text matches the opening or closing
 2637                // bracket of any of this language's bracket pairs.
 2638                let mut bracket_pair = None;
 2639                let mut is_bracket_pair_start = false;
 2640                let mut is_bracket_pair_end = false;
 2641                if !text.is_empty() {
 2642                    // `text` can be empty when a user is using IME (e.g. Chinese Wubi Simplified)
 2643                    //  and they are removing the character that triggered IME popup.
 2644                    for (pair, enabled) in scope.brackets() {
 2645                        if !pair.close && !pair.surround {
 2646                            continue;
 2647                        }
 2648
 2649                        if enabled && pair.start.ends_with(text.as_ref()) {
 2650                            let prefix_len = pair.start.len() - text.len();
 2651                            let preceding_text_matches_prefix = prefix_len == 0
 2652                                || (selection.start.column >= (prefix_len as u32)
 2653                                    && snapshot.contains_str_at(
 2654                                        Point::new(
 2655                                            selection.start.row,
 2656                                            selection.start.column - (prefix_len as u32),
 2657                                        ),
 2658                                        &pair.start[..prefix_len],
 2659                                    ));
 2660                            if preceding_text_matches_prefix {
 2661                                bracket_pair = Some(pair.clone());
 2662                                is_bracket_pair_start = true;
 2663                                break;
 2664                            }
 2665                        }
 2666                        if pair.end.as_str() == text.as_ref() {
 2667                            bracket_pair = Some(pair.clone());
 2668                            is_bracket_pair_end = true;
 2669                            break;
 2670                        }
 2671                    }
 2672                }
 2673
 2674                if let Some(bracket_pair) = bracket_pair {
 2675                    let snapshot_settings = snapshot.settings_at(selection.start, cx);
 2676                    let autoclose = self.use_autoclose && snapshot_settings.use_autoclose;
 2677                    let auto_surround =
 2678                        self.use_auto_surround && snapshot_settings.use_auto_surround;
 2679                    if selection.is_empty() {
 2680                        if is_bracket_pair_start {
 2681                            // If the inserted text is a suffix of an opening bracket and the
 2682                            // selection is preceded by the rest of the opening bracket, then
 2683                            // insert the closing bracket.
 2684                            let following_text_allows_autoclose = snapshot
 2685                                .chars_at(selection.start)
 2686                                .next()
 2687                                .map_or(true, |c| scope.should_autoclose_before(c));
 2688
 2689                            let is_closing_quote = if bracket_pair.end == bracket_pair.start
 2690                                && bracket_pair.start.len() == 1
 2691                            {
 2692                                let target = bracket_pair.start.chars().next().unwrap();
 2693                                let current_line_count = snapshot
 2694                                    .reversed_chars_at(selection.start)
 2695                                    .take_while(|&c| c != '\n')
 2696                                    .filter(|&c| c == target)
 2697                                    .count();
 2698                                current_line_count % 2 == 1
 2699                            } else {
 2700                                false
 2701                            };
 2702
 2703                            if autoclose
 2704                                && bracket_pair.close
 2705                                && following_text_allows_autoclose
 2706                                && !is_closing_quote
 2707                            {
 2708                                let anchor = snapshot.anchor_before(selection.end);
 2709                                new_selections.push((selection.map(|_| anchor), text.len()));
 2710                                new_autoclose_regions.push((
 2711                                    anchor,
 2712                                    text.len(),
 2713                                    selection.id,
 2714                                    bracket_pair.clone(),
 2715                                ));
 2716                                edits.push((
 2717                                    selection.range(),
 2718                                    format!("{}{}", text, bracket_pair.end).into(),
 2719                                ));
 2720                                bracket_inserted = true;
 2721                                continue;
 2722                            }
 2723                        }
 2724
 2725                        if let Some(region) = autoclose_region {
 2726                            // If the selection is followed by an auto-inserted closing bracket,
 2727                            // then don't insert that closing bracket again; just move the selection
 2728                            // past the closing bracket.
 2729                            let should_skip = selection.end == region.range.end.to_point(&snapshot)
 2730                                && text.as_ref() == region.pair.end.as_str();
 2731                            if should_skip {
 2732                                let anchor = snapshot.anchor_after(selection.end);
 2733                                new_selections
 2734                                    .push((selection.map(|_| anchor), region.pair.end.len()));
 2735                                continue;
 2736                            }
 2737                        }
 2738
 2739                        let always_treat_brackets_as_autoclosed = snapshot
 2740                            .settings_at(selection.start, cx)
 2741                            .always_treat_brackets_as_autoclosed;
 2742                        if always_treat_brackets_as_autoclosed
 2743                            && is_bracket_pair_end
 2744                            && snapshot.contains_str_at(selection.end, text.as_ref())
 2745                        {
 2746                            // Otherwise, when `always_treat_brackets_as_autoclosed` is set to `true
 2747                            // and the inserted text is a closing bracket and the selection is followed
 2748                            // by the closing bracket then move the selection past the closing bracket.
 2749                            let anchor = snapshot.anchor_after(selection.end);
 2750                            new_selections.push((selection.map(|_| anchor), text.len()));
 2751                            continue;
 2752                        }
 2753                    }
 2754                    // If an opening bracket is 1 character long and is typed while
 2755                    // text is selected, then surround that text with the bracket pair.
 2756                    else if auto_surround
 2757                        && bracket_pair.surround
 2758                        && is_bracket_pair_start
 2759                        && bracket_pair.start.chars().count() == 1
 2760                    {
 2761                        edits.push((selection.start..selection.start, text.clone()));
 2762                        edits.push((
 2763                            selection.end..selection.end,
 2764                            bracket_pair.end.as_str().into(),
 2765                        ));
 2766                        bracket_inserted = true;
 2767                        new_selections.push((
 2768                            Selection {
 2769                                id: selection.id,
 2770                                start: snapshot.anchor_after(selection.start),
 2771                                end: snapshot.anchor_before(selection.end),
 2772                                reversed: selection.reversed,
 2773                                goal: selection.goal,
 2774                            },
 2775                            0,
 2776                        ));
 2777                        continue;
 2778                    }
 2779                }
 2780            }
 2781
 2782            if self.auto_replace_emoji_shortcode
 2783                && selection.is_empty()
 2784                && text.as_ref().ends_with(':')
 2785            {
 2786                if let Some(possible_emoji_short_code) =
 2787                    Self::find_possible_emoji_shortcode_at_position(&snapshot, selection.start)
 2788                {
 2789                    if !possible_emoji_short_code.is_empty() {
 2790                        if let Some(emoji) = emojis::get_by_shortcode(&possible_emoji_short_code) {
 2791                            let emoji_shortcode_start = Point::new(
 2792                                selection.start.row,
 2793                                selection.start.column - possible_emoji_short_code.len() as u32 - 1,
 2794                            );
 2795
 2796                            // Remove shortcode from buffer
 2797                            edits.push((
 2798                                emoji_shortcode_start..selection.start,
 2799                                "".to_string().into(),
 2800                            ));
 2801                            new_selections.push((
 2802                                Selection {
 2803                                    id: selection.id,
 2804                                    start: snapshot.anchor_after(emoji_shortcode_start),
 2805                                    end: snapshot.anchor_before(selection.start),
 2806                                    reversed: selection.reversed,
 2807                                    goal: selection.goal,
 2808                                },
 2809                                0,
 2810                            ));
 2811
 2812                            // Insert emoji
 2813                            let selection_start_anchor = snapshot.anchor_after(selection.start);
 2814                            new_selections.push((selection.map(|_| selection_start_anchor), 0));
 2815                            edits.push((selection.start..selection.end, emoji.to_string().into()));
 2816
 2817                            continue;
 2818                        }
 2819                    }
 2820                }
 2821            }
 2822
 2823            // If not handling any auto-close operation, then just replace the selected
 2824            // text with the given input and move the selection to the end of the
 2825            // newly inserted text.
 2826            let anchor = snapshot.anchor_after(selection.end);
 2827            if !self.linked_edit_ranges.is_empty() {
 2828                let start_anchor = snapshot.anchor_before(selection.start);
 2829
 2830                let is_word_char = text.chars().next().map_or(true, |char| {
 2831                    let classifier = snapshot.char_classifier_at(start_anchor.to_offset(&snapshot));
 2832                    classifier.is_word(char)
 2833                });
 2834
 2835                if is_word_char {
 2836                    if let Some(ranges) = self
 2837                        .linked_editing_ranges_for(start_anchor.text_anchor..anchor.text_anchor, cx)
 2838                    {
 2839                        for (buffer, edits) in ranges {
 2840                            linked_edits
 2841                                .entry(buffer.clone())
 2842                                .or_default()
 2843                                .extend(edits.into_iter().map(|range| (range, text.clone())));
 2844                        }
 2845                    }
 2846                }
 2847            }
 2848
 2849            new_selections.push((selection.map(|_| anchor), 0));
 2850            edits.push((selection.start..selection.end, text.clone()));
 2851        }
 2852
 2853        drop(snapshot);
 2854
 2855        self.transact(cx, |this, cx| {
 2856            this.buffer.update(cx, |buffer, cx| {
 2857                buffer.edit(edits, this.autoindent_mode.clone(), cx);
 2858            });
 2859            for (buffer, edits) in linked_edits {
 2860                buffer.update(cx, |buffer, cx| {
 2861                    let snapshot = buffer.snapshot();
 2862                    let edits = edits
 2863                        .into_iter()
 2864                        .map(|(range, text)| {
 2865                            use text::ToPoint as TP;
 2866                            let end_point = TP::to_point(&range.end, &snapshot);
 2867                            let start_point = TP::to_point(&range.start, &snapshot);
 2868                            (start_point..end_point, text)
 2869                        })
 2870                        .sorted_by_key(|(range, _)| range.start)
 2871                        .collect::<Vec<_>>();
 2872                    buffer.edit(edits, None, cx);
 2873                })
 2874            }
 2875            let new_anchor_selections = new_selections.iter().map(|e| &e.0);
 2876            let new_selection_deltas = new_selections.iter().map(|e| e.1);
 2877            let map = this.display_map.update(cx, |map, cx| map.snapshot(cx));
 2878            let new_selections = resolve_selections::<usize, _>(new_anchor_selections, &map)
 2879                .zip(new_selection_deltas)
 2880                .map(|(selection, delta)| Selection {
 2881                    id: selection.id,
 2882                    start: selection.start + delta,
 2883                    end: selection.end + delta,
 2884                    reversed: selection.reversed,
 2885                    goal: SelectionGoal::None,
 2886                })
 2887                .collect::<Vec<_>>();
 2888
 2889            let mut i = 0;
 2890            for (position, delta, selection_id, pair) in new_autoclose_regions {
 2891                let position = position.to_offset(&map.buffer_snapshot) + delta;
 2892                let start = map.buffer_snapshot.anchor_before(position);
 2893                let end = map.buffer_snapshot.anchor_after(position);
 2894                while let Some(existing_state) = this.autoclose_regions.get(i) {
 2895                    match existing_state.range.start.cmp(&start, &map.buffer_snapshot) {
 2896                        Ordering::Less => i += 1,
 2897                        Ordering::Greater => break,
 2898                        Ordering::Equal => {
 2899                            match end.cmp(&existing_state.range.end, &map.buffer_snapshot) {
 2900                                Ordering::Less => i += 1,
 2901                                Ordering::Equal => break,
 2902                                Ordering::Greater => break,
 2903                            }
 2904                        }
 2905                    }
 2906                }
 2907                this.autoclose_regions.insert(
 2908                    i,
 2909                    AutocloseRegion {
 2910                        selection_id,
 2911                        range: start..end,
 2912                        pair,
 2913                    },
 2914                );
 2915            }
 2916
 2917            let had_active_inline_completion = this.has_active_inline_completion();
 2918            this.change_selections_inner(Some(Autoscroll::fit()), false, cx, |s| {
 2919                s.select(new_selections)
 2920            });
 2921
 2922            if !bracket_inserted {
 2923                if let Some(on_type_format_task) =
 2924                    this.trigger_on_type_formatting(text.to_string(), cx)
 2925                {
 2926                    on_type_format_task.detach_and_log_err(cx);
 2927                }
 2928            }
 2929
 2930            let editor_settings = EditorSettings::get_global(cx);
 2931            if bracket_inserted
 2932                && (editor_settings.auto_signature_help
 2933                    || editor_settings.show_signature_help_after_edits)
 2934            {
 2935                this.show_signature_help(&ShowSignatureHelp, cx);
 2936            }
 2937
 2938            let trigger_in_words =
 2939                this.show_inline_completions_in_menu(cx) || !had_active_inline_completion;
 2940            this.trigger_completion_on_input(&text, trigger_in_words, cx);
 2941            linked_editing_ranges::refresh_linked_ranges(this, cx);
 2942            this.refresh_inline_completion(true, false, cx);
 2943        });
 2944    }
 2945
 2946    fn find_possible_emoji_shortcode_at_position(
 2947        snapshot: &MultiBufferSnapshot,
 2948        position: Point,
 2949    ) -> Option<String> {
 2950        let mut chars = Vec::new();
 2951        let mut found_colon = false;
 2952        for char in snapshot.reversed_chars_at(position).take(100) {
 2953            // Found a possible emoji shortcode in the middle of the buffer
 2954            if found_colon {
 2955                if char.is_whitespace() {
 2956                    chars.reverse();
 2957                    return Some(chars.iter().collect());
 2958                }
 2959                // If the previous character is not a whitespace, we are in the middle of a word
 2960                // and we only want to complete the shortcode if the word is made up of other emojis
 2961                let mut containing_word = String::new();
 2962                for ch in snapshot
 2963                    .reversed_chars_at(position)
 2964                    .skip(chars.len() + 1)
 2965                    .take(100)
 2966                {
 2967                    if ch.is_whitespace() {
 2968                        break;
 2969                    }
 2970                    containing_word.push(ch);
 2971                }
 2972                let containing_word = containing_word.chars().rev().collect::<String>();
 2973                if util::word_consists_of_emojis(containing_word.as_str()) {
 2974                    chars.reverse();
 2975                    return Some(chars.iter().collect());
 2976                }
 2977            }
 2978
 2979            if char.is_whitespace() || !char.is_ascii() {
 2980                return None;
 2981            }
 2982            if char == ':' {
 2983                found_colon = true;
 2984            } else {
 2985                chars.push(char);
 2986            }
 2987        }
 2988        // Found a possible emoji shortcode at the beginning of the buffer
 2989        chars.reverse();
 2990        Some(chars.iter().collect())
 2991    }
 2992
 2993    pub fn newline(&mut self, _: &Newline, cx: &mut ViewContext<Self>) {
 2994        self.transact(cx, |this, cx| {
 2995            let (edits, selection_fixup_info): (Vec<_>, Vec<_>) = {
 2996                let selections = this.selections.all::<usize>(cx);
 2997                let multi_buffer = this.buffer.read(cx);
 2998                let buffer = multi_buffer.snapshot(cx);
 2999                selections
 3000                    .iter()
 3001                    .map(|selection| {
 3002                        let start_point = selection.start.to_point(&buffer);
 3003                        let mut indent =
 3004                            buffer.indent_size_for_line(MultiBufferRow(start_point.row));
 3005                        indent.len = cmp::min(indent.len, start_point.column);
 3006                        let start = selection.start;
 3007                        let end = selection.end;
 3008                        let selection_is_empty = start == end;
 3009                        let language_scope = buffer.language_scope_at(start);
 3010                        let (comment_delimiter, insert_extra_newline) = if let Some(language) =
 3011                            &language_scope
 3012                        {
 3013                            let leading_whitespace_len = buffer
 3014                                .reversed_chars_at(start)
 3015                                .take_while(|c| c.is_whitespace() && *c != '\n')
 3016                                .map(|c| c.len_utf8())
 3017                                .sum::<usize>();
 3018
 3019                            let trailing_whitespace_len = buffer
 3020                                .chars_at(end)
 3021                                .take_while(|c| c.is_whitespace() && *c != '\n')
 3022                                .map(|c| c.len_utf8())
 3023                                .sum::<usize>();
 3024
 3025                            let insert_extra_newline =
 3026                                language.brackets().any(|(pair, enabled)| {
 3027                                    let pair_start = pair.start.trim_end();
 3028                                    let pair_end = pair.end.trim_start();
 3029
 3030                                    enabled
 3031                                        && pair.newline
 3032                                        && buffer.contains_str_at(
 3033                                            end + trailing_whitespace_len,
 3034                                            pair_end,
 3035                                        )
 3036                                        && buffer.contains_str_at(
 3037                                            (start - leading_whitespace_len)
 3038                                                .saturating_sub(pair_start.len()),
 3039                                            pair_start,
 3040                                        )
 3041                                });
 3042
 3043                            // Comment extension on newline is allowed only for cursor selections
 3044                            let comment_delimiter = maybe!({
 3045                                if !selection_is_empty {
 3046                                    return None;
 3047                                }
 3048
 3049                                if !multi_buffer.settings_at(0, cx).extend_comment_on_newline {
 3050                                    return None;
 3051                                }
 3052
 3053                                let delimiters = language.line_comment_prefixes();
 3054                                let max_len_of_delimiter =
 3055                                    delimiters.iter().map(|delimiter| delimiter.len()).max()?;
 3056                                let (snapshot, range) =
 3057                                    buffer.buffer_line_for_row(MultiBufferRow(start_point.row))?;
 3058
 3059                                let mut index_of_first_non_whitespace = 0;
 3060                                let comment_candidate = snapshot
 3061                                    .chars_for_range(range)
 3062                                    .skip_while(|c| {
 3063                                        let should_skip = c.is_whitespace();
 3064                                        if should_skip {
 3065                                            index_of_first_non_whitespace += 1;
 3066                                        }
 3067                                        should_skip
 3068                                    })
 3069                                    .take(max_len_of_delimiter)
 3070                                    .collect::<String>();
 3071                                let comment_prefix = delimiters.iter().find(|comment_prefix| {
 3072                                    comment_candidate.starts_with(comment_prefix.as_ref())
 3073                                })?;
 3074                                let cursor_is_placed_after_comment_marker =
 3075                                    index_of_first_non_whitespace + comment_prefix.len()
 3076                                        <= start_point.column as usize;
 3077                                if cursor_is_placed_after_comment_marker {
 3078                                    Some(comment_prefix.clone())
 3079                                } else {
 3080                                    None
 3081                                }
 3082                            });
 3083                            (comment_delimiter, insert_extra_newline)
 3084                        } else {
 3085                            (None, false)
 3086                        };
 3087
 3088                        let capacity_for_delimiter = comment_delimiter
 3089                            .as_deref()
 3090                            .map(str::len)
 3091                            .unwrap_or_default();
 3092                        let mut new_text =
 3093                            String::with_capacity(1 + capacity_for_delimiter + indent.len as usize);
 3094                        new_text.push('\n');
 3095                        new_text.extend(indent.chars());
 3096                        if let Some(delimiter) = &comment_delimiter {
 3097                            new_text.push_str(delimiter);
 3098                        }
 3099                        if insert_extra_newline {
 3100                            new_text = new_text.repeat(2);
 3101                        }
 3102
 3103                        let anchor = buffer.anchor_after(end);
 3104                        let new_selection = selection.map(|_| anchor);
 3105                        (
 3106                            (start..end, new_text),
 3107                            (insert_extra_newline, new_selection),
 3108                        )
 3109                    })
 3110                    .unzip()
 3111            };
 3112
 3113            this.edit_with_autoindent(edits, cx);
 3114            let buffer = this.buffer.read(cx).snapshot(cx);
 3115            let new_selections = selection_fixup_info
 3116                .into_iter()
 3117                .map(|(extra_newline_inserted, new_selection)| {
 3118                    let mut cursor = new_selection.end.to_point(&buffer);
 3119                    if extra_newline_inserted {
 3120                        cursor.row -= 1;
 3121                        cursor.column = buffer.line_len(MultiBufferRow(cursor.row));
 3122                    }
 3123                    new_selection.map(|_| cursor)
 3124                })
 3125                .collect();
 3126
 3127            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(new_selections));
 3128            this.refresh_inline_completion(true, false, cx);
 3129        });
 3130    }
 3131
 3132    pub fn newline_above(&mut self, _: &NewlineAbove, cx: &mut ViewContext<Self>) {
 3133        let buffer = self.buffer.read(cx);
 3134        let snapshot = buffer.snapshot(cx);
 3135
 3136        let mut edits = Vec::new();
 3137        let mut rows = Vec::new();
 3138
 3139        for (rows_inserted, selection) in self.selections.all_adjusted(cx).into_iter().enumerate() {
 3140            let cursor = selection.head();
 3141            let row = cursor.row;
 3142
 3143            let start_of_line = snapshot.clip_point(Point::new(row, 0), Bias::Left);
 3144
 3145            let newline = "\n".to_string();
 3146            edits.push((start_of_line..start_of_line, newline));
 3147
 3148            rows.push(row + rows_inserted as u32);
 3149        }
 3150
 3151        self.transact(cx, |editor, cx| {
 3152            editor.edit(edits, cx);
 3153
 3154            editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
 3155                let mut index = 0;
 3156                s.move_cursors_with(|map, _, _| {
 3157                    let row = rows[index];
 3158                    index += 1;
 3159
 3160                    let point = Point::new(row, 0);
 3161                    let boundary = map.next_line_boundary(point).1;
 3162                    let clipped = map.clip_point(boundary, Bias::Left);
 3163
 3164                    (clipped, SelectionGoal::None)
 3165                });
 3166            });
 3167
 3168            let mut indent_edits = Vec::new();
 3169            let multibuffer_snapshot = editor.buffer.read(cx).snapshot(cx);
 3170            for row in rows {
 3171                let indents = multibuffer_snapshot.suggested_indents(row..row + 1, cx);
 3172                for (row, indent) in indents {
 3173                    if indent.len == 0 {
 3174                        continue;
 3175                    }
 3176
 3177                    let text = match indent.kind {
 3178                        IndentKind::Space => " ".repeat(indent.len as usize),
 3179                        IndentKind::Tab => "\t".repeat(indent.len as usize),
 3180                    };
 3181                    let point = Point::new(row.0, 0);
 3182                    indent_edits.push((point..point, text));
 3183                }
 3184            }
 3185            editor.edit(indent_edits, cx);
 3186        });
 3187    }
 3188
 3189    pub fn newline_below(&mut self, _: &NewlineBelow, cx: &mut ViewContext<Self>) {
 3190        let buffer = self.buffer.read(cx);
 3191        let snapshot = buffer.snapshot(cx);
 3192
 3193        let mut edits = Vec::new();
 3194        let mut rows = Vec::new();
 3195        let mut rows_inserted = 0;
 3196
 3197        for selection in self.selections.all_adjusted(cx) {
 3198            let cursor = selection.head();
 3199            let row = cursor.row;
 3200
 3201            let point = Point::new(row + 1, 0);
 3202            let start_of_line = snapshot.clip_point(point, Bias::Left);
 3203
 3204            let newline = "\n".to_string();
 3205            edits.push((start_of_line..start_of_line, newline));
 3206
 3207            rows_inserted += 1;
 3208            rows.push(row + rows_inserted);
 3209        }
 3210
 3211        self.transact(cx, |editor, cx| {
 3212            editor.edit(edits, cx);
 3213
 3214            editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
 3215                let mut index = 0;
 3216                s.move_cursors_with(|map, _, _| {
 3217                    let row = rows[index];
 3218                    index += 1;
 3219
 3220                    let point = Point::new(row, 0);
 3221                    let boundary = map.next_line_boundary(point).1;
 3222                    let clipped = map.clip_point(boundary, Bias::Left);
 3223
 3224                    (clipped, SelectionGoal::None)
 3225                });
 3226            });
 3227
 3228            let mut indent_edits = Vec::new();
 3229            let multibuffer_snapshot = editor.buffer.read(cx).snapshot(cx);
 3230            for row in rows {
 3231                let indents = multibuffer_snapshot.suggested_indents(row..row + 1, cx);
 3232                for (row, indent) in indents {
 3233                    if indent.len == 0 {
 3234                        continue;
 3235                    }
 3236
 3237                    let text = match indent.kind {
 3238                        IndentKind::Space => " ".repeat(indent.len as usize),
 3239                        IndentKind::Tab => "\t".repeat(indent.len as usize),
 3240                    };
 3241                    let point = Point::new(row.0, 0);
 3242                    indent_edits.push((point..point, text));
 3243                }
 3244            }
 3245            editor.edit(indent_edits, cx);
 3246        });
 3247    }
 3248
 3249    pub fn insert(&mut self, text: &str, cx: &mut ViewContext<Self>) {
 3250        let autoindent = text.is_empty().not().then(|| AutoindentMode::Block {
 3251            original_indent_columns: Vec::new(),
 3252        });
 3253        self.insert_with_autoindent_mode(text, autoindent, cx);
 3254    }
 3255
 3256    fn insert_with_autoindent_mode(
 3257        &mut self,
 3258        text: &str,
 3259        autoindent_mode: Option<AutoindentMode>,
 3260        cx: &mut ViewContext<Self>,
 3261    ) {
 3262        if self.read_only(cx) {
 3263            return;
 3264        }
 3265
 3266        let text: Arc<str> = text.into();
 3267        self.transact(cx, |this, cx| {
 3268            let old_selections = this.selections.all_adjusted(cx);
 3269            let selection_anchors = this.buffer.update(cx, |buffer, cx| {
 3270                let anchors = {
 3271                    let snapshot = buffer.read(cx);
 3272                    old_selections
 3273                        .iter()
 3274                        .map(|s| {
 3275                            let anchor = snapshot.anchor_after(s.head());
 3276                            s.map(|_| anchor)
 3277                        })
 3278                        .collect::<Vec<_>>()
 3279                };
 3280                buffer.edit(
 3281                    old_selections
 3282                        .iter()
 3283                        .map(|s| (s.start..s.end, text.clone())),
 3284                    autoindent_mode,
 3285                    cx,
 3286                );
 3287                anchors
 3288            });
 3289
 3290            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 3291                s.select_anchors(selection_anchors);
 3292            })
 3293        });
 3294    }
 3295
 3296    fn trigger_completion_on_input(
 3297        &mut self,
 3298        text: &str,
 3299        trigger_in_words: bool,
 3300        cx: &mut ViewContext<Self>,
 3301    ) {
 3302        if self.is_completion_trigger(text, trigger_in_words, cx) {
 3303            self.show_completions(
 3304                &ShowCompletions {
 3305                    trigger: Some(text.to_owned()).filter(|x| !x.is_empty()),
 3306                },
 3307                cx,
 3308            );
 3309        } else {
 3310            self.hide_context_menu(cx);
 3311        }
 3312    }
 3313
 3314    fn is_completion_trigger(
 3315        &self,
 3316        text: &str,
 3317        trigger_in_words: bool,
 3318        cx: &mut ViewContext<Self>,
 3319    ) -> bool {
 3320        let position = self.selections.newest_anchor().head();
 3321        let multibuffer = self.buffer.read(cx);
 3322        let Some(buffer) = position
 3323            .buffer_id
 3324            .and_then(|buffer_id| multibuffer.buffer(buffer_id).clone())
 3325        else {
 3326            return false;
 3327        };
 3328
 3329        if let Some(completion_provider) = &self.completion_provider {
 3330            completion_provider.is_completion_trigger(
 3331                &buffer,
 3332                position.text_anchor,
 3333                text,
 3334                trigger_in_words,
 3335                cx,
 3336            )
 3337        } else {
 3338            false
 3339        }
 3340    }
 3341
 3342    /// If any empty selections is touching the start of its innermost containing autoclose
 3343    /// region, expand it to select the brackets.
 3344    fn select_autoclose_pair(&mut self, cx: &mut ViewContext<Self>) {
 3345        let selections = self.selections.all::<usize>(cx);
 3346        let buffer = self.buffer.read(cx).read(cx);
 3347        let new_selections = self
 3348            .selections_with_autoclose_regions(selections, &buffer)
 3349            .map(|(mut selection, region)| {
 3350                if !selection.is_empty() {
 3351                    return selection;
 3352                }
 3353
 3354                if let Some(region) = region {
 3355                    let mut range = region.range.to_offset(&buffer);
 3356                    if selection.start == range.start && range.start >= region.pair.start.len() {
 3357                        range.start -= region.pair.start.len();
 3358                        if buffer.contains_str_at(range.start, &region.pair.start)
 3359                            && buffer.contains_str_at(range.end, &region.pair.end)
 3360                        {
 3361                            range.end += region.pair.end.len();
 3362                            selection.start = range.start;
 3363                            selection.end = range.end;
 3364
 3365                            return selection;
 3366                        }
 3367                    }
 3368                }
 3369
 3370                let always_treat_brackets_as_autoclosed = buffer
 3371                    .settings_at(selection.start, cx)
 3372                    .always_treat_brackets_as_autoclosed;
 3373
 3374                if !always_treat_brackets_as_autoclosed {
 3375                    return selection;
 3376                }
 3377
 3378                if let Some(scope) = buffer.language_scope_at(selection.start) {
 3379                    for (pair, enabled) in scope.brackets() {
 3380                        if !enabled || !pair.close {
 3381                            continue;
 3382                        }
 3383
 3384                        if buffer.contains_str_at(selection.start, &pair.end) {
 3385                            let pair_start_len = pair.start.len();
 3386                            if buffer.contains_str_at(
 3387                                selection.start.saturating_sub(pair_start_len),
 3388                                &pair.start,
 3389                            ) {
 3390                                selection.start -= pair_start_len;
 3391                                selection.end += pair.end.len();
 3392
 3393                                return selection;
 3394                            }
 3395                        }
 3396                    }
 3397                }
 3398
 3399                selection
 3400            })
 3401            .collect();
 3402
 3403        drop(buffer);
 3404        self.change_selections(None, cx, |selections| selections.select(new_selections));
 3405    }
 3406
 3407    /// Iterate the given selections, and for each one, find the smallest surrounding
 3408    /// autoclose region. This uses the ordering of the selections and the autoclose
 3409    /// regions to avoid repeated comparisons.
 3410    fn selections_with_autoclose_regions<'a, D: ToOffset + Clone>(
 3411        &'a self,
 3412        selections: impl IntoIterator<Item = Selection<D>>,
 3413        buffer: &'a MultiBufferSnapshot,
 3414    ) -> impl Iterator<Item = (Selection<D>, Option<&'a AutocloseRegion>)> {
 3415        let mut i = 0;
 3416        let mut regions = self.autoclose_regions.as_slice();
 3417        selections.into_iter().map(move |selection| {
 3418            let range = selection.start.to_offset(buffer)..selection.end.to_offset(buffer);
 3419
 3420            let mut enclosing = None;
 3421            while let Some(pair_state) = regions.get(i) {
 3422                if pair_state.range.end.to_offset(buffer) < range.start {
 3423                    regions = &regions[i + 1..];
 3424                    i = 0;
 3425                } else if pair_state.range.start.to_offset(buffer) > range.end {
 3426                    break;
 3427                } else {
 3428                    if pair_state.selection_id == selection.id {
 3429                        enclosing = Some(pair_state);
 3430                    }
 3431                    i += 1;
 3432                }
 3433            }
 3434
 3435            (selection, enclosing)
 3436        })
 3437    }
 3438
 3439    /// Remove any autoclose regions that no longer contain their selection.
 3440    fn invalidate_autoclose_regions(
 3441        &mut self,
 3442        mut selections: &[Selection<Anchor>],
 3443        buffer: &MultiBufferSnapshot,
 3444    ) {
 3445        self.autoclose_regions.retain(|state| {
 3446            let mut i = 0;
 3447            while let Some(selection) = selections.get(i) {
 3448                if selection.end.cmp(&state.range.start, buffer).is_lt() {
 3449                    selections = &selections[1..];
 3450                    continue;
 3451                }
 3452                if selection.start.cmp(&state.range.end, buffer).is_gt() {
 3453                    break;
 3454                }
 3455                if selection.id == state.selection_id {
 3456                    return true;
 3457                } else {
 3458                    i += 1;
 3459                }
 3460            }
 3461            false
 3462        });
 3463    }
 3464
 3465    fn completion_query(buffer: &MultiBufferSnapshot, position: impl ToOffset) -> Option<String> {
 3466        let offset = position.to_offset(buffer);
 3467        let (word_range, kind) = buffer.surrounding_word(offset, true);
 3468        if offset > word_range.start && kind == Some(CharKind::Word) {
 3469            Some(
 3470                buffer
 3471                    .text_for_range(word_range.start..offset)
 3472                    .collect::<String>(),
 3473            )
 3474        } else {
 3475            None
 3476        }
 3477    }
 3478
 3479    pub fn toggle_inlay_hints(&mut self, _: &ToggleInlayHints, cx: &mut ViewContext<Self>) {
 3480        self.refresh_inlay_hints(
 3481            InlayHintRefreshReason::Toggle(!self.inlay_hint_cache.enabled),
 3482            cx,
 3483        );
 3484    }
 3485
 3486    pub fn inlay_hints_enabled(&self) -> bool {
 3487        self.inlay_hint_cache.enabled
 3488    }
 3489
 3490    fn refresh_inlay_hints(&mut self, reason: InlayHintRefreshReason, cx: &mut ViewContext<Self>) {
 3491        if self.semantics_provider.is_none() || self.mode != EditorMode::Full {
 3492            return;
 3493        }
 3494
 3495        let reason_description = reason.description();
 3496        let ignore_debounce = matches!(
 3497            reason,
 3498            InlayHintRefreshReason::SettingsChange(_)
 3499                | InlayHintRefreshReason::Toggle(_)
 3500                | InlayHintRefreshReason::ExcerptsRemoved(_)
 3501        );
 3502        let (invalidate_cache, required_languages) = match reason {
 3503            InlayHintRefreshReason::Toggle(enabled) => {
 3504                self.inlay_hint_cache.enabled = enabled;
 3505                if enabled {
 3506                    (InvalidationStrategy::RefreshRequested, None)
 3507                } else {
 3508                    self.inlay_hint_cache.clear();
 3509                    self.splice_inlays(
 3510                        self.visible_inlay_hints(cx)
 3511                            .iter()
 3512                            .map(|inlay| inlay.id)
 3513                            .collect(),
 3514                        Vec::new(),
 3515                        cx,
 3516                    );
 3517                    return;
 3518                }
 3519            }
 3520            InlayHintRefreshReason::SettingsChange(new_settings) => {
 3521                match self.inlay_hint_cache.update_settings(
 3522                    &self.buffer,
 3523                    new_settings,
 3524                    self.visible_inlay_hints(cx),
 3525                    cx,
 3526                ) {
 3527                    ControlFlow::Break(Some(InlaySplice {
 3528                        to_remove,
 3529                        to_insert,
 3530                    })) => {
 3531                        self.splice_inlays(to_remove, to_insert, cx);
 3532                        return;
 3533                    }
 3534                    ControlFlow::Break(None) => return,
 3535                    ControlFlow::Continue(()) => (InvalidationStrategy::RefreshRequested, None),
 3536                }
 3537            }
 3538            InlayHintRefreshReason::ExcerptsRemoved(excerpts_removed) => {
 3539                if let Some(InlaySplice {
 3540                    to_remove,
 3541                    to_insert,
 3542                }) = self.inlay_hint_cache.remove_excerpts(excerpts_removed)
 3543                {
 3544                    self.splice_inlays(to_remove, to_insert, cx);
 3545                }
 3546                return;
 3547            }
 3548            InlayHintRefreshReason::NewLinesShown => (InvalidationStrategy::None, None),
 3549            InlayHintRefreshReason::BufferEdited(buffer_languages) => {
 3550                (InvalidationStrategy::BufferEdited, Some(buffer_languages))
 3551            }
 3552            InlayHintRefreshReason::RefreshRequested => {
 3553                (InvalidationStrategy::RefreshRequested, None)
 3554            }
 3555        };
 3556
 3557        if let Some(InlaySplice {
 3558            to_remove,
 3559            to_insert,
 3560        }) = self.inlay_hint_cache.spawn_hint_refresh(
 3561            reason_description,
 3562            self.excerpts_for_inlay_hints_query(required_languages.as_ref(), cx),
 3563            invalidate_cache,
 3564            ignore_debounce,
 3565            cx,
 3566        ) {
 3567            self.splice_inlays(to_remove, to_insert, cx);
 3568        }
 3569    }
 3570
 3571    fn visible_inlay_hints(&self, cx: &ViewContext<Editor>) -> Vec<Inlay> {
 3572        self.display_map
 3573            .read(cx)
 3574            .current_inlays()
 3575            .filter(move |inlay| matches!(inlay.id, InlayId::Hint(_)))
 3576            .cloned()
 3577            .collect()
 3578    }
 3579
 3580    pub fn excerpts_for_inlay_hints_query(
 3581        &self,
 3582        restrict_to_languages: Option<&HashSet<Arc<Language>>>,
 3583        cx: &mut ViewContext<Editor>,
 3584    ) -> HashMap<ExcerptId, (Model<Buffer>, clock::Global, Range<usize>)> {
 3585        let Some(project) = self.project.as_ref() else {
 3586            return HashMap::default();
 3587        };
 3588        let project = project.read(cx);
 3589        let multi_buffer = self.buffer().read(cx);
 3590        let multi_buffer_snapshot = multi_buffer.snapshot(cx);
 3591        let multi_buffer_visible_start = self
 3592            .scroll_manager
 3593            .anchor()
 3594            .anchor
 3595            .to_point(&multi_buffer_snapshot);
 3596        let multi_buffer_visible_end = multi_buffer_snapshot.clip_point(
 3597            multi_buffer_visible_start
 3598                + Point::new(self.visible_line_count().unwrap_or(0.).ceil() as u32, 0),
 3599            Bias::Left,
 3600        );
 3601        let multi_buffer_visible_range = multi_buffer_visible_start..multi_buffer_visible_end;
 3602        multi_buffer_snapshot
 3603            .range_to_buffer_ranges(multi_buffer_visible_range)
 3604            .into_iter()
 3605            .filter(|(_, excerpt_visible_range)| !excerpt_visible_range.is_empty())
 3606            .filter_map(|(excerpt, excerpt_visible_range)| {
 3607                let buffer_file = project::File::from_dyn(excerpt.buffer().file())?;
 3608                let buffer_worktree = project.worktree_for_id(buffer_file.worktree_id(cx), cx)?;
 3609                let worktree_entry = buffer_worktree
 3610                    .read(cx)
 3611                    .entry_for_id(buffer_file.project_entry_id(cx)?)?;
 3612                if worktree_entry.is_ignored {
 3613                    return None;
 3614                }
 3615
 3616                let language = excerpt.buffer().language()?;
 3617                if let Some(restrict_to_languages) = restrict_to_languages {
 3618                    if !restrict_to_languages.contains(language) {
 3619                        return None;
 3620                    }
 3621                }
 3622                Some((
 3623                    excerpt.id(),
 3624                    (
 3625                        multi_buffer.buffer(excerpt.buffer_id()).unwrap(),
 3626                        excerpt.buffer().version().clone(),
 3627                        excerpt_visible_range,
 3628                    ),
 3629                ))
 3630            })
 3631            .collect()
 3632    }
 3633
 3634    pub fn text_layout_details(&self, cx: &WindowContext) -> TextLayoutDetails {
 3635        TextLayoutDetails {
 3636            text_system: cx.text_system().clone(),
 3637            editor_style: self.style.clone().unwrap(),
 3638            rem_size: cx.rem_size(),
 3639            scroll_anchor: self.scroll_manager.anchor(),
 3640            visible_rows: self.visible_line_count(),
 3641            vertical_scroll_margin: self.scroll_manager.vertical_scroll_margin,
 3642        }
 3643    }
 3644
 3645    pub fn splice_inlays(
 3646        &self,
 3647        to_remove: Vec<InlayId>,
 3648        to_insert: Vec<Inlay>,
 3649        cx: &mut ViewContext<Self>,
 3650    ) {
 3651        self.display_map.update(cx, |display_map, cx| {
 3652            display_map.splice_inlays(to_remove, to_insert, cx)
 3653        });
 3654        cx.notify();
 3655    }
 3656
 3657    fn trigger_on_type_formatting(
 3658        &self,
 3659        input: String,
 3660        cx: &mut ViewContext<Self>,
 3661    ) -> Option<Task<Result<()>>> {
 3662        if input.len() != 1 {
 3663            return None;
 3664        }
 3665
 3666        let project = self.project.as_ref()?;
 3667        let position = self.selections.newest_anchor().head();
 3668        let (buffer, buffer_position) = self
 3669            .buffer
 3670            .read(cx)
 3671            .text_anchor_for_position(position, cx)?;
 3672
 3673        let settings = language_settings::language_settings(
 3674            buffer
 3675                .read(cx)
 3676                .language_at(buffer_position)
 3677                .map(|l| l.name()),
 3678            buffer.read(cx).file(),
 3679            cx,
 3680        );
 3681        if !settings.use_on_type_format {
 3682            return None;
 3683        }
 3684
 3685        // OnTypeFormatting returns a list of edits, no need to pass them between Zed instances,
 3686        // hence we do LSP request & edit on host side only — add formats to host's history.
 3687        let push_to_lsp_host_history = true;
 3688        // If this is not the host, append its history with new edits.
 3689        let push_to_client_history = project.read(cx).is_via_collab();
 3690
 3691        let on_type_formatting = project.update(cx, |project, cx| {
 3692            project.on_type_format(
 3693                buffer.clone(),
 3694                buffer_position,
 3695                input,
 3696                push_to_lsp_host_history,
 3697                cx,
 3698            )
 3699        });
 3700        Some(cx.spawn(|editor, mut cx| async move {
 3701            if let Some(transaction) = on_type_formatting.await? {
 3702                if push_to_client_history {
 3703                    buffer
 3704                        .update(&mut cx, |buffer, _| {
 3705                            buffer.push_transaction(transaction, Instant::now());
 3706                        })
 3707                        .ok();
 3708                }
 3709                editor.update(&mut cx, |editor, cx| {
 3710                    editor.refresh_document_highlights(cx);
 3711                })?;
 3712            }
 3713            Ok(())
 3714        }))
 3715    }
 3716
 3717    pub fn show_completions(&mut self, options: &ShowCompletions, cx: &mut ViewContext<Self>) {
 3718        if self.pending_rename.is_some() {
 3719            return;
 3720        }
 3721
 3722        let Some(provider) = self.completion_provider.as_ref() else {
 3723            return;
 3724        };
 3725
 3726        if !self.snippet_stack.is_empty() && self.context_menu.borrow().as_ref().is_some() {
 3727            return;
 3728        }
 3729
 3730        let position = self.selections.newest_anchor().head();
 3731        let (buffer, buffer_position) =
 3732            if let Some(output) = self.buffer.read(cx).text_anchor_for_position(position, cx) {
 3733                output
 3734            } else {
 3735                return;
 3736            };
 3737        let show_completion_documentation = buffer
 3738            .read(cx)
 3739            .snapshot()
 3740            .settings_at(buffer_position, cx)
 3741            .show_completion_documentation;
 3742
 3743        let query = Self::completion_query(&self.buffer.read(cx).read(cx), position);
 3744
 3745        let trigger_kind = match &options.trigger {
 3746            Some(trigger) if buffer.read(cx).completion_triggers().contains(trigger) => {
 3747                CompletionTriggerKind::TRIGGER_CHARACTER
 3748            }
 3749            _ => CompletionTriggerKind::INVOKED,
 3750        };
 3751        let completion_context = CompletionContext {
 3752            trigger_character: options.trigger.as_ref().and_then(|trigger| {
 3753                if trigger_kind == CompletionTriggerKind::TRIGGER_CHARACTER {
 3754                    Some(String::from(trigger))
 3755                } else {
 3756                    None
 3757                }
 3758            }),
 3759            trigger_kind,
 3760        };
 3761        let completions = provider.completions(&buffer, buffer_position, completion_context, cx);
 3762        let sort_completions = provider.sort_completions();
 3763
 3764        let id = post_inc(&mut self.next_completion_id);
 3765        let task = cx.spawn(|editor, mut cx| {
 3766            async move {
 3767                editor.update(&mut cx, |this, _| {
 3768                    this.completion_tasks.retain(|(task_id, _)| *task_id >= id);
 3769                })?;
 3770                let completions = completions.await.log_err();
 3771                let menu = if let Some(completions) = completions {
 3772                    let mut menu = CompletionsMenu::new(
 3773                        id,
 3774                        sort_completions,
 3775                        show_completion_documentation,
 3776                        position,
 3777                        buffer.clone(),
 3778                        completions.into(),
 3779                    );
 3780
 3781                    menu.filter(query.as_deref(), cx.background_executor().clone())
 3782                        .await;
 3783
 3784                    menu.visible().then_some(menu)
 3785                } else {
 3786                    None
 3787                };
 3788
 3789                editor.update(&mut cx, |editor, cx| {
 3790                    match editor.context_menu.borrow().as_ref() {
 3791                        None => {}
 3792                        Some(CodeContextMenu::Completions(prev_menu)) => {
 3793                            if prev_menu.id > id {
 3794                                return;
 3795                            }
 3796                        }
 3797                        _ => return,
 3798                    }
 3799
 3800                    if editor.focus_handle.is_focused(cx) && menu.is_some() {
 3801                        let mut menu = menu.unwrap();
 3802                        menu.resolve_visible_completions(editor.completion_provider.as_deref(), cx);
 3803
 3804                        if editor.show_inline_completions_in_menu(cx) {
 3805                            if let Some(hint) = editor.inline_completion_menu_hint(cx) {
 3806                                menu.show_inline_completion_hint(hint);
 3807                            }
 3808                        } else {
 3809                            editor.discard_inline_completion(false, cx);
 3810                        }
 3811
 3812                        *editor.context_menu.borrow_mut() =
 3813                            Some(CodeContextMenu::Completions(menu));
 3814
 3815                        cx.notify();
 3816                    } else if editor.completion_tasks.len() <= 1 {
 3817                        // If there are no more completion tasks and the last menu was
 3818                        // empty, we should hide it.
 3819                        let was_hidden = editor.hide_context_menu(cx).is_none();
 3820                        // If it was already hidden and we don't show inline
 3821                        // completions in the menu, we should also show the
 3822                        // inline-completion when available.
 3823                        if was_hidden && editor.show_inline_completions_in_menu(cx) {
 3824                            editor.update_visible_inline_completion(cx);
 3825                        }
 3826                    }
 3827                })?;
 3828
 3829                Ok::<_, anyhow::Error>(())
 3830            }
 3831            .log_err()
 3832        });
 3833
 3834        self.completion_tasks.push((id, task));
 3835    }
 3836
 3837    pub fn confirm_completion(
 3838        &mut self,
 3839        action: &ConfirmCompletion,
 3840        cx: &mut ViewContext<Self>,
 3841    ) -> Option<Task<Result<()>>> {
 3842        self.do_completion(action.item_ix, CompletionIntent::Complete, cx)
 3843    }
 3844
 3845    pub fn compose_completion(
 3846        &mut self,
 3847        action: &ComposeCompletion,
 3848        cx: &mut ViewContext<Self>,
 3849    ) -> Option<Task<Result<()>>> {
 3850        self.do_completion(action.item_ix, CompletionIntent::Compose, cx)
 3851    }
 3852
 3853    fn toggle_zed_predict_tos(&mut self, cx: &mut ViewContext<Self>) {
 3854        let (Some(workspace), Some(project)) = (self.workspace(), self.project.as_ref()) else {
 3855            return;
 3856        };
 3857
 3858        ZedPredictTos::toggle(workspace, project.read(cx).user_store().clone(), cx);
 3859    }
 3860
 3861    fn do_completion(
 3862        &mut self,
 3863        item_ix: Option<usize>,
 3864        intent: CompletionIntent,
 3865        cx: &mut ViewContext<Editor>,
 3866    ) -> Option<Task<std::result::Result<(), anyhow::Error>>> {
 3867        use language::ToOffset as _;
 3868
 3869        {
 3870            let context_menu = self.context_menu.borrow();
 3871            if let CodeContextMenu::Completions(menu) = context_menu.as_ref()? {
 3872                let entries = menu.entries.borrow();
 3873                let entry = entries.get(item_ix.unwrap_or(menu.selected_item));
 3874                match entry {
 3875                    Some(CompletionEntry::InlineCompletionHint(
 3876                        InlineCompletionMenuHint::Loading,
 3877                    )) => return Some(Task::ready(Ok(()))),
 3878                    Some(CompletionEntry::InlineCompletionHint(InlineCompletionMenuHint::None)) => {
 3879                        drop(entries);
 3880                        drop(context_menu);
 3881                        self.context_menu_next(&Default::default(), cx);
 3882                        return Some(Task::ready(Ok(())));
 3883                    }
 3884                    Some(CompletionEntry::InlineCompletionHint(
 3885                        InlineCompletionMenuHint::PendingTermsAcceptance,
 3886                    )) => {
 3887                        drop(entries);
 3888                        drop(context_menu);
 3889                        self.toggle_zed_predict_tos(cx);
 3890                        return Some(Task::ready(Ok(())));
 3891                    }
 3892                    _ => {}
 3893                }
 3894            }
 3895        }
 3896
 3897        let completions_menu =
 3898            if let CodeContextMenu::Completions(menu) = self.hide_context_menu(cx)? {
 3899                menu
 3900            } else {
 3901                return None;
 3902            };
 3903
 3904        let entries = completions_menu.entries.borrow();
 3905        let mat = entries.get(item_ix.unwrap_or(completions_menu.selected_item))?;
 3906        let mat = match mat {
 3907            CompletionEntry::InlineCompletionHint(_) => {
 3908                self.accept_inline_completion(&AcceptInlineCompletion, cx);
 3909                cx.stop_propagation();
 3910                return Some(Task::ready(Ok(())));
 3911            }
 3912            CompletionEntry::Match(mat) => {
 3913                if self.show_inline_completions_in_menu(cx) {
 3914                    self.discard_inline_completion(true, cx);
 3915                }
 3916                mat
 3917            }
 3918        };
 3919        let candidate_id = mat.candidate_id;
 3920        drop(entries);
 3921
 3922        let buffer_handle = completions_menu.buffer;
 3923        let completion = completions_menu
 3924            .completions
 3925            .borrow()
 3926            .get(candidate_id)?
 3927            .clone();
 3928        cx.stop_propagation();
 3929
 3930        let snippet;
 3931        let text;
 3932
 3933        if completion.is_snippet() {
 3934            snippet = Some(Snippet::parse(&completion.new_text).log_err()?);
 3935            text = snippet.as_ref().unwrap().text.clone();
 3936        } else {
 3937            snippet = None;
 3938            text = completion.new_text.clone();
 3939        };
 3940        let selections = self.selections.all::<usize>(cx);
 3941        let buffer = buffer_handle.read(cx);
 3942        let old_range = completion.old_range.to_offset(buffer);
 3943        let old_text = buffer.text_for_range(old_range.clone()).collect::<String>();
 3944
 3945        let newest_selection = self.selections.newest_anchor();
 3946        if newest_selection.start.buffer_id != Some(buffer_handle.read(cx).remote_id()) {
 3947            return None;
 3948        }
 3949
 3950        let lookbehind = newest_selection
 3951            .start
 3952            .text_anchor
 3953            .to_offset(buffer)
 3954            .saturating_sub(old_range.start);
 3955        let lookahead = old_range
 3956            .end
 3957            .saturating_sub(newest_selection.end.text_anchor.to_offset(buffer));
 3958        let mut common_prefix_len = old_text
 3959            .bytes()
 3960            .zip(text.bytes())
 3961            .take_while(|(a, b)| a == b)
 3962            .count();
 3963
 3964        let snapshot = self.buffer.read(cx).snapshot(cx);
 3965        let mut range_to_replace: Option<Range<isize>> = None;
 3966        let mut ranges = Vec::new();
 3967        let mut linked_edits = HashMap::<_, Vec<_>>::default();
 3968        for selection in &selections {
 3969            if snapshot.contains_str_at(selection.start.saturating_sub(lookbehind), &old_text) {
 3970                let start = selection.start.saturating_sub(lookbehind);
 3971                let end = selection.end + lookahead;
 3972                if selection.id == newest_selection.id {
 3973                    range_to_replace = Some(
 3974                        ((start + common_prefix_len) as isize - selection.start as isize)
 3975                            ..(end as isize - selection.start as isize),
 3976                    );
 3977                }
 3978                ranges.push(start + common_prefix_len..end);
 3979            } else {
 3980                common_prefix_len = 0;
 3981                ranges.clear();
 3982                ranges.extend(selections.iter().map(|s| {
 3983                    if s.id == newest_selection.id {
 3984                        range_to_replace = Some(
 3985                            old_range.start.to_offset_utf16(&snapshot).0 as isize
 3986                                - selection.start as isize
 3987                                ..old_range.end.to_offset_utf16(&snapshot).0 as isize
 3988                                    - selection.start as isize,
 3989                        );
 3990                        old_range.clone()
 3991                    } else {
 3992                        s.start..s.end
 3993                    }
 3994                }));
 3995                break;
 3996            }
 3997            if !self.linked_edit_ranges.is_empty() {
 3998                let start_anchor = snapshot.anchor_before(selection.head());
 3999                let end_anchor = snapshot.anchor_after(selection.tail());
 4000                if let Some(ranges) = self
 4001                    .linked_editing_ranges_for(start_anchor.text_anchor..end_anchor.text_anchor, cx)
 4002                {
 4003                    for (buffer, edits) in ranges {
 4004                        linked_edits.entry(buffer.clone()).or_default().extend(
 4005                            edits
 4006                                .into_iter()
 4007                                .map(|range| (range, text[common_prefix_len..].to_owned())),
 4008                        );
 4009                    }
 4010                }
 4011            }
 4012        }
 4013        let text = &text[common_prefix_len..];
 4014
 4015        cx.emit(EditorEvent::InputHandled {
 4016            utf16_range_to_replace: range_to_replace,
 4017            text: text.into(),
 4018        });
 4019
 4020        self.transact(cx, |this, cx| {
 4021            if let Some(mut snippet) = snippet {
 4022                snippet.text = text.to_string();
 4023                for tabstop in snippet
 4024                    .tabstops
 4025                    .iter_mut()
 4026                    .flat_map(|tabstop| tabstop.ranges.iter_mut())
 4027                {
 4028                    tabstop.start -= common_prefix_len as isize;
 4029                    tabstop.end -= common_prefix_len as isize;
 4030                }
 4031
 4032                this.insert_snippet(&ranges, snippet, cx).log_err();
 4033            } else {
 4034                this.buffer.update(cx, |buffer, cx| {
 4035                    buffer.edit(
 4036                        ranges.iter().map(|range| (range.clone(), text)),
 4037                        this.autoindent_mode.clone(),
 4038                        cx,
 4039                    );
 4040                });
 4041            }
 4042            for (buffer, edits) in linked_edits {
 4043                buffer.update(cx, |buffer, cx| {
 4044                    let snapshot = buffer.snapshot();
 4045                    let edits = edits
 4046                        .into_iter()
 4047                        .map(|(range, text)| {
 4048                            use text::ToPoint as TP;
 4049                            let end_point = TP::to_point(&range.end, &snapshot);
 4050                            let start_point = TP::to_point(&range.start, &snapshot);
 4051                            (start_point..end_point, text)
 4052                        })
 4053                        .sorted_by_key(|(range, _)| range.start)
 4054                        .collect::<Vec<_>>();
 4055                    buffer.edit(edits, None, cx);
 4056                })
 4057            }
 4058
 4059            this.refresh_inline_completion(true, false, cx);
 4060        });
 4061
 4062        let show_new_completions_on_confirm = completion
 4063            .confirm
 4064            .as_ref()
 4065            .map_or(false, |confirm| confirm(intent, cx));
 4066        if show_new_completions_on_confirm {
 4067            self.show_completions(&ShowCompletions { trigger: None }, cx);
 4068        }
 4069
 4070        let provider = self.completion_provider.as_ref()?;
 4071        drop(completion);
 4072        let apply_edits = provider.apply_additional_edits_for_completion(
 4073            buffer_handle,
 4074            completions_menu.completions.clone(),
 4075            candidate_id,
 4076            true,
 4077            cx,
 4078        );
 4079
 4080        let editor_settings = EditorSettings::get_global(cx);
 4081        if editor_settings.show_signature_help_after_edits || editor_settings.auto_signature_help {
 4082            // After the code completion is finished, users often want to know what signatures are needed.
 4083            // so we should automatically call signature_help
 4084            self.show_signature_help(&ShowSignatureHelp, cx);
 4085        }
 4086
 4087        Some(cx.foreground_executor().spawn(async move {
 4088            apply_edits.await?;
 4089            Ok(())
 4090        }))
 4091    }
 4092
 4093    pub fn toggle_code_actions(&mut self, action: &ToggleCodeActions, cx: &mut ViewContext<Self>) {
 4094        let mut context_menu = self.context_menu.borrow_mut();
 4095        if let Some(CodeContextMenu::CodeActions(code_actions)) = context_menu.as_ref() {
 4096            if code_actions.deployed_from_indicator == action.deployed_from_indicator {
 4097                // Toggle if we're selecting the same one
 4098                *context_menu = None;
 4099                cx.notify();
 4100                return;
 4101            } else {
 4102                // Otherwise, clear it and start a new one
 4103                *context_menu = None;
 4104                cx.notify();
 4105            }
 4106        }
 4107        drop(context_menu);
 4108        let snapshot = self.snapshot(cx);
 4109        let deployed_from_indicator = action.deployed_from_indicator;
 4110        let mut task = self.code_actions_task.take();
 4111        let action = action.clone();
 4112        cx.spawn(|editor, mut cx| async move {
 4113            while let Some(prev_task) = task {
 4114                prev_task.await.log_err();
 4115                task = editor.update(&mut cx, |this, _| this.code_actions_task.take())?;
 4116            }
 4117
 4118            let spawned_test_task = editor.update(&mut cx, |editor, cx| {
 4119                if editor.focus_handle.is_focused(cx) {
 4120                    let multibuffer_point = action
 4121                        .deployed_from_indicator
 4122                        .map(|row| DisplayPoint::new(row, 0).to_point(&snapshot))
 4123                        .unwrap_or_else(|| editor.selections.newest::<Point>(cx).head());
 4124                    let (buffer, buffer_row) = snapshot
 4125                        .buffer_snapshot
 4126                        .buffer_line_for_row(MultiBufferRow(multibuffer_point.row))
 4127                        .and_then(|(buffer_snapshot, range)| {
 4128                            editor
 4129                                .buffer
 4130                                .read(cx)
 4131                                .buffer(buffer_snapshot.remote_id())
 4132                                .map(|buffer| (buffer, range.start.row))
 4133                        })?;
 4134                    let (_, code_actions) = editor
 4135                        .available_code_actions
 4136                        .clone()
 4137                        .and_then(|(location, code_actions)| {
 4138                            let snapshot = location.buffer.read(cx).snapshot();
 4139                            let point_range = location.range.to_point(&snapshot);
 4140                            let point_range = point_range.start.row..=point_range.end.row;
 4141                            if point_range.contains(&buffer_row) {
 4142                                Some((location, code_actions))
 4143                            } else {
 4144                                None
 4145                            }
 4146                        })
 4147                        .unzip();
 4148                    let buffer_id = buffer.read(cx).remote_id();
 4149                    let tasks = editor
 4150                        .tasks
 4151                        .get(&(buffer_id, buffer_row))
 4152                        .map(|t| Arc::new(t.to_owned()));
 4153                    if tasks.is_none() && code_actions.is_none() {
 4154                        return None;
 4155                    }
 4156
 4157                    editor.completion_tasks.clear();
 4158                    editor.discard_inline_completion(false, cx);
 4159                    let task_context =
 4160                        tasks
 4161                            .as_ref()
 4162                            .zip(editor.project.clone())
 4163                            .map(|(tasks, project)| {
 4164                                Self::build_tasks_context(&project, &buffer, buffer_row, tasks, cx)
 4165                            });
 4166
 4167                    Some(cx.spawn(|editor, mut cx| async move {
 4168                        let task_context = match task_context {
 4169                            Some(task_context) => task_context.await,
 4170                            None => None,
 4171                        };
 4172                        let resolved_tasks =
 4173                            tasks.zip(task_context).map(|(tasks, task_context)| {
 4174                                Rc::new(ResolvedTasks {
 4175                                    templates: tasks.resolve(&task_context).collect(),
 4176                                    position: snapshot.buffer_snapshot.anchor_before(Point::new(
 4177                                        multibuffer_point.row,
 4178                                        tasks.column,
 4179                                    )),
 4180                                })
 4181                            });
 4182                        let spawn_straight_away = resolved_tasks
 4183                            .as_ref()
 4184                            .map_or(false, |tasks| tasks.templates.len() == 1)
 4185                            && code_actions
 4186                                .as_ref()
 4187                                .map_or(true, |actions| actions.is_empty());
 4188                        if let Ok(task) = editor.update(&mut cx, |editor, cx| {
 4189                            *editor.context_menu.borrow_mut() =
 4190                                Some(CodeContextMenu::CodeActions(CodeActionsMenu {
 4191                                    buffer,
 4192                                    actions: CodeActionContents {
 4193                                        tasks: resolved_tasks,
 4194                                        actions: code_actions,
 4195                                    },
 4196                                    selected_item: Default::default(),
 4197                                    scroll_handle: UniformListScrollHandle::default(),
 4198                                    deployed_from_indicator,
 4199                                }));
 4200                            if spawn_straight_away {
 4201                                if let Some(task) = editor.confirm_code_action(
 4202                                    &ConfirmCodeAction { item_ix: Some(0) },
 4203                                    cx,
 4204                                ) {
 4205                                    cx.notify();
 4206                                    return task;
 4207                                }
 4208                            }
 4209                            cx.notify();
 4210                            Task::ready(Ok(()))
 4211                        }) {
 4212                            task.await
 4213                        } else {
 4214                            Ok(())
 4215                        }
 4216                    }))
 4217                } else {
 4218                    Some(Task::ready(Ok(())))
 4219                }
 4220            })?;
 4221            if let Some(task) = spawned_test_task {
 4222                task.await?;
 4223            }
 4224
 4225            Ok::<_, anyhow::Error>(())
 4226        })
 4227        .detach_and_log_err(cx);
 4228    }
 4229
 4230    pub fn confirm_code_action(
 4231        &mut self,
 4232        action: &ConfirmCodeAction,
 4233        cx: &mut ViewContext<Self>,
 4234    ) -> Option<Task<Result<()>>> {
 4235        let actions_menu = if let CodeContextMenu::CodeActions(menu) = self.hide_context_menu(cx)? {
 4236            menu
 4237        } else {
 4238            return None;
 4239        };
 4240        let action_ix = action.item_ix.unwrap_or(actions_menu.selected_item);
 4241        let action = actions_menu.actions.get(action_ix)?;
 4242        let title = action.label();
 4243        let buffer = actions_menu.buffer;
 4244        let workspace = self.workspace()?;
 4245
 4246        match action {
 4247            CodeActionsItem::Task(task_source_kind, resolved_task) => {
 4248                workspace.update(cx, |workspace, cx| {
 4249                    workspace::tasks::schedule_resolved_task(
 4250                        workspace,
 4251                        task_source_kind,
 4252                        resolved_task,
 4253                        false,
 4254                        cx,
 4255                    );
 4256
 4257                    Some(Task::ready(Ok(())))
 4258                })
 4259            }
 4260            CodeActionsItem::CodeAction {
 4261                excerpt_id,
 4262                action,
 4263                provider,
 4264            } => {
 4265                let apply_code_action =
 4266                    provider.apply_code_action(buffer, action, excerpt_id, true, cx);
 4267                let workspace = workspace.downgrade();
 4268                Some(cx.spawn(|editor, cx| async move {
 4269                    let project_transaction = apply_code_action.await?;
 4270                    Self::open_project_transaction(
 4271                        &editor,
 4272                        workspace,
 4273                        project_transaction,
 4274                        title,
 4275                        cx,
 4276                    )
 4277                    .await
 4278                }))
 4279            }
 4280        }
 4281    }
 4282
 4283    pub async fn open_project_transaction(
 4284        this: &WeakView<Editor>,
 4285        workspace: WeakView<Workspace>,
 4286        transaction: ProjectTransaction,
 4287        title: String,
 4288        mut cx: AsyncWindowContext,
 4289    ) -> Result<()> {
 4290        let mut entries = transaction.0.into_iter().collect::<Vec<_>>();
 4291        cx.update(|cx| {
 4292            entries.sort_unstable_by_key(|(buffer, _)| {
 4293                buffer.read(cx).file().map(|f| f.path().clone())
 4294            });
 4295        })?;
 4296
 4297        // If the project transaction's edits are all contained within this editor, then
 4298        // avoid opening a new editor to display them.
 4299
 4300        if let Some((buffer, transaction)) = entries.first() {
 4301            if entries.len() == 1 {
 4302                let excerpt = this.update(&mut cx, |editor, cx| {
 4303                    editor
 4304                        .buffer()
 4305                        .read(cx)
 4306                        .excerpt_containing(editor.selections.newest_anchor().head(), cx)
 4307                })?;
 4308                if let Some((_, excerpted_buffer, excerpt_range)) = excerpt {
 4309                    if excerpted_buffer == *buffer {
 4310                        let all_edits_within_excerpt = buffer.read_with(&cx, |buffer, _| {
 4311                            let excerpt_range = excerpt_range.to_offset(buffer);
 4312                            buffer
 4313                                .edited_ranges_for_transaction::<usize>(transaction)
 4314                                .all(|range| {
 4315                                    excerpt_range.start <= range.start
 4316                                        && excerpt_range.end >= range.end
 4317                                })
 4318                        })?;
 4319
 4320                        if all_edits_within_excerpt {
 4321                            return Ok(());
 4322                        }
 4323                    }
 4324                }
 4325            }
 4326        } else {
 4327            return Ok(());
 4328        }
 4329
 4330        let mut ranges_to_highlight = Vec::new();
 4331        let excerpt_buffer = cx.new_model(|cx| {
 4332            let mut multibuffer = MultiBuffer::new(Capability::ReadWrite).with_title(title);
 4333            for (buffer_handle, transaction) in &entries {
 4334                let buffer = buffer_handle.read(cx);
 4335                ranges_to_highlight.extend(
 4336                    multibuffer.push_excerpts_with_context_lines(
 4337                        buffer_handle.clone(),
 4338                        buffer
 4339                            .edited_ranges_for_transaction::<usize>(transaction)
 4340                            .collect(),
 4341                        DEFAULT_MULTIBUFFER_CONTEXT,
 4342                        cx,
 4343                    ),
 4344                );
 4345            }
 4346            multibuffer.push_transaction(entries.iter().map(|(b, t)| (b, t)), cx);
 4347            multibuffer
 4348        })?;
 4349
 4350        workspace.update(&mut cx, |workspace, cx| {
 4351            let project = workspace.project().clone();
 4352            let editor =
 4353                cx.new_view(|cx| Editor::for_multibuffer(excerpt_buffer, Some(project), true, cx));
 4354            workspace.add_item_to_active_pane(Box::new(editor.clone()), None, true, cx);
 4355            editor.update(cx, |editor, cx| {
 4356                editor.highlight_background::<Self>(
 4357                    &ranges_to_highlight,
 4358                    |theme| theme.editor_highlighted_line_background,
 4359                    cx,
 4360                );
 4361            });
 4362        })?;
 4363
 4364        Ok(())
 4365    }
 4366
 4367    pub fn clear_code_action_providers(&mut self) {
 4368        self.code_action_providers.clear();
 4369        self.available_code_actions.take();
 4370    }
 4371
 4372    pub fn add_code_action_provider(
 4373        &mut self,
 4374        provider: Rc<dyn CodeActionProvider>,
 4375        cx: &mut ViewContext<Self>,
 4376    ) {
 4377        if self
 4378            .code_action_providers
 4379            .iter()
 4380            .any(|existing_provider| existing_provider.id() == provider.id())
 4381        {
 4382            return;
 4383        }
 4384
 4385        self.code_action_providers.push(provider);
 4386        self.refresh_code_actions(cx);
 4387    }
 4388
 4389    pub fn remove_code_action_provider(&mut self, id: Arc<str>, cx: &mut ViewContext<Self>) {
 4390        self.code_action_providers
 4391            .retain(|provider| provider.id() != id);
 4392        self.refresh_code_actions(cx);
 4393    }
 4394
 4395    fn refresh_code_actions(&mut self, cx: &mut ViewContext<Self>) -> Option<()> {
 4396        let buffer = self.buffer.read(cx);
 4397        let newest_selection = self.selections.newest_anchor().clone();
 4398        let (start_buffer, start) = buffer.text_anchor_for_position(newest_selection.start, cx)?;
 4399        let (end_buffer, end) = buffer.text_anchor_for_position(newest_selection.end, cx)?;
 4400        if start_buffer != end_buffer {
 4401            return None;
 4402        }
 4403
 4404        self.code_actions_task = Some(cx.spawn(|this, mut cx| async move {
 4405            cx.background_executor()
 4406                .timer(CODE_ACTIONS_DEBOUNCE_TIMEOUT)
 4407                .await;
 4408
 4409            let (providers, tasks) = this.update(&mut cx, |this, cx| {
 4410                let providers = this.code_action_providers.clone();
 4411                let tasks = this
 4412                    .code_action_providers
 4413                    .iter()
 4414                    .map(|provider| provider.code_actions(&start_buffer, start..end, cx))
 4415                    .collect::<Vec<_>>();
 4416                (providers, tasks)
 4417            })?;
 4418
 4419            let mut actions = Vec::new();
 4420            for (provider, provider_actions) in
 4421                providers.into_iter().zip(future::join_all(tasks).await)
 4422            {
 4423                if let Some(provider_actions) = provider_actions.log_err() {
 4424                    actions.extend(provider_actions.into_iter().map(|action| {
 4425                        AvailableCodeAction {
 4426                            excerpt_id: newest_selection.start.excerpt_id,
 4427                            action,
 4428                            provider: provider.clone(),
 4429                        }
 4430                    }));
 4431                }
 4432            }
 4433
 4434            this.update(&mut cx, |this, cx| {
 4435                this.available_code_actions = if actions.is_empty() {
 4436                    None
 4437                } else {
 4438                    Some((
 4439                        Location {
 4440                            buffer: start_buffer,
 4441                            range: start..end,
 4442                        },
 4443                        actions.into(),
 4444                    ))
 4445                };
 4446                cx.notify();
 4447            })
 4448        }));
 4449        None
 4450    }
 4451
 4452    fn start_inline_blame_timer(&mut self, cx: &mut ViewContext<Self>) {
 4453        if let Some(delay) = ProjectSettings::get_global(cx).git.inline_blame_delay() {
 4454            self.show_git_blame_inline = false;
 4455
 4456            self.show_git_blame_inline_delay_task = Some(cx.spawn(|this, mut cx| async move {
 4457                cx.background_executor().timer(delay).await;
 4458
 4459                this.update(&mut cx, |this, cx| {
 4460                    this.show_git_blame_inline = true;
 4461                    cx.notify();
 4462                })
 4463                .log_err();
 4464            }));
 4465        }
 4466    }
 4467
 4468    fn refresh_document_highlights(&mut self, cx: &mut ViewContext<Self>) -> Option<()> {
 4469        if self.pending_rename.is_some() {
 4470            return None;
 4471        }
 4472
 4473        let provider = self.semantics_provider.clone()?;
 4474        let buffer = self.buffer.read(cx);
 4475        let newest_selection = self.selections.newest_anchor().clone();
 4476        let cursor_position = newest_selection.head();
 4477        let (cursor_buffer, cursor_buffer_position) =
 4478            buffer.text_anchor_for_position(cursor_position, cx)?;
 4479        let (tail_buffer, _) = buffer.text_anchor_for_position(newest_selection.tail(), cx)?;
 4480        if cursor_buffer != tail_buffer {
 4481            return None;
 4482        }
 4483        let debounce = EditorSettings::get_global(cx).lsp_highlight_debounce;
 4484        self.document_highlights_task = Some(cx.spawn(|this, mut cx| async move {
 4485            cx.background_executor()
 4486                .timer(Duration::from_millis(debounce))
 4487                .await;
 4488
 4489            let highlights = if let Some(highlights) = cx
 4490                .update(|cx| {
 4491                    provider.document_highlights(&cursor_buffer, cursor_buffer_position, cx)
 4492                })
 4493                .ok()
 4494                .flatten()
 4495            {
 4496                highlights.await.log_err()
 4497            } else {
 4498                None
 4499            };
 4500
 4501            if let Some(highlights) = highlights {
 4502                this.update(&mut cx, |this, cx| {
 4503                    if this.pending_rename.is_some() {
 4504                        return;
 4505                    }
 4506
 4507                    let buffer_id = cursor_position.buffer_id;
 4508                    let buffer = this.buffer.read(cx);
 4509                    if !buffer
 4510                        .text_anchor_for_position(cursor_position, cx)
 4511                        .map_or(false, |(buffer, _)| buffer == cursor_buffer)
 4512                    {
 4513                        return;
 4514                    }
 4515
 4516                    let cursor_buffer_snapshot = cursor_buffer.read(cx);
 4517                    let mut write_ranges = Vec::new();
 4518                    let mut read_ranges = Vec::new();
 4519                    for highlight in highlights {
 4520                        for (excerpt_id, excerpt_range) in
 4521                            buffer.excerpts_for_buffer(&cursor_buffer, cx)
 4522                        {
 4523                            let start = highlight
 4524                                .range
 4525                                .start
 4526                                .max(&excerpt_range.context.start, cursor_buffer_snapshot);
 4527                            let end = highlight
 4528                                .range
 4529                                .end
 4530                                .min(&excerpt_range.context.end, cursor_buffer_snapshot);
 4531                            if start.cmp(&end, cursor_buffer_snapshot).is_ge() {
 4532                                continue;
 4533                            }
 4534
 4535                            let range = Anchor {
 4536                                buffer_id,
 4537                                excerpt_id,
 4538                                text_anchor: start,
 4539                            }..Anchor {
 4540                                buffer_id,
 4541                                excerpt_id,
 4542                                text_anchor: end,
 4543                            };
 4544                            if highlight.kind == lsp::DocumentHighlightKind::WRITE {
 4545                                write_ranges.push(range);
 4546                            } else {
 4547                                read_ranges.push(range);
 4548                            }
 4549                        }
 4550                    }
 4551
 4552                    this.highlight_background::<DocumentHighlightRead>(
 4553                        &read_ranges,
 4554                        |theme| theme.editor_document_highlight_read_background,
 4555                        cx,
 4556                    );
 4557                    this.highlight_background::<DocumentHighlightWrite>(
 4558                        &write_ranges,
 4559                        |theme| theme.editor_document_highlight_write_background,
 4560                        cx,
 4561                    );
 4562                    cx.notify();
 4563                })
 4564                .log_err();
 4565            }
 4566        }));
 4567        None
 4568    }
 4569
 4570    pub fn refresh_inline_completion(
 4571        &mut self,
 4572        debounce: bool,
 4573        user_requested: bool,
 4574        cx: &mut ViewContext<Self>,
 4575    ) -> Option<()> {
 4576        let provider = self.inline_completion_provider()?;
 4577        let cursor = self.selections.newest_anchor().head();
 4578        let (buffer, cursor_buffer_position) =
 4579            self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
 4580
 4581        if !user_requested
 4582            && (!self.enable_inline_completions
 4583                || !self.should_show_inline_completions(&buffer, cursor_buffer_position, cx)
 4584                || !self.is_focused(cx)
 4585                || buffer.read(cx).is_empty())
 4586        {
 4587            self.discard_inline_completion(false, cx);
 4588            return None;
 4589        }
 4590
 4591        self.update_visible_inline_completion(cx);
 4592        provider.refresh(buffer, cursor_buffer_position, debounce, cx);
 4593        Some(())
 4594    }
 4595
 4596    fn cycle_inline_completion(
 4597        &mut self,
 4598        direction: Direction,
 4599        cx: &mut ViewContext<Self>,
 4600    ) -> Option<()> {
 4601        let provider = self.inline_completion_provider()?;
 4602        let cursor = self.selections.newest_anchor().head();
 4603        let (buffer, cursor_buffer_position) =
 4604            self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
 4605        if !self.enable_inline_completions
 4606            || !self.should_show_inline_completions(&buffer, cursor_buffer_position, cx)
 4607        {
 4608            return None;
 4609        }
 4610
 4611        provider.cycle(buffer, cursor_buffer_position, direction, cx);
 4612        self.update_visible_inline_completion(cx);
 4613
 4614        Some(())
 4615    }
 4616
 4617    pub fn show_inline_completion(&mut self, _: &ShowInlineCompletion, cx: &mut ViewContext<Self>) {
 4618        if !self.has_active_inline_completion() {
 4619            self.refresh_inline_completion(false, true, cx);
 4620            return;
 4621        }
 4622
 4623        self.update_visible_inline_completion(cx);
 4624    }
 4625
 4626    pub fn display_cursor_names(&mut self, _: &DisplayCursorNames, cx: &mut ViewContext<Self>) {
 4627        self.show_cursor_names(cx);
 4628    }
 4629
 4630    fn show_cursor_names(&mut self, cx: &mut ViewContext<Self>) {
 4631        self.show_cursor_names = true;
 4632        cx.notify();
 4633        cx.spawn(|this, mut cx| async move {
 4634            cx.background_executor().timer(CURSORS_VISIBLE_FOR).await;
 4635            this.update(&mut cx, |this, cx| {
 4636                this.show_cursor_names = false;
 4637                cx.notify()
 4638            })
 4639            .ok()
 4640        })
 4641        .detach();
 4642    }
 4643
 4644    pub fn next_inline_completion(&mut self, _: &NextInlineCompletion, cx: &mut ViewContext<Self>) {
 4645        if self.has_active_inline_completion() {
 4646            self.cycle_inline_completion(Direction::Next, cx);
 4647        } else {
 4648            let is_copilot_disabled = self.refresh_inline_completion(false, true, cx).is_none();
 4649            if is_copilot_disabled {
 4650                cx.propagate();
 4651            }
 4652        }
 4653    }
 4654
 4655    pub fn previous_inline_completion(
 4656        &mut self,
 4657        _: &PreviousInlineCompletion,
 4658        cx: &mut ViewContext<Self>,
 4659    ) {
 4660        if self.has_active_inline_completion() {
 4661            self.cycle_inline_completion(Direction::Prev, cx);
 4662        } else {
 4663            let is_copilot_disabled = self.refresh_inline_completion(false, true, cx).is_none();
 4664            if is_copilot_disabled {
 4665                cx.propagate();
 4666            }
 4667        }
 4668    }
 4669
 4670    pub fn accept_inline_completion(
 4671        &mut self,
 4672        _: &AcceptInlineCompletion,
 4673        cx: &mut ViewContext<Self>,
 4674    ) {
 4675        let buffer = self.buffer.read(cx);
 4676        let snapshot = buffer.snapshot(cx);
 4677        let selection = self.selections.newest_adjusted(cx);
 4678        let cursor = selection.head();
 4679        let current_indent = snapshot.indent_size_for_line(MultiBufferRow(cursor.row));
 4680        let suggested_indents = snapshot.suggested_indents([cursor.row], cx);
 4681        if let Some(suggested_indent) = suggested_indents.get(&MultiBufferRow(cursor.row)).copied()
 4682        {
 4683            if cursor.column < suggested_indent.len
 4684                && cursor.column <= current_indent.len
 4685                && current_indent.len <= suggested_indent.len
 4686            {
 4687                self.tab(&Default::default(), cx);
 4688                return;
 4689            }
 4690        }
 4691
 4692        if self.show_inline_completions_in_menu(cx) {
 4693            self.hide_context_menu(cx);
 4694        }
 4695
 4696        let Some(active_inline_completion) = self.active_inline_completion.as_ref() else {
 4697            return;
 4698        };
 4699
 4700        self.report_inline_completion_event(true, cx);
 4701
 4702        match &active_inline_completion.completion {
 4703            InlineCompletion::Move(position) => {
 4704                let position = *position;
 4705                self.change_selections(Some(Autoscroll::newest()), cx, |selections| {
 4706                    selections.select_anchor_ranges([position..position]);
 4707                });
 4708            }
 4709            InlineCompletion::Edit { edits, .. } => {
 4710                if let Some(provider) = self.inline_completion_provider() {
 4711                    provider.accept(cx);
 4712                }
 4713
 4714                let snapshot = self.buffer.read(cx).snapshot(cx);
 4715                let last_edit_end = edits.last().unwrap().0.end.bias_right(&snapshot);
 4716
 4717                self.buffer.update(cx, |buffer, cx| {
 4718                    buffer.edit(edits.iter().cloned(), None, cx)
 4719                });
 4720
 4721                self.change_selections(None, cx, |s| {
 4722                    s.select_anchor_ranges([last_edit_end..last_edit_end])
 4723                });
 4724
 4725                self.update_visible_inline_completion(cx);
 4726                if self.active_inline_completion.is_none() {
 4727                    self.refresh_inline_completion(true, true, cx);
 4728                }
 4729
 4730                cx.notify();
 4731            }
 4732        }
 4733    }
 4734
 4735    pub fn accept_partial_inline_completion(
 4736        &mut self,
 4737        _: &AcceptPartialInlineCompletion,
 4738        cx: &mut ViewContext<Self>,
 4739    ) {
 4740        let Some(active_inline_completion) = self.active_inline_completion.as_ref() else {
 4741            return;
 4742        };
 4743        if self.selections.count() != 1 {
 4744            return;
 4745        }
 4746
 4747        self.report_inline_completion_event(true, cx);
 4748
 4749        match &active_inline_completion.completion {
 4750            InlineCompletion::Move(position) => {
 4751                let position = *position;
 4752                self.change_selections(Some(Autoscroll::newest()), cx, |selections| {
 4753                    selections.select_anchor_ranges([position..position]);
 4754                });
 4755            }
 4756            InlineCompletion::Edit { edits, .. } => {
 4757                // Find an insertion that starts at the cursor position.
 4758                let snapshot = self.buffer.read(cx).snapshot(cx);
 4759                let cursor_offset = self.selections.newest::<usize>(cx).head();
 4760                let insertion = edits.iter().find_map(|(range, text)| {
 4761                    let range = range.to_offset(&snapshot);
 4762                    if range.is_empty() && range.start == cursor_offset {
 4763                        Some(text)
 4764                    } else {
 4765                        None
 4766                    }
 4767                });
 4768
 4769                if let Some(text) = insertion {
 4770                    let mut partial_completion = text
 4771                        .chars()
 4772                        .by_ref()
 4773                        .take_while(|c| c.is_alphabetic())
 4774                        .collect::<String>();
 4775                    if partial_completion.is_empty() {
 4776                        partial_completion = text
 4777                            .chars()
 4778                            .by_ref()
 4779                            .take_while(|c| c.is_whitespace() || !c.is_alphabetic())
 4780                            .collect::<String>();
 4781                    }
 4782
 4783                    cx.emit(EditorEvent::InputHandled {
 4784                        utf16_range_to_replace: None,
 4785                        text: partial_completion.clone().into(),
 4786                    });
 4787
 4788                    self.insert_with_autoindent_mode(&partial_completion, None, cx);
 4789
 4790                    self.refresh_inline_completion(true, true, cx);
 4791                    cx.notify();
 4792                } else {
 4793                    self.accept_inline_completion(&Default::default(), cx);
 4794                }
 4795            }
 4796        }
 4797    }
 4798
 4799    fn discard_inline_completion(
 4800        &mut self,
 4801        should_report_inline_completion_event: bool,
 4802        cx: &mut ViewContext<Self>,
 4803    ) -> bool {
 4804        if should_report_inline_completion_event {
 4805            self.report_inline_completion_event(false, cx);
 4806        }
 4807
 4808        if let Some(provider) = self.inline_completion_provider() {
 4809            provider.discard(cx);
 4810        }
 4811
 4812        self.take_active_inline_completion(cx).is_some()
 4813    }
 4814
 4815    fn report_inline_completion_event(&self, accepted: bool, cx: &AppContext) {
 4816        let Some(provider) = self.inline_completion_provider() else {
 4817            return;
 4818        };
 4819
 4820        let Some((_, buffer, _)) = self
 4821            .buffer
 4822            .read(cx)
 4823            .excerpt_containing(self.selections.newest_anchor().head(), cx)
 4824        else {
 4825            return;
 4826        };
 4827
 4828        let extension = buffer
 4829            .read(cx)
 4830            .file()
 4831            .and_then(|file| Some(file.path().extension()?.to_string_lossy().to_string()));
 4832
 4833        let event_type = match accepted {
 4834            true => "Inline Completion Accepted",
 4835            false => "Inline Completion Discarded",
 4836        };
 4837        telemetry::event!(
 4838            event_type,
 4839            provider = provider.name(),
 4840            suggestion_accepted = accepted,
 4841            file_extension = extension,
 4842        );
 4843    }
 4844
 4845    pub fn has_active_inline_completion(&self) -> bool {
 4846        self.active_inline_completion.is_some()
 4847    }
 4848
 4849    fn take_active_inline_completion(
 4850        &mut self,
 4851        cx: &mut ViewContext<Self>,
 4852    ) -> Option<InlineCompletion> {
 4853        let active_inline_completion = self.active_inline_completion.take()?;
 4854        self.splice_inlays(active_inline_completion.inlay_ids, Default::default(), cx);
 4855        self.clear_highlights::<InlineCompletionHighlight>(cx);
 4856        Some(active_inline_completion.completion)
 4857    }
 4858
 4859    fn update_visible_inline_completion(&mut self, cx: &mut ViewContext<Self>) -> Option<()> {
 4860        let selection = self.selections.newest_anchor();
 4861        let cursor = selection.head();
 4862        let multibuffer = self.buffer.read(cx).snapshot(cx);
 4863        let offset_selection = selection.map(|endpoint| endpoint.to_offset(&multibuffer));
 4864        let excerpt_id = cursor.excerpt_id;
 4865
 4866        let completions_menu_has_precedence = !self.show_inline_completions_in_menu(cx)
 4867            && (self.context_menu.borrow().is_some()
 4868                || (!self.completion_tasks.is_empty() && !self.has_active_inline_completion()));
 4869        if completions_menu_has_precedence
 4870            || !offset_selection.is_empty()
 4871            || !self.enable_inline_completions
 4872            || self
 4873                .active_inline_completion
 4874                .as_ref()
 4875                .map_or(false, |completion| {
 4876                    let invalidation_range = completion.invalidation_range.to_offset(&multibuffer);
 4877                    let invalidation_range = invalidation_range.start..=invalidation_range.end;
 4878                    !invalidation_range.contains(&offset_selection.head())
 4879                })
 4880        {
 4881            self.discard_inline_completion(false, cx);
 4882            return None;
 4883        }
 4884
 4885        self.take_active_inline_completion(cx);
 4886        let provider = self.inline_completion_provider()?;
 4887
 4888        let (buffer, cursor_buffer_position) =
 4889            self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
 4890
 4891        let inline_completion = provider.suggest(&buffer, cursor_buffer_position, cx)?;
 4892        let edits = inline_completion
 4893            .edits
 4894            .into_iter()
 4895            .flat_map(|(range, new_text)| {
 4896                let start = multibuffer.anchor_in_excerpt(excerpt_id, range.start)?;
 4897                let end = multibuffer.anchor_in_excerpt(excerpt_id, range.end)?;
 4898                Some((start..end, new_text))
 4899            })
 4900            .collect::<Vec<_>>();
 4901        if edits.is_empty() {
 4902            return None;
 4903        }
 4904
 4905        let first_edit_start = edits.first().unwrap().0.start;
 4906        let first_edit_start_point = first_edit_start.to_point(&multibuffer);
 4907        let edit_start_row = first_edit_start_point.row.saturating_sub(2);
 4908
 4909        let last_edit_end = edits.last().unwrap().0.end;
 4910        let last_edit_end_point = last_edit_end.to_point(&multibuffer);
 4911        let edit_end_row = cmp::min(multibuffer.max_point().row, last_edit_end_point.row + 2);
 4912
 4913        let cursor_row = cursor.to_point(&multibuffer).row;
 4914
 4915        let mut inlay_ids = Vec::new();
 4916        let invalidation_row_range;
 4917        let completion = if cursor_row < edit_start_row {
 4918            invalidation_row_range = cursor_row..edit_end_row;
 4919            InlineCompletion::Move(first_edit_start)
 4920        } else if cursor_row > edit_end_row {
 4921            invalidation_row_range = edit_start_row..cursor_row;
 4922            InlineCompletion::Move(first_edit_start)
 4923        } else {
 4924            if edits
 4925                .iter()
 4926                .all(|(range, _)| range.to_offset(&multibuffer).is_empty())
 4927            {
 4928                let mut inlays = Vec::new();
 4929                for (range, new_text) in &edits {
 4930                    let inlay = Inlay::inline_completion(
 4931                        post_inc(&mut self.next_inlay_id),
 4932                        range.start,
 4933                        new_text.as_str(),
 4934                    );
 4935                    inlay_ids.push(inlay.id);
 4936                    inlays.push(inlay);
 4937                }
 4938
 4939                self.splice_inlays(vec![], inlays, cx);
 4940            } else {
 4941                let background_color = cx.theme().status().deleted_background;
 4942                self.highlight_text::<InlineCompletionHighlight>(
 4943                    edits.iter().map(|(range, _)| range.clone()).collect(),
 4944                    HighlightStyle {
 4945                        background_color: Some(background_color),
 4946                        ..Default::default()
 4947                    },
 4948                    cx,
 4949                );
 4950            }
 4951
 4952            invalidation_row_range = edit_start_row..edit_end_row;
 4953
 4954            let display_mode = if all_edits_insertions_or_deletions(&edits, &multibuffer) {
 4955                if provider.show_tab_accept_marker()
 4956                    && first_edit_start_point.row == last_edit_end_point.row
 4957                    && !edits.iter().any(|(_, edit)| edit.contains('\n'))
 4958                {
 4959                    EditDisplayMode::TabAccept
 4960                } else {
 4961                    EditDisplayMode::Inline
 4962                }
 4963            } else {
 4964                EditDisplayMode::DiffPopover
 4965            };
 4966
 4967            let snapshot = multibuffer.buffer_for_excerpt(excerpt_id).cloned()?;
 4968
 4969            InlineCompletion::Edit {
 4970                edits,
 4971                edit_preview: inline_completion.edit_preview,
 4972                display_mode,
 4973                snapshot,
 4974            }
 4975        };
 4976
 4977        let invalidation_range = multibuffer
 4978            .anchor_before(Point::new(invalidation_row_range.start, 0))
 4979            ..multibuffer.anchor_after(Point::new(
 4980                invalidation_row_range.end,
 4981                multibuffer.line_len(MultiBufferRow(invalidation_row_range.end)),
 4982            ));
 4983
 4984        self.active_inline_completion = Some(InlineCompletionState {
 4985            inlay_ids,
 4986            completion,
 4987            invalidation_range,
 4988        });
 4989
 4990        if self.show_inline_completions_in_menu(cx) && self.has_active_completions_menu() {
 4991            if let Some(hint) = self.inline_completion_menu_hint(cx) {
 4992                match self.context_menu.borrow_mut().as_mut() {
 4993                    Some(CodeContextMenu::Completions(menu)) => {
 4994                        menu.show_inline_completion_hint(hint);
 4995                    }
 4996                    _ => {}
 4997                }
 4998            }
 4999        }
 5000
 5001        cx.notify();
 5002
 5003        Some(())
 5004    }
 5005
 5006    fn inline_completion_menu_hint(
 5007        &self,
 5008        cx: &mut ViewContext<Self>,
 5009    ) -> Option<InlineCompletionMenuHint> {
 5010        let provider = self.inline_completion_provider()?;
 5011        if self.has_active_inline_completion() {
 5012            let editor_snapshot = self.snapshot(cx);
 5013
 5014            let text = match &self.active_inline_completion.as_ref()?.completion {
 5015                InlineCompletion::Edit {
 5016                    edits,
 5017                    edit_preview,
 5018                    display_mode: _,
 5019                    snapshot,
 5020                } => edit_preview
 5021                    .as_ref()
 5022                    .and_then(|edit_preview| {
 5023                        inline_completion_edit_text(&snapshot, &edits, edit_preview, true, cx)
 5024                    })
 5025                    .map(InlineCompletionText::Edit),
 5026                InlineCompletion::Move(target) => {
 5027                    let target_point =
 5028                        target.to_point(&editor_snapshot.display_snapshot.buffer_snapshot);
 5029                    let target_line = target_point.row + 1;
 5030                    Some(InlineCompletionText::Move(
 5031                        format!("Jump to edit in line {}", target_line).into(),
 5032                    ))
 5033                }
 5034            };
 5035
 5036            Some(InlineCompletionMenuHint::Loaded { text: text? })
 5037        } else if provider.is_refreshing(cx) {
 5038            Some(InlineCompletionMenuHint::Loading)
 5039        } else if provider.needs_terms_acceptance(cx) {
 5040            Some(InlineCompletionMenuHint::PendingTermsAcceptance)
 5041        } else {
 5042            Some(InlineCompletionMenuHint::None)
 5043        }
 5044    }
 5045
 5046    pub fn inline_completion_provider(&self) -> Option<Arc<dyn InlineCompletionProviderHandle>> {
 5047        Some(self.inline_completion_provider.as_ref()?.provider.clone())
 5048    }
 5049
 5050    fn show_inline_completions_in_menu(&self, cx: &AppContext) -> bool {
 5051        let by_provider = matches!(
 5052            self.menu_inline_completions_policy,
 5053            MenuInlineCompletionsPolicy::ByProvider
 5054        );
 5055
 5056        by_provider
 5057            && EditorSettings::get_global(cx).show_inline_completions_in_menu
 5058            && self
 5059                .inline_completion_provider()
 5060                .map_or(false, |provider| provider.show_completions_in_menu())
 5061    }
 5062
 5063    fn render_code_actions_indicator(
 5064        &self,
 5065        _style: &EditorStyle,
 5066        row: DisplayRow,
 5067        is_active: bool,
 5068        cx: &mut ViewContext<Self>,
 5069    ) -> Option<IconButton> {
 5070        if self.available_code_actions.is_some() {
 5071            Some(
 5072                IconButton::new("code_actions_indicator", ui::IconName::Bolt)
 5073                    .shape(ui::IconButtonShape::Square)
 5074                    .icon_size(IconSize::XSmall)
 5075                    .icon_color(Color::Muted)
 5076                    .toggle_state(is_active)
 5077                    .tooltip({
 5078                        let focus_handle = self.focus_handle.clone();
 5079                        move |cx| {
 5080                            Tooltip::for_action_in(
 5081                                "Toggle Code Actions",
 5082                                &ToggleCodeActions {
 5083                                    deployed_from_indicator: None,
 5084                                },
 5085                                &focus_handle,
 5086                                cx,
 5087                            )
 5088                        }
 5089                    })
 5090                    .on_click(cx.listener(move |editor, _e, cx| {
 5091                        editor.focus(cx);
 5092                        editor.toggle_code_actions(
 5093                            &ToggleCodeActions {
 5094                                deployed_from_indicator: Some(row),
 5095                            },
 5096                            cx,
 5097                        );
 5098                    })),
 5099            )
 5100        } else {
 5101            None
 5102        }
 5103    }
 5104
 5105    fn clear_tasks(&mut self) {
 5106        self.tasks.clear()
 5107    }
 5108
 5109    fn insert_tasks(&mut self, key: (BufferId, BufferRow), value: RunnableTasks) {
 5110        if self.tasks.insert(key, value).is_some() {
 5111            // This case should hopefully be rare, but just in case...
 5112            log::error!("multiple different run targets found on a single line, only the last target will be rendered")
 5113        }
 5114    }
 5115
 5116    fn build_tasks_context(
 5117        project: &Model<Project>,
 5118        buffer: &Model<Buffer>,
 5119        buffer_row: u32,
 5120        tasks: &Arc<RunnableTasks>,
 5121        cx: &mut ViewContext<Self>,
 5122    ) -> Task<Option<task::TaskContext>> {
 5123        let position = Point::new(buffer_row, tasks.column);
 5124        let range_start = buffer.read(cx).anchor_at(position, Bias::Right);
 5125        let location = Location {
 5126            buffer: buffer.clone(),
 5127            range: range_start..range_start,
 5128        };
 5129        // Fill in the environmental variables from the tree-sitter captures
 5130        let mut captured_task_variables = TaskVariables::default();
 5131        for (capture_name, value) in tasks.extra_variables.clone() {
 5132            captured_task_variables.insert(
 5133                task::VariableName::Custom(capture_name.into()),
 5134                value.clone(),
 5135            );
 5136        }
 5137        project.update(cx, |project, cx| {
 5138            project.task_store().update(cx, |task_store, cx| {
 5139                task_store.task_context_for_location(captured_task_variables, location, cx)
 5140            })
 5141        })
 5142    }
 5143
 5144    pub fn spawn_nearest_task(&mut self, action: &SpawnNearestTask, cx: &mut ViewContext<Self>) {
 5145        let Some((workspace, _)) = self.workspace.clone() else {
 5146            return;
 5147        };
 5148        let Some(project) = self.project.clone() else {
 5149            return;
 5150        };
 5151
 5152        // Try to find a closest, enclosing node using tree-sitter that has a
 5153        // task
 5154        let Some((buffer, buffer_row, tasks)) = self
 5155            .find_enclosing_node_task(cx)
 5156            // Or find the task that's closest in row-distance.
 5157            .or_else(|| self.find_closest_task(cx))
 5158        else {
 5159            return;
 5160        };
 5161
 5162        let reveal_strategy = action.reveal;
 5163        let task_context = Self::build_tasks_context(&project, &buffer, buffer_row, &tasks, cx);
 5164        cx.spawn(|_, mut cx| async move {
 5165            let context = task_context.await?;
 5166            let (task_source_kind, mut resolved_task) = tasks.resolve(&context).next()?;
 5167
 5168            let resolved = resolved_task.resolved.as_mut()?;
 5169            resolved.reveal = reveal_strategy;
 5170
 5171            workspace
 5172                .update(&mut cx, |workspace, cx| {
 5173                    workspace::tasks::schedule_resolved_task(
 5174                        workspace,
 5175                        task_source_kind,
 5176                        resolved_task,
 5177                        false,
 5178                        cx,
 5179                    );
 5180                })
 5181                .ok()
 5182        })
 5183        .detach();
 5184    }
 5185
 5186    fn find_closest_task(
 5187        &mut self,
 5188        cx: &mut ViewContext<Self>,
 5189    ) -> Option<(Model<Buffer>, u32, Arc<RunnableTasks>)> {
 5190        let cursor_row = self.selections.newest_adjusted(cx).head().row;
 5191
 5192        let ((buffer_id, row), tasks) = self
 5193            .tasks
 5194            .iter()
 5195            .min_by_key(|((_, row), _)| cursor_row.abs_diff(*row))?;
 5196
 5197        let buffer = self.buffer.read(cx).buffer(*buffer_id)?;
 5198        let tasks = Arc::new(tasks.to_owned());
 5199        Some((buffer, *row, tasks))
 5200    }
 5201
 5202    fn find_enclosing_node_task(
 5203        &mut self,
 5204        cx: &mut ViewContext<Self>,
 5205    ) -> Option<(Model<Buffer>, u32, Arc<RunnableTasks>)> {
 5206        let snapshot = self.buffer.read(cx).snapshot(cx);
 5207        let offset = self.selections.newest::<usize>(cx).head();
 5208        let excerpt = snapshot.excerpt_containing(offset..offset)?;
 5209        let buffer_id = excerpt.buffer().remote_id();
 5210
 5211        let layer = excerpt.buffer().syntax_layer_at(offset)?;
 5212        let mut cursor = layer.node().walk();
 5213
 5214        while cursor.goto_first_child_for_byte(offset).is_some() {
 5215            if cursor.node().end_byte() == offset {
 5216                cursor.goto_next_sibling();
 5217            }
 5218        }
 5219
 5220        // Ascend to the smallest ancestor that contains the range and has a task.
 5221        loop {
 5222            let node = cursor.node();
 5223            let node_range = node.byte_range();
 5224            let symbol_start_row = excerpt.buffer().offset_to_point(node.start_byte()).row;
 5225
 5226            // Check if this node contains our offset
 5227            if node_range.start <= offset && node_range.end >= offset {
 5228                // If it contains offset, check for task
 5229                if let Some(tasks) = self.tasks.get(&(buffer_id, symbol_start_row)) {
 5230                    let buffer = self.buffer.read(cx).buffer(buffer_id)?;
 5231                    return Some((buffer, symbol_start_row, Arc::new(tasks.to_owned())));
 5232                }
 5233            }
 5234
 5235            if !cursor.goto_parent() {
 5236                break;
 5237            }
 5238        }
 5239        None
 5240    }
 5241
 5242    fn render_run_indicator(
 5243        &self,
 5244        _style: &EditorStyle,
 5245        is_active: bool,
 5246        row: DisplayRow,
 5247        cx: &mut ViewContext<Self>,
 5248    ) -> IconButton {
 5249        IconButton::new(("run_indicator", row.0 as usize), ui::IconName::Play)
 5250            .shape(ui::IconButtonShape::Square)
 5251            .icon_size(IconSize::XSmall)
 5252            .icon_color(Color::Muted)
 5253            .toggle_state(is_active)
 5254            .on_click(cx.listener(move |editor, _e, cx| {
 5255                editor.focus(cx);
 5256                editor.toggle_code_actions(
 5257                    &ToggleCodeActions {
 5258                        deployed_from_indicator: Some(row),
 5259                    },
 5260                    cx,
 5261                );
 5262            }))
 5263    }
 5264
 5265    #[cfg(any(feature = "test-support", test))]
 5266    pub fn context_menu_visible(&self) -> bool {
 5267        self.context_menu
 5268            .borrow()
 5269            .as_ref()
 5270            .map_or(false, |menu| menu.visible())
 5271    }
 5272
 5273    #[cfg(feature = "test-support")]
 5274    pub fn context_menu_contains_inline_completion(&self) -> bool {
 5275        self.context_menu
 5276            .borrow()
 5277            .as_ref()
 5278            .map_or(false, |menu| match menu {
 5279                CodeContextMenu::Completions(menu) => {
 5280                    menu.entries.borrow().first().map_or(false, |entry| {
 5281                        matches!(entry, CompletionEntry::InlineCompletionHint(_))
 5282                    })
 5283                }
 5284                CodeContextMenu::CodeActions(_) => false,
 5285            })
 5286    }
 5287
 5288    fn context_menu_origin(&self, cursor_position: DisplayPoint) -> Option<ContextMenuOrigin> {
 5289        self.context_menu
 5290            .borrow()
 5291            .as_ref()
 5292            .map(|menu| menu.origin(cursor_position))
 5293    }
 5294
 5295    fn render_context_menu(
 5296        &self,
 5297        style: &EditorStyle,
 5298        max_height_in_lines: u32,
 5299        y_flipped: bool,
 5300        cx: &mut ViewContext<Editor>,
 5301    ) -> Option<AnyElement> {
 5302        self.context_menu.borrow().as_ref().and_then(|menu| {
 5303            if menu.visible() {
 5304                Some(menu.render(style, max_height_in_lines, y_flipped, cx))
 5305            } else {
 5306                None
 5307            }
 5308        })
 5309    }
 5310
 5311    fn render_context_menu_aside(
 5312        &self,
 5313        style: &EditorStyle,
 5314        max_size: Size<Pixels>,
 5315        cx: &mut ViewContext<Editor>,
 5316    ) -> Option<AnyElement> {
 5317        self.context_menu.borrow().as_ref().and_then(|menu| {
 5318            if menu.visible() {
 5319                menu.render_aside(
 5320                    style,
 5321                    max_size,
 5322                    self.workspace.as_ref().map(|(w, _)| w.clone()),
 5323                    cx,
 5324                )
 5325            } else {
 5326                None
 5327            }
 5328        })
 5329    }
 5330
 5331    fn hide_context_menu(&mut self, cx: &mut ViewContext<Self>) -> Option<CodeContextMenu> {
 5332        cx.notify();
 5333        self.completion_tasks.clear();
 5334        let context_menu = self.context_menu.borrow_mut().take();
 5335        if context_menu.is_some() && !self.show_inline_completions_in_menu(cx) {
 5336            self.update_visible_inline_completion(cx);
 5337        }
 5338        context_menu
 5339    }
 5340
 5341    fn show_snippet_choices(
 5342        &mut self,
 5343        choices: &Vec<String>,
 5344        selection: Range<Anchor>,
 5345        cx: &mut ViewContext<Self>,
 5346    ) {
 5347        if selection.start.buffer_id.is_none() {
 5348            return;
 5349        }
 5350        let buffer_id = selection.start.buffer_id.unwrap();
 5351        let buffer = self.buffer().read(cx).buffer(buffer_id);
 5352        let id = post_inc(&mut self.next_completion_id);
 5353
 5354        if let Some(buffer) = buffer {
 5355            *self.context_menu.borrow_mut() = Some(CodeContextMenu::Completions(
 5356                CompletionsMenu::new_snippet_choices(id, true, choices, selection, buffer),
 5357            ));
 5358        }
 5359    }
 5360
 5361    pub fn insert_snippet(
 5362        &mut self,
 5363        insertion_ranges: &[Range<usize>],
 5364        snippet: Snippet,
 5365        cx: &mut ViewContext<Self>,
 5366    ) -> Result<()> {
 5367        struct Tabstop<T> {
 5368            is_end_tabstop: bool,
 5369            ranges: Vec<Range<T>>,
 5370            choices: Option<Vec<String>>,
 5371        }
 5372
 5373        let tabstops = self.buffer.update(cx, |buffer, cx| {
 5374            let snippet_text: Arc<str> = snippet.text.clone().into();
 5375            buffer.edit(
 5376                insertion_ranges
 5377                    .iter()
 5378                    .cloned()
 5379                    .map(|range| (range, snippet_text.clone())),
 5380                Some(AutoindentMode::EachLine),
 5381                cx,
 5382            );
 5383
 5384            let snapshot = &*buffer.read(cx);
 5385            let snippet = &snippet;
 5386            snippet
 5387                .tabstops
 5388                .iter()
 5389                .map(|tabstop| {
 5390                    let is_end_tabstop = tabstop.ranges.first().map_or(false, |tabstop| {
 5391                        tabstop.is_empty() && tabstop.start == snippet.text.len() as isize
 5392                    });
 5393                    let mut tabstop_ranges = tabstop
 5394                        .ranges
 5395                        .iter()
 5396                        .flat_map(|tabstop_range| {
 5397                            let mut delta = 0_isize;
 5398                            insertion_ranges.iter().map(move |insertion_range| {
 5399                                let insertion_start = insertion_range.start as isize + delta;
 5400                                delta +=
 5401                                    snippet.text.len() as isize - insertion_range.len() as isize;
 5402
 5403                                let start = ((insertion_start + tabstop_range.start) as usize)
 5404                                    .min(snapshot.len());
 5405                                let end = ((insertion_start + tabstop_range.end) as usize)
 5406                                    .min(snapshot.len());
 5407                                snapshot.anchor_before(start)..snapshot.anchor_after(end)
 5408                            })
 5409                        })
 5410                        .collect::<Vec<_>>();
 5411                    tabstop_ranges.sort_unstable_by(|a, b| a.start.cmp(&b.start, snapshot));
 5412
 5413                    Tabstop {
 5414                        is_end_tabstop,
 5415                        ranges: tabstop_ranges,
 5416                        choices: tabstop.choices.clone(),
 5417                    }
 5418                })
 5419                .collect::<Vec<_>>()
 5420        });
 5421        if let Some(tabstop) = tabstops.first() {
 5422            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5423                s.select_ranges(tabstop.ranges.iter().cloned());
 5424            });
 5425
 5426            if let Some(choices) = &tabstop.choices {
 5427                if let Some(selection) = tabstop.ranges.first() {
 5428                    self.show_snippet_choices(choices, selection.clone(), cx)
 5429                }
 5430            }
 5431
 5432            // If we're already at the last tabstop and it's at the end of the snippet,
 5433            // we're done, we don't need to keep the state around.
 5434            if !tabstop.is_end_tabstop {
 5435                let choices = tabstops
 5436                    .iter()
 5437                    .map(|tabstop| tabstop.choices.clone())
 5438                    .collect();
 5439
 5440                let ranges = tabstops
 5441                    .into_iter()
 5442                    .map(|tabstop| tabstop.ranges)
 5443                    .collect::<Vec<_>>();
 5444
 5445                self.snippet_stack.push(SnippetState {
 5446                    active_index: 0,
 5447                    ranges,
 5448                    choices,
 5449                });
 5450            }
 5451
 5452            // Check whether the just-entered snippet ends with an auto-closable bracket.
 5453            if self.autoclose_regions.is_empty() {
 5454                let snapshot = self.buffer.read(cx).snapshot(cx);
 5455                for selection in &mut self.selections.all::<Point>(cx) {
 5456                    let selection_head = selection.head();
 5457                    let Some(scope) = snapshot.language_scope_at(selection_head) else {
 5458                        continue;
 5459                    };
 5460
 5461                    let mut bracket_pair = None;
 5462                    let next_chars = snapshot.chars_at(selection_head).collect::<String>();
 5463                    let prev_chars = snapshot
 5464                        .reversed_chars_at(selection_head)
 5465                        .collect::<String>();
 5466                    for (pair, enabled) in scope.brackets() {
 5467                        if enabled
 5468                            && pair.close
 5469                            && prev_chars.starts_with(pair.start.as_str())
 5470                            && next_chars.starts_with(pair.end.as_str())
 5471                        {
 5472                            bracket_pair = Some(pair.clone());
 5473                            break;
 5474                        }
 5475                    }
 5476                    if let Some(pair) = bracket_pair {
 5477                        let start = snapshot.anchor_after(selection_head);
 5478                        let end = snapshot.anchor_after(selection_head);
 5479                        self.autoclose_regions.push(AutocloseRegion {
 5480                            selection_id: selection.id,
 5481                            range: start..end,
 5482                            pair,
 5483                        });
 5484                    }
 5485                }
 5486            }
 5487        }
 5488        Ok(())
 5489    }
 5490
 5491    pub fn move_to_next_snippet_tabstop(&mut self, cx: &mut ViewContext<Self>) -> bool {
 5492        self.move_to_snippet_tabstop(Bias::Right, cx)
 5493    }
 5494
 5495    pub fn move_to_prev_snippet_tabstop(&mut self, cx: &mut ViewContext<Self>) -> bool {
 5496        self.move_to_snippet_tabstop(Bias::Left, cx)
 5497    }
 5498
 5499    pub fn move_to_snippet_tabstop(&mut self, bias: Bias, cx: &mut ViewContext<Self>) -> bool {
 5500        if let Some(mut snippet) = self.snippet_stack.pop() {
 5501            match bias {
 5502                Bias::Left => {
 5503                    if snippet.active_index > 0 {
 5504                        snippet.active_index -= 1;
 5505                    } else {
 5506                        self.snippet_stack.push(snippet);
 5507                        return false;
 5508                    }
 5509                }
 5510                Bias::Right => {
 5511                    if snippet.active_index + 1 < snippet.ranges.len() {
 5512                        snippet.active_index += 1;
 5513                    } else {
 5514                        self.snippet_stack.push(snippet);
 5515                        return false;
 5516                    }
 5517                }
 5518            }
 5519            if let Some(current_ranges) = snippet.ranges.get(snippet.active_index) {
 5520                self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5521                    s.select_anchor_ranges(current_ranges.iter().cloned())
 5522                });
 5523
 5524                if let Some(choices) = &snippet.choices[snippet.active_index] {
 5525                    if let Some(selection) = current_ranges.first() {
 5526                        self.show_snippet_choices(&choices, selection.clone(), cx);
 5527                    }
 5528                }
 5529
 5530                // If snippet state is not at the last tabstop, push it back on the stack
 5531                if snippet.active_index + 1 < snippet.ranges.len() {
 5532                    self.snippet_stack.push(snippet);
 5533                }
 5534                return true;
 5535            }
 5536        }
 5537
 5538        false
 5539    }
 5540
 5541    pub fn clear(&mut self, cx: &mut ViewContext<Self>) {
 5542        self.transact(cx, |this, cx| {
 5543            this.select_all(&SelectAll, cx);
 5544            this.insert("", cx);
 5545        });
 5546    }
 5547
 5548    pub fn backspace(&mut self, _: &Backspace, cx: &mut ViewContext<Self>) {
 5549        self.transact(cx, |this, cx| {
 5550            this.select_autoclose_pair(cx);
 5551            let mut linked_ranges = HashMap::<_, Vec<_>>::default();
 5552            if !this.linked_edit_ranges.is_empty() {
 5553                let selections = this.selections.all::<MultiBufferPoint>(cx);
 5554                let snapshot = this.buffer.read(cx).snapshot(cx);
 5555
 5556                for selection in selections.iter() {
 5557                    let selection_start = snapshot.anchor_before(selection.start).text_anchor;
 5558                    let selection_end = snapshot.anchor_after(selection.end).text_anchor;
 5559                    if selection_start.buffer_id != selection_end.buffer_id {
 5560                        continue;
 5561                    }
 5562                    if let Some(ranges) =
 5563                        this.linked_editing_ranges_for(selection_start..selection_end, cx)
 5564                    {
 5565                        for (buffer, entries) in ranges {
 5566                            linked_ranges.entry(buffer).or_default().extend(entries);
 5567                        }
 5568                    }
 5569                }
 5570            }
 5571
 5572            let mut selections = this.selections.all::<MultiBufferPoint>(cx);
 5573            if !this.selections.line_mode {
 5574                let display_map = this.display_map.update(cx, |map, cx| map.snapshot(cx));
 5575                for selection in &mut selections {
 5576                    if selection.is_empty() {
 5577                        let old_head = selection.head();
 5578                        let mut new_head =
 5579                            movement::left(&display_map, old_head.to_display_point(&display_map))
 5580                                .to_point(&display_map);
 5581                        if let Some((buffer, line_buffer_range)) = display_map
 5582                            .buffer_snapshot
 5583                            .buffer_line_for_row(MultiBufferRow(old_head.row))
 5584                        {
 5585                            let indent_size =
 5586                                buffer.indent_size_for_line(line_buffer_range.start.row);
 5587                            let indent_len = match indent_size.kind {
 5588                                IndentKind::Space => {
 5589                                    buffer.settings_at(line_buffer_range.start, cx).tab_size
 5590                                }
 5591                                IndentKind::Tab => NonZeroU32::new(1).unwrap(),
 5592                            };
 5593                            if old_head.column <= indent_size.len && old_head.column > 0 {
 5594                                let indent_len = indent_len.get();
 5595                                new_head = cmp::min(
 5596                                    new_head,
 5597                                    MultiBufferPoint::new(
 5598                                        old_head.row,
 5599                                        ((old_head.column - 1) / indent_len) * indent_len,
 5600                                    ),
 5601                                );
 5602                            }
 5603                        }
 5604
 5605                        selection.set_head(new_head, SelectionGoal::None);
 5606                    }
 5607                }
 5608            }
 5609
 5610            this.signature_help_state.set_backspace_pressed(true);
 5611            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
 5612            this.insert("", cx);
 5613            let empty_str: Arc<str> = Arc::from("");
 5614            for (buffer, edits) in linked_ranges {
 5615                let snapshot = buffer.read(cx).snapshot();
 5616                use text::ToPoint as TP;
 5617
 5618                let edits = edits
 5619                    .into_iter()
 5620                    .map(|range| {
 5621                        let end_point = TP::to_point(&range.end, &snapshot);
 5622                        let mut start_point = TP::to_point(&range.start, &snapshot);
 5623
 5624                        if end_point == start_point {
 5625                            let offset = text::ToOffset::to_offset(&range.start, &snapshot)
 5626                                .saturating_sub(1);
 5627                            start_point =
 5628                                snapshot.clip_point(TP::to_point(&offset, &snapshot), Bias::Left);
 5629                        };
 5630
 5631                        (start_point..end_point, empty_str.clone())
 5632                    })
 5633                    .sorted_by_key(|(range, _)| range.start)
 5634                    .collect::<Vec<_>>();
 5635                buffer.update(cx, |this, cx| {
 5636                    this.edit(edits, None, cx);
 5637                })
 5638            }
 5639            this.refresh_inline_completion(true, false, cx);
 5640            linked_editing_ranges::refresh_linked_ranges(this, cx);
 5641        });
 5642    }
 5643
 5644    pub fn delete(&mut self, _: &Delete, cx: &mut ViewContext<Self>) {
 5645        self.transact(cx, |this, cx| {
 5646            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5647                let line_mode = s.line_mode;
 5648                s.move_with(|map, selection| {
 5649                    if selection.is_empty() && !line_mode {
 5650                        let cursor = movement::right(map, selection.head());
 5651                        selection.end = cursor;
 5652                        selection.reversed = true;
 5653                        selection.goal = SelectionGoal::None;
 5654                    }
 5655                })
 5656            });
 5657            this.insert("", cx);
 5658            this.refresh_inline_completion(true, false, cx);
 5659        });
 5660    }
 5661
 5662    pub fn tab_prev(&mut self, _: &TabPrev, cx: &mut ViewContext<Self>) {
 5663        if self.move_to_prev_snippet_tabstop(cx) {
 5664            return;
 5665        }
 5666
 5667        self.outdent(&Outdent, cx);
 5668    }
 5669
 5670    pub fn tab(&mut self, _: &Tab, cx: &mut ViewContext<Self>) {
 5671        if self.move_to_next_snippet_tabstop(cx) || self.read_only(cx) {
 5672            return;
 5673        }
 5674
 5675        let mut selections = self.selections.all_adjusted(cx);
 5676        let buffer = self.buffer.read(cx);
 5677        let snapshot = buffer.snapshot(cx);
 5678        let rows_iter = selections.iter().map(|s| s.head().row);
 5679        let suggested_indents = snapshot.suggested_indents(rows_iter, cx);
 5680
 5681        let mut edits = Vec::new();
 5682        let mut prev_edited_row = 0;
 5683        let mut row_delta = 0;
 5684        for selection in &mut selections {
 5685            if selection.start.row != prev_edited_row {
 5686                row_delta = 0;
 5687            }
 5688            prev_edited_row = selection.end.row;
 5689
 5690            // If the selection is non-empty, then increase the indentation of the selected lines.
 5691            if !selection.is_empty() {
 5692                row_delta =
 5693                    Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
 5694                continue;
 5695            }
 5696
 5697            // If the selection is empty and the cursor is in the leading whitespace before the
 5698            // suggested indentation, then auto-indent the line.
 5699            let cursor = selection.head();
 5700            let current_indent = snapshot.indent_size_for_line(MultiBufferRow(cursor.row));
 5701            if let Some(suggested_indent) =
 5702                suggested_indents.get(&MultiBufferRow(cursor.row)).copied()
 5703            {
 5704                if cursor.column < suggested_indent.len
 5705                    && cursor.column <= current_indent.len
 5706                    && current_indent.len <= suggested_indent.len
 5707                {
 5708                    selection.start = Point::new(cursor.row, suggested_indent.len);
 5709                    selection.end = selection.start;
 5710                    if row_delta == 0 {
 5711                        edits.extend(Buffer::edit_for_indent_size_adjustment(
 5712                            cursor.row,
 5713                            current_indent,
 5714                            suggested_indent,
 5715                        ));
 5716                        row_delta = suggested_indent.len - current_indent.len;
 5717                    }
 5718                    continue;
 5719                }
 5720            }
 5721
 5722            // Otherwise, insert a hard or soft tab.
 5723            let settings = buffer.settings_at(cursor, cx);
 5724            let tab_size = if settings.hard_tabs {
 5725                IndentSize::tab()
 5726            } else {
 5727                let tab_size = settings.tab_size.get();
 5728                let char_column = snapshot
 5729                    .text_for_range(Point::new(cursor.row, 0)..cursor)
 5730                    .flat_map(str::chars)
 5731                    .count()
 5732                    + row_delta as usize;
 5733                let chars_to_next_tab_stop = tab_size - (char_column as u32 % tab_size);
 5734                IndentSize::spaces(chars_to_next_tab_stop)
 5735            };
 5736            selection.start = Point::new(cursor.row, cursor.column + row_delta + tab_size.len);
 5737            selection.end = selection.start;
 5738            edits.push((cursor..cursor, tab_size.chars().collect::<String>()));
 5739            row_delta += tab_size.len;
 5740        }
 5741
 5742        self.transact(cx, |this, cx| {
 5743            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
 5744            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
 5745            this.refresh_inline_completion(true, false, cx);
 5746        });
 5747    }
 5748
 5749    pub fn indent(&mut self, _: &Indent, cx: &mut ViewContext<Self>) {
 5750        if self.read_only(cx) {
 5751            return;
 5752        }
 5753        let mut selections = self.selections.all::<Point>(cx);
 5754        let mut prev_edited_row = 0;
 5755        let mut row_delta = 0;
 5756        let mut edits = Vec::new();
 5757        let buffer = self.buffer.read(cx);
 5758        let snapshot = buffer.snapshot(cx);
 5759        for selection in &mut selections {
 5760            if selection.start.row != prev_edited_row {
 5761                row_delta = 0;
 5762            }
 5763            prev_edited_row = selection.end.row;
 5764
 5765            row_delta =
 5766                Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
 5767        }
 5768
 5769        self.transact(cx, |this, cx| {
 5770            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
 5771            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
 5772        });
 5773    }
 5774
 5775    fn indent_selection(
 5776        buffer: &MultiBuffer,
 5777        snapshot: &MultiBufferSnapshot,
 5778        selection: &mut Selection<Point>,
 5779        edits: &mut Vec<(Range<Point>, String)>,
 5780        delta_for_start_row: u32,
 5781        cx: &AppContext,
 5782    ) -> u32 {
 5783        let settings = buffer.settings_at(selection.start, cx);
 5784        let tab_size = settings.tab_size.get();
 5785        let indent_kind = if settings.hard_tabs {
 5786            IndentKind::Tab
 5787        } else {
 5788            IndentKind::Space
 5789        };
 5790        let mut start_row = selection.start.row;
 5791        let mut end_row = selection.end.row + 1;
 5792
 5793        // If a selection ends at the beginning of a line, don't indent
 5794        // that last line.
 5795        if selection.end.column == 0 && selection.end.row > selection.start.row {
 5796            end_row -= 1;
 5797        }
 5798
 5799        // Avoid re-indenting a row that has already been indented by a
 5800        // previous selection, but still update this selection's column
 5801        // to reflect that indentation.
 5802        if delta_for_start_row > 0 {
 5803            start_row += 1;
 5804            selection.start.column += delta_for_start_row;
 5805            if selection.end.row == selection.start.row {
 5806                selection.end.column += delta_for_start_row;
 5807            }
 5808        }
 5809
 5810        let mut delta_for_end_row = 0;
 5811        let has_multiple_rows = start_row + 1 != end_row;
 5812        for row in start_row..end_row {
 5813            let current_indent = snapshot.indent_size_for_line(MultiBufferRow(row));
 5814            let indent_delta = match (current_indent.kind, indent_kind) {
 5815                (IndentKind::Space, IndentKind::Space) => {
 5816                    let columns_to_next_tab_stop = tab_size - (current_indent.len % tab_size);
 5817                    IndentSize::spaces(columns_to_next_tab_stop)
 5818                }
 5819                (IndentKind::Tab, IndentKind::Space) => IndentSize::spaces(tab_size),
 5820                (_, IndentKind::Tab) => IndentSize::tab(),
 5821            };
 5822
 5823            let start = if has_multiple_rows || current_indent.len < selection.start.column {
 5824                0
 5825            } else {
 5826                selection.start.column
 5827            };
 5828            let row_start = Point::new(row, start);
 5829            edits.push((
 5830                row_start..row_start,
 5831                indent_delta.chars().collect::<String>(),
 5832            ));
 5833
 5834            // Update this selection's endpoints to reflect the indentation.
 5835            if row == selection.start.row {
 5836                selection.start.column += indent_delta.len;
 5837            }
 5838            if row == selection.end.row {
 5839                selection.end.column += indent_delta.len;
 5840                delta_for_end_row = indent_delta.len;
 5841            }
 5842        }
 5843
 5844        if selection.start.row == selection.end.row {
 5845            delta_for_start_row + delta_for_end_row
 5846        } else {
 5847            delta_for_end_row
 5848        }
 5849    }
 5850
 5851    pub fn outdent(&mut self, _: &Outdent, cx: &mut ViewContext<Self>) {
 5852        if self.read_only(cx) {
 5853            return;
 5854        }
 5855        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 5856        let selections = self.selections.all::<Point>(cx);
 5857        let mut deletion_ranges = Vec::new();
 5858        let mut last_outdent = None;
 5859        {
 5860            let buffer = self.buffer.read(cx);
 5861            let snapshot = buffer.snapshot(cx);
 5862            for selection in &selections {
 5863                let settings = buffer.settings_at(selection.start, cx);
 5864                let tab_size = settings.tab_size.get();
 5865                let mut rows = selection.spanned_rows(false, &display_map);
 5866
 5867                // Avoid re-outdenting a row that has already been outdented by a
 5868                // previous selection.
 5869                if let Some(last_row) = last_outdent {
 5870                    if last_row == rows.start {
 5871                        rows.start = rows.start.next_row();
 5872                    }
 5873                }
 5874                let has_multiple_rows = rows.len() > 1;
 5875                for row in rows.iter_rows() {
 5876                    let indent_size = snapshot.indent_size_for_line(row);
 5877                    if indent_size.len > 0 {
 5878                        let deletion_len = match indent_size.kind {
 5879                            IndentKind::Space => {
 5880                                let columns_to_prev_tab_stop = indent_size.len % tab_size;
 5881                                if columns_to_prev_tab_stop == 0 {
 5882                                    tab_size
 5883                                } else {
 5884                                    columns_to_prev_tab_stop
 5885                                }
 5886                            }
 5887                            IndentKind::Tab => 1,
 5888                        };
 5889                        let start = if has_multiple_rows
 5890                            || deletion_len > selection.start.column
 5891                            || indent_size.len < selection.start.column
 5892                        {
 5893                            0
 5894                        } else {
 5895                            selection.start.column - deletion_len
 5896                        };
 5897                        deletion_ranges.push(
 5898                            Point::new(row.0, start)..Point::new(row.0, start + deletion_len),
 5899                        );
 5900                        last_outdent = Some(row);
 5901                    }
 5902                }
 5903            }
 5904        }
 5905
 5906        self.transact(cx, |this, cx| {
 5907            this.buffer.update(cx, |buffer, cx| {
 5908                let empty_str: Arc<str> = Arc::default();
 5909                buffer.edit(
 5910                    deletion_ranges
 5911                        .into_iter()
 5912                        .map(|range| (range, empty_str.clone())),
 5913                    None,
 5914                    cx,
 5915                );
 5916            });
 5917            let selections = this.selections.all::<usize>(cx);
 5918            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
 5919        });
 5920    }
 5921
 5922    pub fn autoindent(&mut self, _: &AutoIndent, cx: &mut ViewContext<Self>) {
 5923        if self.read_only(cx) {
 5924            return;
 5925        }
 5926        let selections = self
 5927            .selections
 5928            .all::<usize>(cx)
 5929            .into_iter()
 5930            .map(|s| s.range());
 5931
 5932        self.transact(cx, |this, cx| {
 5933            this.buffer.update(cx, |buffer, cx| {
 5934                buffer.autoindent_ranges(selections, cx);
 5935            });
 5936            let selections = this.selections.all::<usize>(cx);
 5937            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
 5938        });
 5939    }
 5940
 5941    pub fn delete_line(&mut self, _: &DeleteLine, cx: &mut ViewContext<Self>) {
 5942        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 5943        let selections = self.selections.all::<Point>(cx);
 5944
 5945        let mut new_cursors = Vec::new();
 5946        let mut edit_ranges = Vec::new();
 5947        let mut selections = selections.iter().peekable();
 5948        while let Some(selection) = selections.next() {
 5949            let mut rows = selection.spanned_rows(false, &display_map);
 5950            let goal_display_column = selection.head().to_display_point(&display_map).column();
 5951
 5952            // Accumulate contiguous regions of rows that we want to delete.
 5953            while let Some(next_selection) = selections.peek() {
 5954                let next_rows = next_selection.spanned_rows(false, &display_map);
 5955                if next_rows.start <= rows.end {
 5956                    rows.end = next_rows.end;
 5957                    selections.next().unwrap();
 5958                } else {
 5959                    break;
 5960                }
 5961            }
 5962
 5963            let buffer = &display_map.buffer_snapshot;
 5964            let mut edit_start = Point::new(rows.start.0, 0).to_offset(buffer);
 5965            let edit_end;
 5966            let cursor_buffer_row;
 5967            if buffer.max_point().row >= rows.end.0 {
 5968                // If there's a line after the range, delete the \n from the end of the row range
 5969                // and position the cursor on the next line.
 5970                edit_end = Point::new(rows.end.0, 0).to_offset(buffer);
 5971                cursor_buffer_row = rows.end;
 5972            } else {
 5973                // If there isn't a line after the range, delete the \n from the line before the
 5974                // start of the row range and position the cursor there.
 5975                edit_start = edit_start.saturating_sub(1);
 5976                edit_end = buffer.len();
 5977                cursor_buffer_row = rows.start.previous_row();
 5978            }
 5979
 5980            let mut cursor = Point::new(cursor_buffer_row.0, 0).to_display_point(&display_map);
 5981            *cursor.column_mut() =
 5982                cmp::min(goal_display_column, display_map.line_len(cursor.row()));
 5983
 5984            new_cursors.push((
 5985                selection.id,
 5986                buffer.anchor_after(cursor.to_point(&display_map)),
 5987            ));
 5988            edit_ranges.push(edit_start..edit_end);
 5989        }
 5990
 5991        self.transact(cx, |this, cx| {
 5992            let buffer = this.buffer.update(cx, |buffer, cx| {
 5993                let empty_str: Arc<str> = Arc::default();
 5994                buffer.edit(
 5995                    edit_ranges
 5996                        .into_iter()
 5997                        .map(|range| (range, empty_str.clone())),
 5998                    None,
 5999                    cx,
 6000                );
 6001                buffer.snapshot(cx)
 6002            });
 6003            let new_selections = new_cursors
 6004                .into_iter()
 6005                .map(|(id, cursor)| {
 6006                    let cursor = cursor.to_point(&buffer);
 6007                    Selection {
 6008                        id,
 6009                        start: cursor,
 6010                        end: cursor,
 6011                        reversed: false,
 6012                        goal: SelectionGoal::None,
 6013                    }
 6014                })
 6015                .collect();
 6016
 6017            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6018                s.select(new_selections);
 6019            });
 6020        });
 6021    }
 6022
 6023    pub fn join_lines_impl(&mut self, insert_whitespace: bool, cx: &mut ViewContext<Self>) {
 6024        if self.read_only(cx) {
 6025            return;
 6026        }
 6027        let mut row_ranges = Vec::<Range<MultiBufferRow>>::new();
 6028        for selection in self.selections.all::<Point>(cx) {
 6029            let start = MultiBufferRow(selection.start.row);
 6030            // Treat single line selections as if they include the next line. Otherwise this action
 6031            // would do nothing for single line selections individual cursors.
 6032            let end = if selection.start.row == selection.end.row {
 6033                MultiBufferRow(selection.start.row + 1)
 6034            } else {
 6035                MultiBufferRow(selection.end.row)
 6036            };
 6037
 6038            if let Some(last_row_range) = row_ranges.last_mut() {
 6039                if start <= last_row_range.end {
 6040                    last_row_range.end = end;
 6041                    continue;
 6042                }
 6043            }
 6044            row_ranges.push(start..end);
 6045        }
 6046
 6047        let snapshot = self.buffer.read(cx).snapshot(cx);
 6048        let mut cursor_positions = Vec::new();
 6049        for row_range in &row_ranges {
 6050            let anchor = snapshot.anchor_before(Point::new(
 6051                row_range.end.previous_row().0,
 6052                snapshot.line_len(row_range.end.previous_row()),
 6053            ));
 6054            cursor_positions.push(anchor..anchor);
 6055        }
 6056
 6057        self.transact(cx, |this, cx| {
 6058            for row_range in row_ranges.into_iter().rev() {
 6059                for row in row_range.iter_rows().rev() {
 6060                    let end_of_line = Point::new(row.0, snapshot.line_len(row));
 6061                    let next_line_row = row.next_row();
 6062                    let indent = snapshot.indent_size_for_line(next_line_row);
 6063                    let start_of_next_line = Point::new(next_line_row.0, indent.len);
 6064
 6065                    let replace =
 6066                        if snapshot.line_len(next_line_row) > indent.len && insert_whitespace {
 6067                            " "
 6068                        } else {
 6069                            ""
 6070                        };
 6071
 6072                    this.buffer.update(cx, |buffer, cx| {
 6073                        buffer.edit([(end_of_line..start_of_next_line, replace)], None, cx)
 6074                    });
 6075                }
 6076            }
 6077
 6078            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6079                s.select_anchor_ranges(cursor_positions)
 6080            });
 6081        });
 6082    }
 6083
 6084    pub fn join_lines(&mut self, _: &JoinLines, cx: &mut ViewContext<Self>) {
 6085        self.join_lines_impl(true, cx);
 6086    }
 6087
 6088    pub fn sort_lines_case_sensitive(
 6089        &mut self,
 6090        _: &SortLinesCaseSensitive,
 6091        cx: &mut ViewContext<Self>,
 6092    ) {
 6093        self.manipulate_lines(cx, |lines| lines.sort())
 6094    }
 6095
 6096    pub fn sort_lines_case_insensitive(
 6097        &mut self,
 6098        _: &SortLinesCaseInsensitive,
 6099        cx: &mut ViewContext<Self>,
 6100    ) {
 6101        self.manipulate_lines(cx, |lines| lines.sort_by_key(|line| line.to_lowercase()))
 6102    }
 6103
 6104    pub fn unique_lines_case_insensitive(
 6105        &mut self,
 6106        _: &UniqueLinesCaseInsensitive,
 6107        cx: &mut ViewContext<Self>,
 6108    ) {
 6109        self.manipulate_lines(cx, |lines| {
 6110            let mut seen = HashSet::default();
 6111            lines.retain(|line| seen.insert(line.to_lowercase()));
 6112        })
 6113    }
 6114
 6115    pub fn unique_lines_case_sensitive(
 6116        &mut self,
 6117        _: &UniqueLinesCaseSensitive,
 6118        cx: &mut ViewContext<Self>,
 6119    ) {
 6120        self.manipulate_lines(cx, |lines| {
 6121            let mut seen = HashSet::default();
 6122            lines.retain(|line| seen.insert(*line));
 6123        })
 6124    }
 6125
 6126    pub fn revert_file(&mut self, _: &RevertFile, cx: &mut ViewContext<Self>) {
 6127        let mut revert_changes = HashMap::default();
 6128        let snapshot = self.snapshot(cx);
 6129        for hunk in hunks_for_ranges(
 6130            Some(Point::zero()..snapshot.buffer_snapshot.max_point()).into_iter(),
 6131            &snapshot,
 6132        ) {
 6133            self.prepare_revert_change(&mut revert_changes, &hunk, cx);
 6134        }
 6135        if !revert_changes.is_empty() {
 6136            self.transact(cx, |editor, cx| {
 6137                editor.revert(revert_changes, cx);
 6138            });
 6139        }
 6140    }
 6141
 6142    pub fn reload_file(&mut self, _: &ReloadFile, cx: &mut ViewContext<Self>) {
 6143        let Some(project) = self.project.clone() else {
 6144            return;
 6145        };
 6146        self.reload(project, cx).detach_and_notify_err(cx);
 6147    }
 6148
 6149    pub fn revert_selected_hunks(&mut self, _: &RevertSelectedHunks, cx: &mut ViewContext<Self>) {
 6150        let revert_changes = self.gather_revert_changes(&self.selections.all(cx), cx);
 6151        if !revert_changes.is_empty() {
 6152            self.transact(cx, |editor, cx| {
 6153                editor.revert(revert_changes, cx);
 6154            });
 6155        }
 6156    }
 6157
 6158    fn revert_hunk(&mut self, hunk: HoveredHunk, cx: &mut ViewContext<Editor>) {
 6159        let snapshot = self.buffer.read(cx).read(cx);
 6160        if let Some(hunk) = crate::hunk_diff::to_diff_hunk(&hunk, &snapshot) {
 6161            drop(snapshot);
 6162            let mut revert_changes = HashMap::default();
 6163            self.prepare_revert_change(&mut revert_changes, &hunk, cx);
 6164            if !revert_changes.is_empty() {
 6165                self.revert(revert_changes, cx)
 6166            }
 6167        }
 6168    }
 6169
 6170    pub fn open_active_item_in_terminal(&mut self, _: &OpenInTerminal, cx: &mut ViewContext<Self>) {
 6171        if let Some(working_directory) = self.active_excerpt(cx).and_then(|(_, buffer, _)| {
 6172            let project_path = buffer.read(cx).project_path(cx)?;
 6173            let project = self.project.as_ref()?.read(cx);
 6174            let entry = project.entry_for_path(&project_path, cx)?;
 6175            let parent = match &entry.canonical_path {
 6176                Some(canonical_path) => canonical_path.to_path_buf(),
 6177                None => project.absolute_path(&project_path, cx)?,
 6178            }
 6179            .parent()?
 6180            .to_path_buf();
 6181            Some(parent)
 6182        }) {
 6183            cx.dispatch_action(OpenTerminal { working_directory }.boxed_clone());
 6184        }
 6185    }
 6186
 6187    fn gather_revert_changes(
 6188        &self,
 6189        selections: &[Selection<Point>],
 6190        cx: &mut ViewContext<Editor>,
 6191    ) -> HashMap<BufferId, Vec<(Range<text::Anchor>, Rope)>> {
 6192        let mut revert_changes = HashMap::default();
 6193        let snapshot = self.snapshot(cx);
 6194        for hunk in hunks_for_selections(&snapshot, selections) {
 6195            self.prepare_revert_change(&mut revert_changes, &hunk, cx);
 6196        }
 6197        revert_changes
 6198    }
 6199
 6200    pub fn prepare_revert_change(
 6201        &self,
 6202        revert_changes: &mut HashMap<BufferId, Vec<(Range<text::Anchor>, Rope)>>,
 6203        hunk: &MultiBufferDiffHunk,
 6204        cx: &AppContext,
 6205    ) -> Option<()> {
 6206        let buffer = self.buffer.read(cx).buffer(hunk.buffer_id)?;
 6207        let buffer = buffer.read(cx);
 6208        let change_set = &self.diff_map.diff_bases.get(&hunk.buffer_id)?.change_set;
 6209        let original_text = change_set
 6210            .read(cx)
 6211            .base_text
 6212            .as_ref()?
 6213            .read(cx)
 6214            .as_rope()
 6215            .slice(hunk.diff_base_byte_range.clone());
 6216        let buffer_snapshot = buffer.snapshot();
 6217        let buffer_revert_changes = revert_changes.entry(buffer.remote_id()).or_default();
 6218        if let Err(i) = buffer_revert_changes.binary_search_by(|probe| {
 6219            probe
 6220                .0
 6221                .start
 6222                .cmp(&hunk.buffer_range.start, &buffer_snapshot)
 6223                .then(probe.0.end.cmp(&hunk.buffer_range.end, &buffer_snapshot))
 6224        }) {
 6225            buffer_revert_changes.insert(i, (hunk.buffer_range.clone(), original_text));
 6226            Some(())
 6227        } else {
 6228            None
 6229        }
 6230    }
 6231
 6232    pub fn reverse_lines(&mut self, _: &ReverseLines, cx: &mut ViewContext<Self>) {
 6233        self.manipulate_lines(cx, |lines| lines.reverse())
 6234    }
 6235
 6236    pub fn shuffle_lines(&mut self, _: &ShuffleLines, cx: &mut ViewContext<Self>) {
 6237        self.manipulate_lines(cx, |lines| lines.shuffle(&mut thread_rng()))
 6238    }
 6239
 6240    fn manipulate_lines<Fn>(&mut self, cx: &mut ViewContext<Self>, mut callback: Fn)
 6241    where
 6242        Fn: FnMut(&mut Vec<&str>),
 6243    {
 6244        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 6245        let buffer = self.buffer.read(cx).snapshot(cx);
 6246
 6247        let mut edits = Vec::new();
 6248
 6249        let selections = self.selections.all::<Point>(cx);
 6250        let mut selections = selections.iter().peekable();
 6251        let mut contiguous_row_selections = Vec::new();
 6252        let mut new_selections = Vec::new();
 6253        let mut added_lines = 0;
 6254        let mut removed_lines = 0;
 6255
 6256        while let Some(selection) = selections.next() {
 6257            let (start_row, end_row) = consume_contiguous_rows(
 6258                &mut contiguous_row_selections,
 6259                selection,
 6260                &display_map,
 6261                &mut selections,
 6262            );
 6263
 6264            let start_point = Point::new(start_row.0, 0);
 6265            let end_point = Point::new(
 6266                end_row.previous_row().0,
 6267                buffer.line_len(end_row.previous_row()),
 6268            );
 6269            let text = buffer
 6270                .text_for_range(start_point..end_point)
 6271                .collect::<String>();
 6272
 6273            let mut lines = text.split('\n').collect_vec();
 6274
 6275            let lines_before = lines.len();
 6276            callback(&mut lines);
 6277            let lines_after = lines.len();
 6278
 6279            edits.push((start_point..end_point, lines.join("\n")));
 6280
 6281            // Selections must change based on added and removed line count
 6282            let start_row =
 6283                MultiBufferRow(start_point.row + added_lines as u32 - removed_lines as u32);
 6284            let end_row = MultiBufferRow(start_row.0 + lines_after.saturating_sub(1) as u32);
 6285            new_selections.push(Selection {
 6286                id: selection.id,
 6287                start: start_row,
 6288                end: end_row,
 6289                goal: SelectionGoal::None,
 6290                reversed: selection.reversed,
 6291            });
 6292
 6293            if lines_after > lines_before {
 6294                added_lines += lines_after - lines_before;
 6295            } else if lines_before > lines_after {
 6296                removed_lines += lines_before - lines_after;
 6297            }
 6298        }
 6299
 6300        self.transact(cx, |this, cx| {
 6301            let buffer = this.buffer.update(cx, |buffer, cx| {
 6302                buffer.edit(edits, None, cx);
 6303                buffer.snapshot(cx)
 6304            });
 6305
 6306            // Recalculate offsets on newly edited buffer
 6307            let new_selections = new_selections
 6308                .iter()
 6309                .map(|s| {
 6310                    let start_point = Point::new(s.start.0, 0);
 6311                    let end_point = Point::new(s.end.0, buffer.line_len(s.end));
 6312                    Selection {
 6313                        id: s.id,
 6314                        start: buffer.point_to_offset(start_point),
 6315                        end: buffer.point_to_offset(end_point),
 6316                        goal: s.goal,
 6317                        reversed: s.reversed,
 6318                    }
 6319                })
 6320                .collect();
 6321
 6322            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6323                s.select(new_selections);
 6324            });
 6325
 6326            this.request_autoscroll(Autoscroll::fit(), cx);
 6327        });
 6328    }
 6329
 6330    pub fn convert_to_upper_case(&mut self, _: &ConvertToUpperCase, cx: &mut ViewContext<Self>) {
 6331        self.manipulate_text(cx, |text| text.to_uppercase())
 6332    }
 6333
 6334    pub fn convert_to_lower_case(&mut self, _: &ConvertToLowerCase, cx: &mut ViewContext<Self>) {
 6335        self.manipulate_text(cx, |text| text.to_lowercase())
 6336    }
 6337
 6338    pub fn convert_to_title_case(&mut self, _: &ConvertToTitleCase, cx: &mut ViewContext<Self>) {
 6339        self.manipulate_text(cx, |text| {
 6340            text.split('\n')
 6341                .map(|line| line.to_case(Case::Title))
 6342                .join("\n")
 6343        })
 6344    }
 6345
 6346    pub fn convert_to_snake_case(&mut self, _: &ConvertToSnakeCase, cx: &mut ViewContext<Self>) {
 6347        self.manipulate_text(cx, |text| text.to_case(Case::Snake))
 6348    }
 6349
 6350    pub fn convert_to_kebab_case(&mut self, _: &ConvertToKebabCase, cx: &mut ViewContext<Self>) {
 6351        self.manipulate_text(cx, |text| text.to_case(Case::Kebab))
 6352    }
 6353
 6354    pub fn convert_to_upper_camel_case(
 6355        &mut self,
 6356        _: &ConvertToUpperCamelCase,
 6357        cx: &mut ViewContext<Self>,
 6358    ) {
 6359        self.manipulate_text(cx, |text| {
 6360            text.split('\n')
 6361                .map(|line| line.to_case(Case::UpperCamel))
 6362                .join("\n")
 6363        })
 6364    }
 6365
 6366    pub fn convert_to_lower_camel_case(
 6367        &mut self,
 6368        _: &ConvertToLowerCamelCase,
 6369        cx: &mut ViewContext<Self>,
 6370    ) {
 6371        self.manipulate_text(cx, |text| text.to_case(Case::Camel))
 6372    }
 6373
 6374    pub fn convert_to_opposite_case(
 6375        &mut self,
 6376        _: &ConvertToOppositeCase,
 6377        cx: &mut ViewContext<Self>,
 6378    ) {
 6379        self.manipulate_text(cx, |text| {
 6380            text.chars()
 6381                .fold(String::with_capacity(text.len()), |mut t, c| {
 6382                    if c.is_uppercase() {
 6383                        t.extend(c.to_lowercase());
 6384                    } else {
 6385                        t.extend(c.to_uppercase());
 6386                    }
 6387                    t
 6388                })
 6389        })
 6390    }
 6391
 6392    fn manipulate_text<Fn>(&mut self, cx: &mut ViewContext<Self>, mut callback: Fn)
 6393    where
 6394        Fn: FnMut(&str) -> String,
 6395    {
 6396        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 6397        let buffer = self.buffer.read(cx).snapshot(cx);
 6398
 6399        let mut new_selections = Vec::new();
 6400        let mut edits = Vec::new();
 6401        let mut selection_adjustment = 0i32;
 6402
 6403        for selection in self.selections.all::<usize>(cx) {
 6404            let selection_is_empty = selection.is_empty();
 6405
 6406            let (start, end) = if selection_is_empty {
 6407                let word_range = movement::surrounding_word(
 6408                    &display_map,
 6409                    selection.start.to_display_point(&display_map),
 6410                );
 6411                let start = word_range.start.to_offset(&display_map, Bias::Left);
 6412                let end = word_range.end.to_offset(&display_map, Bias::Left);
 6413                (start, end)
 6414            } else {
 6415                (selection.start, selection.end)
 6416            };
 6417
 6418            let text = buffer.text_for_range(start..end).collect::<String>();
 6419            let old_length = text.len() as i32;
 6420            let text = callback(&text);
 6421
 6422            new_selections.push(Selection {
 6423                start: (start as i32 - selection_adjustment) as usize,
 6424                end: ((start + text.len()) as i32 - selection_adjustment) as usize,
 6425                goal: SelectionGoal::None,
 6426                ..selection
 6427            });
 6428
 6429            selection_adjustment += old_length - text.len() as i32;
 6430
 6431            edits.push((start..end, text));
 6432        }
 6433
 6434        self.transact(cx, |this, cx| {
 6435            this.buffer.update(cx, |buffer, cx| {
 6436                buffer.edit(edits, None, cx);
 6437            });
 6438
 6439            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6440                s.select(new_selections);
 6441            });
 6442
 6443            this.request_autoscroll(Autoscroll::fit(), cx);
 6444        });
 6445    }
 6446
 6447    pub fn duplicate(&mut self, upwards: bool, whole_lines: bool, cx: &mut ViewContext<Self>) {
 6448        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 6449        let buffer = &display_map.buffer_snapshot;
 6450        let selections = self.selections.all::<Point>(cx);
 6451
 6452        let mut edits = Vec::new();
 6453        let mut selections_iter = selections.iter().peekable();
 6454        while let Some(selection) = selections_iter.next() {
 6455            let mut rows = selection.spanned_rows(false, &display_map);
 6456            // duplicate line-wise
 6457            if whole_lines || selection.start == selection.end {
 6458                // Avoid duplicating the same lines twice.
 6459                while let Some(next_selection) = selections_iter.peek() {
 6460                    let next_rows = next_selection.spanned_rows(false, &display_map);
 6461                    if next_rows.start < rows.end {
 6462                        rows.end = next_rows.end;
 6463                        selections_iter.next().unwrap();
 6464                    } else {
 6465                        break;
 6466                    }
 6467                }
 6468
 6469                // Copy the text from the selected row region and splice it either at the start
 6470                // or end of the region.
 6471                let start = Point::new(rows.start.0, 0);
 6472                let end = Point::new(
 6473                    rows.end.previous_row().0,
 6474                    buffer.line_len(rows.end.previous_row()),
 6475                );
 6476                let text = buffer
 6477                    .text_for_range(start..end)
 6478                    .chain(Some("\n"))
 6479                    .collect::<String>();
 6480                let insert_location = if upwards {
 6481                    Point::new(rows.end.0, 0)
 6482                } else {
 6483                    start
 6484                };
 6485                edits.push((insert_location..insert_location, text));
 6486            } else {
 6487                // duplicate character-wise
 6488                let start = selection.start;
 6489                let end = selection.end;
 6490                let text = buffer.text_for_range(start..end).collect::<String>();
 6491                edits.push((selection.end..selection.end, text));
 6492            }
 6493        }
 6494
 6495        self.transact(cx, |this, cx| {
 6496            this.buffer.update(cx, |buffer, cx| {
 6497                buffer.edit(edits, None, cx);
 6498            });
 6499
 6500            this.request_autoscroll(Autoscroll::fit(), cx);
 6501        });
 6502    }
 6503
 6504    pub fn duplicate_line_up(&mut self, _: &DuplicateLineUp, cx: &mut ViewContext<Self>) {
 6505        self.duplicate(true, true, cx);
 6506    }
 6507
 6508    pub fn duplicate_line_down(&mut self, _: &DuplicateLineDown, cx: &mut ViewContext<Self>) {
 6509        self.duplicate(false, true, cx);
 6510    }
 6511
 6512    pub fn duplicate_selection(&mut self, _: &DuplicateSelection, cx: &mut ViewContext<Self>) {
 6513        self.duplicate(false, false, cx);
 6514    }
 6515
 6516    pub fn move_line_up(&mut self, _: &MoveLineUp, cx: &mut ViewContext<Self>) {
 6517        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 6518        let buffer = self.buffer.read(cx).snapshot(cx);
 6519
 6520        let mut edits = Vec::new();
 6521        let mut unfold_ranges = Vec::new();
 6522        let mut refold_creases = Vec::new();
 6523
 6524        let selections = self.selections.all::<Point>(cx);
 6525        let mut selections = selections.iter().peekable();
 6526        let mut contiguous_row_selections = Vec::new();
 6527        let mut new_selections = Vec::new();
 6528
 6529        while let Some(selection) = selections.next() {
 6530            // Find all the selections that span a contiguous row range
 6531            let (start_row, end_row) = consume_contiguous_rows(
 6532                &mut contiguous_row_selections,
 6533                selection,
 6534                &display_map,
 6535                &mut selections,
 6536            );
 6537
 6538            // Move the text spanned by the row range to be before the line preceding the row range
 6539            if start_row.0 > 0 {
 6540                let range_to_move = Point::new(
 6541                    start_row.previous_row().0,
 6542                    buffer.line_len(start_row.previous_row()),
 6543                )
 6544                    ..Point::new(
 6545                        end_row.previous_row().0,
 6546                        buffer.line_len(end_row.previous_row()),
 6547                    );
 6548                let insertion_point = display_map
 6549                    .prev_line_boundary(Point::new(start_row.previous_row().0, 0))
 6550                    .0;
 6551
 6552                // Don't move lines across excerpts
 6553                if buffer
 6554                    .excerpt_boundaries_in_range((
 6555                        Bound::Excluded(insertion_point),
 6556                        Bound::Included(range_to_move.end),
 6557                    ))
 6558                    .next()
 6559                    .is_none()
 6560                {
 6561                    let text = buffer
 6562                        .text_for_range(range_to_move.clone())
 6563                        .flat_map(|s| s.chars())
 6564                        .skip(1)
 6565                        .chain(['\n'])
 6566                        .collect::<String>();
 6567
 6568                    edits.push((
 6569                        buffer.anchor_after(range_to_move.start)
 6570                            ..buffer.anchor_before(range_to_move.end),
 6571                        String::new(),
 6572                    ));
 6573                    let insertion_anchor = buffer.anchor_after(insertion_point);
 6574                    edits.push((insertion_anchor..insertion_anchor, text));
 6575
 6576                    let row_delta = range_to_move.start.row - insertion_point.row + 1;
 6577
 6578                    // Move selections up
 6579                    new_selections.extend(contiguous_row_selections.drain(..).map(
 6580                        |mut selection| {
 6581                            selection.start.row -= row_delta;
 6582                            selection.end.row -= row_delta;
 6583                            selection
 6584                        },
 6585                    ));
 6586
 6587                    // Move folds up
 6588                    unfold_ranges.push(range_to_move.clone());
 6589                    for fold in display_map.folds_in_range(
 6590                        buffer.anchor_before(range_to_move.start)
 6591                            ..buffer.anchor_after(range_to_move.end),
 6592                    ) {
 6593                        let mut start = fold.range.start.to_point(&buffer);
 6594                        let mut end = fold.range.end.to_point(&buffer);
 6595                        start.row -= row_delta;
 6596                        end.row -= row_delta;
 6597                        refold_creases.push(Crease::simple(start..end, fold.placeholder.clone()));
 6598                    }
 6599                }
 6600            }
 6601
 6602            // If we didn't move line(s), preserve the existing selections
 6603            new_selections.append(&mut contiguous_row_selections);
 6604        }
 6605
 6606        self.transact(cx, |this, cx| {
 6607            this.unfold_ranges(&unfold_ranges, true, true, cx);
 6608            this.buffer.update(cx, |buffer, cx| {
 6609                for (range, text) in edits {
 6610                    buffer.edit([(range, text)], None, cx);
 6611                }
 6612            });
 6613            this.fold_creases(refold_creases, true, cx);
 6614            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6615                s.select(new_selections);
 6616            })
 6617        });
 6618    }
 6619
 6620    pub fn move_line_down(&mut self, _: &MoveLineDown, cx: &mut ViewContext<Self>) {
 6621        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 6622        let buffer = self.buffer.read(cx).snapshot(cx);
 6623
 6624        let mut edits = Vec::new();
 6625        let mut unfold_ranges = Vec::new();
 6626        let mut refold_creases = Vec::new();
 6627
 6628        let selections = self.selections.all::<Point>(cx);
 6629        let mut selections = selections.iter().peekable();
 6630        let mut contiguous_row_selections = Vec::new();
 6631        let mut new_selections = Vec::new();
 6632
 6633        while let Some(selection) = selections.next() {
 6634            // Find all the selections that span a contiguous row range
 6635            let (start_row, end_row) = consume_contiguous_rows(
 6636                &mut contiguous_row_selections,
 6637                selection,
 6638                &display_map,
 6639                &mut selections,
 6640            );
 6641
 6642            // Move the text spanned by the row range to be after the last line of the row range
 6643            if end_row.0 <= buffer.max_point().row {
 6644                let range_to_move =
 6645                    MultiBufferPoint::new(start_row.0, 0)..MultiBufferPoint::new(end_row.0, 0);
 6646                let insertion_point = display_map
 6647                    .next_line_boundary(MultiBufferPoint::new(end_row.0, 0))
 6648                    .0;
 6649
 6650                // Don't move lines across excerpt boundaries
 6651                if buffer
 6652                    .excerpt_boundaries_in_range((
 6653                        Bound::Excluded(range_to_move.start),
 6654                        Bound::Included(insertion_point),
 6655                    ))
 6656                    .next()
 6657                    .is_none()
 6658                {
 6659                    let mut text = String::from("\n");
 6660                    text.extend(buffer.text_for_range(range_to_move.clone()));
 6661                    text.pop(); // Drop trailing newline
 6662                    edits.push((
 6663                        buffer.anchor_after(range_to_move.start)
 6664                            ..buffer.anchor_before(range_to_move.end),
 6665                        String::new(),
 6666                    ));
 6667                    let insertion_anchor = buffer.anchor_after(insertion_point);
 6668                    edits.push((insertion_anchor..insertion_anchor, text));
 6669
 6670                    let row_delta = insertion_point.row - range_to_move.end.row + 1;
 6671
 6672                    // Move selections down
 6673                    new_selections.extend(contiguous_row_selections.drain(..).map(
 6674                        |mut selection| {
 6675                            selection.start.row += row_delta;
 6676                            selection.end.row += row_delta;
 6677                            selection
 6678                        },
 6679                    ));
 6680
 6681                    // Move folds down
 6682                    unfold_ranges.push(range_to_move.clone());
 6683                    for fold in display_map.folds_in_range(
 6684                        buffer.anchor_before(range_to_move.start)
 6685                            ..buffer.anchor_after(range_to_move.end),
 6686                    ) {
 6687                        let mut start = fold.range.start.to_point(&buffer);
 6688                        let mut end = fold.range.end.to_point(&buffer);
 6689                        start.row += row_delta;
 6690                        end.row += row_delta;
 6691                        refold_creases.push(Crease::simple(start..end, fold.placeholder.clone()));
 6692                    }
 6693                }
 6694            }
 6695
 6696            // If we didn't move line(s), preserve the existing selections
 6697            new_selections.append(&mut contiguous_row_selections);
 6698        }
 6699
 6700        self.transact(cx, |this, cx| {
 6701            this.unfold_ranges(&unfold_ranges, true, true, cx);
 6702            this.buffer.update(cx, |buffer, cx| {
 6703                for (range, text) in edits {
 6704                    buffer.edit([(range, text)], None, cx);
 6705                }
 6706            });
 6707            this.fold_creases(refold_creases, true, cx);
 6708            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(new_selections));
 6709        });
 6710    }
 6711
 6712    pub fn transpose(&mut self, _: &Transpose, cx: &mut ViewContext<Self>) {
 6713        let text_layout_details = &self.text_layout_details(cx);
 6714        self.transact(cx, |this, cx| {
 6715            let edits = this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6716                let mut edits: Vec<(Range<usize>, String)> = Default::default();
 6717                let line_mode = s.line_mode;
 6718                s.move_with(|display_map, selection| {
 6719                    if !selection.is_empty() || line_mode {
 6720                        return;
 6721                    }
 6722
 6723                    let mut head = selection.head();
 6724                    let mut transpose_offset = head.to_offset(display_map, Bias::Right);
 6725                    if head.column() == display_map.line_len(head.row()) {
 6726                        transpose_offset = display_map
 6727                            .buffer_snapshot
 6728                            .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
 6729                    }
 6730
 6731                    if transpose_offset == 0 {
 6732                        return;
 6733                    }
 6734
 6735                    *head.column_mut() += 1;
 6736                    head = display_map.clip_point(head, Bias::Right);
 6737                    let goal = SelectionGoal::HorizontalPosition(
 6738                        display_map
 6739                            .x_for_display_point(head, text_layout_details)
 6740                            .into(),
 6741                    );
 6742                    selection.collapse_to(head, goal);
 6743
 6744                    let transpose_start = display_map
 6745                        .buffer_snapshot
 6746                        .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
 6747                    if edits.last().map_or(true, |e| e.0.end <= transpose_start) {
 6748                        let transpose_end = display_map
 6749                            .buffer_snapshot
 6750                            .clip_offset(transpose_offset + 1, Bias::Right);
 6751                        if let Some(ch) =
 6752                            display_map.buffer_snapshot.chars_at(transpose_start).next()
 6753                        {
 6754                            edits.push((transpose_start..transpose_offset, String::new()));
 6755                            edits.push((transpose_end..transpose_end, ch.to_string()));
 6756                        }
 6757                    }
 6758                });
 6759                edits
 6760            });
 6761            this.buffer
 6762                .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
 6763            let selections = this.selections.all::<usize>(cx);
 6764            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6765                s.select(selections);
 6766            });
 6767        });
 6768    }
 6769
 6770    pub fn rewrap(&mut self, _: &Rewrap, cx: &mut ViewContext<Self>) {
 6771        self.rewrap_impl(IsVimMode::No, cx)
 6772    }
 6773
 6774    pub fn rewrap_impl(&mut self, is_vim_mode: IsVimMode, cx: &mut ViewContext<Self>) {
 6775        let buffer = self.buffer.read(cx).snapshot(cx);
 6776        let selections = self.selections.all::<Point>(cx);
 6777        let mut selections = selections.iter().peekable();
 6778
 6779        let mut edits = Vec::new();
 6780        let mut rewrapped_row_ranges = Vec::<RangeInclusive<u32>>::new();
 6781
 6782        while let Some(selection) = selections.next() {
 6783            let mut start_row = selection.start.row;
 6784            let mut end_row = selection.end.row;
 6785
 6786            // Skip selections that overlap with a range that has already been rewrapped.
 6787            let selection_range = start_row..end_row;
 6788            if rewrapped_row_ranges
 6789                .iter()
 6790                .any(|range| range.overlaps(&selection_range))
 6791            {
 6792                continue;
 6793            }
 6794
 6795            let mut should_rewrap = is_vim_mode == IsVimMode::Yes;
 6796
 6797            if let Some(language_scope) = buffer.language_scope_at(selection.head()) {
 6798                match language_scope.language_name().0.as_ref() {
 6799                    "Markdown" | "Plain Text" => {
 6800                        should_rewrap = true;
 6801                    }
 6802                    _ => {}
 6803                }
 6804            }
 6805
 6806            let tab_size = buffer.settings_at(selection.head(), cx).tab_size;
 6807
 6808            // Since not all lines in the selection may be at the same indent
 6809            // level, choose the indent size that is the most common between all
 6810            // of the lines.
 6811            //
 6812            // If there is a tie, we use the deepest indent.
 6813            let (indent_size, indent_end) = {
 6814                let mut indent_size_occurrences = HashMap::default();
 6815                let mut rows_by_indent_size = HashMap::<IndentSize, Vec<u32>>::default();
 6816
 6817                for row in start_row..=end_row {
 6818                    let indent = buffer.indent_size_for_line(MultiBufferRow(row));
 6819                    rows_by_indent_size.entry(indent).or_default().push(row);
 6820                    *indent_size_occurrences.entry(indent).or_insert(0) += 1;
 6821                }
 6822
 6823                let indent_size = indent_size_occurrences
 6824                    .into_iter()
 6825                    .max_by_key(|(indent, count)| (*count, indent.len_with_expanded_tabs(tab_size)))
 6826                    .map(|(indent, _)| indent)
 6827                    .unwrap_or_default();
 6828                let row = rows_by_indent_size[&indent_size][0];
 6829                let indent_end = Point::new(row, indent_size.len);
 6830
 6831                (indent_size, indent_end)
 6832            };
 6833
 6834            let mut line_prefix = indent_size.chars().collect::<String>();
 6835
 6836            if let Some(comment_prefix) =
 6837                buffer
 6838                    .language_scope_at(selection.head())
 6839                    .and_then(|language| {
 6840                        language
 6841                            .line_comment_prefixes()
 6842                            .iter()
 6843                            .find(|prefix| buffer.contains_str_at(indent_end, prefix))
 6844                            .cloned()
 6845                    })
 6846            {
 6847                line_prefix.push_str(&comment_prefix);
 6848                should_rewrap = true;
 6849            }
 6850
 6851            if !should_rewrap {
 6852                continue;
 6853            }
 6854
 6855            if selection.is_empty() {
 6856                'expand_upwards: while start_row > 0 {
 6857                    let prev_row = start_row - 1;
 6858                    if buffer.contains_str_at(Point::new(prev_row, 0), &line_prefix)
 6859                        && buffer.line_len(MultiBufferRow(prev_row)) as usize > line_prefix.len()
 6860                    {
 6861                        start_row = prev_row;
 6862                    } else {
 6863                        break 'expand_upwards;
 6864                    }
 6865                }
 6866
 6867                'expand_downwards: while end_row < buffer.max_point().row {
 6868                    let next_row = end_row + 1;
 6869                    if buffer.contains_str_at(Point::new(next_row, 0), &line_prefix)
 6870                        && buffer.line_len(MultiBufferRow(next_row)) as usize > line_prefix.len()
 6871                    {
 6872                        end_row = next_row;
 6873                    } else {
 6874                        break 'expand_downwards;
 6875                    }
 6876                }
 6877            }
 6878
 6879            let start = Point::new(start_row, 0);
 6880            let end = Point::new(end_row, buffer.line_len(MultiBufferRow(end_row)));
 6881            let selection_text = buffer.text_for_range(start..end).collect::<String>();
 6882            let Some(lines_without_prefixes) = selection_text
 6883                .lines()
 6884                .map(|line| {
 6885                    line.strip_prefix(&line_prefix)
 6886                        .or_else(|| line.trim_start().strip_prefix(&line_prefix.trim_start()))
 6887                        .ok_or_else(|| {
 6888                            anyhow!("line did not start with prefix {line_prefix:?}: {line:?}")
 6889                        })
 6890                })
 6891                .collect::<Result<Vec<_>, _>>()
 6892                .log_err()
 6893            else {
 6894                continue;
 6895            };
 6896
 6897            let wrap_column = buffer
 6898                .settings_at(Point::new(start_row, 0), cx)
 6899                .preferred_line_length as usize;
 6900            let wrapped_text = wrap_with_prefix(
 6901                line_prefix,
 6902                lines_without_prefixes.join(" "),
 6903                wrap_column,
 6904                tab_size,
 6905            );
 6906
 6907            // TODO: should always use char-based diff while still supporting cursor behavior that
 6908            // matches vim.
 6909            let diff = match is_vim_mode {
 6910                IsVimMode::Yes => TextDiff::from_lines(&selection_text, &wrapped_text),
 6911                IsVimMode::No => TextDiff::from_chars(&selection_text, &wrapped_text),
 6912            };
 6913            let mut offset = start.to_offset(&buffer);
 6914            let mut moved_since_edit = true;
 6915
 6916            for change in diff.iter_all_changes() {
 6917                let value = change.value();
 6918                match change.tag() {
 6919                    ChangeTag::Equal => {
 6920                        offset += value.len();
 6921                        moved_since_edit = true;
 6922                    }
 6923                    ChangeTag::Delete => {
 6924                        let start = buffer.anchor_after(offset);
 6925                        let end = buffer.anchor_before(offset + value.len());
 6926
 6927                        if moved_since_edit {
 6928                            edits.push((start..end, String::new()));
 6929                        } else {
 6930                            edits.last_mut().unwrap().0.end = end;
 6931                        }
 6932
 6933                        offset += value.len();
 6934                        moved_since_edit = false;
 6935                    }
 6936                    ChangeTag::Insert => {
 6937                        if moved_since_edit {
 6938                            let anchor = buffer.anchor_after(offset);
 6939                            edits.push((anchor..anchor, value.to_string()));
 6940                        } else {
 6941                            edits.last_mut().unwrap().1.push_str(value);
 6942                        }
 6943
 6944                        moved_since_edit = false;
 6945                    }
 6946                }
 6947            }
 6948
 6949            rewrapped_row_ranges.push(start_row..=end_row);
 6950        }
 6951
 6952        self.buffer
 6953            .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
 6954    }
 6955
 6956    pub fn cut_common(&mut self, cx: &mut ViewContext<Self>) -> ClipboardItem {
 6957        let mut text = String::new();
 6958        let buffer = self.buffer.read(cx).snapshot(cx);
 6959        let mut selections = self.selections.all::<Point>(cx);
 6960        let mut clipboard_selections = Vec::with_capacity(selections.len());
 6961        {
 6962            let max_point = buffer.max_point();
 6963            let mut is_first = true;
 6964            for selection in &mut selections {
 6965                let is_entire_line = selection.is_empty() || self.selections.line_mode;
 6966                if is_entire_line {
 6967                    selection.start = Point::new(selection.start.row, 0);
 6968                    if !selection.is_empty() && selection.end.column == 0 {
 6969                        selection.end = cmp::min(max_point, selection.end);
 6970                    } else {
 6971                        selection.end = cmp::min(max_point, Point::new(selection.end.row + 1, 0));
 6972                    }
 6973                    selection.goal = SelectionGoal::None;
 6974                }
 6975                if is_first {
 6976                    is_first = false;
 6977                } else {
 6978                    text += "\n";
 6979                }
 6980                let mut len = 0;
 6981                for chunk in buffer.text_for_range(selection.start..selection.end) {
 6982                    text.push_str(chunk);
 6983                    len += chunk.len();
 6984                }
 6985                clipboard_selections.push(ClipboardSelection {
 6986                    len,
 6987                    is_entire_line,
 6988                    first_line_indent: buffer
 6989                        .indent_size_for_line(MultiBufferRow(selection.start.row))
 6990                        .len,
 6991                });
 6992            }
 6993        }
 6994
 6995        self.transact(cx, |this, cx| {
 6996            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6997                s.select(selections);
 6998            });
 6999            this.insert("", cx);
 7000        });
 7001        ClipboardItem::new_string_with_json_metadata(text, clipboard_selections)
 7002    }
 7003
 7004    pub fn cut(&mut self, _: &Cut, cx: &mut ViewContext<Self>) {
 7005        let item = self.cut_common(cx);
 7006        cx.write_to_clipboard(item);
 7007    }
 7008
 7009    pub fn kill_ring_cut(&mut self, _: &KillRingCut, cx: &mut ViewContext<Self>) {
 7010        self.change_selections(None, cx, |s| {
 7011            s.move_with(|snapshot, sel| {
 7012                if sel.is_empty() {
 7013                    sel.end = DisplayPoint::new(sel.end.row(), snapshot.line_len(sel.end.row()))
 7014                }
 7015            });
 7016        });
 7017        let item = self.cut_common(cx);
 7018        cx.set_global(KillRing(item))
 7019    }
 7020
 7021    pub fn kill_ring_yank(&mut self, _: &KillRingYank, cx: &mut ViewContext<Self>) {
 7022        let (text, metadata) = if let Some(KillRing(item)) = cx.try_global() {
 7023            if let Some(ClipboardEntry::String(kill_ring)) = item.entries().first() {
 7024                (kill_ring.text().to_string(), kill_ring.metadata_json())
 7025            } else {
 7026                return;
 7027            }
 7028        } else {
 7029            return;
 7030        };
 7031        self.do_paste(&text, metadata, false, cx);
 7032    }
 7033
 7034    pub fn copy(&mut self, _: &Copy, cx: &mut ViewContext<Self>) {
 7035        let selections = self.selections.all::<Point>(cx);
 7036        let buffer = self.buffer.read(cx).read(cx);
 7037        let mut text = String::new();
 7038
 7039        let mut clipboard_selections = Vec::with_capacity(selections.len());
 7040        {
 7041            let max_point = buffer.max_point();
 7042            let mut is_first = true;
 7043            for selection in selections.iter() {
 7044                let mut start = selection.start;
 7045                let mut end = selection.end;
 7046                let is_entire_line = selection.is_empty() || self.selections.line_mode;
 7047                if is_entire_line {
 7048                    start = Point::new(start.row, 0);
 7049                    end = cmp::min(max_point, Point::new(end.row + 1, 0));
 7050                }
 7051                if is_first {
 7052                    is_first = false;
 7053                } else {
 7054                    text += "\n";
 7055                }
 7056                let mut len = 0;
 7057                for chunk in buffer.text_for_range(start..end) {
 7058                    text.push_str(chunk);
 7059                    len += chunk.len();
 7060                }
 7061                clipboard_selections.push(ClipboardSelection {
 7062                    len,
 7063                    is_entire_line,
 7064                    first_line_indent: buffer.indent_size_for_line(MultiBufferRow(start.row)).len,
 7065                });
 7066            }
 7067        }
 7068
 7069        cx.write_to_clipboard(ClipboardItem::new_string_with_json_metadata(
 7070            text,
 7071            clipboard_selections,
 7072        ));
 7073    }
 7074
 7075    pub fn do_paste(
 7076        &mut self,
 7077        text: &String,
 7078        clipboard_selections: Option<Vec<ClipboardSelection>>,
 7079        handle_entire_lines: bool,
 7080        cx: &mut ViewContext<Self>,
 7081    ) {
 7082        if self.read_only(cx) {
 7083            return;
 7084        }
 7085
 7086        let clipboard_text = Cow::Borrowed(text);
 7087
 7088        self.transact(cx, |this, cx| {
 7089            if let Some(mut clipboard_selections) = clipboard_selections {
 7090                let old_selections = this.selections.all::<usize>(cx);
 7091                let all_selections_were_entire_line =
 7092                    clipboard_selections.iter().all(|s| s.is_entire_line);
 7093                let first_selection_indent_column =
 7094                    clipboard_selections.first().map(|s| s.first_line_indent);
 7095                if clipboard_selections.len() != old_selections.len() {
 7096                    clipboard_selections.drain(..);
 7097                }
 7098                let cursor_offset = this.selections.last::<usize>(cx).head();
 7099                let mut auto_indent_on_paste = true;
 7100
 7101                this.buffer.update(cx, |buffer, cx| {
 7102                    let snapshot = buffer.read(cx);
 7103                    auto_indent_on_paste =
 7104                        snapshot.settings_at(cursor_offset, cx).auto_indent_on_paste;
 7105
 7106                    let mut start_offset = 0;
 7107                    let mut edits = Vec::new();
 7108                    let mut original_indent_columns = Vec::new();
 7109                    for (ix, selection) in old_selections.iter().enumerate() {
 7110                        let to_insert;
 7111                        let entire_line;
 7112                        let original_indent_column;
 7113                        if let Some(clipboard_selection) = clipboard_selections.get(ix) {
 7114                            let end_offset = start_offset + clipboard_selection.len;
 7115                            to_insert = &clipboard_text[start_offset..end_offset];
 7116                            entire_line = clipboard_selection.is_entire_line;
 7117                            start_offset = end_offset + 1;
 7118                            original_indent_column = Some(clipboard_selection.first_line_indent);
 7119                        } else {
 7120                            to_insert = clipboard_text.as_str();
 7121                            entire_line = all_selections_were_entire_line;
 7122                            original_indent_column = first_selection_indent_column
 7123                        }
 7124
 7125                        // If the corresponding selection was empty when this slice of the
 7126                        // clipboard text was written, then the entire line containing the
 7127                        // selection was copied. If this selection is also currently empty,
 7128                        // then paste the line before the current line of the buffer.
 7129                        let range = if selection.is_empty() && handle_entire_lines && entire_line {
 7130                            let column = selection.start.to_point(&snapshot).column as usize;
 7131                            let line_start = selection.start - column;
 7132                            line_start..line_start
 7133                        } else {
 7134                            selection.range()
 7135                        };
 7136
 7137                        edits.push((range, to_insert));
 7138                        original_indent_columns.extend(original_indent_column);
 7139                    }
 7140                    drop(snapshot);
 7141
 7142                    buffer.edit(
 7143                        edits,
 7144                        if auto_indent_on_paste {
 7145                            Some(AutoindentMode::Block {
 7146                                original_indent_columns,
 7147                            })
 7148                        } else {
 7149                            None
 7150                        },
 7151                        cx,
 7152                    );
 7153                });
 7154
 7155                let selections = this.selections.all::<usize>(cx);
 7156                this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
 7157            } else {
 7158                this.insert(&clipboard_text, cx);
 7159            }
 7160        });
 7161    }
 7162
 7163    pub fn paste(&mut self, _: &Paste, cx: &mut ViewContext<Self>) {
 7164        if let Some(item) = cx.read_from_clipboard() {
 7165            let entries = item.entries();
 7166
 7167            match entries.first() {
 7168                // For now, we only support applying metadata if there's one string. In the future, we can incorporate all the selections
 7169                // of all the pasted entries.
 7170                Some(ClipboardEntry::String(clipboard_string)) if entries.len() == 1 => self
 7171                    .do_paste(
 7172                        clipboard_string.text(),
 7173                        clipboard_string.metadata_json::<Vec<ClipboardSelection>>(),
 7174                        true,
 7175                        cx,
 7176                    ),
 7177                _ => self.do_paste(&item.text().unwrap_or_default(), None, true, cx),
 7178            }
 7179        }
 7180    }
 7181
 7182    pub fn undo(&mut self, _: &Undo, cx: &mut ViewContext<Self>) {
 7183        if self.read_only(cx) {
 7184            return;
 7185        }
 7186
 7187        if let Some(transaction_id) = self.buffer.update(cx, |buffer, cx| buffer.undo(cx)) {
 7188            if let Some((selections, _)) =
 7189                self.selection_history.transaction(transaction_id).cloned()
 7190            {
 7191                self.change_selections(None, cx, |s| {
 7192                    s.select_anchors(selections.to_vec());
 7193                });
 7194            }
 7195            self.request_autoscroll(Autoscroll::fit(), cx);
 7196            self.unmark_text(cx);
 7197            self.refresh_inline_completion(true, false, cx);
 7198            cx.emit(EditorEvent::Edited { transaction_id });
 7199            cx.emit(EditorEvent::TransactionUndone { transaction_id });
 7200        }
 7201    }
 7202
 7203    pub fn redo(&mut self, _: &Redo, cx: &mut ViewContext<Self>) {
 7204        if self.read_only(cx) {
 7205            return;
 7206        }
 7207
 7208        if let Some(transaction_id) = self.buffer.update(cx, |buffer, cx| buffer.redo(cx)) {
 7209            if let Some((_, Some(selections))) =
 7210                self.selection_history.transaction(transaction_id).cloned()
 7211            {
 7212                self.change_selections(None, cx, |s| {
 7213                    s.select_anchors(selections.to_vec());
 7214                });
 7215            }
 7216            self.request_autoscroll(Autoscroll::fit(), cx);
 7217            self.unmark_text(cx);
 7218            self.refresh_inline_completion(true, false, cx);
 7219            cx.emit(EditorEvent::Edited { transaction_id });
 7220        }
 7221    }
 7222
 7223    pub fn finalize_last_transaction(&mut self, cx: &mut ViewContext<Self>) {
 7224        self.buffer
 7225            .update(cx, |buffer, cx| buffer.finalize_last_transaction(cx));
 7226    }
 7227
 7228    pub fn group_until_transaction(&mut self, tx_id: TransactionId, cx: &mut ViewContext<Self>) {
 7229        self.buffer
 7230            .update(cx, |buffer, cx| buffer.group_until_transaction(tx_id, cx));
 7231    }
 7232
 7233    pub fn move_left(&mut self, _: &MoveLeft, cx: &mut ViewContext<Self>) {
 7234        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7235            let line_mode = s.line_mode;
 7236            s.move_with(|map, selection| {
 7237                let cursor = if selection.is_empty() && !line_mode {
 7238                    movement::left(map, selection.start)
 7239                } else {
 7240                    selection.start
 7241                };
 7242                selection.collapse_to(cursor, SelectionGoal::None);
 7243            });
 7244        })
 7245    }
 7246
 7247    pub fn select_left(&mut self, _: &SelectLeft, cx: &mut ViewContext<Self>) {
 7248        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7249            s.move_heads_with(|map, head, _| (movement::left(map, head), SelectionGoal::None));
 7250        })
 7251    }
 7252
 7253    pub fn move_right(&mut self, _: &MoveRight, cx: &mut ViewContext<Self>) {
 7254        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7255            let line_mode = s.line_mode;
 7256            s.move_with(|map, selection| {
 7257                let cursor = if selection.is_empty() && !line_mode {
 7258                    movement::right(map, selection.end)
 7259                } else {
 7260                    selection.end
 7261                };
 7262                selection.collapse_to(cursor, SelectionGoal::None)
 7263            });
 7264        })
 7265    }
 7266
 7267    pub fn select_right(&mut self, _: &SelectRight, cx: &mut ViewContext<Self>) {
 7268        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7269            s.move_heads_with(|map, head, _| (movement::right(map, head), SelectionGoal::None));
 7270        })
 7271    }
 7272
 7273    pub fn move_up(&mut self, _: &MoveUp, cx: &mut ViewContext<Self>) {
 7274        if self.take_rename(true, cx).is_some() {
 7275            return;
 7276        }
 7277
 7278        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 7279            cx.propagate();
 7280            return;
 7281        }
 7282
 7283        let text_layout_details = &self.text_layout_details(cx);
 7284        let selection_count = self.selections.count();
 7285        let first_selection = self.selections.first_anchor();
 7286
 7287        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7288            let line_mode = s.line_mode;
 7289            s.move_with(|map, selection| {
 7290                if !selection.is_empty() && !line_mode {
 7291                    selection.goal = SelectionGoal::None;
 7292                }
 7293                let (cursor, goal) = movement::up(
 7294                    map,
 7295                    selection.start,
 7296                    selection.goal,
 7297                    false,
 7298                    text_layout_details,
 7299                );
 7300                selection.collapse_to(cursor, goal);
 7301            });
 7302        });
 7303
 7304        if selection_count == 1 && first_selection.range() == self.selections.first_anchor().range()
 7305        {
 7306            cx.propagate();
 7307        }
 7308    }
 7309
 7310    pub fn move_up_by_lines(&mut self, action: &MoveUpByLines, cx: &mut ViewContext<Self>) {
 7311        if self.take_rename(true, cx).is_some() {
 7312            return;
 7313        }
 7314
 7315        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 7316            cx.propagate();
 7317            return;
 7318        }
 7319
 7320        let text_layout_details = &self.text_layout_details(cx);
 7321
 7322        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7323            let line_mode = s.line_mode;
 7324            s.move_with(|map, selection| {
 7325                if !selection.is_empty() && !line_mode {
 7326                    selection.goal = SelectionGoal::None;
 7327                }
 7328                let (cursor, goal) = movement::up_by_rows(
 7329                    map,
 7330                    selection.start,
 7331                    action.lines,
 7332                    selection.goal,
 7333                    false,
 7334                    text_layout_details,
 7335                );
 7336                selection.collapse_to(cursor, goal);
 7337            });
 7338        })
 7339    }
 7340
 7341    pub fn move_down_by_lines(&mut self, action: &MoveDownByLines, cx: &mut ViewContext<Self>) {
 7342        if self.take_rename(true, cx).is_some() {
 7343            return;
 7344        }
 7345
 7346        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 7347            cx.propagate();
 7348            return;
 7349        }
 7350
 7351        let text_layout_details = &self.text_layout_details(cx);
 7352
 7353        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7354            let line_mode = s.line_mode;
 7355            s.move_with(|map, selection| {
 7356                if !selection.is_empty() && !line_mode {
 7357                    selection.goal = SelectionGoal::None;
 7358                }
 7359                let (cursor, goal) = movement::down_by_rows(
 7360                    map,
 7361                    selection.start,
 7362                    action.lines,
 7363                    selection.goal,
 7364                    false,
 7365                    text_layout_details,
 7366                );
 7367                selection.collapse_to(cursor, goal);
 7368            });
 7369        })
 7370    }
 7371
 7372    pub fn select_down_by_lines(&mut self, action: &SelectDownByLines, cx: &mut ViewContext<Self>) {
 7373        let text_layout_details = &self.text_layout_details(cx);
 7374        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7375            s.move_heads_with(|map, head, goal| {
 7376                movement::down_by_rows(map, head, action.lines, goal, false, text_layout_details)
 7377            })
 7378        })
 7379    }
 7380
 7381    pub fn select_up_by_lines(&mut self, action: &SelectUpByLines, cx: &mut ViewContext<Self>) {
 7382        let text_layout_details = &self.text_layout_details(cx);
 7383        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7384            s.move_heads_with(|map, head, goal| {
 7385                movement::up_by_rows(map, head, action.lines, goal, false, text_layout_details)
 7386            })
 7387        })
 7388    }
 7389
 7390    pub fn select_page_up(&mut self, _: &SelectPageUp, cx: &mut ViewContext<Self>) {
 7391        let Some(row_count) = self.visible_row_count() else {
 7392            return;
 7393        };
 7394
 7395        let text_layout_details = &self.text_layout_details(cx);
 7396
 7397        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7398            s.move_heads_with(|map, head, goal| {
 7399                movement::up_by_rows(map, head, row_count, goal, false, text_layout_details)
 7400            })
 7401        })
 7402    }
 7403
 7404    pub fn move_page_up(&mut self, action: &MovePageUp, cx: &mut ViewContext<Self>) {
 7405        if self.take_rename(true, cx).is_some() {
 7406            return;
 7407        }
 7408
 7409        if self
 7410            .context_menu
 7411            .borrow_mut()
 7412            .as_mut()
 7413            .map(|menu| menu.select_first(self.completion_provider.as_deref(), cx))
 7414            .unwrap_or(false)
 7415        {
 7416            return;
 7417        }
 7418
 7419        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 7420            cx.propagate();
 7421            return;
 7422        }
 7423
 7424        let Some(row_count) = self.visible_row_count() else {
 7425            return;
 7426        };
 7427
 7428        let autoscroll = if action.center_cursor {
 7429            Autoscroll::center()
 7430        } else {
 7431            Autoscroll::fit()
 7432        };
 7433
 7434        let text_layout_details = &self.text_layout_details(cx);
 7435
 7436        self.change_selections(Some(autoscroll), cx, |s| {
 7437            let line_mode = s.line_mode;
 7438            s.move_with(|map, selection| {
 7439                if !selection.is_empty() && !line_mode {
 7440                    selection.goal = SelectionGoal::None;
 7441                }
 7442                let (cursor, goal) = movement::up_by_rows(
 7443                    map,
 7444                    selection.end,
 7445                    row_count,
 7446                    selection.goal,
 7447                    false,
 7448                    text_layout_details,
 7449                );
 7450                selection.collapse_to(cursor, goal);
 7451            });
 7452        });
 7453    }
 7454
 7455    pub fn select_up(&mut self, _: &SelectUp, cx: &mut ViewContext<Self>) {
 7456        let text_layout_details = &self.text_layout_details(cx);
 7457        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7458            s.move_heads_with(|map, head, goal| {
 7459                movement::up(map, head, goal, false, text_layout_details)
 7460            })
 7461        })
 7462    }
 7463
 7464    pub fn move_down(&mut self, _: &MoveDown, cx: &mut ViewContext<Self>) {
 7465        self.take_rename(true, cx);
 7466
 7467        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 7468            cx.propagate();
 7469            return;
 7470        }
 7471
 7472        let text_layout_details = &self.text_layout_details(cx);
 7473        let selection_count = self.selections.count();
 7474        let first_selection = self.selections.first_anchor();
 7475
 7476        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7477            let line_mode = s.line_mode;
 7478            s.move_with(|map, selection| {
 7479                if !selection.is_empty() && !line_mode {
 7480                    selection.goal = SelectionGoal::None;
 7481                }
 7482                let (cursor, goal) = movement::down(
 7483                    map,
 7484                    selection.end,
 7485                    selection.goal,
 7486                    false,
 7487                    text_layout_details,
 7488                );
 7489                selection.collapse_to(cursor, goal);
 7490            });
 7491        });
 7492
 7493        if selection_count == 1 && first_selection.range() == self.selections.first_anchor().range()
 7494        {
 7495            cx.propagate();
 7496        }
 7497    }
 7498
 7499    pub fn select_page_down(&mut self, _: &SelectPageDown, cx: &mut ViewContext<Self>) {
 7500        let Some(row_count) = self.visible_row_count() else {
 7501            return;
 7502        };
 7503
 7504        let text_layout_details = &self.text_layout_details(cx);
 7505
 7506        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7507            s.move_heads_with(|map, head, goal| {
 7508                movement::down_by_rows(map, head, row_count, goal, false, text_layout_details)
 7509            })
 7510        })
 7511    }
 7512
 7513    pub fn move_page_down(&mut self, action: &MovePageDown, cx: &mut ViewContext<Self>) {
 7514        if self.take_rename(true, cx).is_some() {
 7515            return;
 7516        }
 7517
 7518        if self
 7519            .context_menu
 7520            .borrow_mut()
 7521            .as_mut()
 7522            .map(|menu| menu.select_last(self.completion_provider.as_deref(), cx))
 7523            .unwrap_or(false)
 7524        {
 7525            return;
 7526        }
 7527
 7528        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 7529            cx.propagate();
 7530            return;
 7531        }
 7532
 7533        let Some(row_count) = self.visible_row_count() else {
 7534            return;
 7535        };
 7536
 7537        let autoscroll = if action.center_cursor {
 7538            Autoscroll::center()
 7539        } else {
 7540            Autoscroll::fit()
 7541        };
 7542
 7543        let text_layout_details = &self.text_layout_details(cx);
 7544        self.change_selections(Some(autoscroll), cx, |s| {
 7545            let line_mode = s.line_mode;
 7546            s.move_with(|map, selection| {
 7547                if !selection.is_empty() && !line_mode {
 7548                    selection.goal = SelectionGoal::None;
 7549                }
 7550                let (cursor, goal) = movement::down_by_rows(
 7551                    map,
 7552                    selection.end,
 7553                    row_count,
 7554                    selection.goal,
 7555                    false,
 7556                    text_layout_details,
 7557                );
 7558                selection.collapse_to(cursor, goal);
 7559            });
 7560        });
 7561    }
 7562
 7563    pub fn select_down(&mut self, _: &SelectDown, cx: &mut ViewContext<Self>) {
 7564        let text_layout_details = &self.text_layout_details(cx);
 7565        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7566            s.move_heads_with(|map, head, goal| {
 7567                movement::down(map, head, goal, false, text_layout_details)
 7568            })
 7569        });
 7570    }
 7571
 7572    pub fn context_menu_first(&mut self, _: &ContextMenuFirst, cx: &mut ViewContext<Self>) {
 7573        if let Some(context_menu) = self.context_menu.borrow_mut().as_mut() {
 7574            context_menu.select_first(self.completion_provider.as_deref(), cx);
 7575        }
 7576    }
 7577
 7578    pub fn context_menu_prev(&mut self, _: &ContextMenuPrev, cx: &mut ViewContext<Self>) {
 7579        if let Some(context_menu) = self.context_menu.borrow_mut().as_mut() {
 7580            context_menu.select_prev(self.completion_provider.as_deref(), cx);
 7581        }
 7582    }
 7583
 7584    pub fn context_menu_next(&mut self, _: &ContextMenuNext, cx: &mut ViewContext<Self>) {
 7585        if let Some(context_menu) = self.context_menu.borrow_mut().as_mut() {
 7586            context_menu.select_next(self.completion_provider.as_deref(), cx);
 7587        }
 7588    }
 7589
 7590    pub fn context_menu_last(&mut self, _: &ContextMenuLast, cx: &mut ViewContext<Self>) {
 7591        if let Some(context_menu) = self.context_menu.borrow_mut().as_mut() {
 7592            context_menu.select_last(self.completion_provider.as_deref(), cx);
 7593        }
 7594    }
 7595
 7596    pub fn move_to_previous_word_start(
 7597        &mut self,
 7598        _: &MoveToPreviousWordStart,
 7599        cx: &mut ViewContext<Self>,
 7600    ) {
 7601        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7602            s.move_cursors_with(|map, head, _| {
 7603                (
 7604                    movement::previous_word_start(map, head),
 7605                    SelectionGoal::None,
 7606                )
 7607            });
 7608        })
 7609    }
 7610
 7611    pub fn move_to_previous_subword_start(
 7612        &mut self,
 7613        _: &MoveToPreviousSubwordStart,
 7614        cx: &mut ViewContext<Self>,
 7615    ) {
 7616        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7617            s.move_cursors_with(|map, head, _| {
 7618                (
 7619                    movement::previous_subword_start(map, head),
 7620                    SelectionGoal::None,
 7621                )
 7622            });
 7623        })
 7624    }
 7625
 7626    pub fn select_to_previous_word_start(
 7627        &mut self,
 7628        _: &SelectToPreviousWordStart,
 7629        cx: &mut ViewContext<Self>,
 7630    ) {
 7631        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7632            s.move_heads_with(|map, head, _| {
 7633                (
 7634                    movement::previous_word_start(map, head),
 7635                    SelectionGoal::None,
 7636                )
 7637            });
 7638        })
 7639    }
 7640
 7641    pub fn select_to_previous_subword_start(
 7642        &mut self,
 7643        _: &SelectToPreviousSubwordStart,
 7644        cx: &mut ViewContext<Self>,
 7645    ) {
 7646        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7647            s.move_heads_with(|map, head, _| {
 7648                (
 7649                    movement::previous_subword_start(map, head),
 7650                    SelectionGoal::None,
 7651                )
 7652            });
 7653        })
 7654    }
 7655
 7656    pub fn delete_to_previous_word_start(
 7657        &mut self,
 7658        action: &DeleteToPreviousWordStart,
 7659        cx: &mut ViewContext<Self>,
 7660    ) {
 7661        self.transact(cx, |this, cx| {
 7662            this.select_autoclose_pair(cx);
 7663            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7664                let line_mode = s.line_mode;
 7665                s.move_with(|map, selection| {
 7666                    if selection.is_empty() && !line_mode {
 7667                        let cursor = if action.ignore_newlines {
 7668                            movement::previous_word_start(map, selection.head())
 7669                        } else {
 7670                            movement::previous_word_start_or_newline(map, selection.head())
 7671                        };
 7672                        selection.set_head(cursor, SelectionGoal::None);
 7673                    }
 7674                });
 7675            });
 7676            this.insert("", cx);
 7677        });
 7678    }
 7679
 7680    pub fn delete_to_previous_subword_start(
 7681        &mut self,
 7682        _: &DeleteToPreviousSubwordStart,
 7683        cx: &mut ViewContext<Self>,
 7684    ) {
 7685        self.transact(cx, |this, cx| {
 7686            this.select_autoclose_pair(cx);
 7687            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7688                let line_mode = s.line_mode;
 7689                s.move_with(|map, selection| {
 7690                    if selection.is_empty() && !line_mode {
 7691                        let cursor = movement::previous_subword_start(map, selection.head());
 7692                        selection.set_head(cursor, SelectionGoal::None);
 7693                    }
 7694                });
 7695            });
 7696            this.insert("", cx);
 7697        });
 7698    }
 7699
 7700    pub fn move_to_next_word_end(&mut self, _: &MoveToNextWordEnd, cx: &mut ViewContext<Self>) {
 7701        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7702            s.move_cursors_with(|map, head, _| {
 7703                (movement::next_word_end(map, head), SelectionGoal::None)
 7704            });
 7705        })
 7706    }
 7707
 7708    pub fn move_to_next_subword_end(
 7709        &mut self,
 7710        _: &MoveToNextSubwordEnd,
 7711        cx: &mut ViewContext<Self>,
 7712    ) {
 7713        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7714            s.move_cursors_with(|map, head, _| {
 7715                (movement::next_subword_end(map, head), SelectionGoal::None)
 7716            });
 7717        })
 7718    }
 7719
 7720    pub fn select_to_next_word_end(&mut self, _: &SelectToNextWordEnd, cx: &mut ViewContext<Self>) {
 7721        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7722            s.move_heads_with(|map, head, _| {
 7723                (movement::next_word_end(map, head), SelectionGoal::None)
 7724            });
 7725        })
 7726    }
 7727
 7728    pub fn select_to_next_subword_end(
 7729        &mut self,
 7730        _: &SelectToNextSubwordEnd,
 7731        cx: &mut ViewContext<Self>,
 7732    ) {
 7733        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7734            s.move_heads_with(|map, head, _| {
 7735                (movement::next_subword_end(map, head), SelectionGoal::None)
 7736            });
 7737        })
 7738    }
 7739
 7740    pub fn delete_to_next_word_end(
 7741        &mut self,
 7742        action: &DeleteToNextWordEnd,
 7743        cx: &mut ViewContext<Self>,
 7744    ) {
 7745        self.transact(cx, |this, cx| {
 7746            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7747                let line_mode = s.line_mode;
 7748                s.move_with(|map, selection| {
 7749                    if selection.is_empty() && !line_mode {
 7750                        let cursor = if action.ignore_newlines {
 7751                            movement::next_word_end(map, selection.head())
 7752                        } else {
 7753                            movement::next_word_end_or_newline(map, selection.head())
 7754                        };
 7755                        selection.set_head(cursor, SelectionGoal::None);
 7756                    }
 7757                });
 7758            });
 7759            this.insert("", cx);
 7760        });
 7761    }
 7762
 7763    pub fn delete_to_next_subword_end(
 7764        &mut self,
 7765        _: &DeleteToNextSubwordEnd,
 7766        cx: &mut ViewContext<Self>,
 7767    ) {
 7768        self.transact(cx, |this, cx| {
 7769            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7770                s.move_with(|map, selection| {
 7771                    if selection.is_empty() {
 7772                        let cursor = movement::next_subword_end(map, selection.head());
 7773                        selection.set_head(cursor, SelectionGoal::None);
 7774                    }
 7775                });
 7776            });
 7777            this.insert("", cx);
 7778        });
 7779    }
 7780
 7781    pub fn move_to_beginning_of_line(
 7782        &mut self,
 7783        action: &MoveToBeginningOfLine,
 7784        cx: &mut ViewContext<Self>,
 7785    ) {
 7786        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7787            s.move_cursors_with(|map, head, _| {
 7788                (
 7789                    movement::indented_line_beginning(map, head, action.stop_at_soft_wraps),
 7790                    SelectionGoal::None,
 7791                )
 7792            });
 7793        })
 7794    }
 7795
 7796    pub fn select_to_beginning_of_line(
 7797        &mut self,
 7798        action: &SelectToBeginningOfLine,
 7799        cx: &mut ViewContext<Self>,
 7800    ) {
 7801        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7802            s.move_heads_with(|map, head, _| {
 7803                (
 7804                    movement::indented_line_beginning(map, head, action.stop_at_soft_wraps),
 7805                    SelectionGoal::None,
 7806                )
 7807            });
 7808        });
 7809    }
 7810
 7811    pub fn delete_to_beginning_of_line(
 7812        &mut self,
 7813        _: &DeleteToBeginningOfLine,
 7814        cx: &mut ViewContext<Self>,
 7815    ) {
 7816        self.transact(cx, |this, cx| {
 7817            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7818                s.move_with(|_, selection| {
 7819                    selection.reversed = true;
 7820                });
 7821            });
 7822
 7823            this.select_to_beginning_of_line(
 7824                &SelectToBeginningOfLine {
 7825                    stop_at_soft_wraps: false,
 7826                },
 7827                cx,
 7828            );
 7829            this.backspace(&Backspace, cx);
 7830        });
 7831    }
 7832
 7833    pub fn move_to_end_of_line(&mut self, action: &MoveToEndOfLine, cx: &mut ViewContext<Self>) {
 7834        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7835            s.move_cursors_with(|map, head, _| {
 7836                (
 7837                    movement::line_end(map, head, action.stop_at_soft_wraps),
 7838                    SelectionGoal::None,
 7839                )
 7840            });
 7841        })
 7842    }
 7843
 7844    pub fn select_to_end_of_line(
 7845        &mut self,
 7846        action: &SelectToEndOfLine,
 7847        cx: &mut ViewContext<Self>,
 7848    ) {
 7849        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7850            s.move_heads_with(|map, head, _| {
 7851                (
 7852                    movement::line_end(map, head, action.stop_at_soft_wraps),
 7853                    SelectionGoal::None,
 7854                )
 7855            });
 7856        })
 7857    }
 7858
 7859    pub fn delete_to_end_of_line(&mut self, _: &DeleteToEndOfLine, cx: &mut ViewContext<Self>) {
 7860        self.transact(cx, |this, cx| {
 7861            this.select_to_end_of_line(
 7862                &SelectToEndOfLine {
 7863                    stop_at_soft_wraps: false,
 7864                },
 7865                cx,
 7866            );
 7867            this.delete(&Delete, cx);
 7868        });
 7869    }
 7870
 7871    pub fn cut_to_end_of_line(&mut self, _: &CutToEndOfLine, cx: &mut ViewContext<Self>) {
 7872        self.transact(cx, |this, cx| {
 7873            this.select_to_end_of_line(
 7874                &SelectToEndOfLine {
 7875                    stop_at_soft_wraps: false,
 7876                },
 7877                cx,
 7878            );
 7879            this.cut(&Cut, cx);
 7880        });
 7881    }
 7882
 7883    pub fn move_to_start_of_paragraph(
 7884        &mut self,
 7885        _: &MoveToStartOfParagraph,
 7886        cx: &mut ViewContext<Self>,
 7887    ) {
 7888        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 7889            cx.propagate();
 7890            return;
 7891        }
 7892
 7893        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7894            s.move_with(|map, selection| {
 7895                selection.collapse_to(
 7896                    movement::start_of_paragraph(map, selection.head(), 1),
 7897                    SelectionGoal::None,
 7898                )
 7899            });
 7900        })
 7901    }
 7902
 7903    pub fn move_to_end_of_paragraph(
 7904        &mut self,
 7905        _: &MoveToEndOfParagraph,
 7906        cx: &mut ViewContext<Self>,
 7907    ) {
 7908        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 7909            cx.propagate();
 7910            return;
 7911        }
 7912
 7913        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7914            s.move_with(|map, selection| {
 7915                selection.collapse_to(
 7916                    movement::end_of_paragraph(map, selection.head(), 1),
 7917                    SelectionGoal::None,
 7918                )
 7919            });
 7920        })
 7921    }
 7922
 7923    pub fn select_to_start_of_paragraph(
 7924        &mut self,
 7925        _: &SelectToStartOfParagraph,
 7926        cx: &mut ViewContext<Self>,
 7927    ) {
 7928        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 7929            cx.propagate();
 7930            return;
 7931        }
 7932
 7933        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7934            s.move_heads_with(|map, head, _| {
 7935                (
 7936                    movement::start_of_paragraph(map, head, 1),
 7937                    SelectionGoal::None,
 7938                )
 7939            });
 7940        })
 7941    }
 7942
 7943    pub fn select_to_end_of_paragraph(
 7944        &mut self,
 7945        _: &SelectToEndOfParagraph,
 7946        cx: &mut ViewContext<Self>,
 7947    ) {
 7948        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 7949            cx.propagate();
 7950            return;
 7951        }
 7952
 7953        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7954            s.move_heads_with(|map, head, _| {
 7955                (
 7956                    movement::end_of_paragraph(map, head, 1),
 7957                    SelectionGoal::None,
 7958                )
 7959            });
 7960        })
 7961    }
 7962
 7963    pub fn move_to_beginning(&mut self, _: &MoveToBeginning, cx: &mut ViewContext<Self>) {
 7964        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 7965            cx.propagate();
 7966            return;
 7967        }
 7968
 7969        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7970            s.select_ranges(vec![0..0]);
 7971        });
 7972    }
 7973
 7974    pub fn select_to_beginning(&mut self, _: &SelectToBeginning, cx: &mut ViewContext<Self>) {
 7975        let mut selection = self.selections.last::<Point>(cx);
 7976        selection.set_head(Point::zero(), SelectionGoal::None);
 7977
 7978        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7979            s.select(vec![selection]);
 7980        });
 7981    }
 7982
 7983    pub fn move_to_end(&mut self, _: &MoveToEnd, cx: &mut ViewContext<Self>) {
 7984        if matches!(self.mode, EditorMode::SingleLine { .. }) {
 7985            cx.propagate();
 7986            return;
 7987        }
 7988
 7989        let cursor = self.buffer.read(cx).read(cx).len();
 7990        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7991            s.select_ranges(vec![cursor..cursor])
 7992        });
 7993    }
 7994
 7995    pub fn set_nav_history(&mut self, nav_history: Option<ItemNavHistory>) {
 7996        self.nav_history = nav_history;
 7997    }
 7998
 7999    pub fn nav_history(&self) -> Option<&ItemNavHistory> {
 8000        self.nav_history.as_ref()
 8001    }
 8002
 8003    fn push_to_nav_history(
 8004        &mut self,
 8005        cursor_anchor: Anchor,
 8006        new_position: Option<Point>,
 8007        cx: &mut ViewContext<Self>,
 8008    ) {
 8009        if let Some(nav_history) = self.nav_history.as_mut() {
 8010            let buffer = self.buffer.read(cx).read(cx);
 8011            let cursor_position = cursor_anchor.to_point(&buffer);
 8012            let scroll_state = self.scroll_manager.anchor();
 8013            let scroll_top_row = scroll_state.top_row(&buffer);
 8014            drop(buffer);
 8015
 8016            if let Some(new_position) = new_position {
 8017                let row_delta = (new_position.row as i64 - cursor_position.row as i64).abs();
 8018                if row_delta < MIN_NAVIGATION_HISTORY_ROW_DELTA {
 8019                    return;
 8020                }
 8021            }
 8022
 8023            nav_history.push(
 8024                Some(NavigationData {
 8025                    cursor_anchor,
 8026                    cursor_position,
 8027                    scroll_anchor: scroll_state,
 8028                    scroll_top_row,
 8029                }),
 8030                cx,
 8031            );
 8032        }
 8033    }
 8034
 8035    pub fn select_to_end(&mut self, _: &SelectToEnd, cx: &mut ViewContext<Self>) {
 8036        let buffer = self.buffer.read(cx).snapshot(cx);
 8037        let mut selection = self.selections.first::<usize>(cx);
 8038        selection.set_head(buffer.len(), SelectionGoal::None);
 8039        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 8040            s.select(vec![selection]);
 8041        });
 8042    }
 8043
 8044    pub fn select_all(&mut self, _: &SelectAll, cx: &mut ViewContext<Self>) {
 8045        let end = self.buffer.read(cx).read(cx).len();
 8046        self.change_selections(None, cx, |s| {
 8047            s.select_ranges(vec![0..end]);
 8048        });
 8049    }
 8050
 8051    pub fn select_line(&mut self, _: &SelectLine, cx: &mut ViewContext<Self>) {
 8052        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8053        let mut selections = self.selections.all::<Point>(cx);
 8054        let max_point = display_map.buffer_snapshot.max_point();
 8055        for selection in &mut selections {
 8056            let rows = selection.spanned_rows(true, &display_map);
 8057            selection.start = Point::new(rows.start.0, 0);
 8058            selection.end = cmp::min(max_point, Point::new(rows.end.0, 0));
 8059            selection.reversed = false;
 8060        }
 8061        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 8062            s.select(selections);
 8063        });
 8064    }
 8065
 8066    pub fn split_selection_into_lines(
 8067        &mut self,
 8068        _: &SplitSelectionIntoLines,
 8069        cx: &mut ViewContext<Self>,
 8070    ) {
 8071        let mut to_unfold = Vec::new();
 8072        let mut new_selection_ranges = Vec::new();
 8073        {
 8074            let selections = self.selections.all::<Point>(cx);
 8075            let buffer = self.buffer.read(cx).read(cx);
 8076            for selection in selections {
 8077                for row in selection.start.row..selection.end.row {
 8078                    let cursor = Point::new(row, buffer.line_len(MultiBufferRow(row)));
 8079                    new_selection_ranges.push(cursor..cursor);
 8080                }
 8081                new_selection_ranges.push(selection.end..selection.end);
 8082                to_unfold.push(selection.start..selection.end);
 8083            }
 8084        }
 8085        self.unfold_ranges(&to_unfold, true, true, cx);
 8086        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 8087            s.select_ranges(new_selection_ranges);
 8088        });
 8089    }
 8090
 8091    pub fn add_selection_above(&mut self, _: &AddSelectionAbove, cx: &mut ViewContext<Self>) {
 8092        self.add_selection(true, cx);
 8093    }
 8094
 8095    pub fn add_selection_below(&mut self, _: &AddSelectionBelow, cx: &mut ViewContext<Self>) {
 8096        self.add_selection(false, cx);
 8097    }
 8098
 8099    fn add_selection(&mut self, above: bool, cx: &mut ViewContext<Self>) {
 8100        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8101        let mut selections = self.selections.all::<Point>(cx);
 8102        let text_layout_details = self.text_layout_details(cx);
 8103        let mut state = self.add_selections_state.take().unwrap_or_else(|| {
 8104            let oldest_selection = selections.iter().min_by_key(|s| s.id).unwrap().clone();
 8105            let range = oldest_selection.display_range(&display_map).sorted();
 8106
 8107            let start_x = display_map.x_for_display_point(range.start, &text_layout_details);
 8108            let end_x = display_map.x_for_display_point(range.end, &text_layout_details);
 8109            let positions = start_x.min(end_x)..start_x.max(end_x);
 8110
 8111            selections.clear();
 8112            let mut stack = Vec::new();
 8113            for row in range.start.row().0..=range.end.row().0 {
 8114                if let Some(selection) = self.selections.build_columnar_selection(
 8115                    &display_map,
 8116                    DisplayRow(row),
 8117                    &positions,
 8118                    oldest_selection.reversed,
 8119                    &text_layout_details,
 8120                ) {
 8121                    stack.push(selection.id);
 8122                    selections.push(selection);
 8123                }
 8124            }
 8125
 8126            if above {
 8127                stack.reverse();
 8128            }
 8129
 8130            AddSelectionsState { above, stack }
 8131        });
 8132
 8133        let last_added_selection = *state.stack.last().unwrap();
 8134        let mut new_selections = Vec::new();
 8135        if above == state.above {
 8136            let end_row = if above {
 8137                DisplayRow(0)
 8138            } else {
 8139                display_map.max_point().row()
 8140            };
 8141
 8142            'outer: for selection in selections {
 8143                if selection.id == last_added_selection {
 8144                    let range = selection.display_range(&display_map).sorted();
 8145                    debug_assert_eq!(range.start.row(), range.end.row());
 8146                    let mut row = range.start.row();
 8147                    let positions =
 8148                        if let SelectionGoal::HorizontalRange { start, end } = selection.goal {
 8149                            px(start)..px(end)
 8150                        } else {
 8151                            let start_x =
 8152                                display_map.x_for_display_point(range.start, &text_layout_details);
 8153                            let end_x =
 8154                                display_map.x_for_display_point(range.end, &text_layout_details);
 8155                            start_x.min(end_x)..start_x.max(end_x)
 8156                        };
 8157
 8158                    while row != end_row {
 8159                        if above {
 8160                            row.0 -= 1;
 8161                        } else {
 8162                            row.0 += 1;
 8163                        }
 8164
 8165                        if let Some(new_selection) = self.selections.build_columnar_selection(
 8166                            &display_map,
 8167                            row,
 8168                            &positions,
 8169                            selection.reversed,
 8170                            &text_layout_details,
 8171                        ) {
 8172                            state.stack.push(new_selection.id);
 8173                            if above {
 8174                                new_selections.push(new_selection);
 8175                                new_selections.push(selection);
 8176                            } else {
 8177                                new_selections.push(selection);
 8178                                new_selections.push(new_selection);
 8179                            }
 8180
 8181                            continue 'outer;
 8182                        }
 8183                    }
 8184                }
 8185
 8186                new_selections.push(selection);
 8187            }
 8188        } else {
 8189            new_selections = selections;
 8190            new_selections.retain(|s| s.id != last_added_selection);
 8191            state.stack.pop();
 8192        }
 8193
 8194        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 8195            s.select(new_selections);
 8196        });
 8197        if state.stack.len() > 1 {
 8198            self.add_selections_state = Some(state);
 8199        }
 8200    }
 8201
 8202    pub fn select_next_match_internal(
 8203        &mut self,
 8204        display_map: &DisplaySnapshot,
 8205        replace_newest: bool,
 8206        autoscroll: Option<Autoscroll>,
 8207        cx: &mut ViewContext<Self>,
 8208    ) -> Result<()> {
 8209        fn select_next_match_ranges(
 8210            this: &mut Editor,
 8211            range: Range<usize>,
 8212            replace_newest: bool,
 8213            auto_scroll: Option<Autoscroll>,
 8214            cx: &mut ViewContext<Editor>,
 8215        ) {
 8216            this.unfold_ranges(&[range.clone()], false, true, cx);
 8217            this.change_selections(auto_scroll, cx, |s| {
 8218                if replace_newest {
 8219                    s.delete(s.newest_anchor().id);
 8220                }
 8221                s.insert_range(range.clone());
 8222            });
 8223        }
 8224
 8225        let buffer = &display_map.buffer_snapshot;
 8226        let mut selections = self.selections.all::<usize>(cx);
 8227        if let Some(mut select_next_state) = self.select_next_state.take() {
 8228            let query = &select_next_state.query;
 8229            if !select_next_state.done {
 8230                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
 8231                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
 8232                let mut next_selected_range = None;
 8233
 8234                let bytes_after_last_selection =
 8235                    buffer.bytes_in_range(last_selection.end..buffer.len());
 8236                let bytes_before_first_selection = buffer.bytes_in_range(0..first_selection.start);
 8237                let query_matches = query
 8238                    .stream_find_iter(bytes_after_last_selection)
 8239                    .map(|result| (last_selection.end, result))
 8240                    .chain(
 8241                        query
 8242                            .stream_find_iter(bytes_before_first_selection)
 8243                            .map(|result| (0, result)),
 8244                    );
 8245
 8246                for (start_offset, query_match) in query_matches {
 8247                    let query_match = query_match.unwrap(); // can only fail due to I/O
 8248                    let offset_range =
 8249                        start_offset + query_match.start()..start_offset + query_match.end();
 8250                    let display_range = offset_range.start.to_display_point(display_map)
 8251                        ..offset_range.end.to_display_point(display_map);
 8252
 8253                    if !select_next_state.wordwise
 8254                        || (!movement::is_inside_word(display_map, display_range.start)
 8255                            && !movement::is_inside_word(display_map, display_range.end))
 8256                    {
 8257                        // TODO: This is n^2, because we might check all the selections
 8258                        if !selections
 8259                            .iter()
 8260                            .any(|selection| selection.range().overlaps(&offset_range))
 8261                        {
 8262                            next_selected_range = Some(offset_range);
 8263                            break;
 8264                        }
 8265                    }
 8266                }
 8267
 8268                if let Some(next_selected_range) = next_selected_range {
 8269                    select_next_match_ranges(
 8270                        self,
 8271                        next_selected_range,
 8272                        replace_newest,
 8273                        autoscroll,
 8274                        cx,
 8275                    );
 8276                } else {
 8277                    select_next_state.done = true;
 8278                }
 8279            }
 8280
 8281            self.select_next_state = Some(select_next_state);
 8282        } else {
 8283            let mut only_carets = true;
 8284            let mut same_text_selected = true;
 8285            let mut selected_text = None;
 8286
 8287            let mut selections_iter = selections.iter().peekable();
 8288            while let Some(selection) = selections_iter.next() {
 8289                if selection.start != selection.end {
 8290                    only_carets = false;
 8291                }
 8292
 8293                if same_text_selected {
 8294                    if selected_text.is_none() {
 8295                        selected_text =
 8296                            Some(buffer.text_for_range(selection.range()).collect::<String>());
 8297                    }
 8298
 8299                    if let Some(next_selection) = selections_iter.peek() {
 8300                        if next_selection.range().len() == selection.range().len() {
 8301                            let next_selected_text = buffer
 8302                                .text_for_range(next_selection.range())
 8303                                .collect::<String>();
 8304                            if Some(next_selected_text) != selected_text {
 8305                                same_text_selected = false;
 8306                                selected_text = None;
 8307                            }
 8308                        } else {
 8309                            same_text_selected = false;
 8310                            selected_text = None;
 8311                        }
 8312                    }
 8313                }
 8314            }
 8315
 8316            if only_carets {
 8317                for selection in &mut selections {
 8318                    let word_range = movement::surrounding_word(
 8319                        display_map,
 8320                        selection.start.to_display_point(display_map),
 8321                    );
 8322                    selection.start = word_range.start.to_offset(display_map, Bias::Left);
 8323                    selection.end = word_range.end.to_offset(display_map, Bias::Left);
 8324                    selection.goal = SelectionGoal::None;
 8325                    selection.reversed = false;
 8326                    select_next_match_ranges(
 8327                        self,
 8328                        selection.start..selection.end,
 8329                        replace_newest,
 8330                        autoscroll,
 8331                        cx,
 8332                    );
 8333                }
 8334
 8335                if selections.len() == 1 {
 8336                    let selection = selections
 8337                        .last()
 8338                        .expect("ensured that there's only one selection");
 8339                    let query = buffer
 8340                        .text_for_range(selection.start..selection.end)
 8341                        .collect::<String>();
 8342                    let is_empty = query.is_empty();
 8343                    let select_state = SelectNextState {
 8344                        query: AhoCorasick::new(&[query])?,
 8345                        wordwise: true,
 8346                        done: is_empty,
 8347                    };
 8348                    self.select_next_state = Some(select_state);
 8349                } else {
 8350                    self.select_next_state = None;
 8351                }
 8352            } else if let Some(selected_text) = selected_text {
 8353                self.select_next_state = Some(SelectNextState {
 8354                    query: AhoCorasick::new(&[selected_text])?,
 8355                    wordwise: false,
 8356                    done: false,
 8357                });
 8358                self.select_next_match_internal(display_map, replace_newest, autoscroll, cx)?;
 8359            }
 8360        }
 8361        Ok(())
 8362    }
 8363
 8364    pub fn select_all_matches(
 8365        &mut self,
 8366        _action: &SelectAllMatches,
 8367        cx: &mut ViewContext<Self>,
 8368    ) -> Result<()> {
 8369        self.push_to_selection_history();
 8370        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8371
 8372        self.select_next_match_internal(&display_map, false, None, cx)?;
 8373        let Some(select_next_state) = self.select_next_state.as_mut() else {
 8374            return Ok(());
 8375        };
 8376        if select_next_state.done {
 8377            return Ok(());
 8378        }
 8379
 8380        let mut new_selections = self.selections.all::<usize>(cx);
 8381
 8382        let buffer = &display_map.buffer_snapshot;
 8383        let query_matches = select_next_state
 8384            .query
 8385            .stream_find_iter(buffer.bytes_in_range(0..buffer.len()));
 8386
 8387        for query_match in query_matches {
 8388            let query_match = query_match.unwrap(); // can only fail due to I/O
 8389            let offset_range = query_match.start()..query_match.end();
 8390            let display_range = offset_range.start.to_display_point(&display_map)
 8391                ..offset_range.end.to_display_point(&display_map);
 8392
 8393            if !select_next_state.wordwise
 8394                || (!movement::is_inside_word(&display_map, display_range.start)
 8395                    && !movement::is_inside_word(&display_map, display_range.end))
 8396            {
 8397                self.selections.change_with(cx, |selections| {
 8398                    new_selections.push(Selection {
 8399                        id: selections.new_selection_id(),
 8400                        start: offset_range.start,
 8401                        end: offset_range.end,
 8402                        reversed: false,
 8403                        goal: SelectionGoal::None,
 8404                    });
 8405                });
 8406            }
 8407        }
 8408
 8409        new_selections.sort_by_key(|selection| selection.start);
 8410        let mut ix = 0;
 8411        while ix + 1 < new_selections.len() {
 8412            let current_selection = &new_selections[ix];
 8413            let next_selection = &new_selections[ix + 1];
 8414            if current_selection.range().overlaps(&next_selection.range()) {
 8415                if current_selection.id < next_selection.id {
 8416                    new_selections.remove(ix + 1);
 8417                } else {
 8418                    new_selections.remove(ix);
 8419                }
 8420            } else {
 8421                ix += 1;
 8422            }
 8423        }
 8424
 8425        select_next_state.done = true;
 8426        self.unfold_ranges(
 8427            &new_selections
 8428                .iter()
 8429                .map(|selection| selection.range())
 8430                .collect::<Vec<_>>(),
 8431            false,
 8432            false,
 8433            cx,
 8434        );
 8435        self.change_selections(Some(Autoscroll::fit()), cx, |selections| {
 8436            selections.select(new_selections)
 8437        });
 8438
 8439        Ok(())
 8440    }
 8441
 8442    pub fn select_next(&mut self, action: &SelectNext, cx: &mut ViewContext<Self>) -> Result<()> {
 8443        self.push_to_selection_history();
 8444        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8445        self.select_next_match_internal(
 8446            &display_map,
 8447            action.replace_newest,
 8448            Some(Autoscroll::newest()),
 8449            cx,
 8450        )?;
 8451        Ok(())
 8452    }
 8453
 8454    pub fn select_previous(
 8455        &mut self,
 8456        action: &SelectPrevious,
 8457        cx: &mut ViewContext<Self>,
 8458    ) -> Result<()> {
 8459        self.push_to_selection_history();
 8460        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8461        let buffer = &display_map.buffer_snapshot;
 8462        let mut selections = self.selections.all::<usize>(cx);
 8463        if let Some(mut select_prev_state) = self.select_prev_state.take() {
 8464            let query = &select_prev_state.query;
 8465            if !select_prev_state.done {
 8466                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
 8467                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
 8468                let mut next_selected_range = None;
 8469                // When we're iterating matches backwards, the oldest match will actually be the furthest one in the buffer.
 8470                let bytes_before_last_selection =
 8471                    buffer.reversed_bytes_in_range(0..last_selection.start);
 8472                let bytes_after_first_selection =
 8473                    buffer.reversed_bytes_in_range(first_selection.end..buffer.len());
 8474                let query_matches = query
 8475                    .stream_find_iter(bytes_before_last_selection)
 8476                    .map(|result| (last_selection.start, result))
 8477                    .chain(
 8478                        query
 8479                            .stream_find_iter(bytes_after_first_selection)
 8480                            .map(|result| (buffer.len(), result)),
 8481                    );
 8482                for (end_offset, query_match) in query_matches {
 8483                    let query_match = query_match.unwrap(); // can only fail due to I/O
 8484                    let offset_range =
 8485                        end_offset - query_match.end()..end_offset - query_match.start();
 8486                    let display_range = offset_range.start.to_display_point(&display_map)
 8487                        ..offset_range.end.to_display_point(&display_map);
 8488
 8489                    if !select_prev_state.wordwise
 8490                        || (!movement::is_inside_word(&display_map, display_range.start)
 8491                            && !movement::is_inside_word(&display_map, display_range.end))
 8492                    {
 8493                        next_selected_range = Some(offset_range);
 8494                        break;
 8495                    }
 8496                }
 8497
 8498                if let Some(next_selected_range) = next_selected_range {
 8499                    self.unfold_ranges(&[next_selected_range.clone()], false, true, cx);
 8500                    self.change_selections(Some(Autoscroll::newest()), cx, |s| {
 8501                        if action.replace_newest {
 8502                            s.delete(s.newest_anchor().id);
 8503                        }
 8504                        s.insert_range(next_selected_range);
 8505                    });
 8506                } else {
 8507                    select_prev_state.done = true;
 8508                }
 8509            }
 8510
 8511            self.select_prev_state = Some(select_prev_state);
 8512        } else {
 8513            let mut only_carets = true;
 8514            let mut same_text_selected = true;
 8515            let mut selected_text = None;
 8516
 8517            let mut selections_iter = selections.iter().peekable();
 8518            while let Some(selection) = selections_iter.next() {
 8519                if selection.start != selection.end {
 8520                    only_carets = false;
 8521                }
 8522
 8523                if same_text_selected {
 8524                    if selected_text.is_none() {
 8525                        selected_text =
 8526                            Some(buffer.text_for_range(selection.range()).collect::<String>());
 8527                    }
 8528
 8529                    if let Some(next_selection) = selections_iter.peek() {
 8530                        if next_selection.range().len() == selection.range().len() {
 8531                            let next_selected_text = buffer
 8532                                .text_for_range(next_selection.range())
 8533                                .collect::<String>();
 8534                            if Some(next_selected_text) != selected_text {
 8535                                same_text_selected = false;
 8536                                selected_text = None;
 8537                            }
 8538                        } else {
 8539                            same_text_selected = false;
 8540                            selected_text = None;
 8541                        }
 8542                    }
 8543                }
 8544            }
 8545
 8546            if only_carets {
 8547                for selection in &mut selections {
 8548                    let word_range = movement::surrounding_word(
 8549                        &display_map,
 8550                        selection.start.to_display_point(&display_map),
 8551                    );
 8552                    selection.start = word_range.start.to_offset(&display_map, Bias::Left);
 8553                    selection.end = word_range.end.to_offset(&display_map, Bias::Left);
 8554                    selection.goal = SelectionGoal::None;
 8555                    selection.reversed = false;
 8556                }
 8557                if selections.len() == 1 {
 8558                    let selection = selections
 8559                        .last()
 8560                        .expect("ensured that there's only one selection");
 8561                    let query = buffer
 8562                        .text_for_range(selection.start..selection.end)
 8563                        .collect::<String>();
 8564                    let is_empty = query.is_empty();
 8565                    let select_state = SelectNextState {
 8566                        query: AhoCorasick::new(&[query.chars().rev().collect::<String>()])?,
 8567                        wordwise: true,
 8568                        done: is_empty,
 8569                    };
 8570                    self.select_prev_state = Some(select_state);
 8571                } else {
 8572                    self.select_prev_state = None;
 8573                }
 8574
 8575                self.unfold_ranges(
 8576                    &selections.iter().map(|s| s.range()).collect::<Vec<_>>(),
 8577                    false,
 8578                    true,
 8579                    cx,
 8580                );
 8581                self.change_selections(Some(Autoscroll::newest()), cx, |s| {
 8582                    s.select(selections);
 8583                });
 8584            } else if let Some(selected_text) = selected_text {
 8585                self.select_prev_state = Some(SelectNextState {
 8586                    query: AhoCorasick::new(&[selected_text.chars().rev().collect::<String>()])?,
 8587                    wordwise: false,
 8588                    done: false,
 8589                });
 8590                self.select_previous(action, cx)?;
 8591            }
 8592        }
 8593        Ok(())
 8594    }
 8595
 8596    pub fn toggle_comments(&mut self, action: &ToggleComments, cx: &mut ViewContext<Self>) {
 8597        if self.read_only(cx) {
 8598            return;
 8599        }
 8600        let text_layout_details = &self.text_layout_details(cx);
 8601        self.transact(cx, |this, cx| {
 8602            let mut selections = this.selections.all::<MultiBufferPoint>(cx);
 8603            let mut edits = Vec::new();
 8604            let mut selection_edit_ranges = Vec::new();
 8605            let mut last_toggled_row = None;
 8606            let snapshot = this.buffer.read(cx).read(cx);
 8607            let empty_str: Arc<str> = Arc::default();
 8608            let mut suffixes_inserted = Vec::new();
 8609            let ignore_indent = action.ignore_indent;
 8610
 8611            fn comment_prefix_range(
 8612                snapshot: &MultiBufferSnapshot,
 8613                row: MultiBufferRow,
 8614                comment_prefix: &str,
 8615                comment_prefix_whitespace: &str,
 8616                ignore_indent: bool,
 8617            ) -> Range<Point> {
 8618                let indent_size = if ignore_indent {
 8619                    0
 8620                } else {
 8621                    snapshot.indent_size_for_line(row).len
 8622                };
 8623
 8624                let start = Point::new(row.0, indent_size);
 8625
 8626                let mut line_bytes = snapshot
 8627                    .bytes_in_range(start..snapshot.max_point())
 8628                    .flatten()
 8629                    .copied();
 8630
 8631                // If this line currently begins with the line comment prefix, then record
 8632                // the range containing the prefix.
 8633                if line_bytes
 8634                    .by_ref()
 8635                    .take(comment_prefix.len())
 8636                    .eq(comment_prefix.bytes())
 8637                {
 8638                    // Include any whitespace that matches the comment prefix.
 8639                    let matching_whitespace_len = line_bytes
 8640                        .zip(comment_prefix_whitespace.bytes())
 8641                        .take_while(|(a, b)| a == b)
 8642                        .count() as u32;
 8643                    let end = Point::new(
 8644                        start.row,
 8645                        start.column + comment_prefix.len() as u32 + matching_whitespace_len,
 8646                    );
 8647                    start..end
 8648                } else {
 8649                    start..start
 8650                }
 8651            }
 8652
 8653            fn comment_suffix_range(
 8654                snapshot: &MultiBufferSnapshot,
 8655                row: MultiBufferRow,
 8656                comment_suffix: &str,
 8657                comment_suffix_has_leading_space: bool,
 8658            ) -> Range<Point> {
 8659                let end = Point::new(row.0, snapshot.line_len(row));
 8660                let suffix_start_column = end.column.saturating_sub(comment_suffix.len() as u32);
 8661
 8662                let mut line_end_bytes = snapshot
 8663                    .bytes_in_range(Point::new(end.row, suffix_start_column.saturating_sub(1))..end)
 8664                    .flatten()
 8665                    .copied();
 8666
 8667                let leading_space_len = if suffix_start_column > 0
 8668                    && line_end_bytes.next() == Some(b' ')
 8669                    && comment_suffix_has_leading_space
 8670                {
 8671                    1
 8672                } else {
 8673                    0
 8674                };
 8675
 8676                // If this line currently begins with the line comment prefix, then record
 8677                // the range containing the prefix.
 8678                if line_end_bytes.by_ref().eq(comment_suffix.bytes()) {
 8679                    let start = Point::new(end.row, suffix_start_column - leading_space_len);
 8680                    start..end
 8681                } else {
 8682                    end..end
 8683                }
 8684            }
 8685
 8686            // TODO: Handle selections that cross excerpts
 8687            for selection in &mut selections {
 8688                let start_column = snapshot
 8689                    .indent_size_for_line(MultiBufferRow(selection.start.row))
 8690                    .len;
 8691                let language = if let Some(language) =
 8692                    snapshot.language_scope_at(Point::new(selection.start.row, start_column))
 8693                {
 8694                    language
 8695                } else {
 8696                    continue;
 8697                };
 8698
 8699                selection_edit_ranges.clear();
 8700
 8701                // If multiple selections contain a given row, avoid processing that
 8702                // row more than once.
 8703                let mut start_row = MultiBufferRow(selection.start.row);
 8704                if last_toggled_row == Some(start_row) {
 8705                    start_row = start_row.next_row();
 8706                }
 8707                let end_row =
 8708                    if selection.end.row > selection.start.row && selection.end.column == 0 {
 8709                        MultiBufferRow(selection.end.row - 1)
 8710                    } else {
 8711                        MultiBufferRow(selection.end.row)
 8712                    };
 8713                last_toggled_row = Some(end_row);
 8714
 8715                if start_row > end_row {
 8716                    continue;
 8717                }
 8718
 8719                // If the language has line comments, toggle those.
 8720                let mut full_comment_prefixes = language.line_comment_prefixes().to_vec();
 8721
 8722                // If ignore_indent is set, trim spaces from the right side of all full_comment_prefixes
 8723                if ignore_indent {
 8724                    full_comment_prefixes = full_comment_prefixes
 8725                        .into_iter()
 8726                        .map(|s| Arc::from(s.trim_end()))
 8727                        .collect();
 8728                }
 8729
 8730                if !full_comment_prefixes.is_empty() {
 8731                    let first_prefix = full_comment_prefixes
 8732                        .first()
 8733                        .expect("prefixes is non-empty");
 8734                    let prefix_trimmed_lengths = full_comment_prefixes
 8735                        .iter()
 8736                        .map(|p| p.trim_end_matches(' ').len())
 8737                        .collect::<SmallVec<[usize; 4]>>();
 8738
 8739                    let mut all_selection_lines_are_comments = true;
 8740
 8741                    for row in start_row.0..=end_row.0 {
 8742                        let row = MultiBufferRow(row);
 8743                        if start_row < end_row && snapshot.is_line_blank(row) {
 8744                            continue;
 8745                        }
 8746
 8747                        let prefix_range = full_comment_prefixes
 8748                            .iter()
 8749                            .zip(prefix_trimmed_lengths.iter().copied())
 8750                            .map(|(prefix, trimmed_prefix_len)| {
 8751                                comment_prefix_range(
 8752                                    snapshot.deref(),
 8753                                    row,
 8754                                    &prefix[..trimmed_prefix_len],
 8755                                    &prefix[trimmed_prefix_len..],
 8756                                    ignore_indent,
 8757                                )
 8758                            })
 8759                            .max_by_key(|range| range.end.column - range.start.column)
 8760                            .expect("prefixes is non-empty");
 8761
 8762                        if prefix_range.is_empty() {
 8763                            all_selection_lines_are_comments = false;
 8764                        }
 8765
 8766                        selection_edit_ranges.push(prefix_range);
 8767                    }
 8768
 8769                    if all_selection_lines_are_comments {
 8770                        edits.extend(
 8771                            selection_edit_ranges
 8772                                .iter()
 8773                                .cloned()
 8774                                .map(|range| (range, empty_str.clone())),
 8775                        );
 8776                    } else {
 8777                        let min_column = selection_edit_ranges
 8778                            .iter()
 8779                            .map(|range| range.start.column)
 8780                            .min()
 8781                            .unwrap_or(0);
 8782                        edits.extend(selection_edit_ranges.iter().map(|range| {
 8783                            let position = Point::new(range.start.row, min_column);
 8784                            (position..position, first_prefix.clone())
 8785                        }));
 8786                    }
 8787                } else if let Some((full_comment_prefix, comment_suffix)) =
 8788                    language.block_comment_delimiters()
 8789                {
 8790                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
 8791                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
 8792                    let prefix_range = comment_prefix_range(
 8793                        snapshot.deref(),
 8794                        start_row,
 8795                        comment_prefix,
 8796                        comment_prefix_whitespace,
 8797                        ignore_indent,
 8798                    );
 8799                    let suffix_range = comment_suffix_range(
 8800                        snapshot.deref(),
 8801                        end_row,
 8802                        comment_suffix.trim_start_matches(' '),
 8803                        comment_suffix.starts_with(' '),
 8804                    );
 8805
 8806                    if prefix_range.is_empty() || suffix_range.is_empty() {
 8807                        edits.push((
 8808                            prefix_range.start..prefix_range.start,
 8809                            full_comment_prefix.clone(),
 8810                        ));
 8811                        edits.push((suffix_range.end..suffix_range.end, comment_suffix.clone()));
 8812                        suffixes_inserted.push((end_row, comment_suffix.len()));
 8813                    } else {
 8814                        edits.push((prefix_range, empty_str.clone()));
 8815                        edits.push((suffix_range, empty_str.clone()));
 8816                    }
 8817                } else {
 8818                    continue;
 8819                }
 8820            }
 8821
 8822            drop(snapshot);
 8823            this.buffer.update(cx, |buffer, cx| {
 8824                buffer.edit(edits, None, cx);
 8825            });
 8826
 8827            // Adjust selections so that they end before any comment suffixes that
 8828            // were inserted.
 8829            let mut suffixes_inserted = suffixes_inserted.into_iter().peekable();
 8830            let mut selections = this.selections.all::<Point>(cx);
 8831            let snapshot = this.buffer.read(cx).read(cx);
 8832            for selection in &mut selections {
 8833                while let Some((row, suffix_len)) = suffixes_inserted.peek().copied() {
 8834                    match row.cmp(&MultiBufferRow(selection.end.row)) {
 8835                        Ordering::Less => {
 8836                            suffixes_inserted.next();
 8837                            continue;
 8838                        }
 8839                        Ordering::Greater => break,
 8840                        Ordering::Equal => {
 8841                            if selection.end.column == snapshot.line_len(row) {
 8842                                if selection.is_empty() {
 8843                                    selection.start.column -= suffix_len as u32;
 8844                                }
 8845                                selection.end.column -= suffix_len as u32;
 8846                            }
 8847                            break;
 8848                        }
 8849                    }
 8850                }
 8851            }
 8852
 8853            drop(snapshot);
 8854            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
 8855
 8856            let selections = this.selections.all::<Point>(cx);
 8857            let selections_on_single_row = selections.windows(2).all(|selections| {
 8858                selections[0].start.row == selections[1].start.row
 8859                    && selections[0].end.row == selections[1].end.row
 8860                    && selections[0].start.row == selections[0].end.row
 8861            });
 8862            let selections_selecting = selections
 8863                .iter()
 8864                .any(|selection| selection.start != selection.end);
 8865            let advance_downwards = action.advance_downwards
 8866                && selections_on_single_row
 8867                && !selections_selecting
 8868                && !matches!(this.mode, EditorMode::SingleLine { .. });
 8869
 8870            if advance_downwards {
 8871                let snapshot = this.buffer.read(cx).snapshot(cx);
 8872
 8873                this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 8874                    s.move_cursors_with(|display_snapshot, display_point, _| {
 8875                        let mut point = display_point.to_point(display_snapshot);
 8876                        point.row += 1;
 8877                        point = snapshot.clip_point(point, Bias::Left);
 8878                        let display_point = point.to_display_point(display_snapshot);
 8879                        let goal = SelectionGoal::HorizontalPosition(
 8880                            display_snapshot
 8881                                .x_for_display_point(display_point, text_layout_details)
 8882                                .into(),
 8883                        );
 8884                        (display_point, goal)
 8885                    })
 8886                });
 8887            }
 8888        });
 8889    }
 8890
 8891    pub fn select_enclosing_symbol(
 8892        &mut self,
 8893        _: &SelectEnclosingSymbol,
 8894        cx: &mut ViewContext<Self>,
 8895    ) {
 8896        let buffer = self.buffer.read(cx).snapshot(cx);
 8897        let old_selections = self.selections.all::<usize>(cx).into_boxed_slice();
 8898
 8899        fn update_selection(
 8900            selection: &Selection<usize>,
 8901            buffer_snap: &MultiBufferSnapshot,
 8902        ) -> Option<Selection<usize>> {
 8903            let cursor = selection.head();
 8904            let (_buffer_id, symbols) = buffer_snap.symbols_containing(cursor, None)?;
 8905            for symbol in symbols.iter().rev() {
 8906                let start = symbol.range.start.to_offset(buffer_snap);
 8907                let end = symbol.range.end.to_offset(buffer_snap);
 8908                let new_range = start..end;
 8909                if start < selection.start || end > selection.end {
 8910                    return Some(Selection {
 8911                        id: selection.id,
 8912                        start: new_range.start,
 8913                        end: new_range.end,
 8914                        goal: SelectionGoal::None,
 8915                        reversed: selection.reversed,
 8916                    });
 8917                }
 8918            }
 8919            None
 8920        }
 8921
 8922        let mut selected_larger_symbol = false;
 8923        let new_selections = old_selections
 8924            .iter()
 8925            .map(|selection| match update_selection(selection, &buffer) {
 8926                Some(new_selection) => {
 8927                    if new_selection.range() != selection.range() {
 8928                        selected_larger_symbol = true;
 8929                    }
 8930                    new_selection
 8931                }
 8932                None => selection.clone(),
 8933            })
 8934            .collect::<Vec<_>>();
 8935
 8936        if selected_larger_symbol {
 8937            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 8938                s.select(new_selections);
 8939            });
 8940        }
 8941    }
 8942
 8943    pub fn select_larger_syntax_node(
 8944        &mut self,
 8945        _: &SelectLargerSyntaxNode,
 8946        cx: &mut ViewContext<Self>,
 8947    ) {
 8948        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8949        let buffer = self.buffer.read(cx).snapshot(cx);
 8950        let old_selections = self.selections.all::<usize>(cx).into_boxed_slice();
 8951
 8952        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
 8953        let mut selected_larger_node = false;
 8954        let new_selections = old_selections
 8955            .iter()
 8956            .map(|selection| {
 8957                let old_range = selection.start..selection.end;
 8958                let mut new_range = old_range.clone();
 8959                let mut new_node = None;
 8960                while let Some((node, containing_range)) = buffer.syntax_ancestor(new_range.clone())
 8961                {
 8962                    new_node = Some(node);
 8963                    new_range = containing_range;
 8964                    if !display_map.intersects_fold(new_range.start)
 8965                        && !display_map.intersects_fold(new_range.end)
 8966                    {
 8967                        break;
 8968                    }
 8969                }
 8970
 8971                if let Some(node) = new_node {
 8972                    // Log the ancestor, to support using this action as a way to explore TreeSitter
 8973                    // nodes. Parent and grandparent are also logged because this operation will not
 8974                    // visit nodes that have the same range as their parent.
 8975                    log::info!("Node: {node:?}");
 8976                    let parent = node.parent();
 8977                    log::info!("Parent: {parent:?}");
 8978                    let grandparent = parent.and_then(|x| x.parent());
 8979                    log::info!("Grandparent: {grandparent:?}");
 8980                }
 8981
 8982                selected_larger_node |= new_range != old_range;
 8983                Selection {
 8984                    id: selection.id,
 8985                    start: new_range.start,
 8986                    end: new_range.end,
 8987                    goal: SelectionGoal::None,
 8988                    reversed: selection.reversed,
 8989                }
 8990            })
 8991            .collect::<Vec<_>>();
 8992
 8993        if selected_larger_node {
 8994            stack.push(old_selections);
 8995            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 8996                s.select(new_selections);
 8997            });
 8998        }
 8999        self.select_larger_syntax_node_stack = stack;
 9000    }
 9001
 9002    pub fn select_smaller_syntax_node(
 9003        &mut self,
 9004        _: &SelectSmallerSyntaxNode,
 9005        cx: &mut ViewContext<Self>,
 9006    ) {
 9007        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
 9008        if let Some(selections) = stack.pop() {
 9009            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 9010                s.select(selections.to_vec());
 9011            });
 9012        }
 9013        self.select_larger_syntax_node_stack = stack;
 9014    }
 9015
 9016    fn refresh_runnables(&mut self, cx: &mut ViewContext<Self>) -> Task<()> {
 9017        if !EditorSettings::get_global(cx).gutter.runnables {
 9018            self.clear_tasks();
 9019            return Task::ready(());
 9020        }
 9021        let project = self.project.as_ref().map(Model::downgrade);
 9022        cx.spawn(|this, mut cx| async move {
 9023            cx.background_executor().timer(UPDATE_DEBOUNCE).await;
 9024            let Some(project) = project.and_then(|p| p.upgrade()) else {
 9025                return;
 9026            };
 9027            let Ok(display_snapshot) = this.update(&mut cx, |this, cx| {
 9028                this.display_map.update(cx, |map, cx| map.snapshot(cx))
 9029            }) else {
 9030                return;
 9031            };
 9032
 9033            let hide_runnables = project
 9034                .update(&mut cx, |project, cx| {
 9035                    // Do not display any test indicators in non-dev server remote projects.
 9036                    project.is_via_collab() && project.ssh_connection_string(cx).is_none()
 9037                })
 9038                .unwrap_or(true);
 9039            if hide_runnables {
 9040                return;
 9041            }
 9042            let new_rows =
 9043                cx.background_executor()
 9044                    .spawn({
 9045                        let snapshot = display_snapshot.clone();
 9046                        async move {
 9047                            Self::fetch_runnable_ranges(&snapshot, Anchor::min()..Anchor::max())
 9048                        }
 9049                    })
 9050                    .await;
 9051            let rows = Self::runnable_rows(project, display_snapshot, new_rows, cx.clone());
 9052
 9053            this.update(&mut cx, |this, _| {
 9054                this.clear_tasks();
 9055                for (key, value) in rows {
 9056                    this.insert_tasks(key, value);
 9057                }
 9058            })
 9059            .ok();
 9060        })
 9061    }
 9062    fn fetch_runnable_ranges(
 9063        snapshot: &DisplaySnapshot,
 9064        range: Range<Anchor>,
 9065    ) -> Vec<language::RunnableRange> {
 9066        snapshot.buffer_snapshot.runnable_ranges(range).collect()
 9067    }
 9068
 9069    fn runnable_rows(
 9070        project: Model<Project>,
 9071        snapshot: DisplaySnapshot,
 9072        runnable_ranges: Vec<RunnableRange>,
 9073        mut cx: AsyncWindowContext,
 9074    ) -> Vec<((BufferId, u32), RunnableTasks)> {
 9075        runnable_ranges
 9076            .into_iter()
 9077            .filter_map(|mut runnable| {
 9078                let tasks = cx
 9079                    .update(|cx| Self::templates_with_tags(&project, &mut runnable.runnable, cx))
 9080                    .ok()?;
 9081                if tasks.is_empty() {
 9082                    return None;
 9083                }
 9084
 9085                let point = runnable.run_range.start.to_point(&snapshot.buffer_snapshot);
 9086
 9087                let row = snapshot
 9088                    .buffer_snapshot
 9089                    .buffer_line_for_row(MultiBufferRow(point.row))?
 9090                    .1
 9091                    .start
 9092                    .row;
 9093
 9094                let context_range =
 9095                    BufferOffset(runnable.full_range.start)..BufferOffset(runnable.full_range.end);
 9096                Some((
 9097                    (runnable.buffer_id, row),
 9098                    RunnableTasks {
 9099                        templates: tasks,
 9100                        offset: MultiBufferOffset(runnable.run_range.start),
 9101                        context_range,
 9102                        column: point.column,
 9103                        extra_variables: runnable.extra_captures,
 9104                    },
 9105                ))
 9106            })
 9107            .collect()
 9108    }
 9109
 9110    fn templates_with_tags(
 9111        project: &Model<Project>,
 9112        runnable: &mut Runnable,
 9113        cx: &WindowContext,
 9114    ) -> Vec<(TaskSourceKind, TaskTemplate)> {
 9115        let (inventory, worktree_id, file) = project.read_with(cx, |project, cx| {
 9116            let (worktree_id, file) = project
 9117                .buffer_for_id(runnable.buffer, cx)
 9118                .and_then(|buffer| buffer.read(cx).file())
 9119                .map(|file| (file.worktree_id(cx), file.clone()))
 9120                .unzip();
 9121
 9122            (
 9123                project.task_store().read(cx).task_inventory().cloned(),
 9124                worktree_id,
 9125                file,
 9126            )
 9127        });
 9128
 9129        let tags = mem::take(&mut runnable.tags);
 9130        let mut tags: Vec<_> = tags
 9131            .into_iter()
 9132            .flat_map(|tag| {
 9133                let tag = tag.0.clone();
 9134                inventory
 9135                    .as_ref()
 9136                    .into_iter()
 9137                    .flat_map(|inventory| {
 9138                        inventory.read(cx).list_tasks(
 9139                            file.clone(),
 9140                            Some(runnable.language.clone()),
 9141                            worktree_id,
 9142                            cx,
 9143                        )
 9144                    })
 9145                    .filter(move |(_, template)| {
 9146                        template.tags.iter().any(|source_tag| source_tag == &tag)
 9147                    })
 9148            })
 9149            .sorted_by_key(|(kind, _)| kind.to_owned())
 9150            .collect();
 9151        if let Some((leading_tag_source, _)) = tags.first() {
 9152            // Strongest source wins; if we have worktree tag binding, prefer that to
 9153            // global and language bindings;
 9154            // if we have a global binding, prefer that to language binding.
 9155            let first_mismatch = tags
 9156                .iter()
 9157                .position(|(tag_source, _)| tag_source != leading_tag_source);
 9158            if let Some(index) = first_mismatch {
 9159                tags.truncate(index);
 9160            }
 9161        }
 9162
 9163        tags
 9164    }
 9165
 9166    pub fn move_to_enclosing_bracket(
 9167        &mut self,
 9168        _: &MoveToEnclosingBracket,
 9169        cx: &mut ViewContext<Self>,
 9170    ) {
 9171        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 9172            s.move_offsets_with(|snapshot, selection| {
 9173                let Some(enclosing_bracket_ranges) =
 9174                    snapshot.enclosing_bracket_ranges(selection.start..selection.end)
 9175                else {
 9176                    return;
 9177                };
 9178
 9179                let mut best_length = usize::MAX;
 9180                let mut best_inside = false;
 9181                let mut best_in_bracket_range = false;
 9182                let mut best_destination = None;
 9183                for (open, close) in enclosing_bracket_ranges {
 9184                    let close = close.to_inclusive();
 9185                    let length = close.end() - open.start;
 9186                    let inside = selection.start >= open.end && selection.end <= *close.start();
 9187                    let in_bracket_range = open.to_inclusive().contains(&selection.head())
 9188                        || close.contains(&selection.head());
 9189
 9190                    // If best is next to a bracket and current isn't, skip
 9191                    if !in_bracket_range && best_in_bracket_range {
 9192                        continue;
 9193                    }
 9194
 9195                    // Prefer smaller lengths unless best is inside and current isn't
 9196                    if length > best_length && (best_inside || !inside) {
 9197                        continue;
 9198                    }
 9199
 9200                    best_length = length;
 9201                    best_inside = inside;
 9202                    best_in_bracket_range = in_bracket_range;
 9203                    best_destination = Some(
 9204                        if close.contains(&selection.start) && close.contains(&selection.end) {
 9205                            if inside {
 9206                                open.end
 9207                            } else {
 9208                                open.start
 9209                            }
 9210                        } else if inside {
 9211                            *close.start()
 9212                        } else {
 9213                            *close.end()
 9214                        },
 9215                    );
 9216                }
 9217
 9218                if let Some(destination) = best_destination {
 9219                    selection.collapse_to(destination, SelectionGoal::None);
 9220                }
 9221            })
 9222        });
 9223    }
 9224
 9225    pub fn undo_selection(&mut self, _: &UndoSelection, cx: &mut ViewContext<Self>) {
 9226        self.end_selection(cx);
 9227        self.selection_history.mode = SelectionHistoryMode::Undoing;
 9228        if let Some(entry) = self.selection_history.undo_stack.pop_back() {
 9229            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
 9230            self.select_next_state = entry.select_next_state;
 9231            self.select_prev_state = entry.select_prev_state;
 9232            self.add_selections_state = entry.add_selections_state;
 9233            self.request_autoscroll(Autoscroll::newest(), cx);
 9234        }
 9235        self.selection_history.mode = SelectionHistoryMode::Normal;
 9236    }
 9237
 9238    pub fn redo_selection(&mut self, _: &RedoSelection, cx: &mut ViewContext<Self>) {
 9239        self.end_selection(cx);
 9240        self.selection_history.mode = SelectionHistoryMode::Redoing;
 9241        if let Some(entry) = self.selection_history.redo_stack.pop_back() {
 9242            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
 9243            self.select_next_state = entry.select_next_state;
 9244            self.select_prev_state = entry.select_prev_state;
 9245            self.add_selections_state = entry.add_selections_state;
 9246            self.request_autoscroll(Autoscroll::newest(), cx);
 9247        }
 9248        self.selection_history.mode = SelectionHistoryMode::Normal;
 9249    }
 9250
 9251    pub fn expand_excerpts(&mut self, action: &ExpandExcerpts, cx: &mut ViewContext<Self>) {
 9252        self.expand_excerpts_for_direction(action.lines, ExpandExcerptDirection::UpAndDown, cx)
 9253    }
 9254
 9255    pub fn expand_excerpts_down(
 9256        &mut self,
 9257        action: &ExpandExcerptsDown,
 9258        cx: &mut ViewContext<Self>,
 9259    ) {
 9260        self.expand_excerpts_for_direction(action.lines, ExpandExcerptDirection::Down, cx)
 9261    }
 9262
 9263    pub fn expand_excerpts_up(&mut self, action: &ExpandExcerptsUp, cx: &mut ViewContext<Self>) {
 9264        self.expand_excerpts_for_direction(action.lines, ExpandExcerptDirection::Up, cx)
 9265    }
 9266
 9267    pub fn expand_excerpts_for_direction(
 9268        &mut self,
 9269        lines: u32,
 9270        direction: ExpandExcerptDirection,
 9271        cx: &mut ViewContext<Self>,
 9272    ) {
 9273        let selections = self.selections.disjoint_anchors();
 9274
 9275        let lines = if lines == 0 {
 9276            EditorSettings::get_global(cx).expand_excerpt_lines
 9277        } else {
 9278            lines
 9279        };
 9280
 9281        self.buffer.update(cx, |buffer, cx| {
 9282            let snapshot = buffer.snapshot(cx);
 9283            let mut excerpt_ids = selections
 9284                .iter()
 9285                .flat_map(|selection| {
 9286                    snapshot
 9287                        .excerpts_for_range(selection.range())
 9288                        .map(|excerpt| excerpt.id())
 9289                })
 9290                .collect::<Vec<_>>();
 9291            excerpt_ids.sort();
 9292            excerpt_ids.dedup();
 9293            buffer.expand_excerpts(excerpt_ids, lines, direction, cx)
 9294        })
 9295    }
 9296
 9297    pub fn expand_excerpt(
 9298        &mut self,
 9299        excerpt: ExcerptId,
 9300        direction: ExpandExcerptDirection,
 9301        cx: &mut ViewContext<Self>,
 9302    ) {
 9303        let lines = EditorSettings::get_global(cx).expand_excerpt_lines;
 9304        self.buffer.update(cx, |buffer, cx| {
 9305            buffer.expand_excerpts([excerpt], lines, direction, cx)
 9306        })
 9307    }
 9308
 9309    fn go_to_diagnostic(&mut self, _: &GoToDiagnostic, cx: &mut ViewContext<Self>) {
 9310        self.go_to_diagnostic_impl(Direction::Next, cx)
 9311    }
 9312
 9313    fn go_to_prev_diagnostic(&mut self, _: &GoToPrevDiagnostic, cx: &mut ViewContext<Self>) {
 9314        self.go_to_diagnostic_impl(Direction::Prev, cx)
 9315    }
 9316
 9317    pub fn go_to_diagnostic_impl(&mut self, direction: Direction, cx: &mut ViewContext<Self>) {
 9318        let buffer = self.buffer.read(cx).snapshot(cx);
 9319        let selection = self.selections.newest::<usize>(cx);
 9320
 9321        // If there is an active Diagnostic Popover jump to its diagnostic instead.
 9322        if direction == Direction::Next {
 9323            if let Some(popover) = self.hover_state.diagnostic_popover.as_ref() {
 9324                self.activate_diagnostics(popover.group_id(), cx);
 9325                if let Some(active_diagnostics) = self.active_diagnostics.as_ref() {
 9326                    let primary_range_start = active_diagnostics.primary_range.start;
 9327                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 9328                        let mut new_selection = s.newest_anchor().clone();
 9329                        new_selection.collapse_to(primary_range_start, SelectionGoal::None);
 9330                        s.select_anchors(vec![new_selection.clone()]);
 9331                    });
 9332                    self.refresh_inline_completion(false, true, cx);
 9333                }
 9334                return;
 9335            }
 9336        }
 9337
 9338        let mut active_primary_range = self.active_diagnostics.as_ref().map(|active_diagnostics| {
 9339            active_diagnostics
 9340                .primary_range
 9341                .to_offset(&buffer)
 9342                .to_inclusive()
 9343        });
 9344        let mut search_start = if let Some(active_primary_range) = active_primary_range.as_ref() {
 9345            if active_primary_range.contains(&selection.head()) {
 9346                *active_primary_range.start()
 9347            } else {
 9348                selection.head()
 9349            }
 9350        } else {
 9351            selection.head()
 9352        };
 9353        let snapshot = self.snapshot(cx);
 9354        loop {
 9355            let diagnostics = if direction == Direction::Prev {
 9356                buffer.diagnostics_in_range(0..search_start, true)
 9357            } else {
 9358                buffer.diagnostics_in_range(search_start..buffer.len(), false)
 9359            }
 9360            .filter(|diagnostic| !snapshot.intersects_fold(diagnostic.range.start));
 9361            let search_start_anchor = buffer.anchor_after(search_start);
 9362            let group = diagnostics
 9363                // relies on diagnostics_in_range to return diagnostics with the same starting range to
 9364                // be sorted in a stable way
 9365                // skip until we are at current active diagnostic, if it exists
 9366                .skip_while(|entry| {
 9367                    let is_in_range = match direction {
 9368                        Direction::Prev => {
 9369                            entry.range.start.cmp(&search_start_anchor, &buffer).is_ge()
 9370                        }
 9371                        Direction::Next => {
 9372                            entry.range.start.cmp(&search_start_anchor, &buffer).is_le()
 9373                        }
 9374                    };
 9375                    is_in_range
 9376                        && self
 9377                            .active_diagnostics
 9378                            .as_ref()
 9379                            .is_some_and(|a| a.group_id != entry.diagnostic.group_id)
 9380                })
 9381                .find_map(|entry| {
 9382                    if entry.diagnostic.is_primary
 9383                        && entry.diagnostic.severity <= DiagnosticSeverity::WARNING
 9384                        && !(entry.range.start == entry.range.end)
 9385                        // if we match with the active diagnostic, skip it
 9386                        && Some(entry.diagnostic.group_id)
 9387                            != self.active_diagnostics.as_ref().map(|d| d.group_id)
 9388                    {
 9389                        Some((entry.range, entry.diagnostic.group_id))
 9390                    } else {
 9391                        None
 9392                    }
 9393                });
 9394
 9395            if let Some((primary_range, group_id)) = group {
 9396                self.activate_diagnostics(group_id, cx);
 9397                let primary_range = primary_range.to_offset(&buffer);
 9398                if self.active_diagnostics.is_some() {
 9399                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 9400                        s.select(vec![Selection {
 9401                            id: selection.id,
 9402                            start: primary_range.start,
 9403                            end: primary_range.start,
 9404                            reversed: false,
 9405                            goal: SelectionGoal::None,
 9406                        }]);
 9407                    });
 9408                    self.refresh_inline_completion(false, true, cx);
 9409                }
 9410                break;
 9411            } else {
 9412                // Cycle around to the start of the buffer, potentially moving back to the start of
 9413                // the currently active diagnostic.
 9414                active_primary_range.take();
 9415                if direction == Direction::Prev {
 9416                    if search_start == buffer.len() {
 9417                        break;
 9418                    } else {
 9419                        search_start = buffer.len();
 9420                    }
 9421                } else if search_start == 0 {
 9422                    break;
 9423                } else {
 9424                    search_start = 0;
 9425                }
 9426            }
 9427        }
 9428    }
 9429
 9430    fn go_to_next_hunk(&mut self, _: &GoToHunk, cx: &mut ViewContext<Self>) {
 9431        let snapshot = self.snapshot(cx);
 9432        let selection = self.selections.newest::<Point>(cx);
 9433        self.go_to_hunk_after_position(&snapshot, selection.head(), cx);
 9434    }
 9435
 9436    fn go_to_hunk_after_position(
 9437        &mut self,
 9438        snapshot: &EditorSnapshot,
 9439        position: Point,
 9440        cx: &mut ViewContext<Editor>,
 9441    ) -> Option<MultiBufferDiffHunk> {
 9442        for (ix, position) in [position, Point::zero()].into_iter().enumerate() {
 9443            if let Some(hunk) = self.go_to_next_hunk_in_direction(
 9444                snapshot,
 9445                position,
 9446                ix > 0,
 9447                snapshot.diff_map.diff_hunks_in_range(
 9448                    position + Point::new(1, 0)..snapshot.buffer_snapshot.max_point(),
 9449                    &snapshot.buffer_snapshot,
 9450                ),
 9451                cx,
 9452            ) {
 9453                return Some(hunk);
 9454            }
 9455        }
 9456        None
 9457    }
 9458
 9459    fn go_to_prev_hunk(&mut self, _: &GoToPrevHunk, cx: &mut ViewContext<Self>) {
 9460        let snapshot = self.snapshot(cx);
 9461        let selection = self.selections.newest::<Point>(cx);
 9462        self.go_to_hunk_before_position(&snapshot, selection.head(), cx);
 9463    }
 9464
 9465    fn go_to_hunk_before_position(
 9466        &mut self,
 9467        snapshot: &EditorSnapshot,
 9468        position: Point,
 9469        cx: &mut ViewContext<Editor>,
 9470    ) -> Option<MultiBufferDiffHunk> {
 9471        for (ix, position) in [position, snapshot.buffer_snapshot.max_point()]
 9472            .into_iter()
 9473            .enumerate()
 9474        {
 9475            if let Some(hunk) = self.go_to_next_hunk_in_direction(
 9476                snapshot,
 9477                position,
 9478                ix > 0,
 9479                snapshot
 9480                    .diff_map
 9481                    .diff_hunks_in_range_rev(Point::zero()..position, &snapshot.buffer_snapshot),
 9482                cx,
 9483            ) {
 9484                return Some(hunk);
 9485            }
 9486        }
 9487        None
 9488    }
 9489
 9490    fn go_to_next_hunk_in_direction(
 9491        &mut self,
 9492        snapshot: &DisplaySnapshot,
 9493        initial_point: Point,
 9494        is_wrapped: bool,
 9495        hunks: impl Iterator<Item = MultiBufferDiffHunk>,
 9496        cx: &mut ViewContext<Editor>,
 9497    ) -> Option<MultiBufferDiffHunk> {
 9498        let display_point = initial_point.to_display_point(snapshot);
 9499        let mut hunks = hunks
 9500            .map(|hunk| (diff_hunk_to_display(&hunk, snapshot), hunk))
 9501            .filter(|(display_hunk, _)| {
 9502                is_wrapped || !display_hunk.contains_display_row(display_point.row())
 9503            })
 9504            .dedup();
 9505
 9506        if let Some((display_hunk, hunk)) = hunks.next() {
 9507            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 9508                let row = display_hunk.start_display_row();
 9509                let point = DisplayPoint::new(row, 0);
 9510                s.select_display_ranges([point..point]);
 9511            });
 9512
 9513            Some(hunk)
 9514        } else {
 9515            None
 9516        }
 9517    }
 9518
 9519    pub fn go_to_definition(
 9520        &mut self,
 9521        _: &GoToDefinition,
 9522        cx: &mut ViewContext<Self>,
 9523    ) -> Task<Result<Navigated>> {
 9524        let definition = self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, false, cx);
 9525        cx.spawn(|editor, mut cx| async move {
 9526            if definition.await? == Navigated::Yes {
 9527                return Ok(Navigated::Yes);
 9528            }
 9529            match editor.update(&mut cx, |editor, cx| {
 9530                editor.find_all_references(&FindAllReferences, cx)
 9531            })? {
 9532                Some(references) => references.await,
 9533                None => Ok(Navigated::No),
 9534            }
 9535        })
 9536    }
 9537
 9538    pub fn go_to_declaration(
 9539        &mut self,
 9540        _: &GoToDeclaration,
 9541        cx: &mut ViewContext<Self>,
 9542    ) -> Task<Result<Navigated>> {
 9543        self.go_to_definition_of_kind(GotoDefinitionKind::Declaration, false, cx)
 9544    }
 9545
 9546    pub fn go_to_declaration_split(
 9547        &mut self,
 9548        _: &GoToDeclaration,
 9549        cx: &mut ViewContext<Self>,
 9550    ) -> Task<Result<Navigated>> {
 9551        self.go_to_definition_of_kind(GotoDefinitionKind::Declaration, true, cx)
 9552    }
 9553
 9554    pub fn go_to_implementation(
 9555        &mut self,
 9556        _: &GoToImplementation,
 9557        cx: &mut ViewContext<Self>,
 9558    ) -> Task<Result<Navigated>> {
 9559        self.go_to_definition_of_kind(GotoDefinitionKind::Implementation, false, cx)
 9560    }
 9561
 9562    pub fn go_to_implementation_split(
 9563        &mut self,
 9564        _: &GoToImplementationSplit,
 9565        cx: &mut ViewContext<Self>,
 9566    ) -> Task<Result<Navigated>> {
 9567        self.go_to_definition_of_kind(GotoDefinitionKind::Implementation, true, cx)
 9568    }
 9569
 9570    pub fn go_to_type_definition(
 9571        &mut self,
 9572        _: &GoToTypeDefinition,
 9573        cx: &mut ViewContext<Self>,
 9574    ) -> Task<Result<Navigated>> {
 9575        self.go_to_definition_of_kind(GotoDefinitionKind::Type, false, cx)
 9576    }
 9577
 9578    pub fn go_to_definition_split(
 9579        &mut self,
 9580        _: &GoToDefinitionSplit,
 9581        cx: &mut ViewContext<Self>,
 9582    ) -> Task<Result<Navigated>> {
 9583        self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, true, cx)
 9584    }
 9585
 9586    pub fn go_to_type_definition_split(
 9587        &mut self,
 9588        _: &GoToTypeDefinitionSplit,
 9589        cx: &mut ViewContext<Self>,
 9590    ) -> Task<Result<Navigated>> {
 9591        self.go_to_definition_of_kind(GotoDefinitionKind::Type, true, cx)
 9592    }
 9593
 9594    fn go_to_definition_of_kind(
 9595        &mut self,
 9596        kind: GotoDefinitionKind,
 9597        split: bool,
 9598        cx: &mut ViewContext<Self>,
 9599    ) -> Task<Result<Navigated>> {
 9600        let Some(provider) = self.semantics_provider.clone() else {
 9601            return Task::ready(Ok(Navigated::No));
 9602        };
 9603        let head = self.selections.newest::<usize>(cx).head();
 9604        let buffer = self.buffer.read(cx);
 9605        let (buffer, head) = if let Some(text_anchor) = buffer.text_anchor_for_position(head, cx) {
 9606            text_anchor
 9607        } else {
 9608            return Task::ready(Ok(Navigated::No));
 9609        };
 9610
 9611        let Some(definitions) = provider.definitions(&buffer, head, kind, cx) else {
 9612            return Task::ready(Ok(Navigated::No));
 9613        };
 9614
 9615        cx.spawn(|editor, mut cx| async move {
 9616            let definitions = definitions.await?;
 9617            let navigated = editor
 9618                .update(&mut cx, |editor, cx| {
 9619                    editor.navigate_to_hover_links(
 9620                        Some(kind),
 9621                        definitions
 9622                            .into_iter()
 9623                            .filter(|location| {
 9624                                hover_links::exclude_link_to_position(&buffer, &head, location, cx)
 9625                            })
 9626                            .map(HoverLink::Text)
 9627                            .collect::<Vec<_>>(),
 9628                        split,
 9629                        cx,
 9630                    )
 9631                })?
 9632                .await?;
 9633            anyhow::Ok(navigated)
 9634        })
 9635    }
 9636
 9637    pub fn open_url(&mut self, _: &OpenUrl, cx: &mut ViewContext<Self>) {
 9638        let selection = self.selections.newest_anchor();
 9639        let head = selection.head();
 9640        let tail = selection.tail();
 9641
 9642        let Some((buffer, start_position)) =
 9643            self.buffer.read(cx).text_anchor_for_position(head, cx)
 9644        else {
 9645            return;
 9646        };
 9647
 9648        let end_position = if head != tail {
 9649            let Some((_, pos)) = self.buffer.read(cx).text_anchor_for_position(tail, cx) else {
 9650                return;
 9651            };
 9652            Some(pos)
 9653        } else {
 9654            None
 9655        };
 9656
 9657        let url_finder = cx.spawn(|editor, mut cx| async move {
 9658            let url = if let Some(end_pos) = end_position {
 9659                find_url_from_range(&buffer, start_position..end_pos, cx.clone())
 9660            } else {
 9661                find_url(&buffer, start_position, cx.clone()).map(|(_, url)| url)
 9662            };
 9663
 9664            if let Some(url) = url {
 9665                editor.update(&mut cx, |_, cx| {
 9666                    cx.open_url(&url);
 9667                })
 9668            } else {
 9669                Ok(())
 9670            }
 9671        });
 9672
 9673        url_finder.detach();
 9674    }
 9675
 9676    pub fn open_selected_filename(&mut self, _: &OpenSelectedFilename, cx: &mut ViewContext<Self>) {
 9677        let Some(workspace) = self.workspace() else {
 9678            return;
 9679        };
 9680
 9681        let position = self.selections.newest_anchor().head();
 9682
 9683        let Some((buffer, buffer_position)) =
 9684            self.buffer.read(cx).text_anchor_for_position(position, cx)
 9685        else {
 9686            return;
 9687        };
 9688
 9689        let project = self.project.clone();
 9690
 9691        cx.spawn(|_, mut cx| async move {
 9692            let result = find_file(&buffer, project, buffer_position, &mut cx).await;
 9693
 9694            if let Some((_, path)) = result {
 9695                workspace
 9696                    .update(&mut cx, |workspace, cx| {
 9697                        workspace.open_resolved_path(path, cx)
 9698                    })?
 9699                    .await?;
 9700            }
 9701            anyhow::Ok(())
 9702        })
 9703        .detach();
 9704    }
 9705
 9706    pub(crate) fn navigate_to_hover_links(
 9707        &mut self,
 9708        kind: Option<GotoDefinitionKind>,
 9709        mut definitions: Vec<HoverLink>,
 9710        split: bool,
 9711        cx: &mut ViewContext<Editor>,
 9712    ) -> Task<Result<Navigated>> {
 9713        // If there is one definition, just open it directly
 9714        if definitions.len() == 1 {
 9715            let definition = definitions.pop().unwrap();
 9716
 9717            enum TargetTaskResult {
 9718                Location(Option<Location>),
 9719                AlreadyNavigated,
 9720            }
 9721
 9722            let target_task = match definition {
 9723                HoverLink::Text(link) => {
 9724                    Task::ready(anyhow::Ok(TargetTaskResult::Location(Some(link.target))))
 9725                }
 9726                HoverLink::InlayHint(lsp_location, server_id) => {
 9727                    let computation = self.compute_target_location(lsp_location, server_id, cx);
 9728                    cx.background_executor().spawn(async move {
 9729                        let location = computation.await?;
 9730                        Ok(TargetTaskResult::Location(location))
 9731                    })
 9732                }
 9733                HoverLink::Url(url) => {
 9734                    cx.open_url(&url);
 9735                    Task::ready(Ok(TargetTaskResult::AlreadyNavigated))
 9736                }
 9737                HoverLink::File(path) => {
 9738                    if let Some(workspace) = self.workspace() {
 9739                        cx.spawn(|_, mut cx| async move {
 9740                            workspace
 9741                                .update(&mut cx, |workspace, cx| {
 9742                                    workspace.open_resolved_path(path, cx)
 9743                                })?
 9744                                .await
 9745                                .map(|_| TargetTaskResult::AlreadyNavigated)
 9746                        })
 9747                    } else {
 9748                        Task::ready(Ok(TargetTaskResult::Location(None)))
 9749                    }
 9750                }
 9751            };
 9752            cx.spawn(|editor, mut cx| async move {
 9753                let target = match target_task.await.context("target resolution task")? {
 9754                    TargetTaskResult::AlreadyNavigated => return Ok(Navigated::Yes),
 9755                    TargetTaskResult::Location(None) => return Ok(Navigated::No),
 9756                    TargetTaskResult::Location(Some(target)) => target,
 9757                };
 9758
 9759                editor.update(&mut cx, |editor, cx| {
 9760                    let Some(workspace) = editor.workspace() else {
 9761                        return Navigated::No;
 9762                    };
 9763                    let pane = workspace.read(cx).active_pane().clone();
 9764
 9765                    let range = target.range.to_offset(target.buffer.read(cx));
 9766                    let range = editor.range_for_match(&range);
 9767
 9768                    if Some(&target.buffer) == editor.buffer.read(cx).as_singleton().as_ref() {
 9769                        let buffer = target.buffer.read(cx);
 9770                        let range = check_multiline_range(buffer, range);
 9771                        editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
 9772                            s.select_ranges([range]);
 9773                        });
 9774                    } else {
 9775                        cx.window_context().defer(move |cx| {
 9776                            let target_editor: View<Self> =
 9777                                workspace.update(cx, |workspace, cx| {
 9778                                    let pane = if split {
 9779                                        workspace.adjacent_pane(cx)
 9780                                    } else {
 9781                                        workspace.active_pane().clone()
 9782                                    };
 9783
 9784                                    workspace.open_project_item(
 9785                                        pane,
 9786                                        target.buffer.clone(),
 9787                                        true,
 9788                                        true,
 9789                                        cx,
 9790                                    )
 9791                                });
 9792                            target_editor.update(cx, |target_editor, cx| {
 9793                                // When selecting a definition in a different buffer, disable the nav history
 9794                                // to avoid creating a history entry at the previous cursor location.
 9795                                pane.update(cx, |pane, _| pane.disable_history());
 9796                                let buffer = target.buffer.read(cx);
 9797                                let range = check_multiline_range(buffer, range);
 9798                                target_editor.change_selections(
 9799                                    Some(Autoscroll::focused()),
 9800                                    cx,
 9801                                    |s| {
 9802                                        s.select_ranges([range]);
 9803                                    },
 9804                                );
 9805                                pane.update(cx, |pane, _| pane.enable_history());
 9806                            });
 9807                        });
 9808                    }
 9809                    Navigated::Yes
 9810                })
 9811            })
 9812        } else if !definitions.is_empty() {
 9813            cx.spawn(|editor, mut cx| async move {
 9814                let (title, location_tasks, workspace) = editor
 9815                    .update(&mut cx, |editor, cx| {
 9816                        let tab_kind = match kind {
 9817                            Some(GotoDefinitionKind::Implementation) => "Implementations",
 9818                            _ => "Definitions",
 9819                        };
 9820                        let title = definitions
 9821                            .iter()
 9822                            .find_map(|definition| match definition {
 9823                                HoverLink::Text(link) => link.origin.as_ref().map(|origin| {
 9824                                    let buffer = origin.buffer.read(cx);
 9825                                    format!(
 9826                                        "{} for {}",
 9827                                        tab_kind,
 9828                                        buffer
 9829                                            .text_for_range(origin.range.clone())
 9830                                            .collect::<String>()
 9831                                    )
 9832                                }),
 9833                                HoverLink::InlayHint(_, _) => None,
 9834                                HoverLink::Url(_) => None,
 9835                                HoverLink::File(_) => None,
 9836                            })
 9837                            .unwrap_or(tab_kind.to_string());
 9838                        let location_tasks = definitions
 9839                            .into_iter()
 9840                            .map(|definition| match definition {
 9841                                HoverLink::Text(link) => Task::ready(Ok(Some(link.target))),
 9842                                HoverLink::InlayHint(lsp_location, server_id) => {
 9843                                    editor.compute_target_location(lsp_location, server_id, cx)
 9844                                }
 9845                                HoverLink::Url(_) => Task::ready(Ok(None)),
 9846                                HoverLink::File(_) => Task::ready(Ok(None)),
 9847                            })
 9848                            .collect::<Vec<_>>();
 9849                        (title, location_tasks, editor.workspace().clone())
 9850                    })
 9851                    .context("location tasks preparation")?;
 9852
 9853                let locations = future::join_all(location_tasks)
 9854                    .await
 9855                    .into_iter()
 9856                    .filter_map(|location| location.transpose())
 9857                    .collect::<Result<_>>()
 9858                    .context("location tasks")?;
 9859
 9860                let Some(workspace) = workspace else {
 9861                    return Ok(Navigated::No);
 9862                };
 9863                let opened = workspace
 9864                    .update(&mut cx, |workspace, cx| {
 9865                        Self::open_locations_in_multibuffer(workspace, locations, title, split, cx)
 9866                    })
 9867                    .ok();
 9868
 9869                anyhow::Ok(Navigated::from_bool(opened.is_some()))
 9870            })
 9871        } else {
 9872            Task::ready(Ok(Navigated::No))
 9873        }
 9874    }
 9875
 9876    fn compute_target_location(
 9877        &self,
 9878        lsp_location: lsp::Location,
 9879        server_id: LanguageServerId,
 9880        cx: &mut ViewContext<Self>,
 9881    ) -> Task<anyhow::Result<Option<Location>>> {
 9882        let Some(project) = self.project.clone() else {
 9883            return Task::ready(Ok(None));
 9884        };
 9885
 9886        cx.spawn(move |editor, mut cx| async move {
 9887            let location_task = editor.update(&mut cx, |_, cx| {
 9888                project.update(cx, |project, cx| {
 9889                    let language_server_name = project
 9890                        .language_server_statuses(cx)
 9891                        .find(|(id, _)| server_id == *id)
 9892                        .map(|(_, status)| LanguageServerName::from(status.name.as_str()));
 9893                    language_server_name.map(|language_server_name| {
 9894                        project.open_local_buffer_via_lsp(
 9895                            lsp_location.uri.clone(),
 9896                            server_id,
 9897                            language_server_name,
 9898                            cx,
 9899                        )
 9900                    })
 9901                })
 9902            })?;
 9903            let location = match location_task {
 9904                Some(task) => Some({
 9905                    let target_buffer_handle = task.await.context("open local buffer")?;
 9906                    let range = target_buffer_handle.update(&mut cx, |target_buffer, _| {
 9907                        let target_start = target_buffer
 9908                            .clip_point_utf16(point_from_lsp(lsp_location.range.start), Bias::Left);
 9909                        let target_end = target_buffer
 9910                            .clip_point_utf16(point_from_lsp(lsp_location.range.end), Bias::Left);
 9911                        target_buffer.anchor_after(target_start)
 9912                            ..target_buffer.anchor_before(target_end)
 9913                    })?;
 9914                    Location {
 9915                        buffer: target_buffer_handle,
 9916                        range,
 9917                    }
 9918                }),
 9919                None => None,
 9920            };
 9921            Ok(location)
 9922        })
 9923    }
 9924
 9925    pub fn find_all_references(
 9926        &mut self,
 9927        _: &FindAllReferences,
 9928        cx: &mut ViewContext<Self>,
 9929    ) -> Option<Task<Result<Navigated>>> {
 9930        let selection = self.selections.newest::<usize>(cx);
 9931        let multi_buffer = self.buffer.read(cx);
 9932        let head = selection.head();
 9933
 9934        let multi_buffer_snapshot = multi_buffer.snapshot(cx);
 9935        let head_anchor = multi_buffer_snapshot.anchor_at(
 9936            head,
 9937            if head < selection.tail() {
 9938                Bias::Right
 9939            } else {
 9940                Bias::Left
 9941            },
 9942        );
 9943
 9944        match self
 9945            .find_all_references_task_sources
 9946            .binary_search_by(|anchor| anchor.cmp(&head_anchor, &multi_buffer_snapshot))
 9947        {
 9948            Ok(_) => {
 9949                log::info!(
 9950                    "Ignoring repeated FindAllReferences invocation with the position of already running task"
 9951                );
 9952                return None;
 9953            }
 9954            Err(i) => {
 9955                self.find_all_references_task_sources.insert(i, head_anchor);
 9956            }
 9957        }
 9958
 9959        let (buffer, head) = multi_buffer.text_anchor_for_position(head, cx)?;
 9960        let workspace = self.workspace()?;
 9961        let project = workspace.read(cx).project().clone();
 9962        let references = project.update(cx, |project, cx| project.references(&buffer, head, cx));
 9963        Some(cx.spawn(|editor, mut cx| async move {
 9964            let _cleanup = defer({
 9965                let mut cx = cx.clone();
 9966                move || {
 9967                    let _ = editor.update(&mut cx, |editor, _| {
 9968                        if let Ok(i) =
 9969                            editor
 9970                                .find_all_references_task_sources
 9971                                .binary_search_by(|anchor| {
 9972                                    anchor.cmp(&head_anchor, &multi_buffer_snapshot)
 9973                                })
 9974                        {
 9975                            editor.find_all_references_task_sources.remove(i);
 9976                        }
 9977                    });
 9978                }
 9979            });
 9980
 9981            let locations = references.await?;
 9982            if locations.is_empty() {
 9983                return anyhow::Ok(Navigated::No);
 9984            }
 9985
 9986            workspace.update(&mut cx, |workspace, cx| {
 9987                let title = locations
 9988                    .first()
 9989                    .as_ref()
 9990                    .map(|location| {
 9991                        let buffer = location.buffer.read(cx);
 9992                        format!(
 9993                            "References to `{}`",
 9994                            buffer
 9995                                .text_for_range(location.range.clone())
 9996                                .collect::<String>()
 9997                        )
 9998                    })
 9999                    .unwrap();
10000                Self::open_locations_in_multibuffer(workspace, locations, title, false, cx);
10001                Navigated::Yes
10002            })
10003        }))
10004    }
10005
10006    /// Opens a multibuffer with the given project locations in it
10007    pub fn open_locations_in_multibuffer(
10008        workspace: &mut Workspace,
10009        mut locations: Vec<Location>,
10010        title: String,
10011        split: bool,
10012        cx: &mut ViewContext<Workspace>,
10013    ) {
10014        // If there are multiple definitions, open them in a multibuffer
10015        locations.sort_by_key(|location| location.buffer.read(cx).remote_id());
10016        let mut locations = locations.into_iter().peekable();
10017        let mut ranges_to_highlight = Vec::new();
10018        let capability = workspace.project().read(cx).capability();
10019
10020        let excerpt_buffer = cx.new_model(|cx| {
10021            let mut multibuffer = MultiBuffer::new(capability);
10022            while let Some(location) = locations.next() {
10023                let buffer = location.buffer.read(cx);
10024                let mut ranges_for_buffer = Vec::new();
10025                let range = location.range.to_offset(buffer);
10026                ranges_for_buffer.push(range.clone());
10027
10028                while let Some(next_location) = locations.peek() {
10029                    if next_location.buffer == location.buffer {
10030                        ranges_for_buffer.push(next_location.range.to_offset(buffer));
10031                        locations.next();
10032                    } else {
10033                        break;
10034                    }
10035                }
10036
10037                ranges_for_buffer.sort_by_key(|range| (range.start, Reverse(range.end)));
10038                ranges_to_highlight.extend(multibuffer.push_excerpts_with_context_lines(
10039                    location.buffer.clone(),
10040                    ranges_for_buffer,
10041                    DEFAULT_MULTIBUFFER_CONTEXT,
10042                    cx,
10043                ))
10044            }
10045
10046            multibuffer.with_title(title)
10047        });
10048
10049        let editor = cx.new_view(|cx| {
10050            Editor::for_multibuffer(excerpt_buffer, Some(workspace.project().clone()), true, cx)
10051        });
10052        editor.update(cx, |editor, cx| {
10053            if let Some(first_range) = ranges_to_highlight.first() {
10054                editor.change_selections(None, cx, |selections| {
10055                    selections.clear_disjoint();
10056                    selections.select_anchor_ranges(std::iter::once(first_range.clone()));
10057                });
10058            }
10059            editor.highlight_background::<Self>(
10060                &ranges_to_highlight,
10061                |theme| theme.editor_highlighted_line_background,
10062                cx,
10063            );
10064            editor.register_buffers_with_language_servers(cx);
10065        });
10066
10067        let item = Box::new(editor);
10068        let item_id = item.item_id();
10069
10070        if split {
10071            workspace.split_item(SplitDirection::Right, item.clone(), cx);
10072        } else {
10073            let destination_index = workspace.active_pane().update(cx, |pane, cx| {
10074                if PreviewTabsSettings::get_global(cx).enable_preview_from_code_navigation {
10075                    pane.close_current_preview_item(cx)
10076                } else {
10077                    None
10078                }
10079            });
10080            workspace.add_item_to_active_pane(item.clone(), destination_index, true, cx);
10081        }
10082        workspace.active_pane().update(cx, |pane, cx| {
10083            pane.set_preview_item_id(Some(item_id), cx);
10084        });
10085    }
10086
10087    pub fn rename(&mut self, _: &Rename, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
10088        use language::ToOffset as _;
10089
10090        let provider = self.semantics_provider.clone()?;
10091        let selection = self.selections.newest_anchor().clone();
10092        let (cursor_buffer, cursor_buffer_position) = self
10093            .buffer
10094            .read(cx)
10095            .text_anchor_for_position(selection.head(), cx)?;
10096        let (tail_buffer, cursor_buffer_position_end) = self
10097            .buffer
10098            .read(cx)
10099            .text_anchor_for_position(selection.tail(), cx)?;
10100        if tail_buffer != cursor_buffer {
10101            return None;
10102        }
10103
10104        let snapshot = cursor_buffer.read(cx).snapshot();
10105        let cursor_buffer_offset = cursor_buffer_position.to_offset(&snapshot);
10106        let cursor_buffer_offset_end = cursor_buffer_position_end.to_offset(&snapshot);
10107        let prepare_rename = provider
10108            .range_for_rename(&cursor_buffer, cursor_buffer_position, cx)
10109            .unwrap_or_else(|| Task::ready(Ok(None)));
10110        drop(snapshot);
10111
10112        Some(cx.spawn(|this, mut cx| async move {
10113            let rename_range = if let Some(range) = prepare_rename.await? {
10114                Some(range)
10115            } else {
10116                this.update(&mut cx, |this, cx| {
10117                    let buffer = this.buffer.read(cx).snapshot(cx);
10118                    let mut buffer_highlights = this
10119                        .document_highlights_for_position(selection.head(), &buffer)
10120                        .filter(|highlight| {
10121                            highlight.start.excerpt_id == selection.head().excerpt_id
10122                                && highlight.end.excerpt_id == selection.head().excerpt_id
10123                        });
10124                    buffer_highlights
10125                        .next()
10126                        .map(|highlight| highlight.start.text_anchor..highlight.end.text_anchor)
10127                })?
10128            };
10129            if let Some(rename_range) = rename_range {
10130                this.update(&mut cx, |this, cx| {
10131                    let snapshot = cursor_buffer.read(cx).snapshot();
10132                    let rename_buffer_range = rename_range.to_offset(&snapshot);
10133                    let cursor_offset_in_rename_range =
10134                        cursor_buffer_offset.saturating_sub(rename_buffer_range.start);
10135                    let cursor_offset_in_rename_range_end =
10136                        cursor_buffer_offset_end.saturating_sub(rename_buffer_range.start);
10137
10138                    this.take_rename(false, cx);
10139                    let buffer = this.buffer.read(cx).read(cx);
10140                    let cursor_offset = selection.head().to_offset(&buffer);
10141                    let rename_start = cursor_offset.saturating_sub(cursor_offset_in_rename_range);
10142                    let rename_end = rename_start + rename_buffer_range.len();
10143                    let range = buffer.anchor_before(rename_start)..buffer.anchor_after(rename_end);
10144                    let mut old_highlight_id = None;
10145                    let old_name: Arc<str> = buffer
10146                        .chunks(rename_start..rename_end, true)
10147                        .map(|chunk| {
10148                            if old_highlight_id.is_none() {
10149                                old_highlight_id = chunk.syntax_highlight_id;
10150                            }
10151                            chunk.text
10152                        })
10153                        .collect::<String>()
10154                        .into();
10155
10156                    drop(buffer);
10157
10158                    // Position the selection in the rename editor so that it matches the current selection.
10159                    this.show_local_selections = false;
10160                    let rename_editor = cx.new_view(|cx| {
10161                        let mut editor = Editor::single_line(cx);
10162                        editor.buffer.update(cx, |buffer, cx| {
10163                            buffer.edit([(0..0, old_name.clone())], None, cx)
10164                        });
10165                        let rename_selection_range = match cursor_offset_in_rename_range
10166                            .cmp(&cursor_offset_in_rename_range_end)
10167                        {
10168                            Ordering::Equal => {
10169                                editor.select_all(&SelectAll, cx);
10170                                return editor;
10171                            }
10172                            Ordering::Less => {
10173                                cursor_offset_in_rename_range..cursor_offset_in_rename_range_end
10174                            }
10175                            Ordering::Greater => {
10176                                cursor_offset_in_rename_range_end..cursor_offset_in_rename_range
10177                            }
10178                        };
10179                        if rename_selection_range.end > old_name.len() {
10180                            editor.select_all(&SelectAll, cx);
10181                        } else {
10182                            editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
10183                                s.select_ranges([rename_selection_range]);
10184                            });
10185                        }
10186                        editor
10187                    });
10188                    cx.subscribe(&rename_editor, |_, _, e: &EditorEvent, cx| {
10189                        if e == &EditorEvent::Focused {
10190                            cx.emit(EditorEvent::FocusedIn)
10191                        }
10192                    })
10193                    .detach();
10194
10195                    let write_highlights =
10196                        this.clear_background_highlights::<DocumentHighlightWrite>(cx);
10197                    let read_highlights =
10198                        this.clear_background_highlights::<DocumentHighlightRead>(cx);
10199                    let ranges = write_highlights
10200                        .iter()
10201                        .flat_map(|(_, ranges)| ranges.iter())
10202                        .chain(read_highlights.iter().flat_map(|(_, ranges)| ranges.iter()))
10203                        .cloned()
10204                        .collect();
10205
10206                    this.highlight_text::<Rename>(
10207                        ranges,
10208                        HighlightStyle {
10209                            fade_out: Some(0.6),
10210                            ..Default::default()
10211                        },
10212                        cx,
10213                    );
10214                    let rename_focus_handle = rename_editor.focus_handle(cx);
10215                    cx.focus(&rename_focus_handle);
10216                    let block_id = this.insert_blocks(
10217                        [BlockProperties {
10218                            style: BlockStyle::Flex,
10219                            placement: BlockPlacement::Below(range.start),
10220                            height: 1,
10221                            render: Arc::new({
10222                                let rename_editor = rename_editor.clone();
10223                                move |cx: &mut BlockContext| {
10224                                    let mut text_style = cx.editor_style.text.clone();
10225                                    if let Some(highlight_style) = old_highlight_id
10226                                        .and_then(|h| h.style(&cx.editor_style.syntax))
10227                                    {
10228                                        text_style = text_style.highlight(highlight_style);
10229                                    }
10230                                    div()
10231                                        .block_mouse_down()
10232                                        .pl(cx.anchor_x)
10233                                        .child(EditorElement::new(
10234                                            &rename_editor,
10235                                            EditorStyle {
10236                                                background: cx.theme().system().transparent,
10237                                                local_player: cx.editor_style.local_player,
10238                                                text: text_style,
10239                                                scrollbar_width: cx.editor_style.scrollbar_width,
10240                                                syntax: cx.editor_style.syntax.clone(),
10241                                                status: cx.editor_style.status.clone(),
10242                                                inlay_hints_style: HighlightStyle {
10243                                                    font_weight: Some(FontWeight::BOLD),
10244                                                    ..make_inlay_hints_style(cx)
10245                                                },
10246                                                inline_completion_styles: make_suggestion_styles(
10247                                                    cx,
10248                                                ),
10249                                                ..EditorStyle::default()
10250                                            },
10251                                        ))
10252                                        .into_any_element()
10253                                }
10254                            }),
10255                            priority: 0,
10256                        }],
10257                        Some(Autoscroll::fit()),
10258                        cx,
10259                    )[0];
10260                    this.pending_rename = Some(RenameState {
10261                        range,
10262                        old_name,
10263                        editor: rename_editor,
10264                        block_id,
10265                    });
10266                })?;
10267            }
10268
10269            Ok(())
10270        }))
10271    }
10272
10273    pub fn confirm_rename(
10274        &mut self,
10275        _: &ConfirmRename,
10276        cx: &mut ViewContext<Self>,
10277    ) -> Option<Task<Result<()>>> {
10278        let rename = self.take_rename(false, cx)?;
10279        let workspace = self.workspace()?.downgrade();
10280        let (buffer, start) = self
10281            .buffer
10282            .read(cx)
10283            .text_anchor_for_position(rename.range.start, cx)?;
10284        let (end_buffer, _) = self
10285            .buffer
10286            .read(cx)
10287            .text_anchor_for_position(rename.range.end, cx)?;
10288        if buffer != end_buffer {
10289            return None;
10290        }
10291
10292        let old_name = rename.old_name;
10293        let new_name = rename.editor.read(cx).text(cx);
10294
10295        let rename = self.semantics_provider.as_ref()?.perform_rename(
10296            &buffer,
10297            start,
10298            new_name.clone(),
10299            cx,
10300        )?;
10301
10302        Some(cx.spawn(|editor, mut cx| async move {
10303            let project_transaction = rename.await?;
10304            Self::open_project_transaction(
10305                &editor,
10306                workspace,
10307                project_transaction,
10308                format!("Rename: {}{}", old_name, new_name),
10309                cx.clone(),
10310            )
10311            .await?;
10312
10313            editor.update(&mut cx, |editor, cx| {
10314                editor.refresh_document_highlights(cx);
10315            })?;
10316            Ok(())
10317        }))
10318    }
10319
10320    fn take_rename(
10321        &mut self,
10322        moving_cursor: bool,
10323        cx: &mut ViewContext<Self>,
10324    ) -> Option<RenameState> {
10325        let rename = self.pending_rename.take()?;
10326        if rename.editor.focus_handle(cx).is_focused(cx) {
10327            cx.focus(&self.focus_handle);
10328        }
10329
10330        self.remove_blocks(
10331            [rename.block_id].into_iter().collect(),
10332            Some(Autoscroll::fit()),
10333            cx,
10334        );
10335        self.clear_highlights::<Rename>(cx);
10336        self.show_local_selections = true;
10337
10338        if moving_cursor {
10339            let cursor_in_rename_editor = rename.editor.update(cx, |editor, cx| {
10340                editor.selections.newest::<usize>(cx).head()
10341            });
10342
10343            // Update the selection to match the position of the selection inside
10344            // the rename editor.
10345            let snapshot = self.buffer.read(cx).read(cx);
10346            let rename_range = rename.range.to_offset(&snapshot);
10347            let cursor_in_editor = snapshot
10348                .clip_offset(rename_range.start + cursor_in_rename_editor, Bias::Left)
10349                .min(rename_range.end);
10350            drop(snapshot);
10351
10352            self.change_selections(None, cx, |s| {
10353                s.select_ranges(vec![cursor_in_editor..cursor_in_editor])
10354            });
10355        } else {
10356            self.refresh_document_highlights(cx);
10357        }
10358
10359        Some(rename)
10360    }
10361
10362    pub fn pending_rename(&self) -> Option<&RenameState> {
10363        self.pending_rename.as_ref()
10364    }
10365
10366    fn format(&mut self, _: &Format, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
10367        let project = match &self.project {
10368            Some(project) => project.clone(),
10369            None => return None,
10370        };
10371
10372        Some(self.perform_format(project, FormatTrigger::Manual, FormatTarget::Buffers, cx))
10373    }
10374
10375    fn format_selections(
10376        &mut self,
10377        _: &FormatSelections,
10378        cx: &mut ViewContext<Self>,
10379    ) -> Option<Task<Result<()>>> {
10380        let project = match &self.project {
10381            Some(project) => project.clone(),
10382            None => return None,
10383        };
10384
10385        let ranges = self
10386            .selections
10387            .all_adjusted(cx)
10388            .into_iter()
10389            .map(|selection| selection.range())
10390            .collect_vec();
10391
10392        Some(self.perform_format(
10393            project,
10394            FormatTrigger::Manual,
10395            FormatTarget::Ranges(ranges),
10396            cx,
10397        ))
10398    }
10399
10400    fn perform_format(
10401        &mut self,
10402        project: Model<Project>,
10403        trigger: FormatTrigger,
10404        target: FormatTarget,
10405        cx: &mut ViewContext<Self>,
10406    ) -> Task<Result<()>> {
10407        let buffer = self.buffer.clone();
10408        let (buffers, target) = match target {
10409            FormatTarget::Buffers => {
10410                let mut buffers = buffer.read(cx).all_buffers();
10411                if trigger == FormatTrigger::Save {
10412                    buffers.retain(|buffer| buffer.read(cx).is_dirty());
10413                }
10414                (buffers, LspFormatTarget::Buffers)
10415            }
10416            FormatTarget::Ranges(selection_ranges) => {
10417                let multi_buffer = buffer.read(cx);
10418                let snapshot = multi_buffer.read(cx);
10419                let mut buffers = HashSet::default();
10420                let mut buffer_id_to_ranges: BTreeMap<BufferId, Vec<Range<text::Anchor>>> =
10421                    BTreeMap::new();
10422                for selection_range in selection_ranges {
10423                    for (excerpt, buffer_range) in snapshot.range_to_buffer_ranges(selection_range)
10424                    {
10425                        let buffer_id = excerpt.buffer_id();
10426                        let start = excerpt.buffer().anchor_before(buffer_range.start);
10427                        let end = excerpt.buffer().anchor_after(buffer_range.end);
10428                        buffers.insert(multi_buffer.buffer(buffer_id).unwrap());
10429                        buffer_id_to_ranges
10430                            .entry(buffer_id)
10431                            .and_modify(|buffer_ranges| buffer_ranges.push(start..end))
10432                            .or_insert_with(|| vec![start..end]);
10433                    }
10434                }
10435                (buffers, LspFormatTarget::Ranges(buffer_id_to_ranges))
10436            }
10437        };
10438
10439        let mut timeout = cx.background_executor().timer(FORMAT_TIMEOUT).fuse();
10440        let format = project.update(cx, |project, cx| {
10441            project.format(buffers, target, true, trigger, cx)
10442        });
10443
10444        cx.spawn(|_, mut cx| async move {
10445            let transaction = futures::select_biased! {
10446                () = timeout => {
10447                    log::warn!("timed out waiting for formatting");
10448                    None
10449                }
10450                transaction = format.log_err().fuse() => transaction,
10451            };
10452
10453            buffer
10454                .update(&mut cx, |buffer, cx| {
10455                    if let Some(transaction) = transaction {
10456                        if !buffer.is_singleton() {
10457                            buffer.push_transaction(&transaction.0, cx);
10458                        }
10459                    }
10460
10461                    cx.notify();
10462                })
10463                .ok();
10464
10465            Ok(())
10466        })
10467    }
10468
10469    fn restart_language_server(&mut self, _: &RestartLanguageServer, cx: &mut ViewContext<Self>) {
10470        if let Some(project) = self.project.clone() {
10471            self.buffer.update(cx, |multi_buffer, cx| {
10472                project.update(cx, |project, cx| {
10473                    project.restart_language_servers_for_buffers(multi_buffer.all_buffers(), cx);
10474                });
10475            })
10476        }
10477    }
10478
10479    fn cancel_language_server_work(
10480        &mut self,
10481        _: &actions::CancelLanguageServerWork,
10482        cx: &mut ViewContext<Self>,
10483    ) {
10484        if let Some(project) = self.project.clone() {
10485            self.buffer.update(cx, |multi_buffer, cx| {
10486                project.update(cx, |project, cx| {
10487                    project.cancel_language_server_work_for_buffers(multi_buffer.all_buffers(), cx);
10488                });
10489            })
10490        }
10491    }
10492
10493    fn show_character_palette(&mut self, _: &ShowCharacterPalette, cx: &mut ViewContext<Self>) {
10494        cx.show_character_palette();
10495    }
10496
10497    fn refresh_active_diagnostics(&mut self, cx: &mut ViewContext<Editor>) {
10498        if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
10499            let buffer = self.buffer.read(cx).snapshot(cx);
10500            let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
10501            let is_valid = buffer
10502                .diagnostics_in_range(active_diagnostics.primary_range.clone(), false)
10503                .any(|entry| {
10504                    let range = entry.range.to_offset(&buffer);
10505                    entry.diagnostic.is_primary
10506                        && !range.is_empty()
10507                        && range.start == primary_range_start
10508                        && entry.diagnostic.message == active_diagnostics.primary_message
10509                });
10510
10511            if is_valid != active_diagnostics.is_valid {
10512                active_diagnostics.is_valid = is_valid;
10513                let mut new_styles = HashMap::default();
10514                for (block_id, diagnostic) in &active_diagnostics.blocks {
10515                    new_styles.insert(
10516                        *block_id,
10517                        diagnostic_block_renderer(diagnostic.clone(), None, true, is_valid),
10518                    );
10519                }
10520                self.display_map.update(cx, |display_map, _cx| {
10521                    display_map.replace_blocks(new_styles)
10522                });
10523            }
10524        }
10525    }
10526
10527    fn activate_diagnostics(&mut self, group_id: usize, cx: &mut ViewContext<Self>) {
10528        self.dismiss_diagnostics(cx);
10529        let snapshot = self.snapshot(cx);
10530        self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
10531            let buffer = self.buffer.read(cx).snapshot(cx);
10532
10533            let mut primary_range = None;
10534            let mut primary_message = None;
10535            let mut group_end = Point::zero();
10536            let diagnostic_group = buffer
10537                .diagnostic_group(group_id)
10538                .filter_map(|entry| {
10539                    let start = entry.range.start.to_point(&buffer);
10540                    let end = entry.range.end.to_point(&buffer);
10541                    if snapshot.is_line_folded(MultiBufferRow(start.row))
10542                        && (start.row == end.row
10543                            || snapshot.is_line_folded(MultiBufferRow(end.row)))
10544                    {
10545                        return None;
10546                    }
10547                    if end > group_end {
10548                        group_end = end;
10549                    }
10550                    if entry.diagnostic.is_primary {
10551                        primary_range = Some(entry.range.clone());
10552                        primary_message = Some(entry.diagnostic.message.clone());
10553                    }
10554                    Some(entry)
10555                })
10556                .collect::<Vec<_>>();
10557            let primary_range = primary_range?;
10558            let primary_message = primary_message?;
10559
10560            let blocks = display_map
10561                .insert_blocks(
10562                    diagnostic_group.iter().map(|entry| {
10563                        let diagnostic = entry.diagnostic.clone();
10564                        let message_height = diagnostic.message.matches('\n').count() as u32 + 1;
10565                        BlockProperties {
10566                            style: BlockStyle::Fixed,
10567                            placement: BlockPlacement::Below(
10568                                buffer.anchor_after(entry.range.start),
10569                            ),
10570                            height: message_height,
10571                            render: diagnostic_block_renderer(diagnostic, None, true, true),
10572                            priority: 0,
10573                        }
10574                    }),
10575                    cx,
10576                )
10577                .into_iter()
10578                .zip(diagnostic_group.into_iter().map(|entry| entry.diagnostic))
10579                .collect();
10580
10581            Some(ActiveDiagnosticGroup {
10582                primary_range,
10583                primary_message,
10584                group_id,
10585                blocks,
10586                is_valid: true,
10587            })
10588        });
10589    }
10590
10591    fn dismiss_diagnostics(&mut self, cx: &mut ViewContext<Self>) {
10592        if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
10593            self.display_map.update(cx, |display_map, cx| {
10594                display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx);
10595            });
10596            cx.notify();
10597        }
10598    }
10599
10600    pub fn set_selections_from_remote(
10601        &mut self,
10602        selections: Vec<Selection<Anchor>>,
10603        pending_selection: Option<Selection<Anchor>>,
10604        cx: &mut ViewContext<Self>,
10605    ) {
10606        let old_cursor_position = self.selections.newest_anchor().head();
10607        self.selections.change_with(cx, |s| {
10608            s.select_anchors(selections);
10609            if let Some(pending_selection) = pending_selection {
10610                s.set_pending(pending_selection, SelectMode::Character);
10611            } else {
10612                s.clear_pending();
10613            }
10614        });
10615        self.selections_did_change(false, &old_cursor_position, true, cx);
10616    }
10617
10618    fn push_to_selection_history(&mut self) {
10619        self.selection_history.push(SelectionHistoryEntry {
10620            selections: self.selections.disjoint_anchors(),
10621            select_next_state: self.select_next_state.clone(),
10622            select_prev_state: self.select_prev_state.clone(),
10623            add_selections_state: self.add_selections_state.clone(),
10624        });
10625    }
10626
10627    pub fn transact(
10628        &mut self,
10629        cx: &mut ViewContext<Self>,
10630        update: impl FnOnce(&mut Self, &mut ViewContext<Self>),
10631    ) -> Option<TransactionId> {
10632        self.start_transaction_at(Instant::now(), cx);
10633        update(self, cx);
10634        self.end_transaction_at(Instant::now(), cx)
10635    }
10636
10637    pub fn start_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
10638        self.end_selection(cx);
10639        if let Some(tx_id) = self
10640            .buffer
10641            .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx))
10642        {
10643            self.selection_history
10644                .insert_transaction(tx_id, self.selections.disjoint_anchors());
10645            cx.emit(EditorEvent::TransactionBegun {
10646                transaction_id: tx_id,
10647            })
10648        }
10649    }
10650
10651    pub fn end_transaction_at(
10652        &mut self,
10653        now: Instant,
10654        cx: &mut ViewContext<Self>,
10655    ) -> Option<TransactionId> {
10656        if let Some(transaction_id) = self
10657            .buffer
10658            .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
10659        {
10660            if let Some((_, end_selections)) =
10661                self.selection_history.transaction_mut(transaction_id)
10662            {
10663                *end_selections = Some(self.selections.disjoint_anchors());
10664            } else {
10665                log::error!("unexpectedly ended a transaction that wasn't started by this editor");
10666            }
10667
10668            cx.emit(EditorEvent::Edited { transaction_id });
10669            Some(transaction_id)
10670        } else {
10671            None
10672        }
10673    }
10674
10675    pub fn set_mark(&mut self, _: &actions::SetMark, cx: &mut ViewContext<Self>) {
10676        if self.selection_mark_mode {
10677            self.change_selections(None, cx, |s| {
10678                s.move_with(|_, sel| {
10679                    sel.collapse_to(sel.head(), SelectionGoal::None);
10680                });
10681            })
10682        }
10683        self.selection_mark_mode = true;
10684        cx.notify();
10685    }
10686
10687    pub fn swap_selection_ends(
10688        &mut self,
10689        _: &actions::SwapSelectionEnds,
10690        cx: &mut ViewContext<Self>,
10691    ) {
10692        self.change_selections(None, cx, |s| {
10693            s.move_with(|_, sel| {
10694                if sel.start != sel.end {
10695                    sel.reversed = !sel.reversed
10696                }
10697            });
10698        });
10699        self.request_autoscroll(Autoscroll::newest(), cx);
10700        cx.notify();
10701    }
10702
10703    pub fn toggle_fold(&mut self, _: &actions::ToggleFold, cx: &mut ViewContext<Self>) {
10704        if self.is_singleton(cx) {
10705            let selection = self.selections.newest::<Point>(cx);
10706
10707            let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
10708            let range = if selection.is_empty() {
10709                let point = selection.head().to_display_point(&display_map);
10710                let start = DisplayPoint::new(point.row(), 0).to_point(&display_map);
10711                let end = DisplayPoint::new(point.row(), display_map.line_len(point.row()))
10712                    .to_point(&display_map);
10713                start..end
10714            } else {
10715                selection.range()
10716            };
10717            if display_map.folds_in_range(range).next().is_some() {
10718                self.unfold_lines(&Default::default(), cx)
10719            } else {
10720                self.fold(&Default::default(), cx)
10721            }
10722        } else {
10723            let multi_buffer_snapshot = self.buffer.read(cx).snapshot(cx);
10724            let mut toggled_buffers = HashSet::default();
10725            for (_, buffer_snapshot, _) in
10726                multi_buffer_snapshot.excerpts_in_ranges(self.selections.disjoint_anchor_ranges())
10727            {
10728                let buffer_id = buffer_snapshot.remote_id();
10729                if toggled_buffers.insert(buffer_id) {
10730                    if self.buffer_folded(buffer_id, cx) {
10731                        self.unfold_buffer(buffer_id, cx);
10732                    } else {
10733                        self.fold_buffer(buffer_id, cx);
10734                    }
10735                }
10736            }
10737        }
10738    }
10739
10740    pub fn toggle_fold_recursive(
10741        &mut self,
10742        _: &actions::ToggleFoldRecursive,
10743        cx: &mut ViewContext<Self>,
10744    ) {
10745        let selection = self.selections.newest::<Point>(cx);
10746
10747        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
10748        let range = if selection.is_empty() {
10749            let point = selection.head().to_display_point(&display_map);
10750            let start = DisplayPoint::new(point.row(), 0).to_point(&display_map);
10751            let end = DisplayPoint::new(point.row(), display_map.line_len(point.row()))
10752                .to_point(&display_map);
10753            start..end
10754        } else {
10755            selection.range()
10756        };
10757        if display_map.folds_in_range(range).next().is_some() {
10758            self.unfold_recursive(&Default::default(), cx)
10759        } else {
10760            self.fold_recursive(&Default::default(), cx)
10761        }
10762    }
10763
10764    pub fn fold(&mut self, _: &actions::Fold, cx: &mut ViewContext<Self>) {
10765        if self.is_singleton(cx) {
10766            let mut to_fold = Vec::new();
10767            let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
10768            let selections = self.selections.all_adjusted(cx);
10769
10770            for selection in selections {
10771                let range = selection.range().sorted();
10772                let buffer_start_row = range.start.row;
10773
10774                if range.start.row != range.end.row {
10775                    let mut found = false;
10776                    let mut row = range.start.row;
10777                    while row <= range.end.row {
10778                        if let Some(crease) = display_map.crease_for_buffer_row(MultiBufferRow(row))
10779                        {
10780                            found = true;
10781                            row = crease.range().end.row + 1;
10782                            to_fold.push(crease);
10783                        } else {
10784                            row += 1
10785                        }
10786                    }
10787                    if found {
10788                        continue;
10789                    }
10790                }
10791
10792                for row in (0..=range.start.row).rev() {
10793                    if let Some(crease) = display_map.crease_for_buffer_row(MultiBufferRow(row)) {
10794                        if crease.range().end.row >= buffer_start_row {
10795                            to_fold.push(crease);
10796                            if row <= range.start.row {
10797                                break;
10798                            }
10799                        }
10800                    }
10801                }
10802            }
10803
10804            self.fold_creases(to_fold, true, cx);
10805        } else {
10806            let multi_buffer_snapshot = self.buffer.read(cx).snapshot(cx);
10807            let mut folded_buffers = HashSet::default();
10808            for (_, buffer_snapshot, _) in
10809                multi_buffer_snapshot.excerpts_in_ranges(self.selections.disjoint_anchor_ranges())
10810            {
10811                let buffer_id = buffer_snapshot.remote_id();
10812                if folded_buffers.insert(buffer_id) {
10813                    self.fold_buffer(buffer_id, cx);
10814                }
10815            }
10816        }
10817    }
10818
10819    fn fold_at_level(&mut self, fold_at: &FoldAtLevel, cx: &mut ViewContext<Self>) {
10820        if !self.buffer.read(cx).is_singleton() {
10821            return;
10822        }
10823
10824        let fold_at_level = fold_at.level;
10825        let snapshot = self.buffer.read(cx).snapshot(cx);
10826        let mut to_fold = Vec::new();
10827        let mut stack = vec![(0, snapshot.max_row().0, 1)];
10828
10829        while let Some((mut start_row, end_row, current_level)) = stack.pop() {
10830            while start_row < end_row {
10831                match self
10832                    .snapshot(cx)
10833                    .crease_for_buffer_row(MultiBufferRow(start_row))
10834                {
10835                    Some(crease) => {
10836                        let nested_start_row = crease.range().start.row + 1;
10837                        let nested_end_row = crease.range().end.row;
10838
10839                        if current_level < fold_at_level {
10840                            stack.push((nested_start_row, nested_end_row, current_level + 1));
10841                        } else if current_level == fold_at_level {
10842                            to_fold.push(crease);
10843                        }
10844
10845                        start_row = nested_end_row + 1;
10846                    }
10847                    None => start_row += 1,
10848                }
10849            }
10850        }
10851
10852        self.fold_creases(to_fold, true, cx);
10853    }
10854
10855    pub fn fold_all(&mut self, _: &actions::FoldAll, cx: &mut ViewContext<Self>) {
10856        if self.buffer.read(cx).is_singleton() {
10857            let mut fold_ranges = Vec::new();
10858            let snapshot = self.buffer.read(cx).snapshot(cx);
10859
10860            for row in 0..snapshot.max_row().0 {
10861                if let Some(foldable_range) =
10862                    self.snapshot(cx).crease_for_buffer_row(MultiBufferRow(row))
10863                {
10864                    fold_ranges.push(foldable_range);
10865                }
10866            }
10867
10868            self.fold_creases(fold_ranges, true, cx);
10869        } else {
10870            self.toggle_fold_multiple_buffers = cx.spawn(|editor, mut cx| async move {
10871                editor
10872                    .update(&mut cx, |editor, cx| {
10873                        for buffer_id in editor.buffer.read(cx).excerpt_buffer_ids() {
10874                            editor.fold_buffer(buffer_id, cx);
10875                        }
10876                    })
10877                    .ok();
10878            });
10879        }
10880    }
10881
10882    pub fn fold_function_bodies(
10883        &mut self,
10884        _: &actions::FoldFunctionBodies,
10885        cx: &mut ViewContext<Self>,
10886    ) {
10887        let snapshot = self.buffer.read(cx).snapshot(cx);
10888        let Some((_, _, buffer)) = snapshot.as_singleton() else {
10889            return;
10890        };
10891        let creases = buffer
10892            .function_body_fold_ranges(0..buffer.len())
10893            .map(|range| Crease::simple(range, self.display_map.read(cx).fold_placeholder.clone()))
10894            .collect();
10895
10896        self.fold_creases(creases, true, cx);
10897    }
10898
10899    pub fn fold_recursive(&mut self, _: &actions::FoldRecursive, cx: &mut ViewContext<Self>) {
10900        let mut to_fold = Vec::new();
10901        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
10902        let selections = self.selections.all_adjusted(cx);
10903
10904        for selection in selections {
10905            let range = selection.range().sorted();
10906            let buffer_start_row = range.start.row;
10907
10908            if range.start.row != range.end.row {
10909                let mut found = false;
10910                for row in range.start.row..=range.end.row {
10911                    if let Some(crease) = display_map.crease_for_buffer_row(MultiBufferRow(row)) {
10912                        found = true;
10913                        to_fold.push(crease);
10914                    }
10915                }
10916                if found {
10917                    continue;
10918                }
10919            }
10920
10921            for row in (0..=range.start.row).rev() {
10922                if let Some(crease) = display_map.crease_for_buffer_row(MultiBufferRow(row)) {
10923                    if crease.range().end.row >= buffer_start_row {
10924                        to_fold.push(crease);
10925                    } else {
10926                        break;
10927                    }
10928                }
10929            }
10930        }
10931
10932        self.fold_creases(to_fold, true, cx);
10933    }
10934
10935    pub fn fold_at(&mut self, fold_at: &FoldAt, cx: &mut ViewContext<Self>) {
10936        let buffer_row = fold_at.buffer_row;
10937        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
10938
10939        if let Some(crease) = display_map.crease_for_buffer_row(buffer_row) {
10940            let autoscroll = self
10941                .selections
10942                .all::<Point>(cx)
10943                .iter()
10944                .any(|selection| crease.range().overlaps(&selection.range()));
10945
10946            self.fold_creases(vec![crease], autoscroll, cx);
10947        }
10948    }
10949
10950    pub fn unfold_lines(&mut self, _: &UnfoldLines, cx: &mut ViewContext<Self>) {
10951        if self.is_singleton(cx) {
10952            let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
10953            let buffer = &display_map.buffer_snapshot;
10954            let selections = self.selections.all::<Point>(cx);
10955            let ranges = selections
10956                .iter()
10957                .map(|s| {
10958                    let range = s.display_range(&display_map).sorted();
10959                    let mut start = range.start.to_point(&display_map);
10960                    let mut end = range.end.to_point(&display_map);
10961                    start.column = 0;
10962                    end.column = buffer.line_len(MultiBufferRow(end.row));
10963                    start..end
10964                })
10965                .collect::<Vec<_>>();
10966
10967            self.unfold_ranges(&ranges, true, true, cx);
10968        } else {
10969            let multi_buffer_snapshot = self.buffer.read(cx).snapshot(cx);
10970            let mut unfolded_buffers = HashSet::default();
10971            for (_, buffer_snapshot, _) in
10972                multi_buffer_snapshot.excerpts_in_ranges(self.selections.disjoint_anchor_ranges())
10973            {
10974                let buffer_id = buffer_snapshot.remote_id();
10975                if unfolded_buffers.insert(buffer_id) {
10976                    self.unfold_buffer(buffer_id, cx);
10977                }
10978            }
10979        }
10980    }
10981
10982    pub fn unfold_recursive(&mut self, _: &UnfoldRecursive, cx: &mut ViewContext<Self>) {
10983        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
10984        let selections = self.selections.all::<Point>(cx);
10985        let ranges = selections
10986            .iter()
10987            .map(|s| {
10988                let mut range = s.display_range(&display_map).sorted();
10989                *range.start.column_mut() = 0;
10990                *range.end.column_mut() = display_map.line_len(range.end.row());
10991                let start = range.start.to_point(&display_map);
10992                let end = range.end.to_point(&display_map);
10993                start..end
10994            })
10995            .collect::<Vec<_>>();
10996
10997        self.unfold_ranges(&ranges, true, true, cx);
10998    }
10999
11000    pub fn unfold_at(&mut self, unfold_at: &UnfoldAt, cx: &mut ViewContext<Self>) {
11001        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
11002
11003        let intersection_range = Point::new(unfold_at.buffer_row.0, 0)
11004            ..Point::new(
11005                unfold_at.buffer_row.0,
11006                display_map.buffer_snapshot.line_len(unfold_at.buffer_row),
11007            );
11008
11009        let autoscroll = self
11010            .selections
11011            .all::<Point>(cx)
11012            .iter()
11013            .any(|selection| RangeExt::overlaps(&selection.range(), &intersection_range));
11014
11015        self.unfold_ranges(&[intersection_range], true, autoscroll, cx)
11016    }
11017
11018    pub fn unfold_all(&mut self, _: &actions::UnfoldAll, cx: &mut ViewContext<Self>) {
11019        if self.buffer.read(cx).is_singleton() {
11020            let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
11021            self.unfold_ranges(&[0..display_map.buffer_snapshot.len()], true, true, cx);
11022        } else {
11023            self.toggle_fold_multiple_buffers = cx.spawn(|editor, mut cx| async move {
11024                editor
11025                    .update(&mut cx, |editor, cx| {
11026                        for buffer_id in editor.buffer.read(cx).excerpt_buffer_ids() {
11027                            editor.unfold_buffer(buffer_id, cx);
11028                        }
11029                    })
11030                    .ok();
11031            });
11032        }
11033    }
11034
11035    pub fn fold_selected_ranges(&mut self, _: &FoldSelectedRanges, cx: &mut ViewContext<Self>) {
11036        let selections = self.selections.all::<Point>(cx);
11037        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
11038        let line_mode = self.selections.line_mode;
11039        let ranges = selections
11040            .into_iter()
11041            .map(|s| {
11042                if line_mode {
11043                    let start = Point::new(s.start.row, 0);
11044                    let end = Point::new(
11045                        s.end.row,
11046                        display_map
11047                            .buffer_snapshot
11048                            .line_len(MultiBufferRow(s.end.row)),
11049                    );
11050                    Crease::simple(start..end, display_map.fold_placeholder.clone())
11051                } else {
11052                    Crease::simple(s.start..s.end, display_map.fold_placeholder.clone())
11053                }
11054            })
11055            .collect::<Vec<_>>();
11056        self.fold_creases(ranges, true, cx);
11057    }
11058
11059    pub fn fold_ranges<T: ToOffset + Clone>(
11060        &mut self,
11061        ranges: Vec<Range<T>>,
11062        auto_scroll: bool,
11063        cx: &mut ViewContext<Self>,
11064    ) {
11065        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
11066        let ranges = ranges
11067            .into_iter()
11068            .map(|r| Crease::simple(r, display_map.fold_placeholder.clone()))
11069            .collect::<Vec<_>>();
11070        self.fold_creases(ranges, auto_scroll, cx);
11071    }
11072
11073    pub fn fold_creases<T: ToOffset + Clone>(
11074        &mut self,
11075        creases: Vec<Crease<T>>,
11076        auto_scroll: bool,
11077        cx: &mut ViewContext<Self>,
11078    ) {
11079        if creases.is_empty() {
11080            return;
11081        }
11082
11083        let mut buffers_affected = HashSet::default();
11084        let multi_buffer = self.buffer().read(cx);
11085        for crease in &creases {
11086            if let Some((_, buffer, _)) =
11087                multi_buffer.excerpt_containing(crease.range().start.clone(), cx)
11088            {
11089                buffers_affected.insert(buffer.read(cx).remote_id());
11090            };
11091        }
11092
11093        self.display_map.update(cx, |map, cx| map.fold(creases, cx));
11094
11095        if auto_scroll {
11096            self.request_autoscroll(Autoscroll::fit(), cx);
11097        }
11098
11099        for buffer_id in buffers_affected {
11100            Self::sync_expanded_diff_hunks(&mut self.diff_map, buffer_id, cx);
11101        }
11102
11103        cx.notify();
11104
11105        if let Some(active_diagnostics) = self.active_diagnostics.take() {
11106            // Clear diagnostics block when folding a range that contains it.
11107            let snapshot = self.snapshot(cx);
11108            if snapshot.intersects_fold(active_diagnostics.primary_range.start) {
11109                drop(snapshot);
11110                self.active_diagnostics = Some(active_diagnostics);
11111                self.dismiss_diagnostics(cx);
11112            } else {
11113                self.active_diagnostics = Some(active_diagnostics);
11114            }
11115        }
11116
11117        self.scrollbar_marker_state.dirty = true;
11118    }
11119
11120    /// Removes any folds whose ranges intersect any of the given ranges.
11121    pub fn unfold_ranges<T: ToOffset + Clone>(
11122        &mut self,
11123        ranges: &[Range<T>],
11124        inclusive: bool,
11125        auto_scroll: bool,
11126        cx: &mut ViewContext<Self>,
11127    ) {
11128        self.remove_folds_with(ranges, auto_scroll, cx, |map, cx| {
11129            map.unfold_intersecting(ranges.iter().cloned(), inclusive, cx)
11130        });
11131    }
11132
11133    pub fn fold_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 folded_excerpts = self.buffer().read(cx).excerpts_for_buffer(&buffer, cx);
11141        self.display_map
11142            .update(cx, |display_map, cx| display_map.fold_buffer(buffer_id, cx));
11143        cx.emit(EditorEvent::BufferFoldToggled {
11144            ids: folded_excerpts.iter().map(|&(id, _)| id).collect(),
11145            folded: true,
11146        });
11147        cx.notify();
11148    }
11149
11150    pub fn unfold_buffer(&mut self, buffer_id: BufferId, cx: &mut ViewContext<Self>) {
11151        if self.buffer().read(cx).is_singleton() || !self.buffer_folded(buffer_id, cx) {
11152            return;
11153        }
11154        let Some(buffer) = self.buffer().read(cx).buffer(buffer_id) else {
11155            return;
11156        };
11157        let unfolded_excerpts = self.buffer().read(cx).excerpts_for_buffer(&buffer, cx);
11158        self.display_map.update(cx, |display_map, cx| {
11159            display_map.unfold_buffer(buffer_id, cx);
11160        });
11161        cx.emit(EditorEvent::BufferFoldToggled {
11162            ids: unfolded_excerpts.iter().map(|&(id, _)| id).collect(),
11163            folded: false,
11164        });
11165        cx.notify();
11166    }
11167
11168    pub fn buffer_folded(&self, buffer: BufferId, cx: &AppContext) -> bool {
11169        self.display_map.read(cx).buffer_folded(buffer)
11170    }
11171
11172    /// Removes any folds with the given ranges.
11173    pub fn remove_folds_with_type<T: ToOffset + Clone>(
11174        &mut self,
11175        ranges: &[Range<T>],
11176        type_id: TypeId,
11177        auto_scroll: bool,
11178        cx: &mut ViewContext<Self>,
11179    ) {
11180        self.remove_folds_with(ranges, auto_scroll, cx, |map, cx| {
11181            map.remove_folds_with_type(ranges.iter().cloned(), type_id, cx)
11182        });
11183    }
11184
11185    fn remove_folds_with<T: ToOffset + Clone>(
11186        &mut self,
11187        ranges: &[Range<T>],
11188        auto_scroll: bool,
11189        cx: &mut ViewContext<Self>,
11190        update: impl FnOnce(&mut DisplayMap, &mut ModelContext<DisplayMap>),
11191    ) {
11192        if ranges.is_empty() {
11193            return;
11194        }
11195
11196        let mut buffers_affected = HashSet::default();
11197        let multi_buffer = self.buffer().read(cx);
11198        for range in ranges {
11199            if let Some((_, buffer, _)) = multi_buffer.excerpt_containing(range.start.clone(), cx) {
11200                buffers_affected.insert(buffer.read(cx).remote_id());
11201            };
11202        }
11203
11204        self.display_map.update(cx, update);
11205
11206        if auto_scroll {
11207            self.request_autoscroll(Autoscroll::fit(), cx);
11208        }
11209
11210        for buffer_id in buffers_affected {
11211            Self::sync_expanded_diff_hunks(&mut self.diff_map, buffer_id, cx);
11212        }
11213
11214        cx.notify();
11215        self.scrollbar_marker_state.dirty = true;
11216        self.active_indent_guides_state.dirty = true;
11217    }
11218
11219    pub fn default_fold_placeholder(&self, cx: &AppContext) -> FoldPlaceholder {
11220        self.display_map.read(cx).fold_placeholder.clone()
11221    }
11222
11223    pub fn set_gutter_hovered(&mut self, hovered: bool, cx: &mut ViewContext<Self>) {
11224        if hovered != self.gutter_hovered {
11225            self.gutter_hovered = hovered;
11226            cx.notify();
11227        }
11228    }
11229
11230    pub fn insert_blocks(
11231        &mut self,
11232        blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
11233        autoscroll: Option<Autoscroll>,
11234        cx: &mut ViewContext<Self>,
11235    ) -> Vec<CustomBlockId> {
11236        let blocks = self
11237            .display_map
11238            .update(cx, |display_map, cx| display_map.insert_blocks(blocks, cx));
11239        if let Some(autoscroll) = autoscroll {
11240            self.request_autoscroll(autoscroll, cx);
11241        }
11242        cx.notify();
11243        blocks
11244    }
11245
11246    pub fn resize_blocks(
11247        &mut self,
11248        heights: HashMap<CustomBlockId, u32>,
11249        autoscroll: Option<Autoscroll>,
11250        cx: &mut ViewContext<Self>,
11251    ) {
11252        self.display_map
11253            .update(cx, |display_map, cx| display_map.resize_blocks(heights, cx));
11254        if let Some(autoscroll) = autoscroll {
11255            self.request_autoscroll(autoscroll, cx);
11256        }
11257        cx.notify();
11258    }
11259
11260    pub fn replace_blocks(
11261        &mut self,
11262        renderers: HashMap<CustomBlockId, RenderBlock>,
11263        autoscroll: Option<Autoscroll>,
11264        cx: &mut ViewContext<Self>,
11265    ) {
11266        self.display_map
11267            .update(cx, |display_map, _cx| display_map.replace_blocks(renderers));
11268        if let Some(autoscroll) = autoscroll {
11269            self.request_autoscroll(autoscroll, cx);
11270        }
11271        cx.notify();
11272    }
11273
11274    pub fn remove_blocks(
11275        &mut self,
11276        block_ids: HashSet<CustomBlockId>,
11277        autoscroll: Option<Autoscroll>,
11278        cx: &mut ViewContext<Self>,
11279    ) {
11280        self.display_map.update(cx, |display_map, cx| {
11281            display_map.remove_blocks(block_ids, cx)
11282        });
11283        if let Some(autoscroll) = autoscroll {
11284            self.request_autoscroll(autoscroll, cx);
11285        }
11286        cx.notify();
11287    }
11288
11289    pub fn row_for_block(
11290        &self,
11291        block_id: CustomBlockId,
11292        cx: &mut ViewContext<Self>,
11293    ) -> Option<DisplayRow> {
11294        self.display_map
11295            .update(cx, |map, cx| map.row_for_block(block_id, cx))
11296    }
11297
11298    pub(crate) fn set_focused_block(&mut self, focused_block: FocusedBlock) {
11299        self.focused_block = Some(focused_block);
11300    }
11301
11302    pub(crate) fn take_focused_block(&mut self) -> Option<FocusedBlock> {
11303        self.focused_block.take()
11304    }
11305
11306    pub fn insert_creases(
11307        &mut self,
11308        creases: impl IntoIterator<Item = Crease<Anchor>>,
11309        cx: &mut ViewContext<Self>,
11310    ) -> Vec<CreaseId> {
11311        self.display_map
11312            .update(cx, |map, cx| map.insert_creases(creases, cx))
11313    }
11314
11315    pub fn remove_creases(
11316        &mut self,
11317        ids: impl IntoIterator<Item = CreaseId>,
11318        cx: &mut ViewContext<Self>,
11319    ) {
11320        self.display_map
11321            .update(cx, |map, cx| map.remove_creases(ids, cx));
11322    }
11323
11324    pub fn longest_row(&self, cx: &mut AppContext) -> DisplayRow {
11325        self.display_map
11326            .update(cx, |map, cx| map.snapshot(cx))
11327            .longest_row()
11328    }
11329
11330    pub fn max_point(&self, cx: &mut AppContext) -> DisplayPoint {
11331        self.display_map
11332            .update(cx, |map, cx| map.snapshot(cx))
11333            .max_point()
11334    }
11335
11336    pub fn text(&self, cx: &AppContext) -> String {
11337        self.buffer.read(cx).read(cx).text()
11338    }
11339
11340    pub fn text_option(&self, cx: &AppContext) -> Option<String> {
11341        let text = self.text(cx);
11342        let text = text.trim();
11343
11344        if text.is_empty() {
11345            return None;
11346        }
11347
11348        Some(text.to_string())
11349    }
11350
11351    pub fn set_text(&mut self, text: impl Into<Arc<str>>, cx: &mut ViewContext<Self>) {
11352        self.transact(cx, |this, cx| {
11353            this.buffer
11354                .read(cx)
11355                .as_singleton()
11356                .expect("you can only call set_text on editors for singleton buffers")
11357                .update(cx, |buffer, cx| buffer.set_text(text, cx));
11358        });
11359    }
11360
11361    pub fn display_text(&self, cx: &mut AppContext) -> String {
11362        self.display_map
11363            .update(cx, |map, cx| map.snapshot(cx))
11364            .text()
11365    }
11366
11367    pub fn wrap_guides(&self, cx: &AppContext) -> SmallVec<[(usize, bool); 2]> {
11368        let mut wrap_guides = smallvec::smallvec![];
11369
11370        if self.show_wrap_guides == Some(false) {
11371            return wrap_guides;
11372        }
11373
11374        let settings = self.buffer.read(cx).settings_at(0, cx);
11375        if settings.show_wrap_guides {
11376            if let SoftWrap::Column(soft_wrap) = self.soft_wrap_mode(cx) {
11377                wrap_guides.push((soft_wrap as usize, true));
11378            } else if let SoftWrap::Bounded(soft_wrap) = self.soft_wrap_mode(cx) {
11379                wrap_guides.push((soft_wrap as usize, true));
11380            }
11381            wrap_guides.extend(settings.wrap_guides.iter().map(|guide| (*guide, false)))
11382        }
11383
11384        wrap_guides
11385    }
11386
11387    pub fn soft_wrap_mode(&self, cx: &AppContext) -> SoftWrap {
11388        let settings = self.buffer.read(cx).settings_at(0, cx);
11389        let mode = self.soft_wrap_mode_override.unwrap_or(settings.soft_wrap);
11390        match mode {
11391            language_settings::SoftWrap::PreferLine | language_settings::SoftWrap::None => {
11392                SoftWrap::None
11393            }
11394            language_settings::SoftWrap::EditorWidth => SoftWrap::EditorWidth,
11395            language_settings::SoftWrap::PreferredLineLength => {
11396                SoftWrap::Column(settings.preferred_line_length)
11397            }
11398            language_settings::SoftWrap::Bounded => {
11399                SoftWrap::Bounded(settings.preferred_line_length)
11400            }
11401        }
11402    }
11403
11404    pub fn set_soft_wrap_mode(
11405        &mut self,
11406        mode: language_settings::SoftWrap,
11407        cx: &mut ViewContext<Self>,
11408    ) {
11409        self.soft_wrap_mode_override = Some(mode);
11410        cx.notify();
11411    }
11412
11413    pub fn set_text_style_refinement(&mut self, style: TextStyleRefinement) {
11414        self.text_style_refinement = Some(style);
11415    }
11416
11417    /// called by the Element so we know what style we were most recently rendered with.
11418    pub(crate) fn set_style(&mut self, style: EditorStyle, cx: &mut ViewContext<Self>) {
11419        let rem_size = cx.rem_size();
11420        self.display_map.update(cx, |map, cx| {
11421            map.set_font(
11422                style.text.font(),
11423                style.text.font_size.to_pixels(rem_size),
11424                cx,
11425            )
11426        });
11427        self.style = Some(style);
11428    }
11429
11430    pub fn style(&self) -> Option<&EditorStyle> {
11431        self.style.as_ref()
11432    }
11433
11434    // Called by the element. This method is not designed to be called outside of the editor
11435    // element's layout code because it does not notify when rewrapping is computed synchronously.
11436    pub(crate) fn set_wrap_width(&self, width: Option<Pixels>, cx: &mut AppContext) -> bool {
11437        self.display_map
11438            .update(cx, |map, cx| map.set_wrap_width(width, cx))
11439    }
11440
11441    pub fn toggle_soft_wrap(&mut self, _: &ToggleSoftWrap, cx: &mut ViewContext<Self>) {
11442        if self.soft_wrap_mode_override.is_some() {
11443            self.soft_wrap_mode_override.take();
11444        } else {
11445            let soft_wrap = match self.soft_wrap_mode(cx) {
11446                SoftWrap::GitDiff => return,
11447                SoftWrap::None => language_settings::SoftWrap::EditorWidth,
11448                SoftWrap::EditorWidth | SoftWrap::Column(_) | SoftWrap::Bounded(_) => {
11449                    language_settings::SoftWrap::None
11450                }
11451            };
11452            self.soft_wrap_mode_override = Some(soft_wrap);
11453        }
11454        cx.notify();
11455    }
11456
11457    pub fn toggle_tab_bar(&mut self, _: &ToggleTabBar, cx: &mut ViewContext<Self>) {
11458        let Some(workspace) = self.workspace() else {
11459            return;
11460        };
11461        let fs = workspace.read(cx).app_state().fs.clone();
11462        let current_show = TabBarSettings::get_global(cx).show;
11463        update_settings_file::<TabBarSettings>(fs, cx, move |setting, _| {
11464            setting.show = Some(!current_show);
11465        });
11466    }
11467
11468    pub fn toggle_indent_guides(&mut self, _: &ToggleIndentGuides, cx: &mut ViewContext<Self>) {
11469        let currently_enabled = self.should_show_indent_guides().unwrap_or_else(|| {
11470            self.buffer
11471                .read(cx)
11472                .settings_at(0, cx)
11473                .indent_guides
11474                .enabled
11475        });
11476        self.show_indent_guides = Some(!currently_enabled);
11477        cx.notify();
11478    }
11479
11480    fn should_show_indent_guides(&self) -> Option<bool> {
11481        self.show_indent_guides
11482    }
11483
11484    pub fn toggle_line_numbers(&mut self, _: &ToggleLineNumbers, cx: &mut ViewContext<Self>) {
11485        let mut editor_settings = EditorSettings::get_global(cx).clone();
11486        editor_settings.gutter.line_numbers = !editor_settings.gutter.line_numbers;
11487        EditorSettings::override_global(editor_settings, cx);
11488    }
11489
11490    pub fn should_use_relative_line_numbers(&self, cx: &WindowContext) -> bool {
11491        self.use_relative_line_numbers
11492            .unwrap_or(EditorSettings::get_global(cx).relative_line_numbers)
11493    }
11494
11495    pub fn toggle_relative_line_numbers(
11496        &mut self,
11497        _: &ToggleRelativeLineNumbers,
11498        cx: &mut ViewContext<Self>,
11499    ) {
11500        let is_relative = self.should_use_relative_line_numbers(cx);
11501        self.set_relative_line_number(Some(!is_relative), cx)
11502    }
11503
11504    pub fn set_relative_line_number(
11505        &mut self,
11506        is_relative: Option<bool>,
11507        cx: &mut ViewContext<Self>,
11508    ) {
11509        self.use_relative_line_numbers = is_relative;
11510        cx.notify();
11511    }
11512
11513    pub fn set_show_gutter(&mut self, show_gutter: bool, cx: &mut ViewContext<Self>) {
11514        self.show_gutter = show_gutter;
11515        cx.notify();
11516    }
11517
11518    pub fn set_show_scrollbars(&mut self, show_scrollbars: bool, cx: &mut ViewContext<Self>) {
11519        self.show_scrollbars = show_scrollbars;
11520        cx.notify();
11521    }
11522
11523    pub fn set_show_line_numbers(&mut self, show_line_numbers: bool, cx: &mut ViewContext<Self>) {
11524        self.show_line_numbers = Some(show_line_numbers);
11525        cx.notify();
11526    }
11527
11528    pub fn set_show_git_diff_gutter(
11529        &mut self,
11530        show_git_diff_gutter: bool,
11531        cx: &mut ViewContext<Self>,
11532    ) {
11533        self.show_git_diff_gutter = Some(show_git_diff_gutter);
11534        cx.notify();
11535    }
11536
11537    pub fn set_show_code_actions(&mut self, show_code_actions: bool, cx: &mut ViewContext<Self>) {
11538        self.show_code_actions = Some(show_code_actions);
11539        cx.notify();
11540    }
11541
11542    pub fn set_show_runnables(&mut self, show_runnables: bool, cx: &mut ViewContext<Self>) {
11543        self.show_runnables = Some(show_runnables);
11544        cx.notify();
11545    }
11546
11547    pub fn set_masked(&mut self, masked: bool, cx: &mut ViewContext<Self>) {
11548        if self.display_map.read(cx).masked != masked {
11549            self.display_map.update(cx, |map, _| map.masked = masked);
11550        }
11551        cx.notify()
11552    }
11553
11554    pub fn set_show_wrap_guides(&mut self, show_wrap_guides: bool, cx: &mut ViewContext<Self>) {
11555        self.show_wrap_guides = Some(show_wrap_guides);
11556        cx.notify();
11557    }
11558
11559    pub fn set_show_indent_guides(&mut self, show_indent_guides: bool, cx: &mut ViewContext<Self>) {
11560        self.show_indent_guides = Some(show_indent_guides);
11561        cx.notify();
11562    }
11563
11564    pub fn working_directory(&self, cx: &WindowContext) -> Option<PathBuf> {
11565        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
11566            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
11567                if let Some(dir) = file.abs_path(cx).parent() {
11568                    return Some(dir.to_owned());
11569                }
11570            }
11571
11572            if let Some(project_path) = buffer.read(cx).project_path(cx) {
11573                return Some(project_path.path.to_path_buf());
11574            }
11575        }
11576
11577        None
11578    }
11579
11580    fn target_file<'a>(&self, cx: &'a AppContext) -> Option<&'a dyn language::LocalFile> {
11581        self.active_excerpt(cx)?
11582            .1
11583            .read(cx)
11584            .file()
11585            .and_then(|f| f.as_local())
11586    }
11587
11588    fn target_file_abs_path(&self, cx: &mut ViewContext<Self>) -> Option<PathBuf> {
11589        self.active_excerpt(cx).and_then(|(_, buffer, _)| {
11590            let project_path = buffer.read(cx).project_path(cx)?;
11591            let project = self.project.as_ref()?.read(cx);
11592            project.absolute_path(&project_path, cx)
11593        })
11594    }
11595
11596    fn target_file_path(&self, cx: &mut ViewContext<Self>) -> Option<PathBuf> {
11597        self.active_excerpt(cx).and_then(|(_, buffer, _)| {
11598            let project_path = buffer.read(cx).project_path(cx)?;
11599            let project = self.project.as_ref()?.read(cx);
11600            let entry = project.entry_for_path(&project_path, cx)?;
11601            let path = entry.path.to_path_buf();
11602            Some(path)
11603        })
11604    }
11605
11606    pub fn reveal_in_finder(&mut self, _: &RevealInFileManager, cx: &mut ViewContext<Self>) {
11607        if let Some(target) = self.target_file(cx) {
11608            cx.reveal_path(&target.abs_path(cx));
11609        }
11610    }
11611
11612    pub fn copy_path(&mut self, _: &CopyPath, cx: &mut ViewContext<Self>) {
11613        if let Some(path) = self.target_file_abs_path(cx) {
11614            if let Some(path) = path.to_str() {
11615                cx.write_to_clipboard(ClipboardItem::new_string(path.to_string()));
11616            }
11617        }
11618    }
11619
11620    pub fn copy_relative_path(&mut self, _: &CopyRelativePath, cx: &mut ViewContext<Self>) {
11621        if let Some(path) = self.target_file_path(cx) {
11622            if let Some(path) = path.to_str() {
11623                cx.write_to_clipboard(ClipboardItem::new_string(path.to_string()));
11624            }
11625        }
11626    }
11627
11628    pub fn toggle_git_blame(&mut self, _: &ToggleGitBlame, cx: &mut ViewContext<Self>) {
11629        self.show_git_blame_gutter = !self.show_git_blame_gutter;
11630
11631        if self.show_git_blame_gutter && !self.has_blame_entries(cx) {
11632            self.start_git_blame(true, cx);
11633        }
11634
11635        cx.notify();
11636    }
11637
11638    pub fn toggle_git_blame_inline(
11639        &mut self,
11640        _: &ToggleGitBlameInline,
11641        cx: &mut ViewContext<Self>,
11642    ) {
11643        self.toggle_git_blame_inline_internal(true, cx);
11644        cx.notify();
11645    }
11646
11647    pub fn git_blame_inline_enabled(&self) -> bool {
11648        self.git_blame_inline_enabled
11649    }
11650
11651    pub fn toggle_selection_menu(&mut self, _: &ToggleSelectionMenu, cx: &mut ViewContext<Self>) {
11652        self.show_selection_menu = self
11653            .show_selection_menu
11654            .map(|show_selections_menu| !show_selections_menu)
11655            .or_else(|| Some(!EditorSettings::get_global(cx).toolbar.selections_menu));
11656
11657        cx.notify();
11658    }
11659
11660    pub fn selection_menu_enabled(&self, cx: &AppContext) -> bool {
11661        self.show_selection_menu
11662            .unwrap_or_else(|| EditorSettings::get_global(cx).toolbar.selections_menu)
11663    }
11664
11665    fn start_git_blame(&mut self, user_triggered: bool, cx: &mut ViewContext<Self>) {
11666        if let Some(project) = self.project.as_ref() {
11667            let Some(buffer) = self.buffer().read(cx).as_singleton() else {
11668                return;
11669            };
11670
11671            if buffer.read(cx).file().is_none() {
11672                return;
11673            }
11674
11675            let focused = self.focus_handle(cx).contains_focused(cx);
11676
11677            let project = project.clone();
11678            let blame =
11679                cx.new_model(|cx| GitBlame::new(buffer, project, user_triggered, focused, cx));
11680            self.blame_subscription = Some(cx.observe(&blame, |_, _, cx| cx.notify()));
11681            self.blame = Some(blame);
11682        }
11683    }
11684
11685    fn toggle_git_blame_inline_internal(
11686        &mut self,
11687        user_triggered: bool,
11688        cx: &mut ViewContext<Self>,
11689    ) {
11690        if self.git_blame_inline_enabled {
11691            self.git_blame_inline_enabled = false;
11692            self.show_git_blame_inline = false;
11693            self.show_git_blame_inline_delay_task.take();
11694        } else {
11695            self.git_blame_inline_enabled = true;
11696            self.start_git_blame_inline(user_triggered, cx);
11697        }
11698
11699        cx.notify();
11700    }
11701
11702    fn start_git_blame_inline(&mut self, user_triggered: bool, cx: &mut ViewContext<Self>) {
11703        self.start_git_blame(user_triggered, cx);
11704
11705        if ProjectSettings::get_global(cx)
11706            .git
11707            .inline_blame_delay()
11708            .is_some()
11709        {
11710            self.start_inline_blame_timer(cx);
11711        } else {
11712            self.show_git_blame_inline = true
11713        }
11714    }
11715
11716    pub fn blame(&self) -> Option<&Model<GitBlame>> {
11717        self.blame.as_ref()
11718    }
11719
11720    pub fn show_git_blame_gutter(&self) -> bool {
11721        self.show_git_blame_gutter
11722    }
11723
11724    pub fn render_git_blame_gutter(&self, cx: &WindowContext) -> bool {
11725        self.show_git_blame_gutter && self.has_blame_entries(cx)
11726    }
11727
11728    pub fn render_git_blame_inline(&self, cx: &WindowContext) -> bool {
11729        self.show_git_blame_inline
11730            && self.focus_handle.is_focused(cx)
11731            && !self.newest_selection_head_on_empty_line(cx)
11732            && self.has_blame_entries(cx)
11733    }
11734
11735    fn has_blame_entries(&self, cx: &WindowContext) -> bool {
11736        self.blame()
11737            .map_or(false, |blame| blame.read(cx).has_generated_entries())
11738    }
11739
11740    fn newest_selection_head_on_empty_line(&self, cx: &WindowContext) -> bool {
11741        let cursor_anchor = self.selections.newest_anchor().head();
11742
11743        let snapshot = self.buffer.read(cx).snapshot(cx);
11744        let buffer_row = MultiBufferRow(cursor_anchor.to_point(&snapshot).row);
11745
11746        snapshot.line_len(buffer_row) == 0
11747    }
11748
11749    fn get_permalink_to_line(&self, cx: &mut ViewContext<Self>) -> Task<Result<url::Url>> {
11750        let buffer_and_selection = maybe!({
11751            let selection = self.selections.newest::<Point>(cx);
11752            let selection_range = selection.range();
11753
11754            let (buffer, selection) = if let Some(buffer) = self.buffer().read(cx).as_singleton() {
11755                (buffer, selection_range.start.row..selection_range.end.row)
11756            } else {
11757                let multi_buffer = self.buffer().read(cx);
11758                let multi_buffer_snapshot = multi_buffer.snapshot(cx);
11759                let buffer_ranges = multi_buffer_snapshot.range_to_buffer_ranges(selection_range);
11760
11761                let (excerpt, range) = if selection.reversed {
11762                    buffer_ranges.first()
11763                } else {
11764                    buffer_ranges.last()
11765                }?;
11766
11767                let snapshot = excerpt.buffer();
11768                let selection = text::ToPoint::to_point(&range.start, &snapshot).row
11769                    ..text::ToPoint::to_point(&range.end, &snapshot).row;
11770                (
11771                    multi_buffer.buffer(excerpt.buffer_id()).unwrap().clone(),
11772                    selection,
11773                )
11774            };
11775
11776            Some((buffer, selection))
11777        });
11778
11779        let Some((buffer, selection)) = buffer_and_selection else {
11780            return Task::ready(Err(anyhow!("failed to determine buffer and selection")));
11781        };
11782
11783        let Some(project) = self.project.as_ref() else {
11784            return Task::ready(Err(anyhow!("editor does not have project")));
11785        };
11786
11787        project.update(cx, |project, cx| {
11788            project.get_permalink_to_line(&buffer, selection, cx)
11789        })
11790    }
11791
11792    pub fn copy_permalink_to_line(&mut self, _: &CopyPermalinkToLine, cx: &mut ViewContext<Self>) {
11793        let permalink_task = self.get_permalink_to_line(cx);
11794        let workspace = self.workspace();
11795
11796        cx.spawn(|_, mut cx| async move {
11797            match permalink_task.await {
11798                Ok(permalink) => {
11799                    cx.update(|cx| {
11800                        cx.write_to_clipboard(ClipboardItem::new_string(permalink.to_string()));
11801                    })
11802                    .ok();
11803                }
11804                Err(err) => {
11805                    let message = format!("Failed to copy permalink: {err}");
11806
11807                    Err::<(), anyhow::Error>(err).log_err();
11808
11809                    if let Some(workspace) = workspace {
11810                        workspace
11811                            .update(&mut cx, |workspace, cx| {
11812                                struct CopyPermalinkToLine;
11813
11814                                workspace.show_toast(
11815                                    Toast::new(
11816                                        NotificationId::unique::<CopyPermalinkToLine>(),
11817                                        message,
11818                                    ),
11819                                    cx,
11820                                )
11821                            })
11822                            .ok();
11823                    }
11824                }
11825            }
11826        })
11827        .detach();
11828    }
11829
11830    pub fn copy_file_location(&mut self, _: &CopyFileLocation, cx: &mut ViewContext<Self>) {
11831        let selection = self.selections.newest::<Point>(cx).start.row + 1;
11832        if let Some(file) = self.target_file(cx) {
11833            if let Some(path) = file.path().to_str() {
11834                cx.write_to_clipboard(ClipboardItem::new_string(format!("{path}:{selection}")));
11835            }
11836        }
11837    }
11838
11839    pub fn open_permalink_to_line(&mut self, _: &OpenPermalinkToLine, cx: &mut ViewContext<Self>) {
11840        let permalink_task = self.get_permalink_to_line(cx);
11841        let workspace = self.workspace();
11842
11843        cx.spawn(|_, mut cx| async move {
11844            match permalink_task.await {
11845                Ok(permalink) => {
11846                    cx.update(|cx| {
11847                        cx.open_url(permalink.as_ref());
11848                    })
11849                    .ok();
11850                }
11851                Err(err) => {
11852                    let message = format!("Failed to open permalink: {err}");
11853
11854                    Err::<(), anyhow::Error>(err).log_err();
11855
11856                    if let Some(workspace) = workspace {
11857                        workspace
11858                            .update(&mut cx, |workspace, cx| {
11859                                struct OpenPermalinkToLine;
11860
11861                                workspace.show_toast(
11862                                    Toast::new(
11863                                        NotificationId::unique::<OpenPermalinkToLine>(),
11864                                        message,
11865                                    ),
11866                                    cx,
11867                                )
11868                            })
11869                            .ok();
11870                    }
11871                }
11872            }
11873        })
11874        .detach();
11875    }
11876
11877    pub fn insert_uuid_v4(&mut self, _: &InsertUuidV4, cx: &mut ViewContext<Self>) {
11878        self.insert_uuid(UuidVersion::V4, cx);
11879    }
11880
11881    pub fn insert_uuid_v7(&mut self, _: &InsertUuidV7, cx: &mut ViewContext<Self>) {
11882        self.insert_uuid(UuidVersion::V7, cx);
11883    }
11884
11885    fn insert_uuid(&mut self, version: UuidVersion, cx: &mut ViewContext<Self>) {
11886        self.transact(cx, |this, cx| {
11887            let edits = this
11888                .selections
11889                .all::<Point>(cx)
11890                .into_iter()
11891                .map(|selection| {
11892                    let uuid = match version {
11893                        UuidVersion::V4 => uuid::Uuid::new_v4(),
11894                        UuidVersion::V7 => uuid::Uuid::now_v7(),
11895                    };
11896
11897                    (selection.range(), uuid.to_string())
11898                });
11899            this.edit(edits, cx);
11900            this.refresh_inline_completion(true, false, cx);
11901        });
11902    }
11903
11904    /// Adds a row highlight for the given range. If a row has multiple highlights, the
11905    /// last highlight added will be used.
11906    ///
11907    /// If the range ends at the beginning of a line, then that line will not be highlighted.
11908    pub fn highlight_rows<T: 'static>(
11909        &mut self,
11910        range: Range<Anchor>,
11911        color: Hsla,
11912        should_autoscroll: bool,
11913        cx: &mut ViewContext<Self>,
11914    ) {
11915        let snapshot = self.buffer().read(cx).snapshot(cx);
11916        let row_highlights = self.highlighted_rows.entry(TypeId::of::<T>()).or_default();
11917        let ix = row_highlights.binary_search_by(|highlight| {
11918            Ordering::Equal
11919                .then_with(|| highlight.range.start.cmp(&range.start, &snapshot))
11920                .then_with(|| highlight.range.end.cmp(&range.end, &snapshot))
11921        });
11922
11923        if let Err(mut ix) = ix {
11924            let index = post_inc(&mut self.highlight_order);
11925
11926            // If this range intersects with the preceding highlight, then merge it with
11927            // the preceding highlight. Otherwise insert a new highlight.
11928            let mut merged = false;
11929            if ix > 0 {
11930                let prev_highlight = &mut row_highlights[ix - 1];
11931                if prev_highlight
11932                    .range
11933                    .end
11934                    .cmp(&range.start, &snapshot)
11935                    .is_ge()
11936                {
11937                    ix -= 1;
11938                    if prev_highlight.range.end.cmp(&range.end, &snapshot).is_lt() {
11939                        prev_highlight.range.end = range.end;
11940                    }
11941                    merged = true;
11942                    prev_highlight.index = index;
11943                    prev_highlight.color = color;
11944                    prev_highlight.should_autoscroll = should_autoscroll;
11945                }
11946            }
11947
11948            if !merged {
11949                row_highlights.insert(
11950                    ix,
11951                    RowHighlight {
11952                        range: range.clone(),
11953                        index,
11954                        color,
11955                        should_autoscroll,
11956                    },
11957                );
11958            }
11959
11960            // If any of the following highlights intersect with this one, merge them.
11961            while let Some(next_highlight) = row_highlights.get(ix + 1) {
11962                let highlight = &row_highlights[ix];
11963                if next_highlight
11964                    .range
11965                    .start
11966                    .cmp(&highlight.range.end, &snapshot)
11967                    .is_le()
11968                {
11969                    if next_highlight
11970                        .range
11971                        .end
11972                        .cmp(&highlight.range.end, &snapshot)
11973                        .is_gt()
11974                    {
11975                        row_highlights[ix].range.end = next_highlight.range.end;
11976                    }
11977                    row_highlights.remove(ix + 1);
11978                } else {
11979                    break;
11980                }
11981            }
11982        }
11983    }
11984
11985    /// Remove any highlighted row ranges of the given type that intersect the
11986    /// given ranges.
11987    pub fn remove_highlighted_rows<T: 'static>(
11988        &mut self,
11989        ranges_to_remove: Vec<Range<Anchor>>,
11990        cx: &mut ViewContext<Self>,
11991    ) {
11992        let snapshot = self.buffer().read(cx).snapshot(cx);
11993        let row_highlights = self.highlighted_rows.entry(TypeId::of::<T>()).or_default();
11994        let mut ranges_to_remove = ranges_to_remove.iter().peekable();
11995        row_highlights.retain(|highlight| {
11996            while let Some(range_to_remove) = ranges_to_remove.peek() {
11997                match range_to_remove.end.cmp(&highlight.range.start, &snapshot) {
11998                    Ordering::Less | Ordering::Equal => {
11999                        ranges_to_remove.next();
12000                    }
12001                    Ordering::Greater => {
12002                        match range_to_remove.start.cmp(&highlight.range.end, &snapshot) {
12003                            Ordering::Less | Ordering::Equal => {
12004                                return false;
12005                            }
12006                            Ordering::Greater => break,
12007                        }
12008                    }
12009                }
12010            }
12011
12012            true
12013        })
12014    }
12015
12016    /// Clear all anchor ranges for a certain highlight context type, so no corresponding rows will be highlighted.
12017    pub fn clear_row_highlights<T: 'static>(&mut self) {
12018        self.highlighted_rows.remove(&TypeId::of::<T>());
12019    }
12020
12021    /// For a highlight given context type, gets all anchor ranges that will be used for row highlighting.
12022    pub fn highlighted_rows<T: 'static>(&self) -> impl '_ + Iterator<Item = (Range<Anchor>, Hsla)> {
12023        self.highlighted_rows
12024            .get(&TypeId::of::<T>())
12025            .map_or(&[] as &[_], |vec| vec.as_slice())
12026            .iter()
12027            .map(|highlight| (highlight.range.clone(), highlight.color))
12028    }
12029
12030    /// Merges all anchor ranges for all context types ever set, picking the last highlight added in case of a row conflict.
12031    /// Returns a map of display rows that are highlighted and their corresponding highlight color.
12032    /// Allows to ignore certain kinds of highlights.
12033    pub fn highlighted_display_rows(&self, cx: &mut WindowContext) -> BTreeMap<DisplayRow, Hsla> {
12034        let snapshot = self.snapshot(cx);
12035        let mut used_highlight_orders = HashMap::default();
12036        self.highlighted_rows
12037            .iter()
12038            .flat_map(|(_, highlighted_rows)| highlighted_rows.iter())
12039            .fold(
12040                BTreeMap::<DisplayRow, Hsla>::new(),
12041                |mut unique_rows, highlight| {
12042                    let start = highlight.range.start.to_display_point(&snapshot);
12043                    let end = highlight.range.end.to_display_point(&snapshot);
12044                    let start_row = start.row().0;
12045                    let end_row = if highlight.range.end.text_anchor != text::Anchor::MAX
12046                        && end.column() == 0
12047                    {
12048                        end.row().0.saturating_sub(1)
12049                    } else {
12050                        end.row().0
12051                    };
12052                    for row in start_row..=end_row {
12053                        let used_index =
12054                            used_highlight_orders.entry(row).or_insert(highlight.index);
12055                        if highlight.index >= *used_index {
12056                            *used_index = highlight.index;
12057                            unique_rows.insert(DisplayRow(row), highlight.color);
12058                        }
12059                    }
12060                    unique_rows
12061                },
12062            )
12063    }
12064
12065    pub fn highlighted_display_row_for_autoscroll(
12066        &self,
12067        snapshot: &DisplaySnapshot,
12068    ) -> Option<DisplayRow> {
12069        self.highlighted_rows
12070            .values()
12071            .flat_map(|highlighted_rows| highlighted_rows.iter())
12072            .filter_map(|highlight| {
12073                if highlight.should_autoscroll {
12074                    Some(highlight.range.start.to_display_point(snapshot).row())
12075                } else {
12076                    None
12077                }
12078            })
12079            .min()
12080    }
12081
12082    pub fn set_search_within_ranges(
12083        &mut self,
12084        ranges: &[Range<Anchor>],
12085        cx: &mut ViewContext<Self>,
12086    ) {
12087        self.highlight_background::<SearchWithinRange>(
12088            ranges,
12089            |colors| colors.editor_document_highlight_read_background,
12090            cx,
12091        )
12092    }
12093
12094    pub fn set_breadcrumb_header(&mut self, new_header: String) {
12095        self.breadcrumb_header = Some(new_header);
12096    }
12097
12098    pub fn clear_search_within_ranges(&mut self, cx: &mut ViewContext<Self>) {
12099        self.clear_background_highlights::<SearchWithinRange>(cx);
12100    }
12101
12102    pub fn highlight_background<T: 'static>(
12103        &mut self,
12104        ranges: &[Range<Anchor>],
12105        color_fetcher: fn(&ThemeColors) -> Hsla,
12106        cx: &mut ViewContext<Self>,
12107    ) {
12108        self.background_highlights
12109            .insert(TypeId::of::<T>(), (color_fetcher, Arc::from(ranges)));
12110        self.scrollbar_marker_state.dirty = true;
12111        cx.notify();
12112    }
12113
12114    pub fn clear_background_highlights<T: 'static>(
12115        &mut self,
12116        cx: &mut ViewContext<Self>,
12117    ) -> Option<BackgroundHighlight> {
12118        let text_highlights = self.background_highlights.remove(&TypeId::of::<T>())?;
12119        if !text_highlights.1.is_empty() {
12120            self.scrollbar_marker_state.dirty = true;
12121            cx.notify();
12122        }
12123        Some(text_highlights)
12124    }
12125
12126    pub fn highlight_gutter<T: 'static>(
12127        &mut self,
12128        ranges: &[Range<Anchor>],
12129        color_fetcher: fn(&AppContext) -> Hsla,
12130        cx: &mut ViewContext<Self>,
12131    ) {
12132        self.gutter_highlights
12133            .insert(TypeId::of::<T>(), (color_fetcher, Arc::from(ranges)));
12134        cx.notify();
12135    }
12136
12137    pub fn clear_gutter_highlights<T: 'static>(
12138        &mut self,
12139        cx: &mut ViewContext<Self>,
12140    ) -> Option<GutterHighlight> {
12141        cx.notify();
12142        self.gutter_highlights.remove(&TypeId::of::<T>())
12143    }
12144
12145    #[cfg(feature = "test-support")]
12146    pub fn all_text_background_highlights(
12147        &self,
12148        cx: &mut ViewContext<Self>,
12149    ) -> Vec<(Range<DisplayPoint>, Hsla)> {
12150        let snapshot = self.snapshot(cx);
12151        let buffer = &snapshot.buffer_snapshot;
12152        let start = buffer.anchor_before(0);
12153        let end = buffer.anchor_after(buffer.len());
12154        let theme = cx.theme().colors();
12155        self.background_highlights_in_range(start..end, &snapshot, theme)
12156    }
12157
12158    #[cfg(feature = "test-support")]
12159    pub fn search_background_highlights(
12160        &mut self,
12161        cx: &mut ViewContext<Self>,
12162    ) -> Vec<Range<Point>> {
12163        let snapshot = self.buffer().read(cx).snapshot(cx);
12164
12165        let highlights = self
12166            .background_highlights
12167            .get(&TypeId::of::<items::BufferSearchHighlights>());
12168
12169        if let Some((_color, ranges)) = highlights {
12170            ranges
12171                .iter()
12172                .map(|range| range.start.to_point(&snapshot)..range.end.to_point(&snapshot))
12173                .collect_vec()
12174        } else {
12175            vec![]
12176        }
12177    }
12178
12179    fn document_highlights_for_position<'a>(
12180        &'a self,
12181        position: Anchor,
12182        buffer: &'a MultiBufferSnapshot,
12183    ) -> impl 'a + Iterator<Item = &'a Range<Anchor>> {
12184        let read_highlights = self
12185            .background_highlights
12186            .get(&TypeId::of::<DocumentHighlightRead>())
12187            .map(|h| &h.1);
12188        let write_highlights = self
12189            .background_highlights
12190            .get(&TypeId::of::<DocumentHighlightWrite>())
12191            .map(|h| &h.1);
12192        let left_position = position.bias_left(buffer);
12193        let right_position = position.bias_right(buffer);
12194        read_highlights
12195            .into_iter()
12196            .chain(write_highlights)
12197            .flat_map(move |ranges| {
12198                let start_ix = match ranges.binary_search_by(|probe| {
12199                    let cmp = probe.end.cmp(&left_position, buffer);
12200                    if cmp.is_ge() {
12201                        Ordering::Greater
12202                    } else {
12203                        Ordering::Less
12204                    }
12205                }) {
12206                    Ok(i) | Err(i) => i,
12207                };
12208
12209                ranges[start_ix..]
12210                    .iter()
12211                    .take_while(move |range| range.start.cmp(&right_position, buffer).is_le())
12212            })
12213    }
12214
12215    pub fn has_background_highlights<T: 'static>(&self) -> bool {
12216        self.background_highlights
12217            .get(&TypeId::of::<T>())
12218            .map_or(false, |(_, highlights)| !highlights.is_empty())
12219    }
12220
12221    pub fn background_highlights_in_range(
12222        &self,
12223        search_range: Range<Anchor>,
12224        display_snapshot: &DisplaySnapshot,
12225        theme: &ThemeColors,
12226    ) -> Vec<(Range<DisplayPoint>, Hsla)> {
12227        let mut results = Vec::new();
12228        for (color_fetcher, ranges) in self.background_highlights.values() {
12229            let color = color_fetcher(theme);
12230            let start_ix = match ranges.binary_search_by(|probe| {
12231                let cmp = probe
12232                    .end
12233                    .cmp(&search_range.start, &display_snapshot.buffer_snapshot);
12234                if cmp.is_gt() {
12235                    Ordering::Greater
12236                } else {
12237                    Ordering::Less
12238                }
12239            }) {
12240                Ok(i) | Err(i) => i,
12241            };
12242            for range in &ranges[start_ix..] {
12243                if range
12244                    .start
12245                    .cmp(&search_range.end, &display_snapshot.buffer_snapshot)
12246                    .is_ge()
12247                {
12248                    break;
12249                }
12250
12251                let start = range.start.to_display_point(display_snapshot);
12252                let end = range.end.to_display_point(display_snapshot);
12253                results.push((start..end, color))
12254            }
12255        }
12256        results
12257    }
12258
12259    pub fn background_highlight_row_ranges<T: 'static>(
12260        &self,
12261        search_range: Range<Anchor>,
12262        display_snapshot: &DisplaySnapshot,
12263        count: usize,
12264    ) -> Vec<RangeInclusive<DisplayPoint>> {
12265        let mut results = Vec::new();
12266        let Some((_, ranges)) = self.background_highlights.get(&TypeId::of::<T>()) else {
12267            return vec![];
12268        };
12269
12270        let start_ix = match ranges.binary_search_by(|probe| {
12271            let cmp = probe
12272                .end
12273                .cmp(&search_range.start, &display_snapshot.buffer_snapshot);
12274            if cmp.is_gt() {
12275                Ordering::Greater
12276            } else {
12277                Ordering::Less
12278            }
12279        }) {
12280            Ok(i) | Err(i) => i,
12281        };
12282        let mut push_region = |start: Option<Point>, end: Option<Point>| {
12283            if let (Some(start_display), Some(end_display)) = (start, end) {
12284                results.push(
12285                    start_display.to_display_point(display_snapshot)
12286                        ..=end_display.to_display_point(display_snapshot),
12287                );
12288            }
12289        };
12290        let mut start_row: Option<Point> = None;
12291        let mut end_row: Option<Point> = None;
12292        if ranges.len() > count {
12293            return Vec::new();
12294        }
12295        for range in &ranges[start_ix..] {
12296            if range
12297                .start
12298                .cmp(&search_range.end, &display_snapshot.buffer_snapshot)
12299                .is_ge()
12300            {
12301                break;
12302            }
12303            let end = range.end.to_point(&display_snapshot.buffer_snapshot);
12304            if let Some(current_row) = &end_row {
12305                if end.row == current_row.row {
12306                    continue;
12307                }
12308            }
12309            let start = range.start.to_point(&display_snapshot.buffer_snapshot);
12310            if start_row.is_none() {
12311                assert_eq!(end_row, None);
12312                start_row = Some(start);
12313                end_row = Some(end);
12314                continue;
12315            }
12316            if let Some(current_end) = end_row.as_mut() {
12317                if start.row > current_end.row + 1 {
12318                    push_region(start_row, end_row);
12319                    start_row = Some(start);
12320                    end_row = Some(end);
12321                } else {
12322                    // Merge two hunks.
12323                    *current_end = end;
12324                }
12325            } else {
12326                unreachable!();
12327            }
12328        }
12329        // We might still have a hunk that was not rendered (if there was a search hit on the last line)
12330        push_region(start_row, end_row);
12331        results
12332    }
12333
12334    pub fn gutter_highlights_in_range(
12335        &self,
12336        search_range: Range<Anchor>,
12337        display_snapshot: &DisplaySnapshot,
12338        cx: &AppContext,
12339    ) -> Vec<(Range<DisplayPoint>, Hsla)> {
12340        let mut results = Vec::new();
12341        for (color_fetcher, ranges) in self.gutter_highlights.values() {
12342            let color = color_fetcher(cx);
12343            let start_ix = match ranges.binary_search_by(|probe| {
12344                let cmp = probe
12345                    .end
12346                    .cmp(&search_range.start, &display_snapshot.buffer_snapshot);
12347                if cmp.is_gt() {
12348                    Ordering::Greater
12349                } else {
12350                    Ordering::Less
12351                }
12352            }) {
12353                Ok(i) | Err(i) => i,
12354            };
12355            for range in &ranges[start_ix..] {
12356                if range
12357                    .start
12358                    .cmp(&search_range.end, &display_snapshot.buffer_snapshot)
12359                    .is_ge()
12360                {
12361                    break;
12362                }
12363
12364                let start = range.start.to_display_point(display_snapshot);
12365                let end = range.end.to_display_point(display_snapshot);
12366                results.push((start..end, color))
12367            }
12368        }
12369        results
12370    }
12371
12372    /// Get the text ranges corresponding to the redaction query
12373    pub fn redacted_ranges(
12374        &self,
12375        search_range: Range<Anchor>,
12376        display_snapshot: &DisplaySnapshot,
12377        cx: &WindowContext,
12378    ) -> Vec<Range<DisplayPoint>> {
12379        display_snapshot
12380            .buffer_snapshot
12381            .redacted_ranges(search_range, |file| {
12382                if let Some(file) = file {
12383                    file.is_private()
12384                        && EditorSettings::get(
12385                            Some(SettingsLocation {
12386                                worktree_id: file.worktree_id(cx),
12387                                path: file.path().as_ref(),
12388                            }),
12389                            cx,
12390                        )
12391                        .redact_private_values
12392                } else {
12393                    false
12394                }
12395            })
12396            .map(|range| {
12397                range.start.to_display_point(display_snapshot)
12398                    ..range.end.to_display_point(display_snapshot)
12399            })
12400            .collect()
12401    }
12402
12403    pub fn highlight_text<T: 'static>(
12404        &mut self,
12405        ranges: Vec<Range<Anchor>>,
12406        style: HighlightStyle,
12407        cx: &mut ViewContext<Self>,
12408    ) {
12409        self.display_map.update(cx, |map, _| {
12410            map.highlight_text(TypeId::of::<T>(), ranges, style)
12411        });
12412        cx.notify();
12413    }
12414
12415    pub(crate) fn highlight_inlays<T: 'static>(
12416        &mut self,
12417        highlights: Vec<InlayHighlight>,
12418        style: HighlightStyle,
12419        cx: &mut ViewContext<Self>,
12420    ) {
12421        self.display_map.update(cx, |map, _| {
12422            map.highlight_inlays(TypeId::of::<T>(), highlights, style)
12423        });
12424        cx.notify();
12425    }
12426
12427    pub fn text_highlights<'a, T: 'static>(
12428        &'a self,
12429        cx: &'a AppContext,
12430    ) -> Option<(HighlightStyle, &'a [Range<Anchor>])> {
12431        self.display_map.read(cx).text_highlights(TypeId::of::<T>())
12432    }
12433
12434    pub fn clear_highlights<T: 'static>(&mut self, cx: &mut ViewContext<Self>) {
12435        let cleared = self
12436            .display_map
12437            .update(cx, |map, _| map.clear_highlights(TypeId::of::<T>()));
12438        if cleared {
12439            cx.notify();
12440        }
12441    }
12442
12443    pub fn show_local_cursors(&self, cx: &WindowContext) -> bool {
12444        (self.read_only(cx) || self.blink_manager.read(cx).visible())
12445            && self.focus_handle.is_focused(cx)
12446    }
12447
12448    pub fn set_show_cursor_when_unfocused(&mut self, is_enabled: bool, cx: &mut ViewContext<Self>) {
12449        self.show_cursor_when_unfocused = is_enabled;
12450        cx.notify();
12451    }
12452
12453    pub fn lsp_store(&self, cx: &AppContext) -> Option<Model<LspStore>> {
12454        self.project
12455            .as_ref()
12456            .map(|project| project.read(cx).lsp_store())
12457    }
12458
12459    fn on_buffer_changed(&mut self, _: Model<MultiBuffer>, cx: &mut ViewContext<Self>) {
12460        cx.notify();
12461    }
12462
12463    fn on_buffer_event(
12464        &mut self,
12465        multibuffer: Model<MultiBuffer>,
12466        event: &multi_buffer::Event,
12467        cx: &mut ViewContext<Self>,
12468    ) {
12469        match event {
12470            multi_buffer::Event::Edited {
12471                singleton_buffer_edited,
12472                edited_buffer: buffer_edited,
12473            } => {
12474                self.scrollbar_marker_state.dirty = true;
12475                self.active_indent_guides_state.dirty = true;
12476                self.refresh_active_diagnostics(cx);
12477                self.refresh_code_actions(cx);
12478                if self.has_active_inline_completion() {
12479                    self.update_visible_inline_completion(cx);
12480                }
12481                if let Some(buffer) = buffer_edited {
12482                    let buffer_id = buffer.read(cx).remote_id();
12483                    if !self.registered_buffers.contains_key(&buffer_id) {
12484                        if let Some(lsp_store) = self.lsp_store(cx) {
12485                            lsp_store.update(cx, |lsp_store, cx| {
12486                                self.registered_buffers.insert(
12487                                    buffer_id,
12488                                    lsp_store.register_buffer_with_language_servers(&buffer, cx),
12489                                );
12490                            })
12491                        }
12492                    }
12493                }
12494                cx.emit(EditorEvent::BufferEdited);
12495                cx.emit(SearchEvent::MatchesInvalidated);
12496                if *singleton_buffer_edited {
12497                    if let Some(project) = &self.project {
12498                        let project = project.read(cx);
12499                        #[allow(clippy::mutable_key_type)]
12500                        let languages_affected = multibuffer
12501                            .read(cx)
12502                            .all_buffers()
12503                            .into_iter()
12504                            .filter_map(|buffer| {
12505                                let buffer = buffer.read(cx);
12506                                let language = buffer.language()?;
12507                                if project.is_local()
12508                                    && project
12509                                        .language_servers_for_local_buffer(buffer, cx)
12510                                        .count()
12511                                        == 0
12512                                {
12513                                    None
12514                                } else {
12515                                    Some(language)
12516                                }
12517                            })
12518                            .cloned()
12519                            .collect::<HashSet<_>>();
12520                        if !languages_affected.is_empty() {
12521                            self.refresh_inlay_hints(
12522                                InlayHintRefreshReason::BufferEdited(languages_affected),
12523                                cx,
12524                            );
12525                        }
12526                    }
12527                }
12528
12529                let Some(project) = &self.project else { return };
12530                let (telemetry, is_via_ssh) = {
12531                    let project = project.read(cx);
12532                    let telemetry = project.client().telemetry().clone();
12533                    let is_via_ssh = project.is_via_ssh();
12534                    (telemetry, is_via_ssh)
12535                };
12536                refresh_linked_ranges(self, cx);
12537                telemetry.log_edit_event("editor", is_via_ssh);
12538            }
12539            multi_buffer::Event::ExcerptsAdded {
12540                buffer,
12541                predecessor,
12542                excerpts,
12543            } => {
12544                self.tasks_update_task = Some(self.refresh_runnables(cx));
12545                let buffer_id = buffer.read(cx).remote_id();
12546                if !self.diff_map.diff_bases.contains_key(&buffer_id) {
12547                    if let Some(project) = &self.project {
12548                        get_unstaged_changes_for_buffers(project, [buffer.clone()], cx);
12549                    }
12550                }
12551                cx.emit(EditorEvent::ExcerptsAdded {
12552                    buffer: buffer.clone(),
12553                    predecessor: *predecessor,
12554                    excerpts: excerpts.clone(),
12555                });
12556                self.refresh_inlay_hints(InlayHintRefreshReason::NewLinesShown, cx);
12557            }
12558            multi_buffer::Event::ExcerptsRemoved { ids } => {
12559                self.refresh_inlay_hints(InlayHintRefreshReason::ExcerptsRemoved(ids.clone()), cx);
12560                let buffer = self.buffer.read(cx);
12561                self.registered_buffers
12562                    .retain(|buffer_id, _| buffer.buffer(*buffer_id).is_some());
12563                cx.emit(EditorEvent::ExcerptsRemoved { ids: ids.clone() })
12564            }
12565            multi_buffer::Event::ExcerptsEdited { ids } => {
12566                cx.emit(EditorEvent::ExcerptsEdited { ids: ids.clone() })
12567            }
12568            multi_buffer::Event::ExcerptsExpanded { ids } => {
12569                self.refresh_inlay_hints(InlayHintRefreshReason::NewLinesShown, cx);
12570                cx.emit(EditorEvent::ExcerptsExpanded { ids: ids.clone() })
12571            }
12572            multi_buffer::Event::Reparsed(buffer_id) => {
12573                self.tasks_update_task = Some(self.refresh_runnables(cx));
12574
12575                cx.emit(EditorEvent::Reparsed(*buffer_id));
12576            }
12577            multi_buffer::Event::LanguageChanged(buffer_id) => {
12578                linked_editing_ranges::refresh_linked_ranges(self, cx);
12579                cx.emit(EditorEvent::Reparsed(*buffer_id));
12580                cx.notify();
12581            }
12582            multi_buffer::Event::DirtyChanged => cx.emit(EditorEvent::DirtyChanged),
12583            multi_buffer::Event::Saved => cx.emit(EditorEvent::Saved),
12584            multi_buffer::Event::FileHandleChanged | multi_buffer::Event::Reloaded => {
12585                cx.emit(EditorEvent::TitleChanged)
12586            }
12587            // multi_buffer::Event::DiffBaseChanged => {
12588            //     self.scrollbar_marker_state.dirty = true;
12589            //     cx.emit(EditorEvent::DiffBaseChanged);
12590            //     cx.notify();
12591            // }
12592            multi_buffer::Event::Closed => cx.emit(EditorEvent::Closed),
12593            multi_buffer::Event::DiagnosticsUpdated => {
12594                self.refresh_active_diagnostics(cx);
12595                self.scrollbar_marker_state.dirty = true;
12596                cx.notify();
12597            }
12598            _ => {}
12599        };
12600    }
12601
12602    fn on_display_map_changed(&mut self, _: Model<DisplayMap>, cx: &mut ViewContext<Self>) {
12603        cx.notify();
12604    }
12605
12606    fn settings_changed(&mut self, cx: &mut ViewContext<Self>) {
12607        self.tasks_update_task = Some(self.refresh_runnables(cx));
12608        self.refresh_inline_completion(true, false, cx);
12609        self.refresh_inlay_hints(
12610            InlayHintRefreshReason::SettingsChange(inlay_hint_settings(
12611                self.selections.newest_anchor().head(),
12612                &self.buffer.read(cx).snapshot(cx),
12613                cx,
12614            )),
12615            cx,
12616        );
12617
12618        let old_cursor_shape = self.cursor_shape;
12619
12620        {
12621            let editor_settings = EditorSettings::get_global(cx);
12622            self.scroll_manager.vertical_scroll_margin = editor_settings.vertical_scroll_margin;
12623            self.show_breadcrumbs = editor_settings.toolbar.breadcrumbs;
12624            self.cursor_shape = editor_settings.cursor_shape.unwrap_or_default();
12625        }
12626
12627        if old_cursor_shape != self.cursor_shape {
12628            cx.emit(EditorEvent::CursorShapeChanged);
12629        }
12630
12631        let project_settings = ProjectSettings::get_global(cx);
12632        self.serialize_dirty_buffers = project_settings.session.restore_unsaved_buffers;
12633
12634        if self.mode == EditorMode::Full {
12635            let inline_blame_enabled = project_settings.git.inline_blame_enabled();
12636            if self.git_blame_inline_enabled != inline_blame_enabled {
12637                self.toggle_git_blame_inline_internal(false, cx);
12638            }
12639        }
12640
12641        cx.notify();
12642    }
12643
12644    pub fn set_searchable(&mut self, searchable: bool) {
12645        self.searchable = searchable;
12646    }
12647
12648    pub fn searchable(&self) -> bool {
12649        self.searchable
12650    }
12651
12652    fn open_proposed_changes_editor(
12653        &mut self,
12654        _: &OpenProposedChangesEditor,
12655        cx: &mut ViewContext<Self>,
12656    ) {
12657        let Some(workspace) = self.workspace() else {
12658            cx.propagate();
12659            return;
12660        };
12661
12662        let selections = self.selections.all::<usize>(cx);
12663        let multi_buffer = self.buffer.read(cx);
12664        let multi_buffer_snapshot = multi_buffer.snapshot(cx);
12665        let mut new_selections_by_buffer = HashMap::default();
12666        for selection in selections {
12667            for (excerpt, range) in
12668                multi_buffer_snapshot.range_to_buffer_ranges(selection.start..selection.end)
12669            {
12670                let mut range = range.to_point(excerpt.buffer());
12671                range.start.column = 0;
12672                range.end.column = excerpt.buffer().line_len(range.end.row);
12673                new_selections_by_buffer
12674                    .entry(multi_buffer.buffer(excerpt.buffer_id()).unwrap())
12675                    .or_insert(Vec::new())
12676                    .push(range)
12677            }
12678        }
12679
12680        let proposed_changes_buffers = new_selections_by_buffer
12681            .into_iter()
12682            .map(|(buffer, ranges)| ProposedChangeLocation { buffer, ranges })
12683            .collect::<Vec<_>>();
12684        let proposed_changes_editor = cx.new_view(|cx| {
12685            ProposedChangesEditor::new(
12686                "Proposed changes",
12687                proposed_changes_buffers,
12688                self.project.clone(),
12689                cx,
12690            )
12691        });
12692
12693        cx.window_context().defer(move |cx| {
12694            workspace.update(cx, |workspace, cx| {
12695                workspace.active_pane().update(cx, |pane, cx| {
12696                    pane.add_item(Box::new(proposed_changes_editor), true, true, None, cx);
12697                });
12698            });
12699        });
12700    }
12701
12702    pub fn open_excerpts_in_split(&mut self, _: &OpenExcerptsSplit, cx: &mut ViewContext<Self>) {
12703        self.open_excerpts_common(None, true, cx)
12704    }
12705
12706    pub fn open_excerpts(&mut self, _: &OpenExcerpts, cx: &mut ViewContext<Self>) {
12707        self.open_excerpts_common(None, false, cx)
12708    }
12709
12710    fn open_excerpts_common(
12711        &mut self,
12712        jump_data: Option<JumpData>,
12713        split: bool,
12714        cx: &mut ViewContext<Self>,
12715    ) {
12716        let Some(workspace) = self.workspace() else {
12717            cx.propagate();
12718            return;
12719        };
12720
12721        if self.buffer.read(cx).is_singleton() {
12722            cx.propagate();
12723            return;
12724        }
12725
12726        let mut new_selections_by_buffer = HashMap::default();
12727        match &jump_data {
12728            Some(JumpData::MultiBufferPoint {
12729                excerpt_id,
12730                position,
12731                anchor,
12732                line_offset_from_top,
12733            }) => {
12734                let multi_buffer_snapshot = self.buffer.read(cx).snapshot(cx);
12735                if let Some(buffer) = multi_buffer_snapshot
12736                    .buffer_id_for_excerpt(*excerpt_id)
12737                    .and_then(|buffer_id| self.buffer.read(cx).buffer(buffer_id))
12738                {
12739                    let buffer_snapshot = buffer.read(cx).snapshot();
12740                    let jump_to_point = if buffer_snapshot.can_resolve(anchor) {
12741                        language::ToPoint::to_point(anchor, &buffer_snapshot)
12742                    } else {
12743                        buffer_snapshot.clip_point(*position, Bias::Left)
12744                    };
12745                    let jump_to_offset = buffer_snapshot.point_to_offset(jump_to_point);
12746                    new_selections_by_buffer.insert(
12747                        buffer,
12748                        (
12749                            vec![jump_to_offset..jump_to_offset],
12750                            Some(*line_offset_from_top),
12751                        ),
12752                    );
12753                }
12754            }
12755            Some(JumpData::MultiBufferRow {
12756                row,
12757                line_offset_from_top,
12758            }) => {
12759                let point = MultiBufferPoint::new(row.0, 0);
12760                if let Some((buffer, buffer_point, _)) =
12761                    self.buffer.read(cx).point_to_buffer_point(point, cx)
12762                {
12763                    let buffer_offset = buffer.read(cx).point_to_offset(buffer_point);
12764                    new_selections_by_buffer
12765                        .entry(buffer)
12766                        .or_insert((Vec::new(), Some(*line_offset_from_top)))
12767                        .0
12768                        .push(buffer_offset..buffer_offset)
12769                }
12770            }
12771            None => {
12772                let selections = self.selections.all::<usize>(cx);
12773                let multi_buffer = self.buffer.read(cx);
12774                for selection in selections {
12775                    for (excerpt, mut range) in multi_buffer
12776                        .snapshot(cx)
12777                        .range_to_buffer_ranges(selection.range())
12778                    {
12779                        // When editing branch buffers, jump to the corresponding location
12780                        // in their base buffer.
12781                        let mut buffer_handle = multi_buffer.buffer(excerpt.buffer_id()).unwrap();
12782                        let buffer = buffer_handle.read(cx);
12783                        if let Some(base_buffer) = buffer.base_buffer() {
12784                            range = buffer.range_to_version(range, &base_buffer.read(cx).version());
12785                            buffer_handle = base_buffer;
12786                        }
12787
12788                        if selection.reversed {
12789                            mem::swap(&mut range.start, &mut range.end);
12790                        }
12791                        new_selections_by_buffer
12792                            .entry(buffer_handle)
12793                            .or_insert((Vec::new(), None))
12794                            .0
12795                            .push(range)
12796                    }
12797                }
12798            }
12799        }
12800
12801        if new_selections_by_buffer.is_empty() {
12802            return;
12803        }
12804
12805        // We defer the pane interaction because we ourselves are a workspace item
12806        // and activating a new item causes the pane to call a method on us reentrantly,
12807        // which panics if we're on the stack.
12808        cx.window_context().defer(move |cx| {
12809            workspace.update(cx, |workspace, cx| {
12810                let pane = if split {
12811                    workspace.adjacent_pane(cx)
12812                } else {
12813                    workspace.active_pane().clone()
12814                };
12815
12816                for (buffer, (ranges, scroll_offset)) in new_selections_by_buffer {
12817                    let editor = buffer
12818                        .read(cx)
12819                        .file()
12820                        .is_none()
12821                        .then(|| {
12822                            // Handle file-less buffers separately: those are not really the project items, so won't have a project path or entity id,
12823                            // so `workspace.open_project_item` will never find them, always opening a new editor.
12824                            // Instead, we try to activate the existing editor in the pane first.
12825                            let (editor, pane_item_index) =
12826                                pane.read(cx).items().enumerate().find_map(|(i, item)| {
12827                                    let editor = item.downcast::<Editor>()?;
12828                                    let singleton_buffer =
12829                                        editor.read(cx).buffer().read(cx).as_singleton()?;
12830                                    if singleton_buffer == buffer {
12831                                        Some((editor, i))
12832                                    } else {
12833                                        None
12834                                    }
12835                                })?;
12836                            pane.update(cx, |pane, cx| {
12837                                pane.activate_item(pane_item_index, true, true, cx)
12838                            });
12839                            Some(editor)
12840                        })
12841                        .flatten()
12842                        .unwrap_or_else(|| {
12843                            workspace.open_project_item::<Self>(
12844                                pane.clone(),
12845                                buffer,
12846                                true,
12847                                true,
12848                                cx,
12849                            )
12850                        });
12851
12852                    editor.update(cx, |editor, cx| {
12853                        let autoscroll = match scroll_offset {
12854                            Some(scroll_offset) => Autoscroll::top_relative(scroll_offset as usize),
12855                            None => Autoscroll::newest(),
12856                        };
12857                        let nav_history = editor.nav_history.take();
12858                        editor.change_selections(Some(autoscroll), cx, |s| {
12859                            s.select_ranges(ranges);
12860                        });
12861                        editor.nav_history = nav_history;
12862                    });
12863                }
12864            })
12865        });
12866    }
12867
12868    fn marked_text_ranges(&self, cx: &AppContext) -> Option<Vec<Range<OffsetUtf16>>> {
12869        let snapshot = self.buffer.read(cx).read(cx);
12870        let (_, ranges) = self.text_highlights::<InputComposition>(cx)?;
12871        Some(
12872            ranges
12873                .iter()
12874                .map(move |range| {
12875                    range.start.to_offset_utf16(&snapshot)..range.end.to_offset_utf16(&snapshot)
12876                })
12877                .collect(),
12878        )
12879    }
12880
12881    fn selection_replacement_ranges(
12882        &self,
12883        range: Range<OffsetUtf16>,
12884        cx: &mut AppContext,
12885    ) -> Vec<Range<OffsetUtf16>> {
12886        let selections = self.selections.all::<OffsetUtf16>(cx);
12887        let newest_selection = selections
12888            .iter()
12889            .max_by_key(|selection| selection.id)
12890            .unwrap();
12891        let start_delta = range.start.0 as isize - newest_selection.start.0 as isize;
12892        let end_delta = range.end.0 as isize - newest_selection.end.0 as isize;
12893        let snapshot = self.buffer.read(cx).read(cx);
12894        selections
12895            .into_iter()
12896            .map(|mut selection| {
12897                selection.start.0 =
12898                    (selection.start.0 as isize).saturating_add(start_delta) as usize;
12899                selection.end.0 = (selection.end.0 as isize).saturating_add(end_delta) as usize;
12900                snapshot.clip_offset_utf16(selection.start, Bias::Left)
12901                    ..snapshot.clip_offset_utf16(selection.end, Bias::Right)
12902            })
12903            .collect()
12904    }
12905
12906    fn report_editor_event(
12907        &self,
12908        event_type: &'static str,
12909        file_extension: Option<String>,
12910        cx: &AppContext,
12911    ) {
12912        if cfg!(any(test, feature = "test-support")) {
12913            return;
12914        }
12915
12916        let Some(project) = &self.project else { return };
12917
12918        // If None, we are in a file without an extension
12919        let file = self
12920            .buffer
12921            .read(cx)
12922            .as_singleton()
12923            .and_then(|b| b.read(cx).file());
12924        let file_extension = file_extension.or(file
12925            .as_ref()
12926            .and_then(|file| Path::new(file.file_name(cx)).extension())
12927            .and_then(|e| e.to_str())
12928            .map(|a| a.to_string()));
12929
12930        let vim_mode = cx
12931            .global::<SettingsStore>()
12932            .raw_user_settings()
12933            .get("vim_mode")
12934            == Some(&serde_json::Value::Bool(true));
12935
12936        let copilot_enabled = all_language_settings(file, cx).inline_completions.provider
12937            == language::language_settings::InlineCompletionProvider::Copilot;
12938        let copilot_enabled_for_language = self
12939            .buffer
12940            .read(cx)
12941            .settings_at(0, cx)
12942            .show_inline_completions;
12943
12944        let project = project.read(cx);
12945        telemetry::event!(
12946            event_type,
12947            file_extension,
12948            vim_mode,
12949            copilot_enabled,
12950            copilot_enabled_for_language,
12951            is_via_ssh = project.is_via_ssh(),
12952        );
12953    }
12954
12955    /// Copy the highlighted chunks to the clipboard as JSON. The format is an array of lines,
12956    /// with each line being an array of {text, highlight} objects.
12957    fn copy_highlight_json(&mut self, _: &CopyHighlightJson, cx: &mut ViewContext<Self>) {
12958        let Some(buffer) = self.buffer.read(cx).as_singleton() else {
12959            return;
12960        };
12961
12962        #[derive(Serialize)]
12963        struct Chunk<'a> {
12964            text: String,
12965            highlight: Option<&'a str>,
12966        }
12967
12968        let snapshot = buffer.read(cx).snapshot();
12969        let range = self
12970            .selected_text_range(false, cx)
12971            .and_then(|selection| {
12972                if selection.range.is_empty() {
12973                    None
12974                } else {
12975                    Some(selection.range)
12976                }
12977            })
12978            .unwrap_or_else(|| 0..snapshot.len());
12979
12980        let chunks = snapshot.chunks(range, true);
12981        let mut lines = Vec::new();
12982        let mut line: VecDeque<Chunk> = VecDeque::new();
12983
12984        let Some(style) = self.style.as_ref() else {
12985            return;
12986        };
12987
12988        for chunk in chunks {
12989            let highlight = chunk
12990                .syntax_highlight_id
12991                .and_then(|id| id.name(&style.syntax));
12992            let mut chunk_lines = chunk.text.split('\n').peekable();
12993            while let Some(text) = chunk_lines.next() {
12994                let mut merged_with_last_token = false;
12995                if let Some(last_token) = line.back_mut() {
12996                    if last_token.highlight == highlight {
12997                        last_token.text.push_str(text);
12998                        merged_with_last_token = true;
12999                    }
13000                }
13001
13002                if !merged_with_last_token {
13003                    line.push_back(Chunk {
13004                        text: text.into(),
13005                        highlight,
13006                    });
13007                }
13008
13009                if chunk_lines.peek().is_some() {
13010                    if line.len() > 1 && line.front().unwrap().text.is_empty() {
13011                        line.pop_front();
13012                    }
13013                    if line.len() > 1 && line.back().unwrap().text.is_empty() {
13014                        line.pop_back();
13015                    }
13016
13017                    lines.push(mem::take(&mut line));
13018                }
13019            }
13020        }
13021
13022        let Some(lines) = serde_json::to_string_pretty(&lines).log_err() else {
13023            return;
13024        };
13025        cx.write_to_clipboard(ClipboardItem::new_string(lines));
13026    }
13027
13028    pub fn open_context_menu(&mut self, _: &OpenContextMenu, cx: &mut ViewContext<Self>) {
13029        self.request_autoscroll(Autoscroll::newest(), cx);
13030        let position = self.selections.newest_display(cx).start;
13031        mouse_context_menu::deploy_context_menu(self, None, position, cx);
13032    }
13033
13034    pub fn inlay_hint_cache(&self) -> &InlayHintCache {
13035        &self.inlay_hint_cache
13036    }
13037
13038    pub fn replay_insert_event(
13039        &mut self,
13040        text: &str,
13041        relative_utf16_range: Option<Range<isize>>,
13042        cx: &mut ViewContext<Self>,
13043    ) {
13044        if !self.input_enabled {
13045            cx.emit(EditorEvent::InputIgnored { text: text.into() });
13046            return;
13047        }
13048        if let Some(relative_utf16_range) = relative_utf16_range {
13049            let selections = self.selections.all::<OffsetUtf16>(cx);
13050            self.change_selections(None, cx, |s| {
13051                let new_ranges = selections.into_iter().map(|range| {
13052                    let start = OffsetUtf16(
13053                        range
13054                            .head()
13055                            .0
13056                            .saturating_add_signed(relative_utf16_range.start),
13057                    );
13058                    let end = OffsetUtf16(
13059                        range
13060                            .head()
13061                            .0
13062                            .saturating_add_signed(relative_utf16_range.end),
13063                    );
13064                    start..end
13065                });
13066                s.select_ranges(new_ranges);
13067            });
13068        }
13069
13070        self.handle_input(text, cx);
13071    }
13072
13073    pub fn supports_inlay_hints(&self, cx: &AppContext) -> bool {
13074        let Some(provider) = self.semantics_provider.as_ref() else {
13075            return false;
13076        };
13077
13078        let mut supports = false;
13079        self.buffer().read(cx).for_each_buffer(|buffer| {
13080            supports |= provider.supports_inlay_hints(buffer, cx);
13081        });
13082        supports
13083    }
13084
13085    pub fn focus(&self, cx: &mut WindowContext) {
13086        cx.focus(&self.focus_handle)
13087    }
13088
13089    pub fn is_focused(&self, cx: &WindowContext) -> bool {
13090        self.focus_handle.is_focused(cx)
13091    }
13092
13093    fn handle_focus(&mut self, cx: &mut ViewContext<Self>) {
13094        cx.emit(EditorEvent::Focused);
13095
13096        if let Some(descendant) = self
13097            .last_focused_descendant
13098            .take()
13099            .and_then(|descendant| descendant.upgrade())
13100        {
13101            cx.focus(&descendant);
13102        } else {
13103            if let Some(blame) = self.blame.as_ref() {
13104                blame.update(cx, GitBlame::focus)
13105            }
13106
13107            self.blink_manager.update(cx, BlinkManager::enable);
13108            self.show_cursor_names(cx);
13109            self.buffer.update(cx, |buffer, cx| {
13110                buffer.finalize_last_transaction(cx);
13111                if self.leader_peer_id.is_none() {
13112                    buffer.set_active_selections(
13113                        &self.selections.disjoint_anchors(),
13114                        self.selections.line_mode,
13115                        self.cursor_shape,
13116                        cx,
13117                    );
13118                }
13119            });
13120        }
13121    }
13122
13123    fn handle_focus_in(&mut self, cx: &mut ViewContext<Self>) {
13124        cx.emit(EditorEvent::FocusedIn)
13125    }
13126
13127    fn handle_focus_out(&mut self, event: FocusOutEvent, _cx: &mut ViewContext<Self>) {
13128        if event.blurred != self.focus_handle {
13129            self.last_focused_descendant = Some(event.blurred);
13130        }
13131    }
13132
13133    pub fn handle_blur(&mut self, cx: &mut ViewContext<Self>) {
13134        self.blink_manager.update(cx, BlinkManager::disable);
13135        self.buffer
13136            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
13137
13138        if let Some(blame) = self.blame.as_ref() {
13139            blame.update(cx, GitBlame::blur)
13140        }
13141        if !self.hover_state.focused(cx) {
13142            hide_hover(self, cx);
13143        }
13144
13145        self.hide_context_menu(cx);
13146        cx.emit(EditorEvent::Blurred);
13147        cx.notify();
13148    }
13149
13150    pub fn register_action<A: Action>(
13151        &mut self,
13152        listener: impl Fn(&A, &mut WindowContext) + 'static,
13153    ) -> Subscription {
13154        let id = self.next_editor_action_id.post_inc();
13155        let listener = Arc::new(listener);
13156        self.editor_actions.borrow_mut().insert(
13157            id,
13158            Box::new(move |cx| {
13159                let cx = cx.window_context();
13160                let listener = listener.clone();
13161                cx.on_action(TypeId::of::<A>(), move |action, phase, cx| {
13162                    let action = action.downcast_ref().unwrap();
13163                    if phase == DispatchPhase::Bubble {
13164                        listener(action, cx)
13165                    }
13166                })
13167            }),
13168        );
13169
13170        let editor_actions = self.editor_actions.clone();
13171        Subscription::new(move || {
13172            editor_actions.borrow_mut().remove(&id);
13173        })
13174    }
13175
13176    pub fn file_header_size(&self) -> u32 {
13177        FILE_HEADER_HEIGHT
13178    }
13179
13180    pub fn revert(
13181        &mut self,
13182        revert_changes: HashMap<BufferId, Vec<(Range<text::Anchor>, Rope)>>,
13183        cx: &mut ViewContext<Self>,
13184    ) {
13185        self.buffer().update(cx, |multi_buffer, cx| {
13186            for (buffer_id, changes) in revert_changes {
13187                if let Some(buffer) = multi_buffer.buffer(buffer_id) {
13188                    buffer.update(cx, |buffer, cx| {
13189                        buffer.edit(
13190                            changes.into_iter().map(|(range, text)| {
13191                                (range, text.to_string().map(Arc::<str>::from))
13192                            }),
13193                            None,
13194                            cx,
13195                        );
13196                    });
13197                }
13198            }
13199        });
13200        self.change_selections(None, cx, |selections| selections.refresh());
13201    }
13202
13203    pub fn to_pixel_point(
13204        &self,
13205        source: multi_buffer::Anchor,
13206        editor_snapshot: &EditorSnapshot,
13207        cx: &mut ViewContext<Self>,
13208    ) -> Option<gpui::Point<Pixels>> {
13209        let source_point = source.to_display_point(editor_snapshot);
13210        self.display_to_pixel_point(source_point, editor_snapshot, cx)
13211    }
13212
13213    pub fn display_to_pixel_point(
13214        &self,
13215        source: DisplayPoint,
13216        editor_snapshot: &EditorSnapshot,
13217        cx: &WindowContext,
13218    ) -> Option<gpui::Point<Pixels>> {
13219        let line_height = self.style()?.text.line_height_in_pixels(cx.rem_size());
13220        let text_layout_details = self.text_layout_details(cx);
13221        let scroll_top = text_layout_details
13222            .scroll_anchor
13223            .scroll_position(editor_snapshot)
13224            .y;
13225
13226        if source.row().as_f32() < scroll_top.floor() {
13227            return None;
13228        }
13229        let source_x = editor_snapshot.x_for_display_point(source, &text_layout_details);
13230        let source_y = line_height * (source.row().as_f32() - scroll_top);
13231        Some(gpui::Point::new(source_x, source_y))
13232    }
13233
13234    pub fn has_active_completions_menu(&self) -> bool {
13235        self.context_menu.borrow().as_ref().map_or(false, |menu| {
13236            menu.visible() && matches!(menu, CodeContextMenu::Completions(_))
13237        })
13238    }
13239
13240    pub fn register_addon<T: Addon>(&mut self, instance: T) {
13241        self.addons
13242            .insert(std::any::TypeId::of::<T>(), Box::new(instance));
13243    }
13244
13245    pub fn unregister_addon<T: Addon>(&mut self) {
13246        self.addons.remove(&std::any::TypeId::of::<T>());
13247    }
13248
13249    pub fn addon<T: Addon>(&self) -> Option<&T> {
13250        let type_id = std::any::TypeId::of::<T>();
13251        self.addons
13252            .get(&type_id)
13253            .and_then(|item| item.to_any().downcast_ref::<T>())
13254    }
13255
13256    pub fn add_change_set(
13257        &mut self,
13258        change_set: Model<BufferChangeSet>,
13259        cx: &mut ViewContext<Self>,
13260    ) {
13261        self.diff_map.add_change_set(change_set, cx);
13262    }
13263
13264    fn character_size(&self, cx: &mut ViewContext<Self>) -> gpui::Point<Pixels> {
13265        let text_layout_details = self.text_layout_details(cx);
13266        let style = &text_layout_details.editor_style;
13267        let font_id = cx.text_system().resolve_font(&style.text.font());
13268        let font_size = style.text.font_size.to_pixels(cx.rem_size());
13269        let line_height = style.text.line_height_in_pixels(cx.rem_size());
13270
13271        let em_width = cx
13272            .text_system()
13273            .typographic_bounds(font_id, font_size, 'm')
13274            .unwrap()
13275            .size
13276            .width;
13277
13278        gpui::Point::new(em_width, line_height)
13279    }
13280}
13281
13282fn get_unstaged_changes_for_buffers(
13283    project: &Model<Project>,
13284    buffers: impl IntoIterator<Item = Model<Buffer>>,
13285    cx: &mut ViewContext<Editor>,
13286) {
13287    let mut tasks = Vec::new();
13288    project.update(cx, |project, cx| {
13289        for buffer in buffers {
13290            tasks.push(project.open_unstaged_changes(buffer.clone(), cx))
13291        }
13292    });
13293    cx.spawn(|this, mut cx| async move {
13294        let change_sets = futures::future::join_all(tasks).await;
13295        this.update(&mut cx, |this, cx| {
13296            for change_set in change_sets {
13297                if let Some(change_set) = change_set.log_err() {
13298                    this.diff_map.add_change_set(change_set, cx);
13299                }
13300            }
13301        })
13302        .ok();
13303    })
13304    .detach();
13305}
13306
13307fn char_len_with_expanded_tabs(offset: usize, text: &str, tab_size: NonZeroU32) -> usize {
13308    let tab_size = tab_size.get() as usize;
13309    let mut width = offset;
13310
13311    for ch in text.chars() {
13312        width += if ch == '\t' {
13313            tab_size - (width % tab_size)
13314        } else {
13315            1
13316        };
13317    }
13318
13319    width - offset
13320}
13321
13322#[cfg(test)]
13323mod tests {
13324    use super::*;
13325
13326    #[test]
13327    fn test_string_size_with_expanded_tabs() {
13328        let nz = |val| NonZeroU32::new(val).unwrap();
13329        assert_eq!(char_len_with_expanded_tabs(0, "", nz(4)), 0);
13330        assert_eq!(char_len_with_expanded_tabs(0, "hello", nz(4)), 5);
13331        assert_eq!(char_len_with_expanded_tabs(0, "\thello", nz(4)), 9);
13332        assert_eq!(char_len_with_expanded_tabs(0, "abc\tab", nz(4)), 6);
13333        assert_eq!(char_len_with_expanded_tabs(0, "hello\t", nz(4)), 8);
13334        assert_eq!(char_len_with_expanded_tabs(0, "\t\t", nz(8)), 16);
13335        assert_eq!(char_len_with_expanded_tabs(0, "x\t", nz(8)), 8);
13336        assert_eq!(char_len_with_expanded_tabs(7, "x\t", nz(8)), 9);
13337    }
13338}
13339
13340/// Tokenizes a string into runs of text that should stick together, or that is whitespace.
13341struct WordBreakingTokenizer<'a> {
13342    input: &'a str,
13343}
13344
13345impl<'a> WordBreakingTokenizer<'a> {
13346    fn new(input: &'a str) -> Self {
13347        Self { input }
13348    }
13349}
13350
13351fn is_char_ideographic(ch: char) -> bool {
13352    use unicode_script::Script::*;
13353    use unicode_script::UnicodeScript;
13354    matches!(ch.script(), Han | Tangut | Yi)
13355}
13356
13357fn is_grapheme_ideographic(text: &str) -> bool {
13358    text.chars().any(is_char_ideographic)
13359}
13360
13361fn is_grapheme_whitespace(text: &str) -> bool {
13362    text.chars().any(|x| x.is_whitespace())
13363}
13364
13365fn should_stay_with_preceding_ideograph(text: &str) -> bool {
13366    text.chars().next().map_or(false, |ch| {
13367        matches!(ch, '。' | '、' | ',' | '?' | '!' | ':' | ';' | '…')
13368    })
13369}
13370
13371#[derive(PartialEq, Eq, Debug, Clone, Copy)]
13372struct WordBreakToken<'a> {
13373    token: &'a str,
13374    grapheme_len: usize,
13375    is_whitespace: bool,
13376}
13377
13378impl<'a> Iterator for WordBreakingTokenizer<'a> {
13379    /// Yields a span, the count of graphemes in the token, and whether it was
13380    /// whitespace. Note that it also breaks at word boundaries.
13381    type Item = WordBreakToken<'a>;
13382
13383    fn next(&mut self) -> Option<Self::Item> {
13384        use unicode_segmentation::UnicodeSegmentation;
13385        if self.input.is_empty() {
13386            return None;
13387        }
13388
13389        let mut iter = self.input.graphemes(true).peekable();
13390        let mut offset = 0;
13391        let mut graphemes = 0;
13392        if let Some(first_grapheme) = iter.next() {
13393            let is_whitespace = is_grapheme_whitespace(first_grapheme);
13394            offset += first_grapheme.len();
13395            graphemes += 1;
13396            if is_grapheme_ideographic(first_grapheme) && !is_whitespace {
13397                if let Some(grapheme) = iter.peek().copied() {
13398                    if should_stay_with_preceding_ideograph(grapheme) {
13399                        offset += grapheme.len();
13400                        graphemes += 1;
13401                    }
13402                }
13403            } else {
13404                let mut words = self.input[offset..].split_word_bound_indices().peekable();
13405                let mut next_word_bound = words.peek().copied();
13406                if next_word_bound.map_or(false, |(i, _)| i == 0) {
13407                    next_word_bound = words.next();
13408                }
13409                while let Some(grapheme) = iter.peek().copied() {
13410                    if next_word_bound.map_or(false, |(i, _)| i == offset) {
13411                        break;
13412                    };
13413                    if is_grapheme_whitespace(grapheme) != is_whitespace {
13414                        break;
13415                    };
13416                    offset += grapheme.len();
13417                    graphemes += 1;
13418                    iter.next();
13419                }
13420            }
13421            let token = &self.input[..offset];
13422            self.input = &self.input[offset..];
13423            if is_whitespace {
13424                Some(WordBreakToken {
13425                    token: " ",
13426                    grapheme_len: 1,
13427                    is_whitespace: true,
13428                })
13429            } else {
13430                Some(WordBreakToken {
13431                    token,
13432                    grapheme_len: graphemes,
13433                    is_whitespace: false,
13434                })
13435            }
13436        } else {
13437            None
13438        }
13439    }
13440}
13441
13442#[test]
13443fn test_word_breaking_tokenizer() {
13444    let tests: &[(&str, &[(&str, usize, bool)])] = &[
13445        ("", &[]),
13446        ("  ", &[(" ", 1, true)]),
13447        ("Ʒ", &[("Ʒ", 1, false)]),
13448        ("Ǽ", &[("Ǽ", 1, false)]),
13449        ("", &[("", 1, false)]),
13450        ("⋑⋑", &[("⋑⋑", 2, false)]),
13451        (
13452            "原理,进而",
13453            &[
13454                ("", 1, false),
13455                ("理,", 2, false),
13456                ("", 1, false),
13457                ("", 1, false),
13458            ],
13459        ),
13460        (
13461            "hello world",
13462            &[("hello", 5, false), (" ", 1, true), ("world", 5, false)],
13463        ),
13464        (
13465            "hello, world",
13466            &[("hello,", 6, false), (" ", 1, true), ("world", 5, false)],
13467        ),
13468        (
13469            "  hello world",
13470            &[
13471                (" ", 1, true),
13472                ("hello", 5, false),
13473                (" ", 1, true),
13474                ("world", 5, false),
13475            ],
13476        ),
13477        (
13478            "这是什么 \n 钢笔",
13479            &[
13480                ("", 1, false),
13481                ("", 1, false),
13482                ("", 1, false),
13483                ("", 1, false),
13484                (" ", 1, true),
13485                ("", 1, false),
13486                ("", 1, false),
13487            ],
13488        ),
13489        (" mutton", &[(" ", 1, true), ("mutton", 6, false)]),
13490    ];
13491
13492    for (input, result) in tests {
13493        assert_eq!(
13494            WordBreakingTokenizer::new(input).collect::<Vec<_>>(),
13495            result
13496                .iter()
13497                .copied()
13498                .map(|(token, grapheme_len, is_whitespace)| WordBreakToken {
13499                    token,
13500                    grapheme_len,
13501                    is_whitespace,
13502                })
13503                .collect::<Vec<_>>()
13504        );
13505    }
13506}
13507
13508fn wrap_with_prefix(
13509    line_prefix: String,
13510    unwrapped_text: String,
13511    wrap_column: usize,
13512    tab_size: NonZeroU32,
13513) -> String {
13514    let line_prefix_len = char_len_with_expanded_tabs(0, &line_prefix, tab_size);
13515    let mut wrapped_text = String::new();
13516    let mut current_line = line_prefix.clone();
13517
13518    let tokenizer = WordBreakingTokenizer::new(&unwrapped_text);
13519    let mut current_line_len = line_prefix_len;
13520    for WordBreakToken {
13521        token,
13522        grapheme_len,
13523        is_whitespace,
13524    } in tokenizer
13525    {
13526        if current_line_len + grapheme_len > wrap_column && current_line_len != line_prefix_len {
13527            wrapped_text.push_str(current_line.trim_end());
13528            wrapped_text.push('\n');
13529            current_line.truncate(line_prefix.len());
13530            current_line_len = line_prefix_len;
13531            if !is_whitespace {
13532                current_line.push_str(token);
13533                current_line_len += grapheme_len;
13534            }
13535        } else if !is_whitespace {
13536            current_line.push_str(token);
13537            current_line_len += grapheme_len;
13538        } else if current_line_len != line_prefix_len {
13539            current_line.push(' ');
13540            current_line_len += 1;
13541        }
13542    }
13543
13544    if !current_line.is_empty() {
13545        wrapped_text.push_str(&current_line);
13546    }
13547    wrapped_text
13548}
13549
13550#[test]
13551fn test_wrap_with_prefix() {
13552    assert_eq!(
13553        wrap_with_prefix(
13554            "# ".to_string(),
13555            "abcdefg".to_string(),
13556            4,
13557            NonZeroU32::new(4).unwrap()
13558        ),
13559        "# abcdefg"
13560    );
13561    assert_eq!(
13562        wrap_with_prefix(
13563            "".to_string(),
13564            "\thello world".to_string(),
13565            8,
13566            NonZeroU32::new(4).unwrap()
13567        ),
13568        "hello\nworld"
13569    );
13570    assert_eq!(
13571        wrap_with_prefix(
13572            "// ".to_string(),
13573            "xx \nyy zz aa bb cc".to_string(),
13574            12,
13575            NonZeroU32::new(4).unwrap()
13576        ),
13577        "// xx yy zz\n// aa bb cc"
13578    );
13579    assert_eq!(
13580        wrap_with_prefix(
13581            String::new(),
13582            "这是什么 \n 钢笔".to_string(),
13583            3,
13584            NonZeroU32::new(4).unwrap()
13585        ),
13586        "这是什\n么 钢\n"
13587    );
13588}
13589
13590fn hunks_for_selections(
13591    snapshot: &EditorSnapshot,
13592    selections: &[Selection<Point>],
13593) -> Vec<MultiBufferDiffHunk> {
13594    hunks_for_ranges(
13595        selections.iter().map(|selection| selection.range()),
13596        snapshot,
13597    )
13598}
13599
13600pub fn hunks_for_ranges(
13601    ranges: impl Iterator<Item = Range<Point>>,
13602    snapshot: &EditorSnapshot,
13603) -> Vec<MultiBufferDiffHunk> {
13604    let mut hunks = Vec::new();
13605    let mut processed_buffer_rows: HashMap<BufferId, HashSet<Range<text::Anchor>>> =
13606        HashMap::default();
13607    for query_range in ranges {
13608        let query_rows =
13609            MultiBufferRow(query_range.start.row)..MultiBufferRow(query_range.end.row + 1);
13610        for hunk in snapshot.diff_map.diff_hunks_in_range(
13611            Point::new(query_rows.start.0, 0)..Point::new(query_rows.end.0, 0),
13612            &snapshot.buffer_snapshot,
13613        ) {
13614            // Deleted hunk is an empty row range, no caret can be placed there and Zed allows to revert it
13615            // when the caret is just above or just below the deleted hunk.
13616            let allow_adjacent = hunk_status(&hunk) == DiffHunkStatus::Removed;
13617            let related_to_selection = if allow_adjacent {
13618                hunk.row_range.overlaps(&query_rows)
13619                    || hunk.row_range.start == query_rows.end
13620                    || hunk.row_range.end == query_rows.start
13621            } else {
13622                hunk.row_range.overlaps(&query_rows)
13623            };
13624            if related_to_selection {
13625                if !processed_buffer_rows
13626                    .entry(hunk.buffer_id)
13627                    .or_default()
13628                    .insert(hunk.buffer_range.start..hunk.buffer_range.end)
13629                {
13630                    continue;
13631                }
13632                hunks.push(hunk);
13633            }
13634        }
13635    }
13636
13637    hunks
13638}
13639
13640pub trait CollaborationHub {
13641    fn collaborators<'a>(&self, cx: &'a AppContext) -> &'a HashMap<PeerId, Collaborator>;
13642    fn user_participant_indices<'a>(
13643        &self,
13644        cx: &'a AppContext,
13645    ) -> &'a HashMap<u64, ParticipantIndex>;
13646    fn user_names(&self, cx: &AppContext) -> HashMap<u64, SharedString>;
13647}
13648
13649impl CollaborationHub for Model<Project> {
13650    fn collaborators<'a>(&self, cx: &'a AppContext) -> &'a HashMap<PeerId, Collaborator> {
13651        self.read(cx).collaborators()
13652    }
13653
13654    fn user_participant_indices<'a>(
13655        &self,
13656        cx: &'a AppContext,
13657    ) -> &'a HashMap<u64, ParticipantIndex> {
13658        self.read(cx).user_store().read(cx).participant_indices()
13659    }
13660
13661    fn user_names(&self, cx: &AppContext) -> HashMap<u64, SharedString> {
13662        let this = self.read(cx);
13663        let user_ids = this.collaborators().values().map(|c| c.user_id);
13664        this.user_store().read_with(cx, |user_store, cx| {
13665            user_store.participant_names(user_ids, cx)
13666        })
13667    }
13668}
13669
13670pub trait SemanticsProvider {
13671    fn hover(
13672        &self,
13673        buffer: &Model<Buffer>,
13674        position: text::Anchor,
13675        cx: &mut AppContext,
13676    ) -> Option<Task<Vec<project::Hover>>>;
13677
13678    fn inlay_hints(
13679        &self,
13680        buffer_handle: Model<Buffer>,
13681        range: Range<text::Anchor>,
13682        cx: &mut AppContext,
13683    ) -> Option<Task<anyhow::Result<Vec<InlayHint>>>>;
13684
13685    fn resolve_inlay_hint(
13686        &self,
13687        hint: InlayHint,
13688        buffer_handle: Model<Buffer>,
13689        server_id: LanguageServerId,
13690        cx: &mut AppContext,
13691    ) -> Option<Task<anyhow::Result<InlayHint>>>;
13692
13693    fn supports_inlay_hints(&self, buffer: &Model<Buffer>, cx: &AppContext) -> bool;
13694
13695    fn document_highlights(
13696        &self,
13697        buffer: &Model<Buffer>,
13698        position: text::Anchor,
13699        cx: &mut AppContext,
13700    ) -> Option<Task<Result<Vec<DocumentHighlight>>>>;
13701
13702    fn definitions(
13703        &self,
13704        buffer: &Model<Buffer>,
13705        position: text::Anchor,
13706        kind: GotoDefinitionKind,
13707        cx: &mut AppContext,
13708    ) -> Option<Task<Result<Vec<LocationLink>>>>;
13709
13710    fn range_for_rename(
13711        &self,
13712        buffer: &Model<Buffer>,
13713        position: text::Anchor,
13714        cx: &mut AppContext,
13715    ) -> Option<Task<Result<Option<Range<text::Anchor>>>>>;
13716
13717    fn perform_rename(
13718        &self,
13719        buffer: &Model<Buffer>,
13720        position: text::Anchor,
13721        new_name: String,
13722        cx: &mut AppContext,
13723    ) -> Option<Task<Result<ProjectTransaction>>>;
13724}
13725
13726pub trait CompletionProvider {
13727    fn completions(
13728        &self,
13729        buffer: &Model<Buffer>,
13730        buffer_position: text::Anchor,
13731        trigger: CompletionContext,
13732        cx: &mut ViewContext<Editor>,
13733    ) -> Task<Result<Vec<Completion>>>;
13734
13735    fn resolve_completions(
13736        &self,
13737        buffer: Model<Buffer>,
13738        completion_indices: Vec<usize>,
13739        completions: Rc<RefCell<Box<[Completion]>>>,
13740        cx: &mut ViewContext<Editor>,
13741    ) -> Task<Result<bool>>;
13742
13743    fn apply_additional_edits_for_completion(
13744        &self,
13745        _buffer: Model<Buffer>,
13746        _completions: Rc<RefCell<Box<[Completion]>>>,
13747        _completion_index: usize,
13748        _push_to_history: bool,
13749        _cx: &mut ViewContext<Editor>,
13750    ) -> Task<Result<Option<language::Transaction>>> {
13751        Task::ready(Ok(None))
13752    }
13753
13754    fn is_completion_trigger(
13755        &self,
13756        buffer: &Model<Buffer>,
13757        position: language::Anchor,
13758        text: &str,
13759        trigger_in_words: bool,
13760        cx: &mut ViewContext<Editor>,
13761    ) -> bool;
13762
13763    fn sort_completions(&self) -> bool {
13764        true
13765    }
13766}
13767
13768pub trait CodeActionProvider {
13769    fn id(&self) -> Arc<str>;
13770
13771    fn code_actions(
13772        &self,
13773        buffer: &Model<Buffer>,
13774        range: Range<text::Anchor>,
13775        cx: &mut WindowContext,
13776    ) -> Task<Result<Vec<CodeAction>>>;
13777
13778    fn apply_code_action(
13779        &self,
13780        buffer_handle: Model<Buffer>,
13781        action: CodeAction,
13782        excerpt_id: ExcerptId,
13783        push_to_history: bool,
13784        cx: &mut WindowContext,
13785    ) -> Task<Result<ProjectTransaction>>;
13786}
13787
13788impl CodeActionProvider for Model<Project> {
13789    fn id(&self) -> Arc<str> {
13790        "project".into()
13791    }
13792
13793    fn code_actions(
13794        &self,
13795        buffer: &Model<Buffer>,
13796        range: Range<text::Anchor>,
13797        cx: &mut WindowContext,
13798    ) -> Task<Result<Vec<CodeAction>>> {
13799        self.update(cx, |project, cx| {
13800            project.code_actions(buffer, range, None, cx)
13801        })
13802    }
13803
13804    fn apply_code_action(
13805        &self,
13806        buffer_handle: Model<Buffer>,
13807        action: CodeAction,
13808        _excerpt_id: ExcerptId,
13809        push_to_history: bool,
13810        cx: &mut WindowContext,
13811    ) -> Task<Result<ProjectTransaction>> {
13812        self.update(cx, |project, cx| {
13813            project.apply_code_action(buffer_handle, action, push_to_history, cx)
13814        })
13815    }
13816}
13817
13818fn snippet_completions(
13819    project: &Project,
13820    buffer: &Model<Buffer>,
13821    buffer_position: text::Anchor,
13822    cx: &mut AppContext,
13823) -> Task<Result<Vec<Completion>>> {
13824    let language = buffer.read(cx).language_at(buffer_position);
13825    let language_name = language.as_ref().map(|language| language.lsp_id());
13826    let snippet_store = project.snippets().read(cx);
13827    let snippets = snippet_store.snippets_for(language_name, cx);
13828
13829    if snippets.is_empty() {
13830        return Task::ready(Ok(vec![]));
13831    }
13832    let snapshot = buffer.read(cx).text_snapshot();
13833    let chars: String = snapshot
13834        .reversed_chars_for_range(text::Anchor::MIN..buffer_position)
13835        .collect();
13836
13837    let scope = language.map(|language| language.default_scope());
13838    let executor = cx.background_executor().clone();
13839
13840    cx.background_executor().spawn(async move {
13841        let classifier = CharClassifier::new(scope).for_completion(true);
13842        let mut last_word = chars
13843            .chars()
13844            .take_while(|c| classifier.is_word(*c))
13845            .collect::<String>();
13846        last_word = last_word.chars().rev().collect();
13847
13848        if last_word.is_empty() {
13849            return Ok(vec![]);
13850        }
13851
13852        let as_offset = text::ToOffset::to_offset(&buffer_position, &snapshot);
13853        let to_lsp = |point: &text::Anchor| {
13854            let end = text::ToPointUtf16::to_point_utf16(point, &snapshot);
13855            point_to_lsp(end)
13856        };
13857        let lsp_end = to_lsp(&buffer_position);
13858
13859        let candidates = snippets
13860            .iter()
13861            .enumerate()
13862            .flat_map(|(ix, snippet)| {
13863                snippet
13864                    .prefix
13865                    .iter()
13866                    .map(move |prefix| StringMatchCandidate::new(ix, &prefix))
13867            })
13868            .collect::<Vec<StringMatchCandidate>>();
13869
13870        let mut matches = fuzzy::match_strings(
13871            &candidates,
13872            &last_word,
13873            last_word.chars().any(|c| c.is_uppercase()),
13874            100,
13875            &Default::default(),
13876            executor,
13877        )
13878        .await;
13879
13880        // Remove all candidates where the query's start does not match the start of any word in the candidate
13881        if let Some(query_start) = last_word.chars().next() {
13882            matches.retain(|string_match| {
13883                split_words(&string_match.string).any(|word| {
13884                    // Check that the first codepoint of the word as lowercase matches the first
13885                    // codepoint of the query as lowercase
13886                    word.chars()
13887                        .flat_map(|codepoint| codepoint.to_lowercase())
13888                        .zip(query_start.to_lowercase())
13889                        .all(|(word_cp, query_cp)| word_cp == query_cp)
13890                })
13891            });
13892        }
13893
13894        let matched_strings = matches
13895            .into_iter()
13896            .map(|m| m.string)
13897            .collect::<HashSet<_>>();
13898
13899        let result: Vec<Completion> = snippets
13900            .into_iter()
13901            .filter_map(|snippet| {
13902                let matching_prefix = snippet
13903                    .prefix
13904                    .iter()
13905                    .find(|prefix| matched_strings.contains(*prefix))?;
13906                let start = as_offset - last_word.len();
13907                let start = snapshot.anchor_before(start);
13908                let range = start..buffer_position;
13909                let lsp_start = to_lsp(&start);
13910                let lsp_range = lsp::Range {
13911                    start: lsp_start,
13912                    end: lsp_end,
13913                };
13914                Some(Completion {
13915                    old_range: range,
13916                    new_text: snippet.body.clone(),
13917                    resolved: false,
13918                    label: CodeLabel {
13919                        text: matching_prefix.clone(),
13920                        runs: vec![],
13921                        filter_range: 0..matching_prefix.len(),
13922                    },
13923                    server_id: LanguageServerId(usize::MAX),
13924                    documentation: snippet.description.clone().map(Documentation::SingleLine),
13925                    lsp_completion: lsp::CompletionItem {
13926                        label: snippet.prefix.first().unwrap().clone(),
13927                        kind: Some(CompletionItemKind::SNIPPET),
13928                        label_details: snippet.description.as_ref().map(|description| {
13929                            lsp::CompletionItemLabelDetails {
13930                                detail: Some(description.clone()),
13931                                description: None,
13932                            }
13933                        }),
13934                        insert_text_format: Some(InsertTextFormat::SNIPPET),
13935                        text_edit: Some(lsp::CompletionTextEdit::InsertAndReplace(
13936                            lsp::InsertReplaceEdit {
13937                                new_text: snippet.body.clone(),
13938                                insert: lsp_range,
13939                                replace: lsp_range,
13940                            },
13941                        )),
13942                        filter_text: Some(snippet.body.clone()),
13943                        sort_text: Some(char::MAX.to_string()),
13944                        ..Default::default()
13945                    },
13946                    confirm: None,
13947                })
13948            })
13949            .collect();
13950
13951        Ok(result)
13952    })
13953}
13954
13955impl CompletionProvider for Model<Project> {
13956    fn completions(
13957        &self,
13958        buffer: &Model<Buffer>,
13959        buffer_position: text::Anchor,
13960        options: CompletionContext,
13961        cx: &mut ViewContext<Editor>,
13962    ) -> Task<Result<Vec<Completion>>> {
13963        self.update(cx, |project, cx| {
13964            let snippets = snippet_completions(project, buffer, buffer_position, cx);
13965            let project_completions = project.completions(buffer, buffer_position, options, cx);
13966            cx.background_executor().spawn(async move {
13967                let mut completions = project_completions.await?;
13968                let snippets_completions = snippets.await?;
13969                completions.extend(snippets_completions);
13970                Ok(completions)
13971            })
13972        })
13973    }
13974
13975    fn resolve_completions(
13976        &self,
13977        buffer: Model<Buffer>,
13978        completion_indices: Vec<usize>,
13979        completions: Rc<RefCell<Box<[Completion]>>>,
13980        cx: &mut ViewContext<Editor>,
13981    ) -> Task<Result<bool>> {
13982        self.update(cx, |project, cx| {
13983            project.lsp_store().update(cx, |lsp_store, cx| {
13984                lsp_store.resolve_completions(buffer, completion_indices, completions, cx)
13985            })
13986        })
13987    }
13988
13989    fn apply_additional_edits_for_completion(
13990        &self,
13991        buffer: Model<Buffer>,
13992        completions: Rc<RefCell<Box<[Completion]>>>,
13993        completion_index: usize,
13994        push_to_history: bool,
13995        cx: &mut ViewContext<Editor>,
13996    ) -> Task<Result<Option<language::Transaction>>> {
13997        self.update(cx, |project, cx| {
13998            project.lsp_store().update(cx, |lsp_store, cx| {
13999                lsp_store.apply_additional_edits_for_completion(
14000                    buffer,
14001                    completions,
14002                    completion_index,
14003                    push_to_history,
14004                    cx,
14005                )
14006            })
14007        })
14008    }
14009
14010    fn is_completion_trigger(
14011        &self,
14012        buffer: &Model<Buffer>,
14013        position: language::Anchor,
14014        text: &str,
14015        trigger_in_words: bool,
14016        cx: &mut ViewContext<Editor>,
14017    ) -> bool {
14018        let mut chars = text.chars();
14019        let char = if let Some(char) = chars.next() {
14020            char
14021        } else {
14022            return false;
14023        };
14024        if chars.next().is_some() {
14025            return false;
14026        }
14027
14028        let buffer = buffer.read(cx);
14029        let snapshot = buffer.snapshot();
14030        if !snapshot.settings_at(position, cx).show_completions_on_input {
14031            return false;
14032        }
14033        let classifier = snapshot.char_classifier_at(position).for_completion(true);
14034        if trigger_in_words && classifier.is_word(char) {
14035            return true;
14036        }
14037
14038        buffer.completion_triggers().contains(text)
14039    }
14040}
14041
14042impl SemanticsProvider for Model<Project> {
14043    fn hover(
14044        &self,
14045        buffer: &Model<Buffer>,
14046        position: text::Anchor,
14047        cx: &mut AppContext,
14048    ) -> Option<Task<Vec<project::Hover>>> {
14049        Some(self.update(cx, |project, cx| project.hover(buffer, position, cx)))
14050    }
14051
14052    fn document_highlights(
14053        &self,
14054        buffer: &Model<Buffer>,
14055        position: text::Anchor,
14056        cx: &mut AppContext,
14057    ) -> Option<Task<Result<Vec<DocumentHighlight>>>> {
14058        Some(self.update(cx, |project, cx| {
14059            project.document_highlights(buffer, position, cx)
14060        }))
14061    }
14062
14063    fn definitions(
14064        &self,
14065        buffer: &Model<Buffer>,
14066        position: text::Anchor,
14067        kind: GotoDefinitionKind,
14068        cx: &mut AppContext,
14069    ) -> Option<Task<Result<Vec<LocationLink>>>> {
14070        Some(self.update(cx, |project, cx| match kind {
14071            GotoDefinitionKind::Symbol => project.definition(&buffer, position, cx),
14072            GotoDefinitionKind::Declaration => project.declaration(&buffer, position, cx),
14073            GotoDefinitionKind::Type => project.type_definition(&buffer, position, cx),
14074            GotoDefinitionKind::Implementation => project.implementation(&buffer, position, cx),
14075        }))
14076    }
14077
14078    fn supports_inlay_hints(&self, buffer: &Model<Buffer>, cx: &AppContext) -> bool {
14079        // TODO: make this work for remote projects
14080        self.read(cx)
14081            .language_servers_for_local_buffer(buffer.read(cx), cx)
14082            .any(
14083                |(_, server)| match server.capabilities().inlay_hint_provider {
14084                    Some(lsp::OneOf::Left(enabled)) => enabled,
14085                    Some(lsp::OneOf::Right(_)) => true,
14086                    None => false,
14087                },
14088            )
14089    }
14090
14091    fn inlay_hints(
14092        &self,
14093        buffer_handle: Model<Buffer>,
14094        range: Range<text::Anchor>,
14095        cx: &mut AppContext,
14096    ) -> Option<Task<anyhow::Result<Vec<InlayHint>>>> {
14097        Some(self.update(cx, |project, cx| {
14098            project.inlay_hints(buffer_handle, range, cx)
14099        }))
14100    }
14101
14102    fn resolve_inlay_hint(
14103        &self,
14104        hint: InlayHint,
14105        buffer_handle: Model<Buffer>,
14106        server_id: LanguageServerId,
14107        cx: &mut AppContext,
14108    ) -> Option<Task<anyhow::Result<InlayHint>>> {
14109        Some(self.update(cx, |project, cx| {
14110            project.resolve_inlay_hint(hint, buffer_handle, server_id, cx)
14111        }))
14112    }
14113
14114    fn range_for_rename(
14115        &self,
14116        buffer: &Model<Buffer>,
14117        position: text::Anchor,
14118        cx: &mut AppContext,
14119    ) -> Option<Task<Result<Option<Range<text::Anchor>>>>> {
14120        Some(self.update(cx, |project, cx| {
14121            let buffer = buffer.clone();
14122            let task = project.prepare_rename(buffer.clone(), position, cx);
14123            cx.spawn(|_, mut cx| async move {
14124                Ok(match task.await? {
14125                    PrepareRenameResponse::Success(range) => Some(range),
14126                    PrepareRenameResponse::InvalidPosition => None,
14127                    PrepareRenameResponse::OnlyUnpreparedRenameSupported => {
14128                        // Fallback on using TreeSitter info to determine identifier range
14129                        buffer.update(&mut cx, |buffer, _| {
14130                            let snapshot = buffer.snapshot();
14131                            let (range, kind) = snapshot.surrounding_word(position);
14132                            if kind != Some(CharKind::Word) {
14133                                return None;
14134                            }
14135                            Some(
14136                                snapshot.anchor_before(range.start)
14137                                    ..snapshot.anchor_after(range.end),
14138                            )
14139                        })?
14140                    }
14141                })
14142            })
14143        }))
14144    }
14145
14146    fn perform_rename(
14147        &self,
14148        buffer: &Model<Buffer>,
14149        position: text::Anchor,
14150        new_name: String,
14151        cx: &mut AppContext,
14152    ) -> Option<Task<Result<ProjectTransaction>>> {
14153        Some(self.update(cx, |project, cx| {
14154            project.perform_rename(buffer.clone(), position, new_name, cx)
14155        }))
14156    }
14157}
14158
14159fn inlay_hint_settings(
14160    location: Anchor,
14161    snapshot: &MultiBufferSnapshot,
14162    cx: &mut ViewContext<Editor>,
14163) -> InlayHintSettings {
14164    let file = snapshot.file_at(location);
14165    let language = snapshot.language_at(location).map(|l| l.name());
14166    language_settings(language, file, cx).inlay_hints
14167}
14168
14169fn consume_contiguous_rows(
14170    contiguous_row_selections: &mut Vec<Selection<Point>>,
14171    selection: &Selection<Point>,
14172    display_map: &DisplaySnapshot,
14173    selections: &mut Peekable<std::slice::Iter<Selection<Point>>>,
14174) -> (MultiBufferRow, MultiBufferRow) {
14175    contiguous_row_selections.push(selection.clone());
14176    let start_row = MultiBufferRow(selection.start.row);
14177    let mut end_row = ending_row(selection, display_map);
14178
14179    while let Some(next_selection) = selections.peek() {
14180        if next_selection.start.row <= end_row.0 {
14181            end_row = ending_row(next_selection, display_map);
14182            contiguous_row_selections.push(selections.next().unwrap().clone());
14183        } else {
14184            break;
14185        }
14186    }
14187    (start_row, end_row)
14188}
14189
14190fn ending_row(next_selection: &Selection<Point>, display_map: &DisplaySnapshot) -> MultiBufferRow {
14191    if next_selection.end.column > 0 || next_selection.is_empty() {
14192        MultiBufferRow(display_map.next_line_boundary(next_selection.end).0.row + 1)
14193    } else {
14194        MultiBufferRow(next_selection.end.row)
14195    }
14196}
14197
14198impl EditorSnapshot {
14199    pub fn remote_selections_in_range<'a>(
14200        &'a self,
14201        range: &'a Range<Anchor>,
14202        collaboration_hub: &dyn CollaborationHub,
14203        cx: &'a AppContext,
14204    ) -> impl 'a + Iterator<Item = RemoteSelection> {
14205        let participant_names = collaboration_hub.user_names(cx);
14206        let participant_indices = collaboration_hub.user_participant_indices(cx);
14207        let collaborators_by_peer_id = collaboration_hub.collaborators(cx);
14208        let collaborators_by_replica_id = collaborators_by_peer_id
14209            .iter()
14210            .map(|(_, collaborator)| (collaborator.replica_id, collaborator))
14211            .collect::<HashMap<_, _>>();
14212        self.buffer_snapshot
14213            .selections_in_range(range, false)
14214            .filter_map(move |(replica_id, line_mode, cursor_shape, selection)| {
14215                let collaborator = collaborators_by_replica_id.get(&replica_id)?;
14216                let participant_index = participant_indices.get(&collaborator.user_id).copied();
14217                let user_name = participant_names.get(&collaborator.user_id).cloned();
14218                Some(RemoteSelection {
14219                    replica_id,
14220                    selection,
14221                    cursor_shape,
14222                    line_mode,
14223                    participant_index,
14224                    peer_id: collaborator.peer_id,
14225                    user_name,
14226                })
14227            })
14228    }
14229
14230    pub fn language_at<T: ToOffset>(&self, position: T) -> Option<&Arc<Language>> {
14231        self.display_snapshot.buffer_snapshot.language_at(position)
14232    }
14233
14234    pub fn is_focused(&self) -> bool {
14235        self.is_focused
14236    }
14237
14238    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
14239        self.placeholder_text.as_ref()
14240    }
14241
14242    pub fn scroll_position(&self) -> gpui::Point<f32> {
14243        self.scroll_anchor.scroll_position(&self.display_snapshot)
14244    }
14245
14246    fn gutter_dimensions(
14247        &self,
14248        font_id: FontId,
14249        font_size: Pixels,
14250        em_width: Pixels,
14251        em_advance: Pixels,
14252        max_line_number_width: Pixels,
14253        cx: &AppContext,
14254    ) -> GutterDimensions {
14255        if !self.show_gutter {
14256            return GutterDimensions::default();
14257        }
14258        let descent = cx.text_system().descent(font_id, font_size);
14259
14260        let show_git_gutter = self.show_git_diff_gutter.unwrap_or_else(|| {
14261            matches!(
14262                ProjectSettings::get_global(cx).git.git_gutter,
14263                Some(GitGutterSetting::TrackedFiles)
14264            )
14265        });
14266        let gutter_settings = EditorSettings::get_global(cx).gutter;
14267        let show_line_numbers = self
14268            .show_line_numbers
14269            .unwrap_or(gutter_settings.line_numbers);
14270        let line_gutter_width = if show_line_numbers {
14271            // Avoid flicker-like gutter resizes when the line number gains another digit and only resize the gutter on files with N*10^5 lines.
14272            let min_width_for_number_on_gutter = em_advance * 4.0;
14273            max_line_number_width.max(min_width_for_number_on_gutter)
14274        } else {
14275            0.0.into()
14276        };
14277
14278        let show_code_actions = self
14279            .show_code_actions
14280            .unwrap_or(gutter_settings.code_actions);
14281
14282        let show_runnables = self.show_runnables.unwrap_or(gutter_settings.runnables);
14283
14284        let git_blame_entries_width =
14285            self.git_blame_gutter_max_author_length
14286                .map(|max_author_length| {
14287                    // Length of the author name, but also space for the commit hash,
14288                    // the spacing and the timestamp.
14289                    let max_char_count = max_author_length
14290                        .min(GIT_BLAME_MAX_AUTHOR_CHARS_DISPLAYED)
14291                        + 7 // length of commit sha
14292                        + 14 // length of max relative timestamp ("60 minutes ago")
14293                        + 4; // gaps and margins
14294
14295                    em_advance * max_char_count
14296                });
14297
14298        let mut left_padding = git_blame_entries_width.unwrap_or(Pixels::ZERO);
14299        left_padding += if show_code_actions || show_runnables {
14300            em_width * 3.0
14301        } else if show_git_gutter && show_line_numbers {
14302            em_width * 2.0
14303        } else if show_git_gutter || show_line_numbers {
14304            em_width
14305        } else {
14306            px(0.)
14307        };
14308
14309        let right_padding = if gutter_settings.folds && show_line_numbers {
14310            em_width * 4.0
14311        } else if gutter_settings.folds {
14312            em_width * 3.0
14313        } else if show_line_numbers {
14314            em_width
14315        } else {
14316            px(0.)
14317        };
14318
14319        GutterDimensions {
14320            left_padding,
14321            right_padding,
14322            width: line_gutter_width + left_padding + right_padding,
14323            margin: -descent,
14324            git_blame_entries_width,
14325        }
14326    }
14327
14328    pub fn render_crease_toggle(
14329        &self,
14330        buffer_row: MultiBufferRow,
14331        row_contains_cursor: bool,
14332        editor: View<Editor>,
14333        cx: &mut WindowContext,
14334    ) -> Option<AnyElement> {
14335        let folded = self.is_line_folded(buffer_row);
14336        let mut is_foldable = false;
14337
14338        if let Some(crease) = self
14339            .crease_snapshot
14340            .query_row(buffer_row, &self.buffer_snapshot)
14341        {
14342            is_foldable = true;
14343            match crease {
14344                Crease::Inline { render_toggle, .. } | Crease::Block { render_toggle, .. } => {
14345                    if let Some(render_toggle) = render_toggle {
14346                        let toggle_callback = Arc::new(move |folded, cx: &mut WindowContext| {
14347                            if folded {
14348                                editor.update(cx, |editor, cx| {
14349                                    editor.fold_at(&crate::FoldAt { buffer_row }, cx)
14350                                });
14351                            } else {
14352                                editor.update(cx, |editor, cx| {
14353                                    editor.unfold_at(&crate::UnfoldAt { buffer_row }, cx)
14354                                });
14355                            }
14356                        });
14357                        return Some((render_toggle)(buffer_row, folded, toggle_callback, cx));
14358                    }
14359                }
14360            }
14361        }
14362
14363        is_foldable |= self.starts_indent(buffer_row);
14364
14365        if folded || (is_foldable && (row_contains_cursor || self.gutter_hovered)) {
14366            Some(
14367                Disclosure::new(("gutter_crease", buffer_row.0), !folded)
14368                    .toggle_state(folded)
14369                    .on_click(cx.listener_for(&editor, move |this, _e, cx| {
14370                        if folded {
14371                            this.unfold_at(&UnfoldAt { buffer_row }, cx);
14372                        } else {
14373                            this.fold_at(&FoldAt { buffer_row }, cx);
14374                        }
14375                    }))
14376                    .into_any_element(),
14377            )
14378        } else {
14379            None
14380        }
14381    }
14382
14383    pub fn render_crease_trailer(
14384        &self,
14385        buffer_row: MultiBufferRow,
14386        cx: &mut WindowContext,
14387    ) -> Option<AnyElement> {
14388        let folded = self.is_line_folded(buffer_row);
14389        if let Crease::Inline { render_trailer, .. } = self
14390            .crease_snapshot
14391            .query_row(buffer_row, &self.buffer_snapshot)?
14392        {
14393            let render_trailer = render_trailer.as_ref()?;
14394            Some(render_trailer(buffer_row, folded, cx))
14395        } else {
14396            None
14397        }
14398    }
14399}
14400
14401impl Deref for EditorSnapshot {
14402    type Target = DisplaySnapshot;
14403
14404    fn deref(&self) -> &Self::Target {
14405        &self.display_snapshot
14406    }
14407}
14408
14409#[derive(Clone, Debug, PartialEq, Eq)]
14410pub enum EditorEvent {
14411    InputIgnored {
14412        text: Arc<str>,
14413    },
14414    InputHandled {
14415        utf16_range_to_replace: Option<Range<isize>>,
14416        text: Arc<str>,
14417    },
14418    ExcerptsAdded {
14419        buffer: Model<Buffer>,
14420        predecessor: ExcerptId,
14421        excerpts: Vec<(ExcerptId, ExcerptRange<language::Anchor>)>,
14422    },
14423    ExcerptsRemoved {
14424        ids: Vec<ExcerptId>,
14425    },
14426    BufferFoldToggled {
14427        ids: Vec<ExcerptId>,
14428        folded: bool,
14429    },
14430    ExcerptsEdited {
14431        ids: Vec<ExcerptId>,
14432    },
14433    ExcerptsExpanded {
14434        ids: Vec<ExcerptId>,
14435    },
14436    BufferEdited,
14437    Edited {
14438        transaction_id: clock::Lamport,
14439    },
14440    Reparsed(BufferId),
14441    Focused,
14442    FocusedIn,
14443    Blurred,
14444    DirtyChanged,
14445    Saved,
14446    TitleChanged,
14447    DiffBaseChanged,
14448    SelectionsChanged {
14449        local: bool,
14450    },
14451    ScrollPositionChanged {
14452        local: bool,
14453        autoscroll: bool,
14454    },
14455    Closed,
14456    TransactionUndone {
14457        transaction_id: clock::Lamport,
14458    },
14459    TransactionBegun {
14460        transaction_id: clock::Lamport,
14461    },
14462    Reloaded,
14463    CursorShapeChanged,
14464}
14465
14466impl EventEmitter<EditorEvent> for Editor {}
14467
14468impl FocusableView for Editor {
14469    fn focus_handle(&self, _cx: &AppContext) -> FocusHandle {
14470        self.focus_handle.clone()
14471    }
14472}
14473
14474impl Render for Editor {
14475    fn render<'a>(&mut self, cx: &mut ViewContext<'a, Self>) -> impl IntoElement {
14476        let settings = ThemeSettings::get_global(cx);
14477
14478        let mut text_style = match self.mode {
14479            EditorMode::SingleLine { .. } | EditorMode::AutoHeight { .. } => TextStyle {
14480                color: cx.theme().colors().editor_foreground,
14481                font_family: settings.ui_font.family.clone(),
14482                font_features: settings.ui_font.features.clone(),
14483                font_fallbacks: settings.ui_font.fallbacks.clone(),
14484                font_size: rems(0.875).into(),
14485                font_weight: settings.ui_font.weight,
14486                line_height: relative(settings.buffer_line_height.value()),
14487                ..Default::default()
14488            },
14489            EditorMode::Full => TextStyle {
14490                color: cx.theme().colors().editor_foreground,
14491                font_family: settings.buffer_font.family.clone(),
14492                font_features: settings.buffer_font.features.clone(),
14493                font_fallbacks: settings.buffer_font.fallbacks.clone(),
14494                font_size: settings.buffer_font_size().into(),
14495                font_weight: settings.buffer_font.weight,
14496                line_height: relative(settings.buffer_line_height.value()),
14497                ..Default::default()
14498            },
14499        };
14500        if let Some(text_style_refinement) = &self.text_style_refinement {
14501            text_style.refine(text_style_refinement)
14502        }
14503
14504        let background = match self.mode {
14505            EditorMode::SingleLine { .. } => cx.theme().system().transparent,
14506            EditorMode::AutoHeight { max_lines: _ } => cx.theme().system().transparent,
14507            EditorMode::Full => cx.theme().colors().editor_background,
14508        };
14509
14510        EditorElement::new(
14511            cx.view(),
14512            EditorStyle {
14513                background,
14514                local_player: cx.theme().players().local(),
14515                text: text_style,
14516                scrollbar_width: EditorElement::SCROLLBAR_WIDTH,
14517                syntax: cx.theme().syntax().clone(),
14518                status: cx.theme().status().clone(),
14519                inlay_hints_style: make_inlay_hints_style(cx),
14520                inline_completion_styles: make_suggestion_styles(cx),
14521                unnecessary_code_fade: ThemeSettings::get_global(cx).unnecessary_code_fade,
14522            },
14523        )
14524    }
14525}
14526
14527impl ViewInputHandler for Editor {
14528    fn text_for_range(
14529        &mut self,
14530        range_utf16: Range<usize>,
14531        adjusted_range: &mut Option<Range<usize>>,
14532        cx: &mut ViewContext<Self>,
14533    ) -> Option<String> {
14534        let snapshot = self.buffer.read(cx).read(cx);
14535        let start = snapshot.clip_offset_utf16(OffsetUtf16(range_utf16.start), Bias::Left);
14536        let end = snapshot.clip_offset_utf16(OffsetUtf16(range_utf16.end), Bias::Right);
14537        if (start.0..end.0) != range_utf16 {
14538            adjusted_range.replace(start.0..end.0);
14539        }
14540        Some(snapshot.text_for_range(start..end).collect())
14541    }
14542
14543    fn selected_text_range(
14544        &mut self,
14545        ignore_disabled_input: bool,
14546        cx: &mut ViewContext<Self>,
14547    ) -> Option<UTF16Selection> {
14548        // Prevent the IME menu from appearing when holding down an alphabetic key
14549        // while input is disabled.
14550        if !ignore_disabled_input && !self.input_enabled {
14551            return None;
14552        }
14553
14554        let selection = self.selections.newest::<OffsetUtf16>(cx);
14555        let range = selection.range();
14556
14557        Some(UTF16Selection {
14558            range: range.start.0..range.end.0,
14559            reversed: selection.reversed,
14560        })
14561    }
14562
14563    fn marked_text_range(&self, cx: &mut ViewContext<Self>) -> Option<Range<usize>> {
14564        let snapshot = self.buffer.read(cx).read(cx);
14565        let range = self.text_highlights::<InputComposition>(cx)?.1.first()?;
14566        Some(range.start.to_offset_utf16(&snapshot).0..range.end.to_offset_utf16(&snapshot).0)
14567    }
14568
14569    fn unmark_text(&mut self, cx: &mut ViewContext<Self>) {
14570        self.clear_highlights::<InputComposition>(cx);
14571        self.ime_transaction.take();
14572    }
14573
14574    fn replace_text_in_range(
14575        &mut self,
14576        range_utf16: Option<Range<usize>>,
14577        text: &str,
14578        cx: &mut ViewContext<Self>,
14579    ) {
14580        if !self.input_enabled {
14581            cx.emit(EditorEvent::InputIgnored { text: text.into() });
14582            return;
14583        }
14584
14585        self.transact(cx, |this, cx| {
14586            let new_selected_ranges = if let Some(range_utf16) = range_utf16 {
14587                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
14588                Some(this.selection_replacement_ranges(range_utf16, cx))
14589            } else {
14590                this.marked_text_ranges(cx)
14591            };
14592
14593            let range_to_replace = new_selected_ranges.as_ref().and_then(|ranges_to_replace| {
14594                let newest_selection_id = this.selections.newest_anchor().id;
14595                this.selections
14596                    .all::<OffsetUtf16>(cx)
14597                    .iter()
14598                    .zip(ranges_to_replace.iter())
14599                    .find_map(|(selection, range)| {
14600                        if selection.id == newest_selection_id {
14601                            Some(
14602                                (range.start.0 as isize - selection.head().0 as isize)
14603                                    ..(range.end.0 as isize - selection.head().0 as isize),
14604                            )
14605                        } else {
14606                            None
14607                        }
14608                    })
14609            });
14610
14611            cx.emit(EditorEvent::InputHandled {
14612                utf16_range_to_replace: range_to_replace,
14613                text: text.into(),
14614            });
14615
14616            if let Some(new_selected_ranges) = new_selected_ranges {
14617                this.change_selections(None, cx, |selections| {
14618                    selections.select_ranges(new_selected_ranges)
14619                });
14620                this.backspace(&Default::default(), cx);
14621            }
14622
14623            this.handle_input(text, cx);
14624        });
14625
14626        if let Some(transaction) = self.ime_transaction {
14627            self.buffer.update(cx, |buffer, cx| {
14628                buffer.group_until_transaction(transaction, cx);
14629            });
14630        }
14631
14632        self.unmark_text(cx);
14633    }
14634
14635    fn replace_and_mark_text_in_range(
14636        &mut self,
14637        range_utf16: Option<Range<usize>>,
14638        text: &str,
14639        new_selected_range_utf16: Option<Range<usize>>,
14640        cx: &mut ViewContext<Self>,
14641    ) {
14642        if !self.input_enabled {
14643            return;
14644        }
14645
14646        let transaction = self.transact(cx, |this, cx| {
14647            let ranges_to_replace = if let Some(mut marked_ranges) = this.marked_text_ranges(cx) {
14648                let snapshot = this.buffer.read(cx).read(cx);
14649                if let Some(relative_range_utf16) = range_utf16.as_ref() {
14650                    for marked_range in &mut marked_ranges {
14651                        marked_range.end.0 = marked_range.start.0 + relative_range_utf16.end;
14652                        marked_range.start.0 += relative_range_utf16.start;
14653                        marked_range.start =
14654                            snapshot.clip_offset_utf16(marked_range.start, Bias::Left);
14655                        marked_range.end =
14656                            snapshot.clip_offset_utf16(marked_range.end, Bias::Right);
14657                    }
14658                }
14659                Some(marked_ranges)
14660            } else if let Some(range_utf16) = range_utf16 {
14661                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
14662                Some(this.selection_replacement_ranges(range_utf16, cx))
14663            } else {
14664                None
14665            };
14666
14667            let range_to_replace = ranges_to_replace.as_ref().and_then(|ranges_to_replace| {
14668                let newest_selection_id = this.selections.newest_anchor().id;
14669                this.selections
14670                    .all::<OffsetUtf16>(cx)
14671                    .iter()
14672                    .zip(ranges_to_replace.iter())
14673                    .find_map(|(selection, range)| {
14674                        if selection.id == newest_selection_id {
14675                            Some(
14676                                (range.start.0 as isize - selection.head().0 as isize)
14677                                    ..(range.end.0 as isize - selection.head().0 as isize),
14678                            )
14679                        } else {
14680                            None
14681                        }
14682                    })
14683            });
14684
14685            cx.emit(EditorEvent::InputHandled {
14686                utf16_range_to_replace: range_to_replace,
14687                text: text.into(),
14688            });
14689
14690            if let Some(ranges) = ranges_to_replace {
14691                this.change_selections(None, cx, |s| s.select_ranges(ranges));
14692            }
14693
14694            let marked_ranges = {
14695                let snapshot = this.buffer.read(cx).read(cx);
14696                this.selections
14697                    .disjoint_anchors()
14698                    .iter()
14699                    .map(|selection| {
14700                        selection.start.bias_left(&snapshot)..selection.end.bias_right(&snapshot)
14701                    })
14702                    .collect::<Vec<_>>()
14703            };
14704
14705            if text.is_empty() {
14706                this.unmark_text(cx);
14707            } else {
14708                this.highlight_text::<InputComposition>(
14709                    marked_ranges.clone(),
14710                    HighlightStyle {
14711                        underline: Some(UnderlineStyle {
14712                            thickness: px(1.),
14713                            color: None,
14714                            wavy: false,
14715                        }),
14716                        ..Default::default()
14717                    },
14718                    cx,
14719                );
14720            }
14721
14722            // Disable auto-closing when composing text (i.e. typing a `"` on a Brazilian keyboard)
14723            let use_autoclose = this.use_autoclose;
14724            let use_auto_surround = this.use_auto_surround;
14725            this.set_use_autoclose(false);
14726            this.set_use_auto_surround(false);
14727            this.handle_input(text, cx);
14728            this.set_use_autoclose(use_autoclose);
14729            this.set_use_auto_surround(use_auto_surround);
14730
14731            if let Some(new_selected_range) = new_selected_range_utf16 {
14732                let snapshot = this.buffer.read(cx).read(cx);
14733                let new_selected_ranges = marked_ranges
14734                    .into_iter()
14735                    .map(|marked_range| {
14736                        let insertion_start = marked_range.start.to_offset_utf16(&snapshot).0;
14737                        let new_start = OffsetUtf16(new_selected_range.start + insertion_start);
14738                        let new_end = OffsetUtf16(new_selected_range.end + insertion_start);
14739                        snapshot.clip_offset_utf16(new_start, Bias::Left)
14740                            ..snapshot.clip_offset_utf16(new_end, Bias::Right)
14741                    })
14742                    .collect::<Vec<_>>();
14743
14744                drop(snapshot);
14745                this.change_selections(None, cx, |selections| {
14746                    selections.select_ranges(new_selected_ranges)
14747                });
14748            }
14749        });
14750
14751        self.ime_transaction = self.ime_transaction.or(transaction);
14752        if let Some(transaction) = self.ime_transaction {
14753            self.buffer.update(cx, |buffer, cx| {
14754                buffer.group_until_transaction(transaction, cx);
14755            });
14756        }
14757
14758        if self.text_highlights::<InputComposition>(cx).is_none() {
14759            self.ime_transaction.take();
14760        }
14761    }
14762
14763    fn bounds_for_range(
14764        &mut self,
14765        range_utf16: Range<usize>,
14766        element_bounds: gpui::Bounds<Pixels>,
14767        cx: &mut ViewContext<Self>,
14768    ) -> Option<gpui::Bounds<Pixels>> {
14769        let text_layout_details = self.text_layout_details(cx);
14770        let gpui::Point {
14771            x: em_width,
14772            y: line_height,
14773        } = self.character_size(cx);
14774
14775        let snapshot = self.snapshot(cx);
14776        let scroll_position = snapshot.scroll_position();
14777        let scroll_left = scroll_position.x * em_width;
14778
14779        let start = OffsetUtf16(range_utf16.start).to_display_point(&snapshot);
14780        let x = snapshot.x_for_display_point(start, &text_layout_details) - scroll_left
14781            + self.gutter_dimensions.width
14782            + self.gutter_dimensions.margin;
14783        let y = line_height * (start.row().as_f32() - scroll_position.y);
14784
14785        Some(Bounds {
14786            origin: element_bounds.origin + point(x, y),
14787            size: size(em_width, line_height),
14788        })
14789    }
14790}
14791
14792trait SelectionExt {
14793    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
14794    fn spanned_rows(
14795        &self,
14796        include_end_if_at_line_start: bool,
14797        map: &DisplaySnapshot,
14798    ) -> Range<MultiBufferRow>;
14799}
14800
14801impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
14802    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
14803        let start = self
14804            .start
14805            .to_point(&map.buffer_snapshot)
14806            .to_display_point(map);
14807        let end = self
14808            .end
14809            .to_point(&map.buffer_snapshot)
14810            .to_display_point(map);
14811        if self.reversed {
14812            end..start
14813        } else {
14814            start..end
14815        }
14816    }
14817
14818    fn spanned_rows(
14819        &self,
14820        include_end_if_at_line_start: bool,
14821        map: &DisplaySnapshot,
14822    ) -> Range<MultiBufferRow> {
14823        let start = self.start.to_point(&map.buffer_snapshot);
14824        let mut end = self.end.to_point(&map.buffer_snapshot);
14825        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
14826            end.row -= 1;
14827        }
14828
14829        let buffer_start = map.prev_line_boundary(start).0;
14830        let buffer_end = map.next_line_boundary(end).0;
14831        MultiBufferRow(buffer_start.row)..MultiBufferRow(buffer_end.row + 1)
14832    }
14833}
14834
14835impl<T: InvalidationRegion> InvalidationStack<T> {
14836    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
14837    where
14838        S: Clone + ToOffset,
14839    {
14840        while let Some(region) = self.last() {
14841            let all_selections_inside_invalidation_ranges =
14842                if selections.len() == region.ranges().len() {
14843                    selections
14844                        .iter()
14845                        .zip(region.ranges().iter().map(|r| r.to_offset(buffer)))
14846                        .all(|(selection, invalidation_range)| {
14847                            let head = selection.head().to_offset(buffer);
14848                            invalidation_range.start <= head && invalidation_range.end >= head
14849                        })
14850                } else {
14851                    false
14852                };
14853
14854            if all_selections_inside_invalidation_ranges {
14855                break;
14856            } else {
14857                self.pop();
14858            }
14859        }
14860    }
14861}
14862
14863impl<T> Default for InvalidationStack<T> {
14864    fn default() -> Self {
14865        Self(Default::default())
14866    }
14867}
14868
14869impl<T> Deref for InvalidationStack<T> {
14870    type Target = Vec<T>;
14871
14872    fn deref(&self) -> &Self::Target {
14873        &self.0
14874    }
14875}
14876
14877impl<T> DerefMut for InvalidationStack<T> {
14878    fn deref_mut(&mut self) -> &mut Self::Target {
14879        &mut self.0
14880    }
14881}
14882
14883impl InvalidationRegion for SnippetState {
14884    fn ranges(&self) -> &[Range<Anchor>] {
14885        &self.ranges[self.active_index]
14886    }
14887}
14888
14889pub fn diagnostic_block_renderer(
14890    diagnostic: Diagnostic,
14891    max_message_rows: Option<u8>,
14892    allow_closing: bool,
14893    _is_valid: bool,
14894) -> RenderBlock {
14895    let (text_without_backticks, code_ranges) =
14896        highlight_diagnostic_message(&diagnostic, max_message_rows);
14897
14898    Arc::new(move |cx: &mut BlockContext| {
14899        let group_id: SharedString = cx.block_id.to_string().into();
14900
14901        let mut text_style = cx.text_style().clone();
14902        text_style.color = diagnostic_style(diagnostic.severity, cx.theme().status());
14903        let theme_settings = ThemeSettings::get_global(cx);
14904        text_style.font_family = theme_settings.buffer_font.family.clone();
14905        text_style.font_style = theme_settings.buffer_font.style;
14906        text_style.font_features = theme_settings.buffer_font.features.clone();
14907        text_style.font_weight = theme_settings.buffer_font.weight;
14908
14909        let multi_line_diagnostic = diagnostic.message.contains('\n');
14910
14911        let buttons = |diagnostic: &Diagnostic| {
14912            if multi_line_diagnostic {
14913                v_flex()
14914            } else {
14915                h_flex()
14916            }
14917            .when(allow_closing, |div| {
14918                div.children(diagnostic.is_primary.then(|| {
14919                    IconButton::new("close-block", IconName::XCircle)
14920                        .icon_color(Color::Muted)
14921                        .size(ButtonSize::Compact)
14922                        .style(ButtonStyle::Transparent)
14923                        .visible_on_hover(group_id.clone())
14924                        .on_click(move |_click, cx| cx.dispatch_action(Box::new(Cancel)))
14925                        .tooltip(|cx| Tooltip::for_action("Close Diagnostics", &Cancel, cx))
14926                }))
14927            })
14928            .child(
14929                IconButton::new("copy-block", IconName::Copy)
14930                    .icon_color(Color::Muted)
14931                    .size(ButtonSize::Compact)
14932                    .style(ButtonStyle::Transparent)
14933                    .visible_on_hover(group_id.clone())
14934                    .on_click({
14935                        let message = diagnostic.message.clone();
14936                        move |_click, cx| {
14937                            cx.write_to_clipboard(ClipboardItem::new_string(message.clone()))
14938                        }
14939                    })
14940                    .tooltip(|cx| Tooltip::text("Copy diagnostic message", cx)),
14941            )
14942        };
14943
14944        let icon_size = buttons(&diagnostic)
14945            .into_any_element()
14946            .layout_as_root(AvailableSpace::min_size(), cx);
14947
14948        h_flex()
14949            .id(cx.block_id)
14950            .group(group_id.clone())
14951            .relative()
14952            .size_full()
14953            .block_mouse_down()
14954            .pl(cx.gutter_dimensions.width)
14955            .w(cx.max_width - cx.gutter_dimensions.full_width())
14956            .child(
14957                div()
14958                    .flex()
14959                    .w(cx.anchor_x - cx.gutter_dimensions.width - icon_size.width)
14960                    .flex_shrink(),
14961            )
14962            .child(buttons(&diagnostic))
14963            .child(div().flex().flex_shrink_0().child(
14964                StyledText::new(text_without_backticks.clone()).with_highlights(
14965                    &text_style,
14966                    code_ranges.iter().map(|range| {
14967                        (
14968                            range.clone(),
14969                            HighlightStyle {
14970                                font_weight: Some(FontWeight::BOLD),
14971                                ..Default::default()
14972                            },
14973                        )
14974                    }),
14975                ),
14976            ))
14977            .into_any_element()
14978    })
14979}
14980
14981fn inline_completion_edit_text(
14982    current_snapshot: &BufferSnapshot,
14983    edits: &[(Range<Anchor>, String)],
14984    edit_preview: &EditPreview,
14985    include_deletions: bool,
14986    cx: &WindowContext,
14987) -> Option<HighlightedEdits> {
14988    let edits = edits
14989        .iter()
14990        .map(|(anchor, text)| {
14991            (
14992                anchor.start.text_anchor..anchor.end.text_anchor,
14993                text.clone(),
14994            )
14995        })
14996        .collect::<Vec<_>>();
14997
14998    Some(edit_preview.highlight_edits(current_snapshot, &edits, include_deletions, cx))
14999}
15000
15001pub fn highlight_diagnostic_message(
15002    diagnostic: &Diagnostic,
15003    mut max_message_rows: Option<u8>,
15004) -> (SharedString, Vec<Range<usize>>) {
15005    let mut text_without_backticks = String::new();
15006    let mut code_ranges = Vec::new();
15007
15008    if let Some(source) = &diagnostic.source {
15009        text_without_backticks.push_str(source);
15010        code_ranges.push(0..source.len());
15011        text_without_backticks.push_str(": ");
15012    }
15013
15014    let mut prev_offset = 0;
15015    let mut in_code_block = false;
15016    let has_row_limit = max_message_rows.is_some();
15017    let mut newline_indices = diagnostic
15018        .message
15019        .match_indices('\n')
15020        .filter(|_| has_row_limit)
15021        .map(|(ix, _)| ix)
15022        .fuse()
15023        .peekable();
15024
15025    for (quote_ix, _) in diagnostic
15026        .message
15027        .match_indices('`')
15028        .chain([(diagnostic.message.len(), "")])
15029    {
15030        let mut first_newline_ix = None;
15031        let mut last_newline_ix = None;
15032        while let Some(newline_ix) = newline_indices.peek() {
15033            if *newline_ix < quote_ix {
15034                if first_newline_ix.is_none() {
15035                    first_newline_ix = Some(*newline_ix);
15036                }
15037                last_newline_ix = Some(*newline_ix);
15038
15039                if let Some(rows_left) = &mut max_message_rows {
15040                    if *rows_left == 0 {
15041                        break;
15042                    } else {
15043                        *rows_left -= 1;
15044                    }
15045                }
15046                let _ = newline_indices.next();
15047            } else {
15048                break;
15049            }
15050        }
15051        let prev_len = text_without_backticks.len();
15052        let new_text = &diagnostic.message[prev_offset..first_newline_ix.unwrap_or(quote_ix)];
15053        text_without_backticks.push_str(new_text);
15054        if in_code_block {
15055            code_ranges.push(prev_len..text_without_backticks.len());
15056        }
15057        prev_offset = last_newline_ix.unwrap_or(quote_ix) + 1;
15058        in_code_block = !in_code_block;
15059        if first_newline_ix.map_or(false, |newline_ix| newline_ix < quote_ix) {
15060            text_without_backticks.push_str("...");
15061            break;
15062        }
15063    }
15064
15065    (text_without_backticks.into(), code_ranges)
15066}
15067
15068fn diagnostic_style(severity: DiagnosticSeverity, colors: &StatusColors) -> Hsla {
15069    match severity {
15070        DiagnosticSeverity::ERROR => colors.error,
15071        DiagnosticSeverity::WARNING => colors.warning,
15072        DiagnosticSeverity::INFORMATION => colors.info,
15073        DiagnosticSeverity::HINT => colors.info,
15074        _ => colors.ignored,
15075    }
15076}
15077
15078pub fn styled_runs_for_code_label<'a>(
15079    label: &'a CodeLabel,
15080    syntax_theme: &'a theme::SyntaxTheme,
15081) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
15082    let fade_out = HighlightStyle {
15083        fade_out: Some(0.35),
15084        ..Default::default()
15085    };
15086
15087    let mut prev_end = label.filter_range.end;
15088    label
15089        .runs
15090        .iter()
15091        .enumerate()
15092        .flat_map(move |(ix, (range, highlight_id))| {
15093            let style = if let Some(style) = highlight_id.style(syntax_theme) {
15094                style
15095            } else {
15096                return Default::default();
15097            };
15098            let mut muted_style = style;
15099            muted_style.highlight(fade_out);
15100
15101            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
15102            if range.start >= label.filter_range.end {
15103                if range.start > prev_end {
15104                    runs.push((prev_end..range.start, fade_out));
15105                }
15106                runs.push((range.clone(), muted_style));
15107            } else if range.end <= label.filter_range.end {
15108                runs.push((range.clone(), style));
15109            } else {
15110                runs.push((range.start..label.filter_range.end, style));
15111                runs.push((label.filter_range.end..range.end, muted_style));
15112            }
15113            prev_end = cmp::max(prev_end, range.end);
15114
15115            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
15116                runs.push((prev_end..label.text.len(), fade_out));
15117            }
15118
15119            runs
15120        })
15121}
15122
15123pub(crate) fn split_words(text: &str) -> impl std::iter::Iterator<Item = &str> + '_ {
15124    let mut prev_index = 0;
15125    let mut prev_codepoint: Option<char> = None;
15126    text.char_indices()
15127        .chain([(text.len(), '\0')])
15128        .filter_map(move |(index, codepoint)| {
15129            let prev_codepoint = prev_codepoint.replace(codepoint)?;
15130            let is_boundary = index == text.len()
15131                || !prev_codepoint.is_uppercase() && codepoint.is_uppercase()
15132                || !prev_codepoint.is_alphanumeric() && codepoint.is_alphanumeric();
15133            if is_boundary {
15134                let chunk = &text[prev_index..index];
15135                prev_index = index;
15136                Some(chunk)
15137            } else {
15138                None
15139            }
15140        })
15141}
15142
15143pub trait RangeToAnchorExt: Sized {
15144    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor>;
15145
15146    fn to_display_points(self, snapshot: &EditorSnapshot) -> Range<DisplayPoint> {
15147        let anchor_range = self.to_anchors(&snapshot.buffer_snapshot);
15148        anchor_range.start.to_display_point(snapshot)..anchor_range.end.to_display_point(snapshot)
15149    }
15150}
15151
15152impl<T: ToOffset> RangeToAnchorExt for Range<T> {
15153    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor> {
15154        let start_offset = self.start.to_offset(snapshot);
15155        let end_offset = self.end.to_offset(snapshot);
15156        if start_offset == end_offset {
15157            snapshot.anchor_before(start_offset)..snapshot.anchor_before(end_offset)
15158        } else {
15159            snapshot.anchor_after(self.start)..snapshot.anchor_before(self.end)
15160        }
15161    }
15162}
15163
15164pub trait RowExt {
15165    fn as_f32(&self) -> f32;
15166
15167    fn next_row(&self) -> Self;
15168
15169    fn previous_row(&self) -> Self;
15170
15171    fn minus(&self, other: Self) -> u32;
15172}
15173
15174impl RowExt for DisplayRow {
15175    fn as_f32(&self) -> f32 {
15176        self.0 as f32
15177    }
15178
15179    fn next_row(&self) -> Self {
15180        Self(self.0 + 1)
15181    }
15182
15183    fn previous_row(&self) -> Self {
15184        Self(self.0.saturating_sub(1))
15185    }
15186
15187    fn minus(&self, other: Self) -> u32 {
15188        self.0 - other.0
15189    }
15190}
15191
15192impl RowExt for MultiBufferRow {
15193    fn as_f32(&self) -> f32 {
15194        self.0 as f32
15195    }
15196
15197    fn next_row(&self) -> Self {
15198        Self(self.0 + 1)
15199    }
15200
15201    fn previous_row(&self) -> Self {
15202        Self(self.0.saturating_sub(1))
15203    }
15204
15205    fn minus(&self, other: Self) -> u32 {
15206        self.0 - other.0
15207    }
15208}
15209
15210trait RowRangeExt {
15211    type Row;
15212
15213    fn len(&self) -> usize;
15214
15215    fn iter_rows(&self) -> impl DoubleEndedIterator<Item = Self::Row>;
15216}
15217
15218impl RowRangeExt for Range<MultiBufferRow> {
15219    type Row = MultiBufferRow;
15220
15221    fn len(&self) -> usize {
15222        (self.end.0 - self.start.0) as usize
15223    }
15224
15225    fn iter_rows(&self) -> impl DoubleEndedIterator<Item = MultiBufferRow> {
15226        (self.start.0..self.end.0).map(MultiBufferRow)
15227    }
15228}
15229
15230impl RowRangeExt for Range<DisplayRow> {
15231    type Row = DisplayRow;
15232
15233    fn len(&self) -> usize {
15234        (self.end.0 - self.start.0) as usize
15235    }
15236
15237    fn iter_rows(&self) -> impl DoubleEndedIterator<Item = DisplayRow> {
15238        (self.start.0..self.end.0).map(DisplayRow)
15239    }
15240}
15241
15242fn hunk_status(hunk: &MultiBufferDiffHunk) -> DiffHunkStatus {
15243    if hunk.diff_base_byte_range.is_empty() {
15244        DiffHunkStatus::Added
15245    } else if hunk.row_range.is_empty() {
15246        DiffHunkStatus::Removed
15247    } else {
15248        DiffHunkStatus::Modified
15249    }
15250}
15251
15252/// If select range has more than one line, we
15253/// just point the cursor to range.start.
15254fn check_multiline_range(buffer: &Buffer, range: Range<usize>) -> Range<usize> {
15255    if buffer.offset_to_point(range.start).row == buffer.offset_to_point(range.end).row {
15256        range
15257    } else {
15258        range.start..range.start
15259    }
15260}
15261pub struct KillRing(ClipboardItem);
15262impl Global for KillRing {}
15263
15264const UPDATE_DEBOUNCE: Duration = Duration::from_millis(50);
15265
15266fn all_edits_insertions_or_deletions(
15267    edits: &Vec<(Range<Anchor>, String)>,
15268    snapshot: &MultiBufferSnapshot,
15269) -> bool {
15270    let mut all_insertions = true;
15271    let mut all_deletions = true;
15272
15273    for (range, new_text) in edits.iter() {
15274        let range_is_empty = range.to_offset(&snapshot).is_empty();
15275        let text_is_empty = new_text.is_empty();
15276
15277        if range_is_empty != text_is_empty {
15278            if range_is_empty {
15279                all_deletions = false;
15280            } else {
15281                all_insertions = false;
15282            }
15283        } else {
15284            return false;
15285        }
15286
15287        if !all_insertions && !all_deletions {
15288            return false;
15289        }
15290    }
15291    all_insertions || all_deletions
15292}