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