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 it's behaviour.
   15pub mod actions;
   16mod blink_manager;
   17pub mod display_map;
   18mod editor_settings;
   19mod element;
   20mod inlay_hint_cache;
   21
   22mod debounced_delay;
   23mod git;
   24mod highlight_matching_bracket;
   25mod hover_links;
   26mod hover_popover;
   27pub mod items;
   28mod mouse_context_menu;
   29pub mod movement;
   30mod persistence;
   31mod rust_analyzer_ext;
   32pub mod scroll;
   33mod selections_collection;
   34
   35#[cfg(test)]
   36mod editor_tests;
   37#[cfg(any(test, feature = "test-support"))]
   38pub mod test;
   39use ::git::diff::DiffHunk;
   40pub(crate) use actions::*;
   41use aho_corasick::AhoCorasick;
   42use anyhow::{anyhow, Context as _, Result};
   43use blink_manager::BlinkManager;
   44use client::{Collaborator, ParticipantIndex};
   45use clock::ReplicaId;
   46use collections::{BTreeMap, Bound, HashMap, HashSet, VecDeque};
   47use convert_case::{Case, Casing};
   48use copilot::Copilot;
   49use debounced_delay::DebouncedDelay;
   50pub use display_map::DisplayPoint;
   51use display_map::*;
   52pub use editor_settings::EditorSettings;
   53use element::LineWithInvisibles;
   54pub use element::{Cursor, EditorElement, HighlightedRange, HighlightedRangeLine};
   55use futures::FutureExt;
   56use fuzzy::{StringMatch, StringMatchCandidate};
   57use git::diff_hunk_to_display;
   58use gpui::{
   59    div, impl_actions, point, prelude::*, px, relative, rems, size, uniform_list, Action,
   60    AnyElement, AppContext, AsyncWindowContext, BackgroundExecutor, Bounds, ClipboardItem, Context,
   61    DispatchPhase, ElementId, EventEmitter, FocusHandle, FocusableView, FontId, FontStyle,
   62    FontWeight, HighlightStyle, Hsla, InteractiveText, KeyContext, Model, MouseButton,
   63    ParentElement, Pixels, Render, SharedString, Styled, StyledText, Subscription, Task, TextStyle,
   64    UnderlineStyle, UniformListScrollHandle, View, ViewContext, ViewInputHandler, VisualContext,
   65    WeakView, WhiteSpace, WindowContext,
   66};
   67use highlight_matching_bracket::refresh_matching_bracket_highlights;
   68use hover_popover::{hide_hover, HoverState};
   69use inlay_hint_cache::{InlayHintCache, InlaySplice, InvalidationStrategy};
   70pub use items::MAX_TAB_TITLE_LEN;
   71use itertools::Itertools;
   72use language::{char_kind, CharKind};
   73use language::{
   74    language_settings::{self, all_language_settings, InlayHintSettings},
   75    markdown, point_from_lsp, AutoindentMode, BracketPair, Buffer, Capability, CodeAction,
   76    CodeLabel, Completion, CursorShape, Diagnostic, Documentation, IndentKind, IndentSize,
   77    Language, OffsetRangeExt, Point, Selection, SelectionGoal, TransactionId,
   78};
   79
   80use hover_links::{HoverLink, HoveredLinkState, InlayHighlight};
   81use lsp::{DiagnosticSeverity, LanguageServerId};
   82use mouse_context_menu::MouseContextMenu;
   83use movement::TextLayoutDetails;
   84use multi_buffer::ToOffsetUtf16;
   85pub use multi_buffer::{
   86    Anchor, AnchorRangeExt, ExcerptId, ExcerptRange, MultiBuffer, MultiBufferSnapshot, ToOffset,
   87    ToPoint,
   88};
   89use ordered_float::OrderedFloat;
   90use parking_lot::{Mutex, RwLock};
   91use project::{FormatTrigger, Location, Project, ProjectPath, ProjectTransaction};
   92use rand::prelude::*;
   93use rpc::proto::*;
   94use scroll::{Autoscroll, OngoingScroll, ScrollAnchor, ScrollManager, ScrollbarAutoHide};
   95use selections_collection::{resolve_multiple, MutableSelectionsCollection, SelectionsCollection};
   96use serde::{Deserialize, Serialize};
   97use settings::{Settings, SettingsStore};
   98use smallvec::SmallVec;
   99use snippet::Snippet;
  100use std::{
  101    any::TypeId,
  102    borrow::Cow,
  103    cmp::{self, Ordering, Reverse},
  104    mem,
  105    num::NonZeroU32,
  106    ops::{ControlFlow, Deref, DerefMut, Range, RangeInclusive},
  107    path::Path,
  108    sync::Arc,
  109    time::{Duration, Instant},
  110};
  111pub use sum_tree::Bias;
  112use sum_tree::TreeMap;
  113use text::{BufferId, OffsetUtf16, Rope};
  114use theme::{
  115    observe_buffer_font_size_adjustment, ActiveTheme, PlayerColor, StatusColors, SyntaxTheme,
  116    ThemeColors, ThemeSettings,
  117};
  118use ui::{
  119    h_flex, prelude::*, ButtonSize, ButtonStyle, IconButton, IconName, IconSize, ListItem, Popover,
  120    Tooltip,
  121};
  122use util::{maybe, post_inc, RangeExt, ResultExt, TryFutureExt};
  123use workspace::Toast;
  124use workspace::{searchable::SearchEvent, ItemNavHistory, Pane, SplitDirection, ViewId, Workspace};
  125
  126const CURSOR_BLINK_INTERVAL: Duration = Duration::from_millis(500);
  127const MAX_LINE_LEN: usize = 1024;
  128const MIN_NAVIGATION_HISTORY_ROW_DELTA: i64 = 10;
  129const MAX_SELECTION_HISTORY_LEN: usize = 1024;
  130const COPILOT_DEBOUNCE_TIMEOUT: Duration = Duration::from_millis(75);
  131pub(crate) const CURSORS_VISIBLE_FOR: Duration = Duration::from_millis(2000);
  132#[doc(hidden)]
  133pub const CODE_ACTIONS_DEBOUNCE_TIMEOUT: Duration = Duration::from_millis(250);
  134#[doc(hidden)]
  135pub const DOCUMENT_HIGHLIGHTS_DEBOUNCE_TIMEOUT: Duration = Duration::from_millis(75);
  136
  137pub(crate) const FORMAT_TIMEOUT: Duration = Duration::from_secs(2);
  138
  139pub fn render_parsed_markdown(
  140    element_id: impl Into<ElementId>,
  141    parsed: &language::ParsedMarkdown,
  142    editor_style: &EditorStyle,
  143    workspace: Option<WeakView<Workspace>>,
  144    cx: &mut ViewContext<Editor>,
  145) -> InteractiveText {
  146    let code_span_background_color = cx
  147        .theme()
  148        .colors()
  149        .editor_document_highlight_read_background;
  150
  151    let highlights = gpui::combine_highlights(
  152        parsed.highlights.iter().filter_map(|(range, highlight)| {
  153            let highlight = highlight.to_highlight_style(&editor_style.syntax)?;
  154            Some((range.clone(), highlight))
  155        }),
  156        parsed
  157            .regions
  158            .iter()
  159            .zip(&parsed.region_ranges)
  160            .filter_map(|(region, range)| {
  161                if region.code {
  162                    Some((
  163                        range.clone(),
  164                        HighlightStyle {
  165                            background_color: Some(code_span_background_color),
  166                            ..Default::default()
  167                        },
  168                    ))
  169                } else {
  170                    None
  171                }
  172            }),
  173    );
  174
  175    let mut links = Vec::new();
  176    let mut link_ranges = Vec::new();
  177    for (range, region) in parsed.region_ranges.iter().zip(&parsed.regions) {
  178        if let Some(link) = region.link.clone() {
  179            links.push(link);
  180            link_ranges.push(range.clone());
  181        }
  182    }
  183
  184    InteractiveText::new(
  185        element_id,
  186        StyledText::new(parsed.text.clone()).with_highlights(&editor_style.text, highlights),
  187    )
  188    .on_click(link_ranges, move |clicked_range_ix, cx| {
  189        match &links[clicked_range_ix] {
  190            markdown::Link::Web { url } => cx.open_url(url),
  191            markdown::Link::Path { path } => {
  192                if let Some(workspace) = &workspace {
  193                    _ = workspace.update(cx, |workspace, cx| {
  194                        workspace.open_abs_path(path.clone(), false, cx).detach();
  195                    });
  196                }
  197            }
  198        }
  199    })
  200}
  201
  202#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
  203pub(crate) enum InlayId {
  204    Suggestion(usize),
  205    Hint(usize),
  206}
  207
  208impl InlayId {
  209    fn id(&self) -> usize {
  210        match self {
  211            Self::Suggestion(id) => *id,
  212            Self::Hint(id) => *id,
  213        }
  214    }
  215}
  216
  217enum DocumentHighlightRead {}
  218enum DocumentHighlightWrite {}
  219enum InputComposition {}
  220
  221#[derive(Copy, Clone, PartialEq, Eq)]
  222pub enum Direction {
  223    Prev,
  224    Next,
  225}
  226
  227pub fn init_settings(cx: &mut AppContext) {
  228    EditorSettings::register(cx);
  229}
  230
  231pub fn init(cx: &mut AppContext) {
  232    init_settings(cx);
  233
  234    workspace::register_project_item::<Editor>(cx);
  235    workspace::register_followable_item::<Editor>(cx);
  236    workspace::register_deserializable_item::<Editor>(cx);
  237    cx.observe_new_views(
  238        |workspace: &mut Workspace, _cx: &mut ViewContext<Workspace>| {
  239            workspace.register_action(Editor::new_file);
  240            workspace.register_action(Editor::new_file_in_direction);
  241        },
  242    )
  243    .detach();
  244
  245    cx.on_action(move |_: &workspace::NewFile, cx| {
  246        let app_state = workspace::AppState::global(cx);
  247        if let Some(app_state) = app_state.upgrade() {
  248            workspace::open_new(&app_state, cx, |workspace, cx| {
  249                Editor::new_file(workspace, &Default::default(), cx)
  250            })
  251            .detach();
  252        }
  253    });
  254    cx.on_action(move |_: &workspace::NewWindow, cx| {
  255        let app_state = workspace::AppState::global(cx);
  256        if let Some(app_state) = app_state.upgrade() {
  257            workspace::open_new(&app_state, cx, |workspace, cx| {
  258                Editor::new_file(workspace, &Default::default(), cx)
  259            })
  260            .detach();
  261        }
  262    });
  263}
  264
  265trait InvalidationRegion {
  266    fn ranges(&self) -> &[Range<Anchor>];
  267}
  268
  269#[derive(Clone, Debug, PartialEq)]
  270pub enum SelectPhase {
  271    Begin {
  272        position: DisplayPoint,
  273        add: bool,
  274        click_count: usize,
  275    },
  276    BeginColumnar {
  277        position: DisplayPoint,
  278        goal_column: u32,
  279    },
  280    Extend {
  281        position: DisplayPoint,
  282        click_count: usize,
  283    },
  284    Update {
  285        position: DisplayPoint,
  286        goal_column: u32,
  287        scroll_delta: gpui::Point<f32>,
  288    },
  289    End,
  290}
  291
  292#[derive(Clone, Debug)]
  293pub(crate) enum SelectMode {
  294    Character,
  295    Word(Range<Anchor>),
  296    Line(Range<Anchor>),
  297    All,
  298}
  299
  300#[derive(Copy, Clone, PartialEq, Eq, Debug)]
  301pub enum EditorMode {
  302    SingleLine,
  303    AutoHeight { max_lines: usize },
  304    Full,
  305}
  306
  307#[derive(Clone, Debug)]
  308pub enum SoftWrap {
  309    None,
  310    EditorWidth,
  311    Column(u32),
  312}
  313
  314#[derive(Clone)]
  315pub struct EditorStyle {
  316    pub background: Hsla,
  317    pub local_player: PlayerColor,
  318    pub text: TextStyle,
  319    pub scrollbar_width: Pixels,
  320    pub syntax: Arc<SyntaxTheme>,
  321    pub status: StatusColors,
  322    pub inlays_style: HighlightStyle,
  323    pub suggestions_style: HighlightStyle,
  324}
  325
  326impl Default for EditorStyle {
  327    fn default() -> Self {
  328        Self {
  329            background: Hsla::default(),
  330            local_player: PlayerColor::default(),
  331            text: TextStyle::default(),
  332            scrollbar_width: Pixels::default(),
  333            syntax: Default::default(),
  334            // HACK: Status colors don't have a real default.
  335            // We should look into removing the status colors from the editor
  336            // style and retrieve them directly from the theme.
  337            status: StatusColors::dark(),
  338            inlays_style: HighlightStyle::default(),
  339            suggestions_style: HighlightStyle::default(),
  340        }
  341    }
  342}
  343
  344type CompletionId = usize;
  345
  346// type GetFieldEditorTheme = dyn Fn(&theme::Theme) -> theme::FieldEditor;
  347// type OverrideTextStyle = dyn Fn(&EditorStyle) -> Option<HighlightStyle>;
  348
  349type BackgroundHighlight = (fn(&ThemeColors) -> Hsla, Vec<Range<Anchor>>);
  350type InlayBackgroundHighlight = (fn(&ThemeColors) -> Hsla, Vec<InlayHighlight>);
  351
  352pub struct Editor {
  353    handle: WeakView<Self>,
  354    focus_handle: FocusHandle,
  355    buffer: Model<MultiBuffer>,
  356    display_map: Model<DisplayMap>,
  357    pub selections: SelectionsCollection,
  358    pub scroll_manager: ScrollManager,
  359    columnar_selection_tail: Option<Anchor>,
  360    add_selections_state: Option<AddSelectionsState>,
  361    select_next_state: Option<SelectNextState>,
  362    select_prev_state: Option<SelectNextState>,
  363    selection_history: SelectionHistory,
  364    autoclose_regions: Vec<AutocloseRegion>,
  365    snippet_stack: InvalidationStack<SnippetState>,
  366    select_larger_syntax_node_stack: Vec<Box<[Selection<usize>]>>,
  367    ime_transaction: Option<TransactionId>,
  368    active_diagnostics: Option<ActiveDiagnosticGroup>,
  369    soft_wrap_mode_override: Option<language_settings::SoftWrap>,
  370    project: Option<Model<Project>>,
  371    completion_provider: Option<Box<dyn CompletionProvider>>,
  372    collaboration_hub: Option<Box<dyn CollaborationHub>>,
  373    blink_manager: Model<BlinkManager>,
  374    show_cursor_names: bool,
  375    hovered_cursors: HashMap<HoveredCursor, Task<()>>,
  376    pub show_local_selections: bool,
  377    mode: EditorMode,
  378    show_breadcrumbs: bool,
  379    show_gutter: bool,
  380    show_wrap_guides: Option<bool>,
  381    placeholder_text: Option<Arc<str>>,
  382    highlighted_rows: Option<Range<u32>>,
  383    background_highlights: BTreeMap<TypeId, BackgroundHighlight>,
  384    inlay_background_highlights: TreeMap<Option<TypeId>, InlayBackgroundHighlight>,
  385    nav_history: Option<ItemNavHistory>,
  386    context_menu: RwLock<Option<ContextMenu>>,
  387    mouse_context_menu: Option<MouseContextMenu>,
  388    completion_tasks: Vec<(CompletionId, Task<Option<()>>)>,
  389    next_completion_id: CompletionId,
  390    completion_documentation_pre_resolve_debounce: DebouncedDelay,
  391    available_code_actions: Option<(Model<Buffer>, Arc<[CodeAction]>)>,
  392    code_actions_task: Option<Task<()>>,
  393    document_highlights_task: Option<Task<()>>,
  394    pending_rename: Option<RenameState>,
  395    searchable: bool,
  396    cursor_shape: CursorShape,
  397    collapse_matches: bool,
  398    autoindent_mode: Option<AutoindentMode>,
  399    workspace: Option<(WeakView<Workspace>, i64)>,
  400    keymap_context_layers: BTreeMap<TypeId, KeyContext>,
  401    input_enabled: bool,
  402    read_only: bool,
  403    leader_peer_id: Option<PeerId>,
  404    remote_id: Option<ViewId>,
  405    hover_state: HoverState,
  406    gutter_hovered: bool,
  407    hovered_link_state: Option<HoveredLinkState>,
  408    copilot_state: CopilotState,
  409    inlay_hint_cache: InlayHintCache,
  410    next_inlay_id: usize,
  411    _subscriptions: Vec<Subscription>,
  412    pixel_position_of_newest_cursor: Option<gpui::Point<Pixels>>,
  413    gutter_width: Pixels,
  414    style: Option<EditorStyle>,
  415    editor_actions: Vec<Box<dyn Fn(&mut ViewContext<Self>)>>,
  416    show_copilot_suggestions: bool,
  417    use_autoclose: bool,
  418    custom_context_menu: Option<
  419        Box<
  420            dyn 'static
  421                + Fn(&mut Self, DisplayPoint, &mut ViewContext<Self>) -> Option<View<ui::ContextMenu>>,
  422        >,
  423    >,
  424}
  425
  426pub struct EditorSnapshot {
  427    pub mode: EditorMode,
  428    show_gutter: bool,
  429    pub display_snapshot: DisplaySnapshot,
  430    pub placeholder_text: Option<Arc<str>>,
  431    is_focused: bool,
  432    scroll_anchor: ScrollAnchor,
  433    ongoing_scroll: OngoingScroll,
  434}
  435
  436pub struct GutterDimensions {
  437    pub padding: Pixels,
  438    pub width: Pixels,
  439    pub margin: Pixels,
  440}
  441
  442impl Default for GutterDimensions {
  443    fn default() -> Self {
  444        Self {
  445            padding: Pixels::ZERO,
  446            width: Pixels::ZERO,
  447            margin: Pixels::ZERO,
  448        }
  449    }
  450}
  451
  452#[derive(Debug)]
  453pub struct RemoteSelection {
  454    pub replica_id: ReplicaId,
  455    pub selection: Selection<Anchor>,
  456    pub cursor_shape: CursorShape,
  457    pub peer_id: PeerId,
  458    pub line_mode: bool,
  459    pub participant_index: Option<ParticipantIndex>,
  460    pub user_name: Option<SharedString>,
  461}
  462
  463#[derive(Clone, Debug)]
  464struct SelectionHistoryEntry {
  465    selections: Arc<[Selection<Anchor>]>,
  466    select_next_state: Option<SelectNextState>,
  467    select_prev_state: Option<SelectNextState>,
  468    add_selections_state: Option<AddSelectionsState>,
  469}
  470
  471enum SelectionHistoryMode {
  472    Normal,
  473    Undoing,
  474    Redoing,
  475}
  476
  477#[derive(Clone, PartialEq, Eq, Hash)]
  478struct HoveredCursor {
  479    replica_id: u16,
  480    selection_id: usize,
  481}
  482
  483impl Default for SelectionHistoryMode {
  484    fn default() -> Self {
  485        Self::Normal
  486    }
  487}
  488
  489#[derive(Default)]
  490struct SelectionHistory {
  491    #[allow(clippy::type_complexity)]
  492    selections_by_transaction:
  493        HashMap<TransactionId, (Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)>,
  494    mode: SelectionHistoryMode,
  495    undo_stack: VecDeque<SelectionHistoryEntry>,
  496    redo_stack: VecDeque<SelectionHistoryEntry>,
  497}
  498
  499impl SelectionHistory {
  500    fn insert_transaction(
  501        &mut self,
  502        transaction_id: TransactionId,
  503        selections: Arc<[Selection<Anchor>]>,
  504    ) {
  505        self.selections_by_transaction
  506            .insert(transaction_id, (selections, None));
  507    }
  508
  509    #[allow(clippy::type_complexity)]
  510    fn transaction(
  511        &self,
  512        transaction_id: TransactionId,
  513    ) -> Option<&(Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)> {
  514        self.selections_by_transaction.get(&transaction_id)
  515    }
  516
  517    #[allow(clippy::type_complexity)]
  518    fn transaction_mut(
  519        &mut self,
  520        transaction_id: TransactionId,
  521    ) -> Option<&mut (Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)> {
  522        self.selections_by_transaction.get_mut(&transaction_id)
  523    }
  524
  525    fn push(&mut self, entry: SelectionHistoryEntry) {
  526        if !entry.selections.is_empty() {
  527            match self.mode {
  528                SelectionHistoryMode::Normal => {
  529                    self.push_undo(entry);
  530                    self.redo_stack.clear();
  531                }
  532                SelectionHistoryMode::Undoing => self.push_redo(entry),
  533                SelectionHistoryMode::Redoing => self.push_undo(entry),
  534            }
  535        }
  536    }
  537
  538    fn push_undo(&mut self, entry: SelectionHistoryEntry) {
  539        if self
  540            .undo_stack
  541            .back()
  542            .map_or(true, |e| e.selections != entry.selections)
  543        {
  544            self.undo_stack.push_back(entry);
  545            if self.undo_stack.len() > MAX_SELECTION_HISTORY_LEN {
  546                self.undo_stack.pop_front();
  547            }
  548        }
  549    }
  550
  551    fn push_redo(&mut self, entry: SelectionHistoryEntry) {
  552        if self
  553            .redo_stack
  554            .back()
  555            .map_or(true, |e| e.selections != entry.selections)
  556        {
  557            self.redo_stack.push_back(entry);
  558            if self.redo_stack.len() > MAX_SELECTION_HISTORY_LEN {
  559                self.redo_stack.pop_front();
  560            }
  561        }
  562    }
  563}
  564
  565#[derive(Clone, Debug)]
  566struct AddSelectionsState {
  567    above: bool,
  568    stack: Vec<usize>,
  569}
  570
  571#[derive(Clone)]
  572struct SelectNextState {
  573    query: AhoCorasick,
  574    wordwise: bool,
  575    done: bool,
  576}
  577
  578impl std::fmt::Debug for SelectNextState {
  579    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  580        f.debug_struct(std::any::type_name::<Self>())
  581            .field("wordwise", &self.wordwise)
  582            .field("done", &self.done)
  583            .finish()
  584    }
  585}
  586
  587#[derive(Debug)]
  588struct AutocloseRegion {
  589    selection_id: usize,
  590    range: Range<Anchor>,
  591    pair: BracketPair,
  592}
  593
  594#[derive(Debug)]
  595struct SnippetState {
  596    ranges: Vec<Vec<Range<Anchor>>>,
  597    active_index: usize,
  598}
  599
  600#[doc(hidden)]
  601pub struct RenameState {
  602    pub range: Range<Anchor>,
  603    pub old_name: Arc<str>,
  604    pub editor: View<Editor>,
  605    block_id: BlockId,
  606}
  607
  608struct InvalidationStack<T>(Vec<T>);
  609
  610enum ContextMenu {
  611    Completions(CompletionsMenu),
  612    CodeActions(CodeActionsMenu),
  613}
  614
  615impl ContextMenu {
  616    fn select_first(
  617        &mut self,
  618        project: Option<&Model<Project>>,
  619        cx: &mut ViewContext<Editor>,
  620    ) -> bool {
  621        if self.visible() {
  622            match self {
  623                ContextMenu::Completions(menu) => menu.select_first(project, cx),
  624                ContextMenu::CodeActions(menu) => menu.select_first(cx),
  625            }
  626            true
  627        } else {
  628            false
  629        }
  630    }
  631
  632    fn select_prev(
  633        &mut self,
  634        project: Option<&Model<Project>>,
  635        cx: &mut ViewContext<Editor>,
  636    ) -> bool {
  637        if self.visible() {
  638            match self {
  639                ContextMenu::Completions(menu) => menu.select_prev(project, cx),
  640                ContextMenu::CodeActions(menu) => menu.select_prev(cx),
  641            }
  642            true
  643        } else {
  644            false
  645        }
  646    }
  647
  648    fn select_next(
  649        &mut self,
  650        project: Option<&Model<Project>>,
  651        cx: &mut ViewContext<Editor>,
  652    ) -> bool {
  653        if self.visible() {
  654            match self {
  655                ContextMenu::Completions(menu) => menu.select_next(project, cx),
  656                ContextMenu::CodeActions(menu) => menu.select_next(cx),
  657            }
  658            true
  659        } else {
  660            false
  661        }
  662    }
  663
  664    fn select_last(
  665        &mut self,
  666        project: Option<&Model<Project>>,
  667        cx: &mut ViewContext<Editor>,
  668    ) -> bool {
  669        if self.visible() {
  670            match self {
  671                ContextMenu::Completions(menu) => menu.select_last(project, cx),
  672                ContextMenu::CodeActions(menu) => menu.select_last(cx),
  673            }
  674            true
  675        } else {
  676            false
  677        }
  678    }
  679
  680    fn visible(&self) -> bool {
  681        match self {
  682            ContextMenu::Completions(menu) => menu.visible(),
  683            ContextMenu::CodeActions(menu) => menu.visible(),
  684        }
  685    }
  686
  687    fn render(
  688        &self,
  689        cursor_position: DisplayPoint,
  690        style: &EditorStyle,
  691        max_height: Pixels,
  692        workspace: Option<WeakView<Workspace>>,
  693        cx: &mut ViewContext<Editor>,
  694    ) -> (DisplayPoint, AnyElement) {
  695        match self {
  696            ContextMenu::Completions(menu) => (
  697                cursor_position,
  698                menu.render(style, max_height, workspace, cx),
  699            ),
  700            ContextMenu::CodeActions(menu) => menu.render(cursor_position, style, max_height, cx),
  701        }
  702    }
  703}
  704
  705#[derive(Clone)]
  706struct CompletionsMenu {
  707    id: CompletionId,
  708    initial_position: Anchor,
  709    buffer: Model<Buffer>,
  710    completions: Arc<RwLock<Box<[Completion]>>>,
  711    match_candidates: Arc<[StringMatchCandidate]>,
  712    matches: Arc<[StringMatch]>,
  713    selected_item: usize,
  714    scroll_handle: UniformListScrollHandle,
  715    selected_completion_documentation_resolve_debounce: Arc<Mutex<DebouncedDelay>>,
  716}
  717
  718impl CompletionsMenu {
  719    fn select_first(&mut self, project: Option<&Model<Project>>, cx: &mut ViewContext<Editor>) {
  720        self.selected_item = 0;
  721        self.scroll_handle.scroll_to_item(self.selected_item);
  722        self.attempt_resolve_selected_completion_documentation(project, cx);
  723        cx.notify();
  724    }
  725
  726    fn select_prev(&mut self, project: Option<&Model<Project>>, cx: &mut ViewContext<Editor>) {
  727        if self.selected_item > 0 {
  728            self.selected_item -= 1;
  729        } else {
  730            self.selected_item = self.matches.len() - 1;
  731        }
  732        self.scroll_handle.scroll_to_item(self.selected_item);
  733        self.attempt_resolve_selected_completion_documentation(project, cx);
  734        cx.notify();
  735    }
  736
  737    fn select_next(&mut self, project: Option<&Model<Project>>, cx: &mut ViewContext<Editor>) {
  738        if self.selected_item + 1 < self.matches.len() {
  739            self.selected_item += 1;
  740        } else {
  741            self.selected_item = 0;
  742        }
  743        self.scroll_handle.scroll_to_item(self.selected_item);
  744        self.attempt_resolve_selected_completion_documentation(project, cx);
  745        cx.notify();
  746    }
  747
  748    fn select_last(&mut self, project: Option<&Model<Project>>, cx: &mut ViewContext<Editor>) {
  749        self.selected_item = self.matches.len() - 1;
  750        self.scroll_handle.scroll_to_item(self.selected_item);
  751        self.attempt_resolve_selected_completion_documentation(project, cx);
  752        cx.notify();
  753    }
  754
  755    fn pre_resolve_completion_documentation(
  756        completions: Arc<RwLock<Box<[Completion]>>>,
  757        matches: Arc<[StringMatch]>,
  758        editor: &Editor,
  759        cx: &mut ViewContext<Editor>,
  760    ) -> Task<()> {
  761        let settings = EditorSettings::get_global(cx);
  762        if !settings.show_completion_documentation {
  763            return Task::ready(());
  764        }
  765
  766        let Some(provider) = editor.completion_provider.as_ref() else {
  767            return Task::ready(());
  768        };
  769
  770        let resolve_task = provider.resolve_completions(
  771            matches.iter().map(|m| m.candidate_id).collect(),
  772            completions.clone(),
  773            cx,
  774        );
  775
  776        return cx.spawn(move |this, mut cx| async move {
  777            if let Some(true) = resolve_task.await.log_err() {
  778                this.update(&mut cx, |_, cx| cx.notify()).ok();
  779            }
  780        });
  781    }
  782
  783    fn attempt_resolve_selected_completion_documentation(
  784        &mut self,
  785        project: Option<&Model<Project>>,
  786        cx: &mut ViewContext<Editor>,
  787    ) {
  788        let settings = EditorSettings::get_global(cx);
  789        if !settings.show_completion_documentation {
  790            return;
  791        }
  792
  793        let completion_index = self.matches[self.selected_item].candidate_id;
  794        let Some(project) = project else {
  795            return;
  796        };
  797
  798        let resolve_task = project.update(cx, |project, cx| {
  799            project.resolve_completions(vec![completion_index], self.completions.clone(), cx)
  800        });
  801
  802        let delay_ms =
  803            EditorSettings::get_global(cx).completion_documentation_secondary_query_debounce;
  804        let delay = Duration::from_millis(delay_ms);
  805
  806        self.selected_completion_documentation_resolve_debounce
  807            .lock()
  808            .fire_new(delay, cx, |_, cx| {
  809                cx.spawn(move |this, mut cx| async move {
  810                    if let Some(true) = resolve_task.await.log_err() {
  811                        this.update(&mut cx, |_, cx| cx.notify()).ok();
  812                    }
  813                })
  814            });
  815    }
  816
  817    fn visible(&self) -> bool {
  818        !self.matches.is_empty()
  819    }
  820
  821    fn render(
  822        &self,
  823        style: &EditorStyle,
  824        max_height: Pixels,
  825        workspace: Option<WeakView<Workspace>>,
  826        cx: &mut ViewContext<Editor>,
  827    ) -> AnyElement {
  828        let settings = EditorSettings::get_global(cx);
  829        let show_completion_documentation = settings.show_completion_documentation;
  830
  831        let widest_completion_ix = self
  832            .matches
  833            .iter()
  834            .enumerate()
  835            .max_by_key(|(_, mat)| {
  836                let completions = self.completions.read();
  837                let completion = &completions[mat.candidate_id];
  838                let documentation = &completion.documentation;
  839
  840                let mut len = completion.label.text.chars().count();
  841                if let Some(Documentation::SingleLine(text)) = documentation {
  842                    if show_completion_documentation {
  843                        len += text.chars().count();
  844                    }
  845                }
  846
  847                len
  848            })
  849            .map(|(ix, _)| ix);
  850
  851        let completions = self.completions.clone();
  852        let matches = self.matches.clone();
  853        let selected_item = self.selected_item;
  854        let style = style.clone();
  855
  856        let multiline_docs = if show_completion_documentation {
  857            let mat = &self.matches[selected_item];
  858            let multiline_docs = match &self.completions.read()[mat.candidate_id].documentation {
  859                Some(Documentation::MultiLinePlainText(text)) => {
  860                    Some(div().child(SharedString::from(text.clone())))
  861                }
  862                Some(Documentation::MultiLineMarkdown(parsed)) if !parsed.text.is_empty() => {
  863                    Some(div().child(render_parsed_markdown(
  864                        "completions_markdown",
  865                        parsed,
  866                        &style,
  867                        workspace,
  868                        cx,
  869                    )))
  870                }
  871                _ => None,
  872            };
  873            multiline_docs.map(|div| {
  874                div.id("multiline_docs")
  875                    .max_h(max_height)
  876                    .flex_1()
  877                    .px_1p5()
  878                    .py_1()
  879                    .min_w(px(260.))
  880                    .max_w(px(640.))
  881                    .w(px(500.))
  882                    .overflow_y_scroll()
  883                    // Prevent a mouse down on documentation from being propagated to the editor,
  884                    // because that would move the cursor.
  885                    .on_mouse_down(MouseButton::Left, |_, cx| cx.stop_propagation())
  886            })
  887        } else {
  888            None
  889        };
  890
  891        let list = uniform_list(
  892            cx.view().clone(),
  893            "completions",
  894            matches.len(),
  895            move |_editor, range, cx| {
  896                let start_ix = range.start;
  897                let completions_guard = completions.read();
  898
  899                matches[range]
  900                    .iter()
  901                    .enumerate()
  902                    .map(|(ix, mat)| {
  903                        let item_ix = start_ix + ix;
  904                        let candidate_id = mat.candidate_id;
  905                        let completion = &completions_guard[candidate_id];
  906
  907                        let documentation = if show_completion_documentation {
  908                            &completion.documentation
  909                        } else {
  910                            &None
  911                        };
  912
  913                        let highlights = gpui::combine_highlights(
  914                            mat.ranges().map(|range| (range, FontWeight::BOLD.into())),
  915                            styled_runs_for_code_label(&completion.label, &style.syntax).map(
  916                                |(range, mut highlight)| {
  917                                    // Ignore font weight for syntax highlighting, as we'll use it
  918                                    // for fuzzy matches.
  919                                    highlight.font_weight = None;
  920                                    (range, highlight)
  921                                },
  922                            ),
  923                        );
  924                        let completion_label = StyledText::new(completion.label.text.clone())
  925                            .with_highlights(&style.text, highlights);
  926                        let documentation_label =
  927                            if let Some(Documentation::SingleLine(text)) = documentation {
  928                                if text.trim().is_empty() {
  929                                    None
  930                                } else {
  931                                    Some(
  932                                        h_flex().ml_4().child(
  933                                            Label::new(text.clone())
  934                                                .size(LabelSize::Small)
  935                                                .color(Color::Muted),
  936                                        ),
  937                                    )
  938                                }
  939                            } else {
  940                                None
  941                            };
  942
  943                        div().min_w(px(220.)).max_w(px(540.)).child(
  944                            ListItem::new(mat.candidate_id)
  945                                .inset(true)
  946                                .selected(item_ix == selected_item)
  947                                .on_click(cx.listener(move |editor, _event, cx| {
  948                                    cx.stop_propagation();
  949                                    editor
  950                                        .confirm_completion(
  951                                            &ConfirmCompletion {
  952                                                item_ix: Some(item_ix),
  953                                            },
  954                                            cx,
  955                                        )
  956                                        .map(|task| task.detach_and_log_err(cx));
  957                                }))
  958                                .child(h_flex().overflow_hidden().child(completion_label))
  959                                .end_slot::<Div>(documentation_label),
  960                        )
  961                    })
  962                    .collect()
  963            },
  964        )
  965        .max_h(max_height)
  966        .track_scroll(self.scroll_handle.clone())
  967        .with_width_from_item(widest_completion_ix);
  968
  969        Popover::new()
  970            .child(list)
  971            .when_some(multiline_docs, |popover, multiline_docs| {
  972                popover.aside(multiline_docs)
  973            })
  974            .into_any_element()
  975    }
  976
  977    pub async fn filter(&mut self, query: Option<&str>, executor: BackgroundExecutor) {
  978        let mut matches = if let Some(query) = query {
  979            fuzzy::match_strings(
  980                &self.match_candidates,
  981                query,
  982                query.chars().any(|c| c.is_uppercase()),
  983                100,
  984                &Default::default(),
  985                executor,
  986            )
  987            .await
  988        } else {
  989            self.match_candidates
  990                .iter()
  991                .enumerate()
  992                .map(|(candidate_id, candidate)| StringMatch {
  993                    candidate_id,
  994                    score: Default::default(),
  995                    positions: Default::default(),
  996                    string: candidate.string.clone(),
  997                })
  998                .collect()
  999        };
 1000
 1001        // Remove all candidates where the query's start does not match the start of any word in the candidate
 1002        if let Some(query) = query {
 1003            if let Some(query_start) = query.chars().next() {
 1004                matches.retain(|string_match| {
 1005                    split_words(&string_match.string).any(|word| {
 1006                        // Check that the first codepoint of the word as lowercase matches the first
 1007                        // codepoint of the query as lowercase
 1008                        word.chars()
 1009                            .flat_map(|codepoint| codepoint.to_lowercase())
 1010                            .zip(query_start.to_lowercase())
 1011                            .all(|(word_cp, query_cp)| word_cp == query_cp)
 1012                    })
 1013                });
 1014            }
 1015        }
 1016
 1017        let completions = self.completions.read();
 1018        matches.sort_unstable_by_key(|mat| {
 1019            let completion = &completions[mat.candidate_id];
 1020            (
 1021                completion.lsp_completion.sort_text.as_ref(),
 1022                Reverse(OrderedFloat(mat.score)),
 1023                completion.sort_key(),
 1024            )
 1025        });
 1026
 1027        for mat in &mut matches {
 1028            let completion = &completions[mat.candidate_id];
 1029            mat.string = completion.label.text.clone();
 1030            for position in &mut mat.positions {
 1031                *position += completion.label.filter_range.start;
 1032            }
 1033        }
 1034        drop(completions);
 1035
 1036        self.matches = matches.into();
 1037        self.selected_item = 0;
 1038    }
 1039}
 1040
 1041#[derive(Clone)]
 1042struct CodeActionsMenu {
 1043    actions: Arc<[CodeAction]>,
 1044    buffer: Model<Buffer>,
 1045    selected_item: usize,
 1046    scroll_handle: UniformListScrollHandle,
 1047    deployed_from_indicator: bool,
 1048}
 1049
 1050impl CodeActionsMenu {
 1051    fn select_first(&mut self, cx: &mut ViewContext<Editor>) {
 1052        self.selected_item = 0;
 1053        self.scroll_handle.scroll_to_item(self.selected_item);
 1054        cx.notify()
 1055    }
 1056
 1057    fn select_prev(&mut self, cx: &mut ViewContext<Editor>) {
 1058        if self.selected_item > 0 {
 1059            self.selected_item -= 1;
 1060        } else {
 1061            self.selected_item = self.actions.len() - 1;
 1062        }
 1063        self.scroll_handle.scroll_to_item(self.selected_item);
 1064        cx.notify();
 1065    }
 1066
 1067    fn select_next(&mut self, cx: &mut ViewContext<Editor>) {
 1068        if self.selected_item + 1 < self.actions.len() {
 1069            self.selected_item += 1;
 1070        } else {
 1071            self.selected_item = 0;
 1072        }
 1073        self.scroll_handle.scroll_to_item(self.selected_item);
 1074        cx.notify();
 1075    }
 1076
 1077    fn select_last(&mut self, cx: &mut ViewContext<Editor>) {
 1078        self.selected_item = self.actions.len() - 1;
 1079        self.scroll_handle.scroll_to_item(self.selected_item);
 1080        cx.notify()
 1081    }
 1082
 1083    fn visible(&self) -> bool {
 1084        !self.actions.is_empty()
 1085    }
 1086
 1087    fn render(
 1088        &self,
 1089        mut cursor_position: DisplayPoint,
 1090        _style: &EditorStyle,
 1091        max_height: Pixels,
 1092        cx: &mut ViewContext<Editor>,
 1093    ) -> (DisplayPoint, AnyElement) {
 1094        let actions = self.actions.clone();
 1095        let selected_item = self.selected_item;
 1096
 1097        let element = uniform_list(
 1098            cx.view().clone(),
 1099            "code_actions_menu",
 1100            self.actions.len(),
 1101            move |_this, range, cx| {
 1102                actions[range.clone()]
 1103                    .iter()
 1104                    .enumerate()
 1105                    .map(|(ix, action)| {
 1106                        let item_ix = range.start + ix;
 1107                        let selected = selected_item == item_ix;
 1108                        let colors = cx.theme().colors();
 1109                        div()
 1110                            .px_2()
 1111                            .text_color(colors.text)
 1112                            .when(selected, |style| {
 1113                                style
 1114                                    .bg(colors.element_active)
 1115                                    .text_color(colors.text_accent)
 1116                            })
 1117                            .hover(|style| {
 1118                                style
 1119                                    .bg(colors.element_hover)
 1120                                    .text_color(colors.text_accent)
 1121                            })
 1122                            .on_mouse_down(
 1123                                MouseButton::Left,
 1124                                cx.listener(move |editor, _, cx| {
 1125                                    cx.stop_propagation();
 1126                                    editor
 1127                                        .confirm_code_action(
 1128                                            &ConfirmCodeAction {
 1129                                                item_ix: Some(item_ix),
 1130                                            },
 1131                                            cx,
 1132                                        )
 1133                                        .map(|task| task.detach_and_log_err(cx));
 1134                                }),
 1135                            )
 1136                            // TASK: It would be good to make lsp_action.title a SharedString to avoid allocating here.
 1137                            .child(SharedString::from(action.lsp_action.title.clone()))
 1138                    })
 1139                    .collect()
 1140            },
 1141        )
 1142        .elevation_1(cx)
 1143        .px_2()
 1144        .py_1()
 1145        .max_h(max_height)
 1146        .track_scroll(self.scroll_handle.clone())
 1147        .with_width_from_item(
 1148            self.actions
 1149                .iter()
 1150                .enumerate()
 1151                .max_by_key(|(_, action)| action.lsp_action.title.chars().count())
 1152                .map(|(ix, _)| ix),
 1153        )
 1154        .into_any_element();
 1155
 1156        if self.deployed_from_indicator {
 1157            *cursor_position.column_mut() = 0;
 1158        }
 1159
 1160        (cursor_position, element)
 1161    }
 1162}
 1163
 1164pub(crate) struct CopilotState {
 1165    excerpt_id: Option<ExcerptId>,
 1166    pending_refresh: Task<Option<()>>,
 1167    pending_cycling_refresh: Task<Option<()>>,
 1168    cycled: bool,
 1169    completions: Vec<copilot::Completion>,
 1170    active_completion_index: usize,
 1171    suggestion: Option<Inlay>,
 1172}
 1173
 1174impl Default for CopilotState {
 1175    fn default() -> Self {
 1176        Self {
 1177            excerpt_id: None,
 1178            pending_cycling_refresh: Task::ready(Some(())),
 1179            pending_refresh: Task::ready(Some(())),
 1180            completions: Default::default(),
 1181            active_completion_index: 0,
 1182            cycled: false,
 1183            suggestion: None,
 1184        }
 1185    }
 1186}
 1187
 1188impl CopilotState {
 1189    fn active_completion(&self) -> Option<&copilot::Completion> {
 1190        self.completions.get(self.active_completion_index)
 1191    }
 1192
 1193    fn text_for_active_completion(
 1194        &self,
 1195        cursor: Anchor,
 1196        buffer: &MultiBufferSnapshot,
 1197    ) -> Option<&str> {
 1198        use language::ToOffset as _;
 1199
 1200        let completion = self.active_completion()?;
 1201        let excerpt_id = self.excerpt_id?;
 1202        let completion_buffer = buffer.buffer_for_excerpt(excerpt_id)?;
 1203        if excerpt_id != cursor.excerpt_id
 1204            || !completion.range.start.is_valid(completion_buffer)
 1205            || !completion.range.end.is_valid(completion_buffer)
 1206        {
 1207            return None;
 1208        }
 1209
 1210        let mut completion_range = completion.range.to_offset(&completion_buffer);
 1211        let prefix_len = Self::common_prefix(
 1212            completion_buffer.chars_for_range(completion_range.clone()),
 1213            completion.text.chars(),
 1214        );
 1215        completion_range.start += prefix_len;
 1216        let suffix_len = Self::common_prefix(
 1217            completion_buffer.reversed_chars_for_range(completion_range.clone()),
 1218            completion.text[prefix_len..].chars().rev(),
 1219        );
 1220        completion_range.end = completion_range.end.saturating_sub(suffix_len);
 1221
 1222        if completion_range.is_empty()
 1223            && completion_range.start == cursor.text_anchor.to_offset(&completion_buffer)
 1224        {
 1225            Some(&completion.text[prefix_len..completion.text.len() - suffix_len])
 1226        } else {
 1227            None
 1228        }
 1229    }
 1230
 1231    fn cycle_completions(&mut self, direction: Direction) {
 1232        match direction {
 1233            Direction::Prev => {
 1234                self.active_completion_index = if self.active_completion_index == 0 {
 1235                    self.completions.len().saturating_sub(1)
 1236                } else {
 1237                    self.active_completion_index - 1
 1238                };
 1239            }
 1240            Direction::Next => {
 1241                if self.completions.len() == 0 {
 1242                    self.active_completion_index = 0
 1243                } else {
 1244                    self.active_completion_index =
 1245                        (self.active_completion_index + 1) % self.completions.len();
 1246                }
 1247            }
 1248        }
 1249    }
 1250
 1251    fn push_completion(&mut self, new_completion: copilot::Completion) {
 1252        for completion in &self.completions {
 1253            if completion.text == new_completion.text && completion.range == new_completion.range {
 1254                return;
 1255            }
 1256        }
 1257        self.completions.push(new_completion);
 1258    }
 1259
 1260    fn common_prefix<T1: Iterator<Item = char>, T2: Iterator<Item = char>>(a: T1, b: T2) -> usize {
 1261        a.zip(b)
 1262            .take_while(|(a, b)| a == b)
 1263            .map(|(a, _)| a.len_utf8())
 1264            .sum()
 1265    }
 1266}
 1267
 1268#[derive(Debug)]
 1269struct ActiveDiagnosticGroup {
 1270    primary_range: Range<Anchor>,
 1271    primary_message: String,
 1272    blocks: HashMap<BlockId, Diagnostic>,
 1273    is_valid: bool,
 1274}
 1275
 1276#[derive(Serialize, Deserialize)]
 1277pub struct ClipboardSelection {
 1278    pub len: usize,
 1279    pub is_entire_line: bool,
 1280    pub first_line_indent: u32,
 1281}
 1282
 1283#[derive(Debug)]
 1284pub(crate) struct NavigationData {
 1285    cursor_anchor: Anchor,
 1286    cursor_position: Point,
 1287    scroll_anchor: ScrollAnchor,
 1288    scroll_top_row: u32,
 1289}
 1290
 1291enum GotoDefinitionKind {
 1292    Symbol,
 1293    Type,
 1294}
 1295
 1296#[derive(Debug, Clone)]
 1297enum InlayHintRefreshReason {
 1298    Toggle(bool),
 1299    SettingsChange(InlayHintSettings),
 1300    NewLinesShown,
 1301    BufferEdited(HashSet<Arc<Language>>),
 1302    RefreshRequested,
 1303    ExcerptsRemoved(Vec<ExcerptId>),
 1304}
 1305impl InlayHintRefreshReason {
 1306    fn description(&self) -> &'static str {
 1307        match self {
 1308            Self::Toggle(_) => "toggle",
 1309            Self::SettingsChange(_) => "settings change",
 1310            Self::NewLinesShown => "new lines shown",
 1311            Self::BufferEdited(_) => "buffer edited",
 1312            Self::RefreshRequested => "refresh requested",
 1313            Self::ExcerptsRemoved(_) => "excerpts removed",
 1314        }
 1315    }
 1316}
 1317
 1318impl Editor {
 1319    pub fn single_line(cx: &mut ViewContext<Self>) -> Self {
 1320        let buffer = cx.new_model(|cx| {
 1321            Buffer::new(
 1322                0,
 1323                BufferId::new(cx.entity_id().as_u64()).unwrap(),
 1324                String::new(),
 1325            )
 1326        });
 1327        let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
 1328        Self::new(EditorMode::SingleLine, buffer, None, cx)
 1329    }
 1330
 1331    pub fn multi_line(cx: &mut ViewContext<Self>) -> Self {
 1332        let buffer = cx.new_model(|cx| {
 1333            Buffer::new(
 1334                0,
 1335                BufferId::new(cx.entity_id().as_u64()).unwrap(),
 1336                String::new(),
 1337            )
 1338        });
 1339        let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
 1340        Self::new(EditorMode::Full, buffer, None, cx)
 1341    }
 1342
 1343    pub fn auto_height(max_lines: usize, cx: &mut ViewContext<Self>) -> Self {
 1344        let buffer = cx.new_model(|cx| {
 1345            Buffer::new(
 1346                0,
 1347                BufferId::new(cx.entity_id().as_u64()).unwrap(),
 1348                String::new(),
 1349            )
 1350        });
 1351        let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
 1352        Self::new(EditorMode::AutoHeight { max_lines }, buffer, None, cx)
 1353    }
 1354
 1355    pub fn for_buffer(
 1356        buffer: Model<Buffer>,
 1357        project: Option<Model<Project>>,
 1358        cx: &mut ViewContext<Self>,
 1359    ) -> Self {
 1360        let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
 1361        Self::new(EditorMode::Full, buffer, project, cx)
 1362    }
 1363
 1364    pub fn for_multibuffer(
 1365        buffer: Model<MultiBuffer>,
 1366        project: Option<Model<Project>>,
 1367        cx: &mut ViewContext<Self>,
 1368    ) -> Self {
 1369        Self::new(EditorMode::Full, buffer, project, cx)
 1370    }
 1371
 1372    pub fn clone(&self, cx: &mut ViewContext<Self>) -> Self {
 1373        let mut clone = Self::new(self.mode, self.buffer.clone(), self.project.clone(), cx);
 1374        self.display_map.update(cx, |display_map, cx| {
 1375            let snapshot = display_map.snapshot(cx);
 1376            clone.display_map.update(cx, |display_map, cx| {
 1377                display_map.set_state(&snapshot, cx);
 1378            });
 1379        });
 1380        clone.selections.clone_state(&self.selections);
 1381        clone.scroll_manager.clone_state(&self.scroll_manager);
 1382        clone.searchable = self.searchable;
 1383        clone
 1384    }
 1385
 1386    fn new(
 1387        mode: EditorMode,
 1388        buffer: Model<MultiBuffer>,
 1389        project: Option<Model<Project>>,
 1390        cx: &mut ViewContext<Self>,
 1391    ) -> Self {
 1392        let style = cx.text_style();
 1393        let font_size = style.font_size.to_pixels(cx.rem_size());
 1394        let display_map = cx.new_model(|cx| {
 1395            DisplayMap::new(buffer.clone(), style.font(), font_size, None, 2, 1, cx)
 1396        });
 1397
 1398        let selections = SelectionsCollection::new(display_map.clone(), buffer.clone());
 1399
 1400        let blink_manager = cx.new_model(|cx| BlinkManager::new(CURSOR_BLINK_INTERVAL, cx));
 1401
 1402        let soft_wrap_mode_override =
 1403            (mode == EditorMode::SingleLine).then(|| language_settings::SoftWrap::None);
 1404
 1405        let mut project_subscriptions = Vec::new();
 1406        if mode == EditorMode::Full {
 1407            if let Some(project) = project.as_ref() {
 1408                if buffer.read(cx).is_singleton() {
 1409                    project_subscriptions.push(cx.observe(project, |_, _, cx| {
 1410                        cx.emit(EditorEvent::TitleChanged);
 1411                    }));
 1412                }
 1413                project_subscriptions.push(cx.subscribe(project, |editor, _, event, cx| {
 1414                    if let project::Event::RefreshInlayHints = event {
 1415                        editor.refresh_inlay_hints(InlayHintRefreshReason::RefreshRequested, cx);
 1416                    };
 1417                }));
 1418            }
 1419        }
 1420
 1421        let inlay_hint_settings = inlay_hint_settings(
 1422            selections.newest_anchor().head(),
 1423            &buffer.read(cx).snapshot(cx),
 1424            cx,
 1425        );
 1426
 1427        let focus_handle = cx.focus_handle();
 1428        cx.on_focus(&focus_handle, Self::handle_focus).detach();
 1429        cx.on_blur(&focus_handle, Self::handle_blur).detach();
 1430
 1431        let mut this = Self {
 1432            handle: cx.view().downgrade(),
 1433            focus_handle,
 1434            buffer: buffer.clone(),
 1435            display_map: display_map.clone(),
 1436            selections,
 1437            scroll_manager: ScrollManager::new(cx),
 1438            columnar_selection_tail: None,
 1439            add_selections_state: None,
 1440            select_next_state: None,
 1441            select_prev_state: None,
 1442            selection_history: Default::default(),
 1443            autoclose_regions: Default::default(),
 1444            snippet_stack: Default::default(),
 1445            select_larger_syntax_node_stack: Vec::new(),
 1446            ime_transaction: Default::default(),
 1447            active_diagnostics: None,
 1448            soft_wrap_mode_override,
 1449            completion_provider: project.clone().map(|project| Box::new(project) as _),
 1450            collaboration_hub: project.clone().map(|project| Box::new(project) as _),
 1451            project,
 1452            blink_manager: blink_manager.clone(),
 1453            show_local_selections: true,
 1454            mode,
 1455            show_breadcrumbs: EditorSettings::get_global(cx).toolbar.breadcrumbs,
 1456            show_gutter: mode == EditorMode::Full,
 1457            show_wrap_guides: None,
 1458            placeholder_text: None,
 1459            highlighted_rows: None,
 1460            background_highlights: Default::default(),
 1461            inlay_background_highlights: Default::default(),
 1462            nav_history: None,
 1463            context_menu: RwLock::new(None),
 1464            mouse_context_menu: None,
 1465            completion_tasks: Default::default(),
 1466            next_completion_id: 0,
 1467            completion_documentation_pre_resolve_debounce: DebouncedDelay::new(),
 1468            next_inlay_id: 0,
 1469            available_code_actions: Default::default(),
 1470            code_actions_task: Default::default(),
 1471            document_highlights_task: Default::default(),
 1472            pending_rename: Default::default(),
 1473            searchable: true,
 1474            cursor_shape: Default::default(),
 1475            autoindent_mode: Some(AutoindentMode::EachLine),
 1476            collapse_matches: false,
 1477            workspace: None,
 1478            keymap_context_layers: Default::default(),
 1479            input_enabled: true,
 1480            read_only: false,
 1481            use_autoclose: true,
 1482            leader_peer_id: None,
 1483            remote_id: None,
 1484            hover_state: Default::default(),
 1485            hovered_link_state: Default::default(),
 1486            copilot_state: Default::default(),
 1487            inlay_hint_cache: InlayHintCache::new(inlay_hint_settings),
 1488            gutter_hovered: false,
 1489            pixel_position_of_newest_cursor: None,
 1490            gutter_width: Default::default(),
 1491            style: None,
 1492            show_cursor_names: false,
 1493            hovered_cursors: Default::default(),
 1494            editor_actions: Default::default(),
 1495            show_copilot_suggestions: mode == EditorMode::Full,
 1496            custom_context_menu: None,
 1497            _subscriptions: vec![
 1498                cx.observe(&buffer, Self::on_buffer_changed),
 1499                cx.subscribe(&buffer, Self::on_buffer_event),
 1500                cx.observe(&display_map, Self::on_display_map_changed),
 1501                cx.observe(&blink_manager, |_, _, cx| cx.notify()),
 1502                cx.observe_global::<SettingsStore>(Self::settings_changed),
 1503                observe_buffer_font_size_adjustment(cx, |_, cx| cx.notify()),
 1504                cx.observe_window_activation(|editor, cx| {
 1505                    let active = cx.is_window_active();
 1506                    editor.blink_manager.update(cx, |blink_manager, cx| {
 1507                        if active {
 1508                            blink_manager.enable(cx);
 1509                        } else {
 1510                            blink_manager.show_cursor(cx);
 1511                            blink_manager.disable(cx);
 1512                        }
 1513                    });
 1514                }),
 1515            ],
 1516        };
 1517
 1518        this._subscriptions.extend(project_subscriptions);
 1519
 1520        this.end_selection(cx);
 1521        this.scroll_manager.show_scrollbar(cx);
 1522
 1523        if mode == EditorMode::Full {
 1524            let should_auto_hide_scrollbars = cx.should_auto_hide_scrollbars();
 1525            cx.set_global(ScrollbarAutoHide(should_auto_hide_scrollbars));
 1526        }
 1527
 1528        this.report_editor_event("open", None, cx);
 1529        this
 1530    }
 1531
 1532    fn key_context(&self, cx: &AppContext) -> KeyContext {
 1533        let mut key_context = KeyContext::default();
 1534        key_context.add("Editor");
 1535        let mode = match self.mode {
 1536            EditorMode::SingleLine => "single_line",
 1537            EditorMode::AutoHeight { .. } => "auto_height",
 1538            EditorMode::Full => "full",
 1539        };
 1540        key_context.set("mode", mode);
 1541        if self.pending_rename.is_some() {
 1542            key_context.add("renaming");
 1543        }
 1544        if self.context_menu_visible() {
 1545            match self.context_menu.read().as_ref() {
 1546                Some(ContextMenu::Completions(_)) => {
 1547                    key_context.add("menu");
 1548                    key_context.add("showing_completions")
 1549                }
 1550                Some(ContextMenu::CodeActions(_)) => {
 1551                    key_context.add("menu");
 1552                    key_context.add("showing_code_actions")
 1553                }
 1554                None => {}
 1555            }
 1556        }
 1557
 1558        for layer in self.keymap_context_layers.values() {
 1559            key_context.extend(layer);
 1560        }
 1561
 1562        if let Some(extension) = self
 1563            .buffer
 1564            .read(cx)
 1565            .as_singleton()
 1566            .and_then(|buffer| buffer.read(cx).file()?.path().extension()?.to_str())
 1567        {
 1568            key_context.set("extension", extension.to_string());
 1569        }
 1570
 1571        key_context
 1572    }
 1573
 1574    pub fn new_file(
 1575        workspace: &mut Workspace,
 1576        _: &workspace::NewFile,
 1577        cx: &mut ViewContext<Workspace>,
 1578    ) {
 1579        let project = workspace.project().clone();
 1580        if project.read(cx).is_remote() {
 1581            cx.propagate();
 1582        } else if let Some(buffer) = project
 1583            .update(cx, |project, cx| project.create_buffer("", None, cx))
 1584            .log_err()
 1585        {
 1586            workspace.add_item(
 1587                Box::new(cx.new_view(|cx| Editor::for_buffer(buffer, Some(project.clone()), cx))),
 1588                cx,
 1589            );
 1590        }
 1591    }
 1592
 1593    pub fn new_file_in_direction(
 1594        workspace: &mut Workspace,
 1595        action: &workspace::NewFileInDirection,
 1596        cx: &mut ViewContext<Workspace>,
 1597    ) {
 1598        let project = workspace.project().clone();
 1599        if project.read(cx).is_remote() {
 1600            cx.propagate();
 1601        } else if let Some(buffer) = project
 1602            .update(cx, |project, cx| project.create_buffer("", None, cx))
 1603            .log_err()
 1604        {
 1605            workspace.split_item(
 1606                action.0,
 1607                Box::new(cx.new_view(|cx| Editor::for_buffer(buffer, Some(project.clone()), cx))),
 1608                cx,
 1609            );
 1610        }
 1611    }
 1612
 1613    pub fn replica_id(&self, cx: &AppContext) -> ReplicaId {
 1614        self.buffer.read(cx).replica_id()
 1615    }
 1616
 1617    pub fn leader_peer_id(&self) -> Option<PeerId> {
 1618        self.leader_peer_id
 1619    }
 1620
 1621    pub fn buffer(&self) -> &Model<MultiBuffer> {
 1622        &self.buffer
 1623    }
 1624
 1625    pub fn workspace(&self) -> Option<View<Workspace>> {
 1626        self.workspace.as_ref()?.0.upgrade()
 1627    }
 1628
 1629    pub fn pane(&self, cx: &AppContext) -> Option<View<Pane>> {
 1630        self.workspace()?.read(cx).pane_for(&self.handle.upgrade()?)
 1631    }
 1632
 1633    pub fn title<'a>(&self, cx: &'a AppContext) -> Cow<'a, str> {
 1634        self.buffer().read(cx).title(cx)
 1635    }
 1636
 1637    pub fn snapshot(&mut self, cx: &mut WindowContext) -> EditorSnapshot {
 1638        EditorSnapshot {
 1639            mode: self.mode,
 1640            show_gutter: self.show_gutter,
 1641            display_snapshot: self.display_map.update(cx, |map, cx| map.snapshot(cx)),
 1642            scroll_anchor: self.scroll_manager.anchor(),
 1643            ongoing_scroll: self.scroll_manager.ongoing_scroll(),
 1644            placeholder_text: self.placeholder_text.clone(),
 1645            is_focused: self.focus_handle.is_focused(cx),
 1646        }
 1647    }
 1648
 1649    pub fn language_at<'a, T: ToOffset>(
 1650        &self,
 1651        point: T,
 1652        cx: &'a AppContext,
 1653    ) -> Option<Arc<Language>> {
 1654        self.buffer.read(cx).language_at(point, cx)
 1655    }
 1656
 1657    pub fn file_at<'a, T: ToOffset>(
 1658        &self,
 1659        point: T,
 1660        cx: &'a AppContext,
 1661    ) -> Option<Arc<dyn language::File>> {
 1662        self.buffer.read(cx).read(cx).file_at(point).cloned()
 1663    }
 1664
 1665    pub fn active_excerpt(
 1666        &self,
 1667        cx: &AppContext,
 1668    ) -> Option<(ExcerptId, Model<Buffer>, Range<text::Anchor>)> {
 1669        self.buffer
 1670            .read(cx)
 1671            .excerpt_containing(self.selections.newest_anchor().head(), cx)
 1672    }
 1673
 1674    pub fn mode(&self) -> EditorMode {
 1675        self.mode
 1676    }
 1677
 1678    pub fn collaboration_hub(&self) -> Option<&dyn CollaborationHub> {
 1679        self.collaboration_hub.as_deref()
 1680    }
 1681
 1682    pub fn set_collaboration_hub(&mut self, hub: Box<dyn CollaborationHub>) {
 1683        self.collaboration_hub = Some(hub);
 1684    }
 1685
 1686    pub fn set_custom_context_menu(
 1687        &mut self,
 1688        f: impl 'static
 1689            + Fn(&mut Self, DisplayPoint, &mut ViewContext<Self>) -> Option<View<ui::ContextMenu>>,
 1690    ) {
 1691        self.custom_context_menu = Some(Box::new(f))
 1692    }
 1693
 1694    pub fn set_completion_provider(&mut self, hub: Box<dyn CompletionProvider>) {
 1695        self.completion_provider = Some(hub);
 1696    }
 1697
 1698    pub fn placeholder_text(&self) -> Option<&str> {
 1699        self.placeholder_text.as_deref()
 1700    }
 1701
 1702    pub fn set_placeholder_text(
 1703        &mut self,
 1704        placeholder_text: impl Into<Arc<str>>,
 1705        cx: &mut ViewContext<Self>,
 1706    ) {
 1707        let placeholder_text = Some(placeholder_text.into());
 1708        if self.placeholder_text != placeholder_text {
 1709            self.placeholder_text = placeholder_text;
 1710            cx.notify();
 1711        }
 1712    }
 1713
 1714    pub fn set_cursor_shape(&mut self, cursor_shape: CursorShape, cx: &mut ViewContext<Self>) {
 1715        self.cursor_shape = cursor_shape;
 1716        cx.notify();
 1717    }
 1718
 1719    pub fn set_collapse_matches(&mut self, collapse_matches: bool) {
 1720        self.collapse_matches = collapse_matches;
 1721    }
 1722
 1723    pub fn range_for_match<T: std::marker::Copy>(&self, range: &Range<T>) -> Range<T> {
 1724        if self.collapse_matches {
 1725            return range.start..range.start;
 1726        }
 1727        range.clone()
 1728    }
 1729
 1730    pub fn set_clip_at_line_ends(&mut self, clip: bool, cx: &mut ViewContext<Self>) {
 1731        if self.display_map.read(cx).clip_at_line_ends != clip {
 1732            self.display_map
 1733                .update(cx, |map, _| map.clip_at_line_ends = clip);
 1734        }
 1735    }
 1736
 1737    pub fn set_keymap_context_layer<Tag: 'static>(
 1738        &mut self,
 1739        context: KeyContext,
 1740        cx: &mut ViewContext<Self>,
 1741    ) {
 1742        self.keymap_context_layers
 1743            .insert(TypeId::of::<Tag>(), context);
 1744        cx.notify();
 1745    }
 1746
 1747    pub fn remove_keymap_context_layer<Tag: 'static>(&mut self, cx: &mut ViewContext<Self>) {
 1748        self.keymap_context_layers.remove(&TypeId::of::<Tag>());
 1749        cx.notify();
 1750    }
 1751
 1752    pub fn set_input_enabled(&mut self, input_enabled: bool) {
 1753        self.input_enabled = input_enabled;
 1754    }
 1755
 1756    pub fn set_autoindent(&mut self, autoindent: bool) {
 1757        if autoindent {
 1758            self.autoindent_mode = Some(AutoindentMode::EachLine);
 1759        } else {
 1760            self.autoindent_mode = None;
 1761        }
 1762    }
 1763
 1764    pub fn read_only(&self, cx: &AppContext) -> bool {
 1765        self.read_only || self.buffer.read(cx).read_only()
 1766    }
 1767
 1768    pub fn set_read_only(&mut self, read_only: bool) {
 1769        self.read_only = read_only;
 1770    }
 1771
 1772    pub fn set_use_autoclose(&mut self, autoclose: bool) {
 1773        self.use_autoclose = autoclose;
 1774    }
 1775
 1776    pub fn set_show_copilot_suggestions(&mut self, show_copilot_suggestions: bool) {
 1777        self.show_copilot_suggestions = show_copilot_suggestions;
 1778    }
 1779
 1780    fn selections_did_change(
 1781        &mut self,
 1782        local: bool,
 1783        old_cursor_position: &Anchor,
 1784        cx: &mut ViewContext<Self>,
 1785    ) {
 1786        if self.focus_handle.is_focused(cx) && self.leader_peer_id.is_none() {
 1787            self.buffer.update(cx, |buffer, cx| {
 1788                buffer.set_active_selections(
 1789                    &self.selections.disjoint_anchors(),
 1790                    self.selections.line_mode,
 1791                    self.cursor_shape,
 1792                    cx,
 1793                )
 1794            });
 1795        }
 1796
 1797        let display_map = self
 1798            .display_map
 1799            .update(cx, |display_map, cx| display_map.snapshot(cx));
 1800        let buffer = &display_map.buffer_snapshot;
 1801        self.add_selections_state = None;
 1802        self.select_next_state = None;
 1803        self.select_prev_state = None;
 1804        self.select_larger_syntax_node_stack.clear();
 1805        self.invalidate_autoclose_regions(&self.selections.disjoint_anchors(), buffer);
 1806        self.snippet_stack
 1807            .invalidate(&self.selections.disjoint_anchors(), buffer);
 1808        self.take_rename(false, cx);
 1809
 1810        let new_cursor_position = self.selections.newest_anchor().head();
 1811
 1812        self.push_to_nav_history(
 1813            old_cursor_position.clone(),
 1814            Some(new_cursor_position.to_point(buffer)),
 1815            cx,
 1816        );
 1817
 1818        if local {
 1819            let new_cursor_position = self.selections.newest_anchor().head();
 1820            let mut context_menu = self.context_menu.write();
 1821            let completion_menu = match context_menu.as_ref() {
 1822                Some(ContextMenu::Completions(menu)) => Some(menu),
 1823
 1824                _ => {
 1825                    *context_menu = None;
 1826                    None
 1827                }
 1828            };
 1829
 1830            if let Some(completion_menu) = completion_menu {
 1831                let cursor_position = new_cursor_position.to_offset(buffer);
 1832                let (word_range, kind) =
 1833                    buffer.surrounding_word(completion_menu.initial_position.clone());
 1834                if kind == Some(CharKind::Word)
 1835                    && word_range.to_inclusive().contains(&cursor_position)
 1836                {
 1837                    let mut completion_menu = completion_menu.clone();
 1838                    drop(context_menu);
 1839
 1840                    let query = Self::completion_query(buffer, cursor_position);
 1841                    cx.spawn(move |this, mut cx| async move {
 1842                        completion_menu
 1843                            .filter(query.as_deref(), cx.background_executor().clone())
 1844                            .await;
 1845
 1846                        this.update(&mut cx, |this, cx| {
 1847                            let mut context_menu = this.context_menu.write();
 1848                            let Some(ContextMenu::Completions(menu)) = context_menu.as_ref() else {
 1849                                return;
 1850                            };
 1851
 1852                            if menu.id > completion_menu.id {
 1853                                return;
 1854                            }
 1855
 1856                            *context_menu = Some(ContextMenu::Completions(completion_menu));
 1857                            drop(context_menu);
 1858                            cx.notify();
 1859                        })
 1860                    })
 1861                    .detach();
 1862
 1863                    self.show_completions(&ShowCompletions, cx);
 1864                } else {
 1865                    drop(context_menu);
 1866                    self.hide_context_menu(cx);
 1867                }
 1868            } else {
 1869                drop(context_menu);
 1870            }
 1871
 1872            hide_hover(self, cx);
 1873
 1874            if old_cursor_position.to_display_point(&display_map).row()
 1875                != new_cursor_position.to_display_point(&display_map).row()
 1876            {
 1877                self.available_code_actions.take();
 1878            }
 1879            self.refresh_code_actions(cx);
 1880            self.refresh_document_highlights(cx);
 1881            refresh_matching_bracket_highlights(self, cx);
 1882            self.discard_copilot_suggestion(cx);
 1883        }
 1884
 1885        self.blink_manager.update(cx, BlinkManager::pause_blinking);
 1886        cx.emit(EditorEvent::SelectionsChanged { local });
 1887
 1888        if self.selections.disjoint_anchors().len() == 1 {
 1889            cx.emit(SearchEvent::ActiveMatchChanged)
 1890        }
 1891
 1892        cx.notify();
 1893    }
 1894
 1895    pub fn change_selections<R>(
 1896        &mut self,
 1897        autoscroll: Option<Autoscroll>,
 1898        cx: &mut ViewContext<Self>,
 1899        change: impl FnOnce(&mut MutableSelectionsCollection<'_>) -> R,
 1900    ) -> R {
 1901        let old_cursor_position = self.selections.newest_anchor().head();
 1902        self.push_to_selection_history();
 1903
 1904        let (changed, result) = self.selections.change_with(cx, change);
 1905
 1906        if changed {
 1907            if let Some(autoscroll) = autoscroll {
 1908                self.request_autoscroll(autoscroll, cx);
 1909            }
 1910            self.selections_did_change(true, &old_cursor_position, cx);
 1911        }
 1912
 1913        result
 1914    }
 1915
 1916    pub fn edit<I, S, T>(&mut self, edits: I, cx: &mut ViewContext<Self>)
 1917    where
 1918        I: IntoIterator<Item = (Range<S>, T)>,
 1919        S: ToOffset,
 1920        T: Into<Arc<str>>,
 1921    {
 1922        if self.read_only(cx) {
 1923            return;
 1924        }
 1925
 1926        self.buffer
 1927            .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
 1928    }
 1929
 1930    pub fn edit_with_autoindent<I, S, T>(&mut self, edits: I, cx: &mut ViewContext<Self>)
 1931    where
 1932        I: IntoIterator<Item = (Range<S>, T)>,
 1933        S: ToOffset,
 1934        T: Into<Arc<str>>,
 1935    {
 1936        if self.read_only(cx) {
 1937            return;
 1938        }
 1939
 1940        self.buffer.update(cx, |buffer, cx| {
 1941            buffer.edit(edits, self.autoindent_mode.clone(), cx)
 1942        });
 1943    }
 1944
 1945    pub fn edit_with_block_indent<I, S, T>(
 1946        &mut self,
 1947        edits: I,
 1948        original_indent_columns: Vec<u32>,
 1949        cx: &mut ViewContext<Self>,
 1950    ) where
 1951        I: IntoIterator<Item = (Range<S>, T)>,
 1952        S: ToOffset,
 1953        T: Into<Arc<str>>,
 1954    {
 1955        if self.read_only(cx) {
 1956            return;
 1957        }
 1958
 1959        self.buffer.update(cx, |buffer, cx| {
 1960            buffer.edit(
 1961                edits,
 1962                Some(AutoindentMode::Block {
 1963                    original_indent_columns,
 1964                }),
 1965                cx,
 1966            )
 1967        });
 1968    }
 1969
 1970    fn select(&mut self, phase: SelectPhase, cx: &mut ViewContext<Self>) {
 1971        self.hide_context_menu(cx);
 1972
 1973        match phase {
 1974            SelectPhase::Begin {
 1975                position,
 1976                add,
 1977                click_count,
 1978            } => self.begin_selection(position, add, click_count, cx),
 1979            SelectPhase::BeginColumnar {
 1980                position,
 1981                goal_column,
 1982            } => self.begin_columnar_selection(position, goal_column, cx),
 1983            SelectPhase::Extend {
 1984                position,
 1985                click_count,
 1986            } => self.extend_selection(position, click_count, cx),
 1987            SelectPhase::Update {
 1988                position,
 1989                goal_column,
 1990                scroll_delta,
 1991            } => self.update_selection(position, goal_column, scroll_delta, cx),
 1992            SelectPhase::End => self.end_selection(cx),
 1993        }
 1994    }
 1995
 1996    fn extend_selection(
 1997        &mut self,
 1998        position: DisplayPoint,
 1999        click_count: usize,
 2000        cx: &mut ViewContext<Self>,
 2001    ) {
 2002        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 2003        let tail = self.selections.newest::<usize>(cx).tail();
 2004        self.begin_selection(position, false, click_count, cx);
 2005
 2006        let position = position.to_offset(&display_map, Bias::Left);
 2007        let tail_anchor = display_map.buffer_snapshot.anchor_before(tail);
 2008
 2009        let mut pending_selection = self
 2010            .selections
 2011            .pending_anchor()
 2012            .expect("extend_selection not called with pending selection");
 2013        if position >= tail {
 2014            pending_selection.start = tail_anchor;
 2015        } else {
 2016            pending_selection.end = tail_anchor;
 2017            pending_selection.reversed = true;
 2018        }
 2019
 2020        let mut pending_mode = self.selections.pending_mode().unwrap();
 2021        match &mut pending_mode {
 2022            SelectMode::Word(range) | SelectMode::Line(range) => *range = tail_anchor..tail_anchor,
 2023            _ => {}
 2024        }
 2025
 2026        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 2027            s.set_pending(pending_selection, pending_mode)
 2028        });
 2029    }
 2030
 2031    fn begin_selection(
 2032        &mut self,
 2033        position: DisplayPoint,
 2034        add: bool,
 2035        click_count: usize,
 2036        cx: &mut ViewContext<Self>,
 2037    ) {
 2038        if !self.focus_handle.is_focused(cx) {
 2039            cx.focus(&self.focus_handle);
 2040        }
 2041
 2042        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 2043        let buffer = &display_map.buffer_snapshot;
 2044        let newest_selection = self.selections.newest_anchor().clone();
 2045        let position = display_map.clip_point(position, Bias::Left);
 2046
 2047        let start;
 2048        let end;
 2049        let mode;
 2050        let auto_scroll;
 2051        match click_count {
 2052            1 => {
 2053                start = buffer.anchor_before(position.to_point(&display_map));
 2054                end = start.clone();
 2055                mode = SelectMode::Character;
 2056                auto_scroll = true;
 2057            }
 2058            2 => {
 2059                let range = movement::surrounding_word(&display_map, position);
 2060                start = buffer.anchor_before(range.start.to_point(&display_map));
 2061                end = buffer.anchor_before(range.end.to_point(&display_map));
 2062                mode = SelectMode::Word(start.clone()..end.clone());
 2063                auto_scroll = true;
 2064            }
 2065            3 => {
 2066                let position = display_map
 2067                    .clip_point(position, Bias::Left)
 2068                    .to_point(&display_map);
 2069                let line_start = display_map.prev_line_boundary(position).0;
 2070                let next_line_start = buffer.clip_point(
 2071                    display_map.next_line_boundary(position).0 + Point::new(1, 0),
 2072                    Bias::Left,
 2073                );
 2074                start = buffer.anchor_before(line_start);
 2075                end = buffer.anchor_before(next_line_start);
 2076                mode = SelectMode::Line(start.clone()..end.clone());
 2077                auto_scroll = true;
 2078            }
 2079            _ => {
 2080                start = buffer.anchor_before(0);
 2081                end = buffer.anchor_before(buffer.len());
 2082                mode = SelectMode::All;
 2083                auto_scroll = false;
 2084            }
 2085        }
 2086
 2087        self.change_selections(auto_scroll.then(|| Autoscroll::newest()), cx, |s| {
 2088            if !add {
 2089                s.clear_disjoint();
 2090            } else if click_count > 1 {
 2091                s.delete(newest_selection.id)
 2092            }
 2093
 2094            s.set_pending_anchor_range(start..end, mode);
 2095        });
 2096    }
 2097
 2098    fn begin_columnar_selection(
 2099        &mut self,
 2100        position: DisplayPoint,
 2101        goal_column: u32,
 2102        cx: &mut ViewContext<Self>,
 2103    ) {
 2104        if !self.focus_handle.is_focused(cx) {
 2105            cx.focus(&self.focus_handle);
 2106        }
 2107
 2108        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 2109        let tail = self.selections.newest::<Point>(cx).tail();
 2110        self.columnar_selection_tail = Some(display_map.buffer_snapshot.anchor_before(tail));
 2111
 2112        self.select_columns(
 2113            tail.to_display_point(&display_map),
 2114            position,
 2115            goal_column,
 2116            &display_map,
 2117            cx,
 2118        );
 2119    }
 2120
 2121    fn update_selection(
 2122        &mut self,
 2123        position: DisplayPoint,
 2124        goal_column: u32,
 2125        scroll_delta: gpui::Point<f32>,
 2126        cx: &mut ViewContext<Self>,
 2127    ) {
 2128        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 2129
 2130        if let Some(tail) = self.columnar_selection_tail.as_ref() {
 2131            let tail = tail.to_display_point(&display_map);
 2132            self.select_columns(tail, position, goal_column, &display_map, cx);
 2133        } else if let Some(mut pending) = self.selections.pending_anchor() {
 2134            let buffer = self.buffer.read(cx).snapshot(cx);
 2135            let head;
 2136            let tail;
 2137            let mode = self.selections.pending_mode().unwrap();
 2138            match &mode {
 2139                SelectMode::Character => {
 2140                    head = position.to_point(&display_map);
 2141                    tail = pending.tail().to_point(&buffer);
 2142                }
 2143                SelectMode::Word(original_range) => {
 2144                    let original_display_range = original_range.start.to_display_point(&display_map)
 2145                        ..original_range.end.to_display_point(&display_map);
 2146                    let original_buffer_range = original_display_range.start.to_point(&display_map)
 2147                        ..original_display_range.end.to_point(&display_map);
 2148                    if movement::is_inside_word(&display_map, position)
 2149                        || original_display_range.contains(&position)
 2150                    {
 2151                        let word_range = movement::surrounding_word(&display_map, position);
 2152                        if word_range.start < original_display_range.start {
 2153                            head = word_range.start.to_point(&display_map);
 2154                        } else {
 2155                            head = word_range.end.to_point(&display_map);
 2156                        }
 2157                    } else {
 2158                        head = position.to_point(&display_map);
 2159                    }
 2160
 2161                    if head <= original_buffer_range.start {
 2162                        tail = original_buffer_range.end;
 2163                    } else {
 2164                        tail = original_buffer_range.start;
 2165                    }
 2166                }
 2167                SelectMode::Line(original_range) => {
 2168                    let original_range = original_range.to_point(&display_map.buffer_snapshot);
 2169
 2170                    let position = display_map
 2171                        .clip_point(position, Bias::Left)
 2172                        .to_point(&display_map);
 2173                    let line_start = display_map.prev_line_boundary(position).0;
 2174                    let next_line_start = buffer.clip_point(
 2175                        display_map.next_line_boundary(position).0 + Point::new(1, 0),
 2176                        Bias::Left,
 2177                    );
 2178
 2179                    if line_start < original_range.start {
 2180                        head = line_start
 2181                    } else {
 2182                        head = next_line_start
 2183                    }
 2184
 2185                    if head <= original_range.start {
 2186                        tail = original_range.end;
 2187                    } else {
 2188                        tail = original_range.start;
 2189                    }
 2190                }
 2191                SelectMode::All => {
 2192                    return;
 2193                }
 2194            };
 2195
 2196            if head < tail {
 2197                pending.start = buffer.anchor_before(head);
 2198                pending.end = buffer.anchor_before(tail);
 2199                pending.reversed = true;
 2200            } else {
 2201                pending.start = buffer.anchor_before(tail);
 2202                pending.end = buffer.anchor_before(head);
 2203                pending.reversed = false;
 2204            }
 2205
 2206            self.change_selections(None, cx, |s| {
 2207                s.set_pending(pending, mode);
 2208            });
 2209        } else {
 2210            log::error!("update_selection dispatched with no pending selection");
 2211            return;
 2212        }
 2213
 2214        self.apply_scroll_delta(scroll_delta, cx);
 2215        cx.notify();
 2216    }
 2217
 2218    fn end_selection(&mut self, cx: &mut ViewContext<Self>) {
 2219        self.columnar_selection_tail.take();
 2220        if self.selections.pending_anchor().is_some() {
 2221            let selections = self.selections.all::<usize>(cx);
 2222            self.change_selections(None, cx, |s| {
 2223                s.select(selections);
 2224                s.clear_pending();
 2225            });
 2226        }
 2227    }
 2228
 2229    fn select_columns(
 2230        &mut self,
 2231        tail: DisplayPoint,
 2232        head: DisplayPoint,
 2233        goal_column: u32,
 2234        display_map: &DisplaySnapshot,
 2235        cx: &mut ViewContext<Self>,
 2236    ) {
 2237        let start_row = cmp::min(tail.row(), head.row());
 2238        let end_row = cmp::max(tail.row(), head.row());
 2239        let start_column = cmp::min(tail.column(), goal_column);
 2240        let end_column = cmp::max(tail.column(), goal_column);
 2241        let reversed = start_column < tail.column();
 2242
 2243        let selection_ranges = (start_row..=end_row)
 2244            .filter_map(|row| {
 2245                if start_column <= display_map.line_len(row) && !display_map.is_block_line(row) {
 2246                    let start = display_map
 2247                        .clip_point(DisplayPoint::new(row, start_column), Bias::Left)
 2248                        .to_point(display_map);
 2249                    let end = display_map
 2250                        .clip_point(DisplayPoint::new(row, end_column), Bias::Right)
 2251                        .to_point(display_map);
 2252                    if reversed {
 2253                        Some(end..start)
 2254                    } else {
 2255                        Some(start..end)
 2256                    }
 2257                } else {
 2258                    None
 2259                }
 2260            })
 2261            .collect::<Vec<_>>();
 2262
 2263        self.change_selections(None, cx, |s| {
 2264            s.select_ranges(selection_ranges);
 2265        });
 2266        cx.notify();
 2267    }
 2268
 2269    pub fn has_pending_nonempty_selection(&self) -> bool {
 2270        let pending_nonempty_selection = match self.selections.pending_anchor() {
 2271            Some(Selection { start, end, .. }) => start != end,
 2272            None => false,
 2273        };
 2274        pending_nonempty_selection || self.columnar_selection_tail.is_some()
 2275    }
 2276
 2277    pub fn has_pending_selection(&self) -> bool {
 2278        self.selections.pending_anchor().is_some() || self.columnar_selection_tail.is_some()
 2279    }
 2280
 2281    pub fn cancel(&mut self, _: &Cancel, cx: &mut ViewContext<Self>) {
 2282        if self.take_rename(false, cx).is_some() {
 2283            return;
 2284        }
 2285
 2286        if hide_hover(self, cx) {
 2287            return;
 2288        }
 2289
 2290        if self.hide_context_menu(cx).is_some() {
 2291            return;
 2292        }
 2293
 2294        if self.discard_copilot_suggestion(cx) {
 2295            return;
 2296        }
 2297
 2298        if self.snippet_stack.pop().is_some() {
 2299            return;
 2300        }
 2301
 2302        if self.mode == EditorMode::Full {
 2303            if self.active_diagnostics.is_some() {
 2304                self.dismiss_diagnostics(cx);
 2305                return;
 2306            }
 2307
 2308            if self.change_selections(Some(Autoscroll::fit()), cx, |s| s.try_cancel()) {
 2309                return;
 2310            }
 2311        }
 2312
 2313        cx.propagate();
 2314    }
 2315
 2316    pub fn handle_input(&mut self, text: &str, cx: &mut ViewContext<Self>) {
 2317        let text: Arc<str> = text.into();
 2318
 2319        if self.read_only(cx) {
 2320            return;
 2321        }
 2322
 2323        let selections = self.selections.all_adjusted(cx);
 2324        let mut brace_inserted = false;
 2325        let mut edits = Vec::new();
 2326        let mut new_selections = Vec::with_capacity(selections.len());
 2327        let mut new_autoclose_regions = Vec::new();
 2328        let snapshot = self.buffer.read(cx).read(cx);
 2329
 2330        for (selection, autoclose_region) in
 2331            self.selections_with_autoclose_regions(selections, &snapshot)
 2332        {
 2333            if let Some(scope) = snapshot.language_scope_at(selection.head()) {
 2334                // Determine if the inserted text matches the opening or closing
 2335                // bracket of any of this language's bracket pairs.
 2336                let mut bracket_pair = None;
 2337                let mut is_bracket_pair_start = false;
 2338                if !text.is_empty() {
 2339                    // `text` can be empty when a user is using IME (e.g. Chinese Wubi Simplified)
 2340                    //  and they are removing the character that triggered IME popup.
 2341                    for (pair, enabled) in scope.brackets() {
 2342                        if enabled && pair.close && pair.start.ends_with(text.as_ref()) {
 2343                            bracket_pair = Some(pair.clone());
 2344                            is_bracket_pair_start = true;
 2345                            break;
 2346                        } else if pair.end.as_str() == text.as_ref() {
 2347                            bracket_pair = Some(pair.clone());
 2348                            break;
 2349                        }
 2350                    }
 2351                }
 2352
 2353                if let Some(bracket_pair) = bracket_pair {
 2354                    if selection.is_empty() {
 2355                        if is_bracket_pair_start {
 2356                            let prefix_len = bracket_pair.start.len() - text.len();
 2357
 2358                            // If the inserted text is a suffix of an opening bracket and the
 2359                            // selection is preceded by the rest of the opening bracket, then
 2360                            // insert the closing bracket.
 2361                            let following_text_allows_autoclose = snapshot
 2362                                .chars_at(selection.start)
 2363                                .next()
 2364                                .map_or(true, |c| scope.should_autoclose_before(c));
 2365                            let preceding_text_matches_prefix = prefix_len == 0
 2366                                || (selection.start.column >= (prefix_len as u32)
 2367                                    && snapshot.contains_str_at(
 2368                                        Point::new(
 2369                                            selection.start.row,
 2370                                            selection.start.column - (prefix_len as u32),
 2371                                        ),
 2372                                        &bracket_pair.start[..prefix_len],
 2373                                    ));
 2374                            let autoclose = self.use_autoclose
 2375                                && snapshot.settings_at(selection.start, cx).use_autoclose;
 2376                            if autoclose
 2377                                && following_text_allows_autoclose
 2378                                && preceding_text_matches_prefix
 2379                            {
 2380                                let anchor = snapshot.anchor_before(selection.end);
 2381                                new_selections.push((selection.map(|_| anchor), text.len()));
 2382                                new_autoclose_regions.push((
 2383                                    anchor,
 2384                                    text.len(),
 2385                                    selection.id,
 2386                                    bracket_pair.clone(),
 2387                                ));
 2388                                edits.push((
 2389                                    selection.range(),
 2390                                    format!("{}{}", text, bracket_pair.end).into(),
 2391                                ));
 2392                                brace_inserted = true;
 2393                                continue;
 2394                            }
 2395                        }
 2396
 2397                        if let Some(region) = autoclose_region {
 2398                            // If the selection is followed by an auto-inserted closing bracket,
 2399                            // then don't insert that closing bracket again; just move the selection
 2400                            // past the closing bracket.
 2401                            let should_skip = selection.end == region.range.end.to_point(&snapshot)
 2402                                && text.as_ref() == region.pair.end.as_str();
 2403                            if should_skip {
 2404                                let anchor = snapshot.anchor_after(selection.end);
 2405                                new_selections
 2406                                    .push((selection.map(|_| anchor), region.pair.end.len()));
 2407                                continue;
 2408                            }
 2409                        }
 2410                    }
 2411                    // If an opening bracket is 1 character long and is typed while
 2412                    // text is selected, then surround that text with the bracket pair.
 2413                    else if is_bracket_pair_start && bracket_pair.start.chars().count() == 1 {
 2414                        edits.push((selection.start..selection.start, text.clone()));
 2415                        edits.push((
 2416                            selection.end..selection.end,
 2417                            bracket_pair.end.as_str().into(),
 2418                        ));
 2419                        brace_inserted = true;
 2420                        new_selections.push((
 2421                            Selection {
 2422                                id: selection.id,
 2423                                start: snapshot.anchor_after(selection.start),
 2424                                end: snapshot.anchor_before(selection.end),
 2425                                reversed: selection.reversed,
 2426                                goal: selection.goal,
 2427                            },
 2428                            0,
 2429                        ));
 2430                        continue;
 2431                    }
 2432                }
 2433            }
 2434
 2435            // If not handling any auto-close operation, then just replace the selected
 2436            // text with the given input and move the selection to the end of the
 2437            // newly inserted text.
 2438            let anchor = snapshot.anchor_after(selection.end);
 2439            new_selections.push((selection.map(|_| anchor), 0));
 2440            edits.push((selection.start..selection.end, text.clone()));
 2441        }
 2442
 2443        drop(snapshot);
 2444        self.transact(cx, |this, cx| {
 2445            this.buffer.update(cx, |buffer, cx| {
 2446                buffer.edit(edits, this.autoindent_mode.clone(), cx);
 2447            });
 2448
 2449            let new_anchor_selections = new_selections.iter().map(|e| &e.0);
 2450            let new_selection_deltas = new_selections.iter().map(|e| e.1);
 2451            let snapshot = this.buffer.read(cx).read(cx);
 2452            let new_selections = resolve_multiple::<usize, _>(new_anchor_selections, &snapshot)
 2453                .zip(new_selection_deltas)
 2454                .map(|(selection, delta)| Selection {
 2455                    id: selection.id,
 2456                    start: selection.start + delta,
 2457                    end: selection.end + delta,
 2458                    reversed: selection.reversed,
 2459                    goal: SelectionGoal::None,
 2460                })
 2461                .collect::<Vec<_>>();
 2462
 2463            let mut i = 0;
 2464            for (position, delta, selection_id, pair) in new_autoclose_regions {
 2465                let position = position.to_offset(&snapshot) + delta;
 2466                let start = snapshot.anchor_before(position);
 2467                let end = snapshot.anchor_after(position);
 2468                while let Some(existing_state) = this.autoclose_regions.get(i) {
 2469                    match existing_state.range.start.cmp(&start, &snapshot) {
 2470                        Ordering::Less => i += 1,
 2471                        Ordering::Greater => break,
 2472                        Ordering::Equal => match end.cmp(&existing_state.range.end, &snapshot) {
 2473                            Ordering::Less => i += 1,
 2474                            Ordering::Equal => break,
 2475                            Ordering::Greater => break,
 2476                        },
 2477                    }
 2478                }
 2479                this.autoclose_regions.insert(
 2480                    i,
 2481                    AutocloseRegion {
 2482                        selection_id,
 2483                        range: start..end,
 2484                        pair,
 2485                    },
 2486                );
 2487            }
 2488
 2489            drop(snapshot);
 2490            let had_active_copilot_suggestion = this.has_active_copilot_suggestion(cx);
 2491            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(new_selections));
 2492
 2493            if brace_inserted {
 2494                // If we inserted a brace while composing text (i.e. typing `"` on a
 2495                // Brazilian keyboard), exit the composing state because most likely
 2496                // the user wanted to surround the selection.
 2497                this.unmark_text(cx);
 2498            } else if EditorSettings::get_global(cx).use_on_type_format {
 2499                if let Some(on_type_format_task) =
 2500                    this.trigger_on_type_formatting(text.to_string(), cx)
 2501                {
 2502                    on_type_format_task.detach_and_log_err(cx);
 2503                }
 2504            }
 2505
 2506            if had_active_copilot_suggestion {
 2507                this.refresh_copilot_suggestions(true, cx);
 2508                if !this.has_active_copilot_suggestion(cx) {
 2509                    this.trigger_completion_on_input(&text, cx);
 2510                }
 2511            } else {
 2512                this.trigger_completion_on_input(&text, cx);
 2513                this.refresh_copilot_suggestions(true, cx);
 2514            }
 2515        });
 2516    }
 2517
 2518    pub fn newline(&mut self, _: &Newline, cx: &mut ViewContext<Self>) {
 2519        self.transact(cx, |this, cx| {
 2520            let (edits, selection_fixup_info): (Vec<_>, Vec<_>) = {
 2521                let selections = this.selections.all::<usize>(cx);
 2522                let multi_buffer = this.buffer.read(cx);
 2523                let buffer = multi_buffer.snapshot(cx);
 2524                selections
 2525                    .iter()
 2526                    .map(|selection| {
 2527                        let start_point = selection.start.to_point(&buffer);
 2528                        let mut indent = buffer.indent_size_for_line(start_point.row);
 2529                        indent.len = cmp::min(indent.len, start_point.column);
 2530                        let start = selection.start;
 2531                        let end = selection.end;
 2532                        let is_cursor = start == end;
 2533                        let language_scope = buffer.language_scope_at(start);
 2534                        let (comment_delimiter, insert_extra_newline) = if let Some(language) =
 2535                            &language_scope
 2536                        {
 2537                            let leading_whitespace_len = buffer
 2538                                .reversed_chars_at(start)
 2539                                .take_while(|c| c.is_whitespace() && *c != '\n')
 2540                                .map(|c| c.len_utf8())
 2541                                .sum::<usize>();
 2542
 2543                            let trailing_whitespace_len = buffer
 2544                                .chars_at(end)
 2545                                .take_while(|c| c.is_whitespace() && *c != '\n')
 2546                                .map(|c| c.len_utf8())
 2547                                .sum::<usize>();
 2548
 2549                            let insert_extra_newline =
 2550                                language.brackets().any(|(pair, enabled)| {
 2551                                    let pair_start = pair.start.trim_end();
 2552                                    let pair_end = pair.end.trim_start();
 2553
 2554                                    enabled
 2555                                        && pair.newline
 2556                                        && buffer.contains_str_at(
 2557                                            end + trailing_whitespace_len,
 2558                                            pair_end,
 2559                                        )
 2560                                        && buffer.contains_str_at(
 2561                                            (start - leading_whitespace_len)
 2562                                                .saturating_sub(pair_start.len()),
 2563                                            pair_start,
 2564                                        )
 2565                                });
 2566                            // Comment extension on newline is allowed only for cursor selections
 2567                            let comment_delimiter = language.line_comment_prefixes().filter(|_| {
 2568                                let is_comment_extension_enabled =
 2569                                    multi_buffer.settings_at(0, cx).extend_comment_on_newline;
 2570                                is_cursor && is_comment_extension_enabled
 2571                            });
 2572                            let get_comment_delimiter = |delimiters: &[Arc<str>]| {
 2573                                let max_len_of_delimiter =
 2574                                    delimiters.iter().map(|delimiter| delimiter.len()).max()?;
 2575                                let (snapshot, range) =
 2576                                    buffer.buffer_line_for_row(start_point.row)?;
 2577
 2578                                let mut index_of_first_non_whitespace = 0;
 2579                                let comment_candidate = snapshot
 2580                                    .chars_for_range(range)
 2581                                    .skip_while(|c| {
 2582                                        let should_skip = c.is_whitespace();
 2583                                        if should_skip {
 2584                                            index_of_first_non_whitespace += 1;
 2585                                        }
 2586                                        should_skip
 2587                                    })
 2588                                    .take(max_len_of_delimiter)
 2589                                    .collect::<String>();
 2590                                let comment_prefix = delimiters.iter().find(|comment_prefix| {
 2591                                    comment_candidate.starts_with(comment_prefix.as_ref())
 2592                                })?;
 2593                                let cursor_is_placed_after_comment_marker =
 2594                                    index_of_first_non_whitespace + comment_prefix.len()
 2595                                        <= start_point.column as usize;
 2596                                if cursor_is_placed_after_comment_marker {
 2597                                    Some(comment_prefix.clone())
 2598                                } else {
 2599                                    None
 2600                                }
 2601                            };
 2602                            let comment_delimiter = if let Some(delimiters) = comment_delimiter {
 2603                                get_comment_delimiter(delimiters)
 2604                            } else {
 2605                                None
 2606                            };
 2607                            (comment_delimiter, insert_extra_newline)
 2608                        } else {
 2609                            (None, false)
 2610                        };
 2611
 2612                        let capacity_for_delimiter = comment_delimiter
 2613                            .as_deref()
 2614                            .map(str::len)
 2615                            .unwrap_or_default();
 2616                        let mut new_text =
 2617                            String::with_capacity(1 + capacity_for_delimiter + indent.len as usize);
 2618                        new_text.push_str("\n");
 2619                        new_text.extend(indent.chars());
 2620                        if let Some(delimiter) = &comment_delimiter {
 2621                            new_text.push_str(&delimiter);
 2622                        }
 2623                        if insert_extra_newline {
 2624                            new_text = new_text.repeat(2);
 2625                        }
 2626
 2627                        let anchor = buffer.anchor_after(end);
 2628                        let new_selection = selection.map(|_| anchor);
 2629                        (
 2630                            (start..end, new_text),
 2631                            (insert_extra_newline, new_selection),
 2632                        )
 2633                    })
 2634                    .unzip()
 2635            };
 2636
 2637            this.edit_with_autoindent(edits, cx);
 2638            let buffer = this.buffer.read(cx).snapshot(cx);
 2639            let new_selections = selection_fixup_info
 2640                .into_iter()
 2641                .map(|(extra_newline_inserted, new_selection)| {
 2642                    let mut cursor = new_selection.end.to_point(&buffer);
 2643                    if extra_newline_inserted {
 2644                        cursor.row -= 1;
 2645                        cursor.column = buffer.line_len(cursor.row);
 2646                    }
 2647                    new_selection.map(|_| cursor)
 2648                })
 2649                .collect();
 2650
 2651            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(new_selections));
 2652            this.refresh_copilot_suggestions(true, cx);
 2653        });
 2654    }
 2655
 2656    pub fn newline_above(&mut self, _: &NewlineAbove, cx: &mut ViewContext<Self>) {
 2657        let buffer = self.buffer.read(cx);
 2658        let snapshot = buffer.snapshot(cx);
 2659
 2660        let mut edits = Vec::new();
 2661        let mut rows = Vec::new();
 2662        let mut rows_inserted = 0;
 2663
 2664        for selection in self.selections.all_adjusted(cx) {
 2665            let cursor = selection.head();
 2666            let row = cursor.row;
 2667
 2668            let start_of_line = snapshot.clip_point(Point::new(row, 0), Bias::Left);
 2669
 2670            let newline = "\n".to_string();
 2671            edits.push((start_of_line..start_of_line, newline));
 2672
 2673            rows.push(row + rows_inserted);
 2674            rows_inserted += 1;
 2675        }
 2676
 2677        self.transact(cx, |editor, cx| {
 2678            editor.edit(edits, cx);
 2679
 2680            editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
 2681                let mut index = 0;
 2682                s.move_cursors_with(|map, _, _| {
 2683                    let row = rows[index];
 2684                    index += 1;
 2685
 2686                    let point = Point::new(row, 0);
 2687                    let boundary = map.next_line_boundary(point).1;
 2688                    let clipped = map.clip_point(boundary, Bias::Left);
 2689
 2690                    (clipped, SelectionGoal::None)
 2691                });
 2692            });
 2693
 2694            let mut indent_edits = Vec::new();
 2695            let multibuffer_snapshot = editor.buffer.read(cx).snapshot(cx);
 2696            for row in rows {
 2697                let indents = multibuffer_snapshot.suggested_indents(row..row + 1, cx);
 2698                for (row, indent) in indents {
 2699                    if indent.len == 0 {
 2700                        continue;
 2701                    }
 2702
 2703                    let text = match indent.kind {
 2704                        IndentKind::Space => " ".repeat(indent.len as usize),
 2705                        IndentKind::Tab => "\t".repeat(indent.len as usize),
 2706                    };
 2707                    let point = Point::new(row, 0);
 2708                    indent_edits.push((point..point, text));
 2709                }
 2710            }
 2711            editor.edit(indent_edits, cx);
 2712        });
 2713    }
 2714
 2715    pub fn newline_below(&mut self, _: &NewlineBelow, cx: &mut ViewContext<Self>) {
 2716        let buffer = self.buffer.read(cx);
 2717        let snapshot = buffer.snapshot(cx);
 2718
 2719        let mut edits = Vec::new();
 2720        let mut rows = Vec::new();
 2721        let mut rows_inserted = 0;
 2722
 2723        for selection in self.selections.all_adjusted(cx) {
 2724            let cursor = selection.head();
 2725            let row = cursor.row;
 2726
 2727            let point = Point::new(row + 1, 0);
 2728            let start_of_line = snapshot.clip_point(point, Bias::Left);
 2729
 2730            let newline = "\n".to_string();
 2731            edits.push((start_of_line..start_of_line, newline));
 2732
 2733            rows_inserted += 1;
 2734            rows.push(row + rows_inserted);
 2735        }
 2736
 2737        self.transact(cx, |editor, cx| {
 2738            editor.edit(edits, cx);
 2739
 2740            editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
 2741                let mut index = 0;
 2742                s.move_cursors_with(|map, _, _| {
 2743                    let row = rows[index];
 2744                    index += 1;
 2745
 2746                    let point = Point::new(row, 0);
 2747                    let boundary = map.next_line_boundary(point).1;
 2748                    let clipped = map.clip_point(boundary, Bias::Left);
 2749
 2750                    (clipped, SelectionGoal::None)
 2751                });
 2752            });
 2753
 2754            let mut indent_edits = Vec::new();
 2755            let multibuffer_snapshot = editor.buffer.read(cx).snapshot(cx);
 2756            for row in rows {
 2757                let indents = multibuffer_snapshot.suggested_indents(row..row + 1, cx);
 2758                for (row, indent) in indents {
 2759                    if indent.len == 0 {
 2760                        continue;
 2761                    }
 2762
 2763                    let text = match indent.kind {
 2764                        IndentKind::Space => " ".repeat(indent.len as usize),
 2765                        IndentKind::Tab => "\t".repeat(indent.len as usize),
 2766                    };
 2767                    let point = Point::new(row, 0);
 2768                    indent_edits.push((point..point, text));
 2769                }
 2770            }
 2771            editor.edit(indent_edits, cx);
 2772        });
 2773    }
 2774
 2775    pub fn insert(&mut self, text: &str, cx: &mut ViewContext<Self>) {
 2776        self.insert_with_autoindent_mode(
 2777            text,
 2778            Some(AutoindentMode::Block {
 2779                original_indent_columns: Vec::new(),
 2780            }),
 2781            cx,
 2782        );
 2783    }
 2784
 2785    fn insert_with_autoindent_mode(
 2786        &mut self,
 2787        text: &str,
 2788        autoindent_mode: Option<AutoindentMode>,
 2789        cx: &mut ViewContext<Self>,
 2790    ) {
 2791        if self.read_only(cx) {
 2792            return;
 2793        }
 2794
 2795        let text: Arc<str> = text.into();
 2796        self.transact(cx, |this, cx| {
 2797            let old_selections = this.selections.all_adjusted(cx);
 2798            let selection_anchors = this.buffer.update(cx, |buffer, cx| {
 2799                let anchors = {
 2800                    let snapshot = buffer.read(cx);
 2801                    old_selections
 2802                        .iter()
 2803                        .map(|s| {
 2804                            let anchor = snapshot.anchor_after(s.head());
 2805                            s.map(|_| anchor)
 2806                        })
 2807                        .collect::<Vec<_>>()
 2808                };
 2809                buffer.edit(
 2810                    old_selections
 2811                        .iter()
 2812                        .map(|s| (s.start..s.end, text.clone())),
 2813                    autoindent_mode,
 2814                    cx,
 2815                );
 2816                anchors
 2817            });
 2818
 2819            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 2820                s.select_anchors(selection_anchors);
 2821            })
 2822        });
 2823    }
 2824
 2825    fn trigger_completion_on_input(&mut self, text: &str, cx: &mut ViewContext<Self>) {
 2826        if !EditorSettings::get_global(cx).show_completions_on_input {
 2827            return;
 2828        }
 2829
 2830        let selection = self.selections.newest_anchor();
 2831        if self
 2832            .buffer
 2833            .read(cx)
 2834            .is_completion_trigger(selection.head(), text, cx)
 2835        {
 2836            self.show_completions(&ShowCompletions, cx);
 2837        } else {
 2838            self.hide_context_menu(cx);
 2839        }
 2840    }
 2841
 2842    /// If any empty selections is touching the start of its innermost containing autoclose
 2843    /// region, expand it to select the brackets.
 2844    fn select_autoclose_pair(&mut self, cx: &mut ViewContext<Self>) {
 2845        let selections = self.selections.all::<usize>(cx);
 2846        let buffer = self.buffer.read(cx).read(cx);
 2847        let mut new_selections = Vec::new();
 2848        for (mut selection, region) in self.selections_with_autoclose_regions(selections, &buffer) {
 2849            if let (Some(region), true) = (region, selection.is_empty()) {
 2850                let mut range = region.range.to_offset(&buffer);
 2851                if selection.start == range.start {
 2852                    if range.start >= region.pair.start.len() {
 2853                        range.start -= region.pair.start.len();
 2854                        if buffer.contains_str_at(range.start, &region.pair.start) {
 2855                            if buffer.contains_str_at(range.end, &region.pair.end) {
 2856                                range.end += region.pair.end.len();
 2857                                selection.start = range.start;
 2858                                selection.end = range.end;
 2859                            }
 2860                        }
 2861                    }
 2862                }
 2863            }
 2864            new_selections.push(selection);
 2865        }
 2866
 2867        drop(buffer);
 2868        self.change_selections(None, cx, |selections| selections.select(new_selections));
 2869    }
 2870
 2871    /// Iterate the given selections, and for each one, find the smallest surrounding
 2872    /// autoclose region. This uses the ordering of the selections and the autoclose
 2873    /// regions to avoid repeated comparisons.
 2874    fn selections_with_autoclose_regions<'a, D: ToOffset + Clone>(
 2875        &'a self,
 2876        selections: impl IntoIterator<Item = Selection<D>>,
 2877        buffer: &'a MultiBufferSnapshot,
 2878    ) -> impl Iterator<Item = (Selection<D>, Option<&'a AutocloseRegion>)> {
 2879        let mut i = 0;
 2880        let mut regions = self.autoclose_regions.as_slice();
 2881        selections.into_iter().map(move |selection| {
 2882            let range = selection.start.to_offset(buffer)..selection.end.to_offset(buffer);
 2883
 2884            let mut enclosing = None;
 2885            while let Some(pair_state) = regions.get(i) {
 2886                if pair_state.range.end.to_offset(buffer) < range.start {
 2887                    regions = &regions[i + 1..];
 2888                    i = 0;
 2889                } else if pair_state.range.start.to_offset(buffer) > range.end {
 2890                    break;
 2891                } else {
 2892                    if pair_state.selection_id == selection.id {
 2893                        enclosing = Some(pair_state);
 2894                    }
 2895                    i += 1;
 2896                }
 2897            }
 2898
 2899            (selection.clone(), enclosing)
 2900        })
 2901    }
 2902
 2903    /// Remove any autoclose regions that no longer contain their selection.
 2904    fn invalidate_autoclose_regions(
 2905        &mut self,
 2906        mut selections: &[Selection<Anchor>],
 2907        buffer: &MultiBufferSnapshot,
 2908    ) {
 2909        self.autoclose_regions.retain(|state| {
 2910            let mut i = 0;
 2911            while let Some(selection) = selections.get(i) {
 2912                if selection.end.cmp(&state.range.start, buffer).is_lt() {
 2913                    selections = &selections[1..];
 2914                    continue;
 2915                }
 2916                if selection.start.cmp(&state.range.end, buffer).is_gt() {
 2917                    break;
 2918                }
 2919                if selection.id == state.selection_id {
 2920                    return true;
 2921                } else {
 2922                    i += 1;
 2923                }
 2924            }
 2925            false
 2926        });
 2927    }
 2928
 2929    fn completion_query(buffer: &MultiBufferSnapshot, position: impl ToOffset) -> Option<String> {
 2930        let offset = position.to_offset(buffer);
 2931        let (word_range, kind) = buffer.surrounding_word(offset);
 2932        if offset > word_range.start && kind == Some(CharKind::Word) {
 2933            Some(
 2934                buffer
 2935                    .text_for_range(word_range.start..offset)
 2936                    .collect::<String>(),
 2937            )
 2938        } else {
 2939            None
 2940        }
 2941    }
 2942
 2943    pub fn toggle_inlay_hints(&mut self, _: &ToggleInlayHints, cx: &mut ViewContext<Self>) {
 2944        self.refresh_inlay_hints(
 2945            InlayHintRefreshReason::Toggle(!self.inlay_hint_cache.enabled),
 2946            cx,
 2947        );
 2948    }
 2949
 2950    pub fn inlay_hints_enabled(&self) -> bool {
 2951        self.inlay_hint_cache.enabled
 2952    }
 2953
 2954    fn refresh_inlay_hints(&mut self, reason: InlayHintRefreshReason, cx: &mut ViewContext<Self>) {
 2955        if self.project.is_none() || self.mode != EditorMode::Full {
 2956            return;
 2957        }
 2958
 2959        let reason_description = reason.description();
 2960        let (invalidate_cache, required_languages) = match reason {
 2961            InlayHintRefreshReason::Toggle(enabled) => {
 2962                self.inlay_hint_cache.enabled = enabled;
 2963                if enabled {
 2964                    (InvalidationStrategy::RefreshRequested, None)
 2965                } else {
 2966                    self.inlay_hint_cache.clear();
 2967                    self.splice_inlay_hints(
 2968                        self.visible_inlay_hints(cx)
 2969                            .iter()
 2970                            .map(|inlay| inlay.id)
 2971                            .collect(),
 2972                        Vec::new(),
 2973                        cx,
 2974                    );
 2975                    return;
 2976                }
 2977            }
 2978            InlayHintRefreshReason::SettingsChange(new_settings) => {
 2979                match self.inlay_hint_cache.update_settings(
 2980                    &self.buffer,
 2981                    new_settings,
 2982                    self.visible_inlay_hints(cx),
 2983                    cx,
 2984                ) {
 2985                    ControlFlow::Break(Some(InlaySplice {
 2986                        to_remove,
 2987                        to_insert,
 2988                    })) => {
 2989                        self.splice_inlay_hints(to_remove, to_insert, cx);
 2990                        return;
 2991                    }
 2992                    ControlFlow::Break(None) => return,
 2993                    ControlFlow::Continue(()) => (InvalidationStrategy::RefreshRequested, None),
 2994                }
 2995            }
 2996            InlayHintRefreshReason::ExcerptsRemoved(excerpts_removed) => {
 2997                if let Some(InlaySplice {
 2998                    to_remove,
 2999                    to_insert,
 3000                }) = self.inlay_hint_cache.remove_excerpts(excerpts_removed)
 3001                {
 3002                    self.splice_inlay_hints(to_remove, to_insert, cx);
 3003                }
 3004                return;
 3005            }
 3006            InlayHintRefreshReason::NewLinesShown => (InvalidationStrategy::None, None),
 3007            InlayHintRefreshReason::BufferEdited(buffer_languages) => {
 3008                (InvalidationStrategy::BufferEdited, Some(buffer_languages))
 3009            }
 3010            InlayHintRefreshReason::RefreshRequested => {
 3011                (InvalidationStrategy::RefreshRequested, None)
 3012            }
 3013        };
 3014
 3015        if let Some(InlaySplice {
 3016            to_remove,
 3017            to_insert,
 3018        }) = self.inlay_hint_cache.spawn_hint_refresh(
 3019            reason_description,
 3020            self.excerpts_for_inlay_hints_query(required_languages.as_ref(), cx),
 3021            invalidate_cache,
 3022            cx,
 3023        ) {
 3024            self.splice_inlay_hints(to_remove, to_insert, cx);
 3025        }
 3026    }
 3027
 3028    fn visible_inlay_hints(&self, cx: &ViewContext<'_, Editor>) -> Vec<Inlay> {
 3029        self.display_map
 3030            .read(cx)
 3031            .current_inlays()
 3032            .filter(move |inlay| {
 3033                Some(inlay.id) != self.copilot_state.suggestion.as_ref().map(|h| h.id)
 3034            })
 3035            .cloned()
 3036            .collect()
 3037    }
 3038
 3039    pub fn excerpts_for_inlay_hints_query(
 3040        &self,
 3041        restrict_to_languages: Option<&HashSet<Arc<Language>>>,
 3042        cx: &mut ViewContext<Editor>,
 3043    ) -> HashMap<ExcerptId, (Model<Buffer>, clock::Global, Range<usize>)> {
 3044        let Some(project) = self.project.as_ref() else {
 3045            return HashMap::default();
 3046        };
 3047        let project = project.read(cx);
 3048        let multi_buffer = self.buffer().read(cx);
 3049        let multi_buffer_snapshot = multi_buffer.snapshot(cx);
 3050        let multi_buffer_visible_start = self
 3051            .scroll_manager
 3052            .anchor()
 3053            .anchor
 3054            .to_point(&multi_buffer_snapshot);
 3055        let multi_buffer_visible_end = multi_buffer_snapshot.clip_point(
 3056            multi_buffer_visible_start
 3057                + Point::new(self.visible_line_count().unwrap_or(0.).ceil() as u32, 0),
 3058            Bias::Left,
 3059        );
 3060        let multi_buffer_visible_range = multi_buffer_visible_start..multi_buffer_visible_end;
 3061        multi_buffer
 3062            .range_to_buffer_ranges(multi_buffer_visible_range, cx)
 3063            .into_iter()
 3064            .filter(|(_, excerpt_visible_range, _)| !excerpt_visible_range.is_empty())
 3065            .filter_map(|(buffer_handle, excerpt_visible_range, excerpt_id)| {
 3066                let buffer = buffer_handle.read(cx);
 3067                let buffer_file = project::worktree::File::from_dyn(buffer.file())?;
 3068                let buffer_worktree = project.worktree_for_id(buffer_file.worktree_id(cx), cx)?;
 3069                let worktree_entry = buffer_worktree
 3070                    .read(cx)
 3071                    .entry_for_id(buffer_file.project_entry_id(cx)?)?;
 3072                if worktree_entry.is_ignored {
 3073                    return None;
 3074                }
 3075
 3076                let language = buffer.language()?;
 3077                if let Some(restrict_to_languages) = restrict_to_languages {
 3078                    if !restrict_to_languages.contains(language) {
 3079                        return None;
 3080                    }
 3081                }
 3082                Some((
 3083                    excerpt_id,
 3084                    (
 3085                        buffer_handle,
 3086                        buffer.version().clone(),
 3087                        excerpt_visible_range,
 3088                    ),
 3089                ))
 3090            })
 3091            .collect()
 3092    }
 3093
 3094    pub fn text_layout_details(&self, cx: &WindowContext) -> TextLayoutDetails {
 3095        TextLayoutDetails {
 3096            text_system: cx.text_system().clone(),
 3097            editor_style: self.style.clone().unwrap(),
 3098            rem_size: cx.rem_size(),
 3099            scroll_anchor: self.scroll_manager.anchor(),
 3100            visible_rows: self.visible_line_count(),
 3101            vertical_scroll_margin: self.scroll_manager.vertical_scroll_margin,
 3102        }
 3103    }
 3104
 3105    fn splice_inlay_hints(
 3106        &self,
 3107        to_remove: Vec<InlayId>,
 3108        to_insert: Vec<Inlay>,
 3109        cx: &mut ViewContext<Self>,
 3110    ) {
 3111        self.display_map.update(cx, |display_map, cx| {
 3112            display_map.splice_inlays(to_remove, to_insert, cx);
 3113        });
 3114        cx.notify();
 3115    }
 3116
 3117    fn trigger_on_type_formatting(
 3118        &self,
 3119        input: String,
 3120        cx: &mut ViewContext<Self>,
 3121    ) -> Option<Task<Result<()>>> {
 3122        if input.len() != 1 {
 3123            return None;
 3124        }
 3125
 3126        let project = self.project.as_ref()?;
 3127        let position = self.selections.newest_anchor().head();
 3128        let (buffer, buffer_position) = self
 3129            .buffer
 3130            .read(cx)
 3131            .text_anchor_for_position(position.clone(), cx)?;
 3132
 3133        // OnTypeFormatting returns a list of edits, no need to pass them between Zed instances,
 3134        // hence we do LSP request & edit on host side only — add formats to host's history.
 3135        let push_to_lsp_host_history = true;
 3136        // If this is not the host, append its history with new edits.
 3137        let push_to_client_history = project.read(cx).is_remote();
 3138
 3139        let on_type_formatting = project.update(cx, |project, cx| {
 3140            project.on_type_format(
 3141                buffer.clone(),
 3142                buffer_position,
 3143                input,
 3144                push_to_lsp_host_history,
 3145                cx,
 3146            )
 3147        });
 3148        Some(cx.spawn(|editor, mut cx| async move {
 3149            if let Some(transaction) = on_type_formatting.await? {
 3150                if push_to_client_history {
 3151                    buffer
 3152                        .update(&mut cx, |buffer, _| {
 3153                            buffer.push_transaction(transaction, Instant::now());
 3154                        })
 3155                        .ok();
 3156                }
 3157                editor.update(&mut cx, |editor, cx| {
 3158                    editor.refresh_document_highlights(cx);
 3159                })?;
 3160            }
 3161            Ok(())
 3162        }))
 3163    }
 3164
 3165    fn show_completions(&mut self, _: &ShowCompletions, cx: &mut ViewContext<Self>) {
 3166        if self.pending_rename.is_some() {
 3167            return;
 3168        }
 3169
 3170        let Some(provider) = self.completion_provider.as_ref() else {
 3171            return;
 3172        };
 3173
 3174        let position = self.selections.newest_anchor().head();
 3175        let (buffer, buffer_position) = if let Some(output) = self
 3176            .buffer
 3177            .read(cx)
 3178            .text_anchor_for_position(position.clone(), cx)
 3179        {
 3180            output
 3181        } else {
 3182            return;
 3183        };
 3184
 3185        let query = Self::completion_query(&self.buffer.read(cx).read(cx), position.clone());
 3186        let completions = provider.completions(&buffer, buffer_position, cx);
 3187
 3188        let id = post_inc(&mut self.next_completion_id);
 3189        let task = cx.spawn(|this, mut cx| {
 3190            async move {
 3191                let completions = completions.await.log_err();
 3192                let menu = if let Some(completions) = completions {
 3193                    let mut menu = CompletionsMenu {
 3194                        id,
 3195                        initial_position: position,
 3196                        match_candidates: completions
 3197                            .iter()
 3198                            .enumerate()
 3199                            .map(|(id, completion)| {
 3200                                StringMatchCandidate::new(
 3201                                    id,
 3202                                    completion.label.text[completion.label.filter_range.clone()]
 3203                                        .into(),
 3204                                )
 3205                            })
 3206                            .collect(),
 3207                        buffer,
 3208                        completions: Arc::new(RwLock::new(completions.into())),
 3209                        matches: Vec::new().into(),
 3210                        selected_item: 0,
 3211                        scroll_handle: UniformListScrollHandle::new(),
 3212                        selected_completion_documentation_resolve_debounce: Arc::new(Mutex::new(
 3213                            DebouncedDelay::new(),
 3214                        )),
 3215                    };
 3216                    menu.filter(query.as_deref(), cx.background_executor().clone())
 3217                        .await;
 3218
 3219                    if menu.matches.is_empty() {
 3220                        None
 3221                    } else {
 3222                        this.update(&mut cx, |editor, cx| {
 3223                            let completions = menu.completions.clone();
 3224                            let matches = menu.matches.clone();
 3225
 3226                            let delay_ms = EditorSettings::get_global(cx)
 3227                                .completion_documentation_secondary_query_debounce;
 3228                            let delay = Duration::from_millis(delay_ms);
 3229
 3230                            editor
 3231                                .completion_documentation_pre_resolve_debounce
 3232                                .fire_new(delay, cx, |editor, cx| {
 3233                                    CompletionsMenu::pre_resolve_completion_documentation(
 3234                                        completions,
 3235                                        matches,
 3236                                        editor,
 3237                                        cx,
 3238                                    )
 3239                                });
 3240                        })
 3241                        .ok();
 3242                        Some(menu)
 3243                    }
 3244                } else {
 3245                    None
 3246                };
 3247
 3248                this.update(&mut cx, |this, cx| {
 3249                    this.completion_tasks.retain(|(task_id, _)| *task_id >= id);
 3250
 3251                    let mut context_menu = this.context_menu.write();
 3252                    match context_menu.as_ref() {
 3253                        None => {}
 3254
 3255                        Some(ContextMenu::Completions(prev_menu)) => {
 3256                            if prev_menu.id > id {
 3257                                return;
 3258                            }
 3259                        }
 3260
 3261                        _ => return,
 3262                    }
 3263
 3264                    if this.focus_handle.is_focused(cx) && menu.is_some() {
 3265                        let menu = menu.unwrap();
 3266                        *context_menu = Some(ContextMenu::Completions(menu));
 3267                        drop(context_menu);
 3268                        this.discard_copilot_suggestion(cx);
 3269                        cx.notify();
 3270                    } else if this.completion_tasks.len() <= 1 {
 3271                        // If there are no more completion tasks and the last menu was
 3272                        // empty, we should hide it. If it was already hidden, we should
 3273                        // also show the copilot suggestion when available.
 3274                        drop(context_menu);
 3275                        if this.hide_context_menu(cx).is_none() {
 3276                            this.update_visible_copilot_suggestion(cx);
 3277                        }
 3278                    }
 3279                })?;
 3280
 3281                Ok::<_, anyhow::Error>(())
 3282            }
 3283            .log_err()
 3284        });
 3285
 3286        self.completion_tasks.push((id, task));
 3287    }
 3288
 3289    pub fn confirm_completion(
 3290        &mut self,
 3291        action: &ConfirmCompletion,
 3292        cx: &mut ViewContext<Self>,
 3293    ) -> Option<Task<Result<()>>> {
 3294        use language::ToOffset as _;
 3295
 3296        let completions_menu = if let ContextMenu::Completions(menu) = self.hide_context_menu(cx)? {
 3297            menu
 3298        } else {
 3299            return None;
 3300        };
 3301
 3302        let mat = completions_menu
 3303            .matches
 3304            .get(action.item_ix.unwrap_or(completions_menu.selected_item))?;
 3305        let buffer_handle = completions_menu.buffer;
 3306        let completions = completions_menu.completions.read();
 3307        let completion = completions.get(mat.candidate_id)?;
 3308        cx.stop_propagation();
 3309
 3310        let snippet;
 3311        let text;
 3312        if completion.is_snippet() {
 3313            snippet = Some(Snippet::parse(&completion.new_text).log_err()?);
 3314            text = snippet.as_ref().unwrap().text.clone();
 3315        } else {
 3316            snippet = None;
 3317            text = completion.new_text.clone();
 3318        };
 3319        let selections = self.selections.all::<usize>(cx);
 3320        let buffer = buffer_handle.read(cx);
 3321        let old_range = completion.old_range.to_offset(buffer);
 3322        let old_text = buffer.text_for_range(old_range.clone()).collect::<String>();
 3323
 3324        let newest_selection = self.selections.newest_anchor();
 3325        if newest_selection.start.buffer_id != Some(buffer_handle.read(cx).remote_id()) {
 3326            return None;
 3327        }
 3328
 3329        let lookbehind = newest_selection
 3330            .start
 3331            .text_anchor
 3332            .to_offset(buffer)
 3333            .saturating_sub(old_range.start);
 3334        let lookahead = old_range
 3335            .end
 3336            .saturating_sub(newest_selection.end.text_anchor.to_offset(buffer));
 3337        let mut common_prefix_len = old_text
 3338            .bytes()
 3339            .zip(text.bytes())
 3340            .take_while(|(a, b)| a == b)
 3341            .count();
 3342
 3343        let snapshot = self.buffer.read(cx).snapshot(cx);
 3344        let mut range_to_replace: Option<Range<isize>> = None;
 3345        let mut ranges = Vec::new();
 3346        for selection in &selections {
 3347            if snapshot.contains_str_at(selection.start.saturating_sub(lookbehind), &old_text) {
 3348                let start = selection.start.saturating_sub(lookbehind);
 3349                let end = selection.end + lookahead;
 3350                if selection.id == newest_selection.id {
 3351                    range_to_replace = Some(
 3352                        ((start + common_prefix_len) as isize - selection.start as isize)
 3353                            ..(end as isize - selection.start as isize),
 3354                    );
 3355                }
 3356                ranges.push(start + common_prefix_len..end);
 3357            } else {
 3358                common_prefix_len = 0;
 3359                ranges.clear();
 3360                ranges.extend(selections.iter().map(|s| {
 3361                    if s.id == newest_selection.id {
 3362                        range_to_replace = Some(
 3363                            old_range.start.to_offset_utf16(&snapshot).0 as isize
 3364                                - selection.start as isize
 3365                                ..old_range.end.to_offset_utf16(&snapshot).0 as isize
 3366                                    - selection.start as isize,
 3367                        );
 3368                        old_range.clone()
 3369                    } else {
 3370                        s.start..s.end
 3371                    }
 3372                }));
 3373                break;
 3374            }
 3375        }
 3376        let text = &text[common_prefix_len..];
 3377
 3378        cx.emit(EditorEvent::InputHandled {
 3379            utf16_range_to_replace: range_to_replace,
 3380            text: text.into(),
 3381        });
 3382
 3383        self.transact(cx, |this, cx| {
 3384            if let Some(mut snippet) = snippet {
 3385                snippet.text = text.to_string();
 3386                for tabstop in snippet.tabstops.iter_mut().flatten() {
 3387                    tabstop.start -= common_prefix_len as isize;
 3388                    tabstop.end -= common_prefix_len as isize;
 3389                }
 3390
 3391                this.insert_snippet(&ranges, snippet, cx).log_err();
 3392            } else {
 3393                this.buffer.update(cx, |buffer, cx| {
 3394                    buffer.edit(
 3395                        ranges.iter().map(|range| (range.clone(), text)),
 3396                        this.autoindent_mode.clone(),
 3397                        cx,
 3398                    );
 3399                });
 3400            }
 3401
 3402            this.refresh_copilot_suggestions(true, cx);
 3403        });
 3404
 3405        let provider = self.completion_provider.as_ref()?;
 3406        let apply_edits = provider.apply_additional_edits_for_completion(
 3407            buffer_handle,
 3408            completion.clone(),
 3409            true,
 3410            cx,
 3411        );
 3412        Some(cx.foreground_executor().spawn(async move {
 3413            apply_edits.await?;
 3414            Ok(())
 3415        }))
 3416    }
 3417
 3418    pub fn toggle_code_actions(&mut self, action: &ToggleCodeActions, cx: &mut ViewContext<Self>) {
 3419        let mut context_menu = self.context_menu.write();
 3420        if matches!(context_menu.as_ref(), Some(ContextMenu::CodeActions(_))) {
 3421            *context_menu = None;
 3422            cx.notify();
 3423            return;
 3424        }
 3425        drop(context_menu);
 3426
 3427        let deployed_from_indicator = action.deployed_from_indicator;
 3428        let mut task = self.code_actions_task.take();
 3429        cx.spawn(|this, mut cx| async move {
 3430            while let Some(prev_task) = task {
 3431                prev_task.await;
 3432                task = this.update(&mut cx, |this, _| this.code_actions_task.take())?;
 3433            }
 3434
 3435            this.update(&mut cx, |this, cx| {
 3436                if this.focus_handle.is_focused(cx) {
 3437                    if let Some((buffer, actions)) = this.available_code_actions.clone() {
 3438                        this.completion_tasks.clear();
 3439                        this.discard_copilot_suggestion(cx);
 3440                        *this.context_menu.write() =
 3441                            Some(ContextMenu::CodeActions(CodeActionsMenu {
 3442                                buffer,
 3443                                actions,
 3444                                selected_item: Default::default(),
 3445                                scroll_handle: UniformListScrollHandle::default(),
 3446                                deployed_from_indicator,
 3447                            }));
 3448                        cx.notify();
 3449                    }
 3450                }
 3451            })?;
 3452
 3453            Ok::<_, anyhow::Error>(())
 3454        })
 3455        .detach_and_log_err(cx);
 3456    }
 3457
 3458    pub fn confirm_code_action(
 3459        &mut self,
 3460        action: &ConfirmCodeAction,
 3461        cx: &mut ViewContext<Self>,
 3462    ) -> Option<Task<Result<()>>> {
 3463        let actions_menu = if let ContextMenu::CodeActions(menu) = self.hide_context_menu(cx)? {
 3464            menu
 3465        } else {
 3466            return None;
 3467        };
 3468        let action_ix = action.item_ix.unwrap_or(actions_menu.selected_item);
 3469        let action = actions_menu.actions.get(action_ix)?.clone();
 3470        let title = action.lsp_action.title.clone();
 3471        let buffer = actions_menu.buffer;
 3472        let workspace = self.workspace()?;
 3473
 3474        let apply_code_actions = workspace
 3475            .read(cx)
 3476            .project()
 3477            .clone()
 3478            .update(cx, |project, cx| {
 3479                project.apply_code_action(buffer, action, true, cx)
 3480            });
 3481        let workspace = workspace.downgrade();
 3482        Some(cx.spawn(|editor, cx| async move {
 3483            let project_transaction = apply_code_actions.await?;
 3484            Self::open_project_transaction(&editor, workspace, project_transaction, title, cx).await
 3485        }))
 3486    }
 3487
 3488    async fn open_project_transaction(
 3489        this: &WeakView<Editor>,
 3490        workspace: WeakView<Workspace>,
 3491        transaction: ProjectTransaction,
 3492        title: String,
 3493        mut cx: AsyncWindowContext,
 3494    ) -> Result<()> {
 3495        let replica_id = this.update(&mut cx, |this, cx| this.replica_id(cx))?;
 3496
 3497        let mut entries = transaction.0.into_iter().collect::<Vec<_>>();
 3498        cx.update(|cx| {
 3499            entries.sort_unstable_by_key(|(buffer, _)| {
 3500                buffer.read(cx).file().map(|f| f.path().clone())
 3501            });
 3502        })?;
 3503
 3504        // If the project transaction's edits are all contained within this editor, then
 3505        // avoid opening a new editor to display them.
 3506
 3507        if let Some((buffer, transaction)) = entries.first() {
 3508            if entries.len() == 1 {
 3509                let excerpt = this.update(&mut cx, |editor, cx| {
 3510                    editor
 3511                        .buffer()
 3512                        .read(cx)
 3513                        .excerpt_containing(editor.selections.newest_anchor().head(), cx)
 3514                })?;
 3515                if let Some((_, excerpted_buffer, excerpt_range)) = excerpt {
 3516                    if excerpted_buffer == *buffer {
 3517                        let all_edits_within_excerpt = buffer.read_with(&cx, |buffer, _| {
 3518                            let excerpt_range = excerpt_range.to_offset(buffer);
 3519                            buffer
 3520                                .edited_ranges_for_transaction::<usize>(transaction)
 3521                                .all(|range| {
 3522                                    excerpt_range.start <= range.start
 3523                                        && excerpt_range.end >= range.end
 3524                                })
 3525                        })?;
 3526
 3527                        if all_edits_within_excerpt {
 3528                            return Ok(());
 3529                        }
 3530                    }
 3531                }
 3532            }
 3533        } else {
 3534            return Ok(());
 3535        }
 3536
 3537        let mut ranges_to_highlight = Vec::new();
 3538        let excerpt_buffer = cx.new_model(|cx| {
 3539            let mut multibuffer =
 3540                MultiBuffer::new(replica_id, Capability::ReadWrite).with_title(title);
 3541            for (buffer_handle, transaction) in &entries {
 3542                let buffer = buffer_handle.read(cx);
 3543                ranges_to_highlight.extend(
 3544                    multibuffer.push_excerpts_with_context_lines(
 3545                        buffer_handle.clone(),
 3546                        buffer
 3547                            .edited_ranges_for_transaction::<usize>(transaction)
 3548                            .collect(),
 3549                        1,
 3550                        cx,
 3551                    ),
 3552                );
 3553            }
 3554            multibuffer.push_transaction(entries.iter().map(|(b, t)| (b, t)), cx);
 3555            multibuffer
 3556        })?;
 3557
 3558        workspace.update(&mut cx, |workspace, cx| {
 3559            let project = workspace.project().clone();
 3560            let editor =
 3561                cx.new_view(|cx| Editor::for_multibuffer(excerpt_buffer, Some(project), cx));
 3562            workspace.add_item(Box::new(editor.clone()), cx);
 3563            editor.update(cx, |editor, cx| {
 3564                editor.highlight_background::<Self>(
 3565                    ranges_to_highlight,
 3566                    |theme| theme.editor_highlighted_line_background,
 3567                    cx,
 3568                );
 3569            });
 3570        })?;
 3571
 3572        Ok(())
 3573    }
 3574
 3575    fn refresh_code_actions(&mut self, cx: &mut ViewContext<Self>) -> Option<()> {
 3576        let project = self.project.clone()?;
 3577        let buffer = self.buffer.read(cx);
 3578        let newest_selection = self.selections.newest_anchor().clone();
 3579        let (start_buffer, start) = buffer.text_anchor_for_position(newest_selection.start, cx)?;
 3580        let (end_buffer, end) = buffer.text_anchor_for_position(newest_selection.end, cx)?;
 3581        if start_buffer != end_buffer {
 3582            return None;
 3583        }
 3584
 3585        self.code_actions_task = Some(cx.spawn(|this, mut cx| async move {
 3586            cx.background_executor()
 3587                .timer(CODE_ACTIONS_DEBOUNCE_TIMEOUT)
 3588                .await;
 3589
 3590            let actions = if let Ok(code_actions) = project.update(&mut cx, |project, cx| {
 3591                project.code_actions(&start_buffer, start..end, cx)
 3592            }) {
 3593                code_actions.await.log_err()
 3594            } else {
 3595                None
 3596            };
 3597
 3598            this.update(&mut cx, |this, cx| {
 3599                this.available_code_actions = actions.and_then(|actions| {
 3600                    if actions.is_empty() {
 3601                        None
 3602                    } else {
 3603                        Some((start_buffer, actions.into()))
 3604                    }
 3605                });
 3606                cx.notify();
 3607            })
 3608            .log_err();
 3609        }));
 3610        None
 3611    }
 3612
 3613    fn refresh_document_highlights(&mut self, cx: &mut ViewContext<Self>) -> Option<()> {
 3614        if self.pending_rename.is_some() {
 3615            return None;
 3616        }
 3617
 3618        let project = self.project.clone()?;
 3619        let buffer = self.buffer.read(cx);
 3620        let newest_selection = self.selections.newest_anchor().clone();
 3621        let cursor_position = newest_selection.head();
 3622        let (cursor_buffer, cursor_buffer_position) =
 3623            buffer.text_anchor_for_position(cursor_position.clone(), cx)?;
 3624        let (tail_buffer, _) = buffer.text_anchor_for_position(newest_selection.tail(), cx)?;
 3625        if cursor_buffer != tail_buffer {
 3626            return None;
 3627        }
 3628
 3629        self.document_highlights_task = Some(cx.spawn(|this, mut cx| async move {
 3630            cx.background_executor()
 3631                .timer(DOCUMENT_HIGHLIGHTS_DEBOUNCE_TIMEOUT)
 3632                .await;
 3633
 3634            let highlights = if let Some(highlights) = project
 3635                .update(&mut cx, |project, cx| {
 3636                    project.document_highlights(&cursor_buffer, cursor_buffer_position, cx)
 3637                })
 3638                .log_err()
 3639            {
 3640                highlights.await.log_err()
 3641            } else {
 3642                None
 3643            };
 3644
 3645            if let Some(highlights) = highlights {
 3646                this.update(&mut cx, |this, cx| {
 3647                    if this.pending_rename.is_some() {
 3648                        return;
 3649                    }
 3650
 3651                    let buffer_id = cursor_position.buffer_id;
 3652                    let buffer = this.buffer.read(cx);
 3653                    if !buffer
 3654                        .text_anchor_for_position(cursor_position, cx)
 3655                        .map_or(false, |(buffer, _)| buffer == cursor_buffer)
 3656                    {
 3657                        return;
 3658                    }
 3659
 3660                    let cursor_buffer_snapshot = cursor_buffer.read(cx);
 3661                    let mut write_ranges = Vec::new();
 3662                    let mut read_ranges = Vec::new();
 3663                    for highlight in highlights {
 3664                        for (excerpt_id, excerpt_range) in
 3665                            buffer.excerpts_for_buffer(&cursor_buffer, cx)
 3666                        {
 3667                            let start = highlight
 3668                                .range
 3669                                .start
 3670                                .max(&excerpt_range.context.start, cursor_buffer_snapshot);
 3671                            let end = highlight
 3672                                .range
 3673                                .end
 3674                                .min(&excerpt_range.context.end, cursor_buffer_snapshot);
 3675                            if start.cmp(&end, cursor_buffer_snapshot).is_ge() {
 3676                                continue;
 3677                            }
 3678
 3679                            let range = Anchor {
 3680                                buffer_id,
 3681                                excerpt_id: excerpt_id.clone(),
 3682                                text_anchor: start,
 3683                            }..Anchor {
 3684                                buffer_id,
 3685                                excerpt_id,
 3686                                text_anchor: end,
 3687                            };
 3688                            if highlight.kind == lsp::DocumentHighlightKind::WRITE {
 3689                                write_ranges.push(range);
 3690                            } else {
 3691                                read_ranges.push(range);
 3692                            }
 3693                        }
 3694                    }
 3695
 3696                    this.highlight_background::<DocumentHighlightRead>(
 3697                        read_ranges,
 3698                        |theme| theme.editor_document_highlight_read_background,
 3699                        cx,
 3700                    );
 3701                    this.highlight_background::<DocumentHighlightWrite>(
 3702                        write_ranges,
 3703                        |theme| theme.editor_document_highlight_write_background,
 3704                        cx,
 3705                    );
 3706                    cx.notify();
 3707                })
 3708                .log_err();
 3709            }
 3710        }));
 3711        None
 3712    }
 3713
 3714    fn refresh_copilot_suggestions(
 3715        &mut self,
 3716        debounce: bool,
 3717        cx: &mut ViewContext<Self>,
 3718    ) -> Option<()> {
 3719        let copilot = Copilot::global(cx)?;
 3720        if !self.show_copilot_suggestions || !copilot.read(cx).status().is_authorized() {
 3721            self.clear_copilot_suggestions(cx);
 3722            return None;
 3723        }
 3724        self.update_visible_copilot_suggestion(cx);
 3725
 3726        let snapshot = self.buffer.read(cx).snapshot(cx);
 3727        let cursor = self.selections.newest_anchor().head();
 3728        if !self.is_copilot_enabled_at(cursor, &snapshot, cx) {
 3729            self.clear_copilot_suggestions(cx);
 3730            return None;
 3731        }
 3732
 3733        let (buffer, buffer_position) =
 3734            self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
 3735        self.copilot_state.pending_refresh = cx.spawn(|this, mut cx| async move {
 3736            if debounce {
 3737                cx.background_executor()
 3738                    .timer(COPILOT_DEBOUNCE_TIMEOUT)
 3739                    .await;
 3740            }
 3741
 3742            let completions = copilot
 3743                .update(&mut cx, |copilot, cx| {
 3744                    copilot.completions(&buffer, buffer_position, cx)
 3745                })
 3746                .log_err()
 3747                .unwrap_or(Task::ready(Ok(Vec::new())))
 3748                .await
 3749                .log_err()
 3750                .into_iter()
 3751                .flatten()
 3752                .collect_vec();
 3753
 3754            this.update(&mut cx, |this, cx| {
 3755                if !completions.is_empty() {
 3756                    this.copilot_state.cycled = false;
 3757                    this.copilot_state.pending_cycling_refresh = Task::ready(None);
 3758                    this.copilot_state.completions.clear();
 3759                    this.copilot_state.active_completion_index = 0;
 3760                    this.copilot_state.excerpt_id = Some(cursor.excerpt_id);
 3761                    for completion in completions {
 3762                        this.copilot_state.push_completion(completion);
 3763                    }
 3764                    this.update_visible_copilot_suggestion(cx);
 3765                }
 3766            })
 3767            .log_err()?;
 3768            Some(())
 3769        });
 3770
 3771        Some(())
 3772    }
 3773
 3774    fn cycle_copilot_suggestions(
 3775        &mut self,
 3776        direction: Direction,
 3777        cx: &mut ViewContext<Self>,
 3778    ) -> Option<()> {
 3779        let copilot = Copilot::global(cx)?;
 3780        if !self.show_copilot_suggestions || !copilot.read(cx).status().is_authorized() {
 3781            return None;
 3782        }
 3783
 3784        if self.copilot_state.cycled {
 3785            self.copilot_state.cycle_completions(direction);
 3786            self.update_visible_copilot_suggestion(cx);
 3787        } else {
 3788            let cursor = self.selections.newest_anchor().head();
 3789            let (buffer, buffer_position) =
 3790                self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
 3791            self.copilot_state.pending_cycling_refresh = cx.spawn(|this, mut cx| async move {
 3792                let completions = copilot
 3793                    .update(&mut cx, |copilot, cx| {
 3794                        copilot.completions_cycling(&buffer, buffer_position, cx)
 3795                    })
 3796                    .log_err()?
 3797                    .await;
 3798
 3799                this.update(&mut cx, |this, cx| {
 3800                    this.copilot_state.cycled = true;
 3801                    for completion in completions.log_err().into_iter().flatten() {
 3802                        this.copilot_state.push_completion(completion);
 3803                    }
 3804                    this.copilot_state.cycle_completions(direction);
 3805                    this.update_visible_copilot_suggestion(cx);
 3806                })
 3807                .log_err()?;
 3808
 3809                Some(())
 3810            });
 3811        }
 3812
 3813        Some(())
 3814    }
 3815
 3816    fn copilot_suggest(&mut self, _: &copilot::Suggest, cx: &mut ViewContext<Self>) {
 3817        if !self.has_active_copilot_suggestion(cx) {
 3818            self.refresh_copilot_suggestions(false, cx);
 3819            return;
 3820        }
 3821
 3822        self.update_visible_copilot_suggestion(cx);
 3823    }
 3824
 3825    pub fn display_cursor_names(&mut self, _: &DisplayCursorNames, cx: &mut ViewContext<Self>) {
 3826        self.show_cursor_names(cx);
 3827    }
 3828
 3829    fn show_cursor_names(&mut self, cx: &mut ViewContext<Self>) {
 3830        self.show_cursor_names = true;
 3831        cx.notify();
 3832        cx.spawn(|this, mut cx| async move {
 3833            cx.background_executor().timer(CURSORS_VISIBLE_FOR).await;
 3834            this.update(&mut cx, |this, cx| {
 3835                this.show_cursor_names = false;
 3836                cx.notify()
 3837            })
 3838            .ok()
 3839        })
 3840        .detach();
 3841    }
 3842
 3843    fn next_copilot_suggestion(&mut self, _: &copilot::NextSuggestion, cx: &mut ViewContext<Self>) {
 3844        if self.has_active_copilot_suggestion(cx) {
 3845            self.cycle_copilot_suggestions(Direction::Next, cx);
 3846        } else {
 3847            let is_copilot_disabled = self.refresh_copilot_suggestions(false, cx).is_none();
 3848            if is_copilot_disabled {
 3849                cx.propagate();
 3850            }
 3851        }
 3852    }
 3853
 3854    fn previous_copilot_suggestion(
 3855        &mut self,
 3856        _: &copilot::PreviousSuggestion,
 3857        cx: &mut ViewContext<Self>,
 3858    ) {
 3859        if self.has_active_copilot_suggestion(cx) {
 3860            self.cycle_copilot_suggestions(Direction::Prev, cx);
 3861        } else {
 3862            let is_copilot_disabled = self.refresh_copilot_suggestions(false, cx).is_none();
 3863            if is_copilot_disabled {
 3864                cx.propagate();
 3865            }
 3866        }
 3867    }
 3868
 3869    fn accept_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) -> bool {
 3870        if let Some(suggestion) = self.take_active_copilot_suggestion(cx) {
 3871            if let Some((copilot, completion)) =
 3872                Copilot::global(cx).zip(self.copilot_state.active_completion())
 3873            {
 3874                copilot
 3875                    .update(cx, |copilot, cx| copilot.accept_completion(completion, cx))
 3876                    .detach_and_log_err(cx);
 3877
 3878                self.report_copilot_event(Some(completion.uuid.clone()), true, cx)
 3879            }
 3880            cx.emit(EditorEvent::InputHandled {
 3881                utf16_range_to_replace: None,
 3882                text: suggestion.text.to_string().into(),
 3883            });
 3884            self.insert_with_autoindent_mode(&suggestion.text.to_string(), None, cx);
 3885            cx.notify();
 3886            true
 3887        } else {
 3888            false
 3889        }
 3890    }
 3891
 3892    fn discard_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) -> bool {
 3893        if let Some(suggestion) = self.take_active_copilot_suggestion(cx) {
 3894            if let Some(copilot) = Copilot::global(cx) {
 3895                copilot
 3896                    .update(cx, |copilot, cx| {
 3897                        copilot.discard_completions(&self.copilot_state.completions, cx)
 3898                    })
 3899                    .detach_and_log_err(cx);
 3900
 3901                self.report_copilot_event(None, false, cx)
 3902            }
 3903
 3904            self.display_map.update(cx, |map, cx| {
 3905                map.splice_inlays(vec![suggestion.id], Vec::new(), cx)
 3906            });
 3907            cx.notify();
 3908            true
 3909        } else {
 3910            false
 3911        }
 3912    }
 3913
 3914    fn is_copilot_enabled_at(
 3915        &self,
 3916        location: Anchor,
 3917        snapshot: &MultiBufferSnapshot,
 3918        cx: &mut ViewContext<Self>,
 3919    ) -> bool {
 3920        let file = snapshot.file_at(location);
 3921        let language = snapshot.language_at(location);
 3922        let settings = all_language_settings(file, cx);
 3923        self.show_copilot_suggestions
 3924            && settings.copilot_enabled(language, file.map(|f| f.path().as_ref()))
 3925    }
 3926
 3927    fn has_active_copilot_suggestion(&self, cx: &AppContext) -> bool {
 3928        if let Some(suggestion) = self.copilot_state.suggestion.as_ref() {
 3929            let buffer = self.buffer.read(cx).read(cx);
 3930            suggestion.position.is_valid(&buffer)
 3931        } else {
 3932            false
 3933        }
 3934    }
 3935
 3936    fn take_active_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) -> Option<Inlay> {
 3937        let suggestion = self.copilot_state.suggestion.take()?;
 3938        self.display_map.update(cx, |map, cx| {
 3939            map.splice_inlays(vec![suggestion.id], Default::default(), cx);
 3940        });
 3941        let buffer = self.buffer.read(cx).read(cx);
 3942
 3943        if suggestion.position.is_valid(&buffer) {
 3944            Some(suggestion)
 3945        } else {
 3946            None
 3947        }
 3948    }
 3949
 3950    fn update_visible_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) {
 3951        let snapshot = self.buffer.read(cx).snapshot(cx);
 3952        let selection = self.selections.newest_anchor();
 3953        let cursor = selection.head();
 3954
 3955        if self.context_menu.read().is_some()
 3956            || !self.completion_tasks.is_empty()
 3957            || selection.start != selection.end
 3958        {
 3959            self.discard_copilot_suggestion(cx);
 3960        } else if let Some(text) = self
 3961            .copilot_state
 3962            .text_for_active_completion(cursor, &snapshot)
 3963        {
 3964            let text = Rope::from(text);
 3965            let mut to_remove = Vec::new();
 3966            if let Some(suggestion) = self.copilot_state.suggestion.take() {
 3967                to_remove.push(suggestion.id);
 3968            }
 3969
 3970            let suggestion_inlay =
 3971                Inlay::suggestion(post_inc(&mut self.next_inlay_id), cursor, text);
 3972            self.copilot_state.suggestion = Some(suggestion_inlay.clone());
 3973            self.display_map.update(cx, move |map, cx| {
 3974                map.splice_inlays(to_remove, vec![suggestion_inlay], cx)
 3975            });
 3976            cx.notify();
 3977        } else {
 3978            self.discard_copilot_suggestion(cx);
 3979        }
 3980    }
 3981
 3982    fn clear_copilot_suggestions(&mut self, cx: &mut ViewContext<Self>) {
 3983        self.copilot_state = Default::default();
 3984        self.discard_copilot_suggestion(cx);
 3985    }
 3986
 3987    pub fn render_code_actions_indicator(
 3988        &self,
 3989        _style: &EditorStyle,
 3990        is_active: bool,
 3991        cx: &mut ViewContext<Self>,
 3992    ) -> Option<IconButton> {
 3993        if self.available_code_actions.is_some() {
 3994            Some(
 3995                IconButton::new("code_actions_indicator", ui::IconName::Bolt)
 3996                    .icon_size(IconSize::Small)
 3997                    .icon_color(Color::Muted)
 3998                    .selected(is_active)
 3999                    .on_click(cx.listener(|editor, _e, cx| {
 4000                        editor.toggle_code_actions(
 4001                            &ToggleCodeActions {
 4002                                deployed_from_indicator: true,
 4003                            },
 4004                            cx,
 4005                        );
 4006                    })),
 4007            )
 4008        } else {
 4009            None
 4010        }
 4011    }
 4012
 4013    pub fn render_fold_indicators(
 4014        &self,
 4015        fold_data: Vec<Option<(FoldStatus, u32, bool)>>,
 4016        _style: &EditorStyle,
 4017        gutter_hovered: bool,
 4018        _line_height: Pixels,
 4019        _gutter_margin: Pixels,
 4020        editor_view: View<Editor>,
 4021    ) -> Vec<Option<IconButton>> {
 4022        fold_data
 4023            .iter()
 4024            .enumerate()
 4025            .map(|(ix, fold_data)| {
 4026                fold_data
 4027                    .map(|(fold_status, buffer_row, active)| {
 4028                        (active || gutter_hovered || fold_status == FoldStatus::Folded).then(|| {
 4029                            IconButton::new(ix as usize, ui::IconName::ChevronDown)
 4030                                .on_click({
 4031                                    let view = editor_view.clone();
 4032                                    move |_e, cx| {
 4033                                        view.update(cx, |editor, cx| match fold_status {
 4034                                            FoldStatus::Folded => {
 4035                                                editor.unfold_at(&UnfoldAt { buffer_row }, cx);
 4036                                            }
 4037                                            FoldStatus::Foldable => {
 4038                                                editor.fold_at(&FoldAt { buffer_row }, cx);
 4039                                            }
 4040                                        })
 4041                                    }
 4042                                })
 4043                                .icon_color(ui::Color::Muted)
 4044                                .icon_size(ui::IconSize::Small)
 4045                                .selected(fold_status == FoldStatus::Folded)
 4046                                .selected_icon(ui::IconName::ChevronRight)
 4047                                .size(ui::ButtonSize::None)
 4048                        })
 4049                    })
 4050                    .flatten()
 4051            })
 4052            .collect()
 4053    }
 4054
 4055    pub fn context_menu_visible(&self) -> bool {
 4056        self.context_menu
 4057            .read()
 4058            .as_ref()
 4059            .map_or(false, |menu| menu.visible())
 4060    }
 4061
 4062    pub fn render_context_menu(
 4063        &self,
 4064        cursor_position: DisplayPoint,
 4065        style: &EditorStyle,
 4066        max_height: Pixels,
 4067        cx: &mut ViewContext<Editor>,
 4068    ) -> Option<(DisplayPoint, AnyElement)> {
 4069        self.context_menu.read().as_ref().map(|menu| {
 4070            menu.render(
 4071                cursor_position,
 4072                style,
 4073                max_height,
 4074                self.workspace.as_ref().map(|(w, _)| w.clone()),
 4075                cx,
 4076            )
 4077        })
 4078    }
 4079
 4080    fn hide_context_menu(&mut self, cx: &mut ViewContext<Self>) -> Option<ContextMenu> {
 4081        cx.notify();
 4082        self.completion_tasks.clear();
 4083        let context_menu = self.context_menu.write().take();
 4084        if context_menu.is_some() {
 4085            self.update_visible_copilot_suggestion(cx);
 4086        }
 4087        context_menu
 4088    }
 4089
 4090    pub fn insert_snippet(
 4091        &mut self,
 4092        insertion_ranges: &[Range<usize>],
 4093        snippet: Snippet,
 4094        cx: &mut ViewContext<Self>,
 4095    ) -> Result<()> {
 4096        let tabstops = self.buffer.update(cx, |buffer, cx| {
 4097            let snippet_text: Arc<str> = snippet.text.clone().into();
 4098            buffer.edit(
 4099                insertion_ranges
 4100                    .iter()
 4101                    .cloned()
 4102                    .map(|range| (range, snippet_text.clone())),
 4103                Some(AutoindentMode::EachLine),
 4104                cx,
 4105            );
 4106
 4107            let snapshot = &*buffer.read(cx);
 4108            let snippet = &snippet;
 4109            snippet
 4110                .tabstops
 4111                .iter()
 4112                .map(|tabstop| {
 4113                    let mut tabstop_ranges = tabstop
 4114                        .iter()
 4115                        .flat_map(|tabstop_range| {
 4116                            let mut delta = 0_isize;
 4117                            insertion_ranges.iter().map(move |insertion_range| {
 4118                                let insertion_start = insertion_range.start as isize + delta;
 4119                                delta +=
 4120                                    snippet.text.len() as isize - insertion_range.len() as isize;
 4121
 4122                                let start = snapshot.anchor_before(
 4123                                    (insertion_start + tabstop_range.start) as usize,
 4124                                );
 4125                                let end = snapshot
 4126                                    .anchor_after((insertion_start + tabstop_range.end) as usize);
 4127                                start..end
 4128                            })
 4129                        })
 4130                        .collect::<Vec<_>>();
 4131                    tabstop_ranges.sort_unstable_by(|a, b| a.start.cmp(&b.start, snapshot));
 4132                    tabstop_ranges
 4133                })
 4134                .collect::<Vec<_>>()
 4135        });
 4136
 4137        if let Some(tabstop) = tabstops.first() {
 4138            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 4139                s.select_ranges(tabstop.iter().cloned());
 4140            });
 4141            self.snippet_stack.push(SnippetState {
 4142                active_index: 0,
 4143                ranges: tabstops,
 4144            });
 4145        }
 4146
 4147        Ok(())
 4148    }
 4149
 4150    pub fn move_to_next_snippet_tabstop(&mut self, cx: &mut ViewContext<Self>) -> bool {
 4151        self.move_to_snippet_tabstop(Bias::Right, cx)
 4152    }
 4153
 4154    pub fn move_to_prev_snippet_tabstop(&mut self, cx: &mut ViewContext<Self>) -> bool {
 4155        self.move_to_snippet_tabstop(Bias::Left, cx)
 4156    }
 4157
 4158    pub fn move_to_snippet_tabstop(&mut self, bias: Bias, cx: &mut ViewContext<Self>) -> bool {
 4159        if let Some(mut snippet) = self.snippet_stack.pop() {
 4160            match bias {
 4161                Bias::Left => {
 4162                    if snippet.active_index > 0 {
 4163                        snippet.active_index -= 1;
 4164                    } else {
 4165                        self.snippet_stack.push(snippet);
 4166                        return false;
 4167                    }
 4168                }
 4169                Bias::Right => {
 4170                    if snippet.active_index + 1 < snippet.ranges.len() {
 4171                        snippet.active_index += 1;
 4172                    } else {
 4173                        self.snippet_stack.push(snippet);
 4174                        return false;
 4175                    }
 4176                }
 4177            }
 4178            if let Some(current_ranges) = snippet.ranges.get(snippet.active_index) {
 4179                self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 4180                    s.select_anchor_ranges(current_ranges.iter().cloned())
 4181                });
 4182                // If snippet state is not at the last tabstop, push it back on the stack
 4183                if snippet.active_index + 1 < snippet.ranges.len() {
 4184                    self.snippet_stack.push(snippet);
 4185                }
 4186                return true;
 4187            }
 4188        }
 4189
 4190        false
 4191    }
 4192
 4193    pub fn clear(&mut self, cx: &mut ViewContext<Self>) {
 4194        self.transact(cx, |this, cx| {
 4195            this.select_all(&SelectAll, cx);
 4196            this.insert("", cx);
 4197        });
 4198    }
 4199
 4200    pub fn backspace(&mut self, _: &Backspace, cx: &mut ViewContext<Self>) {
 4201        self.transact(cx, |this, cx| {
 4202            this.select_autoclose_pair(cx);
 4203            let mut selections = this.selections.all::<Point>(cx);
 4204            if !this.selections.line_mode {
 4205                let display_map = this.display_map.update(cx, |map, cx| map.snapshot(cx));
 4206                for selection in &mut selections {
 4207                    if selection.is_empty() {
 4208                        let old_head = selection.head();
 4209                        let mut new_head =
 4210                            movement::left(&display_map, old_head.to_display_point(&display_map))
 4211                                .to_point(&display_map);
 4212                        if let Some((buffer, line_buffer_range)) = display_map
 4213                            .buffer_snapshot
 4214                            .buffer_line_for_row(old_head.row)
 4215                        {
 4216                            let indent_size =
 4217                                buffer.indent_size_for_line(line_buffer_range.start.row);
 4218                            let indent_len = match indent_size.kind {
 4219                                IndentKind::Space => {
 4220                                    buffer.settings_at(line_buffer_range.start, cx).tab_size
 4221                                }
 4222                                IndentKind::Tab => NonZeroU32::new(1).unwrap(),
 4223                            };
 4224                            if old_head.column <= indent_size.len && old_head.column > 0 {
 4225                                let indent_len = indent_len.get();
 4226                                new_head = cmp::min(
 4227                                    new_head,
 4228                                    Point::new(
 4229                                        old_head.row,
 4230                                        ((old_head.column - 1) / indent_len) * indent_len,
 4231                                    ),
 4232                                );
 4233                            }
 4234                        }
 4235
 4236                        selection.set_head(new_head, SelectionGoal::None);
 4237                    }
 4238                }
 4239            }
 4240
 4241            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
 4242            this.insert("", cx);
 4243            this.refresh_copilot_suggestions(true, cx);
 4244        });
 4245    }
 4246
 4247    pub fn delete(&mut self, _: &Delete, cx: &mut ViewContext<Self>) {
 4248        self.transact(cx, |this, cx| {
 4249            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 4250                let line_mode = s.line_mode;
 4251                s.move_with(|map, selection| {
 4252                    if selection.is_empty() && !line_mode {
 4253                        let cursor = movement::right(map, selection.head());
 4254                        selection.end = cursor;
 4255                        selection.reversed = true;
 4256                        selection.goal = SelectionGoal::None;
 4257                    }
 4258                })
 4259            });
 4260            this.insert("", cx);
 4261            this.refresh_copilot_suggestions(true, cx);
 4262        });
 4263    }
 4264
 4265    pub fn tab_prev(&mut self, _: &TabPrev, cx: &mut ViewContext<Self>) {
 4266        if self.move_to_prev_snippet_tabstop(cx) {
 4267            return;
 4268        }
 4269
 4270        self.outdent(&Outdent, cx);
 4271    }
 4272
 4273    pub fn tab(&mut self, _: &Tab, cx: &mut ViewContext<Self>) {
 4274        if self.move_to_next_snippet_tabstop(cx) || self.read_only(cx) {
 4275            return;
 4276        }
 4277
 4278        let mut selections = self.selections.all_adjusted(cx);
 4279        let buffer = self.buffer.read(cx);
 4280        let snapshot = buffer.snapshot(cx);
 4281        let rows_iter = selections.iter().map(|s| s.head().row);
 4282        let suggested_indents = snapshot.suggested_indents(rows_iter, cx);
 4283
 4284        let mut edits = Vec::new();
 4285        let mut prev_edited_row = 0;
 4286        let mut row_delta = 0;
 4287        for selection in &mut selections {
 4288            if selection.start.row != prev_edited_row {
 4289                row_delta = 0;
 4290            }
 4291            prev_edited_row = selection.end.row;
 4292
 4293            // If the selection is non-empty, then increase the indentation of the selected lines.
 4294            if !selection.is_empty() {
 4295                row_delta =
 4296                    Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
 4297                continue;
 4298            }
 4299
 4300            // If the selection is empty and the cursor is in the leading whitespace before the
 4301            // suggested indentation, then auto-indent the line.
 4302            let cursor = selection.head();
 4303            let current_indent = snapshot.indent_size_for_line(cursor.row);
 4304            if let Some(suggested_indent) = suggested_indents.get(&cursor.row).copied() {
 4305                if cursor.column < suggested_indent.len
 4306                    && cursor.column <= current_indent.len
 4307                    && current_indent.len <= suggested_indent.len
 4308                {
 4309                    selection.start = Point::new(cursor.row, suggested_indent.len);
 4310                    selection.end = selection.start;
 4311                    if row_delta == 0 {
 4312                        edits.extend(Buffer::edit_for_indent_size_adjustment(
 4313                            cursor.row,
 4314                            current_indent,
 4315                            suggested_indent,
 4316                        ));
 4317                        row_delta = suggested_indent.len - current_indent.len;
 4318                    }
 4319                    continue;
 4320                }
 4321            }
 4322
 4323            // Accept copilot suggestion if there is only one selection and the cursor is not
 4324            // in the leading whitespace.
 4325            if self.selections.count() == 1
 4326                && cursor.column >= current_indent.len
 4327                && self.has_active_copilot_suggestion(cx)
 4328            {
 4329                self.accept_copilot_suggestion(cx);
 4330                return;
 4331            }
 4332
 4333            // Otherwise, insert a hard or soft tab.
 4334            let settings = buffer.settings_at(cursor, cx);
 4335            let tab_size = if settings.hard_tabs {
 4336                IndentSize::tab()
 4337            } else {
 4338                let tab_size = settings.tab_size.get();
 4339                let char_column = snapshot
 4340                    .text_for_range(Point::new(cursor.row, 0)..cursor)
 4341                    .flat_map(str::chars)
 4342                    .count()
 4343                    + row_delta as usize;
 4344                let chars_to_next_tab_stop = tab_size - (char_column as u32 % tab_size);
 4345                IndentSize::spaces(chars_to_next_tab_stop)
 4346            };
 4347            selection.start = Point::new(cursor.row, cursor.column + row_delta + tab_size.len);
 4348            selection.end = selection.start;
 4349            edits.push((cursor..cursor, tab_size.chars().collect::<String>()));
 4350            row_delta += tab_size.len;
 4351        }
 4352
 4353        self.transact(cx, |this, cx| {
 4354            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
 4355            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
 4356            this.refresh_copilot_suggestions(true, cx);
 4357        });
 4358    }
 4359
 4360    pub fn indent(&mut self, _: &Indent, cx: &mut ViewContext<Self>) {
 4361        let mut selections = self.selections.all::<Point>(cx);
 4362        let mut prev_edited_row = 0;
 4363        let mut row_delta = 0;
 4364        let mut edits = Vec::new();
 4365        let buffer = self.buffer.read(cx);
 4366        let snapshot = buffer.snapshot(cx);
 4367        for selection in &mut selections {
 4368            if selection.start.row != prev_edited_row {
 4369                row_delta = 0;
 4370            }
 4371            prev_edited_row = selection.end.row;
 4372
 4373            row_delta =
 4374                Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
 4375        }
 4376
 4377        self.transact(cx, |this, cx| {
 4378            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
 4379            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
 4380        });
 4381    }
 4382
 4383    fn indent_selection(
 4384        buffer: &MultiBuffer,
 4385        snapshot: &MultiBufferSnapshot,
 4386        selection: &mut Selection<Point>,
 4387        edits: &mut Vec<(Range<Point>, String)>,
 4388        delta_for_start_row: u32,
 4389        cx: &AppContext,
 4390    ) -> u32 {
 4391        let settings = buffer.settings_at(selection.start, cx);
 4392        let tab_size = settings.tab_size.get();
 4393        let indent_kind = if settings.hard_tabs {
 4394            IndentKind::Tab
 4395        } else {
 4396            IndentKind::Space
 4397        };
 4398        let mut start_row = selection.start.row;
 4399        let mut end_row = selection.end.row + 1;
 4400
 4401        // If a selection ends at the beginning of a line, don't indent
 4402        // that last line.
 4403        if selection.end.column == 0 {
 4404            end_row -= 1;
 4405        }
 4406
 4407        // Avoid re-indenting a row that has already been indented by a
 4408        // previous selection, but still update this selection's column
 4409        // to reflect that indentation.
 4410        if delta_for_start_row > 0 {
 4411            start_row += 1;
 4412            selection.start.column += delta_for_start_row;
 4413            if selection.end.row == selection.start.row {
 4414                selection.end.column += delta_for_start_row;
 4415            }
 4416        }
 4417
 4418        let mut delta_for_end_row = 0;
 4419        for row in start_row..end_row {
 4420            let current_indent = snapshot.indent_size_for_line(row);
 4421            let indent_delta = match (current_indent.kind, indent_kind) {
 4422                (IndentKind::Space, IndentKind::Space) => {
 4423                    let columns_to_next_tab_stop = tab_size - (current_indent.len % tab_size);
 4424                    IndentSize::spaces(columns_to_next_tab_stop)
 4425                }
 4426                (IndentKind::Tab, IndentKind::Space) => IndentSize::spaces(tab_size),
 4427                (_, IndentKind::Tab) => IndentSize::tab(),
 4428            };
 4429
 4430            let row_start = Point::new(row, 0);
 4431            edits.push((
 4432                row_start..row_start,
 4433                indent_delta.chars().collect::<String>(),
 4434            ));
 4435
 4436            // Update this selection's endpoints to reflect the indentation.
 4437            if row == selection.start.row {
 4438                selection.start.column += indent_delta.len;
 4439            }
 4440            if row == selection.end.row {
 4441                selection.end.column += indent_delta.len;
 4442                delta_for_end_row = indent_delta.len;
 4443            }
 4444        }
 4445
 4446        if selection.start.row == selection.end.row {
 4447            delta_for_start_row + delta_for_end_row
 4448        } else {
 4449            delta_for_end_row
 4450        }
 4451    }
 4452
 4453    pub fn outdent(&mut self, _: &Outdent, cx: &mut ViewContext<Self>) {
 4454        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 4455        let selections = self.selections.all::<Point>(cx);
 4456        let mut deletion_ranges = Vec::new();
 4457        let mut last_outdent = None;
 4458        {
 4459            let buffer = self.buffer.read(cx);
 4460            let snapshot = buffer.snapshot(cx);
 4461            for selection in &selections {
 4462                let settings = buffer.settings_at(selection.start, cx);
 4463                let tab_size = settings.tab_size.get();
 4464                let mut rows = selection.spanned_rows(false, &display_map);
 4465
 4466                // Avoid re-outdenting a row that has already been outdented by a
 4467                // previous selection.
 4468                if let Some(last_row) = last_outdent {
 4469                    if last_row == rows.start {
 4470                        rows.start += 1;
 4471                    }
 4472                }
 4473
 4474                for row in rows {
 4475                    let indent_size = snapshot.indent_size_for_line(row);
 4476                    if indent_size.len > 0 {
 4477                        let deletion_len = match indent_size.kind {
 4478                            IndentKind::Space => {
 4479                                let columns_to_prev_tab_stop = indent_size.len % tab_size;
 4480                                if columns_to_prev_tab_stop == 0 {
 4481                                    tab_size
 4482                                } else {
 4483                                    columns_to_prev_tab_stop
 4484                                }
 4485                            }
 4486                            IndentKind::Tab => 1,
 4487                        };
 4488                        deletion_ranges.push(Point::new(row, 0)..Point::new(row, deletion_len));
 4489                        last_outdent = Some(row);
 4490                    }
 4491                }
 4492            }
 4493        }
 4494
 4495        self.transact(cx, |this, cx| {
 4496            this.buffer.update(cx, |buffer, cx| {
 4497                let empty_str: Arc<str> = "".into();
 4498                buffer.edit(
 4499                    deletion_ranges
 4500                        .into_iter()
 4501                        .map(|range| (range, empty_str.clone())),
 4502                    None,
 4503                    cx,
 4504                );
 4505            });
 4506            let selections = this.selections.all::<usize>(cx);
 4507            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
 4508        });
 4509    }
 4510
 4511    pub fn delete_line(&mut self, _: &DeleteLine, cx: &mut ViewContext<Self>) {
 4512        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 4513        let selections = self.selections.all::<Point>(cx);
 4514
 4515        let mut new_cursors = Vec::new();
 4516        let mut edit_ranges = Vec::new();
 4517        let mut selections = selections.iter().peekable();
 4518        while let Some(selection) = selections.next() {
 4519            let mut rows = selection.spanned_rows(false, &display_map);
 4520            let goal_display_column = selection.head().to_display_point(&display_map).column();
 4521
 4522            // Accumulate contiguous regions of rows that we want to delete.
 4523            while let Some(next_selection) = selections.peek() {
 4524                let next_rows = next_selection.spanned_rows(false, &display_map);
 4525                if next_rows.start <= rows.end {
 4526                    rows.end = next_rows.end;
 4527                    selections.next().unwrap();
 4528                } else {
 4529                    break;
 4530                }
 4531            }
 4532
 4533            let buffer = &display_map.buffer_snapshot;
 4534            let mut edit_start = Point::new(rows.start, 0).to_offset(buffer);
 4535            let edit_end;
 4536            let cursor_buffer_row;
 4537            if buffer.max_point().row >= rows.end {
 4538                // If there's a line after the range, delete the \n from the end of the row range
 4539                // and position the cursor on the next line.
 4540                edit_end = Point::new(rows.end, 0).to_offset(buffer);
 4541                cursor_buffer_row = rows.end;
 4542            } else {
 4543                // If there isn't a line after the range, delete the \n from the line before the
 4544                // start of the row range and position the cursor there.
 4545                edit_start = edit_start.saturating_sub(1);
 4546                edit_end = buffer.len();
 4547                cursor_buffer_row = rows.start.saturating_sub(1);
 4548            }
 4549
 4550            let mut cursor = Point::new(cursor_buffer_row, 0).to_display_point(&display_map);
 4551            *cursor.column_mut() =
 4552                cmp::min(goal_display_column, display_map.line_len(cursor.row()));
 4553
 4554            new_cursors.push((
 4555                selection.id,
 4556                buffer.anchor_after(cursor.to_point(&display_map)),
 4557            ));
 4558            edit_ranges.push(edit_start..edit_end);
 4559        }
 4560
 4561        self.transact(cx, |this, cx| {
 4562            let buffer = this.buffer.update(cx, |buffer, cx| {
 4563                let empty_str: Arc<str> = "".into();
 4564                buffer.edit(
 4565                    edit_ranges
 4566                        .into_iter()
 4567                        .map(|range| (range, empty_str.clone())),
 4568                    None,
 4569                    cx,
 4570                );
 4571                buffer.snapshot(cx)
 4572            });
 4573            let new_selections = new_cursors
 4574                .into_iter()
 4575                .map(|(id, cursor)| {
 4576                    let cursor = cursor.to_point(&buffer);
 4577                    Selection {
 4578                        id,
 4579                        start: cursor,
 4580                        end: cursor,
 4581                        reversed: false,
 4582                        goal: SelectionGoal::None,
 4583                    }
 4584                })
 4585                .collect();
 4586
 4587            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 4588                s.select(new_selections);
 4589            });
 4590        });
 4591    }
 4592
 4593    pub fn join_lines(&mut self, _: &JoinLines, cx: &mut ViewContext<Self>) {
 4594        let mut row_ranges = Vec::<Range<u32>>::new();
 4595        for selection in self.selections.all::<Point>(cx) {
 4596            let start = selection.start.row;
 4597            let end = if selection.start.row == selection.end.row {
 4598                selection.start.row + 1
 4599            } else {
 4600                selection.end.row
 4601            };
 4602
 4603            if let Some(last_row_range) = row_ranges.last_mut() {
 4604                if start <= last_row_range.end {
 4605                    last_row_range.end = end;
 4606                    continue;
 4607                }
 4608            }
 4609            row_ranges.push(start..end);
 4610        }
 4611
 4612        let snapshot = self.buffer.read(cx).snapshot(cx);
 4613        let mut cursor_positions = Vec::new();
 4614        for row_range in &row_ranges {
 4615            let anchor = snapshot.anchor_before(Point::new(
 4616                row_range.end - 1,
 4617                snapshot.line_len(row_range.end - 1),
 4618            ));
 4619            cursor_positions.push(anchor.clone()..anchor);
 4620        }
 4621
 4622        self.transact(cx, |this, cx| {
 4623            for row_range in row_ranges.into_iter().rev() {
 4624                for row in row_range.rev() {
 4625                    let end_of_line = Point::new(row, snapshot.line_len(row));
 4626                    let indent = snapshot.indent_size_for_line(row + 1);
 4627                    let start_of_next_line = Point::new(row + 1, indent.len);
 4628
 4629                    let replace = if snapshot.line_len(row + 1) > indent.len {
 4630                        " "
 4631                    } else {
 4632                        ""
 4633                    };
 4634
 4635                    this.buffer.update(cx, |buffer, cx| {
 4636                        buffer.edit([(end_of_line..start_of_next_line, replace)], None, cx)
 4637                    });
 4638                }
 4639            }
 4640
 4641            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 4642                s.select_anchor_ranges(cursor_positions)
 4643            });
 4644        });
 4645    }
 4646
 4647    pub fn sort_lines_case_sensitive(
 4648        &mut self,
 4649        _: &SortLinesCaseSensitive,
 4650        cx: &mut ViewContext<Self>,
 4651    ) {
 4652        self.manipulate_lines(cx, |lines| lines.sort())
 4653    }
 4654
 4655    pub fn sort_lines_case_insensitive(
 4656        &mut self,
 4657        _: &SortLinesCaseInsensitive,
 4658        cx: &mut ViewContext<Self>,
 4659    ) {
 4660        self.manipulate_lines(cx, |lines| lines.sort_by_key(|line| line.to_lowercase()))
 4661    }
 4662
 4663    pub fn unique_lines_case_insensitive(
 4664        &mut self,
 4665        _: &UniqueLinesCaseInsensitive,
 4666        cx: &mut ViewContext<Self>,
 4667    ) {
 4668        self.manipulate_lines(cx, |lines| {
 4669            let mut seen = HashSet::default();
 4670            lines.retain(|line| seen.insert(line.to_lowercase()));
 4671        })
 4672    }
 4673
 4674    pub fn unique_lines_case_sensitive(
 4675        &mut self,
 4676        _: &UniqueLinesCaseSensitive,
 4677        cx: &mut ViewContext<Self>,
 4678    ) {
 4679        self.manipulate_lines(cx, |lines| {
 4680            let mut seen = HashSet::default();
 4681            lines.retain(|line| seen.insert(*line));
 4682        })
 4683    }
 4684
 4685    pub fn reverse_lines(&mut self, _: &ReverseLines, cx: &mut ViewContext<Self>) {
 4686        self.manipulate_lines(cx, |lines| lines.reverse())
 4687    }
 4688
 4689    pub fn shuffle_lines(&mut self, _: &ShuffleLines, cx: &mut ViewContext<Self>) {
 4690        self.manipulate_lines(cx, |lines| lines.shuffle(&mut thread_rng()))
 4691    }
 4692
 4693    fn manipulate_lines<Fn>(&mut self, cx: &mut ViewContext<Self>, mut callback: Fn)
 4694    where
 4695        Fn: FnMut(&mut Vec<&str>),
 4696    {
 4697        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 4698        let buffer = self.buffer.read(cx).snapshot(cx);
 4699
 4700        let mut edits = Vec::new();
 4701
 4702        let selections = self.selections.all::<Point>(cx);
 4703        let mut selections = selections.iter().peekable();
 4704        let mut contiguous_row_selections = Vec::new();
 4705        let mut new_selections = Vec::new();
 4706        let mut added_lines = 0;
 4707        let mut removed_lines = 0;
 4708
 4709        while let Some(selection) = selections.next() {
 4710            let (start_row, end_row) = consume_contiguous_rows(
 4711                &mut contiguous_row_selections,
 4712                selection,
 4713                &display_map,
 4714                &mut selections,
 4715            );
 4716
 4717            let start_point = Point::new(start_row, 0);
 4718            let end_point = Point::new(end_row - 1, buffer.line_len(end_row - 1));
 4719            let text = buffer
 4720                .text_for_range(start_point..end_point)
 4721                .collect::<String>();
 4722
 4723            let mut lines = text.split("\n").collect_vec();
 4724
 4725            let lines_before = lines.len();
 4726            callback(&mut lines);
 4727            let lines_after = lines.len();
 4728
 4729            edits.push((start_point..end_point, lines.join("\n")));
 4730
 4731            // Selections must change based on added and removed line count
 4732            let start_row = start_point.row + added_lines as u32 - removed_lines as u32;
 4733            let end_row = start_row + lines_after.saturating_sub(1) as u32;
 4734            new_selections.push(Selection {
 4735                id: selection.id,
 4736                start: start_row,
 4737                end: end_row,
 4738                goal: SelectionGoal::None,
 4739                reversed: selection.reversed,
 4740            });
 4741
 4742            if lines_after > lines_before {
 4743                added_lines += lines_after - lines_before;
 4744            } else if lines_before > lines_after {
 4745                removed_lines += lines_before - lines_after;
 4746            }
 4747        }
 4748
 4749        self.transact(cx, |this, cx| {
 4750            let buffer = this.buffer.update(cx, |buffer, cx| {
 4751                buffer.edit(edits, None, cx);
 4752                buffer.snapshot(cx)
 4753            });
 4754
 4755            // Recalculate offsets on newly edited buffer
 4756            let new_selections = new_selections
 4757                .iter()
 4758                .map(|s| {
 4759                    let start_point = Point::new(s.start, 0);
 4760                    let end_point = Point::new(s.end, buffer.line_len(s.end));
 4761                    Selection {
 4762                        id: s.id,
 4763                        start: buffer.point_to_offset(start_point),
 4764                        end: buffer.point_to_offset(end_point),
 4765                        goal: s.goal,
 4766                        reversed: s.reversed,
 4767                    }
 4768                })
 4769                .collect();
 4770
 4771            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 4772                s.select(new_selections);
 4773            });
 4774
 4775            this.request_autoscroll(Autoscroll::fit(), cx);
 4776        });
 4777    }
 4778
 4779    pub fn convert_to_upper_case(&mut self, _: &ConvertToUpperCase, cx: &mut ViewContext<Self>) {
 4780        self.manipulate_text(cx, |text| text.to_uppercase())
 4781    }
 4782
 4783    pub fn convert_to_lower_case(&mut self, _: &ConvertToLowerCase, cx: &mut ViewContext<Self>) {
 4784        self.manipulate_text(cx, |text| text.to_lowercase())
 4785    }
 4786
 4787    pub fn convert_to_title_case(&mut self, _: &ConvertToTitleCase, cx: &mut ViewContext<Self>) {
 4788        self.manipulate_text(cx, |text| {
 4789            // Hack to get around the fact that to_case crate doesn't support '\n' as a word boundary
 4790            // https://github.com/rutrum/convert-case/issues/16
 4791            text.split("\n")
 4792                .map(|line| line.to_case(Case::Title))
 4793                .join("\n")
 4794        })
 4795    }
 4796
 4797    pub fn convert_to_snake_case(&mut self, _: &ConvertToSnakeCase, cx: &mut ViewContext<Self>) {
 4798        self.manipulate_text(cx, |text| text.to_case(Case::Snake))
 4799    }
 4800
 4801    pub fn convert_to_kebab_case(&mut self, _: &ConvertToKebabCase, cx: &mut ViewContext<Self>) {
 4802        self.manipulate_text(cx, |text| text.to_case(Case::Kebab))
 4803    }
 4804
 4805    pub fn convert_to_upper_camel_case(
 4806        &mut self,
 4807        _: &ConvertToUpperCamelCase,
 4808        cx: &mut ViewContext<Self>,
 4809    ) {
 4810        self.manipulate_text(cx, |text| {
 4811            // Hack to get around the fact that to_case crate doesn't support '\n' as a word boundary
 4812            // https://github.com/rutrum/convert-case/issues/16
 4813            text.split("\n")
 4814                .map(|line| line.to_case(Case::UpperCamel))
 4815                .join("\n")
 4816        })
 4817    }
 4818
 4819    pub fn convert_to_lower_camel_case(
 4820        &mut self,
 4821        _: &ConvertToLowerCamelCase,
 4822        cx: &mut ViewContext<Self>,
 4823    ) {
 4824        self.manipulate_text(cx, |text| text.to_case(Case::Camel))
 4825    }
 4826
 4827    fn manipulate_text<Fn>(&mut self, cx: &mut ViewContext<Self>, mut callback: Fn)
 4828    where
 4829        Fn: FnMut(&str) -> String,
 4830    {
 4831        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 4832        let buffer = self.buffer.read(cx).snapshot(cx);
 4833
 4834        let mut new_selections = Vec::new();
 4835        let mut edits = Vec::new();
 4836        let mut selection_adjustment = 0i32;
 4837
 4838        for selection in self.selections.all::<usize>(cx) {
 4839            let selection_is_empty = selection.is_empty();
 4840
 4841            let (start, end) = if selection_is_empty {
 4842                let word_range = movement::surrounding_word(
 4843                    &display_map,
 4844                    selection.start.to_display_point(&display_map),
 4845                );
 4846                let start = word_range.start.to_offset(&display_map, Bias::Left);
 4847                let end = word_range.end.to_offset(&display_map, Bias::Left);
 4848                (start, end)
 4849            } else {
 4850                (selection.start, selection.end)
 4851            };
 4852
 4853            let text = buffer.text_for_range(start..end).collect::<String>();
 4854            let old_length = text.len() as i32;
 4855            let text = callback(&text);
 4856
 4857            new_selections.push(Selection {
 4858                start: (start as i32 - selection_adjustment) as usize,
 4859                end: ((start + text.len()) as i32 - selection_adjustment) as usize,
 4860                goal: SelectionGoal::None,
 4861                ..selection
 4862            });
 4863
 4864            selection_adjustment += old_length - text.len() as i32;
 4865
 4866            edits.push((start..end, text));
 4867        }
 4868
 4869        self.transact(cx, |this, cx| {
 4870            this.buffer.update(cx, |buffer, cx| {
 4871                buffer.edit(edits, None, cx);
 4872            });
 4873
 4874            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 4875                s.select(new_selections);
 4876            });
 4877
 4878            this.request_autoscroll(Autoscroll::fit(), cx);
 4879        });
 4880    }
 4881
 4882    pub fn duplicate_line(&mut self, _: &DuplicateLine, cx: &mut ViewContext<Self>) {
 4883        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 4884        let buffer = &display_map.buffer_snapshot;
 4885        let selections = self.selections.all::<Point>(cx);
 4886
 4887        let mut edits = Vec::new();
 4888        let mut selections_iter = selections.iter().peekable();
 4889        while let Some(selection) = selections_iter.next() {
 4890            // Avoid duplicating the same lines twice.
 4891            let mut rows = selection.spanned_rows(false, &display_map);
 4892
 4893            while let Some(next_selection) = selections_iter.peek() {
 4894                let next_rows = next_selection.spanned_rows(false, &display_map);
 4895                if next_rows.start < rows.end {
 4896                    rows.end = next_rows.end;
 4897                    selections_iter.next().unwrap();
 4898                } else {
 4899                    break;
 4900                }
 4901            }
 4902
 4903            // Copy the text from the selected row region and splice it at the start of the region.
 4904            let start = Point::new(rows.start, 0);
 4905            let end = Point::new(rows.end - 1, buffer.line_len(rows.end - 1));
 4906            let text = buffer
 4907                .text_for_range(start..end)
 4908                .chain(Some("\n"))
 4909                .collect::<String>();
 4910            edits.push((start..start, text));
 4911        }
 4912
 4913        self.transact(cx, |this, cx| {
 4914            this.buffer.update(cx, |buffer, cx| {
 4915                buffer.edit(edits, None, cx);
 4916            });
 4917
 4918            this.request_autoscroll(Autoscroll::fit(), cx);
 4919        });
 4920    }
 4921
 4922    pub fn move_line_up(&mut self, _: &MoveLineUp, cx: &mut ViewContext<Self>) {
 4923        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 4924        let buffer = self.buffer.read(cx).snapshot(cx);
 4925
 4926        let mut edits = Vec::new();
 4927        let mut unfold_ranges = Vec::new();
 4928        let mut refold_ranges = Vec::new();
 4929
 4930        let selections = self.selections.all::<Point>(cx);
 4931        let mut selections = selections.iter().peekable();
 4932        let mut contiguous_row_selections = Vec::new();
 4933        let mut new_selections = Vec::new();
 4934
 4935        while let Some(selection) = selections.next() {
 4936            // Find all the selections that span a contiguous row range
 4937            let (start_row, end_row) = consume_contiguous_rows(
 4938                &mut contiguous_row_selections,
 4939                selection,
 4940                &display_map,
 4941                &mut selections,
 4942            );
 4943
 4944            // Move the text spanned by the row range to be before the line preceding the row range
 4945            if start_row > 0 {
 4946                let range_to_move = Point::new(start_row - 1, buffer.line_len(start_row - 1))
 4947                    ..Point::new(end_row - 1, buffer.line_len(end_row - 1));
 4948                let insertion_point = display_map
 4949                    .prev_line_boundary(Point::new(start_row - 1, 0))
 4950                    .0;
 4951
 4952                // Don't move lines across excerpts
 4953                if buffer
 4954                    .excerpt_boundaries_in_range((
 4955                        Bound::Excluded(insertion_point),
 4956                        Bound::Included(range_to_move.end),
 4957                    ))
 4958                    .next()
 4959                    .is_none()
 4960                {
 4961                    let text = buffer
 4962                        .text_for_range(range_to_move.clone())
 4963                        .flat_map(|s| s.chars())
 4964                        .skip(1)
 4965                        .chain(['\n'])
 4966                        .collect::<String>();
 4967
 4968                    edits.push((
 4969                        buffer.anchor_after(range_to_move.start)
 4970                            ..buffer.anchor_before(range_to_move.end),
 4971                        String::new(),
 4972                    ));
 4973                    let insertion_anchor = buffer.anchor_after(insertion_point);
 4974                    edits.push((insertion_anchor..insertion_anchor, text));
 4975
 4976                    let row_delta = range_to_move.start.row - insertion_point.row + 1;
 4977
 4978                    // Move selections up
 4979                    new_selections.extend(contiguous_row_selections.drain(..).map(
 4980                        |mut selection| {
 4981                            selection.start.row -= row_delta;
 4982                            selection.end.row -= row_delta;
 4983                            selection
 4984                        },
 4985                    ));
 4986
 4987                    // Move folds up
 4988                    unfold_ranges.push(range_to_move.clone());
 4989                    for fold in display_map.folds_in_range(
 4990                        buffer.anchor_before(range_to_move.start)
 4991                            ..buffer.anchor_after(range_to_move.end),
 4992                    ) {
 4993                        let mut start = fold.range.start.to_point(&buffer);
 4994                        let mut end = fold.range.end.to_point(&buffer);
 4995                        start.row -= row_delta;
 4996                        end.row -= row_delta;
 4997                        refold_ranges.push(start..end);
 4998                    }
 4999                }
 5000            }
 5001
 5002            // If we didn't move line(s), preserve the existing selections
 5003            new_selections.append(&mut contiguous_row_selections);
 5004        }
 5005
 5006        self.transact(cx, |this, cx| {
 5007            this.unfold_ranges(unfold_ranges, true, true, cx);
 5008            this.buffer.update(cx, |buffer, cx| {
 5009                for (range, text) in edits {
 5010                    buffer.edit([(range, text)], None, cx);
 5011                }
 5012            });
 5013            this.fold_ranges(refold_ranges, true, cx);
 5014            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5015                s.select(new_selections);
 5016            })
 5017        });
 5018    }
 5019
 5020    pub fn move_line_down(&mut self, _: &MoveLineDown, cx: &mut ViewContext<Self>) {
 5021        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 5022        let buffer = self.buffer.read(cx).snapshot(cx);
 5023
 5024        let mut edits = Vec::new();
 5025        let mut unfold_ranges = Vec::new();
 5026        let mut refold_ranges = Vec::new();
 5027
 5028        let selections = self.selections.all::<Point>(cx);
 5029        let mut selections = selections.iter().peekable();
 5030        let mut contiguous_row_selections = Vec::new();
 5031        let mut new_selections = Vec::new();
 5032
 5033        while let Some(selection) = selections.next() {
 5034            // Find all the selections that span a contiguous row range
 5035            let (start_row, end_row) = consume_contiguous_rows(
 5036                &mut contiguous_row_selections,
 5037                selection,
 5038                &display_map,
 5039                &mut selections,
 5040            );
 5041
 5042            // Move the text spanned by the row range to be after the last line of the row range
 5043            if end_row <= buffer.max_point().row {
 5044                let range_to_move = Point::new(start_row, 0)..Point::new(end_row, 0);
 5045                let insertion_point = display_map.next_line_boundary(Point::new(end_row, 0)).0;
 5046
 5047                // Don't move lines across excerpt boundaries
 5048                if buffer
 5049                    .excerpt_boundaries_in_range((
 5050                        Bound::Excluded(range_to_move.start),
 5051                        Bound::Included(insertion_point),
 5052                    ))
 5053                    .next()
 5054                    .is_none()
 5055                {
 5056                    let mut text = String::from("\n");
 5057                    text.extend(buffer.text_for_range(range_to_move.clone()));
 5058                    text.pop(); // Drop trailing newline
 5059                    edits.push((
 5060                        buffer.anchor_after(range_to_move.start)
 5061                            ..buffer.anchor_before(range_to_move.end),
 5062                        String::new(),
 5063                    ));
 5064                    let insertion_anchor = buffer.anchor_after(insertion_point);
 5065                    edits.push((insertion_anchor..insertion_anchor, text));
 5066
 5067                    let row_delta = insertion_point.row - range_to_move.end.row + 1;
 5068
 5069                    // Move selections down
 5070                    new_selections.extend(contiguous_row_selections.drain(..).map(
 5071                        |mut selection| {
 5072                            selection.start.row += row_delta;
 5073                            selection.end.row += row_delta;
 5074                            selection
 5075                        },
 5076                    ));
 5077
 5078                    // Move folds down
 5079                    unfold_ranges.push(range_to_move.clone());
 5080                    for fold in display_map.folds_in_range(
 5081                        buffer.anchor_before(range_to_move.start)
 5082                            ..buffer.anchor_after(range_to_move.end),
 5083                    ) {
 5084                        let mut start = fold.range.start.to_point(&buffer);
 5085                        let mut end = fold.range.end.to_point(&buffer);
 5086                        start.row += row_delta;
 5087                        end.row += row_delta;
 5088                        refold_ranges.push(start..end);
 5089                    }
 5090                }
 5091            }
 5092
 5093            // If we didn't move line(s), preserve the existing selections
 5094            new_selections.append(&mut contiguous_row_selections);
 5095        }
 5096
 5097        self.transact(cx, |this, cx| {
 5098            this.unfold_ranges(unfold_ranges, true, true, cx);
 5099            this.buffer.update(cx, |buffer, cx| {
 5100                for (range, text) in edits {
 5101                    buffer.edit([(range, text)], None, cx);
 5102                }
 5103            });
 5104            this.fold_ranges(refold_ranges, true, cx);
 5105            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(new_selections));
 5106        });
 5107    }
 5108
 5109    pub fn transpose(&mut self, _: &Transpose, cx: &mut ViewContext<Self>) {
 5110        let text_layout_details = &self.text_layout_details(cx);
 5111        self.transact(cx, |this, cx| {
 5112            let edits = this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5113                let mut edits: Vec<(Range<usize>, String)> = Default::default();
 5114                let line_mode = s.line_mode;
 5115                s.move_with(|display_map, selection| {
 5116                    if !selection.is_empty() || line_mode {
 5117                        return;
 5118                    }
 5119
 5120                    let mut head = selection.head();
 5121                    let mut transpose_offset = head.to_offset(display_map, Bias::Right);
 5122                    if head.column() == display_map.line_len(head.row()) {
 5123                        transpose_offset = display_map
 5124                            .buffer_snapshot
 5125                            .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
 5126                    }
 5127
 5128                    if transpose_offset == 0 {
 5129                        return;
 5130                    }
 5131
 5132                    *head.column_mut() += 1;
 5133                    head = display_map.clip_point(head, Bias::Right);
 5134                    let goal = SelectionGoal::HorizontalPosition(
 5135                        display_map
 5136                            .x_for_display_point(head, &text_layout_details)
 5137                            .into(),
 5138                    );
 5139                    selection.collapse_to(head, goal);
 5140
 5141                    let transpose_start = display_map
 5142                        .buffer_snapshot
 5143                        .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
 5144                    if edits.last().map_or(true, |e| e.0.end <= transpose_start) {
 5145                        let transpose_end = display_map
 5146                            .buffer_snapshot
 5147                            .clip_offset(transpose_offset + 1, Bias::Right);
 5148                        if let Some(ch) =
 5149                            display_map.buffer_snapshot.chars_at(transpose_start).next()
 5150                        {
 5151                            edits.push((transpose_start..transpose_offset, String::new()));
 5152                            edits.push((transpose_end..transpose_end, ch.to_string()));
 5153                        }
 5154                    }
 5155                });
 5156                edits
 5157            });
 5158            this.buffer
 5159                .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
 5160            let selections = this.selections.all::<usize>(cx);
 5161            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5162                s.select(selections);
 5163            });
 5164        });
 5165    }
 5166
 5167    pub fn cut(&mut self, _: &Cut, cx: &mut ViewContext<Self>) {
 5168        let mut text = String::new();
 5169        let buffer = self.buffer.read(cx).snapshot(cx);
 5170        let mut selections = self.selections.all::<Point>(cx);
 5171        let mut clipboard_selections = Vec::with_capacity(selections.len());
 5172        {
 5173            let max_point = buffer.max_point();
 5174            let mut is_first = true;
 5175            for selection in &mut selections {
 5176                let is_entire_line = selection.is_empty() || self.selections.line_mode;
 5177                if is_entire_line {
 5178                    selection.start = Point::new(selection.start.row, 0);
 5179                    selection.end = cmp::min(max_point, Point::new(selection.end.row + 1, 0));
 5180                    selection.goal = SelectionGoal::None;
 5181                }
 5182                if is_first {
 5183                    is_first = false;
 5184                } else {
 5185                    text += "\n";
 5186                }
 5187                let mut len = 0;
 5188                for chunk in buffer.text_for_range(selection.start..selection.end) {
 5189                    text.push_str(chunk);
 5190                    len += chunk.len();
 5191                }
 5192                clipboard_selections.push(ClipboardSelection {
 5193                    len,
 5194                    is_entire_line,
 5195                    first_line_indent: buffer.indent_size_for_line(selection.start.row).len,
 5196                });
 5197            }
 5198        }
 5199
 5200        self.transact(cx, |this, cx| {
 5201            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5202                s.select(selections);
 5203            });
 5204            this.insert("", cx);
 5205            cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
 5206        });
 5207    }
 5208
 5209    pub fn copy(&mut self, _: &Copy, cx: &mut ViewContext<Self>) {
 5210        let selections = self.selections.all::<Point>(cx);
 5211        let buffer = self.buffer.read(cx).read(cx);
 5212        let mut text = String::new();
 5213
 5214        let mut clipboard_selections = Vec::with_capacity(selections.len());
 5215        {
 5216            let max_point = buffer.max_point();
 5217            let mut is_first = true;
 5218            for selection in selections.iter() {
 5219                let mut start = selection.start;
 5220                let mut end = selection.end;
 5221                let is_entire_line = selection.is_empty() || self.selections.line_mode;
 5222                if is_entire_line {
 5223                    start = Point::new(start.row, 0);
 5224                    end = cmp::min(max_point, Point::new(end.row + 1, 0));
 5225                }
 5226                if is_first {
 5227                    is_first = false;
 5228                } else {
 5229                    text += "\n";
 5230                }
 5231                let mut len = 0;
 5232                for chunk in buffer.text_for_range(start..end) {
 5233                    text.push_str(chunk);
 5234                    len += chunk.len();
 5235                }
 5236                clipboard_selections.push(ClipboardSelection {
 5237                    len,
 5238                    is_entire_line,
 5239                    first_line_indent: buffer.indent_size_for_line(start.row).len,
 5240                });
 5241            }
 5242        }
 5243
 5244        cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
 5245    }
 5246
 5247    pub fn paste(&mut self, _: &Paste, cx: &mut ViewContext<Self>) {
 5248        if self.read_only(cx) {
 5249            return;
 5250        }
 5251
 5252        self.transact(cx, |this, cx| {
 5253            if let Some(item) = cx.read_from_clipboard() {
 5254                let clipboard_text = Cow::Borrowed(item.text());
 5255                if let Some(mut clipboard_selections) = item.metadata::<Vec<ClipboardSelection>>() {
 5256                    let old_selections = this.selections.all::<usize>(cx);
 5257                    let all_selections_were_entire_line =
 5258                        clipboard_selections.iter().all(|s| s.is_entire_line);
 5259                    let first_selection_indent_column =
 5260                        clipboard_selections.first().map(|s| s.first_line_indent);
 5261                    if clipboard_selections.len() != old_selections.len() {
 5262                        clipboard_selections.drain(..);
 5263                    }
 5264
 5265                    this.buffer.update(cx, |buffer, cx| {
 5266                        let snapshot = buffer.read(cx);
 5267                        let mut start_offset = 0;
 5268                        let mut edits = Vec::new();
 5269                        let mut original_indent_columns = Vec::new();
 5270                        let line_mode = this.selections.line_mode;
 5271                        for (ix, selection) in old_selections.iter().enumerate() {
 5272                            let to_insert;
 5273                            let entire_line;
 5274                            let original_indent_column;
 5275                            if let Some(clipboard_selection) = clipboard_selections.get(ix) {
 5276                                let end_offset = start_offset + clipboard_selection.len;
 5277                                to_insert = &clipboard_text[start_offset..end_offset];
 5278                                entire_line = clipboard_selection.is_entire_line;
 5279                                start_offset = end_offset + 1;
 5280                                original_indent_column =
 5281                                    Some(clipboard_selection.first_line_indent);
 5282                            } else {
 5283                                to_insert = clipboard_text.as_str();
 5284                                entire_line = all_selections_were_entire_line;
 5285                                original_indent_column = first_selection_indent_column
 5286                            }
 5287
 5288                            // If the corresponding selection was empty when this slice of the
 5289                            // clipboard text was written, then the entire line containing the
 5290                            // selection was copied. If this selection is also currently empty,
 5291                            // then paste the line before the current line of the buffer.
 5292                            let range = if selection.is_empty() && !line_mode && entire_line {
 5293                                let column = selection.start.to_point(&snapshot).column as usize;
 5294                                let line_start = selection.start - column;
 5295                                line_start..line_start
 5296                            } else {
 5297                                selection.range()
 5298                            };
 5299
 5300                            edits.push((range, to_insert));
 5301                            original_indent_columns.extend(original_indent_column);
 5302                        }
 5303                        drop(snapshot);
 5304
 5305                        buffer.edit(
 5306                            edits,
 5307                            Some(AutoindentMode::Block {
 5308                                original_indent_columns,
 5309                            }),
 5310                            cx,
 5311                        );
 5312                    });
 5313
 5314                    let selections = this.selections.all::<usize>(cx);
 5315                    this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
 5316                } else {
 5317                    this.insert(&clipboard_text, cx);
 5318                }
 5319            }
 5320        });
 5321    }
 5322
 5323    pub fn undo(&mut self, _: &Undo, cx: &mut ViewContext<Self>) {
 5324        if self.read_only(cx) {
 5325            return;
 5326        }
 5327
 5328        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.undo(cx)) {
 5329            if let Some((selections, _)) = self.selection_history.transaction(tx_id).cloned() {
 5330                self.change_selections(None, cx, |s| {
 5331                    s.select_anchors(selections.to_vec());
 5332                });
 5333            }
 5334            self.request_autoscroll(Autoscroll::fit(), cx);
 5335            self.unmark_text(cx);
 5336            self.refresh_copilot_suggestions(true, cx);
 5337            cx.emit(EditorEvent::Edited);
 5338        }
 5339    }
 5340
 5341    pub fn redo(&mut self, _: &Redo, cx: &mut ViewContext<Self>) {
 5342        if self.read_only(cx) {
 5343            return;
 5344        }
 5345
 5346        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.redo(cx)) {
 5347            if let Some((_, Some(selections))) = self.selection_history.transaction(tx_id).cloned()
 5348            {
 5349                self.change_selections(None, cx, |s| {
 5350                    s.select_anchors(selections.to_vec());
 5351                });
 5352            }
 5353            self.request_autoscroll(Autoscroll::fit(), cx);
 5354            self.unmark_text(cx);
 5355            self.refresh_copilot_suggestions(true, cx);
 5356            cx.emit(EditorEvent::Edited);
 5357        }
 5358    }
 5359
 5360    pub fn finalize_last_transaction(&mut self, cx: &mut ViewContext<Self>) {
 5361        self.buffer
 5362            .update(cx, |buffer, cx| buffer.finalize_last_transaction(cx));
 5363    }
 5364
 5365    pub fn move_left(&mut self, _: &MoveLeft, cx: &mut ViewContext<Self>) {
 5366        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5367            let line_mode = s.line_mode;
 5368            s.move_with(|map, selection| {
 5369                let cursor = if selection.is_empty() && !line_mode {
 5370                    movement::left(map, selection.start)
 5371                } else {
 5372                    selection.start
 5373                };
 5374                selection.collapse_to(cursor, SelectionGoal::None);
 5375            });
 5376        })
 5377    }
 5378
 5379    pub fn select_left(&mut self, _: &SelectLeft, cx: &mut ViewContext<Self>) {
 5380        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5381            s.move_heads_with(|map, head, _| (movement::left(map, head), SelectionGoal::None));
 5382        })
 5383    }
 5384
 5385    pub fn move_right(&mut self, _: &MoveRight, cx: &mut ViewContext<Self>) {
 5386        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5387            let line_mode = s.line_mode;
 5388            s.move_with(|map, selection| {
 5389                let cursor = if selection.is_empty() && !line_mode {
 5390                    movement::right(map, selection.end)
 5391                } else {
 5392                    selection.end
 5393                };
 5394                selection.collapse_to(cursor, SelectionGoal::None)
 5395            });
 5396        })
 5397    }
 5398
 5399    pub fn select_right(&mut self, _: &SelectRight, cx: &mut ViewContext<Self>) {
 5400        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5401            s.move_heads_with(|map, head, _| (movement::right(map, head), SelectionGoal::None));
 5402        })
 5403    }
 5404
 5405    pub fn move_up(&mut self, _: &MoveUp, cx: &mut ViewContext<Self>) {
 5406        if self.take_rename(true, cx).is_some() {
 5407            return;
 5408        }
 5409
 5410        if matches!(self.mode, EditorMode::SingleLine) {
 5411            cx.propagate();
 5412            return;
 5413        }
 5414
 5415        let text_layout_details = &self.text_layout_details(cx);
 5416
 5417        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5418            let line_mode = s.line_mode;
 5419            s.move_with(|map, selection| {
 5420                if !selection.is_empty() && !line_mode {
 5421                    selection.goal = SelectionGoal::None;
 5422                }
 5423                let (cursor, goal) = movement::up(
 5424                    map,
 5425                    selection.start,
 5426                    selection.goal,
 5427                    false,
 5428                    &text_layout_details,
 5429                );
 5430                selection.collapse_to(cursor, goal);
 5431            });
 5432        })
 5433    }
 5434
 5435    pub fn move_up_by_lines(&mut self, action: &MoveUpByLines, cx: &mut ViewContext<Self>) {
 5436        if self.take_rename(true, cx).is_some() {
 5437            return;
 5438        }
 5439
 5440        if matches!(self.mode, EditorMode::SingleLine) {
 5441            cx.propagate();
 5442            return;
 5443        }
 5444
 5445        let text_layout_details = &self.text_layout_details(cx);
 5446
 5447        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5448            let line_mode = s.line_mode;
 5449            s.move_with(|map, selection| {
 5450                if !selection.is_empty() && !line_mode {
 5451                    selection.goal = SelectionGoal::None;
 5452                }
 5453                let (cursor, goal) = movement::up_by_rows(
 5454                    map,
 5455                    selection.start,
 5456                    action.lines,
 5457                    selection.goal,
 5458                    false,
 5459                    &text_layout_details,
 5460                );
 5461                selection.collapse_to(cursor, goal);
 5462            });
 5463        })
 5464    }
 5465
 5466    pub fn move_down_by_lines(&mut self, action: &MoveDownByLines, cx: &mut ViewContext<Self>) {
 5467        if self.take_rename(true, cx).is_some() {
 5468            return;
 5469        }
 5470
 5471        if matches!(self.mode, EditorMode::SingleLine) {
 5472            cx.propagate();
 5473            return;
 5474        }
 5475
 5476        let text_layout_details = &self.text_layout_details(cx);
 5477
 5478        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5479            let line_mode = s.line_mode;
 5480            s.move_with(|map, selection| {
 5481                if !selection.is_empty() && !line_mode {
 5482                    selection.goal = SelectionGoal::None;
 5483                }
 5484                let (cursor, goal) = movement::down_by_rows(
 5485                    map,
 5486                    selection.start,
 5487                    action.lines,
 5488                    selection.goal,
 5489                    false,
 5490                    &text_layout_details,
 5491                );
 5492                selection.collapse_to(cursor, goal);
 5493            });
 5494        })
 5495    }
 5496
 5497    pub fn select_down_by_lines(&mut self, action: &SelectDownByLines, cx: &mut ViewContext<Self>) {
 5498        let text_layout_details = &self.text_layout_details(cx);
 5499        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5500            s.move_heads_with(|map, head, goal| {
 5501                movement::down_by_rows(map, head, action.lines, goal, false, &text_layout_details)
 5502            })
 5503        })
 5504    }
 5505
 5506    pub fn select_up_by_lines(&mut self, action: &SelectUpByLines, cx: &mut ViewContext<Self>) {
 5507        let text_layout_details = &self.text_layout_details(cx);
 5508        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5509            s.move_heads_with(|map, head, goal| {
 5510                movement::up_by_rows(map, head, action.lines, goal, false, &text_layout_details)
 5511            })
 5512        })
 5513    }
 5514
 5515    pub fn move_page_up(&mut self, action: &MovePageUp, cx: &mut ViewContext<Self>) {
 5516        if self.take_rename(true, cx).is_some() {
 5517            return;
 5518        }
 5519
 5520        if matches!(self.mode, EditorMode::SingleLine) {
 5521            cx.propagate();
 5522            return;
 5523        }
 5524
 5525        let row_count = if let Some(row_count) = self.visible_line_count() {
 5526            row_count as u32 - 1
 5527        } else {
 5528            return;
 5529        };
 5530
 5531        let autoscroll = if action.center_cursor {
 5532            Autoscroll::center()
 5533        } else {
 5534            Autoscroll::fit()
 5535        };
 5536
 5537        let text_layout_details = &self.text_layout_details(cx);
 5538
 5539        self.change_selections(Some(autoscroll), cx, |s| {
 5540            let line_mode = s.line_mode;
 5541            s.move_with(|map, selection| {
 5542                if !selection.is_empty() && !line_mode {
 5543                    selection.goal = SelectionGoal::None;
 5544                }
 5545                let (cursor, goal) = movement::up_by_rows(
 5546                    map,
 5547                    selection.end,
 5548                    row_count,
 5549                    selection.goal,
 5550                    false,
 5551                    &text_layout_details,
 5552                );
 5553                selection.collapse_to(cursor, goal);
 5554            });
 5555        });
 5556    }
 5557
 5558    pub fn select_up(&mut self, _: &SelectUp, cx: &mut ViewContext<Self>) {
 5559        let text_layout_details = &self.text_layout_details(cx);
 5560        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5561            s.move_heads_with(|map, head, goal| {
 5562                movement::up(map, head, goal, false, &text_layout_details)
 5563            })
 5564        })
 5565    }
 5566
 5567    pub fn move_down(&mut self, _: &MoveDown, cx: &mut ViewContext<Self>) {
 5568        self.take_rename(true, cx);
 5569
 5570        if self.mode == EditorMode::SingleLine {
 5571            cx.propagate();
 5572            return;
 5573        }
 5574
 5575        let text_layout_details = &self.text_layout_details(cx);
 5576        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5577            let line_mode = s.line_mode;
 5578            s.move_with(|map, selection| {
 5579                if !selection.is_empty() && !line_mode {
 5580                    selection.goal = SelectionGoal::None;
 5581                }
 5582                let (cursor, goal) = movement::down(
 5583                    map,
 5584                    selection.end,
 5585                    selection.goal,
 5586                    false,
 5587                    &text_layout_details,
 5588                );
 5589                selection.collapse_to(cursor, goal);
 5590            });
 5591        });
 5592    }
 5593
 5594    pub fn move_page_down(&mut self, action: &MovePageDown, cx: &mut ViewContext<Self>) {
 5595        if self.take_rename(true, cx).is_some() {
 5596            return;
 5597        }
 5598
 5599        if self
 5600            .context_menu
 5601            .write()
 5602            .as_mut()
 5603            .map(|menu| menu.select_last(self.project.as_ref(), cx))
 5604            .unwrap_or(false)
 5605        {
 5606            return;
 5607        }
 5608
 5609        if matches!(self.mode, EditorMode::SingleLine) {
 5610            cx.propagate();
 5611            return;
 5612        }
 5613
 5614        let row_count = if let Some(row_count) = self.visible_line_count() {
 5615            row_count as u32 - 1
 5616        } else {
 5617            return;
 5618        };
 5619
 5620        let autoscroll = if action.center_cursor {
 5621            Autoscroll::center()
 5622        } else {
 5623            Autoscroll::fit()
 5624        };
 5625
 5626        let text_layout_details = &self.text_layout_details(cx);
 5627        self.change_selections(Some(autoscroll), cx, |s| {
 5628            let line_mode = s.line_mode;
 5629            s.move_with(|map, selection| {
 5630                if !selection.is_empty() && !line_mode {
 5631                    selection.goal = SelectionGoal::None;
 5632                }
 5633                let (cursor, goal) = movement::down_by_rows(
 5634                    map,
 5635                    selection.end,
 5636                    row_count,
 5637                    selection.goal,
 5638                    false,
 5639                    &text_layout_details,
 5640                );
 5641                selection.collapse_to(cursor, goal);
 5642            });
 5643        });
 5644    }
 5645
 5646    pub fn select_down(&mut self, _: &SelectDown, cx: &mut ViewContext<Self>) {
 5647        let text_layout_details = &self.text_layout_details(cx);
 5648        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5649            s.move_heads_with(|map, head, goal| {
 5650                movement::down(map, head, goal, false, &text_layout_details)
 5651            })
 5652        });
 5653    }
 5654
 5655    pub fn context_menu_first(&mut self, _: &ContextMenuFirst, cx: &mut ViewContext<Self>) {
 5656        if let Some(context_menu) = self.context_menu.write().as_mut() {
 5657            context_menu.select_first(self.project.as_ref(), cx);
 5658        }
 5659    }
 5660
 5661    pub fn context_menu_prev(&mut self, _: &ContextMenuPrev, cx: &mut ViewContext<Self>) {
 5662        if let Some(context_menu) = self.context_menu.write().as_mut() {
 5663            context_menu.select_prev(self.project.as_ref(), cx);
 5664        }
 5665    }
 5666
 5667    pub fn context_menu_next(&mut self, _: &ContextMenuNext, cx: &mut ViewContext<Self>) {
 5668        if let Some(context_menu) = self.context_menu.write().as_mut() {
 5669            context_menu.select_next(self.project.as_ref(), cx);
 5670        }
 5671    }
 5672
 5673    pub fn context_menu_last(&mut self, _: &ContextMenuLast, cx: &mut ViewContext<Self>) {
 5674        if let Some(context_menu) = self.context_menu.write().as_mut() {
 5675            context_menu.select_last(self.project.as_ref(), cx);
 5676        }
 5677    }
 5678
 5679    pub fn move_to_previous_word_start(
 5680        &mut self,
 5681        _: &MoveToPreviousWordStart,
 5682        cx: &mut ViewContext<Self>,
 5683    ) {
 5684        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5685            s.move_cursors_with(|map, head, _| {
 5686                (
 5687                    movement::previous_word_start(map, head),
 5688                    SelectionGoal::None,
 5689                )
 5690            });
 5691        })
 5692    }
 5693
 5694    pub fn move_to_previous_subword_start(
 5695        &mut self,
 5696        _: &MoveToPreviousSubwordStart,
 5697        cx: &mut ViewContext<Self>,
 5698    ) {
 5699        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5700            s.move_cursors_with(|map, head, _| {
 5701                (
 5702                    movement::previous_subword_start(map, head),
 5703                    SelectionGoal::None,
 5704                )
 5705            });
 5706        })
 5707    }
 5708
 5709    pub fn select_to_previous_word_start(
 5710        &mut self,
 5711        _: &SelectToPreviousWordStart,
 5712        cx: &mut ViewContext<Self>,
 5713    ) {
 5714        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5715            s.move_heads_with(|map, head, _| {
 5716                (
 5717                    movement::previous_word_start(map, head),
 5718                    SelectionGoal::None,
 5719                )
 5720            });
 5721        })
 5722    }
 5723
 5724    pub fn select_to_previous_subword_start(
 5725        &mut self,
 5726        _: &SelectToPreviousSubwordStart,
 5727        cx: &mut ViewContext<Self>,
 5728    ) {
 5729        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5730            s.move_heads_with(|map, head, _| {
 5731                (
 5732                    movement::previous_subword_start(map, head),
 5733                    SelectionGoal::None,
 5734                )
 5735            });
 5736        })
 5737    }
 5738
 5739    pub fn delete_to_previous_word_start(
 5740        &mut self,
 5741        _: &DeleteToPreviousWordStart,
 5742        cx: &mut ViewContext<Self>,
 5743    ) {
 5744        self.transact(cx, |this, cx| {
 5745            this.select_autoclose_pair(cx);
 5746            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5747                let line_mode = s.line_mode;
 5748                s.move_with(|map, selection| {
 5749                    if selection.is_empty() && !line_mode {
 5750                        let cursor = movement::previous_word_start(map, selection.head());
 5751                        selection.set_head(cursor, SelectionGoal::None);
 5752                    }
 5753                });
 5754            });
 5755            this.insert("", cx);
 5756        });
 5757    }
 5758
 5759    pub fn delete_to_previous_subword_start(
 5760        &mut self,
 5761        _: &DeleteToPreviousSubwordStart,
 5762        cx: &mut ViewContext<Self>,
 5763    ) {
 5764        self.transact(cx, |this, cx| {
 5765            this.select_autoclose_pair(cx);
 5766            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5767                let line_mode = s.line_mode;
 5768                s.move_with(|map, selection| {
 5769                    if selection.is_empty() && !line_mode {
 5770                        let cursor = movement::previous_subword_start(map, selection.head());
 5771                        selection.set_head(cursor, SelectionGoal::None);
 5772                    }
 5773                });
 5774            });
 5775            this.insert("", cx);
 5776        });
 5777    }
 5778
 5779    pub fn move_to_next_word_end(&mut self, _: &MoveToNextWordEnd, cx: &mut ViewContext<Self>) {
 5780        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5781            s.move_cursors_with(|map, head, _| {
 5782                (movement::next_word_end(map, head), SelectionGoal::None)
 5783            });
 5784        })
 5785    }
 5786
 5787    pub fn move_to_next_subword_end(
 5788        &mut self,
 5789        _: &MoveToNextSubwordEnd,
 5790        cx: &mut ViewContext<Self>,
 5791    ) {
 5792        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5793            s.move_cursors_with(|map, head, _| {
 5794                (movement::next_subword_end(map, head), SelectionGoal::None)
 5795            });
 5796        })
 5797    }
 5798
 5799    pub fn select_to_next_word_end(&mut self, _: &SelectToNextWordEnd, cx: &mut ViewContext<Self>) {
 5800        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5801            s.move_heads_with(|map, head, _| {
 5802                (movement::next_word_end(map, head), SelectionGoal::None)
 5803            });
 5804        })
 5805    }
 5806
 5807    pub fn select_to_next_subword_end(
 5808        &mut self,
 5809        _: &SelectToNextSubwordEnd,
 5810        cx: &mut ViewContext<Self>,
 5811    ) {
 5812        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5813            s.move_heads_with(|map, head, _| {
 5814                (movement::next_subword_end(map, head), SelectionGoal::None)
 5815            });
 5816        })
 5817    }
 5818
 5819    pub fn delete_to_next_word_end(&mut self, _: &DeleteToNextWordEnd, cx: &mut ViewContext<Self>) {
 5820        self.transact(cx, |this, cx| {
 5821            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5822                let line_mode = s.line_mode;
 5823                s.move_with(|map, selection| {
 5824                    if selection.is_empty() && !line_mode {
 5825                        let cursor = movement::next_word_end(map, selection.head());
 5826                        selection.set_head(cursor, SelectionGoal::None);
 5827                    }
 5828                });
 5829            });
 5830            this.insert("", cx);
 5831        });
 5832    }
 5833
 5834    pub fn delete_to_next_subword_end(
 5835        &mut self,
 5836        _: &DeleteToNextSubwordEnd,
 5837        cx: &mut ViewContext<Self>,
 5838    ) {
 5839        self.transact(cx, |this, cx| {
 5840            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5841                s.move_with(|map, selection| {
 5842                    if selection.is_empty() {
 5843                        let cursor = movement::next_subword_end(map, selection.head());
 5844                        selection.set_head(cursor, SelectionGoal::None);
 5845                    }
 5846                });
 5847            });
 5848            this.insert("", cx);
 5849        });
 5850    }
 5851
 5852    pub fn move_to_beginning_of_line(
 5853        &mut self,
 5854        _: &MoveToBeginningOfLine,
 5855        cx: &mut ViewContext<Self>,
 5856    ) {
 5857        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5858            s.move_cursors_with(|map, head, _| {
 5859                (
 5860                    movement::indented_line_beginning(map, head, true),
 5861                    SelectionGoal::None,
 5862                )
 5863            });
 5864        })
 5865    }
 5866
 5867    pub fn select_to_beginning_of_line(
 5868        &mut self,
 5869        action: &SelectToBeginningOfLine,
 5870        cx: &mut ViewContext<Self>,
 5871    ) {
 5872        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5873            s.move_heads_with(|map, head, _| {
 5874                (
 5875                    movement::indented_line_beginning(map, head, action.stop_at_soft_wraps),
 5876                    SelectionGoal::None,
 5877                )
 5878            });
 5879        });
 5880    }
 5881
 5882    pub fn delete_to_beginning_of_line(
 5883        &mut self,
 5884        _: &DeleteToBeginningOfLine,
 5885        cx: &mut ViewContext<Self>,
 5886    ) {
 5887        self.transact(cx, |this, cx| {
 5888            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5889                s.move_with(|_, selection| {
 5890                    selection.reversed = true;
 5891                });
 5892            });
 5893
 5894            this.select_to_beginning_of_line(
 5895                &SelectToBeginningOfLine {
 5896                    stop_at_soft_wraps: false,
 5897                },
 5898                cx,
 5899            );
 5900            this.backspace(&Backspace, cx);
 5901        });
 5902    }
 5903
 5904    pub fn move_to_end_of_line(&mut self, _: &MoveToEndOfLine, cx: &mut ViewContext<Self>) {
 5905        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5906            s.move_cursors_with(|map, head, _| {
 5907                (movement::line_end(map, head, true), SelectionGoal::None)
 5908            });
 5909        })
 5910    }
 5911
 5912    pub fn select_to_end_of_line(
 5913        &mut self,
 5914        action: &SelectToEndOfLine,
 5915        cx: &mut ViewContext<Self>,
 5916    ) {
 5917        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5918            s.move_heads_with(|map, head, _| {
 5919                (
 5920                    movement::line_end(map, head, action.stop_at_soft_wraps),
 5921                    SelectionGoal::None,
 5922                )
 5923            });
 5924        })
 5925    }
 5926
 5927    pub fn delete_to_end_of_line(&mut self, _: &DeleteToEndOfLine, cx: &mut ViewContext<Self>) {
 5928        self.transact(cx, |this, cx| {
 5929            this.select_to_end_of_line(
 5930                &SelectToEndOfLine {
 5931                    stop_at_soft_wraps: false,
 5932                },
 5933                cx,
 5934            );
 5935            this.delete(&Delete, cx);
 5936        });
 5937    }
 5938
 5939    pub fn cut_to_end_of_line(&mut self, _: &CutToEndOfLine, cx: &mut ViewContext<Self>) {
 5940        self.transact(cx, |this, cx| {
 5941            this.select_to_end_of_line(
 5942                &SelectToEndOfLine {
 5943                    stop_at_soft_wraps: false,
 5944                },
 5945                cx,
 5946            );
 5947            this.cut(&Cut, cx);
 5948        });
 5949    }
 5950
 5951    pub fn move_to_start_of_paragraph(
 5952        &mut self,
 5953        _: &MoveToStartOfParagraph,
 5954        cx: &mut ViewContext<Self>,
 5955    ) {
 5956        if matches!(self.mode, EditorMode::SingleLine) {
 5957            cx.propagate();
 5958            return;
 5959        }
 5960
 5961        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5962            s.move_with(|map, selection| {
 5963                selection.collapse_to(
 5964                    movement::start_of_paragraph(map, selection.head(), 1),
 5965                    SelectionGoal::None,
 5966                )
 5967            });
 5968        })
 5969    }
 5970
 5971    pub fn move_to_end_of_paragraph(
 5972        &mut self,
 5973        _: &MoveToEndOfParagraph,
 5974        cx: &mut ViewContext<Self>,
 5975    ) {
 5976        if matches!(self.mode, EditorMode::SingleLine) {
 5977            cx.propagate();
 5978            return;
 5979        }
 5980
 5981        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5982            s.move_with(|map, selection| {
 5983                selection.collapse_to(
 5984                    movement::end_of_paragraph(map, selection.head(), 1),
 5985                    SelectionGoal::None,
 5986                )
 5987            });
 5988        })
 5989    }
 5990
 5991    pub fn select_to_start_of_paragraph(
 5992        &mut self,
 5993        _: &SelectToStartOfParagraph,
 5994        cx: &mut ViewContext<Self>,
 5995    ) {
 5996        if matches!(self.mode, EditorMode::SingleLine) {
 5997            cx.propagate();
 5998            return;
 5999        }
 6000
 6001        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6002            s.move_heads_with(|map, head, _| {
 6003                (
 6004                    movement::start_of_paragraph(map, head, 1),
 6005                    SelectionGoal::None,
 6006                )
 6007            });
 6008        })
 6009    }
 6010
 6011    pub fn select_to_end_of_paragraph(
 6012        &mut self,
 6013        _: &SelectToEndOfParagraph,
 6014        cx: &mut ViewContext<Self>,
 6015    ) {
 6016        if matches!(self.mode, EditorMode::SingleLine) {
 6017            cx.propagate();
 6018            return;
 6019        }
 6020
 6021        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6022            s.move_heads_with(|map, head, _| {
 6023                (
 6024                    movement::end_of_paragraph(map, head, 1),
 6025                    SelectionGoal::None,
 6026                )
 6027            });
 6028        })
 6029    }
 6030
 6031    pub fn move_to_beginning(&mut self, _: &MoveToBeginning, cx: &mut ViewContext<Self>) {
 6032        if matches!(self.mode, EditorMode::SingleLine) {
 6033            cx.propagate();
 6034            return;
 6035        }
 6036
 6037        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6038            s.select_ranges(vec![0..0]);
 6039        });
 6040    }
 6041
 6042    pub fn select_to_beginning(&mut self, _: &SelectToBeginning, cx: &mut ViewContext<Self>) {
 6043        let mut selection = self.selections.last::<Point>(cx);
 6044        selection.set_head(Point::zero(), SelectionGoal::None);
 6045
 6046        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6047            s.select(vec![selection]);
 6048        });
 6049    }
 6050
 6051    pub fn move_to_end(&mut self, _: &MoveToEnd, cx: &mut ViewContext<Self>) {
 6052        if matches!(self.mode, EditorMode::SingleLine) {
 6053            cx.propagate();
 6054            return;
 6055        }
 6056
 6057        let cursor = self.buffer.read(cx).read(cx).len();
 6058        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6059            s.select_ranges(vec![cursor..cursor])
 6060        });
 6061    }
 6062
 6063    pub fn set_nav_history(&mut self, nav_history: Option<ItemNavHistory>) {
 6064        self.nav_history = nav_history;
 6065    }
 6066
 6067    pub fn nav_history(&self) -> Option<&ItemNavHistory> {
 6068        self.nav_history.as_ref()
 6069    }
 6070
 6071    fn push_to_nav_history(
 6072        &mut self,
 6073        cursor_anchor: Anchor,
 6074        new_position: Option<Point>,
 6075        cx: &mut ViewContext<Self>,
 6076    ) {
 6077        if let Some(nav_history) = self.nav_history.as_mut() {
 6078            let buffer = self.buffer.read(cx).read(cx);
 6079            let cursor_position = cursor_anchor.to_point(&buffer);
 6080            let scroll_state = self.scroll_manager.anchor();
 6081            let scroll_top_row = scroll_state.top_row(&buffer);
 6082            drop(buffer);
 6083
 6084            if let Some(new_position) = new_position {
 6085                let row_delta = (new_position.row as i64 - cursor_position.row as i64).abs();
 6086                if row_delta < MIN_NAVIGATION_HISTORY_ROW_DELTA {
 6087                    return;
 6088                }
 6089            }
 6090
 6091            nav_history.push(
 6092                Some(NavigationData {
 6093                    cursor_anchor,
 6094                    cursor_position,
 6095                    scroll_anchor: scroll_state,
 6096                    scroll_top_row,
 6097                }),
 6098                cx,
 6099            );
 6100        }
 6101    }
 6102
 6103    pub fn select_to_end(&mut self, _: &SelectToEnd, cx: &mut ViewContext<Self>) {
 6104        let buffer = self.buffer.read(cx).snapshot(cx);
 6105        let mut selection = self.selections.first::<usize>(cx);
 6106        selection.set_head(buffer.len(), SelectionGoal::None);
 6107        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6108            s.select(vec![selection]);
 6109        });
 6110    }
 6111
 6112    pub fn select_all(&mut self, _: &SelectAll, cx: &mut ViewContext<Self>) {
 6113        let end = self.buffer.read(cx).read(cx).len();
 6114        self.change_selections(None, cx, |s| {
 6115            s.select_ranges(vec![0..end]);
 6116        });
 6117    }
 6118
 6119    pub fn select_line(&mut self, _: &SelectLine, cx: &mut ViewContext<Self>) {
 6120        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 6121        let mut selections = self.selections.all::<Point>(cx);
 6122        let max_point = display_map.buffer_snapshot.max_point();
 6123        for selection in &mut selections {
 6124            let rows = selection.spanned_rows(true, &display_map);
 6125            selection.start = Point::new(rows.start, 0);
 6126            selection.end = cmp::min(max_point, Point::new(rows.end, 0));
 6127            selection.reversed = false;
 6128        }
 6129        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6130            s.select(selections);
 6131        });
 6132    }
 6133
 6134    pub fn split_selection_into_lines(
 6135        &mut self,
 6136        _: &SplitSelectionIntoLines,
 6137        cx: &mut ViewContext<Self>,
 6138    ) {
 6139        let mut to_unfold = Vec::new();
 6140        let mut new_selection_ranges = Vec::new();
 6141        {
 6142            let selections = self.selections.all::<Point>(cx);
 6143            let buffer = self.buffer.read(cx).read(cx);
 6144            for selection in selections {
 6145                for row in selection.start.row..selection.end.row {
 6146                    let cursor = Point::new(row, buffer.line_len(row));
 6147                    new_selection_ranges.push(cursor..cursor);
 6148                }
 6149                new_selection_ranges.push(selection.end..selection.end);
 6150                to_unfold.push(selection.start..selection.end);
 6151            }
 6152        }
 6153        self.unfold_ranges(to_unfold, true, true, cx);
 6154        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6155            s.select_ranges(new_selection_ranges);
 6156        });
 6157    }
 6158
 6159    pub fn add_selection_above(&mut self, _: &AddSelectionAbove, cx: &mut ViewContext<Self>) {
 6160        self.add_selection(true, cx);
 6161    }
 6162
 6163    pub fn add_selection_below(&mut self, _: &AddSelectionBelow, cx: &mut ViewContext<Self>) {
 6164        self.add_selection(false, cx);
 6165    }
 6166
 6167    fn add_selection(&mut self, above: bool, cx: &mut ViewContext<Self>) {
 6168        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 6169        let mut selections = self.selections.all::<Point>(cx);
 6170        let text_layout_details = self.text_layout_details(cx);
 6171        let mut state = self.add_selections_state.take().unwrap_or_else(|| {
 6172            let oldest_selection = selections.iter().min_by_key(|s| s.id).unwrap().clone();
 6173            let range = oldest_selection.display_range(&display_map).sorted();
 6174
 6175            let start_x = display_map.x_for_display_point(range.start, &text_layout_details);
 6176            let end_x = display_map.x_for_display_point(range.end, &text_layout_details);
 6177            let positions = start_x.min(end_x)..start_x.max(end_x);
 6178
 6179            selections.clear();
 6180            let mut stack = Vec::new();
 6181            for row in range.start.row()..=range.end.row() {
 6182                if let Some(selection) = self.selections.build_columnar_selection(
 6183                    &display_map,
 6184                    row,
 6185                    &positions,
 6186                    oldest_selection.reversed,
 6187                    &text_layout_details,
 6188                ) {
 6189                    stack.push(selection.id);
 6190                    selections.push(selection);
 6191                }
 6192            }
 6193
 6194            if above {
 6195                stack.reverse();
 6196            }
 6197
 6198            AddSelectionsState { above, stack }
 6199        });
 6200
 6201        let last_added_selection = *state.stack.last().unwrap();
 6202        let mut new_selections = Vec::new();
 6203        if above == state.above {
 6204            let end_row = if above {
 6205                0
 6206            } else {
 6207                display_map.max_point().row()
 6208            };
 6209
 6210            'outer: for selection in selections {
 6211                if selection.id == last_added_selection {
 6212                    let range = selection.display_range(&display_map).sorted();
 6213                    debug_assert_eq!(range.start.row(), range.end.row());
 6214                    let mut row = range.start.row();
 6215                    let positions =
 6216                        if let SelectionGoal::HorizontalRange { start, end } = selection.goal {
 6217                            px(start)..px(end)
 6218                        } else {
 6219                            let start_x =
 6220                                display_map.x_for_display_point(range.start, &text_layout_details);
 6221                            let end_x =
 6222                                display_map.x_for_display_point(range.end, &text_layout_details);
 6223                            start_x.min(end_x)..start_x.max(end_x)
 6224                        };
 6225
 6226                    while row != end_row {
 6227                        if above {
 6228                            row -= 1;
 6229                        } else {
 6230                            row += 1;
 6231                        }
 6232
 6233                        if let Some(new_selection) = self.selections.build_columnar_selection(
 6234                            &display_map,
 6235                            row,
 6236                            &positions,
 6237                            selection.reversed,
 6238                            &text_layout_details,
 6239                        ) {
 6240                            state.stack.push(new_selection.id);
 6241                            if above {
 6242                                new_selections.push(new_selection);
 6243                                new_selections.push(selection);
 6244                            } else {
 6245                                new_selections.push(selection);
 6246                                new_selections.push(new_selection);
 6247                            }
 6248
 6249                            continue 'outer;
 6250                        }
 6251                    }
 6252                }
 6253
 6254                new_selections.push(selection);
 6255            }
 6256        } else {
 6257            new_selections = selections;
 6258            new_selections.retain(|s| s.id != last_added_selection);
 6259            state.stack.pop();
 6260        }
 6261
 6262        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6263            s.select(new_selections);
 6264        });
 6265        if state.stack.len() > 1 {
 6266            self.add_selections_state = Some(state);
 6267        }
 6268    }
 6269
 6270    pub fn select_next_match_internal(
 6271        &mut self,
 6272        display_map: &DisplaySnapshot,
 6273        replace_newest: bool,
 6274        autoscroll: Option<Autoscroll>,
 6275        cx: &mut ViewContext<Self>,
 6276    ) -> Result<()> {
 6277        fn select_next_match_ranges(
 6278            this: &mut Editor,
 6279            range: Range<usize>,
 6280            replace_newest: bool,
 6281            auto_scroll: Option<Autoscroll>,
 6282            cx: &mut ViewContext<Editor>,
 6283        ) {
 6284            this.unfold_ranges([range.clone()], false, true, cx);
 6285            this.change_selections(auto_scroll, cx, |s| {
 6286                if replace_newest {
 6287                    s.delete(s.newest_anchor().id);
 6288                }
 6289                s.insert_range(range.clone());
 6290            });
 6291        }
 6292
 6293        let buffer = &display_map.buffer_snapshot;
 6294        let mut selections = self.selections.all::<usize>(cx);
 6295        if let Some(mut select_next_state) = self.select_next_state.take() {
 6296            let query = &select_next_state.query;
 6297            if !select_next_state.done {
 6298                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
 6299                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
 6300                let mut next_selected_range = None;
 6301
 6302                let bytes_after_last_selection =
 6303                    buffer.bytes_in_range(last_selection.end..buffer.len());
 6304                let bytes_before_first_selection = buffer.bytes_in_range(0..first_selection.start);
 6305                let query_matches = query
 6306                    .stream_find_iter(bytes_after_last_selection)
 6307                    .map(|result| (last_selection.end, result))
 6308                    .chain(
 6309                        query
 6310                            .stream_find_iter(bytes_before_first_selection)
 6311                            .map(|result| (0, result)),
 6312                    );
 6313
 6314                for (start_offset, query_match) in query_matches {
 6315                    let query_match = query_match.unwrap(); // can only fail due to I/O
 6316                    let offset_range =
 6317                        start_offset + query_match.start()..start_offset + query_match.end();
 6318                    let display_range = offset_range.start.to_display_point(&display_map)
 6319                        ..offset_range.end.to_display_point(&display_map);
 6320
 6321                    if !select_next_state.wordwise
 6322                        || (!movement::is_inside_word(&display_map, display_range.start)
 6323                            && !movement::is_inside_word(&display_map, display_range.end))
 6324                    {
 6325                        // TODO: This is n^2, because we might check all the selections
 6326                        if selections
 6327                            .iter()
 6328                            .find(|selection| selection.range().overlaps(&offset_range))
 6329                            .is_none()
 6330                        {
 6331                            next_selected_range = Some(offset_range);
 6332                            break;
 6333                        }
 6334                    }
 6335                }
 6336
 6337                if let Some(next_selected_range) = next_selected_range {
 6338                    select_next_match_ranges(
 6339                        self,
 6340                        next_selected_range,
 6341                        replace_newest,
 6342                        autoscroll,
 6343                        cx,
 6344                    );
 6345                } else {
 6346                    select_next_state.done = true;
 6347                }
 6348            }
 6349
 6350            self.select_next_state = Some(select_next_state);
 6351        } else {
 6352            let mut only_carets = true;
 6353            let mut same_text_selected = true;
 6354            let mut selected_text = None;
 6355
 6356            let mut selections_iter = selections.iter().peekable();
 6357            while let Some(selection) = selections_iter.next() {
 6358                if selection.start != selection.end {
 6359                    only_carets = false;
 6360                }
 6361
 6362                if same_text_selected {
 6363                    if selected_text.is_none() {
 6364                        selected_text =
 6365                            Some(buffer.text_for_range(selection.range()).collect::<String>());
 6366                    }
 6367
 6368                    if let Some(next_selection) = selections_iter.peek() {
 6369                        if next_selection.range().len() == selection.range().len() {
 6370                            let next_selected_text = buffer
 6371                                .text_for_range(next_selection.range())
 6372                                .collect::<String>();
 6373                            if Some(next_selected_text) != selected_text {
 6374                                same_text_selected = false;
 6375                                selected_text = None;
 6376                            }
 6377                        } else {
 6378                            same_text_selected = false;
 6379                            selected_text = None;
 6380                        }
 6381                    }
 6382                }
 6383            }
 6384
 6385            if only_carets {
 6386                for selection in &mut selections {
 6387                    let word_range = movement::surrounding_word(
 6388                        &display_map,
 6389                        selection.start.to_display_point(&display_map),
 6390                    );
 6391                    selection.start = word_range.start.to_offset(&display_map, Bias::Left);
 6392                    selection.end = word_range.end.to_offset(&display_map, Bias::Left);
 6393                    selection.goal = SelectionGoal::None;
 6394                    selection.reversed = false;
 6395                    select_next_match_ranges(
 6396                        self,
 6397                        selection.start..selection.end,
 6398                        replace_newest,
 6399                        autoscroll,
 6400                        cx,
 6401                    );
 6402                }
 6403
 6404                if selections.len() == 1 {
 6405                    let selection = selections
 6406                        .last()
 6407                        .expect("ensured that there's only one selection");
 6408                    let query = buffer
 6409                        .text_for_range(selection.start..selection.end)
 6410                        .collect::<String>();
 6411                    let is_empty = query.is_empty();
 6412                    let select_state = SelectNextState {
 6413                        query: AhoCorasick::new(&[query])?,
 6414                        wordwise: true,
 6415                        done: is_empty,
 6416                    };
 6417                    self.select_next_state = Some(select_state);
 6418                } else {
 6419                    self.select_next_state = None;
 6420                }
 6421            } else if let Some(selected_text) = selected_text {
 6422                self.select_next_state = Some(SelectNextState {
 6423                    query: AhoCorasick::new(&[selected_text])?,
 6424                    wordwise: false,
 6425                    done: false,
 6426                });
 6427                self.select_next_match_internal(display_map, replace_newest, autoscroll, cx)?;
 6428            }
 6429        }
 6430        Ok(())
 6431    }
 6432
 6433    pub fn select_all_matches(
 6434        &mut self,
 6435        _action: &SelectAllMatches,
 6436        cx: &mut ViewContext<Self>,
 6437    ) -> Result<()> {
 6438        self.push_to_selection_history();
 6439        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 6440
 6441        self.select_next_match_internal(&display_map, false, None, cx)?;
 6442        let Some(select_next_state) = self.select_next_state.as_mut() else {
 6443            return Ok(());
 6444        };
 6445        if select_next_state.done {
 6446            return Ok(());
 6447        }
 6448
 6449        let mut new_selections = self.selections.all::<usize>(cx);
 6450
 6451        let buffer = &display_map.buffer_snapshot;
 6452        let query_matches = select_next_state
 6453            .query
 6454            .stream_find_iter(buffer.bytes_in_range(0..buffer.len()));
 6455
 6456        for query_match in query_matches {
 6457            let query_match = query_match.unwrap(); // can only fail due to I/O
 6458            let offset_range = query_match.start()..query_match.end();
 6459            let display_range = offset_range.start.to_display_point(&display_map)
 6460                ..offset_range.end.to_display_point(&display_map);
 6461
 6462            if !select_next_state.wordwise
 6463                || (!movement::is_inside_word(&display_map, display_range.start)
 6464                    && !movement::is_inside_word(&display_map, display_range.end))
 6465            {
 6466                self.selections.change_with(cx, |selections| {
 6467                    new_selections.push(Selection {
 6468                        id: selections.new_selection_id(),
 6469                        start: offset_range.start,
 6470                        end: offset_range.end,
 6471                        reversed: false,
 6472                        goal: SelectionGoal::None,
 6473                    });
 6474                });
 6475            }
 6476        }
 6477
 6478        new_selections.sort_by_key(|selection| selection.start);
 6479        let mut ix = 0;
 6480        while ix + 1 < new_selections.len() {
 6481            let current_selection = &new_selections[ix];
 6482            let next_selection = &new_selections[ix + 1];
 6483            if current_selection.range().overlaps(&next_selection.range()) {
 6484                if current_selection.id < next_selection.id {
 6485                    new_selections.remove(ix + 1);
 6486                } else {
 6487                    new_selections.remove(ix);
 6488                }
 6489            } else {
 6490                ix += 1;
 6491            }
 6492        }
 6493
 6494        select_next_state.done = true;
 6495        self.unfold_ranges(
 6496            new_selections.iter().map(|selection| selection.range()),
 6497            false,
 6498            false,
 6499            cx,
 6500        );
 6501        self.change_selections(Some(Autoscroll::fit()), cx, |selections| {
 6502            selections.select(new_selections)
 6503        });
 6504
 6505        Ok(())
 6506    }
 6507
 6508    pub fn select_next(&mut self, action: &SelectNext, cx: &mut ViewContext<Self>) -> Result<()> {
 6509        self.push_to_selection_history();
 6510        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 6511        self.select_next_match_internal(
 6512            &display_map,
 6513            action.replace_newest,
 6514            Some(Autoscroll::newest()),
 6515            cx,
 6516        )?;
 6517        Ok(())
 6518    }
 6519
 6520    pub fn select_previous(
 6521        &mut self,
 6522        action: &SelectPrevious,
 6523        cx: &mut ViewContext<Self>,
 6524    ) -> Result<()> {
 6525        self.push_to_selection_history();
 6526        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 6527        let buffer = &display_map.buffer_snapshot;
 6528        let mut selections = self.selections.all::<usize>(cx);
 6529        if let Some(mut select_prev_state) = self.select_prev_state.take() {
 6530            let query = &select_prev_state.query;
 6531            if !select_prev_state.done {
 6532                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
 6533                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
 6534                let mut next_selected_range = None;
 6535                // When we're iterating matches backwards, the oldest match will actually be the furthest one in the buffer.
 6536                let bytes_before_last_selection =
 6537                    buffer.reversed_bytes_in_range(0..last_selection.start);
 6538                let bytes_after_first_selection =
 6539                    buffer.reversed_bytes_in_range(first_selection.end..buffer.len());
 6540                let query_matches = query
 6541                    .stream_find_iter(bytes_before_last_selection)
 6542                    .map(|result| (last_selection.start, result))
 6543                    .chain(
 6544                        query
 6545                            .stream_find_iter(bytes_after_first_selection)
 6546                            .map(|result| (buffer.len(), result)),
 6547                    );
 6548                for (end_offset, query_match) in query_matches {
 6549                    let query_match = query_match.unwrap(); // can only fail due to I/O
 6550                    let offset_range =
 6551                        end_offset - query_match.end()..end_offset - query_match.start();
 6552                    let display_range = offset_range.start.to_display_point(&display_map)
 6553                        ..offset_range.end.to_display_point(&display_map);
 6554
 6555                    if !select_prev_state.wordwise
 6556                        || (!movement::is_inside_word(&display_map, display_range.start)
 6557                            && !movement::is_inside_word(&display_map, display_range.end))
 6558                    {
 6559                        next_selected_range = Some(offset_range);
 6560                        break;
 6561                    }
 6562                }
 6563
 6564                if let Some(next_selected_range) = next_selected_range {
 6565                    self.unfold_ranges([next_selected_range.clone()], false, true, cx);
 6566                    self.change_selections(Some(Autoscroll::newest()), cx, |s| {
 6567                        if action.replace_newest {
 6568                            s.delete(s.newest_anchor().id);
 6569                        }
 6570                        s.insert_range(next_selected_range);
 6571                    });
 6572                } else {
 6573                    select_prev_state.done = true;
 6574                }
 6575            }
 6576
 6577            self.select_prev_state = Some(select_prev_state);
 6578        } else {
 6579            let mut only_carets = true;
 6580            let mut same_text_selected = true;
 6581            let mut selected_text = None;
 6582
 6583            let mut selections_iter = selections.iter().peekable();
 6584            while let Some(selection) = selections_iter.next() {
 6585                if selection.start != selection.end {
 6586                    only_carets = false;
 6587                }
 6588
 6589                if same_text_selected {
 6590                    if selected_text.is_none() {
 6591                        selected_text =
 6592                            Some(buffer.text_for_range(selection.range()).collect::<String>());
 6593                    }
 6594
 6595                    if let Some(next_selection) = selections_iter.peek() {
 6596                        if next_selection.range().len() == selection.range().len() {
 6597                            let next_selected_text = buffer
 6598                                .text_for_range(next_selection.range())
 6599                                .collect::<String>();
 6600                            if Some(next_selected_text) != selected_text {
 6601                                same_text_selected = false;
 6602                                selected_text = None;
 6603                            }
 6604                        } else {
 6605                            same_text_selected = false;
 6606                            selected_text = None;
 6607                        }
 6608                    }
 6609                }
 6610            }
 6611
 6612            if only_carets {
 6613                for selection in &mut selections {
 6614                    let word_range = movement::surrounding_word(
 6615                        &display_map,
 6616                        selection.start.to_display_point(&display_map),
 6617                    );
 6618                    selection.start = word_range.start.to_offset(&display_map, Bias::Left);
 6619                    selection.end = word_range.end.to_offset(&display_map, Bias::Left);
 6620                    selection.goal = SelectionGoal::None;
 6621                    selection.reversed = false;
 6622                }
 6623                if selections.len() == 1 {
 6624                    let selection = selections
 6625                        .last()
 6626                        .expect("ensured that there's only one selection");
 6627                    let query = buffer
 6628                        .text_for_range(selection.start..selection.end)
 6629                        .collect::<String>();
 6630                    let is_empty = query.is_empty();
 6631                    let select_state = SelectNextState {
 6632                        query: AhoCorasick::new(&[query.chars().rev().collect::<String>()])?,
 6633                        wordwise: true,
 6634                        done: is_empty,
 6635                    };
 6636                    self.select_prev_state = Some(select_state);
 6637                } else {
 6638                    self.select_prev_state = None;
 6639                }
 6640
 6641                self.unfold_ranges(
 6642                    selections.iter().map(|s| s.range()).collect::<Vec<_>>(),
 6643                    false,
 6644                    true,
 6645                    cx,
 6646                );
 6647                self.change_selections(Some(Autoscroll::newest()), cx, |s| {
 6648                    s.select(selections);
 6649                });
 6650            } else if let Some(selected_text) = selected_text {
 6651                self.select_prev_state = Some(SelectNextState {
 6652                    query: AhoCorasick::new(&[selected_text.chars().rev().collect::<String>()])?,
 6653                    wordwise: false,
 6654                    done: false,
 6655                });
 6656                self.select_previous(action, cx)?;
 6657            }
 6658        }
 6659        Ok(())
 6660    }
 6661
 6662    pub fn toggle_comments(&mut self, action: &ToggleComments, cx: &mut ViewContext<Self>) {
 6663        let text_layout_details = &self.text_layout_details(cx);
 6664        self.transact(cx, |this, cx| {
 6665            let mut selections = this.selections.all::<Point>(cx);
 6666            let mut edits = Vec::new();
 6667            let mut selection_edit_ranges = Vec::new();
 6668            let mut last_toggled_row = None;
 6669            let snapshot = this.buffer.read(cx).read(cx);
 6670            let empty_str: Arc<str> = "".into();
 6671            let mut suffixes_inserted = Vec::new();
 6672
 6673            fn comment_prefix_range(
 6674                snapshot: &MultiBufferSnapshot,
 6675                row: u32,
 6676                comment_prefix: &str,
 6677                comment_prefix_whitespace: &str,
 6678            ) -> Range<Point> {
 6679                let start = Point::new(row, snapshot.indent_size_for_line(row).len);
 6680
 6681                let mut line_bytes = snapshot
 6682                    .bytes_in_range(start..snapshot.max_point())
 6683                    .flatten()
 6684                    .copied();
 6685
 6686                // If this line currently begins with the line comment prefix, then record
 6687                // the range containing the prefix.
 6688                if line_bytes
 6689                    .by_ref()
 6690                    .take(comment_prefix.len())
 6691                    .eq(comment_prefix.bytes())
 6692                {
 6693                    // Include any whitespace that matches the comment prefix.
 6694                    let matching_whitespace_len = line_bytes
 6695                        .zip(comment_prefix_whitespace.bytes())
 6696                        .take_while(|(a, b)| a == b)
 6697                        .count() as u32;
 6698                    let end = Point::new(
 6699                        start.row,
 6700                        start.column + comment_prefix.len() as u32 + matching_whitespace_len,
 6701                    );
 6702                    start..end
 6703                } else {
 6704                    start..start
 6705                }
 6706            }
 6707
 6708            fn comment_suffix_range(
 6709                snapshot: &MultiBufferSnapshot,
 6710                row: u32,
 6711                comment_suffix: &str,
 6712                comment_suffix_has_leading_space: bool,
 6713            ) -> Range<Point> {
 6714                let end = Point::new(row, snapshot.line_len(row));
 6715                let suffix_start_column = end.column.saturating_sub(comment_suffix.len() as u32);
 6716
 6717                let mut line_end_bytes = snapshot
 6718                    .bytes_in_range(Point::new(end.row, suffix_start_column.saturating_sub(1))..end)
 6719                    .flatten()
 6720                    .copied();
 6721
 6722                let leading_space_len = if suffix_start_column > 0
 6723                    && line_end_bytes.next() == Some(b' ')
 6724                    && comment_suffix_has_leading_space
 6725                {
 6726                    1
 6727                } else {
 6728                    0
 6729                };
 6730
 6731                // If this line currently begins with the line comment prefix, then record
 6732                // the range containing the prefix.
 6733                if line_end_bytes.by_ref().eq(comment_suffix.bytes()) {
 6734                    let start = Point::new(end.row, suffix_start_column - leading_space_len);
 6735                    start..end
 6736                } else {
 6737                    end..end
 6738                }
 6739            }
 6740
 6741            // TODO: Handle selections that cross excerpts
 6742            for selection in &mut selections {
 6743                let start_column = snapshot.indent_size_for_line(selection.start.row).len;
 6744                let language = if let Some(language) =
 6745                    snapshot.language_scope_at(Point::new(selection.start.row, start_column))
 6746                {
 6747                    language
 6748                } else {
 6749                    continue;
 6750                };
 6751
 6752                selection_edit_ranges.clear();
 6753
 6754                // If multiple selections contain a given row, avoid processing that
 6755                // row more than once.
 6756                let mut start_row = selection.start.row;
 6757                if last_toggled_row == Some(start_row) {
 6758                    start_row += 1;
 6759                }
 6760                let end_row =
 6761                    if selection.end.row > selection.start.row && selection.end.column == 0 {
 6762                        selection.end.row - 1
 6763                    } else {
 6764                        selection.end.row
 6765                    };
 6766                last_toggled_row = Some(end_row);
 6767
 6768                if start_row > end_row {
 6769                    continue;
 6770                }
 6771
 6772                // If the language has line comments, toggle those.
 6773                if let Some(full_comment_prefix) = language
 6774                    .line_comment_prefixes()
 6775                    .and_then(|prefixes| prefixes.first())
 6776                {
 6777                    // Split the comment prefix's trailing whitespace into a separate string,
 6778                    // as that portion won't be used for detecting if a line is a comment.
 6779                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
 6780                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
 6781                    let mut all_selection_lines_are_comments = true;
 6782
 6783                    for row in start_row..=end_row {
 6784                        if start_row < end_row && snapshot.is_line_blank(row) {
 6785                            continue;
 6786                        }
 6787
 6788                        let prefix_range = comment_prefix_range(
 6789                            snapshot.deref(),
 6790                            row,
 6791                            comment_prefix,
 6792                            comment_prefix_whitespace,
 6793                        );
 6794                        if prefix_range.is_empty() {
 6795                            all_selection_lines_are_comments = false;
 6796                        }
 6797                        selection_edit_ranges.push(prefix_range);
 6798                    }
 6799
 6800                    if all_selection_lines_are_comments {
 6801                        edits.extend(
 6802                            selection_edit_ranges
 6803                                .iter()
 6804                                .cloned()
 6805                                .map(|range| (range, empty_str.clone())),
 6806                        );
 6807                    } else {
 6808                        let min_column = selection_edit_ranges
 6809                            .iter()
 6810                            .map(|r| r.start.column)
 6811                            .min()
 6812                            .unwrap_or(0);
 6813                        edits.extend(selection_edit_ranges.iter().map(|range| {
 6814                            let position = Point::new(range.start.row, min_column);
 6815                            (position..position, full_comment_prefix.clone())
 6816                        }));
 6817                    }
 6818                } else if let Some((full_comment_prefix, comment_suffix)) =
 6819                    language.block_comment_delimiters()
 6820                {
 6821                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
 6822                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
 6823                    let prefix_range = comment_prefix_range(
 6824                        snapshot.deref(),
 6825                        start_row,
 6826                        comment_prefix,
 6827                        comment_prefix_whitespace,
 6828                    );
 6829                    let suffix_range = comment_suffix_range(
 6830                        snapshot.deref(),
 6831                        end_row,
 6832                        comment_suffix.trim_start_matches(' '),
 6833                        comment_suffix.starts_with(' '),
 6834                    );
 6835
 6836                    if prefix_range.is_empty() || suffix_range.is_empty() {
 6837                        edits.push((
 6838                            prefix_range.start..prefix_range.start,
 6839                            full_comment_prefix.clone(),
 6840                        ));
 6841                        edits.push((suffix_range.end..suffix_range.end, comment_suffix.clone()));
 6842                        suffixes_inserted.push((end_row, comment_suffix.len()));
 6843                    } else {
 6844                        edits.push((prefix_range, empty_str.clone()));
 6845                        edits.push((suffix_range, empty_str.clone()));
 6846                    }
 6847                } else {
 6848                    continue;
 6849                }
 6850            }
 6851
 6852            drop(snapshot);
 6853            this.buffer.update(cx, |buffer, cx| {
 6854                buffer.edit(edits, None, cx);
 6855            });
 6856
 6857            // Adjust selections so that they end before any comment suffixes that
 6858            // were inserted.
 6859            let mut suffixes_inserted = suffixes_inserted.into_iter().peekable();
 6860            let mut selections = this.selections.all::<Point>(cx);
 6861            let snapshot = this.buffer.read(cx).read(cx);
 6862            for selection in &mut selections {
 6863                while let Some((row, suffix_len)) = suffixes_inserted.peek().copied() {
 6864                    match row.cmp(&selection.end.row) {
 6865                        Ordering::Less => {
 6866                            suffixes_inserted.next();
 6867                            continue;
 6868                        }
 6869                        Ordering::Greater => break,
 6870                        Ordering::Equal => {
 6871                            if selection.end.column == snapshot.line_len(row) {
 6872                                if selection.is_empty() {
 6873                                    selection.start.column -= suffix_len as u32;
 6874                                }
 6875                                selection.end.column -= suffix_len as u32;
 6876                            }
 6877                            break;
 6878                        }
 6879                    }
 6880                }
 6881            }
 6882
 6883            drop(snapshot);
 6884            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
 6885
 6886            let selections = this.selections.all::<Point>(cx);
 6887            let selections_on_single_row = selections.windows(2).all(|selections| {
 6888                selections[0].start.row == selections[1].start.row
 6889                    && selections[0].end.row == selections[1].end.row
 6890                    && selections[0].start.row == selections[0].end.row
 6891            });
 6892            let selections_selecting = selections
 6893                .iter()
 6894                .any(|selection| selection.start != selection.end);
 6895            let advance_downwards = action.advance_downwards
 6896                && selections_on_single_row
 6897                && !selections_selecting
 6898                && this.mode != EditorMode::SingleLine;
 6899
 6900            if advance_downwards {
 6901                let snapshot = this.buffer.read(cx).snapshot(cx);
 6902
 6903                this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6904                    s.move_cursors_with(|display_snapshot, display_point, _| {
 6905                        let mut point = display_point.to_point(display_snapshot);
 6906                        point.row += 1;
 6907                        point = snapshot.clip_point(point, Bias::Left);
 6908                        let display_point = point.to_display_point(display_snapshot);
 6909                        let goal = SelectionGoal::HorizontalPosition(
 6910                            display_snapshot
 6911                                .x_for_display_point(display_point, &text_layout_details)
 6912                                .into(),
 6913                        );
 6914                        (display_point, goal)
 6915                    })
 6916                });
 6917            }
 6918        });
 6919    }
 6920
 6921    pub fn select_larger_syntax_node(
 6922        &mut self,
 6923        _: &SelectLargerSyntaxNode,
 6924        cx: &mut ViewContext<Self>,
 6925    ) {
 6926        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 6927        let buffer = self.buffer.read(cx).snapshot(cx);
 6928        let old_selections = self.selections.all::<usize>(cx).into_boxed_slice();
 6929
 6930        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
 6931        let mut selected_larger_node = false;
 6932        let new_selections = old_selections
 6933            .iter()
 6934            .map(|selection| {
 6935                let old_range = selection.start..selection.end;
 6936                let mut new_range = old_range.clone();
 6937                while let Some(containing_range) =
 6938                    buffer.range_for_syntax_ancestor(new_range.clone())
 6939                {
 6940                    new_range = containing_range;
 6941                    if !display_map.intersects_fold(new_range.start)
 6942                        && !display_map.intersects_fold(new_range.end)
 6943                    {
 6944                        break;
 6945                    }
 6946                }
 6947
 6948                selected_larger_node |= new_range != old_range;
 6949                Selection {
 6950                    id: selection.id,
 6951                    start: new_range.start,
 6952                    end: new_range.end,
 6953                    goal: SelectionGoal::None,
 6954                    reversed: selection.reversed,
 6955                }
 6956            })
 6957            .collect::<Vec<_>>();
 6958
 6959        if selected_larger_node {
 6960            stack.push(old_selections);
 6961            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6962                s.select(new_selections);
 6963            });
 6964        }
 6965        self.select_larger_syntax_node_stack = stack;
 6966    }
 6967
 6968    pub fn select_smaller_syntax_node(
 6969        &mut self,
 6970        _: &SelectSmallerSyntaxNode,
 6971        cx: &mut ViewContext<Self>,
 6972    ) {
 6973        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
 6974        if let Some(selections) = stack.pop() {
 6975            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6976                s.select(selections.to_vec());
 6977            });
 6978        }
 6979        self.select_larger_syntax_node_stack = stack;
 6980    }
 6981
 6982    pub fn move_to_enclosing_bracket(
 6983        &mut self,
 6984        _: &MoveToEnclosingBracket,
 6985        cx: &mut ViewContext<Self>,
 6986    ) {
 6987        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6988            s.move_offsets_with(|snapshot, selection| {
 6989                let Some(enclosing_bracket_ranges) =
 6990                    snapshot.enclosing_bracket_ranges(selection.start..selection.end)
 6991                else {
 6992                    return;
 6993                };
 6994
 6995                let mut best_length = usize::MAX;
 6996                let mut best_inside = false;
 6997                let mut best_in_bracket_range = false;
 6998                let mut best_destination = None;
 6999                for (open, close) in enclosing_bracket_ranges {
 7000                    let close = close.to_inclusive();
 7001                    let length = close.end() - open.start;
 7002                    let inside = selection.start >= open.end && selection.end <= *close.start();
 7003                    let in_bracket_range = open.to_inclusive().contains(&selection.head())
 7004                        || close.contains(&selection.head());
 7005
 7006                    // If best is next to a bracket and current isn't, skip
 7007                    if !in_bracket_range && best_in_bracket_range {
 7008                        continue;
 7009                    }
 7010
 7011                    // Prefer smaller lengths unless best is inside and current isn't
 7012                    if length > best_length && (best_inside || !inside) {
 7013                        continue;
 7014                    }
 7015
 7016                    best_length = length;
 7017                    best_inside = inside;
 7018                    best_in_bracket_range = in_bracket_range;
 7019                    best_destination = Some(
 7020                        if close.contains(&selection.start) && close.contains(&selection.end) {
 7021                            if inside {
 7022                                open.end
 7023                            } else {
 7024                                open.start
 7025                            }
 7026                        } else {
 7027                            if inside {
 7028                                *close.start()
 7029                            } else {
 7030                                *close.end()
 7031                            }
 7032                        },
 7033                    );
 7034                }
 7035
 7036                if let Some(destination) = best_destination {
 7037                    selection.collapse_to(destination, SelectionGoal::None);
 7038                }
 7039            })
 7040        });
 7041    }
 7042
 7043    pub fn undo_selection(&mut self, _: &UndoSelection, cx: &mut ViewContext<Self>) {
 7044        self.end_selection(cx);
 7045        self.selection_history.mode = SelectionHistoryMode::Undoing;
 7046        if let Some(entry) = self.selection_history.undo_stack.pop_back() {
 7047            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
 7048            self.select_next_state = entry.select_next_state;
 7049            self.select_prev_state = entry.select_prev_state;
 7050            self.add_selections_state = entry.add_selections_state;
 7051            self.request_autoscroll(Autoscroll::newest(), cx);
 7052        }
 7053        self.selection_history.mode = SelectionHistoryMode::Normal;
 7054    }
 7055
 7056    pub fn redo_selection(&mut self, _: &RedoSelection, cx: &mut ViewContext<Self>) {
 7057        self.end_selection(cx);
 7058        self.selection_history.mode = SelectionHistoryMode::Redoing;
 7059        if let Some(entry) = self.selection_history.redo_stack.pop_back() {
 7060            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
 7061            self.select_next_state = entry.select_next_state;
 7062            self.select_prev_state = entry.select_prev_state;
 7063            self.add_selections_state = entry.add_selections_state;
 7064            self.request_autoscroll(Autoscroll::newest(), cx);
 7065        }
 7066        self.selection_history.mode = SelectionHistoryMode::Normal;
 7067    }
 7068
 7069    fn go_to_diagnostic(&mut self, _: &GoToDiagnostic, cx: &mut ViewContext<Self>) {
 7070        self.go_to_diagnostic_impl(Direction::Next, cx)
 7071    }
 7072
 7073    fn go_to_prev_diagnostic(&mut self, _: &GoToPrevDiagnostic, cx: &mut ViewContext<Self>) {
 7074        self.go_to_diagnostic_impl(Direction::Prev, cx)
 7075    }
 7076
 7077    pub fn go_to_diagnostic_impl(&mut self, direction: Direction, cx: &mut ViewContext<Self>) {
 7078        let buffer = self.buffer.read(cx).snapshot(cx);
 7079        let selection = self.selections.newest::<usize>(cx);
 7080
 7081        // If there is an active Diagnostic Popover jump to its diagnostic instead.
 7082        if direction == Direction::Next {
 7083            if let Some(popover) = self.hover_state.diagnostic_popover.as_ref() {
 7084                let (group_id, jump_to) = popover.activation_info();
 7085                if self.activate_diagnostics(group_id, cx) {
 7086                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7087                        let mut new_selection = s.newest_anchor().clone();
 7088                        new_selection.collapse_to(jump_to, SelectionGoal::None);
 7089                        s.select_anchors(vec![new_selection.clone()]);
 7090                    });
 7091                }
 7092                return;
 7093            }
 7094        }
 7095
 7096        let mut active_primary_range = self.active_diagnostics.as_ref().map(|active_diagnostics| {
 7097            active_diagnostics
 7098                .primary_range
 7099                .to_offset(&buffer)
 7100                .to_inclusive()
 7101        });
 7102        let mut search_start = if let Some(active_primary_range) = active_primary_range.as_ref() {
 7103            if active_primary_range.contains(&selection.head()) {
 7104                *active_primary_range.end()
 7105            } else {
 7106                selection.head()
 7107            }
 7108        } else {
 7109            selection.head()
 7110        };
 7111
 7112        loop {
 7113            let mut diagnostics = if direction == Direction::Prev {
 7114                buffer.diagnostics_in_range::<_, usize>(0..search_start, true)
 7115            } else {
 7116                buffer.diagnostics_in_range::<_, usize>(search_start..buffer.len(), false)
 7117            };
 7118            let group = diagnostics.find_map(|entry| {
 7119                if entry.diagnostic.is_primary
 7120                    && entry.diagnostic.severity <= DiagnosticSeverity::WARNING
 7121                    && !entry.range.is_empty()
 7122                    && Some(entry.range.end) != active_primary_range.as_ref().map(|r| *r.end())
 7123                    && !entry.range.contains(&search_start)
 7124                {
 7125                    Some((entry.range, entry.diagnostic.group_id))
 7126                } else {
 7127                    None
 7128                }
 7129            });
 7130
 7131            if let Some((primary_range, group_id)) = group {
 7132                if self.activate_diagnostics(group_id, cx) {
 7133                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7134                        s.select(vec![Selection {
 7135                            id: selection.id,
 7136                            start: primary_range.start,
 7137                            end: primary_range.start,
 7138                            reversed: false,
 7139                            goal: SelectionGoal::None,
 7140                        }]);
 7141                    });
 7142                }
 7143                break;
 7144            } else {
 7145                // Cycle around to the start of the buffer, potentially moving back to the start of
 7146                // the currently active diagnostic.
 7147                active_primary_range.take();
 7148                if direction == Direction::Prev {
 7149                    if search_start == buffer.len() {
 7150                        break;
 7151                    } else {
 7152                        search_start = buffer.len();
 7153                    }
 7154                } else if search_start == 0 {
 7155                    break;
 7156                } else {
 7157                    search_start = 0;
 7158                }
 7159            }
 7160        }
 7161    }
 7162
 7163    fn go_to_hunk(&mut self, _: &GoToHunk, cx: &mut ViewContext<Self>) {
 7164        let snapshot = self
 7165            .display_map
 7166            .update(cx, |display_map, cx| display_map.snapshot(cx));
 7167        let selection = self.selections.newest::<Point>(cx);
 7168
 7169        if !self.seek_in_direction(
 7170            &snapshot,
 7171            selection.head(),
 7172            false,
 7173            snapshot
 7174                .buffer_snapshot
 7175                .git_diff_hunks_in_range((selection.head().row + 1)..u32::MAX),
 7176            cx,
 7177        ) {
 7178            let wrapped_point = Point::zero();
 7179            self.seek_in_direction(
 7180                &snapshot,
 7181                wrapped_point,
 7182                true,
 7183                snapshot
 7184                    .buffer_snapshot
 7185                    .git_diff_hunks_in_range((wrapped_point.row + 1)..u32::MAX),
 7186                cx,
 7187            );
 7188        }
 7189    }
 7190
 7191    fn go_to_prev_hunk(&mut self, _: &GoToPrevHunk, cx: &mut ViewContext<Self>) {
 7192        let snapshot = self
 7193            .display_map
 7194            .update(cx, |display_map, cx| display_map.snapshot(cx));
 7195        let selection = self.selections.newest::<Point>(cx);
 7196
 7197        if !self.seek_in_direction(
 7198            &snapshot,
 7199            selection.head(),
 7200            false,
 7201            snapshot
 7202                .buffer_snapshot
 7203                .git_diff_hunks_in_range_rev(0..selection.head().row),
 7204            cx,
 7205        ) {
 7206            let wrapped_point = snapshot.buffer_snapshot.max_point();
 7207            self.seek_in_direction(
 7208                &snapshot,
 7209                wrapped_point,
 7210                true,
 7211                snapshot
 7212                    .buffer_snapshot
 7213                    .git_diff_hunks_in_range_rev(0..wrapped_point.row),
 7214                cx,
 7215            );
 7216        }
 7217    }
 7218
 7219    fn seek_in_direction(
 7220        &mut self,
 7221        snapshot: &DisplaySnapshot,
 7222        initial_point: Point,
 7223        is_wrapped: bool,
 7224        hunks: impl Iterator<Item = DiffHunk<u32>>,
 7225        cx: &mut ViewContext<Editor>,
 7226    ) -> bool {
 7227        let display_point = initial_point.to_display_point(snapshot);
 7228        let mut hunks = hunks
 7229            .map(|hunk| diff_hunk_to_display(hunk, &snapshot))
 7230            .filter(|hunk| {
 7231                if is_wrapped {
 7232                    true
 7233                } else {
 7234                    !hunk.contains_display_row(display_point.row())
 7235                }
 7236            })
 7237            .dedup();
 7238
 7239        if let Some(hunk) = hunks.next() {
 7240            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7241                let row = hunk.start_display_row();
 7242                let point = DisplayPoint::new(row, 0);
 7243                s.select_display_ranges([point..point]);
 7244            });
 7245
 7246            true
 7247        } else {
 7248            false
 7249        }
 7250    }
 7251
 7252    pub fn go_to_definition(&mut self, _: &GoToDefinition, cx: &mut ViewContext<Self>) {
 7253        self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, false, cx);
 7254    }
 7255
 7256    pub fn go_to_type_definition(&mut self, _: &GoToTypeDefinition, cx: &mut ViewContext<Self>) {
 7257        self.go_to_definition_of_kind(GotoDefinitionKind::Type, false, cx);
 7258    }
 7259
 7260    pub fn go_to_definition_split(&mut self, _: &GoToDefinitionSplit, cx: &mut ViewContext<Self>) {
 7261        self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, true, cx);
 7262    }
 7263
 7264    pub fn go_to_type_definition_split(
 7265        &mut self,
 7266        _: &GoToTypeDefinitionSplit,
 7267        cx: &mut ViewContext<Self>,
 7268    ) {
 7269        self.go_to_definition_of_kind(GotoDefinitionKind::Type, true, cx);
 7270    }
 7271
 7272    fn go_to_definition_of_kind(
 7273        &mut self,
 7274        kind: GotoDefinitionKind,
 7275        split: bool,
 7276        cx: &mut ViewContext<Self>,
 7277    ) {
 7278        let Some(workspace) = self.workspace() else {
 7279            return;
 7280        };
 7281        let buffer = self.buffer.read(cx);
 7282        let head = self.selections.newest::<usize>(cx).head();
 7283        let (buffer, head) = if let Some(text_anchor) = buffer.text_anchor_for_position(head, cx) {
 7284            text_anchor
 7285        } else {
 7286            return;
 7287        };
 7288
 7289        let project = workspace.read(cx).project().clone();
 7290        let definitions = project.update(cx, |project, cx| match kind {
 7291            GotoDefinitionKind::Symbol => project.definition(&buffer, head, cx),
 7292            GotoDefinitionKind::Type => project.type_definition(&buffer, head, cx),
 7293        });
 7294
 7295        cx.spawn(|editor, mut cx| async move {
 7296            let definitions = definitions.await?;
 7297            editor.update(&mut cx, |editor, cx| {
 7298                editor.navigate_to_hover_links(
 7299                    definitions.into_iter().map(HoverLink::Text).collect(),
 7300                    split,
 7301                    cx,
 7302                );
 7303            })?;
 7304            Ok::<(), anyhow::Error>(())
 7305        })
 7306        .detach_and_log_err(cx);
 7307    }
 7308
 7309    pub fn navigate_to_hover_links(
 7310        &mut self,
 7311        mut definitions: Vec<HoverLink>,
 7312        split: bool,
 7313        cx: &mut ViewContext<Editor>,
 7314    ) {
 7315        // If there is one definition, just open it directly
 7316        if definitions.len() == 1 {
 7317            let definition = definitions.pop().unwrap();
 7318            let target_task = match definition {
 7319                HoverLink::Text(link) => Task::Ready(Some(Ok(Some(link.target)))),
 7320                HoverLink::InlayHint(lsp_location, server_id) => {
 7321                    self.compute_target_location(lsp_location, server_id, cx)
 7322                }
 7323                HoverLink::Url(url) => {
 7324                    cx.open_url(&url);
 7325                    Task::ready(Ok(None))
 7326                }
 7327            };
 7328            cx.spawn(|editor, mut cx| async move {
 7329                let target = target_task.await.context("target resolution task")?;
 7330                if let Some(target) = target {
 7331                    editor.update(&mut cx, |editor, cx| {
 7332                        let Some(workspace) = editor.workspace() else {
 7333                            return;
 7334                        };
 7335                        let pane = workspace.read(cx).active_pane().clone();
 7336
 7337                        let range = target.range.to_offset(target.buffer.read(cx));
 7338                        let range = editor.range_for_match(&range);
 7339                        if Some(&target.buffer) == editor.buffer.read(cx).as_singleton().as_ref() {
 7340                            editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7341                                s.select_ranges([range]);
 7342                            });
 7343                        } else {
 7344                            cx.window_context().defer(move |cx| {
 7345                                let target_editor: View<Self> =
 7346                                    workspace.update(cx, |workspace, cx| {
 7347                                        if split {
 7348                                            workspace.split_project_item(target.buffer.clone(), cx)
 7349                                        } else {
 7350                                            workspace.open_project_item(target.buffer.clone(), cx)
 7351                                        }
 7352                                    });
 7353                                target_editor.update(cx, |target_editor, cx| {
 7354                                    // When selecting a definition in a different buffer, disable the nav history
 7355                                    // to avoid creating a history entry at the previous cursor location.
 7356                                    pane.update(cx, |pane, _| pane.disable_history());
 7357                                    target_editor.change_selections(
 7358                                        Some(Autoscroll::fit()),
 7359                                        cx,
 7360                                        |s| {
 7361                                            s.select_ranges([range]);
 7362                                        },
 7363                                    );
 7364                                    pane.update(cx, |pane, _| pane.enable_history());
 7365                                });
 7366                            });
 7367                        }
 7368                    })
 7369                } else {
 7370                    Ok(())
 7371                }
 7372            })
 7373            .detach_and_log_err(cx);
 7374        } else if !definitions.is_empty() {
 7375            let replica_id = self.replica_id(cx);
 7376            cx.spawn(|editor, mut cx| async move {
 7377                let (title, location_tasks, workspace) = editor
 7378                    .update(&mut cx, |editor, cx| {
 7379                        let title = definitions
 7380                            .iter()
 7381                            .find_map(|definition| match definition {
 7382                                HoverLink::Text(link) => link.origin.as_ref().map(|origin| {
 7383                                    let buffer = origin.buffer.read(cx);
 7384                                    format!(
 7385                                        "Definitions for {}",
 7386                                        buffer
 7387                                            .text_for_range(origin.range.clone())
 7388                                            .collect::<String>()
 7389                                    )
 7390                                }),
 7391                                HoverLink::InlayHint(_, _) => None,
 7392                                HoverLink::Url(_) => None,
 7393                            })
 7394                            .unwrap_or("Definitions".to_string());
 7395                        let location_tasks = definitions
 7396                            .into_iter()
 7397                            .map(|definition| match definition {
 7398                                HoverLink::Text(link) => Task::Ready(Some(Ok(Some(link.target)))),
 7399                                HoverLink::InlayHint(lsp_location, server_id) => {
 7400                                    editor.compute_target_location(lsp_location, server_id, cx)
 7401                                }
 7402                                HoverLink::Url(_) => Task::ready(Ok(None)),
 7403                            })
 7404                            .collect::<Vec<_>>();
 7405                        (title, location_tasks, editor.workspace().clone())
 7406                    })
 7407                    .context("location tasks preparation")?;
 7408
 7409                let locations = futures::future::join_all(location_tasks)
 7410                    .await
 7411                    .into_iter()
 7412                    .filter_map(|location| location.transpose())
 7413                    .collect::<Result<_>>()
 7414                    .context("location tasks")?;
 7415
 7416                let Some(workspace) = workspace else {
 7417                    return Ok(());
 7418                };
 7419                workspace
 7420                    .update(&mut cx, |workspace, cx| {
 7421                        Self::open_locations_in_multibuffer(
 7422                            workspace, locations, replica_id, title, split, cx,
 7423                        )
 7424                    })
 7425                    .ok();
 7426
 7427                anyhow::Ok(())
 7428            })
 7429            .detach_and_log_err(cx);
 7430        }
 7431    }
 7432
 7433    fn compute_target_location(
 7434        &self,
 7435        lsp_location: lsp::Location,
 7436        server_id: LanguageServerId,
 7437        cx: &mut ViewContext<Editor>,
 7438    ) -> Task<anyhow::Result<Option<Location>>> {
 7439        let Some(project) = self.project.clone() else {
 7440            return Task::Ready(Some(Ok(None)));
 7441        };
 7442
 7443        cx.spawn(move |editor, mut cx| async move {
 7444            let location_task = editor.update(&mut cx, |editor, cx| {
 7445                project.update(cx, |project, cx| {
 7446                    let language_server_name =
 7447                        editor.buffer.read(cx).as_singleton().and_then(|buffer| {
 7448                            project
 7449                                .language_server_for_buffer(buffer.read(cx), server_id, cx)
 7450                                .map(|(lsp_adapter, _)| lsp_adapter.name.clone())
 7451                        });
 7452                    language_server_name.map(|language_server_name| {
 7453                        project.open_local_buffer_via_lsp(
 7454                            lsp_location.uri.clone(),
 7455                            server_id,
 7456                            language_server_name,
 7457                            cx,
 7458                        )
 7459                    })
 7460                })
 7461            })?;
 7462            let location = match location_task {
 7463                Some(task) => Some({
 7464                    let target_buffer_handle = task.await.context("open local buffer")?;
 7465                    let range = target_buffer_handle.update(&mut cx, |target_buffer, _| {
 7466                        let target_start = target_buffer
 7467                            .clip_point_utf16(point_from_lsp(lsp_location.range.start), Bias::Left);
 7468                        let target_end = target_buffer
 7469                            .clip_point_utf16(point_from_lsp(lsp_location.range.end), Bias::Left);
 7470                        target_buffer.anchor_after(target_start)
 7471                            ..target_buffer.anchor_before(target_end)
 7472                    })?;
 7473                    Location {
 7474                        buffer: target_buffer_handle,
 7475                        range,
 7476                    }
 7477                }),
 7478                None => None,
 7479            };
 7480            Ok(location)
 7481        })
 7482    }
 7483
 7484    pub fn find_all_references(
 7485        &mut self,
 7486        _: &FindAllReferences,
 7487        cx: &mut ViewContext<Self>,
 7488    ) -> Option<Task<Result<()>>> {
 7489        let buffer = self.buffer.read(cx);
 7490        let head = self.selections.newest::<usize>(cx).head();
 7491        let (buffer, head) = buffer.text_anchor_for_position(head, cx)?;
 7492        let replica_id = self.replica_id(cx);
 7493
 7494        let workspace = self.workspace()?;
 7495        let project = workspace.read(cx).project().clone();
 7496        let references = project.update(cx, |project, cx| project.references(&buffer, head, cx));
 7497        Some(cx.spawn(|_, mut cx| async move {
 7498            let locations = references.await?;
 7499            if locations.is_empty() {
 7500                return Ok(());
 7501            }
 7502
 7503            workspace.update(&mut cx, |workspace, cx| {
 7504                let title = locations
 7505                    .first()
 7506                    .as_ref()
 7507                    .map(|location| {
 7508                        let buffer = location.buffer.read(cx);
 7509                        format!(
 7510                            "References to `{}`",
 7511                            buffer
 7512                                .text_for_range(location.range.clone())
 7513                                .collect::<String>()
 7514                        )
 7515                    })
 7516                    .unwrap();
 7517                Self::open_locations_in_multibuffer(
 7518                    workspace, locations, replica_id, title, false, cx,
 7519                );
 7520            })?;
 7521
 7522            Ok(())
 7523        }))
 7524    }
 7525
 7526    /// Opens a multibuffer with the given project locations in it
 7527    pub fn open_locations_in_multibuffer(
 7528        workspace: &mut Workspace,
 7529        mut locations: Vec<Location>,
 7530        replica_id: ReplicaId,
 7531        title: String,
 7532        split: bool,
 7533        cx: &mut ViewContext<Workspace>,
 7534    ) {
 7535        // If there are multiple definitions, open them in a multibuffer
 7536        locations.sort_by_key(|location| location.buffer.read(cx).remote_id());
 7537        let mut locations = locations.into_iter().peekable();
 7538        let mut ranges_to_highlight = Vec::new();
 7539        let capability = workspace.project().read(cx).capability();
 7540
 7541        let excerpt_buffer = cx.new_model(|cx| {
 7542            let mut multibuffer = MultiBuffer::new(replica_id, capability);
 7543            while let Some(location) = locations.next() {
 7544                let buffer = location.buffer.read(cx);
 7545                let mut ranges_for_buffer = Vec::new();
 7546                let range = location.range.to_offset(buffer);
 7547                ranges_for_buffer.push(range.clone());
 7548
 7549                while let Some(next_location) = locations.peek() {
 7550                    if next_location.buffer == location.buffer {
 7551                        ranges_for_buffer.push(next_location.range.to_offset(buffer));
 7552                        locations.next();
 7553                    } else {
 7554                        break;
 7555                    }
 7556                }
 7557
 7558                ranges_for_buffer.sort_by_key(|range| (range.start, Reverse(range.end)));
 7559                ranges_to_highlight.extend(multibuffer.push_excerpts_with_context_lines(
 7560                    location.buffer.clone(),
 7561                    ranges_for_buffer,
 7562                    1,
 7563                    cx,
 7564                ))
 7565            }
 7566
 7567            multibuffer.with_title(title)
 7568        });
 7569
 7570        let editor = cx.new_view(|cx| {
 7571            Editor::for_multibuffer(excerpt_buffer, Some(workspace.project().clone()), cx)
 7572        });
 7573        editor.update(cx, |editor, cx| {
 7574            editor.highlight_background::<Self>(
 7575                ranges_to_highlight,
 7576                |theme| theme.editor_highlighted_line_background,
 7577                cx,
 7578            );
 7579        });
 7580        if split {
 7581            workspace.split_item(SplitDirection::Right, Box::new(editor), cx);
 7582        } else {
 7583            workspace.add_item(Box::new(editor), cx);
 7584        }
 7585    }
 7586
 7587    pub fn rename(&mut self, _: &Rename, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
 7588        use language::ToOffset as _;
 7589
 7590        let project = self.project.clone()?;
 7591        let selection = self.selections.newest_anchor().clone();
 7592        let (cursor_buffer, cursor_buffer_position) = self
 7593            .buffer
 7594            .read(cx)
 7595            .text_anchor_for_position(selection.head(), cx)?;
 7596        let (tail_buffer, _) = self
 7597            .buffer
 7598            .read(cx)
 7599            .text_anchor_for_position(selection.tail(), cx)?;
 7600        if tail_buffer != cursor_buffer {
 7601            return None;
 7602        }
 7603
 7604        let snapshot = cursor_buffer.read(cx).snapshot();
 7605        let cursor_buffer_offset = cursor_buffer_position.to_offset(&snapshot);
 7606        let prepare_rename = project.update(cx, |project, cx| {
 7607            project.prepare_rename(cursor_buffer, cursor_buffer_offset, cx)
 7608        });
 7609
 7610        Some(cx.spawn(|this, mut cx| async move {
 7611            let rename_range = if let Some(range) = prepare_rename.await? {
 7612                Some(range)
 7613            } else {
 7614                this.update(&mut cx, |this, cx| {
 7615                    let buffer = this.buffer.read(cx).snapshot(cx);
 7616                    let mut buffer_highlights = this
 7617                        .document_highlights_for_position(selection.head(), &buffer)
 7618                        .filter(|highlight| {
 7619                            highlight.start.excerpt_id == selection.head().excerpt_id
 7620                                && highlight.end.excerpt_id == selection.head().excerpt_id
 7621                        });
 7622                    buffer_highlights
 7623                        .next()
 7624                        .map(|highlight| highlight.start.text_anchor..highlight.end.text_anchor)
 7625                })?
 7626            };
 7627            if let Some(rename_range) = rename_range {
 7628                let rename_buffer_range = rename_range.to_offset(&snapshot);
 7629                let cursor_offset_in_rename_range =
 7630                    cursor_buffer_offset.saturating_sub(rename_buffer_range.start);
 7631
 7632                this.update(&mut cx, |this, cx| {
 7633                    this.take_rename(false, cx);
 7634                    let buffer = this.buffer.read(cx).read(cx);
 7635                    let cursor_offset = selection.head().to_offset(&buffer);
 7636                    let rename_start = cursor_offset.saturating_sub(cursor_offset_in_rename_range);
 7637                    let rename_end = rename_start + rename_buffer_range.len();
 7638                    let range = buffer.anchor_before(rename_start)..buffer.anchor_after(rename_end);
 7639                    let mut old_highlight_id = None;
 7640                    let old_name: Arc<str> = buffer
 7641                        .chunks(rename_start..rename_end, true)
 7642                        .map(|chunk| {
 7643                            if old_highlight_id.is_none() {
 7644                                old_highlight_id = chunk.syntax_highlight_id;
 7645                            }
 7646                            chunk.text
 7647                        })
 7648                        .collect::<String>()
 7649                        .into();
 7650
 7651                    drop(buffer);
 7652
 7653                    // Position the selection in the rename editor so that it matches the current selection.
 7654                    this.show_local_selections = false;
 7655                    let rename_editor = cx.new_view(|cx| {
 7656                        let mut editor = Editor::single_line(cx);
 7657                        editor.buffer.update(cx, |buffer, cx| {
 7658                            buffer.edit([(0..0, old_name.clone())], None, cx)
 7659                        });
 7660                        editor.select_all(&SelectAll, cx);
 7661                        editor
 7662                    });
 7663
 7664                    let ranges = this
 7665                        .clear_background_highlights::<DocumentHighlightWrite>(cx)
 7666                        .into_iter()
 7667                        .flat_map(|(_, ranges)| ranges.into_iter())
 7668                        .chain(
 7669                            this.clear_background_highlights::<DocumentHighlightRead>(cx)
 7670                                .into_iter()
 7671                                .flat_map(|(_, ranges)| ranges.into_iter()),
 7672                        )
 7673                        .collect();
 7674
 7675                    this.highlight_text::<Rename>(
 7676                        ranges,
 7677                        HighlightStyle {
 7678                            fade_out: Some(0.6),
 7679                            ..Default::default()
 7680                        },
 7681                        cx,
 7682                    );
 7683                    let rename_focus_handle = rename_editor.focus_handle(cx);
 7684                    cx.focus(&rename_focus_handle);
 7685                    let block_id = this.insert_blocks(
 7686                        [BlockProperties {
 7687                            style: BlockStyle::Flex,
 7688                            position: range.start.clone(),
 7689                            height: 1,
 7690                            render: Arc::new({
 7691                                let rename_editor = rename_editor.clone();
 7692                                move |cx: &mut BlockContext| {
 7693                                    let mut text_style = cx.editor_style.text.clone();
 7694                                    if let Some(highlight_style) = old_highlight_id
 7695                                        .and_then(|h| h.style(&cx.editor_style.syntax))
 7696                                    {
 7697                                        text_style = text_style.highlight(highlight_style);
 7698                                    }
 7699                                    div()
 7700                                        .pl(cx.anchor_x)
 7701                                        .child(EditorElement::new(
 7702                                            &rename_editor,
 7703                                            EditorStyle {
 7704                                                background: cx.theme().system().transparent,
 7705                                                local_player: cx.editor_style.local_player,
 7706                                                text: text_style,
 7707                                                scrollbar_width: cx.editor_style.scrollbar_width,
 7708                                                syntax: cx.editor_style.syntax.clone(),
 7709                                                status: cx.editor_style.status.clone(),
 7710                                                inlays_style: HighlightStyle {
 7711                                                    color: Some(cx.theme().status().hint),
 7712                                                    font_weight: Some(FontWeight::BOLD),
 7713                                                    ..HighlightStyle::default()
 7714                                                },
 7715                                                suggestions_style: HighlightStyle {
 7716                                                    color: Some(cx.theme().status().predictive),
 7717                                                    ..HighlightStyle::default()
 7718                                                },
 7719                                            },
 7720                                        ))
 7721                                        .into_any_element()
 7722                                }
 7723                            }),
 7724                            disposition: BlockDisposition::Below,
 7725                        }],
 7726                        Some(Autoscroll::fit()),
 7727                        cx,
 7728                    )[0];
 7729                    this.pending_rename = Some(RenameState {
 7730                        range,
 7731                        old_name,
 7732                        editor: rename_editor,
 7733                        block_id,
 7734                    });
 7735                })?;
 7736            }
 7737
 7738            Ok(())
 7739        }))
 7740    }
 7741
 7742    pub fn confirm_rename(
 7743        &mut self,
 7744        _: &ConfirmRename,
 7745        cx: &mut ViewContext<Self>,
 7746    ) -> Option<Task<Result<()>>> {
 7747        let rename = self.take_rename(false, cx)?;
 7748        let workspace = self.workspace()?;
 7749        let (start_buffer, start) = self
 7750            .buffer
 7751            .read(cx)
 7752            .text_anchor_for_position(rename.range.start.clone(), cx)?;
 7753        let (end_buffer, end) = self
 7754            .buffer
 7755            .read(cx)
 7756            .text_anchor_for_position(rename.range.end.clone(), cx)?;
 7757        if start_buffer != end_buffer {
 7758            return None;
 7759        }
 7760
 7761        let buffer = start_buffer;
 7762        let range = start..end;
 7763        let old_name = rename.old_name;
 7764        let new_name = rename.editor.read(cx).text(cx);
 7765
 7766        let rename = workspace
 7767            .read(cx)
 7768            .project()
 7769            .clone()
 7770            .update(cx, |project, cx| {
 7771                project.perform_rename(buffer.clone(), range.start, new_name.clone(), true, cx)
 7772            });
 7773        let workspace = workspace.downgrade();
 7774
 7775        Some(cx.spawn(|editor, mut cx| async move {
 7776            let project_transaction = rename.await?;
 7777            Self::open_project_transaction(
 7778                &editor,
 7779                workspace,
 7780                project_transaction,
 7781                format!("Rename: {}{}", old_name, new_name),
 7782                cx.clone(),
 7783            )
 7784            .await?;
 7785
 7786            editor.update(&mut cx, |editor, cx| {
 7787                editor.refresh_document_highlights(cx);
 7788            })?;
 7789            Ok(())
 7790        }))
 7791    }
 7792
 7793    fn take_rename(
 7794        &mut self,
 7795        moving_cursor: bool,
 7796        cx: &mut ViewContext<Self>,
 7797    ) -> Option<RenameState> {
 7798        let rename = self.pending_rename.take()?;
 7799        if rename.editor.focus_handle(cx).is_focused(cx) {
 7800            cx.focus(&self.focus_handle);
 7801        }
 7802
 7803        self.remove_blocks(
 7804            [rename.block_id].into_iter().collect(),
 7805            Some(Autoscroll::fit()),
 7806            cx,
 7807        );
 7808        self.clear_highlights::<Rename>(cx);
 7809        self.show_local_selections = true;
 7810
 7811        if moving_cursor {
 7812            let rename_editor = rename.editor.read(cx);
 7813            let cursor_in_rename_editor = rename_editor.selections.newest::<usize>(cx).head();
 7814
 7815            // Update the selection to match the position of the selection inside
 7816            // the rename editor.
 7817            let snapshot = self.buffer.read(cx).read(cx);
 7818            let rename_range = rename.range.to_offset(&snapshot);
 7819            let cursor_in_editor = snapshot
 7820                .clip_offset(rename_range.start + cursor_in_rename_editor, Bias::Left)
 7821                .min(rename_range.end);
 7822            drop(snapshot);
 7823
 7824            self.change_selections(None, cx, |s| {
 7825                s.select_ranges(vec![cursor_in_editor..cursor_in_editor])
 7826            });
 7827        } else {
 7828            self.refresh_document_highlights(cx);
 7829        }
 7830
 7831        Some(rename)
 7832    }
 7833
 7834    #[cfg(any(test, feature = "test-support"))]
 7835    pub fn pending_rename(&self) -> Option<&RenameState> {
 7836        self.pending_rename.as_ref()
 7837    }
 7838
 7839    fn format(&mut self, _: &Format, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
 7840        let project = match &self.project {
 7841            Some(project) => project.clone(),
 7842            None => return None,
 7843        };
 7844
 7845        Some(self.perform_format(project, FormatTrigger::Manual, cx))
 7846    }
 7847
 7848    fn perform_format(
 7849        &mut self,
 7850        project: Model<Project>,
 7851        trigger: FormatTrigger,
 7852        cx: &mut ViewContext<Self>,
 7853    ) -> Task<Result<()>> {
 7854        let buffer = self.buffer().clone();
 7855        let buffers = buffer.read(cx).all_buffers();
 7856
 7857        let mut timeout = cx.background_executor().timer(FORMAT_TIMEOUT).fuse();
 7858        let format = project.update(cx, |project, cx| project.format(buffers, true, trigger, cx));
 7859
 7860        cx.spawn(|_, mut cx| async move {
 7861            let transaction = futures::select_biased! {
 7862                _ = timeout => {
 7863                    log::warn!("timed out waiting for formatting");
 7864                    None
 7865                }
 7866                transaction = format.log_err().fuse() => transaction,
 7867            };
 7868
 7869            buffer
 7870                .update(&mut cx, |buffer, cx| {
 7871                    if let Some(transaction) = transaction {
 7872                        if !buffer.is_singleton() {
 7873                            buffer.push_transaction(&transaction.0, cx);
 7874                        }
 7875                    }
 7876
 7877                    cx.notify();
 7878                })
 7879                .ok();
 7880
 7881            Ok(())
 7882        })
 7883    }
 7884
 7885    fn restart_language_server(&mut self, _: &RestartLanguageServer, cx: &mut ViewContext<Self>) {
 7886        if let Some(project) = self.project.clone() {
 7887            self.buffer.update(cx, |multi_buffer, cx| {
 7888                project.update(cx, |project, cx| {
 7889                    project.restart_language_servers_for_buffers(multi_buffer.all_buffers(), cx);
 7890                });
 7891            })
 7892        }
 7893    }
 7894
 7895    fn show_character_palette(&mut self, _: &ShowCharacterPalette, cx: &mut ViewContext<Self>) {
 7896        cx.show_character_palette();
 7897    }
 7898
 7899    fn refresh_active_diagnostics(&mut self, cx: &mut ViewContext<Editor>) {
 7900        if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
 7901            let buffer = self.buffer.read(cx).snapshot(cx);
 7902            let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
 7903            let is_valid = buffer
 7904                .diagnostics_in_range::<_, usize>(active_diagnostics.primary_range.clone(), false)
 7905                .any(|entry| {
 7906                    entry.diagnostic.is_primary
 7907                        && !entry.range.is_empty()
 7908                        && entry.range.start == primary_range_start
 7909                        && entry.diagnostic.message == active_diagnostics.primary_message
 7910                });
 7911
 7912            if is_valid != active_diagnostics.is_valid {
 7913                active_diagnostics.is_valid = is_valid;
 7914                let mut new_styles = HashMap::default();
 7915                for (block_id, diagnostic) in &active_diagnostics.blocks {
 7916                    new_styles.insert(
 7917                        *block_id,
 7918                        diagnostic_block_renderer(diagnostic.clone(), is_valid),
 7919                    );
 7920                }
 7921                self.display_map
 7922                    .update(cx, |display_map, _| display_map.replace_blocks(new_styles));
 7923            }
 7924        }
 7925    }
 7926
 7927    fn activate_diagnostics(&mut self, group_id: usize, cx: &mut ViewContext<Self>) -> bool {
 7928        self.dismiss_diagnostics(cx);
 7929        self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
 7930            let buffer = self.buffer.read(cx).snapshot(cx);
 7931
 7932            let mut primary_range = None;
 7933            let mut primary_message = None;
 7934            let mut group_end = Point::zero();
 7935            let diagnostic_group = buffer
 7936                .diagnostic_group::<Point>(group_id)
 7937                .map(|entry| {
 7938                    if entry.range.end > group_end {
 7939                        group_end = entry.range.end;
 7940                    }
 7941                    if entry.diagnostic.is_primary {
 7942                        primary_range = Some(entry.range.clone());
 7943                        primary_message = Some(entry.diagnostic.message.clone());
 7944                    }
 7945                    entry
 7946                })
 7947                .collect::<Vec<_>>();
 7948            let primary_range = primary_range?;
 7949            let primary_message = primary_message?;
 7950            let primary_range =
 7951                buffer.anchor_after(primary_range.start)..buffer.anchor_before(primary_range.end);
 7952
 7953            let blocks = display_map
 7954                .insert_blocks(
 7955                    diagnostic_group.iter().map(|entry| {
 7956                        let diagnostic = entry.diagnostic.clone();
 7957                        let message_height = diagnostic.message.matches('\n').count() as u8 + 1;
 7958                        BlockProperties {
 7959                            style: BlockStyle::Fixed,
 7960                            position: buffer.anchor_after(entry.range.start),
 7961                            height: message_height,
 7962                            render: diagnostic_block_renderer(diagnostic, true),
 7963                            disposition: BlockDisposition::Below,
 7964                        }
 7965                    }),
 7966                    cx,
 7967                )
 7968                .into_iter()
 7969                .zip(diagnostic_group.into_iter().map(|entry| entry.diagnostic))
 7970                .collect();
 7971
 7972            Some(ActiveDiagnosticGroup {
 7973                primary_range,
 7974                primary_message,
 7975                blocks,
 7976                is_valid: true,
 7977            })
 7978        });
 7979        self.active_diagnostics.is_some()
 7980    }
 7981
 7982    fn dismiss_diagnostics(&mut self, cx: &mut ViewContext<Self>) {
 7983        if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
 7984            self.display_map.update(cx, |display_map, cx| {
 7985                display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx);
 7986            });
 7987            cx.notify();
 7988        }
 7989    }
 7990
 7991    pub fn set_selections_from_remote(
 7992        &mut self,
 7993        selections: Vec<Selection<Anchor>>,
 7994        pending_selection: Option<Selection<Anchor>>,
 7995        cx: &mut ViewContext<Self>,
 7996    ) {
 7997        let old_cursor_position = self.selections.newest_anchor().head();
 7998        self.selections.change_with(cx, |s| {
 7999            s.select_anchors(selections);
 8000            if let Some(pending_selection) = pending_selection {
 8001                s.set_pending(pending_selection, SelectMode::Character);
 8002            } else {
 8003                s.clear_pending();
 8004            }
 8005        });
 8006        self.selections_did_change(false, &old_cursor_position, cx);
 8007    }
 8008
 8009    fn push_to_selection_history(&mut self) {
 8010        self.selection_history.push(SelectionHistoryEntry {
 8011            selections: self.selections.disjoint_anchors(),
 8012            select_next_state: self.select_next_state.clone(),
 8013            select_prev_state: self.select_prev_state.clone(),
 8014            add_selections_state: self.add_selections_state.clone(),
 8015        });
 8016    }
 8017
 8018    pub fn transact(
 8019        &mut self,
 8020        cx: &mut ViewContext<Self>,
 8021        update: impl FnOnce(&mut Self, &mut ViewContext<Self>),
 8022    ) -> Option<TransactionId> {
 8023        self.start_transaction_at(Instant::now(), cx);
 8024        update(self, cx);
 8025        self.end_transaction_at(Instant::now(), cx)
 8026    }
 8027
 8028    fn start_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
 8029        self.end_selection(cx);
 8030        if let Some(tx_id) = self
 8031            .buffer
 8032            .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx))
 8033        {
 8034            self.selection_history
 8035                .insert_transaction(tx_id, self.selections.disjoint_anchors());
 8036        }
 8037    }
 8038
 8039    fn end_transaction_at(
 8040        &mut self,
 8041        now: Instant,
 8042        cx: &mut ViewContext<Self>,
 8043    ) -> Option<TransactionId> {
 8044        if let Some(tx_id) = self
 8045            .buffer
 8046            .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
 8047        {
 8048            if let Some((_, end_selections)) = self.selection_history.transaction_mut(tx_id) {
 8049                *end_selections = Some(self.selections.disjoint_anchors());
 8050            } else {
 8051                log::error!("unexpectedly ended a transaction that wasn't started by this editor");
 8052            }
 8053
 8054            cx.emit(EditorEvent::Edited);
 8055            Some(tx_id)
 8056        } else {
 8057            None
 8058        }
 8059    }
 8060
 8061    pub fn fold(&mut self, _: &actions::Fold, cx: &mut ViewContext<Self>) {
 8062        let mut fold_ranges = Vec::new();
 8063
 8064        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8065
 8066        let selections = self.selections.all_adjusted(cx);
 8067        for selection in selections {
 8068            let range = selection.range().sorted();
 8069            let buffer_start_row = range.start.row;
 8070
 8071            for row in (0..=range.end.row).rev() {
 8072                let fold_range = display_map.foldable_range(row);
 8073
 8074                if let Some(fold_range) = fold_range {
 8075                    if fold_range.end.row >= buffer_start_row {
 8076                        fold_ranges.push(fold_range);
 8077                        if row <= range.start.row {
 8078                            break;
 8079                        }
 8080                    }
 8081                }
 8082            }
 8083        }
 8084
 8085        self.fold_ranges(fold_ranges, true, cx);
 8086    }
 8087
 8088    pub fn fold_at(&mut self, fold_at: &FoldAt, cx: &mut ViewContext<Self>) {
 8089        let buffer_row = fold_at.buffer_row;
 8090        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8091
 8092        if let Some(fold_range) = display_map.foldable_range(buffer_row) {
 8093            let autoscroll = self
 8094                .selections
 8095                .all::<Point>(cx)
 8096                .iter()
 8097                .any(|selection| fold_range.overlaps(&selection.range()));
 8098
 8099            self.fold_ranges(std::iter::once(fold_range), autoscroll, cx);
 8100        }
 8101    }
 8102
 8103    pub fn unfold_lines(&mut self, _: &UnfoldLines, cx: &mut ViewContext<Self>) {
 8104        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8105        let buffer = &display_map.buffer_snapshot;
 8106        let selections = self.selections.all::<Point>(cx);
 8107        let ranges = selections
 8108            .iter()
 8109            .map(|s| {
 8110                let range = s.display_range(&display_map).sorted();
 8111                let mut start = range.start.to_point(&display_map);
 8112                let mut end = range.end.to_point(&display_map);
 8113                start.column = 0;
 8114                end.column = buffer.line_len(end.row);
 8115                start..end
 8116            })
 8117            .collect::<Vec<_>>();
 8118
 8119        self.unfold_ranges(ranges, true, true, cx);
 8120    }
 8121
 8122    pub fn unfold_at(&mut self, unfold_at: &UnfoldAt, cx: &mut ViewContext<Self>) {
 8123        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8124
 8125        let intersection_range = Point::new(unfold_at.buffer_row, 0)
 8126            ..Point::new(
 8127                unfold_at.buffer_row,
 8128                display_map.buffer_snapshot.line_len(unfold_at.buffer_row),
 8129            );
 8130
 8131        let autoscroll = self
 8132            .selections
 8133            .all::<Point>(cx)
 8134            .iter()
 8135            .any(|selection| selection.range().overlaps(&intersection_range));
 8136
 8137        self.unfold_ranges(std::iter::once(intersection_range), true, autoscroll, cx)
 8138    }
 8139
 8140    pub fn fold_selected_ranges(&mut self, _: &FoldSelectedRanges, cx: &mut ViewContext<Self>) {
 8141        let selections = self.selections.all::<Point>(cx);
 8142        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8143        let line_mode = self.selections.line_mode;
 8144        let ranges = selections.into_iter().map(|s| {
 8145            if line_mode {
 8146                let start = Point::new(s.start.row, 0);
 8147                let end = Point::new(s.end.row, display_map.buffer_snapshot.line_len(s.end.row));
 8148                start..end
 8149            } else {
 8150                s.start..s.end
 8151            }
 8152        });
 8153        self.fold_ranges(ranges, true, cx);
 8154    }
 8155
 8156    pub fn fold_ranges<T: ToOffset + Clone>(
 8157        &mut self,
 8158        ranges: impl IntoIterator<Item = Range<T>>,
 8159        auto_scroll: bool,
 8160        cx: &mut ViewContext<Self>,
 8161    ) {
 8162        let mut ranges = ranges.into_iter().peekable();
 8163        if ranges.peek().is_some() {
 8164            self.display_map.update(cx, |map, cx| map.fold(ranges, cx));
 8165
 8166            if auto_scroll {
 8167                self.request_autoscroll(Autoscroll::fit(), cx);
 8168            }
 8169
 8170            cx.notify();
 8171        }
 8172    }
 8173
 8174    pub fn unfold_ranges<T: ToOffset + Clone>(
 8175        &mut self,
 8176        ranges: impl IntoIterator<Item = Range<T>>,
 8177        inclusive: bool,
 8178        auto_scroll: bool,
 8179        cx: &mut ViewContext<Self>,
 8180    ) {
 8181        let mut ranges = ranges.into_iter().peekable();
 8182        if ranges.peek().is_some() {
 8183            self.display_map
 8184                .update(cx, |map, cx| map.unfold(ranges, inclusive, cx));
 8185            if auto_scroll {
 8186                self.request_autoscroll(Autoscroll::fit(), cx);
 8187            }
 8188
 8189            cx.notify();
 8190        }
 8191    }
 8192
 8193    pub fn set_gutter_hovered(&mut self, hovered: bool, cx: &mut ViewContext<Self>) {
 8194        if hovered != self.gutter_hovered {
 8195            self.gutter_hovered = hovered;
 8196            cx.notify();
 8197        }
 8198    }
 8199
 8200    pub fn insert_blocks(
 8201        &mut self,
 8202        blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
 8203        autoscroll: Option<Autoscroll>,
 8204        cx: &mut ViewContext<Self>,
 8205    ) -> Vec<BlockId> {
 8206        let blocks = self
 8207            .display_map
 8208            .update(cx, |display_map, cx| display_map.insert_blocks(blocks, cx));
 8209        if let Some(autoscroll) = autoscroll {
 8210            self.request_autoscroll(autoscroll, cx);
 8211        }
 8212        blocks
 8213    }
 8214
 8215    pub fn replace_blocks(
 8216        &mut self,
 8217        blocks: HashMap<BlockId, RenderBlock>,
 8218        autoscroll: Option<Autoscroll>,
 8219        cx: &mut ViewContext<Self>,
 8220    ) {
 8221        self.display_map
 8222            .update(cx, |display_map, _| display_map.replace_blocks(blocks));
 8223        if let Some(autoscroll) = autoscroll {
 8224            self.request_autoscroll(autoscroll, cx);
 8225        }
 8226    }
 8227
 8228    pub fn remove_blocks(
 8229        &mut self,
 8230        block_ids: HashSet<BlockId>,
 8231        autoscroll: Option<Autoscroll>,
 8232        cx: &mut ViewContext<Self>,
 8233    ) {
 8234        self.display_map.update(cx, |display_map, cx| {
 8235            display_map.remove_blocks(block_ids, cx)
 8236        });
 8237        if let Some(autoscroll) = autoscroll {
 8238            self.request_autoscroll(autoscroll, cx);
 8239        }
 8240    }
 8241
 8242    pub fn longest_row(&self, cx: &mut AppContext) -> u32 {
 8243        self.display_map
 8244            .update(cx, |map, cx| map.snapshot(cx))
 8245            .longest_row()
 8246    }
 8247
 8248    pub fn max_point(&self, cx: &mut AppContext) -> DisplayPoint {
 8249        self.display_map
 8250            .update(cx, |map, cx| map.snapshot(cx))
 8251            .max_point()
 8252    }
 8253
 8254    pub fn text(&self, cx: &AppContext) -> String {
 8255        self.buffer.read(cx).read(cx).text()
 8256    }
 8257
 8258    pub fn text_option(&self, cx: &AppContext) -> Option<String> {
 8259        let text = self.text(cx);
 8260        let text = text.trim();
 8261
 8262        if text.is_empty() {
 8263            return None;
 8264        }
 8265
 8266        Some(text.to_string())
 8267    }
 8268
 8269    pub fn set_text(&mut self, text: impl Into<Arc<str>>, cx: &mut ViewContext<Self>) {
 8270        self.transact(cx, |this, cx| {
 8271            this.buffer
 8272                .read(cx)
 8273                .as_singleton()
 8274                .expect("you can only call set_text on editors for singleton buffers")
 8275                .update(cx, |buffer, cx| buffer.set_text(text, cx));
 8276        });
 8277    }
 8278
 8279    pub fn display_text(&self, cx: &mut AppContext) -> String {
 8280        self.display_map
 8281            .update(cx, |map, cx| map.snapshot(cx))
 8282            .text()
 8283    }
 8284
 8285    pub fn wrap_guides(&self, cx: &AppContext) -> SmallVec<[(usize, bool); 2]> {
 8286        let mut wrap_guides = smallvec::smallvec![];
 8287
 8288        if self.show_wrap_guides == Some(false) {
 8289            return wrap_guides;
 8290        }
 8291
 8292        let settings = self.buffer.read(cx).settings_at(0, cx);
 8293        if settings.show_wrap_guides {
 8294            if let SoftWrap::Column(soft_wrap) = self.soft_wrap_mode(cx) {
 8295                wrap_guides.push((soft_wrap as usize, true));
 8296            }
 8297            wrap_guides.extend(settings.wrap_guides.iter().map(|guide| (*guide, false)))
 8298        }
 8299
 8300        wrap_guides
 8301    }
 8302
 8303    pub fn soft_wrap_mode(&self, cx: &AppContext) -> SoftWrap {
 8304        let settings = self.buffer.read(cx).settings_at(0, cx);
 8305        let mode = self
 8306            .soft_wrap_mode_override
 8307            .unwrap_or_else(|| settings.soft_wrap);
 8308        match mode {
 8309            language_settings::SoftWrap::None => SoftWrap::None,
 8310            language_settings::SoftWrap::EditorWidth => SoftWrap::EditorWidth,
 8311            language_settings::SoftWrap::PreferredLineLength => {
 8312                SoftWrap::Column(settings.preferred_line_length)
 8313            }
 8314        }
 8315    }
 8316
 8317    pub fn set_soft_wrap_mode(
 8318        &mut self,
 8319        mode: language_settings::SoftWrap,
 8320        cx: &mut ViewContext<Self>,
 8321    ) {
 8322        self.soft_wrap_mode_override = Some(mode);
 8323        cx.notify();
 8324    }
 8325
 8326    pub fn set_style(&mut self, style: EditorStyle, cx: &mut ViewContext<Self>) {
 8327        let rem_size = cx.rem_size();
 8328        self.display_map.update(cx, |map, cx| {
 8329            map.set_font(
 8330                style.text.font(),
 8331                style.text.font_size.to_pixels(rem_size),
 8332                cx,
 8333            )
 8334        });
 8335        self.style = Some(style);
 8336    }
 8337
 8338    #[cfg(any(test, feature = "test-support"))]
 8339    pub fn style(&self) -> Option<&EditorStyle> {
 8340        self.style.as_ref()
 8341    }
 8342
 8343    // Called by the element. This method is not designed to be called outside of the editor
 8344    // element's layout code because it does not notify when rewrapping is computed synchronously.
 8345    pub(crate) fn set_wrap_width(&self, width: Option<Pixels>, cx: &mut AppContext) -> bool {
 8346        self.display_map
 8347            .update(cx, |map, cx| map.set_wrap_width(width, cx))
 8348    }
 8349
 8350    pub fn toggle_soft_wrap(&mut self, _: &ToggleSoftWrap, cx: &mut ViewContext<Self>) {
 8351        if self.soft_wrap_mode_override.is_some() {
 8352            self.soft_wrap_mode_override.take();
 8353        } else {
 8354            let soft_wrap = match self.soft_wrap_mode(cx) {
 8355                SoftWrap::None => language_settings::SoftWrap::EditorWidth,
 8356                SoftWrap::EditorWidth | SoftWrap::Column(_) => language_settings::SoftWrap::None,
 8357            };
 8358            self.soft_wrap_mode_override = Some(soft_wrap);
 8359        }
 8360        cx.notify();
 8361    }
 8362
 8363    pub fn set_show_gutter(&mut self, show_gutter: bool, cx: &mut ViewContext<Self>) {
 8364        self.show_gutter = show_gutter;
 8365        cx.notify();
 8366    }
 8367
 8368    pub fn set_show_wrap_guides(&mut self, show_gutter: bool, cx: &mut ViewContext<Self>) {
 8369        self.show_wrap_guides = Some(show_gutter);
 8370        cx.notify();
 8371    }
 8372
 8373    pub fn reveal_in_finder(&mut self, _: &RevealInFinder, cx: &mut ViewContext<Self>) {
 8374        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
 8375            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
 8376                cx.reveal_path(&file.abs_path(cx));
 8377            }
 8378        }
 8379    }
 8380
 8381    pub fn copy_path(&mut self, _: &CopyPath, cx: &mut ViewContext<Self>) {
 8382        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
 8383            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
 8384                if let Some(path) = file.abs_path(cx).to_str() {
 8385                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
 8386                }
 8387            }
 8388        }
 8389    }
 8390
 8391    pub fn copy_relative_path(&mut self, _: &CopyRelativePath, cx: &mut ViewContext<Self>) {
 8392        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
 8393            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
 8394                if let Some(path) = file.path().to_str() {
 8395                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
 8396                }
 8397            }
 8398        }
 8399    }
 8400
 8401    fn get_permalink_to_line(&mut self, cx: &mut ViewContext<Self>) -> Result<url::Url> {
 8402        use git::permalink::{build_permalink, BuildPermalinkParams};
 8403
 8404        let project = self.project.clone().ok_or_else(|| anyhow!("no project"))?;
 8405        let project = project.read(cx);
 8406
 8407        let worktree = project
 8408            .visible_worktrees(cx)
 8409            .next()
 8410            .ok_or_else(|| anyhow!("no worktree"))?;
 8411
 8412        let mut cwd = worktree.read(cx).abs_path().to_path_buf();
 8413        cwd.push(".git");
 8414
 8415        const REMOTE_NAME: &'static str = "origin";
 8416        let repo = project
 8417            .fs()
 8418            .open_repo(&cwd)
 8419            .ok_or_else(|| anyhow!("no Git repo"))?;
 8420        let origin_url = repo
 8421            .lock()
 8422            .remote_url(REMOTE_NAME)
 8423            .ok_or_else(|| anyhow!("remote \"{REMOTE_NAME}\" not found"))?;
 8424        let sha = repo
 8425            .lock()
 8426            .head_sha()
 8427            .ok_or_else(|| anyhow!("failed to read HEAD SHA"))?;
 8428
 8429        let path = maybe!({
 8430            let buffer = self.buffer().read(cx).as_singleton()?;
 8431            let file = buffer.read(cx).file().and_then(|f| f.as_local())?;
 8432            file.path().to_str().map(|path| path.to_string())
 8433        })
 8434        .ok_or_else(|| anyhow!("failed to determine file path"))?;
 8435
 8436        let selections = self.selections.all::<Point>(cx);
 8437        let selection = selections.iter().peekable().next();
 8438
 8439        build_permalink(BuildPermalinkParams {
 8440            remote_url: &origin_url,
 8441            sha: &sha,
 8442            path: &path,
 8443            selection: selection.map(|selection| selection.range()),
 8444        })
 8445    }
 8446
 8447    pub fn copy_permalink_to_line(&mut self, _: &CopyPermalinkToLine, cx: &mut ViewContext<Self>) {
 8448        let permalink = self.get_permalink_to_line(cx);
 8449
 8450        match permalink {
 8451            Ok(permalink) => {
 8452                cx.write_to_clipboard(ClipboardItem::new(permalink.to_string()));
 8453            }
 8454            Err(err) => {
 8455                let message = format!("Failed to copy permalink: {err}");
 8456
 8457                Err::<(), anyhow::Error>(err).log_err();
 8458
 8459                if let Some(workspace) = self.workspace() {
 8460                    workspace.update(cx, |workspace, cx| {
 8461                        workspace.show_toast(Toast::new(0x156a5f9ee, message), cx)
 8462                    })
 8463                }
 8464            }
 8465        }
 8466    }
 8467
 8468    pub fn open_permalink_to_line(&mut self, _: &OpenPermalinkToLine, cx: &mut ViewContext<Self>) {
 8469        let permalink = self.get_permalink_to_line(cx);
 8470
 8471        match permalink {
 8472            Ok(permalink) => {
 8473                cx.open_url(&permalink.to_string());
 8474            }
 8475            Err(err) => {
 8476                let message = format!("Failed to open permalink: {err}");
 8477
 8478                Err::<(), anyhow::Error>(err).log_err();
 8479
 8480                if let Some(workspace) = self.workspace() {
 8481                    workspace.update(cx, |workspace, cx| {
 8482                        workspace.show_toast(Toast::new(0x45a8978, message), cx)
 8483                    })
 8484                }
 8485            }
 8486        }
 8487    }
 8488
 8489    pub fn highlight_rows(&mut self, rows: Option<Range<u32>>) {
 8490        self.highlighted_rows = rows;
 8491    }
 8492
 8493    pub fn highlighted_rows(&self) -> Option<Range<u32>> {
 8494        self.highlighted_rows.clone()
 8495    }
 8496
 8497    pub fn highlight_background<T: 'static>(
 8498        &mut self,
 8499        ranges: Vec<Range<Anchor>>,
 8500        color_fetcher: fn(&ThemeColors) -> Hsla,
 8501        cx: &mut ViewContext<Self>,
 8502    ) {
 8503        self.background_highlights
 8504            .insert(TypeId::of::<T>(), (color_fetcher, ranges));
 8505        cx.notify();
 8506    }
 8507
 8508    pub(crate) fn highlight_inlay_background<T: 'static>(
 8509        &mut self,
 8510        ranges: Vec<InlayHighlight>,
 8511        color_fetcher: fn(&ThemeColors) -> Hsla,
 8512        cx: &mut ViewContext<Self>,
 8513    ) {
 8514        // TODO: no actual highlights happen for inlays currently, find a way to do that
 8515        self.inlay_background_highlights
 8516            .insert(Some(TypeId::of::<T>()), (color_fetcher, ranges));
 8517        cx.notify();
 8518    }
 8519
 8520    pub fn clear_background_highlights<T: 'static>(
 8521        &mut self,
 8522        cx: &mut ViewContext<Self>,
 8523    ) -> Option<BackgroundHighlight> {
 8524        let text_highlights = self.background_highlights.remove(&TypeId::of::<T>());
 8525        let inlay_highlights = self
 8526            .inlay_background_highlights
 8527            .remove(&Some(TypeId::of::<T>()));
 8528        if text_highlights.is_some() || inlay_highlights.is_some() {
 8529            cx.notify();
 8530        }
 8531        text_highlights
 8532    }
 8533
 8534    #[cfg(feature = "test-support")]
 8535    pub fn all_text_background_highlights(
 8536        &mut self,
 8537        cx: &mut ViewContext<Self>,
 8538    ) -> Vec<(Range<DisplayPoint>, Hsla)> {
 8539        let snapshot = self.snapshot(cx);
 8540        let buffer = &snapshot.buffer_snapshot;
 8541        let start = buffer.anchor_before(0);
 8542        let end = buffer.anchor_after(buffer.len());
 8543        let theme = cx.theme().colors();
 8544        self.background_highlights_in_range(start..end, &snapshot, theme)
 8545    }
 8546
 8547    fn document_highlights_for_position<'a>(
 8548        &'a self,
 8549        position: Anchor,
 8550        buffer: &'a MultiBufferSnapshot,
 8551    ) -> impl 'a + Iterator<Item = &Range<Anchor>> {
 8552        let read_highlights = self
 8553            .background_highlights
 8554            .get(&TypeId::of::<DocumentHighlightRead>())
 8555            .map(|h| &h.1);
 8556        let write_highlights = self
 8557            .background_highlights
 8558            .get(&TypeId::of::<DocumentHighlightWrite>())
 8559            .map(|h| &h.1);
 8560        let left_position = position.bias_left(buffer);
 8561        let right_position = position.bias_right(buffer);
 8562        read_highlights
 8563            .into_iter()
 8564            .chain(write_highlights)
 8565            .flat_map(move |ranges| {
 8566                let start_ix = match ranges.binary_search_by(|probe| {
 8567                    let cmp = probe.end.cmp(&left_position, buffer);
 8568                    if cmp.is_ge() {
 8569                        Ordering::Greater
 8570                    } else {
 8571                        Ordering::Less
 8572                    }
 8573                }) {
 8574                    Ok(i) | Err(i) => i,
 8575                };
 8576
 8577                let right_position = right_position.clone();
 8578                ranges[start_ix..]
 8579                    .iter()
 8580                    .take_while(move |range| range.start.cmp(&right_position, buffer).is_le())
 8581            })
 8582    }
 8583
 8584    pub fn has_background_highlights<T: 'static>(&self) -> bool {
 8585        self.background_highlights
 8586            .get(&TypeId::of::<T>())
 8587            .map_or(false, |(_, highlights)| !highlights.is_empty())
 8588    }
 8589
 8590    pub fn background_highlights_in_range(
 8591        &self,
 8592        search_range: Range<Anchor>,
 8593        display_snapshot: &DisplaySnapshot,
 8594        theme: &ThemeColors,
 8595    ) -> Vec<(Range<DisplayPoint>, Hsla)> {
 8596        let mut results = Vec::new();
 8597        for (color_fetcher, ranges) in self.background_highlights.values() {
 8598            let color = color_fetcher(theme);
 8599            let start_ix = match ranges.binary_search_by(|probe| {
 8600                let cmp = probe
 8601                    .end
 8602                    .cmp(&search_range.start, &display_snapshot.buffer_snapshot);
 8603                if cmp.is_gt() {
 8604                    Ordering::Greater
 8605                } else {
 8606                    Ordering::Less
 8607                }
 8608            }) {
 8609                Ok(i) | Err(i) => i,
 8610            };
 8611            for range in &ranges[start_ix..] {
 8612                if range
 8613                    .start
 8614                    .cmp(&search_range.end, &display_snapshot.buffer_snapshot)
 8615                    .is_ge()
 8616                {
 8617                    break;
 8618                }
 8619
 8620                let start = range.start.to_display_point(&display_snapshot);
 8621                let end = range.end.to_display_point(&display_snapshot);
 8622                results.push((start..end, color))
 8623            }
 8624        }
 8625        results
 8626    }
 8627
 8628    pub fn background_highlight_row_ranges<T: 'static>(
 8629        &self,
 8630        search_range: Range<Anchor>,
 8631        display_snapshot: &DisplaySnapshot,
 8632        count: usize,
 8633    ) -> Vec<RangeInclusive<DisplayPoint>> {
 8634        let mut results = Vec::new();
 8635        let Some((_, ranges)) = self.background_highlights.get(&TypeId::of::<T>()) else {
 8636            return vec![];
 8637        };
 8638
 8639        let start_ix = match ranges.binary_search_by(|probe| {
 8640            let cmp = probe
 8641                .end
 8642                .cmp(&search_range.start, &display_snapshot.buffer_snapshot);
 8643            if cmp.is_gt() {
 8644                Ordering::Greater
 8645            } else {
 8646                Ordering::Less
 8647            }
 8648        }) {
 8649            Ok(i) | Err(i) => i,
 8650        };
 8651        let mut push_region = |start: Option<Point>, end: Option<Point>| {
 8652            if let (Some(start_display), Some(end_display)) = (start, end) {
 8653                results.push(
 8654                    start_display.to_display_point(display_snapshot)
 8655                        ..=end_display.to_display_point(display_snapshot),
 8656                );
 8657            }
 8658        };
 8659        let mut start_row: Option<Point> = None;
 8660        let mut end_row: Option<Point> = None;
 8661        if ranges.len() > count {
 8662            return Vec::new();
 8663        }
 8664        for range in &ranges[start_ix..] {
 8665            if range
 8666                .start
 8667                .cmp(&search_range.end, &display_snapshot.buffer_snapshot)
 8668                .is_ge()
 8669            {
 8670                break;
 8671            }
 8672            let end = range.end.to_point(&display_snapshot.buffer_snapshot);
 8673            if let Some(current_row) = &end_row {
 8674                if end.row == current_row.row {
 8675                    continue;
 8676                }
 8677            }
 8678            let start = range.start.to_point(&display_snapshot.buffer_snapshot);
 8679            if start_row.is_none() {
 8680                assert_eq!(end_row, None);
 8681                start_row = Some(start);
 8682                end_row = Some(end);
 8683                continue;
 8684            }
 8685            if let Some(current_end) = end_row.as_mut() {
 8686                if start.row > current_end.row + 1 {
 8687                    push_region(start_row, end_row);
 8688                    start_row = Some(start);
 8689                    end_row = Some(end);
 8690                } else {
 8691                    // Merge two hunks.
 8692                    *current_end = end;
 8693                }
 8694            } else {
 8695                unreachable!();
 8696            }
 8697        }
 8698        // We might still have a hunk that was not rendered (if there was a search hit on the last line)
 8699        push_region(start_row, end_row);
 8700        results
 8701    }
 8702
 8703    /// Get the text ranges corresponding to the redaction query
 8704    pub fn redacted_ranges(
 8705        &self,
 8706        search_range: Range<Anchor>,
 8707        display_snapshot: &DisplaySnapshot,
 8708        cx: &mut ViewContext<Self>,
 8709    ) -> Vec<Range<DisplayPoint>> {
 8710        display_snapshot
 8711            .buffer_snapshot
 8712            .redacted_ranges(search_range, |file| {
 8713                if let Some(file) = file {
 8714                    file.is_private()
 8715                        && EditorSettings::get(Some((file.worktree_id(), file.path())), cx)
 8716                            .redact_private_values
 8717                } else {
 8718                    false
 8719                }
 8720            })
 8721            .map(|range| {
 8722                range.start.to_display_point(display_snapshot)
 8723                    ..range.end.to_display_point(display_snapshot)
 8724            })
 8725            .collect()
 8726    }
 8727
 8728    pub fn highlight_text<T: 'static>(
 8729        &mut self,
 8730        ranges: Vec<Range<Anchor>>,
 8731        style: HighlightStyle,
 8732        cx: &mut ViewContext<Self>,
 8733    ) {
 8734        self.display_map.update(cx, |map, _| {
 8735            map.highlight_text(TypeId::of::<T>(), ranges, style)
 8736        });
 8737        cx.notify();
 8738    }
 8739
 8740    pub(crate) fn highlight_inlays<T: 'static>(
 8741        &mut self,
 8742        highlights: Vec<InlayHighlight>,
 8743        style: HighlightStyle,
 8744        cx: &mut ViewContext<Self>,
 8745    ) {
 8746        self.display_map.update(cx, |map, _| {
 8747            map.highlight_inlays(TypeId::of::<T>(), highlights, style)
 8748        });
 8749        cx.notify();
 8750    }
 8751
 8752    pub fn text_highlights<'a, T: 'static>(
 8753        &'a self,
 8754        cx: &'a AppContext,
 8755    ) -> Option<(HighlightStyle, &'a [Range<Anchor>])> {
 8756        self.display_map.read(cx).text_highlights(TypeId::of::<T>())
 8757    }
 8758
 8759    pub fn clear_highlights<T: 'static>(&mut self, cx: &mut ViewContext<Self>) {
 8760        let cleared = self
 8761            .display_map
 8762            .update(cx, |map, _| map.clear_highlights(TypeId::of::<T>()));
 8763        if cleared {
 8764            cx.notify();
 8765        }
 8766    }
 8767
 8768    pub fn show_local_cursors(&self, cx: &WindowContext) -> bool {
 8769        (self.read_only(cx) || self.blink_manager.read(cx).visible())
 8770            && self.focus_handle.is_focused(cx)
 8771    }
 8772
 8773    fn on_buffer_changed(&mut self, _: Model<MultiBuffer>, cx: &mut ViewContext<Self>) {
 8774        cx.notify();
 8775    }
 8776
 8777    fn on_buffer_event(
 8778        &mut self,
 8779        multibuffer: Model<MultiBuffer>,
 8780        event: &multi_buffer::Event,
 8781        cx: &mut ViewContext<Self>,
 8782    ) {
 8783        match event {
 8784            multi_buffer::Event::Edited {
 8785                singleton_buffer_edited,
 8786            } => {
 8787                self.refresh_active_diagnostics(cx);
 8788                self.refresh_code_actions(cx);
 8789                if self.has_active_copilot_suggestion(cx) {
 8790                    self.update_visible_copilot_suggestion(cx);
 8791                }
 8792                cx.emit(EditorEvent::BufferEdited);
 8793                cx.emit(SearchEvent::MatchesInvalidated);
 8794
 8795                if *singleton_buffer_edited {
 8796                    if let Some(project) = &self.project {
 8797                        let project = project.read(cx);
 8798                        let languages_affected = multibuffer
 8799                            .read(cx)
 8800                            .all_buffers()
 8801                            .into_iter()
 8802                            .filter_map(|buffer| {
 8803                                let buffer = buffer.read(cx);
 8804                                let language = buffer.language()?;
 8805                                if project.is_local()
 8806                                    && project.language_servers_for_buffer(buffer, cx).count() == 0
 8807                                {
 8808                                    None
 8809                                } else {
 8810                                    Some(language)
 8811                                }
 8812                            })
 8813                            .cloned()
 8814                            .collect::<HashSet<_>>();
 8815                        if !languages_affected.is_empty() {
 8816                            self.refresh_inlay_hints(
 8817                                InlayHintRefreshReason::BufferEdited(languages_affected),
 8818                                cx,
 8819                            );
 8820                        }
 8821                    }
 8822                }
 8823
 8824                let Some(project) = &self.project else { return };
 8825                let telemetry = project.read(cx).client().telemetry().clone();
 8826                telemetry.log_edit_event("editor");
 8827            }
 8828            multi_buffer::Event::ExcerptsAdded {
 8829                buffer,
 8830                predecessor,
 8831                excerpts,
 8832            } => {
 8833                cx.emit(EditorEvent::ExcerptsAdded {
 8834                    buffer: buffer.clone(),
 8835                    predecessor: *predecessor,
 8836                    excerpts: excerpts.clone(),
 8837                });
 8838                self.refresh_inlay_hints(InlayHintRefreshReason::NewLinesShown, cx);
 8839            }
 8840            multi_buffer::Event::ExcerptsRemoved { ids } => {
 8841                self.refresh_inlay_hints(InlayHintRefreshReason::ExcerptsRemoved(ids.clone()), cx);
 8842                cx.emit(EditorEvent::ExcerptsRemoved { ids: ids.clone() })
 8843            }
 8844            multi_buffer::Event::Reparsed => cx.emit(EditorEvent::Reparsed),
 8845            multi_buffer::Event::LanguageChanged => {
 8846                cx.emit(EditorEvent::Reparsed);
 8847                cx.notify();
 8848            }
 8849            multi_buffer::Event::DirtyChanged => cx.emit(EditorEvent::DirtyChanged),
 8850            multi_buffer::Event::Saved => cx.emit(EditorEvent::Saved),
 8851            multi_buffer::Event::FileHandleChanged | multi_buffer::Event::Reloaded => {
 8852                cx.emit(EditorEvent::TitleChanged)
 8853            }
 8854            multi_buffer::Event::DiffBaseChanged => cx.emit(EditorEvent::DiffBaseChanged),
 8855            multi_buffer::Event::Closed => cx.emit(EditorEvent::Closed),
 8856            multi_buffer::Event::DiagnosticsUpdated => {
 8857                self.refresh_active_diagnostics(cx);
 8858            }
 8859            _ => {}
 8860        };
 8861    }
 8862
 8863    fn on_display_map_changed(&mut self, _: Model<DisplayMap>, cx: &mut ViewContext<Self>) {
 8864        cx.notify();
 8865    }
 8866
 8867    fn settings_changed(&mut self, cx: &mut ViewContext<Self>) {
 8868        self.refresh_copilot_suggestions(true, cx);
 8869        self.refresh_inlay_hints(
 8870            InlayHintRefreshReason::SettingsChange(inlay_hint_settings(
 8871                self.selections.newest_anchor().head(),
 8872                &self.buffer.read(cx).snapshot(cx),
 8873                cx,
 8874            )),
 8875            cx,
 8876        );
 8877        let editor_settings = EditorSettings::get_global(cx);
 8878        self.scroll_manager.vertical_scroll_margin = editor_settings.vertical_scroll_margin;
 8879        self.show_breadcrumbs = editor_settings.toolbar.breadcrumbs;
 8880        cx.notify();
 8881    }
 8882
 8883    pub fn set_searchable(&mut self, searchable: bool) {
 8884        self.searchable = searchable;
 8885    }
 8886
 8887    pub fn searchable(&self) -> bool {
 8888        self.searchable
 8889    }
 8890
 8891    fn open_excerpts(&mut self, _: &OpenExcerpts, cx: &mut ViewContext<Self>) {
 8892        let buffer = self.buffer.read(cx);
 8893        if buffer.is_singleton() {
 8894            cx.propagate();
 8895            return;
 8896        }
 8897
 8898        let Some(workspace) = self.workspace() else {
 8899            cx.propagate();
 8900            return;
 8901        };
 8902
 8903        let mut new_selections_by_buffer = HashMap::default();
 8904        for selection in self.selections.all::<usize>(cx) {
 8905            for (buffer, mut range, _) in
 8906                buffer.range_to_buffer_ranges(selection.start..selection.end, cx)
 8907            {
 8908                if selection.reversed {
 8909                    mem::swap(&mut range.start, &mut range.end);
 8910                }
 8911                new_selections_by_buffer
 8912                    .entry(buffer)
 8913                    .or_insert(Vec::new())
 8914                    .push(range)
 8915            }
 8916        }
 8917
 8918        self.push_to_nav_history(self.selections.newest_anchor().head(), None, cx);
 8919
 8920        // We defer the pane interaction because we ourselves are a workspace item
 8921        // and activating a new item causes the pane to call a method on us reentrantly,
 8922        // which panics if we're on the stack.
 8923        cx.window_context().defer(move |cx| {
 8924            workspace.update(cx, |workspace, cx| {
 8925                let pane = workspace.active_pane().clone();
 8926                pane.update(cx, |pane, _| pane.disable_history());
 8927
 8928                for (buffer, ranges) in new_selections_by_buffer.into_iter() {
 8929                    let editor = workspace.open_project_item::<Self>(buffer, cx);
 8930                    editor.update(cx, |editor, cx| {
 8931                        editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
 8932                            s.select_ranges(ranges);
 8933                        });
 8934                    });
 8935                }
 8936
 8937                pane.update(cx, |pane, _| pane.enable_history());
 8938            })
 8939        });
 8940    }
 8941
 8942    fn jump(
 8943        &mut self,
 8944        path: ProjectPath,
 8945        position: Point,
 8946        anchor: language::Anchor,
 8947        cx: &mut ViewContext<Self>,
 8948    ) {
 8949        let workspace = self.workspace();
 8950        cx.spawn(|_, mut cx| async move {
 8951            let workspace = workspace.ok_or_else(|| anyhow!("cannot jump without workspace"))?;
 8952            let editor = workspace.update(&mut cx, |workspace, cx| {
 8953                workspace.open_path(path, None, true, cx)
 8954            })?;
 8955            let editor = editor
 8956                .await?
 8957                .downcast::<Editor>()
 8958                .ok_or_else(|| anyhow!("opened item was not an editor"))?
 8959                .downgrade();
 8960            editor.update(&mut cx, |editor, cx| {
 8961                let buffer = editor
 8962                    .buffer()
 8963                    .read(cx)
 8964                    .as_singleton()
 8965                    .ok_or_else(|| anyhow!("cannot jump in a multi-buffer"))?;
 8966                let buffer = buffer.read(cx);
 8967                let cursor = if buffer.can_resolve(&anchor) {
 8968                    language::ToPoint::to_point(&anchor, buffer)
 8969                } else {
 8970                    buffer.clip_point(position, Bias::Left)
 8971                };
 8972
 8973                let nav_history = editor.nav_history.take();
 8974                editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
 8975                    s.select_ranges([cursor..cursor]);
 8976                });
 8977                editor.nav_history = nav_history;
 8978
 8979                anyhow::Ok(())
 8980            })??;
 8981
 8982            anyhow::Ok(())
 8983        })
 8984        .detach_and_log_err(cx);
 8985    }
 8986
 8987    fn marked_text_ranges(&self, cx: &AppContext) -> Option<Vec<Range<OffsetUtf16>>> {
 8988        let snapshot = self.buffer.read(cx).read(cx);
 8989        let (_, ranges) = self.text_highlights::<InputComposition>(cx)?;
 8990        Some(
 8991            ranges
 8992                .iter()
 8993                .map(move |range| {
 8994                    range.start.to_offset_utf16(&snapshot)..range.end.to_offset_utf16(&snapshot)
 8995                })
 8996                .collect(),
 8997        )
 8998    }
 8999
 9000    fn selection_replacement_ranges(
 9001        &self,
 9002        range: Range<OffsetUtf16>,
 9003        cx: &AppContext,
 9004    ) -> Vec<Range<OffsetUtf16>> {
 9005        let selections = self.selections.all::<OffsetUtf16>(cx);
 9006        let newest_selection = selections
 9007            .iter()
 9008            .max_by_key(|selection| selection.id)
 9009            .unwrap();
 9010        let start_delta = range.start.0 as isize - newest_selection.start.0 as isize;
 9011        let end_delta = range.end.0 as isize - newest_selection.end.0 as isize;
 9012        let snapshot = self.buffer.read(cx).read(cx);
 9013        selections
 9014            .into_iter()
 9015            .map(|mut selection| {
 9016                selection.start.0 =
 9017                    (selection.start.0 as isize).saturating_add(start_delta) as usize;
 9018                selection.end.0 = (selection.end.0 as isize).saturating_add(end_delta) as usize;
 9019                snapshot.clip_offset_utf16(selection.start, Bias::Left)
 9020                    ..snapshot.clip_offset_utf16(selection.end, Bias::Right)
 9021            })
 9022            .collect()
 9023    }
 9024
 9025    fn report_copilot_event(
 9026        &self,
 9027        suggestion_id: Option<String>,
 9028        suggestion_accepted: bool,
 9029        cx: &AppContext,
 9030    ) {
 9031        let Some(project) = &self.project else { return };
 9032
 9033        // If None, we are either getting suggestions in a new, unsaved file, or in a file without an extension
 9034        let file_extension = self
 9035            .buffer
 9036            .read(cx)
 9037            .as_singleton()
 9038            .and_then(|b| b.read(cx).file())
 9039            .and_then(|file| Path::new(file.file_name(cx)).extension())
 9040            .and_then(|e| e.to_str())
 9041            .map(|a| a.to_string());
 9042
 9043        let telemetry = project.read(cx).client().telemetry().clone();
 9044
 9045        telemetry.report_copilot_event(suggestion_id, suggestion_accepted, file_extension)
 9046    }
 9047
 9048    #[cfg(any(test, feature = "test-support"))]
 9049    fn report_editor_event(
 9050        &self,
 9051        _operation: &'static str,
 9052        _file_extension: Option<String>,
 9053        _cx: &AppContext,
 9054    ) {
 9055    }
 9056
 9057    #[cfg(not(any(test, feature = "test-support")))]
 9058    fn report_editor_event(
 9059        &self,
 9060        operation: &'static str,
 9061        file_extension: Option<String>,
 9062        cx: &AppContext,
 9063    ) {
 9064        let Some(project) = &self.project else { return };
 9065
 9066        // If None, we are in a file without an extension
 9067        let file = self
 9068            .buffer
 9069            .read(cx)
 9070            .as_singleton()
 9071            .and_then(|b| b.read(cx).file());
 9072        let file_extension = file_extension.or(file
 9073            .as_ref()
 9074            .and_then(|file| Path::new(file.file_name(cx)).extension())
 9075            .and_then(|e| e.to_str())
 9076            .map(|a| a.to_string()));
 9077
 9078        let vim_mode = cx
 9079            .global::<SettingsStore>()
 9080            .raw_user_settings()
 9081            .get("vim_mode")
 9082            == Some(&serde_json::Value::Bool(true));
 9083        let copilot_enabled = all_language_settings(file, cx).copilot_enabled(None, None);
 9084        let copilot_enabled_for_language = self
 9085            .buffer
 9086            .read(cx)
 9087            .settings_at(0, cx)
 9088            .show_copilot_suggestions;
 9089
 9090        let telemetry = project.read(cx).client().telemetry().clone();
 9091        telemetry.report_editor_event(
 9092            file_extension,
 9093            vim_mode,
 9094            operation,
 9095            copilot_enabled,
 9096            copilot_enabled_for_language,
 9097        )
 9098    }
 9099
 9100    /// Copy the highlighted chunks to the clipboard as JSON. The format is an array of lines,
 9101    /// with each line being an array of {text, highlight} objects.
 9102    fn copy_highlight_json(&mut self, _: &CopyHighlightJson, cx: &mut ViewContext<Self>) {
 9103        let Some(buffer) = self.buffer.read(cx).as_singleton() else {
 9104            return;
 9105        };
 9106
 9107        #[derive(Serialize)]
 9108        struct Chunk<'a> {
 9109            text: String,
 9110            highlight: Option<&'a str>,
 9111        }
 9112
 9113        let snapshot = buffer.read(cx).snapshot();
 9114        let range = self
 9115            .selected_text_range(cx)
 9116            .and_then(|selected_range| {
 9117                if selected_range.is_empty() {
 9118                    None
 9119                } else {
 9120                    Some(selected_range)
 9121                }
 9122            })
 9123            .unwrap_or_else(|| 0..snapshot.len());
 9124
 9125        let chunks = snapshot.chunks(range, true);
 9126        let mut lines = Vec::new();
 9127        let mut line: VecDeque<Chunk> = VecDeque::new();
 9128
 9129        let Some(style) = self.style.as_ref() else {
 9130            return;
 9131        };
 9132
 9133        for chunk in chunks {
 9134            let highlight = chunk
 9135                .syntax_highlight_id
 9136                .and_then(|id| id.name(&style.syntax));
 9137            let mut chunk_lines = chunk.text.split("\n").peekable();
 9138            while let Some(text) = chunk_lines.next() {
 9139                let mut merged_with_last_token = false;
 9140                if let Some(last_token) = line.back_mut() {
 9141                    if last_token.highlight == highlight {
 9142                        last_token.text.push_str(text);
 9143                        merged_with_last_token = true;
 9144                    }
 9145                }
 9146
 9147                if !merged_with_last_token {
 9148                    line.push_back(Chunk {
 9149                        text: text.into(),
 9150                        highlight,
 9151                    });
 9152                }
 9153
 9154                if chunk_lines.peek().is_some() {
 9155                    if line.len() > 1 && line.front().unwrap().text.is_empty() {
 9156                        line.pop_front();
 9157                    }
 9158                    if line.len() > 1 && line.back().unwrap().text.is_empty() {
 9159                        line.pop_back();
 9160                    }
 9161
 9162                    lines.push(mem::take(&mut line));
 9163                }
 9164            }
 9165        }
 9166
 9167        let Some(lines) = serde_json::to_string_pretty(&lines).log_err() else {
 9168            return;
 9169        };
 9170        cx.write_to_clipboard(ClipboardItem::new(lines));
 9171    }
 9172
 9173    pub fn inlay_hint_cache(&self) -> &InlayHintCache {
 9174        &self.inlay_hint_cache
 9175    }
 9176
 9177    pub fn replay_insert_event(
 9178        &mut self,
 9179        text: &str,
 9180        relative_utf16_range: Option<Range<isize>>,
 9181        cx: &mut ViewContext<Self>,
 9182    ) {
 9183        if !self.input_enabled {
 9184            cx.emit(EditorEvent::InputIgnored { text: text.into() });
 9185            return;
 9186        }
 9187        if let Some(relative_utf16_range) = relative_utf16_range {
 9188            let selections = self.selections.all::<OffsetUtf16>(cx);
 9189            self.change_selections(None, cx, |s| {
 9190                let new_ranges = selections.into_iter().map(|range| {
 9191                    let start = OffsetUtf16(
 9192                        range
 9193                            .head()
 9194                            .0
 9195                            .saturating_add_signed(relative_utf16_range.start),
 9196                    );
 9197                    let end = OffsetUtf16(
 9198                        range
 9199                            .head()
 9200                            .0
 9201                            .saturating_add_signed(relative_utf16_range.end),
 9202                    );
 9203                    start..end
 9204                });
 9205                s.select_ranges(new_ranges);
 9206            });
 9207        }
 9208
 9209        self.handle_input(text, cx);
 9210    }
 9211
 9212    pub fn supports_inlay_hints(&self, cx: &AppContext) -> bool {
 9213        let Some(project) = self.project.as_ref() else {
 9214            return false;
 9215        };
 9216        let project = project.read(cx);
 9217
 9218        let mut supports = false;
 9219        self.buffer().read(cx).for_each_buffer(|buffer| {
 9220            if !supports {
 9221                supports = project
 9222                    .language_servers_for_buffer(buffer.read(cx), cx)
 9223                    .any(
 9224                        |(_, server)| match server.capabilities().inlay_hint_provider {
 9225                            Some(lsp::OneOf::Left(enabled)) => enabled,
 9226                            Some(lsp::OneOf::Right(_)) => true,
 9227                            None => false,
 9228                        },
 9229                    )
 9230            }
 9231        });
 9232        supports
 9233    }
 9234
 9235    pub fn focus(&self, cx: &mut WindowContext) {
 9236        cx.focus(&self.focus_handle)
 9237    }
 9238
 9239    pub fn is_focused(&self, cx: &WindowContext) -> bool {
 9240        self.focus_handle.is_focused(cx)
 9241    }
 9242
 9243    fn handle_focus(&mut self, cx: &mut ViewContext<Self>) {
 9244        cx.emit(EditorEvent::Focused);
 9245
 9246        if let Some(rename) = self.pending_rename.as_ref() {
 9247            let rename_editor_focus_handle = rename.editor.read(cx).focus_handle.clone();
 9248            cx.focus(&rename_editor_focus_handle);
 9249        } else {
 9250            self.blink_manager.update(cx, BlinkManager::enable);
 9251            self.show_cursor_names(cx);
 9252            self.buffer.update(cx, |buffer, cx| {
 9253                buffer.finalize_last_transaction(cx);
 9254                if self.leader_peer_id.is_none() {
 9255                    buffer.set_active_selections(
 9256                        &self.selections.disjoint_anchors(),
 9257                        self.selections.line_mode,
 9258                        self.cursor_shape,
 9259                        cx,
 9260                    );
 9261                }
 9262            });
 9263        }
 9264    }
 9265
 9266    pub fn handle_blur(&mut self, cx: &mut ViewContext<Self>) {
 9267        self.blink_manager.update(cx, BlinkManager::disable);
 9268        self.buffer
 9269            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
 9270        self.hide_context_menu(cx);
 9271        hide_hover(self, cx);
 9272        cx.emit(EditorEvent::Blurred);
 9273        cx.notify();
 9274    }
 9275
 9276    pub fn register_action<A: Action>(
 9277        &mut self,
 9278        listener: impl Fn(&A, &mut WindowContext) + 'static,
 9279    ) -> &mut Self {
 9280        let listener = Arc::new(listener);
 9281
 9282        self.editor_actions.push(Box::new(move |cx| {
 9283            let _view = cx.view().clone();
 9284            let cx = cx.window_context();
 9285            let listener = listener.clone();
 9286            cx.on_action(TypeId::of::<A>(), move |action, phase, cx| {
 9287                let action = action.downcast_ref().unwrap();
 9288                if phase == DispatchPhase::Bubble {
 9289                    listener(action, cx)
 9290                }
 9291            })
 9292        }));
 9293        self
 9294    }
 9295}
 9296
 9297pub trait CollaborationHub {
 9298    fn collaborators<'a>(&self, cx: &'a AppContext) -> &'a HashMap<PeerId, Collaborator>;
 9299    fn user_participant_indices<'a>(
 9300        &self,
 9301        cx: &'a AppContext,
 9302    ) -> &'a HashMap<u64, ParticipantIndex>;
 9303    fn user_names(&self, cx: &AppContext) -> HashMap<u64, SharedString>;
 9304}
 9305
 9306impl CollaborationHub for Model<Project> {
 9307    fn collaborators<'a>(&self, cx: &'a AppContext) -> &'a HashMap<PeerId, Collaborator> {
 9308        self.read(cx).collaborators()
 9309    }
 9310
 9311    fn user_participant_indices<'a>(
 9312        &self,
 9313        cx: &'a AppContext,
 9314    ) -> &'a HashMap<u64, ParticipantIndex> {
 9315        self.read(cx).user_store().read(cx).participant_indices()
 9316    }
 9317
 9318    fn user_names(&self, cx: &AppContext) -> HashMap<u64, SharedString> {
 9319        let this = self.read(cx);
 9320        let user_ids = this.collaborators().values().map(|c| c.user_id);
 9321        this.user_store().read_with(cx, |user_store, cx| {
 9322            user_store.participant_names(user_ids, cx)
 9323        })
 9324    }
 9325}
 9326
 9327pub trait CompletionProvider {
 9328    fn completions(
 9329        &self,
 9330        buffer: &Model<Buffer>,
 9331        buffer_position: text::Anchor,
 9332        cx: &mut ViewContext<Editor>,
 9333    ) -> Task<Result<Vec<Completion>>>;
 9334
 9335    fn resolve_completions(
 9336        &self,
 9337        completion_indices: Vec<usize>,
 9338        completions: Arc<RwLock<Box<[Completion]>>>,
 9339        cx: &mut ViewContext<Editor>,
 9340    ) -> Task<Result<bool>>;
 9341
 9342    fn apply_additional_edits_for_completion(
 9343        &self,
 9344        buffer: Model<Buffer>,
 9345        completion: Completion,
 9346        push_to_history: bool,
 9347        cx: &mut ViewContext<Editor>,
 9348    ) -> Task<Result<Option<language::Transaction>>>;
 9349}
 9350
 9351impl CompletionProvider for Model<Project> {
 9352    fn completions(
 9353        &self,
 9354        buffer: &Model<Buffer>,
 9355        buffer_position: text::Anchor,
 9356        cx: &mut ViewContext<Editor>,
 9357    ) -> Task<Result<Vec<Completion>>> {
 9358        self.update(cx, |project, cx| {
 9359            project.completions(&buffer, buffer_position, cx)
 9360        })
 9361    }
 9362
 9363    fn resolve_completions(
 9364        &self,
 9365        completion_indices: Vec<usize>,
 9366        completions: Arc<RwLock<Box<[Completion]>>>,
 9367        cx: &mut ViewContext<Editor>,
 9368    ) -> Task<Result<bool>> {
 9369        self.update(cx, |project, cx| {
 9370            project.resolve_completions(completion_indices, completions, cx)
 9371        })
 9372    }
 9373
 9374    fn apply_additional_edits_for_completion(
 9375        &self,
 9376        buffer: Model<Buffer>,
 9377        completion: Completion,
 9378        push_to_history: bool,
 9379        cx: &mut ViewContext<Editor>,
 9380    ) -> Task<Result<Option<language::Transaction>>> {
 9381        self.update(cx, |project, cx| {
 9382            project.apply_additional_edits_for_completion(buffer, completion, push_to_history, cx)
 9383        })
 9384    }
 9385}
 9386
 9387fn inlay_hint_settings(
 9388    location: Anchor,
 9389    snapshot: &MultiBufferSnapshot,
 9390    cx: &mut ViewContext<'_, Editor>,
 9391) -> InlayHintSettings {
 9392    let file = snapshot.file_at(location);
 9393    let language = snapshot.language_at(location);
 9394    let settings = all_language_settings(file, cx);
 9395    settings
 9396        .language(language.map(|l| l.name()).as_deref())
 9397        .inlay_hints
 9398}
 9399
 9400fn consume_contiguous_rows(
 9401    contiguous_row_selections: &mut Vec<Selection<Point>>,
 9402    selection: &Selection<Point>,
 9403    display_map: &DisplaySnapshot,
 9404    selections: &mut std::iter::Peekable<std::slice::Iter<Selection<Point>>>,
 9405) -> (u32, u32) {
 9406    contiguous_row_selections.push(selection.clone());
 9407    let start_row = selection.start.row;
 9408    let mut end_row = ending_row(selection, display_map);
 9409
 9410    while let Some(next_selection) = selections.peek() {
 9411        if next_selection.start.row <= end_row {
 9412            end_row = ending_row(next_selection, display_map);
 9413            contiguous_row_selections.push(selections.next().unwrap().clone());
 9414        } else {
 9415            break;
 9416        }
 9417    }
 9418    (start_row, end_row)
 9419}
 9420
 9421fn ending_row(next_selection: &Selection<Point>, display_map: &DisplaySnapshot) -> u32 {
 9422    if next_selection.end.column > 0 || next_selection.is_empty() {
 9423        display_map.next_line_boundary(next_selection.end).0.row + 1
 9424    } else {
 9425        next_selection.end.row
 9426    }
 9427}
 9428
 9429impl EditorSnapshot {
 9430    pub fn remote_selections_in_range<'a>(
 9431        &'a self,
 9432        range: &'a Range<Anchor>,
 9433        collaboration_hub: &dyn CollaborationHub,
 9434        cx: &'a AppContext,
 9435    ) -> impl 'a + Iterator<Item = RemoteSelection> {
 9436        let participant_names = collaboration_hub.user_names(cx);
 9437        let participant_indices = collaboration_hub.user_participant_indices(cx);
 9438        let collaborators_by_peer_id = collaboration_hub.collaborators(cx);
 9439        let collaborators_by_replica_id = collaborators_by_peer_id
 9440            .iter()
 9441            .map(|(_, collaborator)| (collaborator.replica_id, collaborator))
 9442            .collect::<HashMap<_, _>>();
 9443        self.buffer_snapshot
 9444            .remote_selections_in_range(range)
 9445            .filter_map(move |(replica_id, line_mode, cursor_shape, selection)| {
 9446                let collaborator = collaborators_by_replica_id.get(&replica_id)?;
 9447                let participant_index = participant_indices.get(&collaborator.user_id).copied();
 9448                let user_name = participant_names.get(&collaborator.user_id).cloned();
 9449                Some(RemoteSelection {
 9450                    replica_id,
 9451                    selection,
 9452                    cursor_shape,
 9453                    line_mode,
 9454                    participant_index,
 9455                    peer_id: collaborator.peer_id,
 9456                    user_name,
 9457                })
 9458            })
 9459    }
 9460
 9461    pub fn language_at<T: ToOffset>(&self, position: T) -> Option<&Arc<Language>> {
 9462        self.display_snapshot.buffer_snapshot.language_at(position)
 9463    }
 9464
 9465    pub fn is_focused(&self) -> bool {
 9466        self.is_focused
 9467    }
 9468
 9469    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
 9470        self.placeholder_text.as_ref()
 9471    }
 9472
 9473    pub fn scroll_position(&self) -> gpui::Point<f32> {
 9474        self.scroll_anchor.scroll_position(&self.display_snapshot)
 9475    }
 9476
 9477    pub fn gutter_dimensions(
 9478        &self,
 9479        font_id: FontId,
 9480        font_size: Pixels,
 9481        em_width: Pixels,
 9482        max_line_number_width: Pixels,
 9483        cx: &AppContext,
 9484    ) -> GutterDimensions {
 9485        if self.show_gutter {
 9486            let descent = cx.text_system().descent(font_id, font_size);
 9487            let gutter_padding_factor = 4.0;
 9488            let gutter_padding = (em_width * gutter_padding_factor).round();
 9489            // Avoid flicker-like gutter resizes when the line number gains another digit and only resize the gutter on files with N*10^5 lines.
 9490            let min_width_for_number_on_gutter = em_width * 4.0;
 9491            let gutter_width =
 9492                max_line_number_width.max(min_width_for_number_on_gutter) + gutter_padding * 2.0;
 9493            let gutter_margin = -descent;
 9494
 9495            GutterDimensions {
 9496                padding: gutter_padding,
 9497                width: gutter_width,
 9498                margin: gutter_margin,
 9499            }
 9500        } else {
 9501            GutterDimensions::default()
 9502        }
 9503    }
 9504}
 9505
 9506impl Deref for EditorSnapshot {
 9507    type Target = DisplaySnapshot;
 9508
 9509    fn deref(&self) -> &Self::Target {
 9510        &self.display_snapshot
 9511    }
 9512}
 9513
 9514#[derive(Clone, Debug, PartialEq, Eq)]
 9515pub enum EditorEvent {
 9516    InputIgnored {
 9517        text: Arc<str>,
 9518    },
 9519    InputHandled {
 9520        utf16_range_to_replace: Option<Range<isize>>,
 9521        text: Arc<str>,
 9522    },
 9523    ExcerptsAdded {
 9524        buffer: Model<Buffer>,
 9525        predecessor: ExcerptId,
 9526        excerpts: Vec<(ExcerptId, ExcerptRange<language::Anchor>)>,
 9527    },
 9528    ExcerptsRemoved {
 9529        ids: Vec<ExcerptId>,
 9530    },
 9531    BufferEdited,
 9532    Edited,
 9533    Reparsed,
 9534    Focused,
 9535    Blurred,
 9536    DirtyChanged,
 9537    Saved,
 9538    TitleChanged,
 9539    DiffBaseChanged,
 9540    SelectionsChanged {
 9541        local: bool,
 9542    },
 9543    ScrollPositionChanged {
 9544        local: bool,
 9545        autoscroll: bool,
 9546    },
 9547    Closed,
 9548}
 9549
 9550impl EventEmitter<EditorEvent> for Editor {}
 9551
 9552impl FocusableView for Editor {
 9553    fn focus_handle(&self, _cx: &AppContext) -> FocusHandle {
 9554        self.focus_handle.clone()
 9555    }
 9556}
 9557
 9558impl Render for Editor {
 9559    fn render<'a>(&mut self, cx: &mut ViewContext<'a, Self>) -> impl IntoElement {
 9560        let settings = ThemeSettings::get_global(cx);
 9561        let text_style = match self.mode {
 9562            EditorMode::SingleLine | EditorMode::AutoHeight { .. } => TextStyle {
 9563                color: cx.theme().colors().editor_foreground,
 9564                font_family: settings.ui_font.family.clone(),
 9565                font_features: settings.ui_font.features,
 9566                font_size: rems(0.875).into(),
 9567                font_weight: FontWeight::NORMAL,
 9568                font_style: FontStyle::Normal,
 9569                line_height: relative(settings.buffer_line_height.value()),
 9570                background_color: None,
 9571                underline: None,
 9572                strikethrough: None,
 9573                white_space: WhiteSpace::Normal,
 9574            },
 9575
 9576            EditorMode::Full => TextStyle {
 9577                color: cx.theme().colors().editor_foreground,
 9578                font_family: settings.buffer_font.family.clone(),
 9579                font_features: settings.buffer_font.features,
 9580                font_size: settings.buffer_font_size(cx).into(),
 9581                font_weight: FontWeight::NORMAL,
 9582                font_style: FontStyle::Normal,
 9583                line_height: relative(settings.buffer_line_height.value()),
 9584                background_color: None,
 9585                underline: None,
 9586                strikethrough: None,
 9587                white_space: WhiteSpace::Normal,
 9588            },
 9589        };
 9590
 9591        let background = match self.mode {
 9592            EditorMode::SingleLine => cx.theme().system().transparent,
 9593            EditorMode::AutoHeight { max_lines: _ } => cx.theme().system().transparent,
 9594            EditorMode::Full => cx.theme().colors().editor_background,
 9595        };
 9596
 9597        EditorElement::new(
 9598            cx.view(),
 9599            EditorStyle {
 9600                background,
 9601                local_player: cx.theme().players().local(),
 9602                text: text_style,
 9603                scrollbar_width: px(12.),
 9604                syntax: cx.theme().syntax().clone(),
 9605                status: cx.theme().status().clone(),
 9606                inlays_style: HighlightStyle {
 9607                    color: Some(cx.theme().status().hint),
 9608                    font_weight: Some(FontWeight::BOLD),
 9609                    ..HighlightStyle::default()
 9610                },
 9611                suggestions_style: HighlightStyle {
 9612                    color: Some(cx.theme().status().predictive),
 9613                    ..HighlightStyle::default()
 9614                },
 9615            },
 9616        )
 9617    }
 9618}
 9619
 9620impl ViewInputHandler for Editor {
 9621    fn text_for_range(
 9622        &mut self,
 9623        range_utf16: Range<usize>,
 9624        cx: &mut ViewContext<Self>,
 9625    ) -> Option<String> {
 9626        Some(
 9627            self.buffer
 9628                .read(cx)
 9629                .read(cx)
 9630                .text_for_range(OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end))
 9631                .collect(),
 9632        )
 9633    }
 9634
 9635    fn selected_text_range(&mut self, cx: &mut ViewContext<Self>) -> Option<Range<usize>> {
 9636        // Prevent the IME menu from appearing when holding down an alphabetic key
 9637        // while input is disabled.
 9638        if !self.input_enabled {
 9639            return None;
 9640        }
 9641
 9642        let range = self.selections.newest::<OffsetUtf16>(cx).range();
 9643        Some(range.start.0..range.end.0)
 9644    }
 9645
 9646    fn marked_text_range(&self, cx: &mut ViewContext<Self>) -> Option<Range<usize>> {
 9647        let snapshot = self.buffer.read(cx).read(cx);
 9648        let range = self.text_highlights::<InputComposition>(cx)?.1.get(0)?;
 9649        Some(range.start.to_offset_utf16(&snapshot).0..range.end.to_offset_utf16(&snapshot).0)
 9650    }
 9651
 9652    fn unmark_text(&mut self, cx: &mut ViewContext<Self>) {
 9653        self.clear_highlights::<InputComposition>(cx);
 9654        self.ime_transaction.take();
 9655    }
 9656
 9657    fn replace_text_in_range(
 9658        &mut self,
 9659        range_utf16: Option<Range<usize>>,
 9660        text: &str,
 9661        cx: &mut ViewContext<Self>,
 9662    ) {
 9663        if !self.input_enabled {
 9664            cx.emit(EditorEvent::InputIgnored { text: text.into() });
 9665            return;
 9666        }
 9667
 9668        self.transact(cx, |this, cx| {
 9669            let new_selected_ranges = if let Some(range_utf16) = range_utf16 {
 9670                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
 9671                Some(this.selection_replacement_ranges(range_utf16, cx))
 9672            } else {
 9673                this.marked_text_ranges(cx)
 9674            };
 9675
 9676            let range_to_replace = new_selected_ranges.as_ref().and_then(|ranges_to_replace| {
 9677                let newest_selection_id = this.selections.newest_anchor().id;
 9678                this.selections
 9679                    .all::<OffsetUtf16>(cx)
 9680                    .iter()
 9681                    .zip(ranges_to_replace.iter())
 9682                    .find_map(|(selection, range)| {
 9683                        if selection.id == newest_selection_id {
 9684                            Some(
 9685                                (range.start.0 as isize - selection.head().0 as isize)
 9686                                    ..(range.end.0 as isize - selection.head().0 as isize),
 9687                            )
 9688                        } else {
 9689                            None
 9690                        }
 9691                    })
 9692            });
 9693
 9694            cx.emit(EditorEvent::InputHandled {
 9695                utf16_range_to_replace: range_to_replace,
 9696                text: text.into(),
 9697            });
 9698
 9699            if let Some(new_selected_ranges) = new_selected_ranges {
 9700                this.change_selections(None, cx, |selections| {
 9701                    selections.select_ranges(new_selected_ranges)
 9702                });
 9703                this.backspace(&Default::default(), cx);
 9704            }
 9705
 9706            this.handle_input(text, cx);
 9707        });
 9708
 9709        if let Some(transaction) = self.ime_transaction {
 9710            self.buffer.update(cx, |buffer, cx| {
 9711                buffer.group_until_transaction(transaction, cx);
 9712            });
 9713        }
 9714
 9715        self.unmark_text(cx);
 9716    }
 9717
 9718    fn replace_and_mark_text_in_range(
 9719        &mut self,
 9720        range_utf16: Option<Range<usize>>,
 9721        text: &str,
 9722        new_selected_range_utf16: Option<Range<usize>>,
 9723        cx: &mut ViewContext<Self>,
 9724    ) {
 9725        if !self.input_enabled {
 9726            cx.emit(EditorEvent::InputIgnored { text: text.into() });
 9727            return;
 9728        }
 9729
 9730        let transaction = self.transact(cx, |this, cx| {
 9731            let ranges_to_replace = if let Some(mut marked_ranges) = this.marked_text_ranges(cx) {
 9732                let snapshot = this.buffer.read(cx).read(cx);
 9733                if let Some(relative_range_utf16) = range_utf16.as_ref() {
 9734                    for marked_range in &mut marked_ranges {
 9735                        marked_range.end.0 = marked_range.start.0 + relative_range_utf16.end;
 9736                        marked_range.start.0 += relative_range_utf16.start;
 9737                        marked_range.start =
 9738                            snapshot.clip_offset_utf16(marked_range.start, Bias::Left);
 9739                        marked_range.end =
 9740                            snapshot.clip_offset_utf16(marked_range.end, Bias::Right);
 9741                    }
 9742                }
 9743                Some(marked_ranges)
 9744            } else if let Some(range_utf16) = range_utf16 {
 9745                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
 9746                Some(this.selection_replacement_ranges(range_utf16, cx))
 9747            } else {
 9748                None
 9749            };
 9750
 9751            let range_to_replace = ranges_to_replace.as_ref().and_then(|ranges_to_replace| {
 9752                let newest_selection_id = this.selections.newest_anchor().id;
 9753                this.selections
 9754                    .all::<OffsetUtf16>(cx)
 9755                    .iter()
 9756                    .zip(ranges_to_replace.iter())
 9757                    .find_map(|(selection, range)| {
 9758                        if selection.id == newest_selection_id {
 9759                            Some(
 9760                                (range.start.0 as isize - selection.head().0 as isize)
 9761                                    ..(range.end.0 as isize - selection.head().0 as isize),
 9762                            )
 9763                        } else {
 9764                            None
 9765                        }
 9766                    })
 9767            });
 9768
 9769            cx.emit(EditorEvent::InputHandled {
 9770                utf16_range_to_replace: range_to_replace,
 9771                text: text.into(),
 9772            });
 9773
 9774            if let Some(ranges) = ranges_to_replace {
 9775                this.change_selections(None, cx, |s| s.select_ranges(ranges));
 9776            }
 9777
 9778            let marked_ranges = {
 9779                let snapshot = this.buffer.read(cx).read(cx);
 9780                this.selections
 9781                    .disjoint_anchors()
 9782                    .iter()
 9783                    .map(|selection| {
 9784                        selection.start.bias_left(&*snapshot)..selection.end.bias_right(&*snapshot)
 9785                    })
 9786                    .collect::<Vec<_>>()
 9787            };
 9788
 9789            if text.is_empty() {
 9790                this.unmark_text(cx);
 9791            } else {
 9792                this.highlight_text::<InputComposition>(
 9793                    marked_ranges.clone(),
 9794                    HighlightStyle {
 9795                        underline: Some(UnderlineStyle {
 9796                            thickness: px(1.),
 9797                            color: None,
 9798                            wavy: false,
 9799                        }),
 9800                        ..Default::default()
 9801                    },
 9802                    cx,
 9803                );
 9804            }
 9805
 9806            // Disable auto-closing when composing text (i.e. typing a `"` on a Brazilian keyboard)
 9807            let use_autoclose = this.use_autoclose;
 9808            this.set_use_autoclose(false);
 9809            this.handle_input(text, cx);
 9810            this.set_use_autoclose(use_autoclose);
 9811
 9812            if let Some(new_selected_range) = new_selected_range_utf16 {
 9813                let snapshot = this.buffer.read(cx).read(cx);
 9814                let new_selected_ranges = marked_ranges
 9815                    .into_iter()
 9816                    .map(|marked_range| {
 9817                        let insertion_start = marked_range.start.to_offset_utf16(&snapshot).0;
 9818                        let new_start = OffsetUtf16(new_selected_range.start + insertion_start);
 9819                        let new_end = OffsetUtf16(new_selected_range.end + insertion_start);
 9820                        snapshot.clip_offset_utf16(new_start, Bias::Left)
 9821                            ..snapshot.clip_offset_utf16(new_end, Bias::Right)
 9822                    })
 9823                    .collect::<Vec<_>>();
 9824
 9825                drop(snapshot);
 9826                this.change_selections(None, cx, |selections| {
 9827                    selections.select_ranges(new_selected_ranges)
 9828                });
 9829            }
 9830        });
 9831
 9832        self.ime_transaction = self.ime_transaction.or(transaction);
 9833        if let Some(transaction) = self.ime_transaction {
 9834            self.buffer.update(cx, |buffer, cx| {
 9835                buffer.group_until_transaction(transaction, cx);
 9836            });
 9837        }
 9838
 9839        if self.text_highlights::<InputComposition>(cx).is_none() {
 9840            self.ime_transaction.take();
 9841        }
 9842    }
 9843
 9844    fn bounds_for_range(
 9845        &mut self,
 9846        range_utf16: Range<usize>,
 9847        element_bounds: gpui::Bounds<Pixels>,
 9848        cx: &mut ViewContext<Self>,
 9849    ) -> Option<gpui::Bounds<Pixels>> {
 9850        let text_layout_details = self.text_layout_details(cx);
 9851        let style = &text_layout_details.editor_style;
 9852        let font_id = cx.text_system().resolve_font(&style.text.font());
 9853        let font_size = style.text.font_size.to_pixels(cx.rem_size());
 9854        let line_height = style.text.line_height_in_pixels(cx.rem_size());
 9855        let em_width = cx
 9856            .text_system()
 9857            .typographic_bounds(font_id, font_size, 'm')
 9858            .unwrap()
 9859            .size
 9860            .width;
 9861
 9862        let snapshot = self.snapshot(cx);
 9863        let scroll_position = snapshot.scroll_position();
 9864        let scroll_left = scroll_position.x * em_width;
 9865
 9866        let start = OffsetUtf16(range_utf16.start).to_display_point(&snapshot);
 9867        let x = snapshot.x_for_display_point(start, &text_layout_details) - scroll_left
 9868            + self.gutter_width;
 9869        let y = line_height * (start.row() as f32 - scroll_position.y);
 9870
 9871        Some(Bounds {
 9872            origin: element_bounds.origin + point(x, y),
 9873            size: size(em_width, line_height),
 9874        })
 9875    }
 9876}
 9877
 9878trait SelectionExt {
 9879    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize>;
 9880    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point>;
 9881    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
 9882    fn spanned_rows(&self, include_end_if_at_line_start: bool, map: &DisplaySnapshot)
 9883        -> Range<u32>;
 9884}
 9885
 9886impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
 9887    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
 9888        let start = self.start.to_point(buffer);
 9889        let end = self.end.to_point(buffer);
 9890        if self.reversed {
 9891            end..start
 9892        } else {
 9893            start..end
 9894        }
 9895    }
 9896
 9897    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
 9898        let start = self.start.to_offset(buffer);
 9899        let end = self.end.to_offset(buffer);
 9900        if self.reversed {
 9901            end..start
 9902        } else {
 9903            start..end
 9904        }
 9905    }
 9906
 9907    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
 9908        let start = self
 9909            .start
 9910            .to_point(&map.buffer_snapshot)
 9911            .to_display_point(map);
 9912        let end = self
 9913            .end
 9914            .to_point(&map.buffer_snapshot)
 9915            .to_display_point(map);
 9916        if self.reversed {
 9917            end..start
 9918        } else {
 9919            start..end
 9920        }
 9921    }
 9922
 9923    fn spanned_rows(
 9924        &self,
 9925        include_end_if_at_line_start: bool,
 9926        map: &DisplaySnapshot,
 9927    ) -> Range<u32> {
 9928        let start = self.start.to_point(&map.buffer_snapshot);
 9929        let mut end = self.end.to_point(&map.buffer_snapshot);
 9930        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
 9931            end.row -= 1;
 9932        }
 9933
 9934        let buffer_start = map.prev_line_boundary(start).0;
 9935        let buffer_end = map.next_line_boundary(end).0;
 9936        buffer_start.row..buffer_end.row + 1
 9937    }
 9938}
 9939
 9940impl<T: InvalidationRegion> InvalidationStack<T> {
 9941    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
 9942    where
 9943        S: Clone + ToOffset,
 9944    {
 9945        while let Some(region) = self.last() {
 9946            let all_selections_inside_invalidation_ranges =
 9947                if selections.len() == region.ranges().len() {
 9948                    selections
 9949                        .iter()
 9950                        .zip(region.ranges().iter().map(|r| r.to_offset(buffer)))
 9951                        .all(|(selection, invalidation_range)| {
 9952                            let head = selection.head().to_offset(buffer);
 9953                            invalidation_range.start <= head && invalidation_range.end >= head
 9954                        })
 9955                } else {
 9956                    false
 9957                };
 9958
 9959            if all_selections_inside_invalidation_ranges {
 9960                break;
 9961            } else {
 9962                self.pop();
 9963            }
 9964        }
 9965    }
 9966}
 9967
 9968impl<T> Default for InvalidationStack<T> {
 9969    fn default() -> Self {
 9970        Self(Default::default())
 9971    }
 9972}
 9973
 9974impl<T> Deref for InvalidationStack<T> {
 9975    type Target = Vec<T>;
 9976
 9977    fn deref(&self) -> &Self::Target {
 9978        &self.0
 9979    }
 9980}
 9981
 9982impl<T> DerefMut for InvalidationStack<T> {
 9983    fn deref_mut(&mut self) -> &mut Self::Target {
 9984        &mut self.0
 9985    }
 9986}
 9987
 9988impl InvalidationRegion for SnippetState {
 9989    fn ranges(&self) -> &[Range<Anchor>] {
 9990        &self.ranges[self.active_index]
 9991    }
 9992}
 9993
 9994pub fn diagnostic_block_renderer(diagnostic: Diagnostic, _is_valid: bool) -> RenderBlock {
 9995    let (text_without_backticks, code_ranges) = highlight_diagnostic_message(&diagnostic);
 9996
 9997    Arc::new(move |cx: &mut BlockContext| {
 9998        let group_id: SharedString = cx.block_id.to_string().into();
 9999
10000        let mut text_style = cx.text_style().clone();
10001        text_style.color = diagnostic_style(diagnostic.severity, true, cx.theme().status());
10002
10003        h_flex()
10004            .id(cx.block_id)
10005            .group(group_id.clone())
10006            .relative()
10007            .size_full()
10008            .pl(cx.gutter_width)
10009            .w(cx.max_width + cx.gutter_width)
10010            .child(div().flex().w(cx.anchor_x - cx.gutter_width).flex_shrink())
10011            .child(div().flex().flex_shrink_0().child(
10012                StyledText::new(text_without_backticks.clone()).with_highlights(
10013                    &text_style,
10014                    code_ranges.iter().map(|range| {
10015                        (
10016                            range.clone(),
10017                            HighlightStyle {
10018                                font_weight: Some(FontWeight::BOLD),
10019                                ..Default::default()
10020                            },
10021                        )
10022                    }),
10023                ),
10024            ))
10025            .child(
10026                IconButton::new(("copy-block", cx.block_id), IconName::Copy)
10027                    .icon_color(Color::Muted)
10028                    .size(ButtonSize::Compact)
10029                    .style(ButtonStyle::Transparent)
10030                    .visible_on_hover(group_id)
10031                    .on_click({
10032                        let message = diagnostic.message.clone();
10033                        move |_click, cx| cx.write_to_clipboard(ClipboardItem::new(message.clone()))
10034                    })
10035                    .tooltip(|cx| Tooltip::text("Copy diagnostic message", cx)),
10036            )
10037            .into_any_element()
10038    })
10039}
10040
10041pub fn highlight_diagnostic_message(diagnostic: &Diagnostic) -> (SharedString, Vec<Range<usize>>) {
10042    let mut text_without_backticks = String::new();
10043    let mut code_ranges = Vec::new();
10044
10045    if let Some(source) = &diagnostic.source {
10046        text_without_backticks.push_str(&source);
10047        code_ranges.push(0..source.len());
10048        text_without_backticks.push_str(": ");
10049    }
10050
10051    let mut prev_offset = 0;
10052    let mut in_code_block = false;
10053    for (ix, _) in diagnostic
10054        .message
10055        .match_indices('`')
10056        .chain([(diagnostic.message.len(), "")])
10057    {
10058        let prev_len = text_without_backticks.len();
10059        text_without_backticks.push_str(&diagnostic.message[prev_offset..ix]);
10060        prev_offset = ix + 1;
10061        if in_code_block {
10062            code_ranges.push(prev_len..text_without_backticks.len());
10063            in_code_block = false;
10064        } else {
10065            in_code_block = true;
10066        }
10067    }
10068
10069    (text_without_backticks.into(), code_ranges)
10070}
10071
10072fn diagnostic_style(severity: DiagnosticSeverity, valid: bool, colors: &StatusColors) -> Hsla {
10073    match (severity, valid) {
10074        (DiagnosticSeverity::ERROR, true) => colors.error,
10075        (DiagnosticSeverity::ERROR, false) => colors.error,
10076        (DiagnosticSeverity::WARNING, true) => colors.warning,
10077        (DiagnosticSeverity::WARNING, false) => colors.warning,
10078        (DiagnosticSeverity::INFORMATION, true) => colors.info,
10079        (DiagnosticSeverity::INFORMATION, false) => colors.info,
10080        (DiagnosticSeverity::HINT, true) => colors.info,
10081        (DiagnosticSeverity::HINT, false) => colors.info,
10082        _ => colors.ignored,
10083    }
10084}
10085
10086pub fn styled_runs_for_code_label<'a>(
10087    label: &'a CodeLabel,
10088    syntax_theme: &'a theme::SyntaxTheme,
10089) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
10090    let fade_out = HighlightStyle {
10091        fade_out: Some(0.35),
10092        ..Default::default()
10093    };
10094
10095    let mut prev_end = label.filter_range.end;
10096    label
10097        .runs
10098        .iter()
10099        .enumerate()
10100        .flat_map(move |(ix, (range, highlight_id))| {
10101            let style = if let Some(style) = highlight_id.style(syntax_theme) {
10102                style
10103            } else {
10104                return Default::default();
10105            };
10106            let mut muted_style = style;
10107            muted_style.highlight(fade_out);
10108
10109            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
10110            if range.start >= label.filter_range.end {
10111                if range.start > prev_end {
10112                    runs.push((prev_end..range.start, fade_out));
10113                }
10114                runs.push((range.clone(), muted_style));
10115            } else if range.end <= label.filter_range.end {
10116                runs.push((range.clone(), style));
10117            } else {
10118                runs.push((range.start..label.filter_range.end, style));
10119                runs.push((label.filter_range.end..range.end, muted_style));
10120            }
10121            prev_end = cmp::max(prev_end, range.end);
10122
10123            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
10124                runs.push((prev_end..label.text.len(), fade_out));
10125            }
10126
10127            runs
10128        })
10129}
10130
10131pub(crate) fn split_words<'a>(text: &'a str) -> impl std::iter::Iterator<Item = &'a str> + 'a {
10132    let mut index = 0;
10133    let mut codepoints = text.char_indices().peekable();
10134
10135    std::iter::from_fn(move || {
10136        let start_index = index;
10137        while let Some((new_index, codepoint)) = codepoints.next() {
10138            index = new_index + codepoint.len_utf8();
10139            let current_upper = codepoint.is_uppercase();
10140            let next_upper = codepoints
10141                .peek()
10142                .map(|(_, c)| c.is_uppercase())
10143                .unwrap_or(false);
10144
10145            if !current_upper && next_upper {
10146                return Some(&text[start_index..index]);
10147            }
10148        }
10149
10150        index = text.len();
10151        if start_index < text.len() {
10152            return Some(&text[start_index..]);
10153        }
10154        None
10155    })
10156    .flat_map(|word| word.split_inclusive('_'))
10157    .flat_map(|word| word.split_inclusive('-'))
10158}
10159
10160trait RangeToAnchorExt {
10161    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor>;
10162}
10163
10164impl<T: ToOffset> RangeToAnchorExt for Range<T> {
10165    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor> {
10166        snapshot.anchor_after(self.start)..snapshot.anchor_before(self.end)
10167    }
10168}