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