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