editor.rs

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