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