editor.rs

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