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