editor.rs

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