editor.rs

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