editor.rs

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