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