editor.rs

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