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