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