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