editor.rs

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