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