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