editor.rs

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