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 && EditorSettings::get_global(cx).use_on_type_format {
 2494                if let Some(on_type_format_task) =
 2495                    this.trigger_on_type_formatting(text.to_string(), cx)
 2496                {
 2497                    on_type_format_task.detach_and_log_err(cx);
 2498                }
 2499            }
 2500
 2501            if had_active_copilot_suggestion {
 2502                this.refresh_copilot_suggestions(true, cx);
 2503                if !this.has_active_copilot_suggestion(cx) {
 2504                    this.trigger_completion_on_input(&text, cx);
 2505                }
 2506            } else {
 2507                this.trigger_completion_on_input(&text, cx);
 2508                this.refresh_copilot_suggestions(true, cx);
 2509            }
 2510        });
 2511    }
 2512
 2513    pub fn newline(&mut self, _: &Newline, cx: &mut ViewContext<Self>) {
 2514        self.transact(cx, |this, cx| {
 2515            let (edits, selection_fixup_info): (Vec<_>, Vec<_>) = {
 2516                let selections = this.selections.all::<usize>(cx);
 2517                let multi_buffer = this.buffer.read(cx);
 2518                let buffer = multi_buffer.snapshot(cx);
 2519                selections
 2520                    .iter()
 2521                    .map(|selection| {
 2522                        let start_point = selection.start.to_point(&buffer);
 2523                        let mut indent = buffer.indent_size_for_line(start_point.row);
 2524                        indent.len = cmp::min(indent.len, start_point.column);
 2525                        let start = selection.start;
 2526                        let end = selection.end;
 2527                        let is_cursor = start == end;
 2528                        let language_scope = buffer.language_scope_at(start);
 2529                        let (comment_delimiter, insert_extra_newline) = if let Some(language) =
 2530                            &language_scope
 2531                        {
 2532                            let leading_whitespace_len = buffer
 2533                                .reversed_chars_at(start)
 2534                                .take_while(|c| c.is_whitespace() && *c != '\n')
 2535                                .map(|c| c.len_utf8())
 2536                                .sum::<usize>();
 2537
 2538                            let trailing_whitespace_len = buffer
 2539                                .chars_at(end)
 2540                                .take_while(|c| c.is_whitespace() && *c != '\n')
 2541                                .map(|c| c.len_utf8())
 2542                                .sum::<usize>();
 2543
 2544                            let insert_extra_newline =
 2545                                language.brackets().any(|(pair, enabled)| {
 2546                                    let pair_start = pair.start.trim_end();
 2547                                    let pair_end = pair.end.trim_start();
 2548
 2549                                    enabled
 2550                                        && pair.newline
 2551                                        && buffer.contains_str_at(
 2552                                            end + trailing_whitespace_len,
 2553                                            pair_end,
 2554                                        )
 2555                                        && buffer.contains_str_at(
 2556                                            (start - leading_whitespace_len)
 2557                                                .saturating_sub(pair_start.len()),
 2558                                            pair_start,
 2559                                        )
 2560                                });
 2561                            // Comment extension on newline is allowed only for cursor selections
 2562                            let comment_delimiter = language.line_comment_prefixes().filter(|_| {
 2563                                let is_comment_extension_enabled =
 2564                                    multi_buffer.settings_at(0, cx).extend_comment_on_newline;
 2565                                is_cursor && is_comment_extension_enabled
 2566                            });
 2567                            let get_comment_delimiter = |delimiters: &[Arc<str>]| {
 2568                                let max_len_of_delimiter =
 2569                                    delimiters.iter().map(|delimiter| delimiter.len()).max()?;
 2570                                let (snapshot, range) =
 2571                                    buffer.buffer_line_for_row(start_point.row)?;
 2572
 2573                                let mut index_of_first_non_whitespace = 0;
 2574                                let comment_candidate = snapshot
 2575                                    .chars_for_range(range)
 2576                                    .skip_while(|c| {
 2577                                        let should_skip = c.is_whitespace();
 2578                                        if should_skip {
 2579                                            index_of_first_non_whitespace += 1;
 2580                                        }
 2581                                        should_skip
 2582                                    })
 2583                                    .take(max_len_of_delimiter)
 2584                                    .collect::<String>();
 2585                                let comment_prefix = delimiters.iter().find(|comment_prefix| {
 2586                                    comment_candidate.starts_with(comment_prefix.as_ref())
 2587                                })?;
 2588                                let cursor_is_placed_after_comment_marker =
 2589                                    index_of_first_non_whitespace + comment_prefix.len()
 2590                                        <= start_point.column as usize;
 2591                                if cursor_is_placed_after_comment_marker {
 2592                                    Some(comment_prefix.clone())
 2593                                } else {
 2594                                    None
 2595                                }
 2596                            };
 2597                            let comment_delimiter = if let Some(delimiters) = comment_delimiter {
 2598                                get_comment_delimiter(delimiters)
 2599                            } else {
 2600                                None
 2601                            };
 2602                            (comment_delimiter, insert_extra_newline)
 2603                        } else {
 2604                            (None, false)
 2605                        };
 2606
 2607                        let capacity_for_delimiter = comment_delimiter
 2608                            .as_deref()
 2609                            .map(str::len)
 2610                            .unwrap_or_default();
 2611                        let mut new_text =
 2612                            String::with_capacity(1 + capacity_for_delimiter + indent.len as usize);
 2613                        new_text.push_str("\n");
 2614                        new_text.extend(indent.chars());
 2615                        if let Some(delimiter) = &comment_delimiter {
 2616                            new_text.push_str(&delimiter);
 2617                        }
 2618                        if insert_extra_newline {
 2619                            new_text = new_text.repeat(2);
 2620                        }
 2621
 2622                        let anchor = buffer.anchor_after(end);
 2623                        let new_selection = selection.map(|_| anchor);
 2624                        (
 2625                            (start..end, new_text),
 2626                            (insert_extra_newline, new_selection),
 2627                        )
 2628                    })
 2629                    .unzip()
 2630            };
 2631
 2632            this.edit_with_autoindent(edits, cx);
 2633            let buffer = this.buffer.read(cx).snapshot(cx);
 2634            let new_selections = selection_fixup_info
 2635                .into_iter()
 2636                .map(|(extra_newline_inserted, new_selection)| {
 2637                    let mut cursor = new_selection.end.to_point(&buffer);
 2638                    if extra_newline_inserted {
 2639                        cursor.row -= 1;
 2640                        cursor.column = buffer.line_len(cursor.row);
 2641                    }
 2642                    new_selection.map(|_| cursor)
 2643                })
 2644                .collect();
 2645
 2646            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(new_selections));
 2647            this.refresh_copilot_suggestions(true, cx);
 2648        });
 2649    }
 2650
 2651    pub fn newline_above(&mut self, _: &NewlineAbove, cx: &mut ViewContext<Self>) {
 2652        let buffer = self.buffer.read(cx);
 2653        let snapshot = buffer.snapshot(cx);
 2654
 2655        let mut edits = Vec::new();
 2656        let mut rows = Vec::new();
 2657        let mut rows_inserted = 0;
 2658
 2659        for selection in self.selections.all_adjusted(cx) {
 2660            let cursor = selection.head();
 2661            let row = cursor.row;
 2662
 2663            let start_of_line = snapshot.clip_point(Point::new(row, 0), Bias::Left);
 2664
 2665            let newline = "\n".to_string();
 2666            edits.push((start_of_line..start_of_line, newline));
 2667
 2668            rows.push(row + rows_inserted);
 2669            rows_inserted += 1;
 2670        }
 2671
 2672        self.transact(cx, |editor, cx| {
 2673            editor.edit(edits, cx);
 2674
 2675            editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
 2676                let mut index = 0;
 2677                s.move_cursors_with(|map, _, _| {
 2678                    let row = rows[index];
 2679                    index += 1;
 2680
 2681                    let point = Point::new(row, 0);
 2682                    let boundary = map.next_line_boundary(point).1;
 2683                    let clipped = map.clip_point(boundary, Bias::Left);
 2684
 2685                    (clipped, SelectionGoal::None)
 2686                });
 2687            });
 2688
 2689            let mut indent_edits = Vec::new();
 2690            let multibuffer_snapshot = editor.buffer.read(cx).snapshot(cx);
 2691            for row in rows {
 2692                let indents = multibuffer_snapshot.suggested_indents(row..row + 1, cx);
 2693                for (row, indent) in indents {
 2694                    if indent.len == 0 {
 2695                        continue;
 2696                    }
 2697
 2698                    let text = match indent.kind {
 2699                        IndentKind::Space => " ".repeat(indent.len as usize),
 2700                        IndentKind::Tab => "\t".repeat(indent.len as usize),
 2701                    };
 2702                    let point = Point::new(row, 0);
 2703                    indent_edits.push((point..point, text));
 2704                }
 2705            }
 2706            editor.edit(indent_edits, cx);
 2707        });
 2708    }
 2709
 2710    pub fn newline_below(&mut self, _: &NewlineBelow, cx: &mut ViewContext<Self>) {
 2711        let buffer = self.buffer.read(cx);
 2712        let snapshot = buffer.snapshot(cx);
 2713
 2714        let mut edits = Vec::new();
 2715        let mut rows = Vec::new();
 2716        let mut rows_inserted = 0;
 2717
 2718        for selection in self.selections.all_adjusted(cx) {
 2719            let cursor = selection.head();
 2720            let row = cursor.row;
 2721
 2722            let point = Point::new(row + 1, 0);
 2723            let start_of_line = snapshot.clip_point(point, Bias::Left);
 2724
 2725            let newline = "\n".to_string();
 2726            edits.push((start_of_line..start_of_line, newline));
 2727
 2728            rows_inserted += 1;
 2729            rows.push(row + rows_inserted);
 2730        }
 2731
 2732        self.transact(cx, |editor, cx| {
 2733            editor.edit(edits, cx);
 2734
 2735            editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
 2736                let mut index = 0;
 2737                s.move_cursors_with(|map, _, _| {
 2738                    let row = rows[index];
 2739                    index += 1;
 2740
 2741                    let point = Point::new(row, 0);
 2742                    let boundary = map.next_line_boundary(point).1;
 2743                    let clipped = map.clip_point(boundary, Bias::Left);
 2744
 2745                    (clipped, SelectionGoal::None)
 2746                });
 2747            });
 2748
 2749            let mut indent_edits = Vec::new();
 2750            let multibuffer_snapshot = editor.buffer.read(cx).snapshot(cx);
 2751            for row in rows {
 2752                let indents = multibuffer_snapshot.suggested_indents(row..row + 1, cx);
 2753                for (row, indent) in indents {
 2754                    if indent.len == 0 {
 2755                        continue;
 2756                    }
 2757
 2758                    let text = match indent.kind {
 2759                        IndentKind::Space => " ".repeat(indent.len as usize),
 2760                        IndentKind::Tab => "\t".repeat(indent.len as usize),
 2761                    };
 2762                    let point = Point::new(row, 0);
 2763                    indent_edits.push((point..point, text));
 2764                }
 2765            }
 2766            editor.edit(indent_edits, cx);
 2767        });
 2768    }
 2769
 2770    pub fn insert(&mut self, text: &str, cx: &mut ViewContext<Self>) {
 2771        self.insert_with_autoindent_mode(
 2772            text,
 2773            Some(AutoindentMode::Block {
 2774                original_indent_columns: Vec::new(),
 2775            }),
 2776            cx,
 2777        );
 2778    }
 2779
 2780    fn insert_with_autoindent_mode(
 2781        &mut self,
 2782        text: &str,
 2783        autoindent_mode: Option<AutoindentMode>,
 2784        cx: &mut ViewContext<Self>,
 2785    ) {
 2786        if self.read_only(cx) {
 2787            return;
 2788        }
 2789
 2790        let text: Arc<str> = text.into();
 2791        self.transact(cx, |this, cx| {
 2792            let old_selections = this.selections.all_adjusted(cx);
 2793            let selection_anchors = this.buffer.update(cx, |buffer, cx| {
 2794                let anchors = {
 2795                    let snapshot = buffer.read(cx);
 2796                    old_selections
 2797                        .iter()
 2798                        .map(|s| {
 2799                            let anchor = snapshot.anchor_after(s.head());
 2800                            s.map(|_| anchor)
 2801                        })
 2802                        .collect::<Vec<_>>()
 2803                };
 2804                buffer.edit(
 2805                    old_selections
 2806                        .iter()
 2807                        .map(|s| (s.start..s.end, text.clone())),
 2808                    autoindent_mode,
 2809                    cx,
 2810                );
 2811                anchors
 2812            });
 2813
 2814            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 2815                s.select_anchors(selection_anchors);
 2816            })
 2817        });
 2818    }
 2819
 2820    fn trigger_completion_on_input(&mut self, text: &str, cx: &mut ViewContext<Self>) {
 2821        if !EditorSettings::get_global(cx).show_completions_on_input {
 2822            return;
 2823        }
 2824
 2825        let selection = self.selections.newest_anchor();
 2826        if self
 2827            .buffer
 2828            .read(cx)
 2829            .is_completion_trigger(selection.head(), text, cx)
 2830        {
 2831            self.show_completions(&ShowCompletions, cx);
 2832        } else {
 2833            self.hide_context_menu(cx);
 2834        }
 2835    }
 2836
 2837    /// If any empty selections is touching the start of its innermost containing autoclose
 2838    /// region, expand it to select the brackets.
 2839    fn select_autoclose_pair(&mut self, cx: &mut ViewContext<Self>) {
 2840        let selections = self.selections.all::<usize>(cx);
 2841        let buffer = self.buffer.read(cx).read(cx);
 2842        let mut new_selections = Vec::new();
 2843        for (mut selection, region) in self.selections_with_autoclose_regions(selections, &buffer) {
 2844            if let (Some(region), true) = (region, selection.is_empty()) {
 2845                let mut range = region.range.to_offset(&buffer);
 2846                if selection.start == range.start {
 2847                    if range.start >= region.pair.start.len() {
 2848                        range.start -= region.pair.start.len();
 2849                        if buffer.contains_str_at(range.start, &region.pair.start) {
 2850                            if buffer.contains_str_at(range.end, &region.pair.end) {
 2851                                range.end += region.pair.end.len();
 2852                                selection.start = range.start;
 2853                                selection.end = range.end;
 2854                            }
 2855                        }
 2856                    }
 2857                }
 2858            }
 2859            new_selections.push(selection);
 2860        }
 2861
 2862        drop(buffer);
 2863        self.change_selections(None, cx, |selections| selections.select(new_selections));
 2864    }
 2865
 2866    /// Iterate the given selections, and for each one, find the smallest surrounding
 2867    /// autoclose region. This uses the ordering of the selections and the autoclose
 2868    /// regions to avoid repeated comparisons.
 2869    fn selections_with_autoclose_regions<'a, D: ToOffset + Clone>(
 2870        &'a self,
 2871        selections: impl IntoIterator<Item = Selection<D>>,
 2872        buffer: &'a MultiBufferSnapshot,
 2873    ) -> impl Iterator<Item = (Selection<D>, Option<&'a AutocloseRegion>)> {
 2874        let mut i = 0;
 2875        let mut regions = self.autoclose_regions.as_slice();
 2876        selections.into_iter().map(move |selection| {
 2877            let range = selection.start.to_offset(buffer)..selection.end.to_offset(buffer);
 2878
 2879            let mut enclosing = None;
 2880            while let Some(pair_state) = regions.get(i) {
 2881                if pair_state.range.end.to_offset(buffer) < range.start {
 2882                    regions = &regions[i + 1..];
 2883                    i = 0;
 2884                } else if pair_state.range.start.to_offset(buffer) > range.end {
 2885                    break;
 2886                } else {
 2887                    if pair_state.selection_id == selection.id {
 2888                        enclosing = Some(pair_state);
 2889                    }
 2890                    i += 1;
 2891                }
 2892            }
 2893
 2894            (selection.clone(), enclosing)
 2895        })
 2896    }
 2897
 2898    /// Remove any autoclose regions that no longer contain their selection.
 2899    fn invalidate_autoclose_regions(
 2900        &mut self,
 2901        mut selections: &[Selection<Anchor>],
 2902        buffer: &MultiBufferSnapshot,
 2903    ) {
 2904        self.autoclose_regions.retain(|state| {
 2905            let mut i = 0;
 2906            while let Some(selection) = selections.get(i) {
 2907                if selection.end.cmp(&state.range.start, buffer).is_lt() {
 2908                    selections = &selections[1..];
 2909                    continue;
 2910                }
 2911                if selection.start.cmp(&state.range.end, buffer).is_gt() {
 2912                    break;
 2913                }
 2914                if selection.id == state.selection_id {
 2915                    return true;
 2916                } else {
 2917                    i += 1;
 2918                }
 2919            }
 2920            false
 2921        });
 2922    }
 2923
 2924    fn completion_query(buffer: &MultiBufferSnapshot, position: impl ToOffset) -> Option<String> {
 2925        let offset = position.to_offset(buffer);
 2926        let (word_range, kind) = buffer.surrounding_word(offset);
 2927        if offset > word_range.start && kind == Some(CharKind::Word) {
 2928            Some(
 2929                buffer
 2930                    .text_for_range(word_range.start..offset)
 2931                    .collect::<String>(),
 2932            )
 2933        } else {
 2934            None
 2935        }
 2936    }
 2937
 2938    pub fn toggle_inlay_hints(&mut self, _: &ToggleInlayHints, cx: &mut ViewContext<Self>) {
 2939        self.refresh_inlay_hints(
 2940            InlayHintRefreshReason::Toggle(!self.inlay_hint_cache.enabled),
 2941            cx,
 2942        );
 2943    }
 2944
 2945    pub fn inlay_hints_enabled(&self) -> bool {
 2946        self.inlay_hint_cache.enabled
 2947    }
 2948
 2949    fn refresh_inlay_hints(&mut self, reason: InlayHintRefreshReason, cx: &mut ViewContext<Self>) {
 2950        if self.project.is_none() || self.mode != EditorMode::Full {
 2951            return;
 2952        }
 2953
 2954        let reason_description = reason.description();
 2955        let (invalidate_cache, required_languages) = match reason {
 2956            InlayHintRefreshReason::Toggle(enabled) => {
 2957                self.inlay_hint_cache.enabled = enabled;
 2958                if enabled {
 2959                    (InvalidationStrategy::RefreshRequested, None)
 2960                } else {
 2961                    self.inlay_hint_cache.clear();
 2962                    self.splice_inlay_hints(
 2963                        self.visible_inlay_hints(cx)
 2964                            .iter()
 2965                            .map(|inlay| inlay.id)
 2966                            .collect(),
 2967                        Vec::new(),
 2968                        cx,
 2969                    );
 2970                    return;
 2971                }
 2972            }
 2973            InlayHintRefreshReason::SettingsChange(new_settings) => {
 2974                match self.inlay_hint_cache.update_settings(
 2975                    &self.buffer,
 2976                    new_settings,
 2977                    self.visible_inlay_hints(cx),
 2978                    cx,
 2979                ) {
 2980                    ControlFlow::Break(Some(InlaySplice {
 2981                        to_remove,
 2982                        to_insert,
 2983                    })) => {
 2984                        self.splice_inlay_hints(to_remove, to_insert, cx);
 2985                        return;
 2986                    }
 2987                    ControlFlow::Break(None) => return,
 2988                    ControlFlow::Continue(()) => (InvalidationStrategy::RefreshRequested, None),
 2989                }
 2990            }
 2991            InlayHintRefreshReason::ExcerptsRemoved(excerpts_removed) => {
 2992                if let Some(InlaySplice {
 2993                    to_remove,
 2994                    to_insert,
 2995                }) = self.inlay_hint_cache.remove_excerpts(excerpts_removed)
 2996                {
 2997                    self.splice_inlay_hints(to_remove, to_insert, cx);
 2998                }
 2999                return;
 3000            }
 3001            InlayHintRefreshReason::NewLinesShown => (InvalidationStrategy::None, None),
 3002            InlayHintRefreshReason::BufferEdited(buffer_languages) => {
 3003                (InvalidationStrategy::BufferEdited, Some(buffer_languages))
 3004            }
 3005            InlayHintRefreshReason::RefreshRequested => {
 3006                (InvalidationStrategy::RefreshRequested, None)
 3007            }
 3008        };
 3009
 3010        if let Some(InlaySplice {
 3011            to_remove,
 3012            to_insert,
 3013        }) = self.inlay_hint_cache.spawn_hint_refresh(
 3014            reason_description,
 3015            self.excerpts_for_inlay_hints_query(required_languages.as_ref(), cx),
 3016            invalidate_cache,
 3017            cx,
 3018        ) {
 3019            self.splice_inlay_hints(to_remove, to_insert, cx);
 3020        }
 3021    }
 3022
 3023    fn visible_inlay_hints(&self, cx: &ViewContext<'_, Editor>) -> Vec<Inlay> {
 3024        self.display_map
 3025            .read(cx)
 3026            .current_inlays()
 3027            .filter(move |inlay| {
 3028                Some(inlay.id) != self.copilot_state.suggestion.as_ref().map(|h| h.id)
 3029            })
 3030            .cloned()
 3031            .collect()
 3032    }
 3033
 3034    pub fn excerpts_for_inlay_hints_query(
 3035        &self,
 3036        restrict_to_languages: Option<&HashSet<Arc<Language>>>,
 3037        cx: &mut ViewContext<Editor>,
 3038    ) -> HashMap<ExcerptId, (Model<Buffer>, clock::Global, Range<usize>)> {
 3039        let Some(project) = self.project.as_ref() else {
 3040            return HashMap::default();
 3041        };
 3042        let project = project.read(cx);
 3043        let multi_buffer = self.buffer().read(cx);
 3044        let multi_buffer_snapshot = multi_buffer.snapshot(cx);
 3045        let multi_buffer_visible_start = self
 3046            .scroll_manager
 3047            .anchor()
 3048            .anchor
 3049            .to_point(&multi_buffer_snapshot);
 3050        let multi_buffer_visible_end = multi_buffer_snapshot.clip_point(
 3051            multi_buffer_visible_start
 3052                + Point::new(self.visible_line_count().unwrap_or(0.).ceil() as u32, 0),
 3053            Bias::Left,
 3054        );
 3055        let multi_buffer_visible_range = multi_buffer_visible_start..multi_buffer_visible_end;
 3056        multi_buffer
 3057            .range_to_buffer_ranges(multi_buffer_visible_range, cx)
 3058            .into_iter()
 3059            .filter(|(_, excerpt_visible_range, _)| !excerpt_visible_range.is_empty())
 3060            .filter_map(|(buffer_handle, excerpt_visible_range, excerpt_id)| {
 3061                let buffer = buffer_handle.read(cx);
 3062                let buffer_file = project::worktree::File::from_dyn(buffer.file())?;
 3063                let buffer_worktree = project.worktree_for_id(buffer_file.worktree_id(cx), cx)?;
 3064                let worktree_entry = buffer_worktree
 3065                    .read(cx)
 3066                    .entry_for_id(buffer_file.project_entry_id(cx)?)?;
 3067                if worktree_entry.is_ignored {
 3068                    return None;
 3069                }
 3070
 3071                let language = buffer.language()?;
 3072                if let Some(restrict_to_languages) = restrict_to_languages {
 3073                    if !restrict_to_languages.contains(language) {
 3074                        return None;
 3075                    }
 3076                }
 3077                Some((
 3078                    excerpt_id,
 3079                    (
 3080                        buffer_handle,
 3081                        buffer.version().clone(),
 3082                        excerpt_visible_range,
 3083                    ),
 3084                ))
 3085            })
 3086            .collect()
 3087    }
 3088
 3089    pub fn text_layout_details(&self, cx: &WindowContext) -> TextLayoutDetails {
 3090        TextLayoutDetails {
 3091            text_system: cx.text_system().clone(),
 3092            editor_style: self.style.clone().unwrap(),
 3093            rem_size: cx.rem_size(),
 3094            scroll_anchor: self.scroll_manager.anchor(),
 3095            visible_rows: self.visible_line_count(),
 3096            vertical_scroll_margin: self.scroll_manager.vertical_scroll_margin,
 3097        }
 3098    }
 3099
 3100    fn splice_inlay_hints(
 3101        &self,
 3102        to_remove: Vec<InlayId>,
 3103        to_insert: Vec<Inlay>,
 3104        cx: &mut ViewContext<Self>,
 3105    ) {
 3106        self.display_map.update(cx, |display_map, cx| {
 3107            display_map.splice_inlays(to_remove, to_insert, cx);
 3108        });
 3109        cx.notify();
 3110    }
 3111
 3112    fn trigger_on_type_formatting(
 3113        &self,
 3114        input: String,
 3115        cx: &mut ViewContext<Self>,
 3116    ) -> Option<Task<Result<()>>> {
 3117        if input.len() != 1 {
 3118            return None;
 3119        }
 3120
 3121        let project = self.project.as_ref()?;
 3122        let position = self.selections.newest_anchor().head();
 3123        let (buffer, buffer_position) = self
 3124            .buffer
 3125            .read(cx)
 3126            .text_anchor_for_position(position.clone(), cx)?;
 3127
 3128        // OnTypeFormatting returns a list of edits, no need to pass them between Zed instances,
 3129        // hence we do LSP request & edit on host side only — add formats to host's history.
 3130        let push_to_lsp_host_history = true;
 3131        // If this is not the host, append its history with new edits.
 3132        let push_to_client_history = project.read(cx).is_remote();
 3133
 3134        let on_type_formatting = project.update(cx, |project, cx| {
 3135            project.on_type_format(
 3136                buffer.clone(),
 3137                buffer_position,
 3138                input,
 3139                push_to_lsp_host_history,
 3140                cx,
 3141            )
 3142        });
 3143        Some(cx.spawn(|editor, mut cx| async move {
 3144            if let Some(transaction) = on_type_formatting.await? {
 3145                if push_to_client_history {
 3146                    buffer
 3147                        .update(&mut cx, |buffer, _| {
 3148                            buffer.push_transaction(transaction, Instant::now());
 3149                        })
 3150                        .ok();
 3151                }
 3152                editor.update(&mut cx, |editor, cx| {
 3153                    editor.refresh_document_highlights(cx);
 3154                })?;
 3155            }
 3156            Ok(())
 3157        }))
 3158    }
 3159
 3160    fn show_completions(&mut self, _: &ShowCompletions, cx: &mut ViewContext<Self>) {
 3161        if self.pending_rename.is_some() {
 3162            return;
 3163        }
 3164
 3165        let Some(provider) = self.completion_provider.as_ref() else {
 3166            return;
 3167        };
 3168
 3169        let position = self.selections.newest_anchor().head();
 3170        let (buffer, buffer_position) = if let Some(output) = self
 3171            .buffer
 3172            .read(cx)
 3173            .text_anchor_for_position(position.clone(), cx)
 3174        {
 3175            output
 3176        } else {
 3177            return;
 3178        };
 3179
 3180        let query = Self::completion_query(&self.buffer.read(cx).read(cx), position.clone());
 3181        let completions = provider.completions(&buffer, buffer_position, cx);
 3182
 3183        let id = post_inc(&mut self.next_completion_id);
 3184        let task = cx.spawn(|this, mut cx| {
 3185            async move {
 3186                let completions = completions.await.log_err();
 3187                let menu = if let Some(completions) = completions {
 3188                    let mut menu = CompletionsMenu {
 3189                        id,
 3190                        initial_position: position,
 3191                        match_candidates: completions
 3192                            .iter()
 3193                            .enumerate()
 3194                            .map(|(id, completion)| {
 3195                                StringMatchCandidate::new(
 3196                                    id,
 3197                                    completion.label.text[completion.label.filter_range.clone()]
 3198                                        .into(),
 3199                                )
 3200                            })
 3201                            .collect(),
 3202                        buffer,
 3203                        completions: Arc::new(RwLock::new(completions.into())),
 3204                        matches: Vec::new().into(),
 3205                        selected_item: 0,
 3206                        scroll_handle: UniformListScrollHandle::new(),
 3207                        selected_completion_documentation_resolve_debounce: Arc::new(Mutex::new(
 3208                            DebouncedDelay::new(),
 3209                        )),
 3210                    };
 3211                    menu.filter(query.as_deref(), cx.background_executor().clone())
 3212                        .await;
 3213
 3214                    if menu.matches.is_empty() {
 3215                        None
 3216                    } else {
 3217                        this.update(&mut cx, |editor, cx| {
 3218                            let completions = menu.completions.clone();
 3219                            let matches = menu.matches.clone();
 3220
 3221                            let delay_ms = EditorSettings::get_global(cx)
 3222                                .completion_documentation_secondary_query_debounce;
 3223                            let delay = Duration::from_millis(delay_ms);
 3224
 3225                            editor
 3226                                .completion_documentation_pre_resolve_debounce
 3227                                .fire_new(delay, cx, |editor, cx| {
 3228                                    CompletionsMenu::pre_resolve_completion_documentation(
 3229                                        completions,
 3230                                        matches,
 3231                                        editor,
 3232                                        cx,
 3233                                    )
 3234                                });
 3235                        })
 3236                        .ok();
 3237                        Some(menu)
 3238                    }
 3239                } else {
 3240                    None
 3241                };
 3242
 3243                this.update(&mut cx, |this, cx| {
 3244                    this.completion_tasks.retain(|(task_id, _)| *task_id >= id);
 3245
 3246                    let mut context_menu = this.context_menu.write();
 3247                    match context_menu.as_ref() {
 3248                        None => {}
 3249
 3250                        Some(ContextMenu::Completions(prev_menu)) => {
 3251                            if prev_menu.id > id {
 3252                                return;
 3253                            }
 3254                        }
 3255
 3256                        _ => return,
 3257                    }
 3258
 3259                    if this.focus_handle.is_focused(cx) && menu.is_some() {
 3260                        let menu = menu.unwrap();
 3261                        *context_menu = Some(ContextMenu::Completions(menu));
 3262                        drop(context_menu);
 3263                        this.discard_copilot_suggestion(cx);
 3264                        cx.notify();
 3265                    } else if this.completion_tasks.len() <= 1 {
 3266                        // If there are no more completion tasks and the last menu was
 3267                        // empty, we should hide it. If it was already hidden, we should
 3268                        // also show the copilot suggestion when available.
 3269                        drop(context_menu);
 3270                        if this.hide_context_menu(cx).is_none() {
 3271                            this.update_visible_copilot_suggestion(cx);
 3272                        }
 3273                    }
 3274                })?;
 3275
 3276                Ok::<_, anyhow::Error>(())
 3277            }
 3278            .log_err()
 3279        });
 3280
 3281        self.completion_tasks.push((id, task));
 3282    }
 3283
 3284    pub fn confirm_completion(
 3285        &mut self,
 3286        action: &ConfirmCompletion,
 3287        cx: &mut ViewContext<Self>,
 3288    ) -> Option<Task<Result<()>>> {
 3289        use language::ToOffset as _;
 3290
 3291        let completions_menu = if let ContextMenu::Completions(menu) = self.hide_context_menu(cx)? {
 3292            menu
 3293        } else {
 3294            return None;
 3295        };
 3296
 3297        let mat = completions_menu
 3298            .matches
 3299            .get(action.item_ix.unwrap_or(completions_menu.selected_item))?;
 3300        let buffer_handle = completions_menu.buffer;
 3301        let completions = completions_menu.completions.read();
 3302        let completion = completions.get(mat.candidate_id)?;
 3303        cx.stop_propagation();
 3304
 3305        let snippet;
 3306        let text;
 3307        if completion.is_snippet() {
 3308            snippet = Some(Snippet::parse(&completion.new_text).log_err()?);
 3309            text = snippet.as_ref().unwrap().text.clone();
 3310        } else {
 3311            snippet = None;
 3312            text = completion.new_text.clone();
 3313        };
 3314        let selections = self.selections.all::<usize>(cx);
 3315        let buffer = buffer_handle.read(cx);
 3316        let old_range = completion.old_range.to_offset(buffer);
 3317        let old_text = buffer.text_for_range(old_range.clone()).collect::<String>();
 3318
 3319        let newest_selection = self.selections.newest_anchor();
 3320        if newest_selection.start.buffer_id != Some(buffer_handle.read(cx).remote_id()) {
 3321            return None;
 3322        }
 3323
 3324        let lookbehind = newest_selection
 3325            .start
 3326            .text_anchor
 3327            .to_offset(buffer)
 3328            .saturating_sub(old_range.start);
 3329        let lookahead = old_range
 3330            .end
 3331            .saturating_sub(newest_selection.end.text_anchor.to_offset(buffer));
 3332        let mut common_prefix_len = old_text
 3333            .bytes()
 3334            .zip(text.bytes())
 3335            .take_while(|(a, b)| a == b)
 3336            .count();
 3337
 3338        let snapshot = self.buffer.read(cx).snapshot(cx);
 3339        let mut range_to_replace: Option<Range<isize>> = None;
 3340        let mut ranges = Vec::new();
 3341        for selection in &selections {
 3342            if snapshot.contains_str_at(selection.start.saturating_sub(lookbehind), &old_text) {
 3343                let start = selection.start.saturating_sub(lookbehind);
 3344                let end = selection.end + lookahead;
 3345                if selection.id == newest_selection.id {
 3346                    range_to_replace = Some(
 3347                        ((start + common_prefix_len) as isize - selection.start as isize)
 3348                            ..(end as isize - selection.start as isize),
 3349                    );
 3350                }
 3351                ranges.push(start + common_prefix_len..end);
 3352            } else {
 3353                common_prefix_len = 0;
 3354                ranges.clear();
 3355                ranges.extend(selections.iter().map(|s| {
 3356                    if s.id == newest_selection.id {
 3357                        range_to_replace = Some(
 3358                            old_range.start.to_offset_utf16(&snapshot).0 as isize
 3359                                - selection.start as isize
 3360                                ..old_range.end.to_offset_utf16(&snapshot).0 as isize
 3361                                    - selection.start as isize,
 3362                        );
 3363                        old_range.clone()
 3364                    } else {
 3365                        s.start..s.end
 3366                    }
 3367                }));
 3368                break;
 3369            }
 3370        }
 3371        let text = &text[common_prefix_len..];
 3372
 3373        cx.emit(EditorEvent::InputHandled {
 3374            utf16_range_to_replace: range_to_replace,
 3375            text: text.into(),
 3376        });
 3377
 3378        self.transact(cx, |this, cx| {
 3379            if let Some(mut snippet) = snippet {
 3380                snippet.text = text.to_string();
 3381                for tabstop in snippet.tabstops.iter_mut().flatten() {
 3382                    tabstop.start -= common_prefix_len as isize;
 3383                    tabstop.end -= common_prefix_len as isize;
 3384                }
 3385
 3386                this.insert_snippet(&ranges, snippet, cx).log_err();
 3387            } else {
 3388                this.buffer.update(cx, |buffer, cx| {
 3389                    buffer.edit(
 3390                        ranges.iter().map(|range| (range.clone(), text)),
 3391                        this.autoindent_mode.clone(),
 3392                        cx,
 3393                    );
 3394                });
 3395            }
 3396
 3397            this.refresh_copilot_suggestions(true, cx);
 3398        });
 3399
 3400        let provider = self.completion_provider.as_ref()?;
 3401        let apply_edits = provider.apply_additional_edits_for_completion(
 3402            buffer_handle,
 3403            completion.clone(),
 3404            true,
 3405            cx,
 3406        );
 3407        Some(cx.foreground_executor().spawn(async move {
 3408            apply_edits.await?;
 3409            Ok(())
 3410        }))
 3411    }
 3412
 3413    pub fn toggle_code_actions(&mut self, action: &ToggleCodeActions, cx: &mut ViewContext<Self>) {
 3414        let mut context_menu = self.context_menu.write();
 3415        if matches!(context_menu.as_ref(), Some(ContextMenu::CodeActions(_))) {
 3416            *context_menu = None;
 3417            cx.notify();
 3418            return;
 3419        }
 3420        drop(context_menu);
 3421
 3422        let deployed_from_indicator = action.deployed_from_indicator;
 3423        let mut task = self.code_actions_task.take();
 3424        cx.spawn(|this, mut cx| async move {
 3425            while let Some(prev_task) = task {
 3426                prev_task.await;
 3427                task = this.update(&mut cx, |this, _| this.code_actions_task.take())?;
 3428            }
 3429
 3430            this.update(&mut cx, |this, cx| {
 3431                if this.focus_handle.is_focused(cx) {
 3432                    if let Some((buffer, actions)) = this.available_code_actions.clone() {
 3433                        this.completion_tasks.clear();
 3434                        this.discard_copilot_suggestion(cx);
 3435                        *this.context_menu.write() =
 3436                            Some(ContextMenu::CodeActions(CodeActionsMenu {
 3437                                buffer,
 3438                                actions,
 3439                                selected_item: Default::default(),
 3440                                scroll_handle: UniformListScrollHandle::default(),
 3441                                deployed_from_indicator,
 3442                            }));
 3443                        cx.notify();
 3444                    }
 3445                }
 3446            })?;
 3447
 3448            Ok::<_, anyhow::Error>(())
 3449        })
 3450        .detach_and_log_err(cx);
 3451    }
 3452
 3453    pub fn confirm_code_action(
 3454        &mut self,
 3455        action: &ConfirmCodeAction,
 3456        cx: &mut ViewContext<Self>,
 3457    ) -> Option<Task<Result<()>>> {
 3458        let actions_menu = if let ContextMenu::CodeActions(menu) = self.hide_context_menu(cx)? {
 3459            menu
 3460        } else {
 3461            return None;
 3462        };
 3463        let action_ix = action.item_ix.unwrap_or(actions_menu.selected_item);
 3464        let action = actions_menu.actions.get(action_ix)?.clone();
 3465        let title = action.lsp_action.title.clone();
 3466        let buffer = actions_menu.buffer;
 3467        let workspace = self.workspace()?;
 3468
 3469        let apply_code_actions = workspace
 3470            .read(cx)
 3471            .project()
 3472            .clone()
 3473            .update(cx, |project, cx| {
 3474                project.apply_code_action(buffer, action, true, cx)
 3475            });
 3476        let workspace = workspace.downgrade();
 3477        Some(cx.spawn(|editor, cx| async move {
 3478            let project_transaction = apply_code_actions.await?;
 3479            Self::open_project_transaction(&editor, workspace, project_transaction, title, cx).await
 3480        }))
 3481    }
 3482
 3483    async fn open_project_transaction(
 3484        this: &WeakView<Editor>,
 3485        workspace: WeakView<Workspace>,
 3486        transaction: ProjectTransaction,
 3487        title: String,
 3488        mut cx: AsyncWindowContext,
 3489    ) -> Result<()> {
 3490        let replica_id = this.update(&mut cx, |this, cx| this.replica_id(cx))?;
 3491
 3492        let mut entries = transaction.0.into_iter().collect::<Vec<_>>();
 3493        cx.update(|cx| {
 3494            entries.sort_unstable_by_key(|(buffer, _)| {
 3495                buffer.read(cx).file().map(|f| f.path().clone())
 3496            });
 3497        })?;
 3498
 3499        // If the project transaction's edits are all contained within this editor, then
 3500        // avoid opening a new editor to display them.
 3501
 3502        if let Some((buffer, transaction)) = entries.first() {
 3503            if entries.len() == 1 {
 3504                let excerpt = this.update(&mut cx, |editor, cx| {
 3505                    editor
 3506                        .buffer()
 3507                        .read(cx)
 3508                        .excerpt_containing(editor.selections.newest_anchor().head(), cx)
 3509                })?;
 3510                if let Some((_, excerpted_buffer, excerpt_range)) = excerpt {
 3511                    if excerpted_buffer == *buffer {
 3512                        let all_edits_within_excerpt = buffer.read_with(&cx, |buffer, _| {
 3513                            let excerpt_range = excerpt_range.to_offset(buffer);
 3514                            buffer
 3515                                .edited_ranges_for_transaction::<usize>(transaction)
 3516                                .all(|range| {
 3517                                    excerpt_range.start <= range.start
 3518                                        && excerpt_range.end >= range.end
 3519                                })
 3520                        })?;
 3521
 3522                        if all_edits_within_excerpt {
 3523                            return Ok(());
 3524                        }
 3525                    }
 3526                }
 3527            }
 3528        } else {
 3529            return Ok(());
 3530        }
 3531
 3532        let mut ranges_to_highlight = Vec::new();
 3533        let excerpt_buffer = cx.new_model(|cx| {
 3534            let mut multibuffer =
 3535                MultiBuffer::new(replica_id, Capability::ReadWrite).with_title(title);
 3536            for (buffer_handle, transaction) in &entries {
 3537                let buffer = buffer_handle.read(cx);
 3538                ranges_to_highlight.extend(
 3539                    multibuffer.push_excerpts_with_context_lines(
 3540                        buffer_handle.clone(),
 3541                        buffer
 3542                            .edited_ranges_for_transaction::<usize>(transaction)
 3543                            .collect(),
 3544                        1,
 3545                        cx,
 3546                    ),
 3547                );
 3548            }
 3549            multibuffer.push_transaction(entries.iter().map(|(b, t)| (b, t)), cx);
 3550            multibuffer
 3551        })?;
 3552
 3553        workspace.update(&mut cx, |workspace, cx| {
 3554            let project = workspace.project().clone();
 3555            let editor =
 3556                cx.new_view(|cx| Editor::for_multibuffer(excerpt_buffer, Some(project), cx));
 3557            workspace.add_item(Box::new(editor.clone()), cx);
 3558            editor.update(cx, |editor, cx| {
 3559                editor.highlight_background::<Self>(
 3560                    ranges_to_highlight,
 3561                    |theme| theme.editor_highlighted_line_background,
 3562                    cx,
 3563                );
 3564            });
 3565        })?;
 3566
 3567        Ok(())
 3568    }
 3569
 3570    fn refresh_code_actions(&mut self, cx: &mut ViewContext<Self>) -> Option<()> {
 3571        let project = self.project.clone()?;
 3572        let buffer = self.buffer.read(cx);
 3573        let newest_selection = self.selections.newest_anchor().clone();
 3574        let (start_buffer, start) = buffer.text_anchor_for_position(newest_selection.start, cx)?;
 3575        let (end_buffer, end) = buffer.text_anchor_for_position(newest_selection.end, cx)?;
 3576        if start_buffer != end_buffer {
 3577            return None;
 3578        }
 3579
 3580        self.code_actions_task = Some(cx.spawn(|this, mut cx| async move {
 3581            cx.background_executor()
 3582                .timer(CODE_ACTIONS_DEBOUNCE_TIMEOUT)
 3583                .await;
 3584
 3585            let actions = if let Ok(code_actions) = project.update(&mut cx, |project, cx| {
 3586                project.code_actions(&start_buffer, start..end, cx)
 3587            }) {
 3588                code_actions.await.log_err()
 3589            } else {
 3590                None
 3591            };
 3592
 3593            this.update(&mut cx, |this, cx| {
 3594                this.available_code_actions = actions.and_then(|actions| {
 3595                    if actions.is_empty() {
 3596                        None
 3597                    } else {
 3598                        Some((start_buffer, actions.into()))
 3599                    }
 3600                });
 3601                cx.notify();
 3602            })
 3603            .log_err();
 3604        }));
 3605        None
 3606    }
 3607
 3608    fn refresh_document_highlights(&mut self, cx: &mut ViewContext<Self>) -> Option<()> {
 3609        if self.pending_rename.is_some() {
 3610            return None;
 3611        }
 3612
 3613        let project = self.project.clone()?;
 3614        let buffer = self.buffer.read(cx);
 3615        let newest_selection = self.selections.newest_anchor().clone();
 3616        let cursor_position = newest_selection.head();
 3617        let (cursor_buffer, cursor_buffer_position) =
 3618            buffer.text_anchor_for_position(cursor_position.clone(), cx)?;
 3619        let (tail_buffer, _) = buffer.text_anchor_for_position(newest_selection.tail(), cx)?;
 3620        if cursor_buffer != tail_buffer {
 3621            return None;
 3622        }
 3623
 3624        self.document_highlights_task = Some(cx.spawn(|this, mut cx| async move {
 3625            cx.background_executor()
 3626                .timer(DOCUMENT_HIGHLIGHTS_DEBOUNCE_TIMEOUT)
 3627                .await;
 3628
 3629            let highlights = if let Some(highlights) = project
 3630                .update(&mut cx, |project, cx| {
 3631                    project.document_highlights(&cursor_buffer, cursor_buffer_position, cx)
 3632                })
 3633                .log_err()
 3634            {
 3635                highlights.await.log_err()
 3636            } else {
 3637                None
 3638            };
 3639
 3640            if let Some(highlights) = highlights {
 3641                this.update(&mut cx, |this, cx| {
 3642                    if this.pending_rename.is_some() {
 3643                        return;
 3644                    }
 3645
 3646                    let buffer_id = cursor_position.buffer_id;
 3647                    let buffer = this.buffer.read(cx);
 3648                    if !buffer
 3649                        .text_anchor_for_position(cursor_position, cx)
 3650                        .map_or(false, |(buffer, _)| buffer == cursor_buffer)
 3651                    {
 3652                        return;
 3653                    }
 3654
 3655                    let cursor_buffer_snapshot = cursor_buffer.read(cx);
 3656                    let mut write_ranges = Vec::new();
 3657                    let mut read_ranges = Vec::new();
 3658                    for highlight in highlights {
 3659                        for (excerpt_id, excerpt_range) in
 3660                            buffer.excerpts_for_buffer(&cursor_buffer, cx)
 3661                        {
 3662                            let start = highlight
 3663                                .range
 3664                                .start
 3665                                .max(&excerpt_range.context.start, cursor_buffer_snapshot);
 3666                            let end = highlight
 3667                                .range
 3668                                .end
 3669                                .min(&excerpt_range.context.end, cursor_buffer_snapshot);
 3670                            if start.cmp(&end, cursor_buffer_snapshot).is_ge() {
 3671                                continue;
 3672                            }
 3673
 3674                            let range = Anchor {
 3675                                buffer_id,
 3676                                excerpt_id: excerpt_id.clone(),
 3677                                text_anchor: start,
 3678                            }..Anchor {
 3679                                buffer_id,
 3680                                excerpt_id,
 3681                                text_anchor: end,
 3682                            };
 3683                            if highlight.kind == lsp::DocumentHighlightKind::WRITE {
 3684                                write_ranges.push(range);
 3685                            } else {
 3686                                read_ranges.push(range);
 3687                            }
 3688                        }
 3689                    }
 3690
 3691                    this.highlight_background::<DocumentHighlightRead>(
 3692                        read_ranges,
 3693                        |theme| theme.editor_document_highlight_read_background,
 3694                        cx,
 3695                    );
 3696                    this.highlight_background::<DocumentHighlightWrite>(
 3697                        write_ranges,
 3698                        |theme| theme.editor_document_highlight_write_background,
 3699                        cx,
 3700                    );
 3701                    cx.notify();
 3702                })
 3703                .log_err();
 3704            }
 3705        }));
 3706        None
 3707    }
 3708
 3709    fn refresh_copilot_suggestions(
 3710        &mut self,
 3711        debounce: bool,
 3712        cx: &mut ViewContext<Self>,
 3713    ) -> Option<()> {
 3714        let copilot = Copilot::global(cx)?;
 3715        if !self.show_copilot_suggestions || !copilot.read(cx).status().is_authorized() {
 3716            self.clear_copilot_suggestions(cx);
 3717            return None;
 3718        }
 3719        self.update_visible_copilot_suggestion(cx);
 3720
 3721        let snapshot = self.buffer.read(cx).snapshot(cx);
 3722        let cursor = self.selections.newest_anchor().head();
 3723        if !self.is_copilot_enabled_at(cursor, &snapshot, cx) {
 3724            self.clear_copilot_suggestions(cx);
 3725            return None;
 3726        }
 3727
 3728        let (buffer, buffer_position) =
 3729            self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
 3730        self.copilot_state.pending_refresh = cx.spawn(|this, mut cx| async move {
 3731            if debounce {
 3732                cx.background_executor()
 3733                    .timer(COPILOT_DEBOUNCE_TIMEOUT)
 3734                    .await;
 3735            }
 3736
 3737            let completions = copilot
 3738                .update(&mut cx, |copilot, cx| {
 3739                    copilot.completions(&buffer, buffer_position, cx)
 3740                })
 3741                .log_err()
 3742                .unwrap_or(Task::ready(Ok(Vec::new())))
 3743                .await
 3744                .log_err()
 3745                .into_iter()
 3746                .flatten()
 3747                .collect_vec();
 3748
 3749            this.update(&mut cx, |this, cx| {
 3750                if !completions.is_empty() {
 3751                    this.copilot_state.cycled = false;
 3752                    this.copilot_state.pending_cycling_refresh = Task::ready(None);
 3753                    this.copilot_state.completions.clear();
 3754                    this.copilot_state.active_completion_index = 0;
 3755                    this.copilot_state.excerpt_id = Some(cursor.excerpt_id);
 3756                    for completion in completions {
 3757                        this.copilot_state.push_completion(completion);
 3758                    }
 3759                    this.update_visible_copilot_suggestion(cx);
 3760                }
 3761            })
 3762            .log_err()?;
 3763            Some(())
 3764        });
 3765
 3766        Some(())
 3767    }
 3768
 3769    fn cycle_copilot_suggestions(
 3770        &mut self,
 3771        direction: Direction,
 3772        cx: &mut ViewContext<Self>,
 3773    ) -> Option<()> {
 3774        let copilot = Copilot::global(cx)?;
 3775        if !self.show_copilot_suggestions || !copilot.read(cx).status().is_authorized() {
 3776            return None;
 3777        }
 3778
 3779        if self.copilot_state.cycled {
 3780            self.copilot_state.cycle_completions(direction);
 3781            self.update_visible_copilot_suggestion(cx);
 3782        } else {
 3783            let cursor = self.selections.newest_anchor().head();
 3784            let (buffer, buffer_position) =
 3785                self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
 3786            self.copilot_state.pending_cycling_refresh = cx.spawn(|this, mut cx| async move {
 3787                let completions = copilot
 3788                    .update(&mut cx, |copilot, cx| {
 3789                        copilot.completions_cycling(&buffer, buffer_position, cx)
 3790                    })
 3791                    .log_err()?
 3792                    .await;
 3793
 3794                this.update(&mut cx, |this, cx| {
 3795                    this.copilot_state.cycled = true;
 3796                    for completion in completions.log_err().into_iter().flatten() {
 3797                        this.copilot_state.push_completion(completion);
 3798                    }
 3799                    this.copilot_state.cycle_completions(direction);
 3800                    this.update_visible_copilot_suggestion(cx);
 3801                })
 3802                .log_err()?;
 3803
 3804                Some(())
 3805            });
 3806        }
 3807
 3808        Some(())
 3809    }
 3810
 3811    fn copilot_suggest(&mut self, _: &copilot::Suggest, cx: &mut ViewContext<Self>) {
 3812        if !self.has_active_copilot_suggestion(cx) {
 3813            self.refresh_copilot_suggestions(false, cx);
 3814            return;
 3815        }
 3816
 3817        self.update_visible_copilot_suggestion(cx);
 3818    }
 3819
 3820    pub fn display_cursor_names(&mut self, _: &DisplayCursorNames, cx: &mut ViewContext<Self>) {
 3821        self.show_cursor_names(cx);
 3822    }
 3823
 3824    fn show_cursor_names(&mut self, cx: &mut ViewContext<Self>) {
 3825        self.show_cursor_names = true;
 3826        cx.notify();
 3827        cx.spawn(|this, mut cx| async move {
 3828            cx.background_executor().timer(CURSORS_VISIBLE_FOR).await;
 3829            this.update(&mut cx, |this, cx| {
 3830                this.show_cursor_names = false;
 3831                cx.notify()
 3832            })
 3833            .ok()
 3834        })
 3835        .detach();
 3836    }
 3837
 3838    fn next_copilot_suggestion(&mut self, _: &copilot::NextSuggestion, cx: &mut ViewContext<Self>) {
 3839        if self.has_active_copilot_suggestion(cx) {
 3840            self.cycle_copilot_suggestions(Direction::Next, cx);
 3841        } else {
 3842            let is_copilot_disabled = self.refresh_copilot_suggestions(false, cx).is_none();
 3843            if is_copilot_disabled {
 3844                cx.propagate();
 3845            }
 3846        }
 3847    }
 3848
 3849    fn previous_copilot_suggestion(
 3850        &mut self,
 3851        _: &copilot::PreviousSuggestion,
 3852        cx: &mut ViewContext<Self>,
 3853    ) {
 3854        if self.has_active_copilot_suggestion(cx) {
 3855            self.cycle_copilot_suggestions(Direction::Prev, cx);
 3856        } else {
 3857            let is_copilot_disabled = self.refresh_copilot_suggestions(false, cx).is_none();
 3858            if is_copilot_disabled {
 3859                cx.propagate();
 3860            }
 3861        }
 3862    }
 3863
 3864    fn accept_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) -> bool {
 3865        if let Some(suggestion) = self.take_active_copilot_suggestion(cx) {
 3866            if let Some((copilot, completion)) =
 3867                Copilot::global(cx).zip(self.copilot_state.active_completion())
 3868            {
 3869                copilot
 3870                    .update(cx, |copilot, cx| copilot.accept_completion(completion, cx))
 3871                    .detach_and_log_err(cx);
 3872
 3873                self.report_copilot_event(Some(completion.uuid.clone()), true, cx)
 3874            }
 3875            cx.emit(EditorEvent::InputHandled {
 3876                utf16_range_to_replace: None,
 3877                text: suggestion.text.to_string().into(),
 3878            });
 3879            self.insert_with_autoindent_mode(&suggestion.text.to_string(), None, cx);
 3880            cx.notify();
 3881            true
 3882        } else {
 3883            false
 3884        }
 3885    }
 3886
 3887    fn discard_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) -> bool {
 3888        if let Some(suggestion) = self.take_active_copilot_suggestion(cx) {
 3889            if let Some(copilot) = Copilot::global(cx) {
 3890                copilot
 3891                    .update(cx, |copilot, cx| {
 3892                        copilot.discard_completions(&self.copilot_state.completions, cx)
 3893                    })
 3894                    .detach_and_log_err(cx);
 3895
 3896                self.report_copilot_event(None, false, cx)
 3897            }
 3898
 3899            self.display_map.update(cx, |map, cx| {
 3900                map.splice_inlays(vec![suggestion.id], Vec::new(), cx)
 3901            });
 3902            cx.notify();
 3903            true
 3904        } else {
 3905            false
 3906        }
 3907    }
 3908
 3909    fn is_copilot_enabled_at(
 3910        &self,
 3911        location: Anchor,
 3912        snapshot: &MultiBufferSnapshot,
 3913        cx: &mut ViewContext<Self>,
 3914    ) -> bool {
 3915        let file = snapshot.file_at(location);
 3916        let language = snapshot.language_at(location);
 3917        let settings = all_language_settings(file, cx);
 3918        self.show_copilot_suggestions
 3919            && settings.copilot_enabled(language, file.map(|f| f.path().as_ref()))
 3920    }
 3921
 3922    fn has_active_copilot_suggestion(&self, cx: &AppContext) -> bool {
 3923        if let Some(suggestion) = self.copilot_state.suggestion.as_ref() {
 3924            let buffer = self.buffer.read(cx).read(cx);
 3925            suggestion.position.is_valid(&buffer)
 3926        } else {
 3927            false
 3928        }
 3929    }
 3930
 3931    fn take_active_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) -> Option<Inlay> {
 3932        let suggestion = self.copilot_state.suggestion.take()?;
 3933        self.display_map.update(cx, |map, cx| {
 3934            map.splice_inlays(vec![suggestion.id], Default::default(), cx);
 3935        });
 3936        let buffer = self.buffer.read(cx).read(cx);
 3937
 3938        if suggestion.position.is_valid(&buffer) {
 3939            Some(suggestion)
 3940        } else {
 3941            None
 3942        }
 3943    }
 3944
 3945    fn update_visible_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) {
 3946        let snapshot = self.buffer.read(cx).snapshot(cx);
 3947        let selection = self.selections.newest_anchor();
 3948        let cursor = selection.head();
 3949
 3950        if self.context_menu.read().is_some()
 3951            || !self.completion_tasks.is_empty()
 3952            || selection.start != selection.end
 3953        {
 3954            self.discard_copilot_suggestion(cx);
 3955        } else if let Some(text) = self
 3956            .copilot_state
 3957            .text_for_active_completion(cursor, &snapshot)
 3958        {
 3959            let text = Rope::from(text);
 3960            let mut to_remove = Vec::new();
 3961            if let Some(suggestion) = self.copilot_state.suggestion.take() {
 3962                to_remove.push(suggestion.id);
 3963            }
 3964
 3965            let suggestion_inlay =
 3966                Inlay::suggestion(post_inc(&mut self.next_inlay_id), cursor, text);
 3967            self.copilot_state.suggestion = Some(suggestion_inlay.clone());
 3968            self.display_map.update(cx, move |map, cx| {
 3969                map.splice_inlays(to_remove, vec![suggestion_inlay], cx)
 3970            });
 3971            cx.notify();
 3972        } else {
 3973            self.discard_copilot_suggestion(cx);
 3974        }
 3975    }
 3976
 3977    fn clear_copilot_suggestions(&mut self, cx: &mut ViewContext<Self>) {
 3978        self.copilot_state = Default::default();
 3979        self.discard_copilot_suggestion(cx);
 3980    }
 3981
 3982    pub fn render_code_actions_indicator(
 3983        &self,
 3984        _style: &EditorStyle,
 3985        is_active: bool,
 3986        cx: &mut ViewContext<Self>,
 3987    ) -> Option<IconButton> {
 3988        if self.available_code_actions.is_some() {
 3989            Some(
 3990                IconButton::new("code_actions_indicator", ui::IconName::Bolt)
 3991                    .icon_size(IconSize::Small)
 3992                    .icon_color(Color::Muted)
 3993                    .selected(is_active)
 3994                    .on_click(cx.listener(|editor, _e, cx| {
 3995                        editor.toggle_code_actions(
 3996                            &ToggleCodeActions {
 3997                                deployed_from_indicator: true,
 3998                            },
 3999                            cx,
 4000                        );
 4001                    })),
 4002            )
 4003        } else {
 4004            None
 4005        }
 4006    }
 4007
 4008    pub fn render_fold_indicators(
 4009        &self,
 4010        fold_data: Vec<Option<(FoldStatus, u32, bool)>>,
 4011        _style: &EditorStyle,
 4012        gutter_hovered: bool,
 4013        _line_height: Pixels,
 4014        _gutter_margin: Pixels,
 4015        editor_view: View<Editor>,
 4016    ) -> Vec<Option<IconButton>> {
 4017        fold_data
 4018            .iter()
 4019            .enumerate()
 4020            .map(|(ix, fold_data)| {
 4021                fold_data
 4022                    .map(|(fold_status, buffer_row, active)| {
 4023                        (active || gutter_hovered || fold_status == FoldStatus::Folded).then(|| {
 4024                            IconButton::new(ix as usize, ui::IconName::ChevronDown)
 4025                                .on_click({
 4026                                    let view = editor_view.clone();
 4027                                    move |_e, cx| {
 4028                                        view.update(cx, |editor, cx| match fold_status {
 4029                                            FoldStatus::Folded => {
 4030                                                editor.unfold_at(&UnfoldAt { buffer_row }, cx);
 4031                                            }
 4032                                            FoldStatus::Foldable => {
 4033                                                editor.fold_at(&FoldAt { buffer_row }, cx);
 4034                                            }
 4035                                        })
 4036                                    }
 4037                                })
 4038                                .icon_color(ui::Color::Muted)
 4039                                .icon_size(ui::IconSize::Small)
 4040                                .selected(fold_status == FoldStatus::Folded)
 4041                                .selected_icon(ui::IconName::ChevronRight)
 4042                                .size(ui::ButtonSize::None)
 4043                        })
 4044                    })
 4045                    .flatten()
 4046            })
 4047            .collect()
 4048    }
 4049
 4050    pub fn context_menu_visible(&self) -> bool {
 4051        self.context_menu
 4052            .read()
 4053            .as_ref()
 4054            .map_or(false, |menu| menu.visible())
 4055    }
 4056
 4057    pub fn render_context_menu(
 4058        &self,
 4059        cursor_position: DisplayPoint,
 4060        style: &EditorStyle,
 4061        max_height: Pixels,
 4062        cx: &mut ViewContext<Editor>,
 4063    ) -> Option<(DisplayPoint, AnyElement)> {
 4064        self.context_menu.read().as_ref().map(|menu| {
 4065            menu.render(
 4066                cursor_position,
 4067                style,
 4068                max_height,
 4069                self.workspace.as_ref().map(|(w, _)| w.clone()),
 4070                cx,
 4071            )
 4072        })
 4073    }
 4074
 4075    fn hide_context_menu(&mut self, cx: &mut ViewContext<Self>) -> Option<ContextMenu> {
 4076        cx.notify();
 4077        self.completion_tasks.clear();
 4078        let context_menu = self.context_menu.write().take();
 4079        if context_menu.is_some() {
 4080            self.update_visible_copilot_suggestion(cx);
 4081        }
 4082        context_menu
 4083    }
 4084
 4085    pub fn insert_snippet(
 4086        &mut self,
 4087        insertion_ranges: &[Range<usize>],
 4088        snippet: Snippet,
 4089        cx: &mut ViewContext<Self>,
 4090    ) -> Result<()> {
 4091        let tabstops = self.buffer.update(cx, |buffer, cx| {
 4092            let snippet_text: Arc<str> = snippet.text.clone().into();
 4093            buffer.edit(
 4094                insertion_ranges
 4095                    .iter()
 4096                    .cloned()
 4097                    .map(|range| (range, snippet_text.clone())),
 4098                Some(AutoindentMode::EachLine),
 4099                cx,
 4100            );
 4101
 4102            let snapshot = &*buffer.read(cx);
 4103            let snippet = &snippet;
 4104            snippet
 4105                .tabstops
 4106                .iter()
 4107                .map(|tabstop| {
 4108                    let mut tabstop_ranges = tabstop
 4109                        .iter()
 4110                        .flat_map(|tabstop_range| {
 4111                            let mut delta = 0_isize;
 4112                            insertion_ranges.iter().map(move |insertion_range| {
 4113                                let insertion_start = insertion_range.start as isize + delta;
 4114                                delta +=
 4115                                    snippet.text.len() as isize - insertion_range.len() as isize;
 4116
 4117                                let start = snapshot.anchor_before(
 4118                                    (insertion_start + tabstop_range.start) as usize,
 4119                                );
 4120                                let end = snapshot
 4121                                    .anchor_after((insertion_start + tabstop_range.end) as usize);
 4122                                start..end
 4123                            })
 4124                        })
 4125                        .collect::<Vec<_>>();
 4126                    tabstop_ranges.sort_unstable_by(|a, b| a.start.cmp(&b.start, snapshot));
 4127                    tabstop_ranges
 4128                })
 4129                .collect::<Vec<_>>()
 4130        });
 4131
 4132        if let Some(tabstop) = tabstops.first() {
 4133            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 4134                s.select_ranges(tabstop.iter().cloned());
 4135            });
 4136            self.snippet_stack.push(SnippetState {
 4137                active_index: 0,
 4138                ranges: tabstops,
 4139            });
 4140        }
 4141
 4142        Ok(())
 4143    }
 4144
 4145    pub fn move_to_next_snippet_tabstop(&mut self, cx: &mut ViewContext<Self>) -> bool {
 4146        self.move_to_snippet_tabstop(Bias::Right, cx)
 4147    }
 4148
 4149    pub fn move_to_prev_snippet_tabstop(&mut self, cx: &mut ViewContext<Self>) -> bool {
 4150        self.move_to_snippet_tabstop(Bias::Left, cx)
 4151    }
 4152
 4153    pub fn move_to_snippet_tabstop(&mut self, bias: Bias, cx: &mut ViewContext<Self>) -> bool {
 4154        if let Some(mut snippet) = self.snippet_stack.pop() {
 4155            match bias {
 4156                Bias::Left => {
 4157                    if snippet.active_index > 0 {
 4158                        snippet.active_index -= 1;
 4159                    } else {
 4160                        self.snippet_stack.push(snippet);
 4161                        return false;
 4162                    }
 4163                }
 4164                Bias::Right => {
 4165                    if snippet.active_index + 1 < snippet.ranges.len() {
 4166                        snippet.active_index += 1;
 4167                    } else {
 4168                        self.snippet_stack.push(snippet);
 4169                        return false;
 4170                    }
 4171                }
 4172            }
 4173            if let Some(current_ranges) = snippet.ranges.get(snippet.active_index) {
 4174                self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 4175                    s.select_anchor_ranges(current_ranges.iter().cloned())
 4176                });
 4177                // If snippet state is not at the last tabstop, push it back on the stack
 4178                if snippet.active_index + 1 < snippet.ranges.len() {
 4179                    self.snippet_stack.push(snippet);
 4180                }
 4181                return true;
 4182            }
 4183        }
 4184
 4185        false
 4186    }
 4187
 4188    pub fn clear(&mut self, cx: &mut ViewContext<Self>) {
 4189        self.transact(cx, |this, cx| {
 4190            this.select_all(&SelectAll, cx);
 4191            this.insert("", cx);
 4192        });
 4193    }
 4194
 4195    pub fn backspace(&mut self, _: &Backspace, cx: &mut ViewContext<Self>) {
 4196        self.transact(cx, |this, cx| {
 4197            this.select_autoclose_pair(cx);
 4198            let mut selections = this.selections.all::<Point>(cx);
 4199            if !this.selections.line_mode {
 4200                let display_map = this.display_map.update(cx, |map, cx| map.snapshot(cx));
 4201                for selection in &mut selections {
 4202                    if selection.is_empty() {
 4203                        let old_head = selection.head();
 4204                        let mut new_head =
 4205                            movement::left(&display_map, old_head.to_display_point(&display_map))
 4206                                .to_point(&display_map);
 4207                        if let Some((buffer, line_buffer_range)) = display_map
 4208                            .buffer_snapshot
 4209                            .buffer_line_for_row(old_head.row)
 4210                        {
 4211                            let indent_size =
 4212                                buffer.indent_size_for_line(line_buffer_range.start.row);
 4213                            let indent_len = match indent_size.kind {
 4214                                IndentKind::Space => {
 4215                                    buffer.settings_at(line_buffer_range.start, cx).tab_size
 4216                                }
 4217                                IndentKind::Tab => NonZeroU32::new(1).unwrap(),
 4218                            };
 4219                            if old_head.column <= indent_size.len && old_head.column > 0 {
 4220                                let indent_len = indent_len.get();
 4221                                new_head = cmp::min(
 4222                                    new_head,
 4223                                    Point::new(
 4224                                        old_head.row,
 4225                                        ((old_head.column - 1) / indent_len) * indent_len,
 4226                                    ),
 4227                                );
 4228                            }
 4229                        }
 4230
 4231                        selection.set_head(new_head, SelectionGoal::None);
 4232                    }
 4233                }
 4234            }
 4235
 4236            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
 4237            this.insert("", cx);
 4238            this.refresh_copilot_suggestions(true, cx);
 4239        });
 4240    }
 4241
 4242    pub fn delete(&mut self, _: &Delete, cx: &mut ViewContext<Self>) {
 4243        self.transact(cx, |this, cx| {
 4244            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 4245                let line_mode = s.line_mode;
 4246                s.move_with(|map, selection| {
 4247                    if selection.is_empty() && !line_mode {
 4248                        let cursor = movement::right(map, selection.head());
 4249                        selection.end = cursor;
 4250                        selection.reversed = true;
 4251                        selection.goal = SelectionGoal::None;
 4252                    }
 4253                })
 4254            });
 4255            this.insert("", cx);
 4256            this.refresh_copilot_suggestions(true, cx);
 4257        });
 4258    }
 4259
 4260    pub fn tab_prev(&mut self, _: &TabPrev, cx: &mut ViewContext<Self>) {
 4261        if self.move_to_prev_snippet_tabstop(cx) {
 4262            return;
 4263        }
 4264
 4265        self.outdent(&Outdent, cx);
 4266    }
 4267
 4268    pub fn tab(&mut self, _: &Tab, cx: &mut ViewContext<Self>) {
 4269        if self.move_to_next_snippet_tabstop(cx) || self.read_only(cx) {
 4270            return;
 4271        }
 4272
 4273        let mut selections = self.selections.all_adjusted(cx);
 4274        let buffer = self.buffer.read(cx);
 4275        let snapshot = buffer.snapshot(cx);
 4276        let rows_iter = selections.iter().map(|s| s.head().row);
 4277        let suggested_indents = snapshot.suggested_indents(rows_iter, cx);
 4278
 4279        let mut edits = Vec::new();
 4280        let mut prev_edited_row = 0;
 4281        let mut row_delta = 0;
 4282        for selection in &mut selections {
 4283            if selection.start.row != prev_edited_row {
 4284                row_delta = 0;
 4285            }
 4286            prev_edited_row = selection.end.row;
 4287
 4288            // If the selection is non-empty, then increase the indentation of the selected lines.
 4289            if !selection.is_empty() {
 4290                row_delta =
 4291                    Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
 4292                continue;
 4293            }
 4294
 4295            // If the selection is empty and the cursor is in the leading whitespace before the
 4296            // suggested indentation, then auto-indent the line.
 4297            let cursor = selection.head();
 4298            let current_indent = snapshot.indent_size_for_line(cursor.row);
 4299            if let Some(suggested_indent) = suggested_indents.get(&cursor.row).copied() {
 4300                if cursor.column < suggested_indent.len
 4301                    && cursor.column <= current_indent.len
 4302                    && current_indent.len <= suggested_indent.len
 4303                {
 4304                    selection.start = Point::new(cursor.row, suggested_indent.len);
 4305                    selection.end = selection.start;
 4306                    if row_delta == 0 {
 4307                        edits.extend(Buffer::edit_for_indent_size_adjustment(
 4308                            cursor.row,
 4309                            current_indent,
 4310                            suggested_indent,
 4311                        ));
 4312                        row_delta = suggested_indent.len - current_indent.len;
 4313                    }
 4314                    continue;
 4315                }
 4316            }
 4317
 4318            // Accept copilot suggestion if there is only one selection and the cursor is not
 4319            // in the leading whitespace.
 4320            if self.selections.count() == 1
 4321                && cursor.column >= current_indent.len
 4322                && self.has_active_copilot_suggestion(cx)
 4323            {
 4324                self.accept_copilot_suggestion(cx);
 4325                return;
 4326            }
 4327
 4328            // Otherwise, insert a hard or soft tab.
 4329            let settings = buffer.settings_at(cursor, cx);
 4330            let tab_size = if settings.hard_tabs {
 4331                IndentSize::tab()
 4332            } else {
 4333                let tab_size = settings.tab_size.get();
 4334                let char_column = snapshot
 4335                    .text_for_range(Point::new(cursor.row, 0)..cursor)
 4336                    .flat_map(str::chars)
 4337                    .count()
 4338                    + row_delta as usize;
 4339                let chars_to_next_tab_stop = tab_size - (char_column as u32 % tab_size);
 4340                IndentSize::spaces(chars_to_next_tab_stop)
 4341            };
 4342            selection.start = Point::new(cursor.row, cursor.column + row_delta + tab_size.len);
 4343            selection.end = selection.start;
 4344            edits.push((cursor..cursor, tab_size.chars().collect::<String>()));
 4345            row_delta += tab_size.len;
 4346        }
 4347
 4348        self.transact(cx, |this, cx| {
 4349            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
 4350            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
 4351            this.refresh_copilot_suggestions(true, cx);
 4352        });
 4353    }
 4354
 4355    pub fn indent(&mut self, _: &Indent, cx: &mut ViewContext<Self>) {
 4356        let mut selections = self.selections.all::<Point>(cx);
 4357        let mut prev_edited_row = 0;
 4358        let mut row_delta = 0;
 4359        let mut edits = Vec::new();
 4360        let buffer = self.buffer.read(cx);
 4361        let snapshot = buffer.snapshot(cx);
 4362        for selection in &mut selections {
 4363            if selection.start.row != prev_edited_row {
 4364                row_delta = 0;
 4365            }
 4366            prev_edited_row = selection.end.row;
 4367
 4368            row_delta =
 4369                Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
 4370        }
 4371
 4372        self.transact(cx, |this, cx| {
 4373            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
 4374            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
 4375        });
 4376    }
 4377
 4378    fn indent_selection(
 4379        buffer: &MultiBuffer,
 4380        snapshot: &MultiBufferSnapshot,
 4381        selection: &mut Selection<Point>,
 4382        edits: &mut Vec<(Range<Point>, String)>,
 4383        delta_for_start_row: u32,
 4384        cx: &AppContext,
 4385    ) -> u32 {
 4386        let settings = buffer.settings_at(selection.start, cx);
 4387        let tab_size = settings.tab_size.get();
 4388        let indent_kind = if settings.hard_tabs {
 4389            IndentKind::Tab
 4390        } else {
 4391            IndentKind::Space
 4392        };
 4393        let mut start_row = selection.start.row;
 4394        let mut end_row = selection.end.row + 1;
 4395
 4396        // If a selection ends at the beginning of a line, don't indent
 4397        // that last line.
 4398        if selection.end.column == 0 {
 4399            end_row -= 1;
 4400        }
 4401
 4402        // Avoid re-indenting a row that has already been indented by a
 4403        // previous selection, but still update this selection's column
 4404        // to reflect that indentation.
 4405        if delta_for_start_row > 0 {
 4406            start_row += 1;
 4407            selection.start.column += delta_for_start_row;
 4408            if selection.end.row == selection.start.row {
 4409                selection.end.column += delta_for_start_row;
 4410            }
 4411        }
 4412
 4413        let mut delta_for_end_row = 0;
 4414        for row in start_row..end_row {
 4415            let current_indent = snapshot.indent_size_for_line(row);
 4416            let indent_delta = match (current_indent.kind, indent_kind) {
 4417                (IndentKind::Space, IndentKind::Space) => {
 4418                    let columns_to_next_tab_stop = tab_size - (current_indent.len % tab_size);
 4419                    IndentSize::spaces(columns_to_next_tab_stop)
 4420                }
 4421                (IndentKind::Tab, IndentKind::Space) => IndentSize::spaces(tab_size),
 4422                (_, IndentKind::Tab) => IndentSize::tab(),
 4423            };
 4424
 4425            let row_start = Point::new(row, 0);
 4426            edits.push((
 4427                row_start..row_start,
 4428                indent_delta.chars().collect::<String>(),
 4429            ));
 4430
 4431            // Update this selection's endpoints to reflect the indentation.
 4432            if row == selection.start.row {
 4433                selection.start.column += indent_delta.len;
 4434            }
 4435            if row == selection.end.row {
 4436                selection.end.column += indent_delta.len;
 4437                delta_for_end_row = indent_delta.len;
 4438            }
 4439        }
 4440
 4441        if selection.start.row == selection.end.row {
 4442            delta_for_start_row + delta_for_end_row
 4443        } else {
 4444            delta_for_end_row
 4445        }
 4446    }
 4447
 4448    pub fn outdent(&mut self, _: &Outdent, cx: &mut ViewContext<Self>) {
 4449        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 4450        let selections = self.selections.all::<Point>(cx);
 4451        let mut deletion_ranges = Vec::new();
 4452        let mut last_outdent = None;
 4453        {
 4454            let buffer = self.buffer.read(cx);
 4455            let snapshot = buffer.snapshot(cx);
 4456            for selection in &selections {
 4457                let settings = buffer.settings_at(selection.start, cx);
 4458                let tab_size = settings.tab_size.get();
 4459                let mut rows = selection.spanned_rows(false, &display_map);
 4460
 4461                // Avoid re-outdenting a row that has already been outdented by a
 4462                // previous selection.
 4463                if let Some(last_row) = last_outdent {
 4464                    if last_row == rows.start {
 4465                        rows.start += 1;
 4466                    }
 4467                }
 4468
 4469                for row in rows {
 4470                    let indent_size = snapshot.indent_size_for_line(row);
 4471                    if indent_size.len > 0 {
 4472                        let deletion_len = match indent_size.kind {
 4473                            IndentKind::Space => {
 4474                                let columns_to_prev_tab_stop = indent_size.len % tab_size;
 4475                                if columns_to_prev_tab_stop == 0 {
 4476                                    tab_size
 4477                                } else {
 4478                                    columns_to_prev_tab_stop
 4479                                }
 4480                            }
 4481                            IndentKind::Tab => 1,
 4482                        };
 4483                        deletion_ranges.push(Point::new(row, 0)..Point::new(row, deletion_len));
 4484                        last_outdent = Some(row);
 4485                    }
 4486                }
 4487            }
 4488        }
 4489
 4490        self.transact(cx, |this, cx| {
 4491            this.buffer.update(cx, |buffer, cx| {
 4492                let empty_str: Arc<str> = "".into();
 4493                buffer.edit(
 4494                    deletion_ranges
 4495                        .into_iter()
 4496                        .map(|range| (range, empty_str.clone())),
 4497                    None,
 4498                    cx,
 4499                );
 4500            });
 4501            let selections = this.selections.all::<usize>(cx);
 4502            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
 4503        });
 4504    }
 4505
 4506    pub fn delete_line(&mut self, _: &DeleteLine, cx: &mut ViewContext<Self>) {
 4507        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 4508        let selections = self.selections.all::<Point>(cx);
 4509
 4510        let mut new_cursors = Vec::new();
 4511        let mut edit_ranges = Vec::new();
 4512        let mut selections = selections.iter().peekable();
 4513        while let Some(selection) = selections.next() {
 4514            let mut rows = selection.spanned_rows(false, &display_map);
 4515            let goal_display_column = selection.head().to_display_point(&display_map).column();
 4516
 4517            // Accumulate contiguous regions of rows that we want to delete.
 4518            while let Some(next_selection) = selections.peek() {
 4519                let next_rows = next_selection.spanned_rows(false, &display_map);
 4520                if next_rows.start <= rows.end {
 4521                    rows.end = next_rows.end;
 4522                    selections.next().unwrap();
 4523                } else {
 4524                    break;
 4525                }
 4526            }
 4527
 4528            let buffer = &display_map.buffer_snapshot;
 4529            let mut edit_start = Point::new(rows.start, 0).to_offset(buffer);
 4530            let edit_end;
 4531            let cursor_buffer_row;
 4532            if buffer.max_point().row >= rows.end {
 4533                // If there's a line after the range, delete the \n from the end of the row range
 4534                // and position the cursor on the next line.
 4535                edit_end = Point::new(rows.end, 0).to_offset(buffer);
 4536                cursor_buffer_row = rows.end;
 4537            } else {
 4538                // If there isn't a line after the range, delete the \n from the line before the
 4539                // start of the row range and position the cursor there.
 4540                edit_start = edit_start.saturating_sub(1);
 4541                edit_end = buffer.len();
 4542                cursor_buffer_row = rows.start.saturating_sub(1);
 4543            }
 4544
 4545            let mut cursor = Point::new(cursor_buffer_row, 0).to_display_point(&display_map);
 4546            *cursor.column_mut() =
 4547                cmp::min(goal_display_column, display_map.line_len(cursor.row()));
 4548
 4549            new_cursors.push((
 4550                selection.id,
 4551                buffer.anchor_after(cursor.to_point(&display_map)),
 4552            ));
 4553            edit_ranges.push(edit_start..edit_end);
 4554        }
 4555
 4556        self.transact(cx, |this, cx| {
 4557            let buffer = this.buffer.update(cx, |buffer, cx| {
 4558                let empty_str: Arc<str> = "".into();
 4559                buffer.edit(
 4560                    edit_ranges
 4561                        .into_iter()
 4562                        .map(|range| (range, empty_str.clone())),
 4563                    None,
 4564                    cx,
 4565                );
 4566                buffer.snapshot(cx)
 4567            });
 4568            let new_selections = new_cursors
 4569                .into_iter()
 4570                .map(|(id, cursor)| {
 4571                    let cursor = cursor.to_point(&buffer);
 4572                    Selection {
 4573                        id,
 4574                        start: cursor,
 4575                        end: cursor,
 4576                        reversed: false,
 4577                        goal: SelectionGoal::None,
 4578                    }
 4579                })
 4580                .collect();
 4581
 4582            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 4583                s.select(new_selections);
 4584            });
 4585        });
 4586    }
 4587
 4588    pub fn join_lines(&mut self, _: &JoinLines, cx: &mut ViewContext<Self>) {
 4589        let mut row_ranges = Vec::<Range<u32>>::new();
 4590        for selection in self.selections.all::<Point>(cx) {
 4591            let start = selection.start.row;
 4592            let end = if selection.start.row == selection.end.row {
 4593                selection.start.row + 1
 4594            } else {
 4595                selection.end.row
 4596            };
 4597
 4598            if let Some(last_row_range) = row_ranges.last_mut() {
 4599                if start <= last_row_range.end {
 4600                    last_row_range.end = end;
 4601                    continue;
 4602                }
 4603            }
 4604            row_ranges.push(start..end);
 4605        }
 4606
 4607        let snapshot = self.buffer.read(cx).snapshot(cx);
 4608        let mut cursor_positions = Vec::new();
 4609        for row_range in &row_ranges {
 4610            let anchor = snapshot.anchor_before(Point::new(
 4611                row_range.end - 1,
 4612                snapshot.line_len(row_range.end - 1),
 4613            ));
 4614            cursor_positions.push(anchor.clone()..anchor);
 4615        }
 4616
 4617        self.transact(cx, |this, cx| {
 4618            for row_range in row_ranges.into_iter().rev() {
 4619                for row in row_range.rev() {
 4620                    let end_of_line = Point::new(row, snapshot.line_len(row));
 4621                    let indent = snapshot.indent_size_for_line(row + 1);
 4622                    let start_of_next_line = Point::new(row + 1, indent.len);
 4623
 4624                    let replace = if snapshot.line_len(row + 1) > indent.len {
 4625                        " "
 4626                    } else {
 4627                        ""
 4628                    };
 4629
 4630                    this.buffer.update(cx, |buffer, cx| {
 4631                        buffer.edit([(end_of_line..start_of_next_line, replace)], None, cx)
 4632                    });
 4633                }
 4634            }
 4635
 4636            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 4637                s.select_anchor_ranges(cursor_positions)
 4638            });
 4639        });
 4640    }
 4641
 4642    pub fn sort_lines_case_sensitive(
 4643        &mut self,
 4644        _: &SortLinesCaseSensitive,
 4645        cx: &mut ViewContext<Self>,
 4646    ) {
 4647        self.manipulate_lines(cx, |lines| lines.sort())
 4648    }
 4649
 4650    pub fn sort_lines_case_insensitive(
 4651        &mut self,
 4652        _: &SortLinesCaseInsensitive,
 4653        cx: &mut ViewContext<Self>,
 4654    ) {
 4655        self.manipulate_lines(cx, |lines| lines.sort_by_key(|line| line.to_lowercase()))
 4656    }
 4657
 4658    pub fn unique_lines_case_insensitive(
 4659        &mut self,
 4660        _: &UniqueLinesCaseInsensitive,
 4661        cx: &mut ViewContext<Self>,
 4662    ) {
 4663        self.manipulate_lines(cx, |lines| {
 4664            let mut seen = HashSet::default();
 4665            lines.retain(|line| seen.insert(line.to_lowercase()));
 4666        })
 4667    }
 4668
 4669    pub fn unique_lines_case_sensitive(
 4670        &mut self,
 4671        _: &UniqueLinesCaseSensitive,
 4672        cx: &mut ViewContext<Self>,
 4673    ) {
 4674        self.manipulate_lines(cx, |lines| {
 4675            let mut seen = HashSet::default();
 4676            lines.retain(|line| seen.insert(*line));
 4677        })
 4678    }
 4679
 4680    pub fn reverse_lines(&mut self, _: &ReverseLines, cx: &mut ViewContext<Self>) {
 4681        self.manipulate_lines(cx, |lines| lines.reverse())
 4682    }
 4683
 4684    pub fn shuffle_lines(&mut self, _: &ShuffleLines, cx: &mut ViewContext<Self>) {
 4685        self.manipulate_lines(cx, |lines| lines.shuffle(&mut thread_rng()))
 4686    }
 4687
 4688    fn manipulate_lines<Fn>(&mut self, cx: &mut ViewContext<Self>, mut callback: Fn)
 4689    where
 4690        Fn: FnMut(&mut Vec<&str>),
 4691    {
 4692        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 4693        let buffer = self.buffer.read(cx).snapshot(cx);
 4694
 4695        let mut edits = Vec::new();
 4696
 4697        let selections = self.selections.all::<Point>(cx);
 4698        let mut selections = selections.iter().peekable();
 4699        let mut contiguous_row_selections = Vec::new();
 4700        let mut new_selections = Vec::new();
 4701        let mut added_lines = 0;
 4702        let mut removed_lines = 0;
 4703
 4704        while let Some(selection) = selections.next() {
 4705            let (start_row, end_row) = consume_contiguous_rows(
 4706                &mut contiguous_row_selections,
 4707                selection,
 4708                &display_map,
 4709                &mut selections,
 4710            );
 4711
 4712            let start_point = Point::new(start_row, 0);
 4713            let end_point = Point::new(end_row - 1, buffer.line_len(end_row - 1));
 4714            let text = buffer
 4715                .text_for_range(start_point..end_point)
 4716                .collect::<String>();
 4717
 4718            let mut lines = text.split("\n").collect_vec();
 4719
 4720            let lines_before = lines.len();
 4721            callback(&mut lines);
 4722            let lines_after = lines.len();
 4723
 4724            edits.push((start_point..end_point, lines.join("\n")));
 4725
 4726            // Selections must change based on added and removed line count
 4727            let start_row = start_point.row + added_lines as u32 - removed_lines as u32;
 4728            let end_row = start_row + lines_after.saturating_sub(1) as u32;
 4729            new_selections.push(Selection {
 4730                id: selection.id,
 4731                start: start_row,
 4732                end: end_row,
 4733                goal: SelectionGoal::None,
 4734                reversed: selection.reversed,
 4735            });
 4736
 4737            if lines_after > lines_before {
 4738                added_lines += lines_after - lines_before;
 4739            } else if lines_before > lines_after {
 4740                removed_lines += lines_before - lines_after;
 4741            }
 4742        }
 4743
 4744        self.transact(cx, |this, cx| {
 4745            let buffer = this.buffer.update(cx, |buffer, cx| {
 4746                buffer.edit(edits, None, cx);
 4747                buffer.snapshot(cx)
 4748            });
 4749
 4750            // Recalculate offsets on newly edited buffer
 4751            let new_selections = new_selections
 4752                .iter()
 4753                .map(|s| {
 4754                    let start_point = Point::new(s.start, 0);
 4755                    let end_point = Point::new(s.end, buffer.line_len(s.end));
 4756                    Selection {
 4757                        id: s.id,
 4758                        start: buffer.point_to_offset(start_point),
 4759                        end: buffer.point_to_offset(end_point),
 4760                        goal: s.goal,
 4761                        reversed: s.reversed,
 4762                    }
 4763                })
 4764                .collect();
 4765
 4766            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 4767                s.select(new_selections);
 4768            });
 4769
 4770            this.request_autoscroll(Autoscroll::fit(), cx);
 4771        });
 4772    }
 4773
 4774    pub fn convert_to_upper_case(&mut self, _: &ConvertToUpperCase, cx: &mut ViewContext<Self>) {
 4775        self.manipulate_text(cx, |text| text.to_uppercase())
 4776    }
 4777
 4778    pub fn convert_to_lower_case(&mut self, _: &ConvertToLowerCase, cx: &mut ViewContext<Self>) {
 4779        self.manipulate_text(cx, |text| text.to_lowercase())
 4780    }
 4781
 4782    pub fn convert_to_title_case(&mut self, _: &ConvertToTitleCase, cx: &mut ViewContext<Self>) {
 4783        self.manipulate_text(cx, |text| {
 4784            // Hack to get around the fact that to_case crate doesn't support '\n' as a word boundary
 4785            // https://github.com/rutrum/convert-case/issues/16
 4786            text.split("\n")
 4787                .map(|line| line.to_case(Case::Title))
 4788                .join("\n")
 4789        })
 4790    }
 4791
 4792    pub fn convert_to_snake_case(&mut self, _: &ConvertToSnakeCase, cx: &mut ViewContext<Self>) {
 4793        self.manipulate_text(cx, |text| text.to_case(Case::Snake))
 4794    }
 4795
 4796    pub fn convert_to_kebab_case(&mut self, _: &ConvertToKebabCase, cx: &mut ViewContext<Self>) {
 4797        self.manipulate_text(cx, |text| text.to_case(Case::Kebab))
 4798    }
 4799
 4800    pub fn convert_to_upper_camel_case(
 4801        &mut self,
 4802        _: &ConvertToUpperCamelCase,
 4803        cx: &mut ViewContext<Self>,
 4804    ) {
 4805        self.manipulate_text(cx, |text| {
 4806            // Hack to get around the fact that to_case crate doesn't support '\n' as a word boundary
 4807            // https://github.com/rutrum/convert-case/issues/16
 4808            text.split("\n")
 4809                .map(|line| line.to_case(Case::UpperCamel))
 4810                .join("\n")
 4811        })
 4812    }
 4813
 4814    pub fn convert_to_lower_camel_case(
 4815        &mut self,
 4816        _: &ConvertToLowerCamelCase,
 4817        cx: &mut ViewContext<Self>,
 4818    ) {
 4819        self.manipulate_text(cx, |text| text.to_case(Case::Camel))
 4820    }
 4821
 4822    fn manipulate_text<Fn>(&mut self, cx: &mut ViewContext<Self>, mut callback: Fn)
 4823    where
 4824        Fn: FnMut(&str) -> String,
 4825    {
 4826        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 4827        let buffer = self.buffer.read(cx).snapshot(cx);
 4828
 4829        let mut new_selections = Vec::new();
 4830        let mut edits = Vec::new();
 4831        let mut selection_adjustment = 0i32;
 4832
 4833        for selection in self.selections.all::<usize>(cx) {
 4834            let selection_is_empty = selection.is_empty();
 4835
 4836            let (start, end) = if selection_is_empty {
 4837                let word_range = movement::surrounding_word(
 4838                    &display_map,
 4839                    selection.start.to_display_point(&display_map),
 4840                );
 4841                let start = word_range.start.to_offset(&display_map, Bias::Left);
 4842                let end = word_range.end.to_offset(&display_map, Bias::Left);
 4843                (start, end)
 4844            } else {
 4845                (selection.start, selection.end)
 4846            };
 4847
 4848            let text = buffer.text_for_range(start..end).collect::<String>();
 4849            let old_length = text.len() as i32;
 4850            let text = callback(&text);
 4851
 4852            new_selections.push(Selection {
 4853                start: (start as i32 - selection_adjustment) as usize,
 4854                end: ((start + text.len()) as i32 - selection_adjustment) as usize,
 4855                goal: SelectionGoal::None,
 4856                ..selection
 4857            });
 4858
 4859            selection_adjustment += old_length - text.len() as i32;
 4860
 4861            edits.push((start..end, text));
 4862        }
 4863
 4864        self.transact(cx, |this, cx| {
 4865            this.buffer.update(cx, |buffer, cx| {
 4866                buffer.edit(edits, None, cx);
 4867            });
 4868
 4869            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 4870                s.select(new_selections);
 4871            });
 4872
 4873            this.request_autoscroll(Autoscroll::fit(), cx);
 4874        });
 4875    }
 4876
 4877    pub fn duplicate_line(&mut self, _: &DuplicateLine, cx: &mut ViewContext<Self>) {
 4878        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 4879        let buffer = &display_map.buffer_snapshot;
 4880        let selections = self.selections.all::<Point>(cx);
 4881
 4882        let mut edits = Vec::new();
 4883        let mut selections_iter = selections.iter().peekable();
 4884        while let Some(selection) = selections_iter.next() {
 4885            // Avoid duplicating the same lines twice.
 4886            let mut rows = selection.spanned_rows(false, &display_map);
 4887
 4888            while let Some(next_selection) = selections_iter.peek() {
 4889                let next_rows = next_selection.spanned_rows(false, &display_map);
 4890                if next_rows.start < rows.end {
 4891                    rows.end = next_rows.end;
 4892                    selections_iter.next().unwrap();
 4893                } else {
 4894                    break;
 4895                }
 4896            }
 4897
 4898            // Copy the text from the selected row region and splice it at the start of the region.
 4899            let start = Point::new(rows.start, 0);
 4900            let end = Point::new(rows.end - 1, buffer.line_len(rows.end - 1));
 4901            let text = buffer
 4902                .text_for_range(start..end)
 4903                .chain(Some("\n"))
 4904                .collect::<String>();
 4905            edits.push((start..start, text));
 4906        }
 4907
 4908        self.transact(cx, |this, cx| {
 4909            this.buffer.update(cx, |buffer, cx| {
 4910                buffer.edit(edits, None, cx);
 4911            });
 4912
 4913            this.request_autoscroll(Autoscroll::fit(), cx);
 4914        });
 4915    }
 4916
 4917    pub fn move_line_up(&mut self, _: &MoveLineUp, cx: &mut ViewContext<Self>) {
 4918        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 4919        let buffer = self.buffer.read(cx).snapshot(cx);
 4920
 4921        let mut edits = Vec::new();
 4922        let mut unfold_ranges = Vec::new();
 4923        let mut refold_ranges = Vec::new();
 4924
 4925        let selections = self.selections.all::<Point>(cx);
 4926        let mut selections = selections.iter().peekable();
 4927        let mut contiguous_row_selections = Vec::new();
 4928        let mut new_selections = Vec::new();
 4929
 4930        while let Some(selection) = selections.next() {
 4931            // Find all the selections that span a contiguous row range
 4932            let (start_row, end_row) = consume_contiguous_rows(
 4933                &mut contiguous_row_selections,
 4934                selection,
 4935                &display_map,
 4936                &mut selections,
 4937            );
 4938
 4939            // Move the text spanned by the row range to be before the line preceding the row range
 4940            if start_row > 0 {
 4941                let range_to_move = Point::new(start_row - 1, buffer.line_len(start_row - 1))
 4942                    ..Point::new(end_row - 1, buffer.line_len(end_row - 1));
 4943                let insertion_point = display_map
 4944                    .prev_line_boundary(Point::new(start_row - 1, 0))
 4945                    .0;
 4946
 4947                // Don't move lines across excerpts
 4948                if buffer
 4949                    .excerpt_boundaries_in_range((
 4950                        Bound::Excluded(insertion_point),
 4951                        Bound::Included(range_to_move.end),
 4952                    ))
 4953                    .next()
 4954                    .is_none()
 4955                {
 4956                    let text = buffer
 4957                        .text_for_range(range_to_move.clone())
 4958                        .flat_map(|s| s.chars())
 4959                        .skip(1)
 4960                        .chain(['\n'])
 4961                        .collect::<String>();
 4962
 4963                    edits.push((
 4964                        buffer.anchor_after(range_to_move.start)
 4965                            ..buffer.anchor_before(range_to_move.end),
 4966                        String::new(),
 4967                    ));
 4968                    let insertion_anchor = buffer.anchor_after(insertion_point);
 4969                    edits.push((insertion_anchor..insertion_anchor, text));
 4970
 4971                    let row_delta = range_to_move.start.row - insertion_point.row + 1;
 4972
 4973                    // Move selections up
 4974                    new_selections.extend(contiguous_row_selections.drain(..).map(
 4975                        |mut selection| {
 4976                            selection.start.row -= row_delta;
 4977                            selection.end.row -= row_delta;
 4978                            selection
 4979                        },
 4980                    ));
 4981
 4982                    // Move folds up
 4983                    unfold_ranges.push(range_to_move.clone());
 4984                    for fold in display_map.folds_in_range(
 4985                        buffer.anchor_before(range_to_move.start)
 4986                            ..buffer.anchor_after(range_to_move.end),
 4987                    ) {
 4988                        let mut start = fold.range.start.to_point(&buffer);
 4989                        let mut end = fold.range.end.to_point(&buffer);
 4990                        start.row -= row_delta;
 4991                        end.row -= row_delta;
 4992                        refold_ranges.push(start..end);
 4993                    }
 4994                }
 4995            }
 4996
 4997            // If we didn't move line(s), preserve the existing selections
 4998            new_selections.append(&mut contiguous_row_selections);
 4999        }
 5000
 5001        self.transact(cx, |this, cx| {
 5002            this.unfold_ranges(unfold_ranges, true, true, cx);
 5003            this.buffer.update(cx, |buffer, cx| {
 5004                for (range, text) in edits {
 5005                    buffer.edit([(range, text)], None, cx);
 5006                }
 5007            });
 5008            this.fold_ranges(refold_ranges, true, cx);
 5009            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5010                s.select(new_selections);
 5011            })
 5012        });
 5013    }
 5014
 5015    pub fn move_line_down(&mut self, _: &MoveLineDown, cx: &mut ViewContext<Self>) {
 5016        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 5017        let buffer = self.buffer.read(cx).snapshot(cx);
 5018
 5019        let mut edits = Vec::new();
 5020        let mut unfold_ranges = Vec::new();
 5021        let mut refold_ranges = Vec::new();
 5022
 5023        let selections = self.selections.all::<Point>(cx);
 5024        let mut selections = selections.iter().peekable();
 5025        let mut contiguous_row_selections = Vec::new();
 5026        let mut new_selections = Vec::new();
 5027
 5028        while let Some(selection) = selections.next() {
 5029            // Find all the selections that span a contiguous row range
 5030            let (start_row, end_row) = consume_contiguous_rows(
 5031                &mut contiguous_row_selections,
 5032                selection,
 5033                &display_map,
 5034                &mut selections,
 5035            );
 5036
 5037            // Move the text spanned by the row range to be after the last line of the row range
 5038            if end_row <= buffer.max_point().row {
 5039                let range_to_move = Point::new(start_row, 0)..Point::new(end_row, 0);
 5040                let insertion_point = display_map.next_line_boundary(Point::new(end_row, 0)).0;
 5041
 5042                // Don't move lines across excerpt boundaries
 5043                if buffer
 5044                    .excerpt_boundaries_in_range((
 5045                        Bound::Excluded(range_to_move.start),
 5046                        Bound::Included(insertion_point),
 5047                    ))
 5048                    .next()
 5049                    .is_none()
 5050                {
 5051                    let mut text = String::from("\n");
 5052                    text.extend(buffer.text_for_range(range_to_move.clone()));
 5053                    text.pop(); // Drop trailing newline
 5054                    edits.push((
 5055                        buffer.anchor_after(range_to_move.start)
 5056                            ..buffer.anchor_before(range_to_move.end),
 5057                        String::new(),
 5058                    ));
 5059                    let insertion_anchor = buffer.anchor_after(insertion_point);
 5060                    edits.push((insertion_anchor..insertion_anchor, text));
 5061
 5062                    let row_delta = insertion_point.row - range_to_move.end.row + 1;
 5063
 5064                    // Move selections down
 5065                    new_selections.extend(contiguous_row_selections.drain(..).map(
 5066                        |mut selection| {
 5067                            selection.start.row += row_delta;
 5068                            selection.end.row += row_delta;
 5069                            selection
 5070                        },
 5071                    ));
 5072
 5073                    // Move folds down
 5074                    unfold_ranges.push(range_to_move.clone());
 5075                    for fold in display_map.folds_in_range(
 5076                        buffer.anchor_before(range_to_move.start)
 5077                            ..buffer.anchor_after(range_to_move.end),
 5078                    ) {
 5079                        let mut start = fold.range.start.to_point(&buffer);
 5080                        let mut end = fold.range.end.to_point(&buffer);
 5081                        start.row += row_delta;
 5082                        end.row += row_delta;
 5083                        refold_ranges.push(start..end);
 5084                    }
 5085                }
 5086            }
 5087
 5088            // If we didn't move line(s), preserve the existing selections
 5089            new_selections.append(&mut contiguous_row_selections);
 5090        }
 5091
 5092        self.transact(cx, |this, cx| {
 5093            this.unfold_ranges(unfold_ranges, true, true, cx);
 5094            this.buffer.update(cx, |buffer, cx| {
 5095                for (range, text) in edits {
 5096                    buffer.edit([(range, text)], None, cx);
 5097                }
 5098            });
 5099            this.fold_ranges(refold_ranges, true, cx);
 5100            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(new_selections));
 5101        });
 5102    }
 5103
 5104    pub fn transpose(&mut self, _: &Transpose, cx: &mut ViewContext<Self>) {
 5105        let text_layout_details = &self.text_layout_details(cx);
 5106        self.transact(cx, |this, cx| {
 5107            let edits = this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5108                let mut edits: Vec<(Range<usize>, String)> = Default::default();
 5109                let line_mode = s.line_mode;
 5110                s.move_with(|display_map, selection| {
 5111                    if !selection.is_empty() || line_mode {
 5112                        return;
 5113                    }
 5114
 5115                    let mut head = selection.head();
 5116                    let mut transpose_offset = head.to_offset(display_map, Bias::Right);
 5117                    if head.column() == display_map.line_len(head.row()) {
 5118                        transpose_offset = display_map
 5119                            .buffer_snapshot
 5120                            .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
 5121                    }
 5122
 5123                    if transpose_offset == 0 {
 5124                        return;
 5125                    }
 5126
 5127                    *head.column_mut() += 1;
 5128                    head = display_map.clip_point(head, Bias::Right);
 5129                    let goal = SelectionGoal::HorizontalPosition(
 5130                        display_map
 5131                            .x_for_display_point(head, &text_layout_details)
 5132                            .into(),
 5133                    );
 5134                    selection.collapse_to(head, goal);
 5135
 5136                    let transpose_start = display_map
 5137                        .buffer_snapshot
 5138                        .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
 5139                    if edits.last().map_or(true, |e| e.0.end <= transpose_start) {
 5140                        let transpose_end = display_map
 5141                            .buffer_snapshot
 5142                            .clip_offset(transpose_offset + 1, Bias::Right);
 5143                        if let Some(ch) =
 5144                            display_map.buffer_snapshot.chars_at(transpose_start).next()
 5145                        {
 5146                            edits.push((transpose_start..transpose_offset, String::new()));
 5147                            edits.push((transpose_end..transpose_end, ch.to_string()));
 5148                        }
 5149                    }
 5150                });
 5151                edits
 5152            });
 5153            this.buffer
 5154                .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
 5155            let selections = this.selections.all::<usize>(cx);
 5156            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5157                s.select(selections);
 5158            });
 5159        });
 5160    }
 5161
 5162    pub fn cut(&mut self, _: &Cut, cx: &mut ViewContext<Self>) {
 5163        let mut text = String::new();
 5164        let buffer = self.buffer.read(cx).snapshot(cx);
 5165        let mut selections = self.selections.all::<Point>(cx);
 5166        let mut clipboard_selections = Vec::with_capacity(selections.len());
 5167        {
 5168            let max_point = buffer.max_point();
 5169            let mut is_first = true;
 5170            for selection in &mut selections {
 5171                let is_entire_line = selection.is_empty() || self.selections.line_mode;
 5172                if is_entire_line {
 5173                    selection.start = Point::new(selection.start.row, 0);
 5174                    selection.end = cmp::min(max_point, Point::new(selection.end.row + 1, 0));
 5175                    selection.goal = SelectionGoal::None;
 5176                }
 5177                if is_first {
 5178                    is_first = false;
 5179                } else {
 5180                    text += "\n";
 5181                }
 5182                let mut len = 0;
 5183                for chunk in buffer.text_for_range(selection.start..selection.end) {
 5184                    text.push_str(chunk);
 5185                    len += chunk.len();
 5186                }
 5187                clipboard_selections.push(ClipboardSelection {
 5188                    len,
 5189                    is_entire_line,
 5190                    first_line_indent: buffer.indent_size_for_line(selection.start.row).len,
 5191                });
 5192            }
 5193        }
 5194
 5195        self.transact(cx, |this, cx| {
 5196            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5197                s.select(selections);
 5198            });
 5199            this.insert("", cx);
 5200            cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
 5201        });
 5202    }
 5203
 5204    pub fn copy(&mut self, _: &Copy, cx: &mut ViewContext<Self>) {
 5205        let selections = self.selections.all::<Point>(cx);
 5206        let buffer = self.buffer.read(cx).read(cx);
 5207        let mut text = String::new();
 5208
 5209        let mut clipboard_selections = Vec::with_capacity(selections.len());
 5210        {
 5211            let max_point = buffer.max_point();
 5212            let mut is_first = true;
 5213            for selection in selections.iter() {
 5214                let mut start = selection.start;
 5215                let mut end = selection.end;
 5216                let is_entire_line = selection.is_empty() || self.selections.line_mode;
 5217                if is_entire_line {
 5218                    start = Point::new(start.row, 0);
 5219                    end = cmp::min(max_point, Point::new(end.row + 1, 0));
 5220                }
 5221                if is_first {
 5222                    is_first = false;
 5223                } else {
 5224                    text += "\n";
 5225                }
 5226                let mut len = 0;
 5227                for chunk in buffer.text_for_range(start..end) {
 5228                    text.push_str(chunk);
 5229                    len += chunk.len();
 5230                }
 5231                clipboard_selections.push(ClipboardSelection {
 5232                    len,
 5233                    is_entire_line,
 5234                    first_line_indent: buffer.indent_size_for_line(start.row).len,
 5235                });
 5236            }
 5237        }
 5238
 5239        cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
 5240    }
 5241
 5242    pub fn paste(&mut self, _: &Paste, cx: &mut ViewContext<Self>) {
 5243        if self.read_only(cx) {
 5244            return;
 5245        }
 5246
 5247        self.transact(cx, |this, cx| {
 5248            if let Some(item) = cx.read_from_clipboard() {
 5249                let clipboard_text = Cow::Borrowed(item.text());
 5250                if let Some(mut clipboard_selections) = item.metadata::<Vec<ClipboardSelection>>() {
 5251                    let old_selections = this.selections.all::<usize>(cx);
 5252                    let all_selections_were_entire_line =
 5253                        clipboard_selections.iter().all(|s| s.is_entire_line);
 5254                    let first_selection_indent_column =
 5255                        clipboard_selections.first().map(|s| s.first_line_indent);
 5256                    if clipboard_selections.len() != old_selections.len() {
 5257                        clipboard_selections.drain(..);
 5258                    }
 5259
 5260                    this.buffer.update(cx, |buffer, cx| {
 5261                        let snapshot = buffer.read(cx);
 5262                        let mut start_offset = 0;
 5263                        let mut edits = Vec::new();
 5264                        let mut original_indent_columns = Vec::new();
 5265                        let line_mode = this.selections.line_mode;
 5266                        for (ix, selection) in old_selections.iter().enumerate() {
 5267                            let to_insert;
 5268                            let entire_line;
 5269                            let original_indent_column;
 5270                            if let Some(clipboard_selection) = clipboard_selections.get(ix) {
 5271                                let end_offset = start_offset + clipboard_selection.len;
 5272                                to_insert = &clipboard_text[start_offset..end_offset];
 5273                                entire_line = clipboard_selection.is_entire_line;
 5274                                start_offset = end_offset + 1;
 5275                                original_indent_column =
 5276                                    Some(clipboard_selection.first_line_indent);
 5277                            } else {
 5278                                to_insert = clipboard_text.as_str();
 5279                                entire_line = all_selections_were_entire_line;
 5280                                original_indent_column = first_selection_indent_column
 5281                            }
 5282
 5283                            // If the corresponding selection was empty when this slice of the
 5284                            // clipboard text was written, then the entire line containing the
 5285                            // selection was copied. If this selection is also currently empty,
 5286                            // then paste the line before the current line of the buffer.
 5287                            let range = if selection.is_empty() && !line_mode && entire_line {
 5288                                let column = selection.start.to_point(&snapshot).column as usize;
 5289                                let line_start = selection.start - column;
 5290                                line_start..line_start
 5291                            } else {
 5292                                selection.range()
 5293                            };
 5294
 5295                            edits.push((range, to_insert));
 5296                            original_indent_columns.extend(original_indent_column);
 5297                        }
 5298                        drop(snapshot);
 5299
 5300                        buffer.edit(
 5301                            edits,
 5302                            Some(AutoindentMode::Block {
 5303                                original_indent_columns,
 5304                            }),
 5305                            cx,
 5306                        );
 5307                    });
 5308
 5309                    let selections = this.selections.all::<usize>(cx);
 5310                    this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
 5311                } else {
 5312                    this.insert(&clipboard_text, cx);
 5313                }
 5314            }
 5315        });
 5316    }
 5317
 5318    pub fn undo(&mut self, _: &Undo, cx: &mut ViewContext<Self>) {
 5319        if self.read_only(cx) {
 5320            return;
 5321        }
 5322
 5323        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.undo(cx)) {
 5324            if let Some((selections, _)) = self.selection_history.transaction(tx_id).cloned() {
 5325                self.change_selections(None, cx, |s| {
 5326                    s.select_anchors(selections.to_vec());
 5327                });
 5328            }
 5329            self.request_autoscroll(Autoscroll::fit(), cx);
 5330            self.unmark_text(cx);
 5331            self.refresh_copilot_suggestions(true, cx);
 5332            cx.emit(EditorEvent::Edited);
 5333        }
 5334    }
 5335
 5336    pub fn redo(&mut self, _: &Redo, cx: &mut ViewContext<Self>) {
 5337        if self.read_only(cx) {
 5338            return;
 5339        }
 5340
 5341        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.redo(cx)) {
 5342            if let Some((_, Some(selections))) = self.selection_history.transaction(tx_id).cloned()
 5343            {
 5344                self.change_selections(None, cx, |s| {
 5345                    s.select_anchors(selections.to_vec());
 5346                });
 5347            }
 5348            self.request_autoscroll(Autoscroll::fit(), cx);
 5349            self.unmark_text(cx);
 5350            self.refresh_copilot_suggestions(true, cx);
 5351            cx.emit(EditorEvent::Edited);
 5352        }
 5353    }
 5354
 5355    pub fn finalize_last_transaction(&mut self, cx: &mut ViewContext<Self>) {
 5356        self.buffer
 5357            .update(cx, |buffer, cx| buffer.finalize_last_transaction(cx));
 5358    }
 5359
 5360    pub fn move_left(&mut self, _: &MoveLeft, cx: &mut ViewContext<Self>) {
 5361        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5362            let line_mode = s.line_mode;
 5363            s.move_with(|map, selection| {
 5364                let cursor = if selection.is_empty() && !line_mode {
 5365                    movement::left(map, selection.start)
 5366                } else {
 5367                    selection.start
 5368                };
 5369                selection.collapse_to(cursor, SelectionGoal::None);
 5370            });
 5371        })
 5372    }
 5373
 5374    pub fn select_left(&mut self, _: &SelectLeft, cx: &mut ViewContext<Self>) {
 5375        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5376            s.move_heads_with(|map, head, _| (movement::left(map, head), SelectionGoal::None));
 5377        })
 5378    }
 5379
 5380    pub fn move_right(&mut self, _: &MoveRight, cx: &mut ViewContext<Self>) {
 5381        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5382            let line_mode = s.line_mode;
 5383            s.move_with(|map, selection| {
 5384                let cursor = if selection.is_empty() && !line_mode {
 5385                    movement::right(map, selection.end)
 5386                } else {
 5387                    selection.end
 5388                };
 5389                selection.collapse_to(cursor, SelectionGoal::None)
 5390            });
 5391        })
 5392    }
 5393
 5394    pub fn select_right(&mut self, _: &SelectRight, cx: &mut ViewContext<Self>) {
 5395        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5396            s.move_heads_with(|map, head, _| (movement::right(map, head), SelectionGoal::None));
 5397        })
 5398    }
 5399
 5400    pub fn move_up(&mut self, _: &MoveUp, cx: &mut ViewContext<Self>) {
 5401        if self.take_rename(true, cx).is_some() {
 5402            return;
 5403        }
 5404
 5405        if matches!(self.mode, EditorMode::SingleLine) {
 5406            cx.propagate();
 5407            return;
 5408        }
 5409
 5410        let text_layout_details = &self.text_layout_details(cx);
 5411
 5412        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5413            let line_mode = s.line_mode;
 5414            s.move_with(|map, selection| {
 5415                if !selection.is_empty() && !line_mode {
 5416                    selection.goal = SelectionGoal::None;
 5417                }
 5418                let (cursor, goal) = movement::up(
 5419                    map,
 5420                    selection.start,
 5421                    selection.goal,
 5422                    false,
 5423                    &text_layout_details,
 5424                );
 5425                selection.collapse_to(cursor, goal);
 5426            });
 5427        })
 5428    }
 5429
 5430    pub fn move_up_by_lines(&mut self, action: &MoveUpByLines, cx: &mut ViewContext<Self>) {
 5431        if self.take_rename(true, cx).is_some() {
 5432            return;
 5433        }
 5434
 5435        if matches!(self.mode, EditorMode::SingleLine) {
 5436            cx.propagate();
 5437            return;
 5438        }
 5439
 5440        let text_layout_details = &self.text_layout_details(cx);
 5441
 5442        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5443            let line_mode = s.line_mode;
 5444            s.move_with(|map, selection| {
 5445                if !selection.is_empty() && !line_mode {
 5446                    selection.goal = SelectionGoal::None;
 5447                }
 5448                let (cursor, goal) = movement::up_by_rows(
 5449                    map,
 5450                    selection.start,
 5451                    action.lines,
 5452                    selection.goal,
 5453                    false,
 5454                    &text_layout_details,
 5455                );
 5456                selection.collapse_to(cursor, goal);
 5457            });
 5458        })
 5459    }
 5460
 5461    pub fn move_down_by_lines(&mut self, action: &MoveDownByLines, cx: &mut ViewContext<Self>) {
 5462        if self.take_rename(true, cx).is_some() {
 5463            return;
 5464        }
 5465
 5466        if matches!(self.mode, EditorMode::SingleLine) {
 5467            cx.propagate();
 5468            return;
 5469        }
 5470
 5471        let text_layout_details = &self.text_layout_details(cx);
 5472
 5473        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5474            let line_mode = s.line_mode;
 5475            s.move_with(|map, selection| {
 5476                if !selection.is_empty() && !line_mode {
 5477                    selection.goal = SelectionGoal::None;
 5478                }
 5479                let (cursor, goal) = movement::down_by_rows(
 5480                    map,
 5481                    selection.start,
 5482                    action.lines,
 5483                    selection.goal,
 5484                    false,
 5485                    &text_layout_details,
 5486                );
 5487                selection.collapse_to(cursor, goal);
 5488            });
 5489        })
 5490    }
 5491
 5492    pub fn select_down_by_lines(&mut self, action: &SelectDownByLines, cx: &mut ViewContext<Self>) {
 5493        let text_layout_details = &self.text_layout_details(cx);
 5494        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5495            s.move_heads_with(|map, head, goal| {
 5496                movement::down_by_rows(map, head, action.lines, goal, false, &text_layout_details)
 5497            })
 5498        })
 5499    }
 5500
 5501    pub fn select_up_by_lines(&mut self, action: &SelectUpByLines, cx: &mut ViewContext<Self>) {
 5502        let text_layout_details = &self.text_layout_details(cx);
 5503        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5504            s.move_heads_with(|map, head, goal| {
 5505                movement::up_by_rows(map, head, action.lines, goal, false, &text_layout_details)
 5506            })
 5507        })
 5508    }
 5509
 5510    pub fn move_page_up(&mut self, action: &MovePageUp, cx: &mut ViewContext<Self>) {
 5511        if self.take_rename(true, cx).is_some() {
 5512            return;
 5513        }
 5514
 5515        if matches!(self.mode, EditorMode::SingleLine) {
 5516            cx.propagate();
 5517            return;
 5518        }
 5519
 5520        let row_count = if let Some(row_count) = self.visible_line_count() {
 5521            row_count as u32 - 1
 5522        } else {
 5523            return;
 5524        };
 5525
 5526        let autoscroll = if action.center_cursor {
 5527            Autoscroll::center()
 5528        } else {
 5529            Autoscroll::fit()
 5530        };
 5531
 5532        let text_layout_details = &self.text_layout_details(cx);
 5533
 5534        self.change_selections(Some(autoscroll), cx, |s| {
 5535            let line_mode = s.line_mode;
 5536            s.move_with(|map, selection| {
 5537                if !selection.is_empty() && !line_mode {
 5538                    selection.goal = SelectionGoal::None;
 5539                }
 5540                let (cursor, goal) = movement::up_by_rows(
 5541                    map,
 5542                    selection.end,
 5543                    row_count,
 5544                    selection.goal,
 5545                    false,
 5546                    &text_layout_details,
 5547                );
 5548                selection.collapse_to(cursor, goal);
 5549            });
 5550        });
 5551    }
 5552
 5553    pub fn select_up(&mut self, _: &SelectUp, cx: &mut ViewContext<Self>) {
 5554        let text_layout_details = &self.text_layout_details(cx);
 5555        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5556            s.move_heads_with(|map, head, goal| {
 5557                movement::up(map, head, goal, false, &text_layout_details)
 5558            })
 5559        })
 5560    }
 5561
 5562    pub fn move_down(&mut self, _: &MoveDown, cx: &mut ViewContext<Self>) {
 5563        self.take_rename(true, cx);
 5564
 5565        if self.mode == EditorMode::SingleLine {
 5566            cx.propagate();
 5567            return;
 5568        }
 5569
 5570        let text_layout_details = &self.text_layout_details(cx);
 5571        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5572            let line_mode = s.line_mode;
 5573            s.move_with(|map, selection| {
 5574                if !selection.is_empty() && !line_mode {
 5575                    selection.goal = SelectionGoal::None;
 5576                }
 5577                let (cursor, goal) = movement::down(
 5578                    map,
 5579                    selection.end,
 5580                    selection.goal,
 5581                    false,
 5582                    &text_layout_details,
 5583                );
 5584                selection.collapse_to(cursor, goal);
 5585            });
 5586        });
 5587    }
 5588
 5589    pub fn move_page_down(&mut self, action: &MovePageDown, cx: &mut ViewContext<Self>) {
 5590        if self.take_rename(true, cx).is_some() {
 5591            return;
 5592        }
 5593
 5594        if self
 5595            .context_menu
 5596            .write()
 5597            .as_mut()
 5598            .map(|menu| menu.select_last(self.project.as_ref(), cx))
 5599            .unwrap_or(false)
 5600        {
 5601            return;
 5602        }
 5603
 5604        if matches!(self.mode, EditorMode::SingleLine) {
 5605            cx.propagate();
 5606            return;
 5607        }
 5608
 5609        let row_count = if let Some(row_count) = self.visible_line_count() {
 5610            row_count as u32 - 1
 5611        } else {
 5612            return;
 5613        };
 5614
 5615        let autoscroll = if action.center_cursor {
 5616            Autoscroll::center()
 5617        } else {
 5618            Autoscroll::fit()
 5619        };
 5620
 5621        let text_layout_details = &self.text_layout_details(cx);
 5622        self.change_selections(Some(autoscroll), cx, |s| {
 5623            let line_mode = s.line_mode;
 5624            s.move_with(|map, selection| {
 5625                if !selection.is_empty() && !line_mode {
 5626                    selection.goal = SelectionGoal::None;
 5627                }
 5628                let (cursor, goal) = movement::down_by_rows(
 5629                    map,
 5630                    selection.end,
 5631                    row_count,
 5632                    selection.goal,
 5633                    false,
 5634                    &text_layout_details,
 5635                );
 5636                selection.collapse_to(cursor, goal);
 5637            });
 5638        });
 5639    }
 5640
 5641    pub fn select_down(&mut self, _: &SelectDown, cx: &mut ViewContext<Self>) {
 5642        let text_layout_details = &self.text_layout_details(cx);
 5643        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5644            s.move_heads_with(|map, head, goal| {
 5645                movement::down(map, head, goal, false, &text_layout_details)
 5646            })
 5647        });
 5648    }
 5649
 5650    pub fn context_menu_first(&mut self, _: &ContextMenuFirst, cx: &mut ViewContext<Self>) {
 5651        if let Some(context_menu) = self.context_menu.write().as_mut() {
 5652            context_menu.select_first(self.project.as_ref(), cx);
 5653        }
 5654    }
 5655
 5656    pub fn context_menu_prev(&mut self, _: &ContextMenuPrev, cx: &mut ViewContext<Self>) {
 5657        if let Some(context_menu) = self.context_menu.write().as_mut() {
 5658            context_menu.select_prev(self.project.as_ref(), cx);
 5659        }
 5660    }
 5661
 5662    pub fn context_menu_next(&mut self, _: &ContextMenuNext, cx: &mut ViewContext<Self>) {
 5663        if let Some(context_menu) = self.context_menu.write().as_mut() {
 5664            context_menu.select_next(self.project.as_ref(), cx);
 5665        }
 5666    }
 5667
 5668    pub fn context_menu_last(&mut self, _: &ContextMenuLast, cx: &mut ViewContext<Self>) {
 5669        if let Some(context_menu) = self.context_menu.write().as_mut() {
 5670            context_menu.select_last(self.project.as_ref(), cx);
 5671        }
 5672    }
 5673
 5674    pub fn move_to_previous_word_start(
 5675        &mut self,
 5676        _: &MoveToPreviousWordStart,
 5677        cx: &mut ViewContext<Self>,
 5678    ) {
 5679        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5680            s.move_cursors_with(|map, head, _| {
 5681                (
 5682                    movement::previous_word_start(map, head),
 5683                    SelectionGoal::None,
 5684                )
 5685            });
 5686        })
 5687    }
 5688
 5689    pub fn move_to_previous_subword_start(
 5690        &mut self,
 5691        _: &MoveToPreviousSubwordStart,
 5692        cx: &mut ViewContext<Self>,
 5693    ) {
 5694        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5695            s.move_cursors_with(|map, head, _| {
 5696                (
 5697                    movement::previous_subword_start(map, head),
 5698                    SelectionGoal::None,
 5699                )
 5700            });
 5701        })
 5702    }
 5703
 5704    pub fn select_to_previous_word_start(
 5705        &mut self,
 5706        _: &SelectToPreviousWordStart,
 5707        cx: &mut ViewContext<Self>,
 5708    ) {
 5709        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5710            s.move_heads_with(|map, head, _| {
 5711                (
 5712                    movement::previous_word_start(map, head),
 5713                    SelectionGoal::None,
 5714                )
 5715            });
 5716        })
 5717    }
 5718
 5719    pub fn select_to_previous_subword_start(
 5720        &mut self,
 5721        _: &SelectToPreviousSubwordStart,
 5722        cx: &mut ViewContext<Self>,
 5723    ) {
 5724        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5725            s.move_heads_with(|map, head, _| {
 5726                (
 5727                    movement::previous_subword_start(map, head),
 5728                    SelectionGoal::None,
 5729                )
 5730            });
 5731        })
 5732    }
 5733
 5734    pub fn delete_to_previous_word_start(
 5735        &mut self,
 5736        _: &DeleteToPreviousWordStart,
 5737        cx: &mut ViewContext<Self>,
 5738    ) {
 5739        self.transact(cx, |this, cx| {
 5740            this.select_autoclose_pair(cx);
 5741            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5742                let line_mode = s.line_mode;
 5743                s.move_with(|map, selection| {
 5744                    if selection.is_empty() && !line_mode {
 5745                        let cursor = movement::previous_word_start(map, selection.head());
 5746                        selection.set_head(cursor, SelectionGoal::None);
 5747                    }
 5748                });
 5749            });
 5750            this.insert("", cx);
 5751        });
 5752    }
 5753
 5754    pub fn delete_to_previous_subword_start(
 5755        &mut self,
 5756        _: &DeleteToPreviousSubwordStart,
 5757        cx: &mut ViewContext<Self>,
 5758    ) {
 5759        self.transact(cx, |this, cx| {
 5760            this.select_autoclose_pair(cx);
 5761            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5762                let line_mode = s.line_mode;
 5763                s.move_with(|map, selection| {
 5764                    if selection.is_empty() && !line_mode {
 5765                        let cursor = movement::previous_subword_start(map, selection.head());
 5766                        selection.set_head(cursor, SelectionGoal::None);
 5767                    }
 5768                });
 5769            });
 5770            this.insert("", cx);
 5771        });
 5772    }
 5773
 5774    pub fn move_to_next_word_end(&mut self, _: &MoveToNextWordEnd, cx: &mut ViewContext<Self>) {
 5775        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5776            s.move_cursors_with(|map, head, _| {
 5777                (movement::next_word_end(map, head), SelectionGoal::None)
 5778            });
 5779        })
 5780    }
 5781
 5782    pub fn move_to_next_subword_end(
 5783        &mut self,
 5784        _: &MoveToNextSubwordEnd,
 5785        cx: &mut ViewContext<Self>,
 5786    ) {
 5787        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5788            s.move_cursors_with(|map, head, _| {
 5789                (movement::next_subword_end(map, head), SelectionGoal::None)
 5790            });
 5791        })
 5792    }
 5793
 5794    pub fn select_to_next_word_end(&mut self, _: &SelectToNextWordEnd, cx: &mut ViewContext<Self>) {
 5795        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5796            s.move_heads_with(|map, head, _| {
 5797                (movement::next_word_end(map, head), SelectionGoal::None)
 5798            });
 5799        })
 5800    }
 5801
 5802    pub fn select_to_next_subword_end(
 5803        &mut self,
 5804        _: &SelectToNextSubwordEnd,
 5805        cx: &mut ViewContext<Self>,
 5806    ) {
 5807        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5808            s.move_heads_with(|map, head, _| {
 5809                (movement::next_subword_end(map, head), SelectionGoal::None)
 5810            });
 5811        })
 5812    }
 5813
 5814    pub fn delete_to_next_word_end(&mut self, _: &DeleteToNextWordEnd, cx: &mut ViewContext<Self>) {
 5815        self.transact(cx, |this, cx| {
 5816            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5817                let line_mode = s.line_mode;
 5818                s.move_with(|map, selection| {
 5819                    if selection.is_empty() && !line_mode {
 5820                        let cursor = movement::next_word_end(map, selection.head());
 5821                        selection.set_head(cursor, SelectionGoal::None);
 5822                    }
 5823                });
 5824            });
 5825            this.insert("", cx);
 5826        });
 5827    }
 5828
 5829    pub fn delete_to_next_subword_end(
 5830        &mut self,
 5831        _: &DeleteToNextSubwordEnd,
 5832        cx: &mut ViewContext<Self>,
 5833    ) {
 5834        self.transact(cx, |this, cx| {
 5835            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5836                s.move_with(|map, selection| {
 5837                    if selection.is_empty() {
 5838                        let cursor = movement::next_subword_end(map, selection.head());
 5839                        selection.set_head(cursor, SelectionGoal::None);
 5840                    }
 5841                });
 5842            });
 5843            this.insert("", cx);
 5844        });
 5845    }
 5846
 5847    pub fn move_to_beginning_of_line(
 5848        &mut self,
 5849        _: &MoveToBeginningOfLine,
 5850        cx: &mut ViewContext<Self>,
 5851    ) {
 5852        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5853            s.move_cursors_with(|map, head, _| {
 5854                (
 5855                    movement::indented_line_beginning(map, head, true),
 5856                    SelectionGoal::None,
 5857                )
 5858            });
 5859        })
 5860    }
 5861
 5862    pub fn select_to_beginning_of_line(
 5863        &mut self,
 5864        action: &SelectToBeginningOfLine,
 5865        cx: &mut ViewContext<Self>,
 5866    ) {
 5867        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5868            s.move_heads_with(|map, head, _| {
 5869                (
 5870                    movement::indented_line_beginning(map, head, action.stop_at_soft_wraps),
 5871                    SelectionGoal::None,
 5872                )
 5873            });
 5874        });
 5875    }
 5876
 5877    pub fn delete_to_beginning_of_line(
 5878        &mut self,
 5879        _: &DeleteToBeginningOfLine,
 5880        cx: &mut ViewContext<Self>,
 5881    ) {
 5882        self.transact(cx, |this, cx| {
 5883            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5884                s.move_with(|_, selection| {
 5885                    selection.reversed = true;
 5886                });
 5887            });
 5888
 5889            this.select_to_beginning_of_line(
 5890                &SelectToBeginningOfLine {
 5891                    stop_at_soft_wraps: false,
 5892                },
 5893                cx,
 5894            );
 5895            this.backspace(&Backspace, cx);
 5896        });
 5897    }
 5898
 5899    pub fn move_to_end_of_line(&mut self, _: &MoveToEndOfLine, cx: &mut ViewContext<Self>) {
 5900        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5901            s.move_cursors_with(|map, head, _| {
 5902                (movement::line_end(map, head, true), SelectionGoal::None)
 5903            });
 5904        })
 5905    }
 5906
 5907    pub fn select_to_end_of_line(
 5908        &mut self,
 5909        action: &SelectToEndOfLine,
 5910        cx: &mut ViewContext<Self>,
 5911    ) {
 5912        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5913            s.move_heads_with(|map, head, _| {
 5914                (
 5915                    movement::line_end(map, head, action.stop_at_soft_wraps),
 5916                    SelectionGoal::None,
 5917                )
 5918            });
 5919        })
 5920    }
 5921
 5922    pub fn delete_to_end_of_line(&mut self, _: &DeleteToEndOfLine, cx: &mut ViewContext<Self>) {
 5923        self.transact(cx, |this, cx| {
 5924            this.select_to_end_of_line(
 5925                &SelectToEndOfLine {
 5926                    stop_at_soft_wraps: false,
 5927                },
 5928                cx,
 5929            );
 5930            this.delete(&Delete, cx);
 5931        });
 5932    }
 5933
 5934    pub fn cut_to_end_of_line(&mut self, _: &CutToEndOfLine, cx: &mut ViewContext<Self>) {
 5935        self.transact(cx, |this, cx| {
 5936            this.select_to_end_of_line(
 5937                &SelectToEndOfLine {
 5938                    stop_at_soft_wraps: false,
 5939                },
 5940                cx,
 5941            );
 5942            this.cut(&Cut, cx);
 5943        });
 5944    }
 5945
 5946    pub fn move_to_start_of_paragraph(
 5947        &mut self,
 5948        _: &MoveToStartOfParagraph,
 5949        cx: &mut ViewContext<Self>,
 5950    ) {
 5951        if matches!(self.mode, EditorMode::SingleLine) {
 5952            cx.propagate();
 5953            return;
 5954        }
 5955
 5956        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5957            s.move_with(|map, selection| {
 5958                selection.collapse_to(
 5959                    movement::start_of_paragraph(map, selection.head(), 1),
 5960                    SelectionGoal::None,
 5961                )
 5962            });
 5963        })
 5964    }
 5965
 5966    pub fn move_to_end_of_paragraph(
 5967        &mut self,
 5968        _: &MoveToEndOfParagraph,
 5969        cx: &mut ViewContext<Self>,
 5970    ) {
 5971        if matches!(self.mode, EditorMode::SingleLine) {
 5972            cx.propagate();
 5973            return;
 5974        }
 5975
 5976        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5977            s.move_with(|map, selection| {
 5978                selection.collapse_to(
 5979                    movement::end_of_paragraph(map, selection.head(), 1),
 5980                    SelectionGoal::None,
 5981                )
 5982            });
 5983        })
 5984    }
 5985
 5986    pub fn select_to_start_of_paragraph(
 5987        &mut self,
 5988        _: &SelectToStartOfParagraph,
 5989        cx: &mut ViewContext<Self>,
 5990    ) {
 5991        if matches!(self.mode, EditorMode::SingleLine) {
 5992            cx.propagate();
 5993            return;
 5994        }
 5995
 5996        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5997            s.move_heads_with(|map, head, _| {
 5998                (
 5999                    movement::start_of_paragraph(map, head, 1),
 6000                    SelectionGoal::None,
 6001                )
 6002            });
 6003        })
 6004    }
 6005
 6006    pub fn select_to_end_of_paragraph(
 6007        &mut self,
 6008        _: &SelectToEndOfParagraph,
 6009        cx: &mut ViewContext<Self>,
 6010    ) {
 6011        if matches!(self.mode, EditorMode::SingleLine) {
 6012            cx.propagate();
 6013            return;
 6014        }
 6015
 6016        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6017            s.move_heads_with(|map, head, _| {
 6018                (
 6019                    movement::end_of_paragraph(map, head, 1),
 6020                    SelectionGoal::None,
 6021                )
 6022            });
 6023        })
 6024    }
 6025
 6026    pub fn move_to_beginning(&mut self, _: &MoveToBeginning, cx: &mut ViewContext<Self>) {
 6027        if matches!(self.mode, EditorMode::SingleLine) {
 6028            cx.propagate();
 6029            return;
 6030        }
 6031
 6032        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6033            s.select_ranges(vec![0..0]);
 6034        });
 6035    }
 6036
 6037    pub fn select_to_beginning(&mut self, _: &SelectToBeginning, cx: &mut ViewContext<Self>) {
 6038        let mut selection = self.selections.last::<Point>(cx);
 6039        selection.set_head(Point::zero(), SelectionGoal::None);
 6040
 6041        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6042            s.select(vec![selection]);
 6043        });
 6044    }
 6045
 6046    pub fn move_to_end(&mut self, _: &MoveToEnd, cx: &mut ViewContext<Self>) {
 6047        if matches!(self.mode, EditorMode::SingleLine) {
 6048            cx.propagate();
 6049            return;
 6050        }
 6051
 6052        let cursor = self.buffer.read(cx).read(cx).len();
 6053        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6054            s.select_ranges(vec![cursor..cursor])
 6055        });
 6056    }
 6057
 6058    pub fn set_nav_history(&mut self, nav_history: Option<ItemNavHistory>) {
 6059        self.nav_history = nav_history;
 6060    }
 6061
 6062    pub fn nav_history(&self) -> Option<&ItemNavHistory> {
 6063        self.nav_history.as_ref()
 6064    }
 6065
 6066    fn push_to_nav_history(
 6067        &mut self,
 6068        cursor_anchor: Anchor,
 6069        new_position: Option<Point>,
 6070        cx: &mut ViewContext<Self>,
 6071    ) {
 6072        if let Some(nav_history) = self.nav_history.as_mut() {
 6073            let buffer = self.buffer.read(cx).read(cx);
 6074            let cursor_position = cursor_anchor.to_point(&buffer);
 6075            let scroll_state = self.scroll_manager.anchor();
 6076            let scroll_top_row = scroll_state.top_row(&buffer);
 6077            drop(buffer);
 6078
 6079            if let Some(new_position) = new_position {
 6080                let row_delta = (new_position.row as i64 - cursor_position.row as i64).abs();
 6081                if row_delta < MIN_NAVIGATION_HISTORY_ROW_DELTA {
 6082                    return;
 6083                }
 6084            }
 6085
 6086            nav_history.push(
 6087                Some(NavigationData {
 6088                    cursor_anchor,
 6089                    cursor_position,
 6090                    scroll_anchor: scroll_state,
 6091                    scroll_top_row,
 6092                }),
 6093                cx,
 6094            );
 6095        }
 6096    }
 6097
 6098    pub fn select_to_end(&mut self, _: &SelectToEnd, cx: &mut ViewContext<Self>) {
 6099        let buffer = self.buffer.read(cx).snapshot(cx);
 6100        let mut selection = self.selections.first::<usize>(cx);
 6101        selection.set_head(buffer.len(), SelectionGoal::None);
 6102        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6103            s.select(vec![selection]);
 6104        });
 6105    }
 6106
 6107    pub fn select_all(&mut self, _: &SelectAll, cx: &mut ViewContext<Self>) {
 6108        let end = self.buffer.read(cx).read(cx).len();
 6109        self.change_selections(None, cx, |s| {
 6110            s.select_ranges(vec![0..end]);
 6111        });
 6112    }
 6113
 6114    pub fn select_line(&mut self, _: &SelectLine, cx: &mut ViewContext<Self>) {
 6115        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 6116        let mut selections = self.selections.all::<Point>(cx);
 6117        let max_point = display_map.buffer_snapshot.max_point();
 6118        for selection in &mut selections {
 6119            let rows = selection.spanned_rows(true, &display_map);
 6120            selection.start = Point::new(rows.start, 0);
 6121            selection.end = cmp::min(max_point, Point::new(rows.end, 0));
 6122            selection.reversed = false;
 6123        }
 6124        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6125            s.select(selections);
 6126        });
 6127    }
 6128
 6129    pub fn split_selection_into_lines(
 6130        &mut self,
 6131        _: &SplitSelectionIntoLines,
 6132        cx: &mut ViewContext<Self>,
 6133    ) {
 6134        let mut to_unfold = Vec::new();
 6135        let mut new_selection_ranges = Vec::new();
 6136        {
 6137            let selections = self.selections.all::<Point>(cx);
 6138            let buffer = self.buffer.read(cx).read(cx);
 6139            for selection in selections {
 6140                for row in selection.start.row..selection.end.row {
 6141                    let cursor = Point::new(row, buffer.line_len(row));
 6142                    new_selection_ranges.push(cursor..cursor);
 6143                }
 6144                new_selection_ranges.push(selection.end..selection.end);
 6145                to_unfold.push(selection.start..selection.end);
 6146            }
 6147        }
 6148        self.unfold_ranges(to_unfold, true, true, cx);
 6149        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6150            s.select_ranges(new_selection_ranges);
 6151        });
 6152    }
 6153
 6154    pub fn add_selection_above(&mut self, _: &AddSelectionAbove, cx: &mut ViewContext<Self>) {
 6155        self.add_selection(true, cx);
 6156    }
 6157
 6158    pub fn add_selection_below(&mut self, _: &AddSelectionBelow, cx: &mut ViewContext<Self>) {
 6159        self.add_selection(false, cx);
 6160    }
 6161
 6162    fn add_selection(&mut self, above: bool, cx: &mut ViewContext<Self>) {
 6163        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 6164        let mut selections = self.selections.all::<Point>(cx);
 6165        let text_layout_details = self.text_layout_details(cx);
 6166        let mut state = self.add_selections_state.take().unwrap_or_else(|| {
 6167            let oldest_selection = selections.iter().min_by_key(|s| s.id).unwrap().clone();
 6168            let range = oldest_selection.display_range(&display_map).sorted();
 6169
 6170            let start_x = display_map.x_for_display_point(range.start, &text_layout_details);
 6171            let end_x = display_map.x_for_display_point(range.end, &text_layout_details);
 6172            let positions = start_x.min(end_x)..start_x.max(end_x);
 6173
 6174            selections.clear();
 6175            let mut stack = Vec::new();
 6176            for row in range.start.row()..=range.end.row() {
 6177                if let Some(selection) = self.selections.build_columnar_selection(
 6178                    &display_map,
 6179                    row,
 6180                    &positions,
 6181                    oldest_selection.reversed,
 6182                    &text_layout_details,
 6183                ) {
 6184                    stack.push(selection.id);
 6185                    selections.push(selection);
 6186                }
 6187            }
 6188
 6189            if above {
 6190                stack.reverse();
 6191            }
 6192
 6193            AddSelectionsState { above, stack }
 6194        });
 6195
 6196        let last_added_selection = *state.stack.last().unwrap();
 6197        let mut new_selections = Vec::new();
 6198        if above == state.above {
 6199            let end_row = if above {
 6200                0
 6201            } else {
 6202                display_map.max_point().row()
 6203            };
 6204
 6205            'outer: for selection in selections {
 6206                if selection.id == last_added_selection {
 6207                    let range = selection.display_range(&display_map).sorted();
 6208                    debug_assert_eq!(range.start.row(), range.end.row());
 6209                    let mut row = range.start.row();
 6210                    let positions =
 6211                        if let SelectionGoal::HorizontalRange { start, end } = selection.goal {
 6212                            px(start)..px(end)
 6213                        } else {
 6214                            let start_x =
 6215                                display_map.x_for_display_point(range.start, &text_layout_details);
 6216                            let end_x =
 6217                                display_map.x_for_display_point(range.end, &text_layout_details);
 6218                            start_x.min(end_x)..start_x.max(end_x)
 6219                        };
 6220
 6221                    while row != end_row {
 6222                        if above {
 6223                            row -= 1;
 6224                        } else {
 6225                            row += 1;
 6226                        }
 6227
 6228                        if let Some(new_selection) = self.selections.build_columnar_selection(
 6229                            &display_map,
 6230                            row,
 6231                            &positions,
 6232                            selection.reversed,
 6233                            &text_layout_details,
 6234                        ) {
 6235                            state.stack.push(new_selection.id);
 6236                            if above {
 6237                                new_selections.push(new_selection);
 6238                                new_selections.push(selection);
 6239                            } else {
 6240                                new_selections.push(selection);
 6241                                new_selections.push(new_selection);
 6242                            }
 6243
 6244                            continue 'outer;
 6245                        }
 6246                    }
 6247                }
 6248
 6249                new_selections.push(selection);
 6250            }
 6251        } else {
 6252            new_selections = selections;
 6253            new_selections.retain(|s| s.id != last_added_selection);
 6254            state.stack.pop();
 6255        }
 6256
 6257        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6258            s.select(new_selections);
 6259        });
 6260        if state.stack.len() > 1 {
 6261            self.add_selections_state = Some(state);
 6262        }
 6263    }
 6264
 6265    pub fn select_next_match_internal(
 6266        &mut self,
 6267        display_map: &DisplaySnapshot,
 6268        replace_newest: bool,
 6269        autoscroll: Option<Autoscroll>,
 6270        cx: &mut ViewContext<Self>,
 6271    ) -> Result<()> {
 6272        fn select_next_match_ranges(
 6273            this: &mut Editor,
 6274            range: Range<usize>,
 6275            replace_newest: bool,
 6276            auto_scroll: Option<Autoscroll>,
 6277            cx: &mut ViewContext<Editor>,
 6278        ) {
 6279            this.unfold_ranges([range.clone()], false, true, cx);
 6280            this.change_selections(auto_scroll, cx, |s| {
 6281                if replace_newest {
 6282                    s.delete(s.newest_anchor().id);
 6283                }
 6284                s.insert_range(range.clone());
 6285            });
 6286        }
 6287
 6288        let buffer = &display_map.buffer_snapshot;
 6289        let mut selections = self.selections.all::<usize>(cx);
 6290        if let Some(mut select_next_state) = self.select_next_state.take() {
 6291            let query = &select_next_state.query;
 6292            if !select_next_state.done {
 6293                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
 6294                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
 6295                let mut next_selected_range = None;
 6296
 6297                let bytes_after_last_selection =
 6298                    buffer.bytes_in_range(last_selection.end..buffer.len());
 6299                let bytes_before_first_selection = buffer.bytes_in_range(0..first_selection.start);
 6300                let query_matches = query
 6301                    .stream_find_iter(bytes_after_last_selection)
 6302                    .map(|result| (last_selection.end, result))
 6303                    .chain(
 6304                        query
 6305                            .stream_find_iter(bytes_before_first_selection)
 6306                            .map(|result| (0, result)),
 6307                    );
 6308
 6309                for (start_offset, query_match) in query_matches {
 6310                    let query_match = query_match.unwrap(); // can only fail due to I/O
 6311                    let offset_range =
 6312                        start_offset + query_match.start()..start_offset + query_match.end();
 6313                    let display_range = offset_range.start.to_display_point(&display_map)
 6314                        ..offset_range.end.to_display_point(&display_map);
 6315
 6316                    if !select_next_state.wordwise
 6317                        || (!movement::is_inside_word(&display_map, display_range.start)
 6318                            && !movement::is_inside_word(&display_map, display_range.end))
 6319                    {
 6320                        // TODO: This is n^2, because we might check all the selections
 6321                        if selections
 6322                            .iter()
 6323                            .find(|selection| selection.range().overlaps(&offset_range))
 6324                            .is_none()
 6325                        {
 6326                            next_selected_range = Some(offset_range);
 6327                            break;
 6328                        }
 6329                    }
 6330                }
 6331
 6332                if let Some(next_selected_range) = next_selected_range {
 6333                    select_next_match_ranges(
 6334                        self,
 6335                        next_selected_range,
 6336                        replace_newest,
 6337                        autoscroll,
 6338                        cx,
 6339                    );
 6340                } else {
 6341                    select_next_state.done = true;
 6342                }
 6343            }
 6344
 6345            self.select_next_state = Some(select_next_state);
 6346        } else {
 6347            let mut only_carets = true;
 6348            let mut same_text_selected = true;
 6349            let mut selected_text = None;
 6350
 6351            let mut selections_iter = selections.iter().peekable();
 6352            while let Some(selection) = selections_iter.next() {
 6353                if selection.start != selection.end {
 6354                    only_carets = false;
 6355                }
 6356
 6357                if same_text_selected {
 6358                    if selected_text.is_none() {
 6359                        selected_text =
 6360                            Some(buffer.text_for_range(selection.range()).collect::<String>());
 6361                    }
 6362
 6363                    if let Some(next_selection) = selections_iter.peek() {
 6364                        if next_selection.range().len() == selection.range().len() {
 6365                            let next_selected_text = buffer
 6366                                .text_for_range(next_selection.range())
 6367                                .collect::<String>();
 6368                            if Some(next_selected_text) != selected_text {
 6369                                same_text_selected = false;
 6370                                selected_text = None;
 6371                            }
 6372                        } else {
 6373                            same_text_selected = false;
 6374                            selected_text = None;
 6375                        }
 6376                    }
 6377                }
 6378            }
 6379
 6380            if only_carets {
 6381                for selection in &mut selections {
 6382                    let word_range = movement::surrounding_word(
 6383                        &display_map,
 6384                        selection.start.to_display_point(&display_map),
 6385                    );
 6386                    selection.start = word_range.start.to_offset(&display_map, Bias::Left);
 6387                    selection.end = word_range.end.to_offset(&display_map, Bias::Left);
 6388                    selection.goal = SelectionGoal::None;
 6389                    selection.reversed = false;
 6390                    select_next_match_ranges(
 6391                        self,
 6392                        selection.start..selection.end,
 6393                        replace_newest,
 6394                        autoscroll,
 6395                        cx,
 6396                    );
 6397                }
 6398
 6399                if selections.len() == 1 {
 6400                    let selection = selections
 6401                        .last()
 6402                        .expect("ensured that there's only one selection");
 6403                    let query = buffer
 6404                        .text_for_range(selection.start..selection.end)
 6405                        .collect::<String>();
 6406                    let is_empty = query.is_empty();
 6407                    let select_state = SelectNextState {
 6408                        query: AhoCorasick::new(&[query])?,
 6409                        wordwise: true,
 6410                        done: is_empty,
 6411                    };
 6412                    self.select_next_state = Some(select_state);
 6413                } else {
 6414                    self.select_next_state = None;
 6415                }
 6416            } else if let Some(selected_text) = selected_text {
 6417                self.select_next_state = Some(SelectNextState {
 6418                    query: AhoCorasick::new(&[selected_text])?,
 6419                    wordwise: false,
 6420                    done: false,
 6421                });
 6422                self.select_next_match_internal(display_map, replace_newest, autoscroll, cx)?;
 6423            }
 6424        }
 6425        Ok(())
 6426    }
 6427
 6428    pub fn select_all_matches(
 6429        &mut self,
 6430        _action: &SelectAllMatches,
 6431        cx: &mut ViewContext<Self>,
 6432    ) -> Result<()> {
 6433        self.push_to_selection_history();
 6434        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 6435
 6436        self.select_next_match_internal(&display_map, false, None, cx)?;
 6437        let Some(select_next_state) = self.select_next_state.as_mut() else {
 6438            return Ok(());
 6439        };
 6440        if select_next_state.done {
 6441            return Ok(());
 6442        }
 6443
 6444        let mut new_selections = self.selections.all::<usize>(cx);
 6445
 6446        let buffer = &display_map.buffer_snapshot;
 6447        let query_matches = select_next_state
 6448            .query
 6449            .stream_find_iter(buffer.bytes_in_range(0..buffer.len()));
 6450
 6451        for query_match in query_matches {
 6452            let query_match = query_match.unwrap(); // can only fail due to I/O
 6453            let offset_range = query_match.start()..query_match.end();
 6454            let display_range = offset_range.start.to_display_point(&display_map)
 6455                ..offset_range.end.to_display_point(&display_map);
 6456
 6457            if !select_next_state.wordwise
 6458                || (!movement::is_inside_word(&display_map, display_range.start)
 6459                    && !movement::is_inside_word(&display_map, display_range.end))
 6460            {
 6461                self.selections.change_with(cx, |selections| {
 6462                    new_selections.push(Selection {
 6463                        id: selections.new_selection_id(),
 6464                        start: offset_range.start,
 6465                        end: offset_range.end,
 6466                        reversed: false,
 6467                        goal: SelectionGoal::None,
 6468                    });
 6469                });
 6470            }
 6471        }
 6472
 6473        new_selections.sort_by_key(|selection| selection.start);
 6474        let mut ix = 0;
 6475        while ix + 1 < new_selections.len() {
 6476            let current_selection = &new_selections[ix];
 6477            let next_selection = &new_selections[ix + 1];
 6478            if current_selection.range().overlaps(&next_selection.range()) {
 6479                if current_selection.id < next_selection.id {
 6480                    new_selections.remove(ix + 1);
 6481                } else {
 6482                    new_selections.remove(ix);
 6483                }
 6484            } else {
 6485                ix += 1;
 6486            }
 6487        }
 6488
 6489        select_next_state.done = true;
 6490        self.unfold_ranges(
 6491            new_selections.iter().map(|selection| selection.range()),
 6492            false,
 6493            false,
 6494            cx,
 6495        );
 6496        self.change_selections(Some(Autoscroll::fit()), cx, |selections| {
 6497            selections.select(new_selections)
 6498        });
 6499
 6500        Ok(())
 6501    }
 6502
 6503    pub fn select_next(&mut self, action: &SelectNext, cx: &mut ViewContext<Self>) -> Result<()> {
 6504        self.push_to_selection_history();
 6505        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 6506        self.select_next_match_internal(
 6507            &display_map,
 6508            action.replace_newest,
 6509            Some(Autoscroll::newest()),
 6510            cx,
 6511        )?;
 6512        Ok(())
 6513    }
 6514
 6515    pub fn select_previous(
 6516        &mut self,
 6517        action: &SelectPrevious,
 6518        cx: &mut ViewContext<Self>,
 6519    ) -> Result<()> {
 6520        self.push_to_selection_history();
 6521        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 6522        let buffer = &display_map.buffer_snapshot;
 6523        let mut selections = self.selections.all::<usize>(cx);
 6524        if let Some(mut select_prev_state) = self.select_prev_state.take() {
 6525            let query = &select_prev_state.query;
 6526            if !select_prev_state.done {
 6527                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
 6528                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
 6529                let mut next_selected_range = None;
 6530                // When we're iterating matches backwards, the oldest match will actually be the furthest one in the buffer.
 6531                let bytes_before_last_selection =
 6532                    buffer.reversed_bytes_in_range(0..last_selection.start);
 6533                let bytes_after_first_selection =
 6534                    buffer.reversed_bytes_in_range(first_selection.end..buffer.len());
 6535                let query_matches = query
 6536                    .stream_find_iter(bytes_before_last_selection)
 6537                    .map(|result| (last_selection.start, result))
 6538                    .chain(
 6539                        query
 6540                            .stream_find_iter(bytes_after_first_selection)
 6541                            .map(|result| (buffer.len(), result)),
 6542                    );
 6543                for (end_offset, query_match) in query_matches {
 6544                    let query_match = query_match.unwrap(); // can only fail due to I/O
 6545                    let offset_range =
 6546                        end_offset - query_match.end()..end_offset - query_match.start();
 6547                    let display_range = offset_range.start.to_display_point(&display_map)
 6548                        ..offset_range.end.to_display_point(&display_map);
 6549
 6550                    if !select_prev_state.wordwise
 6551                        || (!movement::is_inside_word(&display_map, display_range.start)
 6552                            && !movement::is_inside_word(&display_map, display_range.end))
 6553                    {
 6554                        next_selected_range = Some(offset_range);
 6555                        break;
 6556                    }
 6557                }
 6558
 6559                if let Some(next_selected_range) = next_selected_range {
 6560                    self.unfold_ranges([next_selected_range.clone()], false, true, cx);
 6561                    self.change_selections(Some(Autoscroll::newest()), cx, |s| {
 6562                        if action.replace_newest {
 6563                            s.delete(s.newest_anchor().id);
 6564                        }
 6565                        s.insert_range(next_selected_range);
 6566                    });
 6567                } else {
 6568                    select_prev_state.done = true;
 6569                }
 6570            }
 6571
 6572            self.select_prev_state = Some(select_prev_state);
 6573        } else {
 6574            let mut only_carets = true;
 6575            let mut same_text_selected = true;
 6576            let mut selected_text = None;
 6577
 6578            let mut selections_iter = selections.iter().peekable();
 6579            while let Some(selection) = selections_iter.next() {
 6580                if selection.start != selection.end {
 6581                    only_carets = false;
 6582                }
 6583
 6584                if same_text_selected {
 6585                    if selected_text.is_none() {
 6586                        selected_text =
 6587                            Some(buffer.text_for_range(selection.range()).collect::<String>());
 6588                    }
 6589
 6590                    if let Some(next_selection) = selections_iter.peek() {
 6591                        if next_selection.range().len() == selection.range().len() {
 6592                            let next_selected_text = buffer
 6593                                .text_for_range(next_selection.range())
 6594                                .collect::<String>();
 6595                            if Some(next_selected_text) != selected_text {
 6596                                same_text_selected = false;
 6597                                selected_text = None;
 6598                            }
 6599                        } else {
 6600                            same_text_selected = false;
 6601                            selected_text = None;
 6602                        }
 6603                    }
 6604                }
 6605            }
 6606
 6607            if only_carets {
 6608                for selection in &mut selections {
 6609                    let word_range = movement::surrounding_word(
 6610                        &display_map,
 6611                        selection.start.to_display_point(&display_map),
 6612                    );
 6613                    selection.start = word_range.start.to_offset(&display_map, Bias::Left);
 6614                    selection.end = word_range.end.to_offset(&display_map, Bias::Left);
 6615                    selection.goal = SelectionGoal::None;
 6616                    selection.reversed = false;
 6617                }
 6618                if selections.len() == 1 {
 6619                    let selection = selections
 6620                        .last()
 6621                        .expect("ensured that there's only one selection");
 6622                    let query = buffer
 6623                        .text_for_range(selection.start..selection.end)
 6624                        .collect::<String>();
 6625                    let is_empty = query.is_empty();
 6626                    let select_state = SelectNextState {
 6627                        query: AhoCorasick::new(&[query.chars().rev().collect::<String>()])?,
 6628                        wordwise: true,
 6629                        done: is_empty,
 6630                    };
 6631                    self.select_prev_state = Some(select_state);
 6632                } else {
 6633                    self.select_prev_state = None;
 6634                }
 6635
 6636                self.unfold_ranges(
 6637                    selections.iter().map(|s| s.range()).collect::<Vec<_>>(),
 6638                    false,
 6639                    true,
 6640                    cx,
 6641                );
 6642                self.change_selections(Some(Autoscroll::newest()), cx, |s| {
 6643                    s.select(selections);
 6644                });
 6645            } else if let Some(selected_text) = selected_text {
 6646                self.select_prev_state = Some(SelectNextState {
 6647                    query: AhoCorasick::new(&[selected_text.chars().rev().collect::<String>()])?,
 6648                    wordwise: false,
 6649                    done: false,
 6650                });
 6651                self.select_previous(action, cx)?;
 6652            }
 6653        }
 6654        Ok(())
 6655    }
 6656
 6657    pub fn toggle_comments(&mut self, action: &ToggleComments, cx: &mut ViewContext<Self>) {
 6658        let text_layout_details = &self.text_layout_details(cx);
 6659        self.transact(cx, |this, cx| {
 6660            let mut selections = this.selections.all::<Point>(cx);
 6661            let mut edits = Vec::new();
 6662            let mut selection_edit_ranges = Vec::new();
 6663            let mut last_toggled_row = None;
 6664            let snapshot = this.buffer.read(cx).read(cx);
 6665            let empty_str: Arc<str> = "".into();
 6666            let mut suffixes_inserted = Vec::new();
 6667
 6668            fn comment_prefix_range(
 6669                snapshot: &MultiBufferSnapshot,
 6670                row: u32,
 6671                comment_prefix: &str,
 6672                comment_prefix_whitespace: &str,
 6673            ) -> Range<Point> {
 6674                let start = Point::new(row, snapshot.indent_size_for_line(row).len);
 6675
 6676                let mut line_bytes = snapshot
 6677                    .bytes_in_range(start..snapshot.max_point())
 6678                    .flatten()
 6679                    .copied();
 6680
 6681                // If this line currently begins with the line comment prefix, then record
 6682                // the range containing the prefix.
 6683                if line_bytes
 6684                    .by_ref()
 6685                    .take(comment_prefix.len())
 6686                    .eq(comment_prefix.bytes())
 6687                {
 6688                    // Include any whitespace that matches the comment prefix.
 6689                    let matching_whitespace_len = line_bytes
 6690                        .zip(comment_prefix_whitespace.bytes())
 6691                        .take_while(|(a, b)| a == b)
 6692                        .count() as u32;
 6693                    let end = Point::new(
 6694                        start.row,
 6695                        start.column + comment_prefix.len() as u32 + matching_whitespace_len,
 6696                    );
 6697                    start..end
 6698                } else {
 6699                    start..start
 6700                }
 6701            }
 6702
 6703            fn comment_suffix_range(
 6704                snapshot: &MultiBufferSnapshot,
 6705                row: u32,
 6706                comment_suffix: &str,
 6707                comment_suffix_has_leading_space: bool,
 6708            ) -> Range<Point> {
 6709                let end = Point::new(row, snapshot.line_len(row));
 6710                let suffix_start_column = end.column.saturating_sub(comment_suffix.len() as u32);
 6711
 6712                let mut line_end_bytes = snapshot
 6713                    .bytes_in_range(Point::new(end.row, suffix_start_column.saturating_sub(1))..end)
 6714                    .flatten()
 6715                    .copied();
 6716
 6717                let leading_space_len = if suffix_start_column > 0
 6718                    && line_end_bytes.next() == Some(b' ')
 6719                    && comment_suffix_has_leading_space
 6720                {
 6721                    1
 6722                } else {
 6723                    0
 6724                };
 6725
 6726                // If this line currently begins with the line comment prefix, then record
 6727                // the range containing the prefix.
 6728                if line_end_bytes.by_ref().eq(comment_suffix.bytes()) {
 6729                    let start = Point::new(end.row, suffix_start_column - leading_space_len);
 6730                    start..end
 6731                } else {
 6732                    end..end
 6733                }
 6734            }
 6735
 6736            // TODO: Handle selections that cross excerpts
 6737            for selection in &mut selections {
 6738                let start_column = snapshot.indent_size_for_line(selection.start.row).len;
 6739                let language = if let Some(language) =
 6740                    snapshot.language_scope_at(Point::new(selection.start.row, start_column))
 6741                {
 6742                    language
 6743                } else {
 6744                    continue;
 6745                };
 6746
 6747                selection_edit_ranges.clear();
 6748
 6749                // If multiple selections contain a given row, avoid processing that
 6750                // row more than once.
 6751                let mut start_row = selection.start.row;
 6752                if last_toggled_row == Some(start_row) {
 6753                    start_row += 1;
 6754                }
 6755                let end_row =
 6756                    if selection.end.row > selection.start.row && selection.end.column == 0 {
 6757                        selection.end.row - 1
 6758                    } else {
 6759                        selection.end.row
 6760                    };
 6761                last_toggled_row = Some(end_row);
 6762
 6763                if start_row > end_row {
 6764                    continue;
 6765                }
 6766
 6767                // If the language has line comments, toggle those.
 6768                if let Some(full_comment_prefix) = language
 6769                    .line_comment_prefixes()
 6770                    .and_then(|prefixes| prefixes.first())
 6771                {
 6772                    // Split the comment prefix's trailing whitespace into a separate string,
 6773                    // as that portion won't be used for detecting if a line is a comment.
 6774                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
 6775                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
 6776                    let mut all_selection_lines_are_comments = true;
 6777
 6778                    for row in start_row..=end_row {
 6779                        if start_row < end_row && snapshot.is_line_blank(row) {
 6780                            continue;
 6781                        }
 6782
 6783                        let prefix_range = comment_prefix_range(
 6784                            snapshot.deref(),
 6785                            row,
 6786                            comment_prefix,
 6787                            comment_prefix_whitespace,
 6788                        );
 6789                        if prefix_range.is_empty() {
 6790                            all_selection_lines_are_comments = false;
 6791                        }
 6792                        selection_edit_ranges.push(prefix_range);
 6793                    }
 6794
 6795                    if all_selection_lines_are_comments {
 6796                        edits.extend(
 6797                            selection_edit_ranges
 6798                                .iter()
 6799                                .cloned()
 6800                                .map(|range| (range, empty_str.clone())),
 6801                        );
 6802                    } else {
 6803                        let min_column = selection_edit_ranges
 6804                            .iter()
 6805                            .map(|r| r.start.column)
 6806                            .min()
 6807                            .unwrap_or(0);
 6808                        edits.extend(selection_edit_ranges.iter().map(|range| {
 6809                            let position = Point::new(range.start.row, min_column);
 6810                            (position..position, full_comment_prefix.clone())
 6811                        }));
 6812                    }
 6813                } else if let Some((full_comment_prefix, comment_suffix)) =
 6814                    language.block_comment_delimiters()
 6815                {
 6816                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
 6817                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
 6818                    let prefix_range = comment_prefix_range(
 6819                        snapshot.deref(),
 6820                        start_row,
 6821                        comment_prefix,
 6822                        comment_prefix_whitespace,
 6823                    );
 6824                    let suffix_range = comment_suffix_range(
 6825                        snapshot.deref(),
 6826                        end_row,
 6827                        comment_suffix.trim_start_matches(' '),
 6828                        comment_suffix.starts_with(' '),
 6829                    );
 6830
 6831                    if prefix_range.is_empty() || suffix_range.is_empty() {
 6832                        edits.push((
 6833                            prefix_range.start..prefix_range.start,
 6834                            full_comment_prefix.clone(),
 6835                        ));
 6836                        edits.push((suffix_range.end..suffix_range.end, comment_suffix.clone()));
 6837                        suffixes_inserted.push((end_row, comment_suffix.len()));
 6838                    } else {
 6839                        edits.push((prefix_range, empty_str.clone()));
 6840                        edits.push((suffix_range, empty_str.clone()));
 6841                    }
 6842                } else {
 6843                    continue;
 6844                }
 6845            }
 6846
 6847            drop(snapshot);
 6848            this.buffer.update(cx, |buffer, cx| {
 6849                buffer.edit(edits, None, cx);
 6850            });
 6851
 6852            // Adjust selections so that they end before any comment suffixes that
 6853            // were inserted.
 6854            let mut suffixes_inserted = suffixes_inserted.into_iter().peekable();
 6855            let mut selections = this.selections.all::<Point>(cx);
 6856            let snapshot = this.buffer.read(cx).read(cx);
 6857            for selection in &mut selections {
 6858                while let Some((row, suffix_len)) = suffixes_inserted.peek().copied() {
 6859                    match row.cmp(&selection.end.row) {
 6860                        Ordering::Less => {
 6861                            suffixes_inserted.next();
 6862                            continue;
 6863                        }
 6864                        Ordering::Greater => break,
 6865                        Ordering::Equal => {
 6866                            if selection.end.column == snapshot.line_len(row) {
 6867                                if selection.is_empty() {
 6868                                    selection.start.column -= suffix_len as u32;
 6869                                }
 6870                                selection.end.column -= suffix_len as u32;
 6871                            }
 6872                            break;
 6873                        }
 6874                    }
 6875                }
 6876            }
 6877
 6878            drop(snapshot);
 6879            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
 6880
 6881            let selections = this.selections.all::<Point>(cx);
 6882            let selections_on_single_row = selections.windows(2).all(|selections| {
 6883                selections[0].start.row == selections[1].start.row
 6884                    && selections[0].end.row == selections[1].end.row
 6885                    && selections[0].start.row == selections[0].end.row
 6886            });
 6887            let selections_selecting = selections
 6888                .iter()
 6889                .any(|selection| selection.start != selection.end);
 6890            let advance_downwards = action.advance_downwards
 6891                && selections_on_single_row
 6892                && !selections_selecting
 6893                && this.mode != EditorMode::SingleLine;
 6894
 6895            if advance_downwards {
 6896                let snapshot = this.buffer.read(cx).snapshot(cx);
 6897
 6898                this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6899                    s.move_cursors_with(|display_snapshot, display_point, _| {
 6900                        let mut point = display_point.to_point(display_snapshot);
 6901                        point.row += 1;
 6902                        point = snapshot.clip_point(point, Bias::Left);
 6903                        let display_point = point.to_display_point(display_snapshot);
 6904                        let goal = SelectionGoal::HorizontalPosition(
 6905                            display_snapshot
 6906                                .x_for_display_point(display_point, &text_layout_details)
 6907                                .into(),
 6908                        );
 6909                        (display_point, goal)
 6910                    })
 6911                });
 6912            }
 6913        });
 6914    }
 6915
 6916    pub fn select_larger_syntax_node(
 6917        &mut self,
 6918        _: &SelectLargerSyntaxNode,
 6919        cx: &mut ViewContext<Self>,
 6920    ) {
 6921        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 6922        let buffer = self.buffer.read(cx).snapshot(cx);
 6923        let old_selections = self.selections.all::<usize>(cx).into_boxed_slice();
 6924
 6925        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
 6926        let mut selected_larger_node = false;
 6927        let new_selections = old_selections
 6928            .iter()
 6929            .map(|selection| {
 6930                let old_range = selection.start..selection.end;
 6931                let mut new_range = old_range.clone();
 6932                while let Some(containing_range) =
 6933                    buffer.range_for_syntax_ancestor(new_range.clone())
 6934                {
 6935                    new_range = containing_range;
 6936                    if !display_map.intersects_fold(new_range.start)
 6937                        && !display_map.intersects_fold(new_range.end)
 6938                    {
 6939                        break;
 6940                    }
 6941                }
 6942
 6943                selected_larger_node |= new_range != old_range;
 6944                Selection {
 6945                    id: selection.id,
 6946                    start: new_range.start,
 6947                    end: new_range.end,
 6948                    goal: SelectionGoal::None,
 6949                    reversed: selection.reversed,
 6950                }
 6951            })
 6952            .collect::<Vec<_>>();
 6953
 6954        if selected_larger_node {
 6955            stack.push(old_selections);
 6956            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6957                s.select(new_selections);
 6958            });
 6959        }
 6960        self.select_larger_syntax_node_stack = stack;
 6961    }
 6962
 6963    pub fn select_smaller_syntax_node(
 6964        &mut self,
 6965        _: &SelectSmallerSyntaxNode,
 6966        cx: &mut ViewContext<Self>,
 6967    ) {
 6968        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
 6969        if let Some(selections) = stack.pop() {
 6970            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6971                s.select(selections.to_vec());
 6972            });
 6973        }
 6974        self.select_larger_syntax_node_stack = stack;
 6975    }
 6976
 6977    pub fn move_to_enclosing_bracket(
 6978        &mut self,
 6979        _: &MoveToEnclosingBracket,
 6980        cx: &mut ViewContext<Self>,
 6981    ) {
 6982        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6983            s.move_offsets_with(|snapshot, selection| {
 6984                let Some(enclosing_bracket_ranges) =
 6985                    snapshot.enclosing_bracket_ranges(selection.start..selection.end)
 6986                else {
 6987                    return;
 6988                };
 6989
 6990                let mut best_length = usize::MAX;
 6991                let mut best_inside = false;
 6992                let mut best_in_bracket_range = false;
 6993                let mut best_destination = None;
 6994                for (open, close) in enclosing_bracket_ranges {
 6995                    let close = close.to_inclusive();
 6996                    let length = close.end() - open.start;
 6997                    let inside = selection.start >= open.end && selection.end <= *close.start();
 6998                    let in_bracket_range = open.to_inclusive().contains(&selection.head())
 6999                        || close.contains(&selection.head());
 7000
 7001                    // If best is next to a bracket and current isn't, skip
 7002                    if !in_bracket_range && best_in_bracket_range {
 7003                        continue;
 7004                    }
 7005
 7006                    // Prefer smaller lengths unless best is inside and current isn't
 7007                    if length > best_length && (best_inside || !inside) {
 7008                        continue;
 7009                    }
 7010
 7011                    best_length = length;
 7012                    best_inside = inside;
 7013                    best_in_bracket_range = in_bracket_range;
 7014                    best_destination = Some(
 7015                        if close.contains(&selection.start) && close.contains(&selection.end) {
 7016                            if inside {
 7017                                open.end
 7018                            } else {
 7019                                open.start
 7020                            }
 7021                        } else {
 7022                            if inside {
 7023                                *close.start()
 7024                            } else {
 7025                                *close.end()
 7026                            }
 7027                        },
 7028                    );
 7029                }
 7030
 7031                if let Some(destination) = best_destination {
 7032                    selection.collapse_to(destination, SelectionGoal::None);
 7033                }
 7034            })
 7035        });
 7036    }
 7037
 7038    pub fn undo_selection(&mut self, _: &UndoSelection, cx: &mut ViewContext<Self>) {
 7039        self.end_selection(cx);
 7040        self.selection_history.mode = SelectionHistoryMode::Undoing;
 7041        if let Some(entry) = self.selection_history.undo_stack.pop_back() {
 7042            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
 7043            self.select_next_state = entry.select_next_state;
 7044            self.select_prev_state = entry.select_prev_state;
 7045            self.add_selections_state = entry.add_selections_state;
 7046            self.request_autoscroll(Autoscroll::newest(), cx);
 7047        }
 7048        self.selection_history.mode = SelectionHistoryMode::Normal;
 7049    }
 7050
 7051    pub fn redo_selection(&mut self, _: &RedoSelection, cx: &mut ViewContext<Self>) {
 7052        self.end_selection(cx);
 7053        self.selection_history.mode = SelectionHistoryMode::Redoing;
 7054        if let Some(entry) = self.selection_history.redo_stack.pop_back() {
 7055            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
 7056            self.select_next_state = entry.select_next_state;
 7057            self.select_prev_state = entry.select_prev_state;
 7058            self.add_selections_state = entry.add_selections_state;
 7059            self.request_autoscroll(Autoscroll::newest(), cx);
 7060        }
 7061        self.selection_history.mode = SelectionHistoryMode::Normal;
 7062    }
 7063
 7064    fn go_to_diagnostic(&mut self, _: &GoToDiagnostic, cx: &mut ViewContext<Self>) {
 7065        self.go_to_diagnostic_impl(Direction::Next, cx)
 7066    }
 7067
 7068    fn go_to_prev_diagnostic(&mut self, _: &GoToPrevDiagnostic, cx: &mut ViewContext<Self>) {
 7069        self.go_to_diagnostic_impl(Direction::Prev, cx)
 7070    }
 7071
 7072    pub fn go_to_diagnostic_impl(&mut self, direction: Direction, cx: &mut ViewContext<Self>) {
 7073        let buffer = self.buffer.read(cx).snapshot(cx);
 7074        let selection = self.selections.newest::<usize>(cx);
 7075
 7076        // If there is an active Diagnostic Popover jump to its diagnostic instead.
 7077        if direction == Direction::Next {
 7078            if let Some(popover) = self.hover_state.diagnostic_popover.as_ref() {
 7079                let (group_id, jump_to) = popover.activation_info();
 7080                if self.activate_diagnostics(group_id, cx) {
 7081                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7082                        let mut new_selection = s.newest_anchor().clone();
 7083                        new_selection.collapse_to(jump_to, SelectionGoal::None);
 7084                        s.select_anchors(vec![new_selection.clone()]);
 7085                    });
 7086                }
 7087                return;
 7088            }
 7089        }
 7090
 7091        let mut active_primary_range = self.active_diagnostics.as_ref().map(|active_diagnostics| {
 7092            active_diagnostics
 7093                .primary_range
 7094                .to_offset(&buffer)
 7095                .to_inclusive()
 7096        });
 7097        let mut search_start = if let Some(active_primary_range) = active_primary_range.as_ref() {
 7098            if active_primary_range.contains(&selection.head()) {
 7099                *active_primary_range.end()
 7100            } else {
 7101                selection.head()
 7102            }
 7103        } else {
 7104            selection.head()
 7105        };
 7106
 7107        loop {
 7108            let mut diagnostics = if direction == Direction::Prev {
 7109                buffer.diagnostics_in_range::<_, usize>(0..search_start, true)
 7110            } else {
 7111                buffer.diagnostics_in_range::<_, usize>(search_start..buffer.len(), false)
 7112            };
 7113            let group = diagnostics.find_map(|entry| {
 7114                if entry.diagnostic.is_primary
 7115                    && entry.diagnostic.severity <= DiagnosticSeverity::WARNING
 7116                    && !entry.range.is_empty()
 7117                    && Some(entry.range.end) != active_primary_range.as_ref().map(|r| *r.end())
 7118                    && !entry.range.contains(&search_start)
 7119                {
 7120                    Some((entry.range, entry.diagnostic.group_id))
 7121                } else {
 7122                    None
 7123                }
 7124            });
 7125
 7126            if let Some((primary_range, group_id)) = group {
 7127                if self.activate_diagnostics(group_id, cx) {
 7128                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7129                        s.select(vec![Selection {
 7130                            id: selection.id,
 7131                            start: primary_range.start,
 7132                            end: primary_range.start,
 7133                            reversed: false,
 7134                            goal: SelectionGoal::None,
 7135                        }]);
 7136                    });
 7137                }
 7138                break;
 7139            } else {
 7140                // Cycle around to the start of the buffer, potentially moving back to the start of
 7141                // the currently active diagnostic.
 7142                active_primary_range.take();
 7143                if direction == Direction::Prev {
 7144                    if search_start == buffer.len() {
 7145                        break;
 7146                    } else {
 7147                        search_start = buffer.len();
 7148                    }
 7149                } else if search_start == 0 {
 7150                    break;
 7151                } else {
 7152                    search_start = 0;
 7153                }
 7154            }
 7155        }
 7156    }
 7157
 7158    fn go_to_hunk(&mut self, _: &GoToHunk, cx: &mut ViewContext<Self>) {
 7159        let snapshot = self
 7160            .display_map
 7161            .update(cx, |display_map, cx| display_map.snapshot(cx));
 7162        let selection = self.selections.newest::<Point>(cx);
 7163
 7164        if !self.seek_in_direction(
 7165            &snapshot,
 7166            selection.head(),
 7167            false,
 7168            snapshot
 7169                .buffer_snapshot
 7170                .git_diff_hunks_in_range((selection.head().row + 1)..u32::MAX),
 7171            cx,
 7172        ) {
 7173            let wrapped_point = Point::zero();
 7174            self.seek_in_direction(
 7175                &snapshot,
 7176                wrapped_point,
 7177                true,
 7178                snapshot
 7179                    .buffer_snapshot
 7180                    .git_diff_hunks_in_range((wrapped_point.row + 1)..u32::MAX),
 7181                cx,
 7182            );
 7183        }
 7184    }
 7185
 7186    fn go_to_prev_hunk(&mut self, _: &GoToPrevHunk, cx: &mut ViewContext<Self>) {
 7187        let snapshot = self
 7188            .display_map
 7189            .update(cx, |display_map, cx| display_map.snapshot(cx));
 7190        let selection = self.selections.newest::<Point>(cx);
 7191
 7192        if !self.seek_in_direction(
 7193            &snapshot,
 7194            selection.head(),
 7195            false,
 7196            snapshot
 7197                .buffer_snapshot
 7198                .git_diff_hunks_in_range_rev(0..selection.head().row),
 7199            cx,
 7200        ) {
 7201            let wrapped_point = snapshot.buffer_snapshot.max_point();
 7202            self.seek_in_direction(
 7203                &snapshot,
 7204                wrapped_point,
 7205                true,
 7206                snapshot
 7207                    .buffer_snapshot
 7208                    .git_diff_hunks_in_range_rev(0..wrapped_point.row),
 7209                cx,
 7210            );
 7211        }
 7212    }
 7213
 7214    fn seek_in_direction(
 7215        &mut self,
 7216        snapshot: &DisplaySnapshot,
 7217        initial_point: Point,
 7218        is_wrapped: bool,
 7219        hunks: impl Iterator<Item = DiffHunk<u32>>,
 7220        cx: &mut ViewContext<Editor>,
 7221    ) -> bool {
 7222        let display_point = initial_point.to_display_point(snapshot);
 7223        let mut hunks = hunks
 7224            .map(|hunk| diff_hunk_to_display(hunk, &snapshot))
 7225            .filter(|hunk| {
 7226                if is_wrapped {
 7227                    true
 7228                } else {
 7229                    !hunk.contains_display_row(display_point.row())
 7230                }
 7231            })
 7232            .dedup();
 7233
 7234        if let Some(hunk) = hunks.next() {
 7235            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7236                let row = hunk.start_display_row();
 7237                let point = DisplayPoint::new(row, 0);
 7238                s.select_display_ranges([point..point]);
 7239            });
 7240
 7241            true
 7242        } else {
 7243            false
 7244        }
 7245    }
 7246
 7247    pub fn go_to_definition(&mut self, _: &GoToDefinition, cx: &mut ViewContext<Self>) {
 7248        self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, false, cx);
 7249    }
 7250
 7251    pub fn go_to_type_definition(&mut self, _: &GoToTypeDefinition, cx: &mut ViewContext<Self>) {
 7252        self.go_to_definition_of_kind(GotoDefinitionKind::Type, false, cx);
 7253    }
 7254
 7255    pub fn go_to_definition_split(&mut self, _: &GoToDefinitionSplit, cx: &mut ViewContext<Self>) {
 7256        self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, true, cx);
 7257    }
 7258
 7259    pub fn go_to_type_definition_split(
 7260        &mut self,
 7261        _: &GoToTypeDefinitionSplit,
 7262        cx: &mut ViewContext<Self>,
 7263    ) {
 7264        self.go_to_definition_of_kind(GotoDefinitionKind::Type, true, cx);
 7265    }
 7266
 7267    fn go_to_definition_of_kind(
 7268        &mut self,
 7269        kind: GotoDefinitionKind,
 7270        split: bool,
 7271        cx: &mut ViewContext<Self>,
 7272    ) {
 7273        let Some(workspace) = self.workspace() else {
 7274            return;
 7275        };
 7276        let buffer = self.buffer.read(cx);
 7277        let head = self.selections.newest::<usize>(cx).head();
 7278        let (buffer, head) = if let Some(text_anchor) = buffer.text_anchor_for_position(head, cx) {
 7279            text_anchor
 7280        } else {
 7281            return;
 7282        };
 7283
 7284        let project = workspace.read(cx).project().clone();
 7285        let definitions = project.update(cx, |project, cx| match kind {
 7286            GotoDefinitionKind::Symbol => project.definition(&buffer, head, cx),
 7287            GotoDefinitionKind::Type => project.type_definition(&buffer, head, cx),
 7288        });
 7289
 7290        cx.spawn(|editor, mut cx| async move {
 7291            let definitions = definitions.await?;
 7292            editor.update(&mut cx, |editor, cx| {
 7293                editor.navigate_to_hover_links(
 7294                    definitions.into_iter().map(HoverLink::Text).collect(),
 7295                    split,
 7296                    cx,
 7297                );
 7298            })?;
 7299            Ok::<(), anyhow::Error>(())
 7300        })
 7301        .detach_and_log_err(cx);
 7302    }
 7303
 7304    pub fn navigate_to_hover_links(
 7305        &mut self,
 7306        mut definitions: Vec<HoverLink>,
 7307        split: bool,
 7308        cx: &mut ViewContext<Editor>,
 7309    ) {
 7310        // If there is one definition, just open it directly
 7311        if definitions.len() == 1 {
 7312            let definition = definitions.pop().unwrap();
 7313            let target_task = match definition {
 7314                HoverLink::Text(link) => Task::Ready(Some(Ok(Some(link.target)))),
 7315                HoverLink::InlayHint(lsp_location, server_id) => {
 7316                    self.compute_target_location(lsp_location, server_id, cx)
 7317                }
 7318                HoverLink::Url(url) => {
 7319                    cx.open_url(&url);
 7320                    Task::ready(Ok(None))
 7321                }
 7322            };
 7323            cx.spawn(|editor, mut cx| async move {
 7324                let target = target_task.await.context("target resolution task")?;
 7325                if let Some(target) = target {
 7326                    editor.update(&mut cx, |editor, cx| {
 7327                        let Some(workspace) = editor.workspace() else {
 7328                            return;
 7329                        };
 7330                        let pane = workspace.read(cx).active_pane().clone();
 7331
 7332                        let range = target.range.to_offset(target.buffer.read(cx));
 7333                        let range = editor.range_for_match(&range);
 7334                        if Some(&target.buffer) == editor.buffer.read(cx).as_singleton().as_ref() {
 7335                            editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7336                                s.select_ranges([range]);
 7337                            });
 7338                        } else {
 7339                            cx.window_context().defer(move |cx| {
 7340                                let target_editor: View<Self> =
 7341                                    workspace.update(cx, |workspace, cx| {
 7342                                        if split {
 7343                                            workspace.split_project_item(target.buffer.clone(), cx)
 7344                                        } else {
 7345                                            workspace.open_project_item(target.buffer.clone(), cx)
 7346                                        }
 7347                                    });
 7348                                target_editor.update(cx, |target_editor, cx| {
 7349                                    // When selecting a definition in a different buffer, disable the nav history
 7350                                    // to avoid creating a history entry at the previous cursor location.
 7351                                    pane.update(cx, |pane, _| pane.disable_history());
 7352                                    target_editor.change_selections(
 7353                                        Some(Autoscroll::fit()),
 7354                                        cx,
 7355                                        |s| {
 7356                                            s.select_ranges([range]);
 7357                                        },
 7358                                    );
 7359                                    pane.update(cx, |pane, _| pane.enable_history());
 7360                                });
 7361                            });
 7362                        }
 7363                    })
 7364                } else {
 7365                    Ok(())
 7366                }
 7367            })
 7368            .detach_and_log_err(cx);
 7369        } else if !definitions.is_empty() {
 7370            let replica_id = self.replica_id(cx);
 7371            cx.spawn(|editor, mut cx| async move {
 7372                let (title, location_tasks, workspace) = editor
 7373                    .update(&mut cx, |editor, cx| {
 7374                        let title = definitions
 7375                            .iter()
 7376                            .find_map(|definition| match definition {
 7377                                HoverLink::Text(link) => link.origin.as_ref().map(|origin| {
 7378                                    let buffer = origin.buffer.read(cx);
 7379                                    format!(
 7380                                        "Definitions for {}",
 7381                                        buffer
 7382                                            .text_for_range(origin.range.clone())
 7383                                            .collect::<String>()
 7384                                    )
 7385                                }),
 7386                                HoverLink::InlayHint(_, _) => None,
 7387                                HoverLink::Url(_) => None,
 7388                            })
 7389                            .unwrap_or("Definitions".to_string());
 7390                        let location_tasks = definitions
 7391                            .into_iter()
 7392                            .map(|definition| match definition {
 7393                                HoverLink::Text(link) => Task::Ready(Some(Ok(Some(link.target)))),
 7394                                HoverLink::InlayHint(lsp_location, server_id) => {
 7395                                    editor.compute_target_location(lsp_location, server_id, cx)
 7396                                }
 7397                                HoverLink::Url(_) => Task::ready(Ok(None)),
 7398                            })
 7399                            .collect::<Vec<_>>();
 7400                        (title, location_tasks, editor.workspace().clone())
 7401                    })
 7402                    .context("location tasks preparation")?;
 7403
 7404                let locations = futures::future::join_all(location_tasks)
 7405                    .await
 7406                    .into_iter()
 7407                    .filter_map(|location| location.transpose())
 7408                    .collect::<Result<_>>()
 7409                    .context("location tasks")?;
 7410
 7411                let Some(workspace) = workspace else {
 7412                    return Ok(());
 7413                };
 7414                workspace
 7415                    .update(&mut cx, |workspace, cx| {
 7416                        Self::open_locations_in_multibuffer(
 7417                            workspace, locations, replica_id, title, split, cx,
 7418                        )
 7419                    })
 7420                    .ok();
 7421
 7422                anyhow::Ok(())
 7423            })
 7424            .detach_and_log_err(cx);
 7425        }
 7426    }
 7427
 7428    fn compute_target_location(
 7429        &self,
 7430        lsp_location: lsp::Location,
 7431        server_id: LanguageServerId,
 7432        cx: &mut ViewContext<Editor>,
 7433    ) -> Task<anyhow::Result<Option<Location>>> {
 7434        let Some(project) = self.project.clone() else {
 7435            return Task::Ready(Some(Ok(None)));
 7436        };
 7437
 7438        cx.spawn(move |editor, mut cx| async move {
 7439            let location_task = editor.update(&mut cx, |editor, cx| {
 7440                project.update(cx, |project, cx| {
 7441                    let language_server_name =
 7442                        editor.buffer.read(cx).as_singleton().and_then(|buffer| {
 7443                            project
 7444                                .language_server_for_buffer(buffer.read(cx), server_id, cx)
 7445                                .map(|(lsp_adapter, _)| lsp_adapter.name.clone())
 7446                        });
 7447                    language_server_name.map(|language_server_name| {
 7448                        project.open_local_buffer_via_lsp(
 7449                            lsp_location.uri.clone(),
 7450                            server_id,
 7451                            language_server_name,
 7452                            cx,
 7453                        )
 7454                    })
 7455                })
 7456            })?;
 7457            let location = match location_task {
 7458                Some(task) => Some({
 7459                    let target_buffer_handle = task.await.context("open local buffer")?;
 7460                    let range = target_buffer_handle.update(&mut cx, |target_buffer, _| {
 7461                        let target_start = target_buffer
 7462                            .clip_point_utf16(point_from_lsp(lsp_location.range.start), Bias::Left);
 7463                        let target_end = target_buffer
 7464                            .clip_point_utf16(point_from_lsp(lsp_location.range.end), Bias::Left);
 7465                        target_buffer.anchor_after(target_start)
 7466                            ..target_buffer.anchor_before(target_end)
 7467                    })?;
 7468                    Location {
 7469                        buffer: target_buffer_handle,
 7470                        range,
 7471                    }
 7472                }),
 7473                None => None,
 7474            };
 7475            Ok(location)
 7476        })
 7477    }
 7478
 7479    pub fn find_all_references(
 7480        &mut self,
 7481        _: &FindAllReferences,
 7482        cx: &mut ViewContext<Self>,
 7483    ) -> Option<Task<Result<()>>> {
 7484        let buffer = self.buffer.read(cx);
 7485        let head = self.selections.newest::<usize>(cx).head();
 7486        let (buffer, head) = buffer.text_anchor_for_position(head, cx)?;
 7487        let replica_id = self.replica_id(cx);
 7488
 7489        let workspace = self.workspace()?;
 7490        let project = workspace.read(cx).project().clone();
 7491        let references = project.update(cx, |project, cx| project.references(&buffer, head, cx));
 7492        Some(cx.spawn(|_, mut cx| async move {
 7493            let locations = references.await?;
 7494            if locations.is_empty() {
 7495                return Ok(());
 7496            }
 7497
 7498            workspace.update(&mut cx, |workspace, cx| {
 7499                let title = locations
 7500                    .first()
 7501                    .as_ref()
 7502                    .map(|location| {
 7503                        let buffer = location.buffer.read(cx);
 7504                        format!(
 7505                            "References to `{}`",
 7506                            buffer
 7507                                .text_for_range(location.range.clone())
 7508                                .collect::<String>()
 7509                        )
 7510                    })
 7511                    .unwrap();
 7512                Self::open_locations_in_multibuffer(
 7513                    workspace, locations, replica_id, title, false, cx,
 7514                );
 7515            })?;
 7516
 7517            Ok(())
 7518        }))
 7519    }
 7520
 7521    /// Opens a multibuffer with the given project locations in it
 7522    pub fn open_locations_in_multibuffer(
 7523        workspace: &mut Workspace,
 7524        mut locations: Vec<Location>,
 7525        replica_id: ReplicaId,
 7526        title: String,
 7527        split: bool,
 7528        cx: &mut ViewContext<Workspace>,
 7529    ) {
 7530        // If there are multiple definitions, open them in a multibuffer
 7531        locations.sort_by_key(|location| location.buffer.read(cx).remote_id());
 7532        let mut locations = locations.into_iter().peekable();
 7533        let mut ranges_to_highlight = Vec::new();
 7534        let capability = workspace.project().read(cx).capability();
 7535
 7536        let excerpt_buffer = cx.new_model(|cx| {
 7537            let mut multibuffer = MultiBuffer::new(replica_id, capability);
 7538            while let Some(location) = locations.next() {
 7539                let buffer = location.buffer.read(cx);
 7540                let mut ranges_for_buffer = Vec::new();
 7541                let range = location.range.to_offset(buffer);
 7542                ranges_for_buffer.push(range.clone());
 7543
 7544                while let Some(next_location) = locations.peek() {
 7545                    if next_location.buffer == location.buffer {
 7546                        ranges_for_buffer.push(next_location.range.to_offset(buffer));
 7547                        locations.next();
 7548                    } else {
 7549                        break;
 7550                    }
 7551                }
 7552
 7553                ranges_for_buffer.sort_by_key(|range| (range.start, Reverse(range.end)));
 7554                ranges_to_highlight.extend(multibuffer.push_excerpts_with_context_lines(
 7555                    location.buffer.clone(),
 7556                    ranges_for_buffer,
 7557                    1,
 7558                    cx,
 7559                ))
 7560            }
 7561
 7562            multibuffer.with_title(title)
 7563        });
 7564
 7565        let editor = cx.new_view(|cx| {
 7566            Editor::for_multibuffer(excerpt_buffer, Some(workspace.project().clone()), cx)
 7567        });
 7568        editor.update(cx, |editor, cx| {
 7569            editor.highlight_background::<Self>(
 7570                ranges_to_highlight,
 7571                |theme| theme.editor_highlighted_line_background,
 7572                cx,
 7573            );
 7574        });
 7575        if split {
 7576            workspace.split_item(SplitDirection::Right, Box::new(editor), cx);
 7577        } else {
 7578            workspace.add_item(Box::new(editor), cx);
 7579        }
 7580    }
 7581
 7582    pub fn rename(&mut self, _: &Rename, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
 7583        use language::ToOffset as _;
 7584
 7585        let project = self.project.clone()?;
 7586        let selection = self.selections.newest_anchor().clone();
 7587        let (cursor_buffer, cursor_buffer_position) = self
 7588            .buffer
 7589            .read(cx)
 7590            .text_anchor_for_position(selection.head(), cx)?;
 7591        let (tail_buffer, _) = self
 7592            .buffer
 7593            .read(cx)
 7594            .text_anchor_for_position(selection.tail(), cx)?;
 7595        if tail_buffer != cursor_buffer {
 7596            return None;
 7597        }
 7598
 7599        let snapshot = cursor_buffer.read(cx).snapshot();
 7600        let cursor_buffer_offset = cursor_buffer_position.to_offset(&snapshot);
 7601        let prepare_rename = project.update(cx, |project, cx| {
 7602            project.prepare_rename(cursor_buffer, cursor_buffer_offset, cx)
 7603        });
 7604
 7605        Some(cx.spawn(|this, mut cx| async move {
 7606            let rename_range = if let Some(range) = prepare_rename.await? {
 7607                Some(range)
 7608            } else {
 7609                this.update(&mut cx, |this, cx| {
 7610                    let buffer = this.buffer.read(cx).snapshot(cx);
 7611                    let mut buffer_highlights = this
 7612                        .document_highlights_for_position(selection.head(), &buffer)
 7613                        .filter(|highlight| {
 7614                            highlight.start.excerpt_id == selection.head().excerpt_id
 7615                                && highlight.end.excerpt_id == selection.head().excerpt_id
 7616                        });
 7617                    buffer_highlights
 7618                        .next()
 7619                        .map(|highlight| highlight.start.text_anchor..highlight.end.text_anchor)
 7620                })?
 7621            };
 7622            if let Some(rename_range) = rename_range {
 7623                let rename_buffer_range = rename_range.to_offset(&snapshot);
 7624                let cursor_offset_in_rename_range =
 7625                    cursor_buffer_offset.saturating_sub(rename_buffer_range.start);
 7626
 7627                this.update(&mut cx, |this, cx| {
 7628                    this.take_rename(false, cx);
 7629                    let buffer = this.buffer.read(cx).read(cx);
 7630                    let cursor_offset = selection.head().to_offset(&buffer);
 7631                    let rename_start = cursor_offset.saturating_sub(cursor_offset_in_rename_range);
 7632                    let rename_end = rename_start + rename_buffer_range.len();
 7633                    let range = buffer.anchor_before(rename_start)..buffer.anchor_after(rename_end);
 7634                    let mut old_highlight_id = None;
 7635                    let old_name: Arc<str> = buffer
 7636                        .chunks(rename_start..rename_end, true)
 7637                        .map(|chunk| {
 7638                            if old_highlight_id.is_none() {
 7639                                old_highlight_id = chunk.syntax_highlight_id;
 7640                            }
 7641                            chunk.text
 7642                        })
 7643                        .collect::<String>()
 7644                        .into();
 7645
 7646                    drop(buffer);
 7647
 7648                    // Position the selection in the rename editor so that it matches the current selection.
 7649                    this.show_local_selections = false;
 7650                    let rename_editor = cx.new_view(|cx| {
 7651                        let mut editor = Editor::single_line(cx);
 7652                        editor.buffer.update(cx, |buffer, cx| {
 7653                            buffer.edit([(0..0, old_name.clone())], None, cx)
 7654                        });
 7655                        editor.select_all(&SelectAll, cx);
 7656                        editor
 7657                    });
 7658
 7659                    let ranges = this
 7660                        .clear_background_highlights::<DocumentHighlightWrite>(cx)
 7661                        .into_iter()
 7662                        .flat_map(|(_, ranges)| ranges.into_iter())
 7663                        .chain(
 7664                            this.clear_background_highlights::<DocumentHighlightRead>(cx)
 7665                                .into_iter()
 7666                                .flat_map(|(_, ranges)| ranges.into_iter()),
 7667                        )
 7668                        .collect();
 7669
 7670                    this.highlight_text::<Rename>(
 7671                        ranges,
 7672                        HighlightStyle {
 7673                            fade_out: Some(0.6),
 7674                            ..Default::default()
 7675                        },
 7676                        cx,
 7677                    );
 7678                    let rename_focus_handle = rename_editor.focus_handle(cx);
 7679                    cx.focus(&rename_focus_handle);
 7680                    let block_id = this.insert_blocks(
 7681                        [BlockProperties {
 7682                            style: BlockStyle::Flex,
 7683                            position: range.start.clone(),
 7684                            height: 1,
 7685                            render: Arc::new({
 7686                                let rename_editor = rename_editor.clone();
 7687                                move |cx: &mut BlockContext| {
 7688                                    let mut text_style = cx.editor_style.text.clone();
 7689                                    if let Some(highlight_style) = old_highlight_id
 7690                                        .and_then(|h| h.style(&cx.editor_style.syntax))
 7691                                    {
 7692                                        text_style = text_style.highlight(highlight_style);
 7693                                    }
 7694                                    div()
 7695                                        .pl(cx.anchor_x)
 7696                                        .child(EditorElement::new(
 7697                                            &rename_editor,
 7698                                            EditorStyle {
 7699                                                background: cx.theme().system().transparent,
 7700                                                local_player: cx.editor_style.local_player,
 7701                                                text: text_style,
 7702                                                scrollbar_width: cx.editor_style.scrollbar_width,
 7703                                                syntax: cx.editor_style.syntax.clone(),
 7704                                                status: cx.editor_style.status.clone(),
 7705                                                inlays_style: HighlightStyle {
 7706                                                    color: Some(cx.theme().status().hint),
 7707                                                    font_weight: Some(FontWeight::BOLD),
 7708                                                    ..HighlightStyle::default()
 7709                                                },
 7710                                                suggestions_style: HighlightStyle {
 7711                                                    color: Some(cx.theme().status().predictive),
 7712                                                    ..HighlightStyle::default()
 7713                                                },
 7714                                            },
 7715                                        ))
 7716                                        .into_any_element()
 7717                                }
 7718                            }),
 7719                            disposition: BlockDisposition::Below,
 7720                        }],
 7721                        Some(Autoscroll::fit()),
 7722                        cx,
 7723                    )[0];
 7724                    this.pending_rename = Some(RenameState {
 7725                        range,
 7726                        old_name,
 7727                        editor: rename_editor,
 7728                        block_id,
 7729                    });
 7730                })?;
 7731            }
 7732
 7733            Ok(())
 7734        }))
 7735    }
 7736
 7737    pub fn confirm_rename(
 7738        &mut self,
 7739        _: &ConfirmRename,
 7740        cx: &mut ViewContext<Self>,
 7741    ) -> Option<Task<Result<()>>> {
 7742        let rename = self.take_rename(false, cx)?;
 7743        let workspace = self.workspace()?;
 7744        let (start_buffer, start) = self
 7745            .buffer
 7746            .read(cx)
 7747            .text_anchor_for_position(rename.range.start.clone(), cx)?;
 7748        let (end_buffer, end) = self
 7749            .buffer
 7750            .read(cx)
 7751            .text_anchor_for_position(rename.range.end.clone(), cx)?;
 7752        if start_buffer != end_buffer {
 7753            return None;
 7754        }
 7755
 7756        let buffer = start_buffer;
 7757        let range = start..end;
 7758        let old_name = rename.old_name;
 7759        let new_name = rename.editor.read(cx).text(cx);
 7760
 7761        let rename = workspace
 7762            .read(cx)
 7763            .project()
 7764            .clone()
 7765            .update(cx, |project, cx| {
 7766                project.perform_rename(buffer.clone(), range.start, new_name.clone(), true, cx)
 7767            });
 7768        let workspace = workspace.downgrade();
 7769
 7770        Some(cx.spawn(|editor, mut cx| async move {
 7771            let project_transaction = rename.await?;
 7772            Self::open_project_transaction(
 7773                &editor,
 7774                workspace,
 7775                project_transaction,
 7776                format!("Rename: {}{}", old_name, new_name),
 7777                cx.clone(),
 7778            )
 7779            .await?;
 7780
 7781            editor.update(&mut cx, |editor, cx| {
 7782                editor.refresh_document_highlights(cx);
 7783            })?;
 7784            Ok(())
 7785        }))
 7786    }
 7787
 7788    fn take_rename(
 7789        &mut self,
 7790        moving_cursor: bool,
 7791        cx: &mut ViewContext<Self>,
 7792    ) -> Option<RenameState> {
 7793        let rename = self.pending_rename.take()?;
 7794        if rename.editor.focus_handle(cx).is_focused(cx) {
 7795            cx.focus(&self.focus_handle);
 7796        }
 7797
 7798        self.remove_blocks(
 7799            [rename.block_id].into_iter().collect(),
 7800            Some(Autoscroll::fit()),
 7801            cx,
 7802        );
 7803        self.clear_highlights::<Rename>(cx);
 7804        self.show_local_selections = true;
 7805
 7806        if moving_cursor {
 7807            let rename_editor = rename.editor.read(cx);
 7808            let cursor_in_rename_editor = rename_editor.selections.newest::<usize>(cx).head();
 7809
 7810            // Update the selection to match the position of the selection inside
 7811            // the rename editor.
 7812            let snapshot = self.buffer.read(cx).read(cx);
 7813            let rename_range = rename.range.to_offset(&snapshot);
 7814            let cursor_in_editor = snapshot
 7815                .clip_offset(rename_range.start + cursor_in_rename_editor, Bias::Left)
 7816                .min(rename_range.end);
 7817            drop(snapshot);
 7818
 7819            self.change_selections(None, cx, |s| {
 7820                s.select_ranges(vec![cursor_in_editor..cursor_in_editor])
 7821            });
 7822        } else {
 7823            self.refresh_document_highlights(cx);
 7824        }
 7825
 7826        Some(rename)
 7827    }
 7828
 7829    #[cfg(any(test, feature = "test-support"))]
 7830    pub fn pending_rename(&self) -> Option<&RenameState> {
 7831        self.pending_rename.as_ref()
 7832    }
 7833
 7834    fn format(&mut self, _: &Format, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
 7835        let project = match &self.project {
 7836            Some(project) => project.clone(),
 7837            None => return None,
 7838        };
 7839
 7840        Some(self.perform_format(project, FormatTrigger::Manual, cx))
 7841    }
 7842
 7843    fn perform_format(
 7844        &mut self,
 7845        project: Model<Project>,
 7846        trigger: FormatTrigger,
 7847        cx: &mut ViewContext<Self>,
 7848    ) -> Task<Result<()>> {
 7849        let buffer = self.buffer().clone();
 7850        let buffers = buffer.read(cx).all_buffers();
 7851
 7852        let mut timeout = cx.background_executor().timer(FORMAT_TIMEOUT).fuse();
 7853        let format = project.update(cx, |project, cx| project.format(buffers, true, trigger, cx));
 7854
 7855        cx.spawn(|_, mut cx| async move {
 7856            let transaction = futures::select_biased! {
 7857                _ = timeout => {
 7858                    log::warn!("timed out waiting for formatting");
 7859                    None
 7860                }
 7861                transaction = format.log_err().fuse() => transaction,
 7862            };
 7863
 7864            buffer
 7865                .update(&mut cx, |buffer, cx| {
 7866                    if let Some(transaction) = transaction {
 7867                        if !buffer.is_singleton() {
 7868                            buffer.push_transaction(&transaction.0, cx);
 7869                        }
 7870                    }
 7871
 7872                    cx.notify();
 7873                })
 7874                .ok();
 7875
 7876            Ok(())
 7877        })
 7878    }
 7879
 7880    fn restart_language_server(&mut self, _: &RestartLanguageServer, cx: &mut ViewContext<Self>) {
 7881        if let Some(project) = self.project.clone() {
 7882            self.buffer.update(cx, |multi_buffer, cx| {
 7883                project.update(cx, |project, cx| {
 7884                    project.restart_language_servers_for_buffers(multi_buffer.all_buffers(), cx);
 7885                });
 7886            })
 7887        }
 7888    }
 7889
 7890    fn show_character_palette(&mut self, _: &ShowCharacterPalette, cx: &mut ViewContext<Self>) {
 7891        cx.show_character_palette();
 7892    }
 7893
 7894    fn refresh_active_diagnostics(&mut self, cx: &mut ViewContext<Editor>) {
 7895        if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
 7896            let buffer = self.buffer.read(cx).snapshot(cx);
 7897            let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
 7898            let is_valid = buffer
 7899                .diagnostics_in_range::<_, usize>(active_diagnostics.primary_range.clone(), false)
 7900                .any(|entry| {
 7901                    entry.diagnostic.is_primary
 7902                        && !entry.range.is_empty()
 7903                        && entry.range.start == primary_range_start
 7904                        && entry.diagnostic.message == active_diagnostics.primary_message
 7905                });
 7906
 7907            if is_valid != active_diagnostics.is_valid {
 7908                active_diagnostics.is_valid = is_valid;
 7909                let mut new_styles = HashMap::default();
 7910                for (block_id, diagnostic) in &active_diagnostics.blocks {
 7911                    new_styles.insert(
 7912                        *block_id,
 7913                        diagnostic_block_renderer(diagnostic.clone(), is_valid),
 7914                    );
 7915                }
 7916                self.display_map
 7917                    .update(cx, |display_map, _| display_map.replace_blocks(new_styles));
 7918            }
 7919        }
 7920    }
 7921
 7922    fn activate_diagnostics(&mut self, group_id: usize, cx: &mut ViewContext<Self>) -> bool {
 7923        self.dismiss_diagnostics(cx);
 7924        self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
 7925            let buffer = self.buffer.read(cx).snapshot(cx);
 7926
 7927            let mut primary_range = None;
 7928            let mut primary_message = None;
 7929            let mut group_end = Point::zero();
 7930            let diagnostic_group = buffer
 7931                .diagnostic_group::<Point>(group_id)
 7932                .map(|entry| {
 7933                    if entry.range.end > group_end {
 7934                        group_end = entry.range.end;
 7935                    }
 7936                    if entry.diagnostic.is_primary {
 7937                        primary_range = Some(entry.range.clone());
 7938                        primary_message = Some(entry.diagnostic.message.clone());
 7939                    }
 7940                    entry
 7941                })
 7942                .collect::<Vec<_>>();
 7943            let primary_range = primary_range?;
 7944            let primary_message = primary_message?;
 7945            let primary_range =
 7946                buffer.anchor_after(primary_range.start)..buffer.anchor_before(primary_range.end);
 7947
 7948            let blocks = display_map
 7949                .insert_blocks(
 7950                    diagnostic_group.iter().map(|entry| {
 7951                        let diagnostic = entry.diagnostic.clone();
 7952                        let message_height = diagnostic.message.matches('\n').count() as u8 + 1;
 7953                        BlockProperties {
 7954                            style: BlockStyle::Fixed,
 7955                            position: buffer.anchor_after(entry.range.start),
 7956                            height: message_height,
 7957                            render: diagnostic_block_renderer(diagnostic, true),
 7958                            disposition: BlockDisposition::Below,
 7959                        }
 7960                    }),
 7961                    cx,
 7962                )
 7963                .into_iter()
 7964                .zip(diagnostic_group.into_iter().map(|entry| entry.diagnostic))
 7965                .collect();
 7966
 7967            Some(ActiveDiagnosticGroup {
 7968                primary_range,
 7969                primary_message,
 7970                blocks,
 7971                is_valid: true,
 7972            })
 7973        });
 7974        self.active_diagnostics.is_some()
 7975    }
 7976
 7977    fn dismiss_diagnostics(&mut self, cx: &mut ViewContext<Self>) {
 7978        if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
 7979            self.display_map.update(cx, |display_map, cx| {
 7980                display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx);
 7981            });
 7982            cx.notify();
 7983        }
 7984    }
 7985
 7986    pub fn set_selections_from_remote(
 7987        &mut self,
 7988        selections: Vec<Selection<Anchor>>,
 7989        pending_selection: Option<Selection<Anchor>>,
 7990        cx: &mut ViewContext<Self>,
 7991    ) {
 7992        let old_cursor_position = self.selections.newest_anchor().head();
 7993        self.selections.change_with(cx, |s| {
 7994            s.select_anchors(selections);
 7995            if let Some(pending_selection) = pending_selection {
 7996                s.set_pending(pending_selection, SelectMode::Character);
 7997            } else {
 7998                s.clear_pending();
 7999            }
 8000        });
 8001        self.selections_did_change(false, &old_cursor_position, cx);
 8002    }
 8003
 8004    fn push_to_selection_history(&mut self) {
 8005        self.selection_history.push(SelectionHistoryEntry {
 8006            selections: self.selections.disjoint_anchors(),
 8007            select_next_state: self.select_next_state.clone(),
 8008            select_prev_state: self.select_prev_state.clone(),
 8009            add_selections_state: self.add_selections_state.clone(),
 8010        });
 8011    }
 8012
 8013    pub fn transact(
 8014        &mut self,
 8015        cx: &mut ViewContext<Self>,
 8016        update: impl FnOnce(&mut Self, &mut ViewContext<Self>),
 8017    ) -> Option<TransactionId> {
 8018        self.start_transaction_at(Instant::now(), cx);
 8019        update(self, cx);
 8020        self.end_transaction_at(Instant::now(), cx)
 8021    }
 8022
 8023    fn start_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
 8024        self.end_selection(cx);
 8025        if let Some(tx_id) = self
 8026            .buffer
 8027            .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx))
 8028        {
 8029            self.selection_history
 8030                .insert_transaction(tx_id, self.selections.disjoint_anchors());
 8031        }
 8032    }
 8033
 8034    fn end_transaction_at(
 8035        &mut self,
 8036        now: Instant,
 8037        cx: &mut ViewContext<Self>,
 8038    ) -> Option<TransactionId> {
 8039        if let Some(tx_id) = self
 8040            .buffer
 8041            .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
 8042        {
 8043            if let Some((_, end_selections)) = self.selection_history.transaction_mut(tx_id) {
 8044                *end_selections = Some(self.selections.disjoint_anchors());
 8045            } else {
 8046                log::error!("unexpectedly ended a transaction that wasn't started by this editor");
 8047            }
 8048
 8049            cx.emit(EditorEvent::Edited);
 8050            Some(tx_id)
 8051        } else {
 8052            None
 8053        }
 8054    }
 8055
 8056    pub fn fold(&mut self, _: &actions::Fold, cx: &mut ViewContext<Self>) {
 8057        let mut fold_ranges = Vec::new();
 8058
 8059        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8060
 8061        let selections = self.selections.all_adjusted(cx);
 8062        for selection in selections {
 8063            let range = selection.range().sorted();
 8064            let buffer_start_row = range.start.row;
 8065
 8066            for row in (0..=range.end.row).rev() {
 8067                let fold_range = display_map.foldable_range(row);
 8068
 8069                if let Some(fold_range) = fold_range {
 8070                    if fold_range.end.row >= buffer_start_row {
 8071                        fold_ranges.push(fold_range);
 8072                        if row <= range.start.row {
 8073                            break;
 8074                        }
 8075                    }
 8076                }
 8077            }
 8078        }
 8079
 8080        self.fold_ranges(fold_ranges, true, cx);
 8081    }
 8082
 8083    pub fn fold_at(&mut self, fold_at: &FoldAt, cx: &mut ViewContext<Self>) {
 8084        let buffer_row = fold_at.buffer_row;
 8085        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8086
 8087        if let Some(fold_range) = display_map.foldable_range(buffer_row) {
 8088            let autoscroll = self
 8089                .selections
 8090                .all::<Point>(cx)
 8091                .iter()
 8092                .any(|selection| fold_range.overlaps(&selection.range()));
 8093
 8094            self.fold_ranges(std::iter::once(fold_range), autoscroll, cx);
 8095        }
 8096    }
 8097
 8098    pub fn unfold_lines(&mut self, _: &UnfoldLines, cx: &mut ViewContext<Self>) {
 8099        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8100        let buffer = &display_map.buffer_snapshot;
 8101        let selections = self.selections.all::<Point>(cx);
 8102        let ranges = selections
 8103            .iter()
 8104            .map(|s| {
 8105                let range = s.display_range(&display_map).sorted();
 8106                let mut start = range.start.to_point(&display_map);
 8107                let mut end = range.end.to_point(&display_map);
 8108                start.column = 0;
 8109                end.column = buffer.line_len(end.row);
 8110                start..end
 8111            })
 8112            .collect::<Vec<_>>();
 8113
 8114        self.unfold_ranges(ranges, true, true, cx);
 8115    }
 8116
 8117    pub fn unfold_at(&mut self, unfold_at: &UnfoldAt, cx: &mut ViewContext<Self>) {
 8118        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8119
 8120        let intersection_range = Point::new(unfold_at.buffer_row, 0)
 8121            ..Point::new(
 8122                unfold_at.buffer_row,
 8123                display_map.buffer_snapshot.line_len(unfold_at.buffer_row),
 8124            );
 8125
 8126        let autoscroll = self
 8127            .selections
 8128            .all::<Point>(cx)
 8129            .iter()
 8130            .any(|selection| selection.range().overlaps(&intersection_range));
 8131
 8132        self.unfold_ranges(std::iter::once(intersection_range), true, autoscroll, cx)
 8133    }
 8134
 8135    pub fn fold_selected_ranges(&mut self, _: &FoldSelectedRanges, cx: &mut ViewContext<Self>) {
 8136        let selections = self.selections.all::<Point>(cx);
 8137        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8138        let line_mode = self.selections.line_mode;
 8139        let ranges = selections.into_iter().map(|s| {
 8140            if line_mode {
 8141                let start = Point::new(s.start.row, 0);
 8142                let end = Point::new(s.end.row, display_map.buffer_snapshot.line_len(s.end.row));
 8143                start..end
 8144            } else {
 8145                s.start..s.end
 8146            }
 8147        });
 8148        self.fold_ranges(ranges, true, cx);
 8149    }
 8150
 8151    pub fn fold_ranges<T: ToOffset + Clone>(
 8152        &mut self,
 8153        ranges: impl IntoIterator<Item = Range<T>>,
 8154        auto_scroll: bool,
 8155        cx: &mut ViewContext<Self>,
 8156    ) {
 8157        let mut ranges = ranges.into_iter().peekable();
 8158        if ranges.peek().is_some() {
 8159            self.display_map.update(cx, |map, cx| map.fold(ranges, cx));
 8160
 8161            if auto_scroll {
 8162                self.request_autoscroll(Autoscroll::fit(), cx);
 8163            }
 8164
 8165            cx.notify();
 8166        }
 8167    }
 8168
 8169    pub fn unfold_ranges<T: ToOffset + Clone>(
 8170        &mut self,
 8171        ranges: impl IntoIterator<Item = Range<T>>,
 8172        inclusive: bool,
 8173        auto_scroll: bool,
 8174        cx: &mut ViewContext<Self>,
 8175    ) {
 8176        let mut ranges = ranges.into_iter().peekable();
 8177        if ranges.peek().is_some() {
 8178            self.display_map
 8179                .update(cx, |map, cx| map.unfold(ranges, inclusive, cx));
 8180            if auto_scroll {
 8181                self.request_autoscroll(Autoscroll::fit(), cx);
 8182            }
 8183
 8184            cx.notify();
 8185        }
 8186    }
 8187
 8188    pub fn set_gutter_hovered(&mut self, hovered: bool, cx: &mut ViewContext<Self>) {
 8189        if hovered != self.gutter_hovered {
 8190            self.gutter_hovered = hovered;
 8191            cx.notify();
 8192        }
 8193    }
 8194
 8195    pub fn insert_blocks(
 8196        &mut self,
 8197        blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
 8198        autoscroll: Option<Autoscroll>,
 8199        cx: &mut ViewContext<Self>,
 8200    ) -> Vec<BlockId> {
 8201        let blocks = self
 8202            .display_map
 8203            .update(cx, |display_map, cx| display_map.insert_blocks(blocks, cx));
 8204        if let Some(autoscroll) = autoscroll {
 8205            self.request_autoscroll(autoscroll, cx);
 8206        }
 8207        blocks
 8208    }
 8209
 8210    pub fn replace_blocks(
 8211        &mut self,
 8212        blocks: HashMap<BlockId, RenderBlock>,
 8213        autoscroll: Option<Autoscroll>,
 8214        cx: &mut ViewContext<Self>,
 8215    ) {
 8216        self.display_map
 8217            .update(cx, |display_map, _| display_map.replace_blocks(blocks));
 8218        if let Some(autoscroll) = autoscroll {
 8219            self.request_autoscroll(autoscroll, cx);
 8220        }
 8221    }
 8222
 8223    pub fn remove_blocks(
 8224        &mut self,
 8225        block_ids: HashSet<BlockId>,
 8226        autoscroll: Option<Autoscroll>,
 8227        cx: &mut ViewContext<Self>,
 8228    ) {
 8229        self.display_map.update(cx, |display_map, cx| {
 8230            display_map.remove_blocks(block_ids, cx)
 8231        });
 8232        if let Some(autoscroll) = autoscroll {
 8233            self.request_autoscroll(autoscroll, cx);
 8234        }
 8235    }
 8236
 8237    pub fn longest_row(&self, cx: &mut AppContext) -> u32 {
 8238        self.display_map
 8239            .update(cx, |map, cx| map.snapshot(cx))
 8240            .longest_row()
 8241    }
 8242
 8243    pub fn max_point(&self, cx: &mut AppContext) -> DisplayPoint {
 8244        self.display_map
 8245            .update(cx, |map, cx| map.snapshot(cx))
 8246            .max_point()
 8247    }
 8248
 8249    pub fn text(&self, cx: &AppContext) -> String {
 8250        self.buffer.read(cx).read(cx).text()
 8251    }
 8252
 8253    pub fn text_option(&self, cx: &AppContext) -> Option<String> {
 8254        let text = self.text(cx);
 8255        let text = text.trim();
 8256
 8257        if text.is_empty() {
 8258            return None;
 8259        }
 8260
 8261        Some(text.to_string())
 8262    }
 8263
 8264    pub fn set_text(&mut self, text: impl Into<Arc<str>>, cx: &mut ViewContext<Self>) {
 8265        self.transact(cx, |this, cx| {
 8266            this.buffer
 8267                .read(cx)
 8268                .as_singleton()
 8269                .expect("you can only call set_text on editors for singleton buffers")
 8270                .update(cx, |buffer, cx| buffer.set_text(text, cx));
 8271        });
 8272    }
 8273
 8274    pub fn display_text(&self, cx: &mut AppContext) -> String {
 8275        self.display_map
 8276            .update(cx, |map, cx| map.snapshot(cx))
 8277            .text()
 8278    }
 8279
 8280    pub fn wrap_guides(&self, cx: &AppContext) -> SmallVec<[(usize, bool); 2]> {
 8281        let mut wrap_guides = smallvec::smallvec![];
 8282
 8283        if self.show_wrap_guides == Some(false) {
 8284            return wrap_guides;
 8285        }
 8286
 8287        let settings = self.buffer.read(cx).settings_at(0, cx);
 8288        if settings.show_wrap_guides {
 8289            if let SoftWrap::Column(soft_wrap) = self.soft_wrap_mode(cx) {
 8290                wrap_guides.push((soft_wrap as usize, true));
 8291            }
 8292            wrap_guides.extend(settings.wrap_guides.iter().map(|guide| (*guide, false)))
 8293        }
 8294
 8295        wrap_guides
 8296    }
 8297
 8298    pub fn soft_wrap_mode(&self, cx: &AppContext) -> SoftWrap {
 8299        let settings = self.buffer.read(cx).settings_at(0, cx);
 8300        let mode = self
 8301            .soft_wrap_mode_override
 8302            .unwrap_or_else(|| settings.soft_wrap);
 8303        match mode {
 8304            language_settings::SoftWrap::None => SoftWrap::None,
 8305            language_settings::SoftWrap::EditorWidth => SoftWrap::EditorWidth,
 8306            language_settings::SoftWrap::PreferredLineLength => {
 8307                SoftWrap::Column(settings.preferred_line_length)
 8308            }
 8309        }
 8310    }
 8311
 8312    pub fn set_soft_wrap_mode(
 8313        &mut self,
 8314        mode: language_settings::SoftWrap,
 8315        cx: &mut ViewContext<Self>,
 8316    ) {
 8317        self.soft_wrap_mode_override = Some(mode);
 8318        cx.notify();
 8319    }
 8320
 8321    pub fn set_style(&mut self, style: EditorStyle, cx: &mut ViewContext<Self>) {
 8322        let rem_size = cx.rem_size();
 8323        self.display_map.update(cx, |map, cx| {
 8324            map.set_font(
 8325                style.text.font(),
 8326                style.text.font_size.to_pixels(rem_size),
 8327                cx,
 8328            )
 8329        });
 8330        self.style = Some(style);
 8331    }
 8332
 8333    #[cfg(any(test, feature = "test-support"))]
 8334    pub fn style(&self) -> Option<&EditorStyle> {
 8335        self.style.as_ref()
 8336    }
 8337
 8338    // Called by the element. This method is not designed to be called outside of the editor
 8339    // element's layout code because it does not notify when rewrapping is computed synchronously.
 8340    pub(crate) fn set_wrap_width(&self, width: Option<Pixels>, cx: &mut AppContext) -> bool {
 8341        self.display_map
 8342            .update(cx, |map, cx| map.set_wrap_width(width, cx))
 8343    }
 8344
 8345    pub fn toggle_soft_wrap(&mut self, _: &ToggleSoftWrap, cx: &mut ViewContext<Self>) {
 8346        if self.soft_wrap_mode_override.is_some() {
 8347            self.soft_wrap_mode_override.take();
 8348        } else {
 8349            let soft_wrap = match self.soft_wrap_mode(cx) {
 8350                SoftWrap::None => language_settings::SoftWrap::EditorWidth,
 8351                SoftWrap::EditorWidth | SoftWrap::Column(_) => language_settings::SoftWrap::None,
 8352            };
 8353            self.soft_wrap_mode_override = Some(soft_wrap);
 8354        }
 8355        cx.notify();
 8356    }
 8357
 8358    pub fn set_show_gutter(&mut self, show_gutter: bool, cx: &mut ViewContext<Self>) {
 8359        self.show_gutter = show_gutter;
 8360        cx.notify();
 8361    }
 8362
 8363    pub fn set_show_wrap_guides(&mut self, show_gutter: bool, cx: &mut ViewContext<Self>) {
 8364        self.show_wrap_guides = Some(show_gutter);
 8365        cx.notify();
 8366    }
 8367
 8368    pub fn reveal_in_finder(&mut self, _: &RevealInFinder, cx: &mut ViewContext<Self>) {
 8369        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
 8370            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
 8371                cx.reveal_path(&file.abs_path(cx));
 8372            }
 8373        }
 8374    }
 8375
 8376    pub fn copy_path(&mut self, _: &CopyPath, cx: &mut ViewContext<Self>) {
 8377        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
 8378            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
 8379                if let Some(path) = file.abs_path(cx).to_str() {
 8380                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
 8381                }
 8382            }
 8383        }
 8384    }
 8385
 8386    pub fn copy_relative_path(&mut self, _: &CopyRelativePath, cx: &mut ViewContext<Self>) {
 8387        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
 8388            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
 8389                if let Some(path) = file.path().to_str() {
 8390                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
 8391                }
 8392            }
 8393        }
 8394    }
 8395
 8396    fn get_permalink_to_line(&mut self, cx: &mut ViewContext<Self>) -> Result<url::Url> {
 8397        use git::permalink::{build_permalink, BuildPermalinkParams};
 8398
 8399        let permalink = maybe!({
 8400            let project = self.project.clone().ok_or_else(|| anyhow!("no project"))?;
 8401            let project = project.read(cx);
 8402
 8403            let worktree = project
 8404                .visible_worktrees(cx)
 8405                .next()
 8406                .ok_or_else(|| anyhow!("no worktree"))?;
 8407
 8408            let mut cwd = worktree.read(cx).abs_path().to_path_buf();
 8409            cwd.push(".git");
 8410
 8411            const REMOTE_NAME: &'static str = "origin";
 8412            let repo = project
 8413                .fs()
 8414                .open_repo(&cwd)
 8415                .ok_or_else(|| anyhow!("no Git repo"))?;
 8416            let origin_url = repo
 8417                .lock()
 8418                .remote_url(REMOTE_NAME)
 8419                .ok_or_else(|| anyhow!("remote \"{REMOTE_NAME}\" not found"))?;
 8420            let sha = repo
 8421                .lock()
 8422                .head_sha()
 8423                .ok_or_else(|| anyhow!("failed to read HEAD SHA"))?;
 8424
 8425            let path = maybe!({
 8426                let buffer = self.buffer().read(cx).as_singleton()?;
 8427                let file = buffer.read(cx).file().and_then(|f| f.as_local())?;
 8428                file.path().to_str().map(|path| path.to_string())
 8429            })
 8430            .ok_or_else(|| anyhow!("failed to determine file path"))?;
 8431
 8432            let selections = self.selections.all::<Point>(cx);
 8433            let selection = selections.iter().peekable().next();
 8434
 8435            build_permalink(BuildPermalinkParams {
 8436                remote_url: &origin_url,
 8437                sha: &sha,
 8438                path: &path,
 8439                selection: selection.map(|selection| selection.range()),
 8440            })
 8441        });
 8442        permalink
 8443    }
 8444
 8445    pub fn copy_permalink_to_line(&mut self, _: &CopyPermalinkToLine, cx: &mut ViewContext<Self>) {
 8446        let permalink = self.get_permalink_to_line(cx);
 8447
 8448        match permalink {
 8449            Ok(permalink) => {
 8450                cx.write_to_clipboard(ClipboardItem::new(permalink.to_string()));
 8451            }
 8452            Err(err) => {
 8453                let message = format!("Failed to copy permalink: {err}");
 8454
 8455                Err::<(), anyhow::Error>(err).log_err();
 8456
 8457                if let Some(workspace) = self.workspace() {
 8458                    workspace.update(cx, |workspace, cx| {
 8459                        workspace.show_toast(Toast::new(0x156a5f9ee, message), cx)
 8460                    })
 8461                }
 8462            }
 8463        }
 8464    }
 8465
 8466    pub fn open_permalink_to_line(&mut self, _: &OpenPermalinkToLine, cx: &mut ViewContext<Self>) {
 8467        let permalink = self.get_permalink_to_line(cx);
 8468
 8469        match permalink {
 8470            Ok(permalink) => {
 8471                cx.open_url(&permalink.to_string());
 8472            }
 8473            Err(err) => {
 8474                let message = format!("Failed to open permalink: {err}");
 8475
 8476                Err::<(), anyhow::Error>(err).log_err();
 8477
 8478                if let Some(workspace) = self.workspace() {
 8479                    workspace.update(cx, |workspace, cx| {
 8480                        workspace.show_toast(Toast::new(0x45a8978, message), cx)
 8481                    })
 8482                }
 8483            }
 8484        }
 8485    }
 8486
 8487    pub fn highlight_rows(&mut self, rows: Option<Range<u32>>) {
 8488        self.highlighted_rows = rows;
 8489    }
 8490
 8491    pub fn highlighted_rows(&self) -> Option<Range<u32>> {
 8492        self.highlighted_rows.clone()
 8493    }
 8494
 8495    pub fn highlight_background<T: 'static>(
 8496        &mut self,
 8497        ranges: Vec<Range<Anchor>>,
 8498        color_fetcher: fn(&ThemeColors) -> Hsla,
 8499        cx: &mut ViewContext<Self>,
 8500    ) {
 8501        self.background_highlights
 8502            .insert(TypeId::of::<T>(), (color_fetcher, ranges));
 8503        cx.notify();
 8504    }
 8505
 8506    pub(crate) fn highlight_inlay_background<T: 'static>(
 8507        &mut self,
 8508        ranges: Vec<InlayHighlight>,
 8509        color_fetcher: fn(&ThemeColors) -> Hsla,
 8510        cx: &mut ViewContext<Self>,
 8511    ) {
 8512        // TODO: no actual highlights happen for inlays currently, find a way to do that
 8513        self.inlay_background_highlights
 8514            .insert(Some(TypeId::of::<T>()), (color_fetcher, ranges));
 8515        cx.notify();
 8516    }
 8517
 8518    pub fn clear_background_highlights<T: 'static>(
 8519        &mut self,
 8520        cx: &mut ViewContext<Self>,
 8521    ) -> Option<BackgroundHighlight> {
 8522        let text_highlights = self.background_highlights.remove(&TypeId::of::<T>());
 8523        let inlay_highlights = self
 8524            .inlay_background_highlights
 8525            .remove(&Some(TypeId::of::<T>()));
 8526        if text_highlights.is_some() || inlay_highlights.is_some() {
 8527            cx.notify();
 8528        }
 8529        text_highlights
 8530    }
 8531
 8532    #[cfg(feature = "test-support")]
 8533    pub fn all_text_background_highlights(
 8534        &mut self,
 8535        cx: &mut ViewContext<Self>,
 8536    ) -> Vec<(Range<DisplayPoint>, Hsla)> {
 8537        let snapshot = self.snapshot(cx);
 8538        let buffer = &snapshot.buffer_snapshot;
 8539        let start = buffer.anchor_before(0);
 8540        let end = buffer.anchor_after(buffer.len());
 8541        let theme = cx.theme().colors();
 8542        self.background_highlights_in_range(start..end, &snapshot, theme)
 8543    }
 8544
 8545    fn document_highlights_for_position<'a>(
 8546        &'a self,
 8547        position: Anchor,
 8548        buffer: &'a MultiBufferSnapshot,
 8549    ) -> impl 'a + Iterator<Item = &Range<Anchor>> {
 8550        let read_highlights = self
 8551            .background_highlights
 8552            .get(&TypeId::of::<DocumentHighlightRead>())
 8553            .map(|h| &h.1);
 8554        let write_highlights = self
 8555            .background_highlights
 8556            .get(&TypeId::of::<DocumentHighlightWrite>())
 8557            .map(|h| &h.1);
 8558        let left_position = position.bias_left(buffer);
 8559        let right_position = position.bias_right(buffer);
 8560        read_highlights
 8561            .into_iter()
 8562            .chain(write_highlights)
 8563            .flat_map(move |ranges| {
 8564                let start_ix = match ranges.binary_search_by(|probe| {
 8565                    let cmp = probe.end.cmp(&left_position, buffer);
 8566                    if cmp.is_ge() {
 8567                        Ordering::Greater
 8568                    } else {
 8569                        Ordering::Less
 8570                    }
 8571                }) {
 8572                    Ok(i) | Err(i) => i,
 8573                };
 8574
 8575                let right_position = right_position.clone();
 8576                ranges[start_ix..]
 8577                    .iter()
 8578                    .take_while(move |range| range.start.cmp(&right_position, buffer).is_le())
 8579            })
 8580    }
 8581
 8582    pub fn has_background_highlights<T: 'static>(&self) -> bool {
 8583        self.background_highlights
 8584            .get(&TypeId::of::<T>())
 8585            .map_or(false, |(_, highlights)| !highlights.is_empty())
 8586    }
 8587
 8588    pub fn background_highlights_in_range(
 8589        &self,
 8590        search_range: Range<Anchor>,
 8591        display_snapshot: &DisplaySnapshot,
 8592        theme: &ThemeColors,
 8593    ) -> Vec<(Range<DisplayPoint>, Hsla)> {
 8594        let mut results = Vec::new();
 8595        for (color_fetcher, ranges) in self.background_highlights.values() {
 8596            let color = color_fetcher(theme);
 8597            let start_ix = match ranges.binary_search_by(|probe| {
 8598                let cmp = probe
 8599                    .end
 8600                    .cmp(&search_range.start, &display_snapshot.buffer_snapshot);
 8601                if cmp.is_gt() {
 8602                    Ordering::Greater
 8603                } else {
 8604                    Ordering::Less
 8605                }
 8606            }) {
 8607                Ok(i) | Err(i) => i,
 8608            };
 8609            for range in &ranges[start_ix..] {
 8610                if range
 8611                    .start
 8612                    .cmp(&search_range.end, &display_snapshot.buffer_snapshot)
 8613                    .is_ge()
 8614                {
 8615                    break;
 8616                }
 8617
 8618                let start = range.start.to_display_point(&display_snapshot);
 8619                let end = range.end.to_display_point(&display_snapshot);
 8620                results.push((start..end, color))
 8621            }
 8622        }
 8623        results
 8624    }
 8625
 8626    pub fn background_highlight_row_ranges<T: 'static>(
 8627        &self,
 8628        search_range: Range<Anchor>,
 8629        display_snapshot: &DisplaySnapshot,
 8630        count: usize,
 8631    ) -> Vec<RangeInclusive<DisplayPoint>> {
 8632        let mut results = Vec::new();
 8633        let Some((_, ranges)) = self.background_highlights.get(&TypeId::of::<T>()) else {
 8634            return vec![];
 8635        };
 8636
 8637        let start_ix = match ranges.binary_search_by(|probe| {
 8638            let cmp = probe
 8639                .end
 8640                .cmp(&search_range.start, &display_snapshot.buffer_snapshot);
 8641            if cmp.is_gt() {
 8642                Ordering::Greater
 8643            } else {
 8644                Ordering::Less
 8645            }
 8646        }) {
 8647            Ok(i) | Err(i) => i,
 8648        };
 8649        let mut push_region = |start: Option<Point>, end: Option<Point>| {
 8650            if let (Some(start_display), Some(end_display)) = (start, end) {
 8651                results.push(
 8652                    start_display.to_display_point(display_snapshot)
 8653                        ..=end_display.to_display_point(display_snapshot),
 8654                );
 8655            }
 8656        };
 8657        let mut start_row: Option<Point> = None;
 8658        let mut end_row: Option<Point> = None;
 8659        if ranges.len() > count {
 8660            return Vec::new();
 8661        }
 8662        for range in &ranges[start_ix..] {
 8663            if range
 8664                .start
 8665                .cmp(&search_range.end, &display_snapshot.buffer_snapshot)
 8666                .is_ge()
 8667            {
 8668                break;
 8669            }
 8670            let end = range.end.to_point(&display_snapshot.buffer_snapshot);
 8671            if let Some(current_row) = &end_row {
 8672                if end.row == current_row.row {
 8673                    continue;
 8674                }
 8675            }
 8676            let start = range.start.to_point(&display_snapshot.buffer_snapshot);
 8677            if start_row.is_none() {
 8678                assert_eq!(end_row, None);
 8679                start_row = Some(start);
 8680                end_row = Some(end);
 8681                continue;
 8682            }
 8683            if let Some(current_end) = end_row.as_mut() {
 8684                if start.row > current_end.row + 1 {
 8685                    push_region(start_row, end_row);
 8686                    start_row = Some(start);
 8687                    end_row = Some(end);
 8688                } else {
 8689                    // Merge two hunks.
 8690                    *current_end = end;
 8691                }
 8692            } else {
 8693                unreachable!();
 8694            }
 8695        }
 8696        // We might still have a hunk that was not rendered (if there was a search hit on the last line)
 8697        push_region(start_row, end_row);
 8698        results
 8699    }
 8700
 8701    /// Get the text ranges corresponding to the redaction query
 8702    pub fn redacted_ranges(
 8703        &self,
 8704        search_range: Range<Anchor>,
 8705        display_snapshot: &DisplaySnapshot,
 8706        cx: &mut ViewContext<Self>,
 8707    ) -> Vec<Range<DisplayPoint>> {
 8708        display_snapshot
 8709            .buffer_snapshot
 8710            .redacted_ranges(search_range, |file| {
 8711                if let Some(file) = file {
 8712                    file.is_private()
 8713                        && EditorSettings::get(Some((file.worktree_id(), file.path())), cx)
 8714                            .redact_private_values
 8715                } else {
 8716                    false
 8717                }
 8718            })
 8719            .map(|range| {
 8720                range.start.to_display_point(display_snapshot)
 8721                    ..range.end.to_display_point(display_snapshot)
 8722            })
 8723            .collect()
 8724    }
 8725
 8726    pub fn highlight_text<T: 'static>(
 8727        &mut self,
 8728        ranges: Vec<Range<Anchor>>,
 8729        style: HighlightStyle,
 8730        cx: &mut ViewContext<Self>,
 8731    ) {
 8732        self.display_map.update(cx, |map, _| {
 8733            map.highlight_text(TypeId::of::<T>(), ranges, style)
 8734        });
 8735        cx.notify();
 8736    }
 8737
 8738    pub(crate) fn highlight_inlays<T: 'static>(
 8739        &mut self,
 8740        highlights: Vec<InlayHighlight>,
 8741        style: HighlightStyle,
 8742        cx: &mut ViewContext<Self>,
 8743    ) {
 8744        self.display_map.update(cx, |map, _| {
 8745            map.highlight_inlays(TypeId::of::<T>(), highlights, style)
 8746        });
 8747        cx.notify();
 8748    }
 8749
 8750    pub fn text_highlights<'a, T: 'static>(
 8751        &'a self,
 8752        cx: &'a AppContext,
 8753    ) -> Option<(HighlightStyle, &'a [Range<Anchor>])> {
 8754        self.display_map.read(cx).text_highlights(TypeId::of::<T>())
 8755    }
 8756
 8757    pub fn clear_highlights<T: 'static>(&mut self, cx: &mut ViewContext<Self>) {
 8758        let cleared = self
 8759            .display_map
 8760            .update(cx, |map, _| map.clear_highlights(TypeId::of::<T>()));
 8761        if cleared {
 8762            cx.notify();
 8763        }
 8764    }
 8765
 8766    pub fn show_local_cursors(&self, cx: &WindowContext) -> bool {
 8767        (self.read_only(cx) || self.blink_manager.read(cx).visible())
 8768            && self.focus_handle.is_focused(cx)
 8769    }
 8770
 8771    fn on_buffer_changed(&mut self, _: Model<MultiBuffer>, cx: &mut ViewContext<Self>) {
 8772        cx.notify();
 8773    }
 8774
 8775    fn on_buffer_event(
 8776        &mut self,
 8777        multibuffer: Model<MultiBuffer>,
 8778        event: &multi_buffer::Event,
 8779        cx: &mut ViewContext<Self>,
 8780    ) {
 8781        match event {
 8782            multi_buffer::Event::Edited {
 8783                singleton_buffer_edited,
 8784            } => {
 8785                self.refresh_active_diagnostics(cx);
 8786                self.refresh_code_actions(cx);
 8787                if self.has_active_copilot_suggestion(cx) {
 8788                    self.update_visible_copilot_suggestion(cx);
 8789                }
 8790                cx.emit(EditorEvent::BufferEdited);
 8791                cx.emit(SearchEvent::MatchesInvalidated);
 8792
 8793                if *singleton_buffer_edited {
 8794                    if let Some(project) = &self.project {
 8795                        let project = project.read(cx);
 8796                        let languages_affected = multibuffer
 8797                            .read(cx)
 8798                            .all_buffers()
 8799                            .into_iter()
 8800                            .filter_map(|buffer| {
 8801                                let buffer = buffer.read(cx);
 8802                                let language = buffer.language()?;
 8803                                if project.is_local()
 8804                                    && project.language_servers_for_buffer(buffer, cx).count() == 0
 8805                                {
 8806                                    None
 8807                                } else {
 8808                                    Some(language)
 8809                                }
 8810                            })
 8811                            .cloned()
 8812                            .collect::<HashSet<_>>();
 8813                        if !languages_affected.is_empty() {
 8814                            self.refresh_inlay_hints(
 8815                                InlayHintRefreshReason::BufferEdited(languages_affected),
 8816                                cx,
 8817                            );
 8818                        }
 8819                    }
 8820                }
 8821
 8822                let Some(project) = &self.project else { return };
 8823                let telemetry = project.read(cx).client().telemetry().clone();
 8824                telemetry.log_edit_event("editor");
 8825            }
 8826            multi_buffer::Event::ExcerptsAdded {
 8827                buffer,
 8828                predecessor,
 8829                excerpts,
 8830            } => {
 8831                cx.emit(EditorEvent::ExcerptsAdded {
 8832                    buffer: buffer.clone(),
 8833                    predecessor: *predecessor,
 8834                    excerpts: excerpts.clone(),
 8835                });
 8836                self.refresh_inlay_hints(InlayHintRefreshReason::NewLinesShown, cx);
 8837            }
 8838            multi_buffer::Event::ExcerptsRemoved { ids } => {
 8839                self.refresh_inlay_hints(InlayHintRefreshReason::ExcerptsRemoved(ids.clone()), cx);
 8840                cx.emit(EditorEvent::ExcerptsRemoved { ids: ids.clone() })
 8841            }
 8842            multi_buffer::Event::Reparsed => cx.emit(EditorEvent::Reparsed),
 8843            multi_buffer::Event::LanguageChanged => {
 8844                cx.emit(EditorEvent::Reparsed);
 8845                cx.notify();
 8846            }
 8847            multi_buffer::Event::DirtyChanged => cx.emit(EditorEvent::DirtyChanged),
 8848            multi_buffer::Event::Saved => cx.emit(EditorEvent::Saved),
 8849            multi_buffer::Event::FileHandleChanged | multi_buffer::Event::Reloaded => {
 8850                cx.emit(EditorEvent::TitleChanged)
 8851            }
 8852            multi_buffer::Event::DiffBaseChanged => cx.emit(EditorEvent::DiffBaseChanged),
 8853            multi_buffer::Event::Closed => cx.emit(EditorEvent::Closed),
 8854            multi_buffer::Event::DiagnosticsUpdated => {
 8855                self.refresh_active_diagnostics(cx);
 8856            }
 8857            _ => {}
 8858        };
 8859    }
 8860
 8861    fn on_display_map_changed(&mut self, _: Model<DisplayMap>, cx: &mut ViewContext<Self>) {
 8862        cx.notify();
 8863    }
 8864
 8865    fn settings_changed(&mut self, cx: &mut ViewContext<Self>) {
 8866        self.refresh_copilot_suggestions(true, cx);
 8867        self.refresh_inlay_hints(
 8868            InlayHintRefreshReason::SettingsChange(inlay_hint_settings(
 8869                self.selections.newest_anchor().head(),
 8870                &self.buffer.read(cx).snapshot(cx),
 8871                cx,
 8872            )),
 8873            cx,
 8874        );
 8875        let editor_settings = EditorSettings::get_global(cx);
 8876        self.scroll_manager.vertical_scroll_margin = editor_settings.vertical_scroll_margin;
 8877        self.show_breadcrumbs = editor_settings.toolbar.breadcrumbs;
 8878        cx.notify();
 8879    }
 8880
 8881    pub fn set_searchable(&mut self, searchable: bool) {
 8882        self.searchable = searchable;
 8883    }
 8884
 8885    pub fn searchable(&self) -> bool {
 8886        self.searchable
 8887    }
 8888
 8889    fn open_excerpts(&mut self, _: &OpenExcerpts, cx: &mut ViewContext<Self>) {
 8890        let buffer = self.buffer.read(cx);
 8891        if buffer.is_singleton() {
 8892            cx.propagate();
 8893            return;
 8894        }
 8895
 8896        let Some(workspace) = self.workspace() else {
 8897            cx.propagate();
 8898            return;
 8899        };
 8900
 8901        let mut new_selections_by_buffer = HashMap::default();
 8902        for selection in self.selections.all::<usize>(cx) {
 8903            for (buffer, mut range, _) in
 8904                buffer.range_to_buffer_ranges(selection.start..selection.end, cx)
 8905            {
 8906                if selection.reversed {
 8907                    mem::swap(&mut range.start, &mut range.end);
 8908                }
 8909                new_selections_by_buffer
 8910                    .entry(buffer)
 8911                    .or_insert(Vec::new())
 8912                    .push(range)
 8913            }
 8914        }
 8915
 8916        self.push_to_nav_history(self.selections.newest_anchor().head(), None, cx);
 8917
 8918        // We defer the pane interaction because we ourselves are a workspace item
 8919        // and activating a new item causes the pane to call a method on us reentrantly,
 8920        // which panics if we're on the stack.
 8921        cx.window_context().defer(move |cx| {
 8922            workspace.update(cx, |workspace, cx| {
 8923                let pane = workspace.active_pane().clone();
 8924                pane.update(cx, |pane, _| pane.disable_history());
 8925
 8926                for (buffer, ranges) in new_selections_by_buffer.into_iter() {
 8927                    let editor = workspace.open_project_item::<Self>(buffer, cx);
 8928                    editor.update(cx, |editor, cx| {
 8929                        editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
 8930                            s.select_ranges(ranges);
 8931                        });
 8932                    });
 8933                }
 8934
 8935                pane.update(cx, |pane, _| pane.enable_history());
 8936            })
 8937        });
 8938    }
 8939
 8940    fn jump(
 8941        &mut self,
 8942        path: ProjectPath,
 8943        position: Point,
 8944        anchor: language::Anchor,
 8945        cx: &mut ViewContext<Self>,
 8946    ) {
 8947        let workspace = self.workspace();
 8948        cx.spawn(|_, mut cx| async move {
 8949            let workspace = workspace.ok_or_else(|| anyhow!("cannot jump without workspace"))?;
 8950            let editor = workspace.update(&mut cx, |workspace, cx| {
 8951                workspace.open_path(path, None, true, cx)
 8952            })?;
 8953            let editor = editor
 8954                .await?
 8955                .downcast::<Editor>()
 8956                .ok_or_else(|| anyhow!("opened item was not an editor"))?
 8957                .downgrade();
 8958            editor.update(&mut cx, |editor, cx| {
 8959                let buffer = editor
 8960                    .buffer()
 8961                    .read(cx)
 8962                    .as_singleton()
 8963                    .ok_or_else(|| anyhow!("cannot jump in a multi-buffer"))?;
 8964                let buffer = buffer.read(cx);
 8965                let cursor = if buffer.can_resolve(&anchor) {
 8966                    language::ToPoint::to_point(&anchor, buffer)
 8967                } else {
 8968                    buffer.clip_point(position, Bias::Left)
 8969                };
 8970
 8971                let nav_history = editor.nav_history.take();
 8972                editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
 8973                    s.select_ranges([cursor..cursor]);
 8974                });
 8975                editor.nav_history = nav_history;
 8976
 8977                anyhow::Ok(())
 8978            })??;
 8979
 8980            anyhow::Ok(())
 8981        })
 8982        .detach_and_log_err(cx);
 8983    }
 8984
 8985    fn marked_text_ranges(&self, cx: &AppContext) -> Option<Vec<Range<OffsetUtf16>>> {
 8986        let snapshot = self.buffer.read(cx).read(cx);
 8987        let (_, ranges) = self.text_highlights::<InputComposition>(cx)?;
 8988        Some(
 8989            ranges
 8990                .iter()
 8991                .map(move |range| {
 8992                    range.start.to_offset_utf16(&snapshot)..range.end.to_offset_utf16(&snapshot)
 8993                })
 8994                .collect(),
 8995        )
 8996    }
 8997
 8998    fn selection_replacement_ranges(
 8999        &self,
 9000        range: Range<OffsetUtf16>,
 9001        cx: &AppContext,
 9002    ) -> Vec<Range<OffsetUtf16>> {
 9003        let selections = self.selections.all::<OffsetUtf16>(cx);
 9004        let newest_selection = selections
 9005            .iter()
 9006            .max_by_key(|selection| selection.id)
 9007            .unwrap();
 9008        let start_delta = range.start.0 as isize - newest_selection.start.0 as isize;
 9009        let end_delta = range.end.0 as isize - newest_selection.end.0 as isize;
 9010        let snapshot = self.buffer.read(cx).read(cx);
 9011        selections
 9012            .into_iter()
 9013            .map(|mut selection| {
 9014                selection.start.0 =
 9015                    (selection.start.0 as isize).saturating_add(start_delta) as usize;
 9016                selection.end.0 = (selection.end.0 as isize).saturating_add(end_delta) as usize;
 9017                snapshot.clip_offset_utf16(selection.start, Bias::Left)
 9018                    ..snapshot.clip_offset_utf16(selection.end, Bias::Right)
 9019            })
 9020            .collect()
 9021    }
 9022
 9023    fn report_copilot_event(
 9024        &self,
 9025        suggestion_id: Option<String>,
 9026        suggestion_accepted: bool,
 9027        cx: &AppContext,
 9028    ) {
 9029        let Some(project) = &self.project else { return };
 9030
 9031        // If None, we are either getting suggestions in a new, unsaved file, or in a file without an extension
 9032        let file_extension = self
 9033            .buffer
 9034            .read(cx)
 9035            .as_singleton()
 9036            .and_then(|b| b.read(cx).file())
 9037            .and_then(|file| Path::new(file.file_name(cx)).extension())
 9038            .and_then(|e| e.to_str())
 9039            .map(|a| a.to_string());
 9040
 9041        let telemetry = project.read(cx).client().telemetry().clone();
 9042
 9043        telemetry.report_copilot_event(suggestion_id, suggestion_accepted, file_extension)
 9044    }
 9045
 9046    #[cfg(any(test, feature = "test-support"))]
 9047    fn report_editor_event(
 9048        &self,
 9049        _operation: &'static str,
 9050        _file_extension: Option<String>,
 9051        _cx: &AppContext,
 9052    ) {
 9053    }
 9054
 9055    #[cfg(not(any(test, feature = "test-support")))]
 9056    fn report_editor_event(
 9057        &self,
 9058        operation: &'static str,
 9059        file_extension: Option<String>,
 9060        cx: &AppContext,
 9061    ) {
 9062        let Some(project) = &self.project else { return };
 9063
 9064        // If None, we are in a file without an extension
 9065        let file = self
 9066            .buffer
 9067            .read(cx)
 9068            .as_singleton()
 9069            .and_then(|b| b.read(cx).file());
 9070        let file_extension = file_extension.or(file
 9071            .as_ref()
 9072            .and_then(|file| Path::new(file.file_name(cx)).extension())
 9073            .and_then(|e| e.to_str())
 9074            .map(|a| a.to_string()));
 9075
 9076        let vim_mode = cx
 9077            .global::<SettingsStore>()
 9078            .raw_user_settings()
 9079            .get("vim_mode")
 9080            == Some(&serde_json::Value::Bool(true));
 9081        let copilot_enabled = all_language_settings(file, cx).copilot_enabled(None, None);
 9082        let copilot_enabled_for_language = self
 9083            .buffer
 9084            .read(cx)
 9085            .settings_at(0, cx)
 9086            .show_copilot_suggestions;
 9087
 9088        let telemetry = project.read(cx).client().telemetry().clone();
 9089        telemetry.report_editor_event(
 9090            file_extension,
 9091            vim_mode,
 9092            operation,
 9093            copilot_enabled,
 9094            copilot_enabled_for_language,
 9095        )
 9096    }
 9097
 9098    /// Copy the highlighted chunks to the clipboard as JSON. The format is an array of lines,
 9099    /// with each line being an array of {text, highlight} objects.
 9100    fn copy_highlight_json(&mut self, _: &CopyHighlightJson, cx: &mut ViewContext<Self>) {
 9101        let Some(buffer) = self.buffer.read(cx).as_singleton() else {
 9102            return;
 9103        };
 9104
 9105        #[derive(Serialize)]
 9106        struct Chunk<'a> {
 9107            text: String,
 9108            highlight: Option<&'a str>,
 9109        }
 9110
 9111        let snapshot = buffer.read(cx).snapshot();
 9112        let range = self
 9113            .selected_text_range(cx)
 9114            .and_then(|selected_range| {
 9115                if selected_range.is_empty() {
 9116                    None
 9117                } else {
 9118                    Some(selected_range)
 9119                }
 9120            })
 9121            .unwrap_or_else(|| 0..snapshot.len());
 9122
 9123        let chunks = snapshot.chunks(range, true);
 9124        let mut lines = Vec::new();
 9125        let mut line: VecDeque<Chunk> = VecDeque::new();
 9126
 9127        let Some(style) = self.style.as_ref() else {
 9128            return;
 9129        };
 9130
 9131        for chunk in chunks {
 9132            let highlight = chunk
 9133                .syntax_highlight_id
 9134                .and_then(|id| id.name(&style.syntax));
 9135            let mut chunk_lines = chunk.text.split("\n").peekable();
 9136            while let Some(text) = chunk_lines.next() {
 9137                let mut merged_with_last_token = false;
 9138                if let Some(last_token) = line.back_mut() {
 9139                    if last_token.highlight == highlight {
 9140                        last_token.text.push_str(text);
 9141                        merged_with_last_token = true;
 9142                    }
 9143                }
 9144
 9145                if !merged_with_last_token {
 9146                    line.push_back(Chunk {
 9147                        text: text.into(),
 9148                        highlight,
 9149                    });
 9150                }
 9151
 9152                if chunk_lines.peek().is_some() {
 9153                    if line.len() > 1 && line.front().unwrap().text.is_empty() {
 9154                        line.pop_front();
 9155                    }
 9156                    if line.len() > 1 && line.back().unwrap().text.is_empty() {
 9157                        line.pop_back();
 9158                    }
 9159
 9160                    lines.push(mem::take(&mut line));
 9161                }
 9162            }
 9163        }
 9164
 9165        let Some(lines) = serde_json::to_string_pretty(&lines).log_err() else {
 9166            return;
 9167        };
 9168        cx.write_to_clipboard(ClipboardItem::new(lines));
 9169    }
 9170
 9171    pub fn inlay_hint_cache(&self) -> &InlayHintCache {
 9172        &self.inlay_hint_cache
 9173    }
 9174
 9175    pub fn replay_insert_event(
 9176        &mut self,
 9177        text: &str,
 9178        relative_utf16_range: Option<Range<isize>>,
 9179        cx: &mut ViewContext<Self>,
 9180    ) {
 9181        if !self.input_enabled {
 9182            cx.emit(EditorEvent::InputIgnored { text: text.into() });
 9183            return;
 9184        }
 9185        if let Some(relative_utf16_range) = relative_utf16_range {
 9186            let selections = self.selections.all::<OffsetUtf16>(cx);
 9187            self.change_selections(None, cx, |s| {
 9188                let new_ranges = selections.into_iter().map(|range| {
 9189                    let start = OffsetUtf16(
 9190                        range
 9191                            .head()
 9192                            .0
 9193                            .saturating_add_signed(relative_utf16_range.start),
 9194                    );
 9195                    let end = OffsetUtf16(
 9196                        range
 9197                            .head()
 9198                            .0
 9199                            .saturating_add_signed(relative_utf16_range.end),
 9200                    );
 9201                    start..end
 9202                });
 9203                s.select_ranges(new_ranges);
 9204            });
 9205        }
 9206
 9207        self.handle_input(text, cx);
 9208    }
 9209
 9210    pub fn supports_inlay_hints(&self, cx: &AppContext) -> bool {
 9211        let Some(project) = self.project.as_ref() else {
 9212            return false;
 9213        };
 9214        let project = project.read(cx);
 9215
 9216        let mut supports = false;
 9217        self.buffer().read(cx).for_each_buffer(|buffer| {
 9218            if !supports {
 9219                supports = project
 9220                    .language_servers_for_buffer(buffer.read(cx), cx)
 9221                    .any(
 9222                        |(_, server)| match server.capabilities().inlay_hint_provider {
 9223                            Some(lsp::OneOf::Left(enabled)) => enabled,
 9224                            Some(lsp::OneOf::Right(_)) => true,
 9225                            None => false,
 9226                        },
 9227                    )
 9228            }
 9229        });
 9230        supports
 9231    }
 9232
 9233    pub fn focus(&self, cx: &mut WindowContext) {
 9234        cx.focus(&self.focus_handle)
 9235    }
 9236
 9237    pub fn is_focused(&self, cx: &WindowContext) -> bool {
 9238        self.focus_handle.is_focused(cx)
 9239    }
 9240
 9241    fn handle_focus(&mut self, cx: &mut ViewContext<Self>) {
 9242        cx.emit(EditorEvent::Focused);
 9243
 9244        if let Some(rename) = self.pending_rename.as_ref() {
 9245            let rename_editor_focus_handle = rename.editor.read(cx).focus_handle.clone();
 9246            cx.focus(&rename_editor_focus_handle);
 9247        } else {
 9248            self.blink_manager.update(cx, BlinkManager::enable);
 9249            self.show_cursor_names(cx);
 9250            self.buffer.update(cx, |buffer, cx| {
 9251                buffer.finalize_last_transaction(cx);
 9252                if self.leader_peer_id.is_none() {
 9253                    buffer.set_active_selections(
 9254                        &self.selections.disjoint_anchors(),
 9255                        self.selections.line_mode,
 9256                        self.cursor_shape,
 9257                        cx,
 9258                    );
 9259                }
 9260            });
 9261        }
 9262    }
 9263
 9264    pub fn handle_blur(&mut self, cx: &mut ViewContext<Self>) {
 9265        self.blink_manager.update(cx, BlinkManager::disable);
 9266        self.buffer
 9267            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
 9268        self.hide_context_menu(cx);
 9269        hide_hover(self, cx);
 9270        cx.emit(EditorEvent::Blurred);
 9271        cx.notify();
 9272    }
 9273
 9274    pub fn register_action<A: Action>(
 9275        &mut self,
 9276        listener: impl Fn(&A, &mut WindowContext) + 'static,
 9277    ) -> &mut Self {
 9278        let listener = Arc::new(listener);
 9279
 9280        self.editor_actions.push(Box::new(move |cx| {
 9281            let _view = cx.view().clone();
 9282            let cx = cx.window_context();
 9283            let listener = listener.clone();
 9284            cx.on_action(TypeId::of::<A>(), move |action, phase, cx| {
 9285                let action = action.downcast_ref().unwrap();
 9286                if phase == DispatchPhase::Bubble {
 9287                    listener(action, cx)
 9288                }
 9289            })
 9290        }));
 9291        self
 9292    }
 9293}
 9294
 9295pub trait CollaborationHub {
 9296    fn collaborators<'a>(&self, cx: &'a AppContext) -> &'a HashMap<PeerId, Collaborator>;
 9297    fn user_participant_indices<'a>(
 9298        &self,
 9299        cx: &'a AppContext,
 9300    ) -> &'a HashMap<u64, ParticipantIndex>;
 9301    fn user_names(&self, cx: &AppContext) -> HashMap<u64, SharedString>;
 9302}
 9303
 9304impl CollaborationHub for Model<Project> {
 9305    fn collaborators<'a>(&self, cx: &'a AppContext) -> &'a HashMap<PeerId, Collaborator> {
 9306        self.read(cx).collaborators()
 9307    }
 9308
 9309    fn user_participant_indices<'a>(
 9310        &self,
 9311        cx: &'a AppContext,
 9312    ) -> &'a HashMap<u64, ParticipantIndex> {
 9313        self.read(cx).user_store().read(cx).participant_indices()
 9314    }
 9315
 9316    fn user_names(&self, cx: &AppContext) -> HashMap<u64, SharedString> {
 9317        let this = self.read(cx);
 9318        let user_ids = this.collaborators().values().map(|c| c.user_id);
 9319        this.user_store().read_with(cx, |user_store, cx| {
 9320            user_store.participant_names(user_ids, cx)
 9321        })
 9322    }
 9323}
 9324
 9325pub trait CompletionProvider {
 9326    fn completions(
 9327        &self,
 9328        buffer: &Model<Buffer>,
 9329        buffer_position: text::Anchor,
 9330        cx: &mut ViewContext<Editor>,
 9331    ) -> Task<Result<Vec<Completion>>>;
 9332
 9333    fn resolve_completions(
 9334        &self,
 9335        completion_indices: Vec<usize>,
 9336        completions: Arc<RwLock<Box<[Completion]>>>,
 9337        cx: &mut ViewContext<Editor>,
 9338    ) -> Task<Result<bool>>;
 9339
 9340    fn apply_additional_edits_for_completion(
 9341        &self,
 9342        buffer: Model<Buffer>,
 9343        completion: Completion,
 9344        push_to_history: bool,
 9345        cx: &mut ViewContext<Editor>,
 9346    ) -> Task<Result<Option<language::Transaction>>>;
 9347}
 9348
 9349impl CompletionProvider for Model<Project> {
 9350    fn completions(
 9351        &self,
 9352        buffer: &Model<Buffer>,
 9353        buffer_position: text::Anchor,
 9354        cx: &mut ViewContext<Editor>,
 9355    ) -> Task<Result<Vec<Completion>>> {
 9356        self.update(cx, |project, cx| {
 9357            project.completions(&buffer, buffer_position, cx)
 9358        })
 9359    }
 9360
 9361    fn resolve_completions(
 9362        &self,
 9363        completion_indices: Vec<usize>,
 9364        completions: Arc<RwLock<Box<[Completion]>>>,
 9365        cx: &mut ViewContext<Editor>,
 9366    ) -> Task<Result<bool>> {
 9367        self.update(cx, |project, cx| {
 9368            project.resolve_completions(completion_indices, completions, cx)
 9369        })
 9370    }
 9371
 9372    fn apply_additional_edits_for_completion(
 9373        &self,
 9374        buffer: Model<Buffer>,
 9375        completion: Completion,
 9376        push_to_history: bool,
 9377        cx: &mut ViewContext<Editor>,
 9378    ) -> Task<Result<Option<language::Transaction>>> {
 9379        self.update(cx, |project, cx| {
 9380            project.apply_additional_edits_for_completion(buffer, completion, push_to_history, cx)
 9381        })
 9382    }
 9383}
 9384
 9385fn inlay_hint_settings(
 9386    location: Anchor,
 9387    snapshot: &MultiBufferSnapshot,
 9388    cx: &mut ViewContext<'_, Editor>,
 9389) -> InlayHintSettings {
 9390    let file = snapshot.file_at(location);
 9391    let language = snapshot.language_at(location);
 9392    let settings = all_language_settings(file, cx);
 9393    settings
 9394        .language(language.map(|l| l.name()).as_deref())
 9395        .inlay_hints
 9396}
 9397
 9398fn consume_contiguous_rows(
 9399    contiguous_row_selections: &mut Vec<Selection<Point>>,
 9400    selection: &Selection<Point>,
 9401    display_map: &DisplaySnapshot,
 9402    selections: &mut std::iter::Peekable<std::slice::Iter<Selection<Point>>>,
 9403) -> (u32, u32) {
 9404    contiguous_row_selections.push(selection.clone());
 9405    let start_row = selection.start.row;
 9406    let mut end_row = ending_row(selection, display_map);
 9407
 9408    while let Some(next_selection) = selections.peek() {
 9409        if next_selection.start.row <= end_row {
 9410            end_row = ending_row(next_selection, display_map);
 9411            contiguous_row_selections.push(selections.next().unwrap().clone());
 9412        } else {
 9413            break;
 9414        }
 9415    }
 9416    (start_row, end_row)
 9417}
 9418
 9419fn ending_row(next_selection: &Selection<Point>, display_map: &DisplaySnapshot) -> u32 {
 9420    if next_selection.end.column > 0 || next_selection.is_empty() {
 9421        display_map.next_line_boundary(next_selection.end).0.row + 1
 9422    } else {
 9423        next_selection.end.row
 9424    }
 9425}
 9426
 9427impl EditorSnapshot {
 9428    pub fn remote_selections_in_range<'a>(
 9429        &'a self,
 9430        range: &'a Range<Anchor>,
 9431        collaboration_hub: &dyn CollaborationHub,
 9432        cx: &'a AppContext,
 9433    ) -> impl 'a + Iterator<Item = RemoteSelection> {
 9434        let participant_names = collaboration_hub.user_names(cx);
 9435        let participant_indices = collaboration_hub.user_participant_indices(cx);
 9436        let collaborators_by_peer_id = collaboration_hub.collaborators(cx);
 9437        let collaborators_by_replica_id = collaborators_by_peer_id
 9438            .iter()
 9439            .map(|(_, collaborator)| (collaborator.replica_id, collaborator))
 9440            .collect::<HashMap<_, _>>();
 9441        self.buffer_snapshot
 9442            .remote_selections_in_range(range)
 9443            .filter_map(move |(replica_id, line_mode, cursor_shape, selection)| {
 9444                let collaborator = collaborators_by_replica_id.get(&replica_id)?;
 9445                let participant_index = participant_indices.get(&collaborator.user_id).copied();
 9446                let user_name = participant_names.get(&collaborator.user_id).cloned();
 9447                Some(RemoteSelection {
 9448                    replica_id,
 9449                    selection,
 9450                    cursor_shape,
 9451                    line_mode,
 9452                    participant_index,
 9453                    peer_id: collaborator.peer_id,
 9454                    user_name,
 9455                })
 9456            })
 9457    }
 9458
 9459    pub fn language_at<T: ToOffset>(&self, position: T) -> Option<&Arc<Language>> {
 9460        self.display_snapshot.buffer_snapshot.language_at(position)
 9461    }
 9462
 9463    pub fn is_focused(&self) -> bool {
 9464        self.is_focused
 9465    }
 9466
 9467    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
 9468        self.placeholder_text.as_ref()
 9469    }
 9470
 9471    pub fn scroll_position(&self) -> gpui::Point<f32> {
 9472        self.scroll_anchor.scroll_position(&self.display_snapshot)
 9473    }
 9474
 9475    pub fn gutter_dimensions(
 9476        &self,
 9477        font_id: FontId,
 9478        font_size: Pixels,
 9479        em_width: Pixels,
 9480        max_line_number_width: Pixels,
 9481        cx: &AppContext,
 9482    ) -> GutterDimensions {
 9483        if self.show_gutter {
 9484            let descent = cx.text_system().descent(font_id, font_size);
 9485            let gutter_padding_factor = 4.0;
 9486            let gutter_padding = (em_width * gutter_padding_factor).round();
 9487            // Avoid flicker-like gutter resizes when the line number gains another digit and only resize the gutter on files with N*10^5 lines.
 9488            let min_width_for_number_on_gutter = em_width * 4.0;
 9489            let gutter_width =
 9490                max_line_number_width.max(min_width_for_number_on_gutter) + gutter_padding * 2.0;
 9491            let gutter_margin = -descent;
 9492
 9493            GutterDimensions {
 9494                padding: gutter_padding,
 9495                width: gutter_width,
 9496                margin: gutter_margin,
 9497            }
 9498        } else {
 9499            GutterDimensions::default()
 9500        }
 9501    }
 9502}
 9503
 9504impl Deref for EditorSnapshot {
 9505    type Target = DisplaySnapshot;
 9506
 9507    fn deref(&self) -> &Self::Target {
 9508        &self.display_snapshot
 9509    }
 9510}
 9511
 9512#[derive(Clone, Debug, PartialEq, Eq)]
 9513pub enum EditorEvent {
 9514    InputIgnored {
 9515        text: Arc<str>,
 9516    },
 9517    InputHandled {
 9518        utf16_range_to_replace: Option<Range<isize>>,
 9519        text: Arc<str>,
 9520    },
 9521    ExcerptsAdded {
 9522        buffer: Model<Buffer>,
 9523        predecessor: ExcerptId,
 9524        excerpts: Vec<(ExcerptId, ExcerptRange<language::Anchor>)>,
 9525    },
 9526    ExcerptsRemoved {
 9527        ids: Vec<ExcerptId>,
 9528    },
 9529    BufferEdited,
 9530    Edited,
 9531    Reparsed,
 9532    Focused,
 9533    Blurred,
 9534    DirtyChanged,
 9535    Saved,
 9536    TitleChanged,
 9537    DiffBaseChanged,
 9538    SelectionsChanged {
 9539        local: bool,
 9540    },
 9541    ScrollPositionChanged {
 9542        local: bool,
 9543        autoscroll: bool,
 9544    },
 9545    Closed,
 9546}
 9547
 9548impl EventEmitter<EditorEvent> for Editor {}
 9549
 9550impl FocusableView for Editor {
 9551    fn focus_handle(&self, _cx: &AppContext) -> FocusHandle {
 9552        self.focus_handle.clone()
 9553    }
 9554}
 9555
 9556impl Render for Editor {
 9557    fn render<'a>(&mut self, cx: &mut ViewContext<'a, Self>) -> impl IntoElement {
 9558        let settings = ThemeSettings::get_global(cx);
 9559        let text_style = match self.mode {
 9560            EditorMode::SingleLine | EditorMode::AutoHeight { .. } => TextStyle {
 9561                color: cx.theme().colors().editor_foreground,
 9562                font_family: settings.ui_font.family.clone(),
 9563                font_features: settings.ui_font.features,
 9564                font_size: rems(0.875).into(),
 9565                font_weight: FontWeight::NORMAL,
 9566                font_style: FontStyle::Normal,
 9567                line_height: relative(settings.buffer_line_height.value()),
 9568                background_color: None,
 9569                underline: None,
 9570                strikethrough: None,
 9571                white_space: WhiteSpace::Normal,
 9572            },
 9573
 9574            EditorMode::Full => TextStyle {
 9575                color: cx.theme().colors().editor_foreground,
 9576                font_family: settings.buffer_font.family.clone(),
 9577                font_features: settings.buffer_font.features,
 9578                font_size: settings.buffer_font_size(cx).into(),
 9579                font_weight: FontWeight::NORMAL,
 9580                font_style: FontStyle::Normal,
 9581                line_height: relative(settings.buffer_line_height.value()),
 9582                background_color: None,
 9583                underline: None,
 9584                strikethrough: None,
 9585                white_space: WhiteSpace::Normal,
 9586            },
 9587        };
 9588
 9589        let background = match self.mode {
 9590            EditorMode::SingleLine => cx.theme().system().transparent,
 9591            EditorMode::AutoHeight { max_lines: _ } => cx.theme().system().transparent,
 9592            EditorMode::Full => cx.theme().colors().editor_background,
 9593        };
 9594
 9595        EditorElement::new(
 9596            cx.view(),
 9597            EditorStyle {
 9598                background,
 9599                local_player: cx.theme().players().local(),
 9600                text: text_style,
 9601                scrollbar_width: px(12.),
 9602                syntax: cx.theme().syntax().clone(),
 9603                status: cx.theme().status().clone(),
 9604                inlays_style: HighlightStyle {
 9605                    color: Some(cx.theme().status().hint),
 9606                    font_weight: Some(FontWeight::BOLD),
 9607                    ..HighlightStyle::default()
 9608                },
 9609                suggestions_style: HighlightStyle {
 9610                    color: Some(cx.theme().status().predictive),
 9611                    ..HighlightStyle::default()
 9612                },
 9613            },
 9614        )
 9615    }
 9616}
 9617
 9618impl ViewInputHandler for Editor {
 9619    fn text_for_range(
 9620        &mut self,
 9621        range_utf16: Range<usize>,
 9622        cx: &mut ViewContext<Self>,
 9623    ) -> Option<String> {
 9624        Some(
 9625            self.buffer
 9626                .read(cx)
 9627                .read(cx)
 9628                .text_for_range(OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end))
 9629                .collect(),
 9630        )
 9631    }
 9632
 9633    fn selected_text_range(&mut self, cx: &mut ViewContext<Self>) -> Option<Range<usize>> {
 9634        // Prevent the IME menu from appearing when holding down an alphabetic key
 9635        // while input is disabled.
 9636        if !self.input_enabled {
 9637            return None;
 9638        }
 9639
 9640        let range = self.selections.newest::<OffsetUtf16>(cx).range();
 9641        Some(range.start.0..range.end.0)
 9642    }
 9643
 9644    fn marked_text_range(&self, cx: &mut ViewContext<Self>) -> Option<Range<usize>> {
 9645        let snapshot = self.buffer.read(cx).read(cx);
 9646        let range = self.text_highlights::<InputComposition>(cx)?.1.get(0)?;
 9647        Some(range.start.to_offset_utf16(&snapshot).0..range.end.to_offset_utf16(&snapshot).0)
 9648    }
 9649
 9650    fn unmark_text(&mut self, cx: &mut ViewContext<Self>) {
 9651        self.clear_highlights::<InputComposition>(cx);
 9652        self.ime_transaction.take();
 9653    }
 9654
 9655    fn replace_text_in_range(
 9656        &mut self,
 9657        range_utf16: Option<Range<usize>>,
 9658        text: &str,
 9659        cx: &mut ViewContext<Self>,
 9660    ) {
 9661        if !self.input_enabled {
 9662            cx.emit(EditorEvent::InputIgnored { text: text.into() });
 9663            return;
 9664        }
 9665
 9666        self.transact(cx, |this, cx| {
 9667            let new_selected_ranges = if let Some(range_utf16) = range_utf16 {
 9668                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
 9669                Some(this.selection_replacement_ranges(range_utf16, cx))
 9670            } else {
 9671                this.marked_text_ranges(cx)
 9672            };
 9673
 9674            let range_to_replace = new_selected_ranges.as_ref().and_then(|ranges_to_replace| {
 9675                let newest_selection_id = this.selections.newest_anchor().id;
 9676                this.selections
 9677                    .all::<OffsetUtf16>(cx)
 9678                    .iter()
 9679                    .zip(ranges_to_replace.iter())
 9680                    .find_map(|(selection, range)| {
 9681                        if selection.id == newest_selection_id {
 9682                            Some(
 9683                                (range.start.0 as isize - selection.head().0 as isize)
 9684                                    ..(range.end.0 as isize - selection.head().0 as isize),
 9685                            )
 9686                        } else {
 9687                            None
 9688                        }
 9689                    })
 9690            });
 9691
 9692            cx.emit(EditorEvent::InputHandled {
 9693                utf16_range_to_replace: range_to_replace,
 9694                text: text.into(),
 9695            });
 9696
 9697            if let Some(new_selected_ranges) = new_selected_ranges {
 9698                this.change_selections(None, cx, |selections| {
 9699                    selections.select_ranges(new_selected_ranges)
 9700                });
 9701            }
 9702
 9703            this.handle_input(text, cx);
 9704        });
 9705
 9706        if let Some(transaction) = self.ime_transaction {
 9707            self.buffer.update(cx, |buffer, cx| {
 9708                buffer.group_until_transaction(transaction, cx);
 9709            });
 9710        }
 9711
 9712        self.unmark_text(cx);
 9713    }
 9714
 9715    fn replace_and_mark_text_in_range(
 9716        &mut self,
 9717        range_utf16: Option<Range<usize>>,
 9718        text: &str,
 9719        new_selected_range_utf16: Option<Range<usize>>,
 9720        cx: &mut ViewContext<Self>,
 9721    ) {
 9722        if !self.input_enabled {
 9723            cx.emit(EditorEvent::InputIgnored { text: text.into() });
 9724            return;
 9725        }
 9726
 9727        let transaction = self.transact(cx, |this, cx| {
 9728            let ranges_to_replace = if let Some(mut marked_ranges) = this.marked_text_ranges(cx) {
 9729                let snapshot = this.buffer.read(cx).read(cx);
 9730                if let Some(relative_range_utf16) = range_utf16.as_ref() {
 9731                    for marked_range in &mut marked_ranges {
 9732                        marked_range.end.0 = marked_range.start.0 + relative_range_utf16.end;
 9733                        marked_range.start.0 += relative_range_utf16.start;
 9734                        marked_range.start =
 9735                            snapshot.clip_offset_utf16(marked_range.start, Bias::Left);
 9736                        marked_range.end =
 9737                            snapshot.clip_offset_utf16(marked_range.end, Bias::Right);
 9738                    }
 9739                }
 9740                Some(marked_ranges)
 9741            } else if let Some(range_utf16) = range_utf16 {
 9742                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
 9743                Some(this.selection_replacement_ranges(range_utf16, cx))
 9744            } else {
 9745                None
 9746            };
 9747
 9748            let range_to_replace = ranges_to_replace.as_ref().and_then(|ranges_to_replace| {
 9749                let newest_selection_id = this.selections.newest_anchor().id;
 9750                this.selections
 9751                    .all::<OffsetUtf16>(cx)
 9752                    .iter()
 9753                    .zip(ranges_to_replace.iter())
 9754                    .find_map(|(selection, range)| {
 9755                        if selection.id == newest_selection_id {
 9756                            Some(
 9757                                (range.start.0 as isize - selection.head().0 as isize)
 9758                                    ..(range.end.0 as isize - selection.head().0 as isize),
 9759                            )
 9760                        } else {
 9761                            None
 9762                        }
 9763                    })
 9764            });
 9765
 9766            cx.emit(EditorEvent::InputHandled {
 9767                utf16_range_to_replace: range_to_replace,
 9768                text: text.into(),
 9769            });
 9770
 9771            if let Some(ranges) = ranges_to_replace {
 9772                this.change_selections(None, cx, |s| s.select_ranges(ranges));
 9773            }
 9774
 9775            let marked_ranges = {
 9776                let snapshot = this.buffer.read(cx).read(cx);
 9777                this.selections
 9778                    .disjoint_anchors()
 9779                    .iter()
 9780                    .map(|selection| {
 9781                        selection.start.bias_left(&*snapshot)..selection.end.bias_right(&*snapshot)
 9782                    })
 9783                    .collect::<Vec<_>>()
 9784            };
 9785
 9786            if text.is_empty() {
 9787                this.unmark_text(cx);
 9788            } else {
 9789                this.highlight_text::<InputComposition>(
 9790                    marked_ranges.clone(),
 9791                    HighlightStyle {
 9792                        underline: Some(UnderlineStyle {
 9793                            thickness: px(1.),
 9794                            color: None,
 9795                            wavy: false,
 9796                        }),
 9797                        ..Default::default()
 9798                    },
 9799                    cx,
 9800                );
 9801            }
 9802
 9803            this.handle_input(text, cx);
 9804
 9805            if let Some(new_selected_range) = new_selected_range_utf16 {
 9806                let snapshot = this.buffer.read(cx).read(cx);
 9807                let new_selected_ranges = marked_ranges
 9808                    .into_iter()
 9809                    .map(|marked_range| {
 9810                        let insertion_start = marked_range.start.to_offset_utf16(&snapshot).0;
 9811                        let new_start = OffsetUtf16(new_selected_range.start + insertion_start);
 9812                        let new_end = OffsetUtf16(new_selected_range.end + insertion_start);
 9813                        snapshot.clip_offset_utf16(new_start, Bias::Left)
 9814                            ..snapshot.clip_offset_utf16(new_end, Bias::Right)
 9815                    })
 9816                    .collect::<Vec<_>>();
 9817
 9818                drop(snapshot);
 9819                this.change_selections(None, cx, |selections| {
 9820                    selections.select_ranges(new_selected_ranges)
 9821                });
 9822            }
 9823        });
 9824
 9825        self.ime_transaction = self.ime_transaction.or(transaction);
 9826        if let Some(transaction) = self.ime_transaction {
 9827            self.buffer.update(cx, |buffer, cx| {
 9828                buffer.group_until_transaction(transaction, cx);
 9829            });
 9830        }
 9831
 9832        if self.text_highlights::<InputComposition>(cx).is_none() {
 9833            self.ime_transaction.take();
 9834        }
 9835    }
 9836
 9837    fn bounds_for_range(
 9838        &mut self,
 9839        range_utf16: Range<usize>,
 9840        element_bounds: gpui::Bounds<Pixels>,
 9841        cx: &mut ViewContext<Self>,
 9842    ) -> Option<gpui::Bounds<Pixels>> {
 9843        let text_layout_details = self.text_layout_details(cx);
 9844        let style = &text_layout_details.editor_style;
 9845        let font_id = cx.text_system().resolve_font(&style.text.font());
 9846        let font_size = style.text.font_size.to_pixels(cx.rem_size());
 9847        let line_height = style.text.line_height_in_pixels(cx.rem_size());
 9848        let em_width = cx
 9849            .text_system()
 9850            .typographic_bounds(font_id, font_size, 'm')
 9851            .unwrap()
 9852            .size
 9853            .width;
 9854
 9855        let snapshot = self.snapshot(cx);
 9856        let scroll_position = snapshot.scroll_position();
 9857        let scroll_left = scroll_position.x * em_width;
 9858
 9859        let start = OffsetUtf16(range_utf16.start).to_display_point(&snapshot);
 9860        let x = snapshot.x_for_display_point(start, &text_layout_details) - scroll_left
 9861            + self.gutter_width;
 9862        let y = line_height * (start.row() as f32 - scroll_position.y);
 9863
 9864        Some(Bounds {
 9865            origin: element_bounds.origin + point(x, y),
 9866            size: size(em_width, line_height),
 9867        })
 9868    }
 9869}
 9870
 9871trait SelectionExt {
 9872    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize>;
 9873    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point>;
 9874    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
 9875    fn spanned_rows(&self, include_end_if_at_line_start: bool, map: &DisplaySnapshot)
 9876        -> Range<u32>;
 9877}
 9878
 9879impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
 9880    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
 9881        let start = self.start.to_point(buffer);
 9882        let end = self.end.to_point(buffer);
 9883        if self.reversed {
 9884            end..start
 9885        } else {
 9886            start..end
 9887        }
 9888    }
 9889
 9890    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
 9891        let start = self.start.to_offset(buffer);
 9892        let end = self.end.to_offset(buffer);
 9893        if self.reversed {
 9894            end..start
 9895        } else {
 9896            start..end
 9897        }
 9898    }
 9899
 9900    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
 9901        let start = self
 9902            .start
 9903            .to_point(&map.buffer_snapshot)
 9904            .to_display_point(map);
 9905        let end = self
 9906            .end
 9907            .to_point(&map.buffer_snapshot)
 9908            .to_display_point(map);
 9909        if self.reversed {
 9910            end..start
 9911        } else {
 9912            start..end
 9913        }
 9914    }
 9915
 9916    fn spanned_rows(
 9917        &self,
 9918        include_end_if_at_line_start: bool,
 9919        map: &DisplaySnapshot,
 9920    ) -> Range<u32> {
 9921        let start = self.start.to_point(&map.buffer_snapshot);
 9922        let mut end = self.end.to_point(&map.buffer_snapshot);
 9923        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
 9924            end.row -= 1;
 9925        }
 9926
 9927        let buffer_start = map.prev_line_boundary(start).0;
 9928        let buffer_end = map.next_line_boundary(end).0;
 9929        buffer_start.row..buffer_end.row + 1
 9930    }
 9931}
 9932
 9933impl<T: InvalidationRegion> InvalidationStack<T> {
 9934    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
 9935    where
 9936        S: Clone + ToOffset,
 9937    {
 9938        while let Some(region) = self.last() {
 9939            let all_selections_inside_invalidation_ranges =
 9940                if selections.len() == region.ranges().len() {
 9941                    selections
 9942                        .iter()
 9943                        .zip(region.ranges().iter().map(|r| r.to_offset(buffer)))
 9944                        .all(|(selection, invalidation_range)| {
 9945                            let head = selection.head().to_offset(buffer);
 9946                            invalidation_range.start <= head && invalidation_range.end >= head
 9947                        })
 9948                } else {
 9949                    false
 9950                };
 9951
 9952            if all_selections_inside_invalidation_ranges {
 9953                break;
 9954            } else {
 9955                self.pop();
 9956            }
 9957        }
 9958    }
 9959}
 9960
 9961impl<T> Default for InvalidationStack<T> {
 9962    fn default() -> Self {
 9963        Self(Default::default())
 9964    }
 9965}
 9966
 9967impl<T> Deref for InvalidationStack<T> {
 9968    type Target = Vec<T>;
 9969
 9970    fn deref(&self) -> &Self::Target {
 9971        &self.0
 9972    }
 9973}
 9974
 9975impl<T> DerefMut for InvalidationStack<T> {
 9976    fn deref_mut(&mut self) -> &mut Self::Target {
 9977        &mut self.0
 9978    }
 9979}
 9980
 9981impl InvalidationRegion for SnippetState {
 9982    fn ranges(&self) -> &[Range<Anchor>] {
 9983        &self.ranges[self.active_index]
 9984    }
 9985}
 9986
 9987pub fn diagnostic_block_renderer(diagnostic: Diagnostic, _is_valid: bool) -> RenderBlock {
 9988    let (text_without_backticks, code_ranges) = highlight_diagnostic_message(&diagnostic);
 9989
 9990    Arc::new(move |cx: &mut BlockContext| {
 9991        let group_id: SharedString = cx.block_id.to_string().into();
 9992
 9993        let mut text_style = cx.text_style().clone();
 9994        text_style.color = diagnostic_style(diagnostic.severity, true, cx.theme().status());
 9995
 9996        h_flex()
 9997            .id(cx.block_id)
 9998            .group(group_id.clone())
 9999            .relative()
10000            .size_full()
10001            .pl(cx.gutter_width)
10002            .w(cx.max_width + cx.gutter_width)
10003            .child(div().flex().w(cx.anchor_x - cx.gutter_width).flex_shrink())
10004            .child(div().flex().flex_shrink_0().child(
10005                StyledText::new(text_without_backticks.clone()).with_highlights(
10006                    &text_style,
10007                    code_ranges.iter().map(|range| {
10008                        (
10009                            range.clone(),
10010                            HighlightStyle {
10011                                font_weight: Some(FontWeight::BOLD),
10012                                ..Default::default()
10013                            },
10014                        )
10015                    }),
10016                ),
10017            ))
10018            .child(
10019                IconButton::new(("copy-block", cx.block_id), IconName::Copy)
10020                    .icon_color(Color::Muted)
10021                    .size(ButtonSize::Compact)
10022                    .style(ButtonStyle::Transparent)
10023                    .visible_on_hover(group_id)
10024                    .on_click({
10025                        let message = diagnostic.message.clone();
10026                        move |_click, cx| cx.write_to_clipboard(ClipboardItem::new(message.clone()))
10027                    })
10028                    .tooltip(|cx| Tooltip::text("Copy diagnostic message", cx)),
10029            )
10030            .into_any_element()
10031    })
10032}
10033
10034pub fn highlight_diagnostic_message(diagnostic: &Diagnostic) -> (SharedString, Vec<Range<usize>>) {
10035    let mut text_without_backticks = String::new();
10036    let mut code_ranges = Vec::new();
10037
10038    if let Some(source) = &diagnostic.source {
10039        text_without_backticks.push_str(&source);
10040        code_ranges.push(0..source.len());
10041        text_without_backticks.push_str(": ");
10042    }
10043
10044    let mut prev_offset = 0;
10045    let mut in_code_block = false;
10046    for (ix, _) in diagnostic
10047        .message
10048        .match_indices('`')
10049        .chain([(diagnostic.message.len(), "")])
10050    {
10051        let prev_len = text_without_backticks.len();
10052        text_without_backticks.push_str(&diagnostic.message[prev_offset..ix]);
10053        prev_offset = ix + 1;
10054        if in_code_block {
10055            code_ranges.push(prev_len..text_without_backticks.len());
10056            in_code_block = false;
10057        } else {
10058            in_code_block = true;
10059        }
10060    }
10061
10062    (text_without_backticks.into(), code_ranges)
10063}
10064
10065fn diagnostic_style(severity: DiagnosticSeverity, valid: bool, colors: &StatusColors) -> Hsla {
10066    match (severity, valid) {
10067        (DiagnosticSeverity::ERROR, true) => colors.error,
10068        (DiagnosticSeverity::ERROR, false) => colors.error,
10069        (DiagnosticSeverity::WARNING, true) => colors.warning,
10070        (DiagnosticSeverity::WARNING, false) => colors.warning,
10071        (DiagnosticSeverity::INFORMATION, true) => colors.info,
10072        (DiagnosticSeverity::INFORMATION, false) => colors.info,
10073        (DiagnosticSeverity::HINT, true) => colors.info,
10074        (DiagnosticSeverity::HINT, false) => colors.info,
10075        _ => colors.ignored,
10076    }
10077}
10078
10079pub fn styled_runs_for_code_label<'a>(
10080    label: &'a CodeLabel,
10081    syntax_theme: &'a theme::SyntaxTheme,
10082) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
10083    let fade_out = HighlightStyle {
10084        fade_out: Some(0.35),
10085        ..Default::default()
10086    };
10087
10088    let mut prev_end = label.filter_range.end;
10089    label
10090        .runs
10091        .iter()
10092        .enumerate()
10093        .flat_map(move |(ix, (range, highlight_id))| {
10094            let style = if let Some(style) = highlight_id.style(syntax_theme) {
10095                style
10096            } else {
10097                return Default::default();
10098            };
10099            let mut muted_style = style;
10100            muted_style.highlight(fade_out);
10101
10102            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
10103            if range.start >= label.filter_range.end {
10104                if range.start > prev_end {
10105                    runs.push((prev_end..range.start, fade_out));
10106                }
10107                runs.push((range.clone(), muted_style));
10108            } else if range.end <= label.filter_range.end {
10109                runs.push((range.clone(), style));
10110            } else {
10111                runs.push((range.start..label.filter_range.end, style));
10112                runs.push((label.filter_range.end..range.end, muted_style));
10113            }
10114            prev_end = cmp::max(prev_end, range.end);
10115
10116            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
10117                runs.push((prev_end..label.text.len(), fade_out));
10118            }
10119
10120            runs
10121        })
10122}
10123
10124pub(crate) fn split_words<'a>(text: &'a str) -> impl std::iter::Iterator<Item = &'a str> + 'a {
10125    let mut index = 0;
10126    let mut codepoints = text.char_indices().peekable();
10127
10128    std::iter::from_fn(move || {
10129        let start_index = index;
10130        while let Some((new_index, codepoint)) = codepoints.next() {
10131            index = new_index + codepoint.len_utf8();
10132            let current_upper = codepoint.is_uppercase();
10133            let next_upper = codepoints
10134                .peek()
10135                .map(|(_, c)| c.is_uppercase())
10136                .unwrap_or(false);
10137
10138            if !current_upper && next_upper {
10139                return Some(&text[start_index..index]);
10140            }
10141        }
10142
10143        index = text.len();
10144        if start_index < text.len() {
10145            return Some(&text[start_index..]);
10146        }
10147        None
10148    })
10149    .flat_map(|word| word.split_inclusive('_'))
10150    .flat_map(|word| word.split_inclusive('-'))
10151}
10152
10153trait RangeToAnchorExt {
10154    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor>;
10155}
10156
10157impl<T: ToOffset> RangeToAnchorExt for Range<T> {
10158    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor> {
10159        snapshot.anchor_after(self.start)..snapshot.anchor_before(self.end)
10160    }
10161}