editor.rs

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