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