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