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