editor.rs

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