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, Context, DispatchContext, EventEmitter, FocusHandle, FontFeatures,
   44    FontStyle, FontWeight, HighlightStyle, Hsla, InputHandler, Model, Pixels, Render, Subscription,
   45    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 util::{post_inc, RangeExt, ResultExt, TryFutureExt};
   99use workspace::{
  100    item::ItemEvent, searchable::SearchEvent, ItemNavHistory, SplitDirection, ViewId, Workspace,
  101};
  102
  103const CURSOR_BLINK_INTERVAL: Duration = Duration::from_millis(500);
  104const MAX_LINE_LEN: usize = 1024;
  105const MIN_NAVIGATION_HISTORY_ROW_DELTA: i64 = 10;
  106const MAX_SELECTION_HISTORY_LEN: usize = 1024;
  107const COPILOT_DEBOUNCE_TIMEOUT: Duration = Duration::from_millis(75);
  108pub const CODE_ACTIONS_DEBOUNCE_TIMEOUT: Duration = Duration::from_millis(250);
  109pub const DOCUMENT_HIGHLIGHTS_DEBOUNCE_TIMEOUT: Duration = Duration::from_millis(75);
  110
  111pub const FORMAT_TIMEOUT: Duration = Duration::from_secs(2);
  112
  113// pub fn render_parsed_markdown<Tag: 'static>(
  114//     parsed: &language::ParsedMarkdown,
  115//     editor_style: &EditorStyle,
  116//     workspace: Option<WeakView<Workspace>>,
  117//     cx: &mut ViewContext<Editor>,
  118// ) -> Text {
  119//     enum RenderedMarkdown {}
  120
  121//     let parsed = parsed.clone();
  122//     let view_id = cx.view_id();
  123//     let code_span_background_color = editor_style.document_highlight_read_background;
  124
  125//     let mut region_id = 0;
  126
  127//     todo!()
  128//     // Text::new(parsed.text, editor_style.text.clone())
  129//     //     .with_highlights(
  130//     //         parsed
  131//     //             .highlights
  132//     //             .iter()
  133//     //             .filter_map(|(range, highlight)| {
  134//     //                 let highlight = highlight.to_highlight_style(&editor_style.syntax)?;
  135//     //                 Some((range.clone(), highlight))
  136//     //             })
  137//     //             .collect::<Vec<_>>(),
  138//     //     )
  139//     //     .with_custom_runs(parsed.region_ranges, move |ix, bounds, cx| {
  140//     //         region_id += 1;
  141//     //         let region = parsed.regions[ix].clone();
  142
  143//     //         if let Some(link) = region.link {
  144//     //             cx.scene().push_cursor_region(CursorRegion {
  145//     //                 bounds,
  146//     //                 style: CursorStyle::PointingHand,
  147//     //             });
  148//     //             cx.scene().push_mouse_region(
  149//     //                 MouseRegion::new::<(RenderedMarkdown, Tag)>(view_id, region_id, bounds)
  150//     //                     .on_down::<Editor, _>(MouseButton::Left, move |_, _, cx| match &link {
  151//     //                         markdown::Link::Web { url } => cx.platform().open_url(url),
  152//     //                         markdown::Link::Path { path } => {
  153//     //                             if let Some(workspace) = &workspace {
  154//     //                                 _ = workspace.update(cx, |workspace, cx| {
  155//     //                                     workspace.open_abs_path(path.clone(), false, cx).detach();
  156//     //                                 });
  157//     //                             }
  158//     //                         }
  159//     //                     }),
  160//     //             );
  161//     //         }
  162
  163//     //         if region.code {
  164//     //             cx.draw_quad(Quad {
  165//     //                 bounds,
  166//     //                 background: Some(code_span_background_color),
  167//     //                 corner_radii: (2.0).into(),
  168//     //                 order: todo!(),
  169//     //                 content_mask: todo!(),
  170//     //                 border_color: todo!(),
  171//     //                 border_widths: todo!(),
  172//     //             });
  173//     //         }
  174//     //     })
  175//     //     .with_soft_wrap(true)
  176// }
  177
  178#[action]
  179pub struct SelectNext {
  180    #[serde(default)]
  181    pub replace_newest: bool,
  182}
  183
  184#[action]
  185pub struct SelectPrevious {
  186    #[serde(default)]
  187    pub replace_newest: bool,
  188}
  189
  190#[action]
  191pub struct SelectAllMatches {
  192    #[serde(default)]
  193    pub replace_newest: bool,
  194}
  195
  196#[action]
  197pub struct SelectToBeginningOfLine {
  198    #[serde(default)]
  199    stop_at_soft_wraps: bool,
  200}
  201
  202#[action]
  203pub struct MovePageUp {
  204    #[serde(default)]
  205    center_cursor: bool,
  206}
  207
  208#[action]
  209pub struct MovePageDown {
  210    #[serde(default)]
  211    center_cursor: bool,
  212}
  213
  214#[action]
  215pub struct SelectToEndOfLine {
  216    #[serde(default)]
  217    stop_at_soft_wraps: bool,
  218}
  219
  220#[action]
  221pub struct ToggleCodeActions {
  222    #[serde(default)]
  223    pub deployed_from_indicator: bool,
  224}
  225
  226#[action]
  227pub struct ConfirmCompletion {
  228    #[serde(default)]
  229    pub item_ix: Option<usize>,
  230}
  231
  232#[action]
  233pub struct ConfirmCodeAction {
  234    #[serde(default)]
  235    pub item_ix: Option<usize>,
  236}
  237
  238#[action]
  239pub struct ToggleComments {
  240    #[serde(default)]
  241    pub advance_downwards: bool,
  242}
  243
  244#[action]
  245pub struct FoldAt {
  246    pub buffer_row: u32,
  247}
  248
  249#[action]
  250pub struct UnfoldAt {
  251    pub buffer_row: u32,
  252}
  253
  254#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
  255pub enum InlayId {
  256    Suggestion(usize),
  257    Hint(usize),
  258}
  259
  260impl InlayId {
  261    fn id(&self) -> usize {
  262        match self {
  263            Self::Suggestion(id) => *id,
  264            Self::Hint(id) => *id,
  265        }
  266    }
  267}
  268
  269actions!(
  270    AddSelectionAbove,
  271    AddSelectionBelow,
  272    Backspace,
  273    Cancel,
  274    ConfirmRename,
  275    ContextMenuFirst,
  276    ContextMenuLast,
  277    ContextMenuNext,
  278    ContextMenuPrev,
  279    ConvertToKebabCase,
  280    ConvertToLowerCamelCase,
  281    ConvertToLowerCase,
  282    ConvertToSnakeCase,
  283    ConvertToTitleCase,
  284    ConvertToUpperCamelCase,
  285    ConvertToUpperCase,
  286    Copy,
  287    CopyHighlightJson,
  288    CopyPath,
  289    CopyRelativePath,
  290    Cut,
  291    CutToEndOfLine,
  292    Delete,
  293    DeleteLine,
  294    DeleteToBeginningOfLine,
  295    DeleteToEndOfLine,
  296    DeleteToNextSubwordEnd,
  297    DeleteToNextWordEnd,
  298    DeleteToPreviousSubwordStart,
  299    DeleteToPreviousWordStart,
  300    DuplicateLine,
  301    FindAllReferences,
  302    Fold,
  303    FoldSelectedRanges,
  304    Format,
  305    GoToDefinition,
  306    GoToDefinitionSplit,
  307    GoToDiagnostic,
  308    GoToHunk,
  309    GoToPrevDiagnostic,
  310    GoToPrevHunk,
  311    GoToTypeDefinition,
  312    GoToTypeDefinitionSplit,
  313    HalfPageDown,
  314    HalfPageUp,
  315    Hover,
  316    Indent,
  317    JoinLines,
  318    LineDown,
  319    LineUp,
  320    MoveDown,
  321    MoveLeft,
  322    MoveLineDown,
  323    MoveLineUp,
  324    MoveRight,
  325    MoveToBeginning,
  326    MoveToBeginningOfLine,
  327    MoveToEnclosingBracket,
  328    MoveToEnd,
  329    MoveToEndOfLine,
  330    MoveToEndOfParagraph,
  331    MoveToNextSubwordEnd,
  332    MoveToNextWordEnd,
  333    MoveToPreviousSubwordStart,
  334    MoveToPreviousWordStart,
  335    MoveToStartOfParagraph,
  336    MoveUp,
  337    Newline,
  338    NewlineAbove,
  339    NewlineBelow,
  340    NextScreen,
  341    OpenExcerpts,
  342    Outdent,
  343    PageDown,
  344    PageUp,
  345    Paste,
  346    Redo,
  347    RedoSelection,
  348    Rename,
  349    RestartLanguageServer,
  350    RevealInFinder,
  351    ReverseLines,
  352    ScrollCursorBottom,
  353    ScrollCursorCenter,
  354    ScrollCursorTop,
  355    SelectAll,
  356    SelectDown,
  357    SelectLargerSyntaxNode,
  358    SelectLeft,
  359    SelectLine,
  360    SelectRight,
  361    SelectSmallerSyntaxNode,
  362    SelectToBeginning,
  363    SelectToEnd,
  364    SelectToEndOfParagraph,
  365    SelectToNextSubwordEnd,
  366    SelectToNextWordEnd,
  367    SelectToPreviousSubwordStart,
  368    SelectToPreviousWordStart,
  369    SelectToStartOfParagraph,
  370    SelectUp,
  371    ShowCharacterPalette,
  372    ShowCompletions,
  373    ShuffleLines,
  374    SortLinesCaseInsensitive,
  375    SortLinesCaseSensitive,
  376    SplitSelectionIntoLines,
  377    Tab,
  378    TabPrev,
  379    ToggleInlayHints,
  380    ToggleSoftWrap,
  381    Transpose,
  382    Undo,
  383    UndoSelection,
  384    UnfoldLines,
  385);
  386
  387// impl_actions!(
  388//     editor,
  389//     [
  390//         SelectNext,
  391//         SelectPrevious,
  392//         SelectAllMatches,
  393//         SelectToBeginningOfLine,
  394//         SelectToEndOfLine,
  395//         ToggleCodeActions,
  396//         MovePageUp,
  397//         MovePageDown,
  398//         ConfirmCompletion,
  399//         ConfirmCodeAction,
  400//         ToggleComments,
  401//         FoldAt,
  402//         UnfoldAt,
  403//         GutterHover
  404//     ]
  405// );
  406
  407enum DocumentHighlightRead {}
  408enum DocumentHighlightWrite {}
  409enum InputComposition {}
  410
  411#[derive(Copy, Clone, PartialEq, Eq)]
  412pub enum Direction {
  413    Prev,
  414    Next,
  415}
  416
  417pub fn init_settings(cx: &mut AppContext) {
  418    EditorSettings::register(cx);
  419}
  420
  421pub fn init(cx: &mut AppContext) {
  422    init_settings(cx);
  423    // cx.register_action_type(Editor::new_file);
  424    // cx.register_action_type(Editor::new_file_in_direction);
  425    // cx.register_action_type(Editor::cancel);
  426    // cx.register_action_type(Editor::newline);
  427    // cx.register_action_type(Editor::newline_above);
  428    // cx.register_action_type(Editor::newline_below);
  429    // cx.register_action_type(Editor::backspace);
  430    // cx.register_action_type(Editor::delete);
  431    // cx.register_action_type(Editor::tab);
  432    // cx.register_action_type(Editor::tab_prev);
  433    // cx.register_action_type(Editor::indent);
  434    // cx.register_action_type(Editor::outdent);
  435    // cx.register_action_type(Editor::delete_line);
  436    // cx.register_action_type(Editor::join_lines);
  437    // cx.register_action_type(Editor::sort_lines_case_sensitive);
  438    // cx.register_action_type(Editor::sort_lines_case_insensitive);
  439    // cx.register_action_type(Editor::reverse_lines);
  440    // cx.register_action_type(Editor::shuffle_lines);
  441    // cx.register_action_type(Editor::convert_to_upper_case);
  442    // cx.register_action_type(Editor::convert_to_lower_case);
  443    // cx.register_action_type(Editor::convert_to_title_case);
  444    // cx.register_action_type(Editor::convert_to_snake_case);
  445    // cx.register_action_type(Editor::convert_to_kebab_case);
  446    // cx.register_action_type(Editor::convert_to_upper_camel_case);
  447    // cx.register_action_type(Editor::convert_to_lower_camel_case);
  448    // cx.register_action_type(Editor::delete_to_previous_word_start);
  449    // cx.register_action_type(Editor::delete_to_previous_subword_start);
  450    // cx.register_action_type(Editor::delete_to_next_word_end);
  451    // cx.register_action_type(Editor::delete_to_next_subword_end);
  452    // cx.register_action_type(Editor::delete_to_beginning_of_line);
  453    // cx.register_action_type(Editor::delete_to_end_of_line);
  454    // cx.register_action_type(Editor::cut_to_end_of_line);
  455    // cx.register_action_type(Editor::duplicate_line);
  456    // cx.register_action_type(Editor::move_line_up);
  457    // cx.register_action_type(Editor::move_line_down);
  458    // cx.register_action_type(Editor::transpose);
  459    // cx.register_action_type(Editor::cut);
  460    // cx.register_action_type(Editor::copy);
  461    // cx.register_action_type(Editor::paste);
  462    // cx.register_action_type(Editor::undo);
  463    // cx.register_action_type(Editor::redo);
  464    // cx.register_action_type(Editor::move_page_up);
  465    // cx.register_action_type::<MoveDown>();
  466    // cx.register_action_type(Editor::move_page_down);
  467    // cx.register_action_type(Editor::next_screen);
  468    // cx.register_action_type::<MoveLeft>();
  469    // cx.register_action_type::<MoveRight>();
  470    // cx.register_action_type(Editor::move_to_previous_word_start);
  471    // cx.register_action_type(Editor::move_to_previous_subword_start);
  472    // cx.register_action_type(Editor::move_to_next_word_end);
  473    // cx.register_action_type(Editor::move_to_next_subword_end);
  474    // cx.register_action_type(Editor::move_to_beginning_of_line);
  475    // cx.register_action_type(Editor::move_to_end_of_line);
  476    // cx.register_action_type(Editor::move_to_start_of_paragraph);
  477    // cx.register_action_type(Editor::move_to_end_of_paragraph);
  478    // cx.register_action_type(Editor::move_to_beginning);
  479    // cx.register_action_type(Editor::move_to_end);
  480    // cx.register_action_type(Editor::select_up);
  481    // cx.register_action_type(Editor::select_down);
  482    // cx.register_action_type(Editor::select_left);
  483    // cx.register_action_type(Editor::select_right);
  484    // cx.register_action_type(Editor::select_to_previous_word_start);
  485    // cx.register_action_type(Editor::select_to_previous_subword_start);
  486    // cx.register_action_type(Editor::select_to_next_word_end);
  487    // cx.register_action_type(Editor::select_to_next_subword_end);
  488    // cx.register_action_type(Editor::select_to_beginning_of_line);
  489    // cx.register_action_type(Editor::select_to_end_of_line);
  490    // cx.register_action_type(Editor::select_to_start_of_paragraph);
  491    // cx.register_action_type(Editor::select_to_end_of_paragraph);
  492    // cx.register_action_type(Editor::select_to_beginning);
  493    // cx.register_action_type(Editor::select_to_end);
  494    // cx.register_action_type(Editor::select_all);
  495    // cx.register_action_type(Editor::select_all_matches);
  496    // cx.register_action_type(Editor::select_line);
  497    // cx.register_action_type(Editor::split_selection_into_lines);
  498    // cx.register_action_type(Editor::add_selection_above);
  499    // cx.register_action_type(Editor::add_selection_below);
  500    // cx.register_action_type(Editor::select_next);
  501    // cx.register_action_type(Editor::select_previous);
  502    // cx.register_action_type(Editor::toggle_comments);
  503    // cx.register_action_type(Editor::select_larger_syntax_node);
  504    // cx.register_action_type(Editor::select_smaller_syntax_node);
  505    // cx.register_action_type(Editor::move_to_enclosing_bracket);
  506    // cx.register_action_type(Editor::undo_selection);
  507    // cx.register_action_type(Editor::redo_selection);
  508    // cx.register_action_type(Editor::go_to_diagnostic);
  509    // cx.register_action_type(Editor::go_to_prev_diagnostic);
  510    // cx.register_action_type(Editor::go_to_hunk);
  511    // cx.register_action_type(Editor::go_to_prev_hunk);
  512    // cx.register_action_type(Editor::go_to_definition);
  513    // cx.register_action_type(Editor::go_to_definition_split);
  514    // cx.register_action_type(Editor::go_to_type_definition);
  515    // cx.register_action_type(Editor::go_to_type_definition_split);
  516    // cx.register_action_type(Editor::fold);
  517    // cx.register_action_type(Editor::fold_at);
  518    // cx.register_action_type(Editor::unfold_lines);
  519    // cx.register_action_type(Editor::unfold_at);
  520    // cx.register_action_type(Editor::gutter_hover);
  521    // cx.register_action_type(Editor::fold_selected_ranges);
  522    // cx.register_action_type(Editor::show_completions);
  523    // cx.register_action_type(Editor::toggle_code_actions);
  524    // cx.register_action_type(Editor::open_excerpts);
  525    // cx.register_action_type(Editor::toggle_soft_wrap);
  526    // cx.register_action_type(Editor::toggle_inlay_hints);
  527    // cx.register_action_type(Editor::reveal_in_finder);
  528    // cx.register_action_type(Editor::copy_path);
  529    // cx.register_action_type(Editor::copy_relative_path);
  530    // cx.register_action_type(Editor::copy_highlight_json);
  531    // cx.add_async_action(Editor::format);
  532    // cx.register_action_type(Editor::restart_language_server);
  533    // cx.register_action_type(Editor::show_character_palette);
  534    // cx.add_async_action(Editor::confirm_completion);
  535    // cx.add_async_action(Editor::confirm_code_action);
  536    // cx.add_async_action(Editor::rename);
  537    // cx.add_async_action(Editor::confirm_rename);
  538    // cx.add_async_action(Editor::find_all_references);
  539    // cx.register_action_type(Editor::next_copilot_suggestion);
  540    // cx.register_action_type(Editor::previous_copilot_suggestion);
  541    // cx.register_action_type(Editor::copilot_suggest);
  542    // cx.register_action_type(Editor::context_menu_first);
  543    // cx.register_action_type(Editor::context_menu_prev);
  544    // cx.register_action_type(Editor::context_menu_next);
  545    // cx.register_action_type(Editor::context_menu_last);
  546
  547    hover_popover::init(cx);
  548
  549    workspace::register_project_item::<Editor>(cx);
  550    workspace::register_followable_item::<Editor>(cx);
  551    workspace::register_deserializable_item::<Editor>(cx);
  552}
  553
  554trait InvalidationRegion {
  555    fn ranges(&self) -> &[Range<Anchor>];
  556}
  557
  558#[derive(Clone, Debug, PartialEq)]
  559pub enum SelectPhase {
  560    Begin {
  561        position: DisplayPoint,
  562        add: bool,
  563        click_count: usize,
  564    },
  565    BeginColumnar {
  566        position: DisplayPoint,
  567        goal_column: u32,
  568    },
  569    Extend {
  570        position: DisplayPoint,
  571        click_count: usize,
  572    },
  573    Update {
  574        position: DisplayPoint,
  575        goal_column: u32,
  576        scroll_position: gpui::Point<f32>,
  577    },
  578    End,
  579}
  580
  581#[derive(Clone, Debug)]
  582pub enum SelectMode {
  583    Character,
  584    Word(Range<Anchor>),
  585    Line(Range<Anchor>),
  586    All,
  587}
  588
  589#[derive(Copy, Clone, PartialEq, Eq, Debug)]
  590pub enum EditorMode {
  591    SingleLine,
  592    AutoHeight { max_lines: usize },
  593    Full,
  594}
  595
  596#[derive(Clone, Debug)]
  597pub enum SoftWrap {
  598    None,
  599    EditorWidth,
  600    Column(u32),
  601}
  602
  603#[derive(Clone)]
  604pub struct EditorStyle {
  605    pub background: Hsla,
  606    pub local_player: PlayerColor,
  607    pub text: TextStyle,
  608    pub scrollbar_width: Pixels,
  609    pub syntax: Arc<SyntaxTheme>,
  610    pub diagnostic_style: DiagnosticStyle,
  611}
  612
  613type CompletionId = usize;
  614
  615// type GetFieldEditorTheme = dyn Fn(&theme::Theme) -> theme::FieldEditor;
  616// type OverrideTextStyle = dyn Fn(&EditorStyle) -> Option<HighlightStyle>;
  617
  618type BackgroundHighlight = (fn(&ThemeColors) -> Hsla, Vec<Range<Anchor>>);
  619type InlayBackgroundHighlight = (fn(&ThemeColors) -> Hsla, Vec<InlayHighlight>);
  620
  621pub struct Editor {
  622    handle: WeakView<Self>,
  623    focus_handle: FocusHandle,
  624    buffer: Model<MultiBuffer>,
  625    display_map: Model<DisplayMap>,
  626    pub selections: SelectionsCollection,
  627    pub scroll_manager: ScrollManager,
  628    columnar_selection_tail: Option<Anchor>,
  629    add_selections_state: Option<AddSelectionsState>,
  630    select_next_state: Option<SelectNextState>,
  631    select_prev_state: Option<SelectNextState>,
  632    selection_history: SelectionHistory,
  633    autoclose_regions: Vec<AutocloseRegion>,
  634    snippet_stack: InvalidationStack<SnippetState>,
  635    select_larger_syntax_node_stack: Vec<Box<[Selection<usize>]>>,
  636    ime_transaction: Option<TransactionId>,
  637    active_diagnostics: Option<ActiveDiagnosticGroup>,
  638    soft_wrap_mode_override: Option<language_settings::SoftWrap>,
  639    // get_field_editor_theme: Option<Arc<GetFieldEditorTheme>>,
  640    // override_text_style: Option<Box<OverrideTextStyle>>,
  641    project: Option<Model<Project>>,
  642    collaboration_hub: Option<Box<dyn CollaborationHub>>,
  643    blink_manager: Model<BlinkManager>,
  644    pub show_local_selections: bool,
  645    mode: EditorMode,
  646    show_gutter: bool,
  647    show_wrap_guides: Option<bool>,
  648    placeholder_text: Option<Arc<str>>,
  649    highlighted_rows: Option<Range<u32>>,
  650    background_highlights: BTreeMap<TypeId, BackgroundHighlight>,
  651    inlay_background_highlights: TreeMap<Option<TypeId>, InlayBackgroundHighlight>,
  652    nav_history: Option<ItemNavHistory>,
  653    context_menu: RwLock<Option<ContextMenu>>,
  654    // mouse_context_menu: View<context_menu::ContextMenu>,
  655    completion_tasks: Vec<(CompletionId, Task<Option<()>>)>,
  656    next_completion_id: CompletionId,
  657    available_code_actions: Option<(Model<Buffer>, Arc<[CodeAction]>)>,
  658    code_actions_task: Option<Task<()>>,
  659    document_highlights_task: Option<Task<()>>,
  660    pending_rename: Option<RenameState>,
  661    searchable: bool,
  662    cursor_shape: CursorShape,
  663    collapse_matches: bool,
  664    autoindent_mode: Option<AutoindentMode>,
  665    workspace: Option<(WeakView<Workspace>, i64)>,
  666    keymap_context_layers: BTreeMap<TypeId, DispatchContext>,
  667    input_enabled: bool,
  668    read_only: bool,
  669    leader_peer_id: Option<PeerId>,
  670    remote_id: Option<ViewId>,
  671    hover_state: HoverState,
  672    gutter_hovered: bool,
  673    link_go_to_definition_state: LinkGoToDefinitionState,
  674    copilot_state: CopilotState,
  675    inlay_hint_cache: InlayHintCache,
  676    next_inlay_id: usize,
  677    _subscriptions: Vec<Subscription>,
  678    pixel_position_of_newest_cursor: Option<gpui::Point<Pixels>>,
  679    gutter_width: Pixels,
  680    style: Option<EditorStyle>,
  681}
  682
  683pub struct EditorSnapshot {
  684    pub mode: EditorMode,
  685    pub show_gutter: bool,
  686    pub display_snapshot: DisplaySnapshot,
  687    pub placeholder_text: Option<Arc<str>>,
  688    is_focused: bool,
  689    scroll_anchor: ScrollAnchor,
  690    ongoing_scroll: OngoingScroll,
  691}
  692
  693pub struct RemoteSelection {
  694    pub replica_id: ReplicaId,
  695    pub selection: Selection<Anchor>,
  696    pub cursor_shape: CursorShape,
  697    pub peer_id: PeerId,
  698    pub line_mode: bool,
  699    pub participant_index: Option<ParticipantIndex>,
  700}
  701
  702#[derive(Clone, Debug)]
  703struct SelectionHistoryEntry {
  704    selections: Arc<[Selection<Anchor>]>,
  705    select_next_state: Option<SelectNextState>,
  706    select_prev_state: Option<SelectNextState>,
  707    add_selections_state: Option<AddSelectionsState>,
  708}
  709
  710enum SelectionHistoryMode {
  711    Normal,
  712    Undoing,
  713    Redoing,
  714}
  715
  716impl Default for SelectionHistoryMode {
  717    fn default() -> Self {
  718        Self::Normal
  719    }
  720}
  721
  722#[derive(Default)]
  723struct SelectionHistory {
  724    #[allow(clippy::type_complexity)]
  725    selections_by_transaction:
  726        HashMap<TransactionId, (Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)>,
  727    mode: SelectionHistoryMode,
  728    undo_stack: VecDeque<SelectionHistoryEntry>,
  729    redo_stack: VecDeque<SelectionHistoryEntry>,
  730}
  731
  732impl SelectionHistory {
  733    fn insert_transaction(
  734        &mut self,
  735        transaction_id: TransactionId,
  736        selections: Arc<[Selection<Anchor>]>,
  737    ) {
  738        self.selections_by_transaction
  739            .insert(transaction_id, (selections, None));
  740    }
  741
  742    #[allow(clippy::type_complexity)]
  743    fn transaction(
  744        &self,
  745        transaction_id: TransactionId,
  746    ) -> Option<&(Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)> {
  747        self.selections_by_transaction.get(&transaction_id)
  748    }
  749
  750    #[allow(clippy::type_complexity)]
  751    fn transaction_mut(
  752        &mut self,
  753        transaction_id: TransactionId,
  754    ) -> Option<&mut (Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)> {
  755        self.selections_by_transaction.get_mut(&transaction_id)
  756    }
  757
  758    fn push(&mut self, entry: SelectionHistoryEntry) {
  759        if !entry.selections.is_empty() {
  760            match self.mode {
  761                SelectionHistoryMode::Normal => {
  762                    self.push_undo(entry);
  763                    self.redo_stack.clear();
  764                }
  765                SelectionHistoryMode::Undoing => self.push_redo(entry),
  766                SelectionHistoryMode::Redoing => self.push_undo(entry),
  767            }
  768        }
  769    }
  770
  771    fn push_undo(&mut self, entry: SelectionHistoryEntry) {
  772        if self
  773            .undo_stack
  774            .back()
  775            .map_or(true, |e| e.selections != entry.selections)
  776        {
  777            self.undo_stack.push_back(entry);
  778            if self.undo_stack.len() > MAX_SELECTION_HISTORY_LEN {
  779                self.undo_stack.pop_front();
  780            }
  781        }
  782    }
  783
  784    fn push_redo(&mut self, entry: SelectionHistoryEntry) {
  785        if self
  786            .redo_stack
  787            .back()
  788            .map_or(true, |e| e.selections != entry.selections)
  789        {
  790            self.redo_stack.push_back(entry);
  791            if self.redo_stack.len() > MAX_SELECTION_HISTORY_LEN {
  792                self.redo_stack.pop_front();
  793            }
  794        }
  795    }
  796}
  797
  798#[derive(Clone, Debug)]
  799struct AddSelectionsState {
  800    above: bool,
  801    stack: Vec<usize>,
  802}
  803
  804#[derive(Clone)]
  805struct SelectNextState {
  806    query: AhoCorasick,
  807    wordwise: bool,
  808    done: bool,
  809}
  810
  811impl std::fmt::Debug for SelectNextState {
  812    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  813        f.debug_struct(std::any::type_name::<Self>())
  814            .field("wordwise", &self.wordwise)
  815            .field("done", &self.done)
  816            .finish()
  817    }
  818}
  819
  820#[derive(Debug)]
  821struct AutocloseRegion {
  822    selection_id: usize,
  823    range: Range<Anchor>,
  824    pair: BracketPair,
  825}
  826
  827#[derive(Debug)]
  828struct SnippetState {
  829    ranges: Vec<Vec<Range<Anchor>>>,
  830    active_index: usize,
  831}
  832
  833pub struct RenameState {
  834    pub range: Range<Anchor>,
  835    pub old_name: Arc<str>,
  836    pub editor: View<Editor>,
  837    block_id: BlockId,
  838}
  839
  840struct InvalidationStack<T>(Vec<T>);
  841
  842enum ContextMenu {
  843    Completions(CompletionsMenu),
  844    CodeActions(CodeActionsMenu),
  845}
  846
  847impl ContextMenu {
  848    fn select_first(
  849        &mut self,
  850        project: Option<&Model<Project>>,
  851        cx: &mut ViewContext<Editor>,
  852    ) -> bool {
  853        if self.visible() {
  854            match self {
  855                ContextMenu::Completions(menu) => menu.select_first(project, cx),
  856                ContextMenu::CodeActions(menu) => menu.select_first(cx),
  857            }
  858            true
  859        } else {
  860            false
  861        }
  862    }
  863
  864    fn select_prev(
  865        &mut self,
  866        project: Option<&Model<Project>>,
  867        cx: &mut ViewContext<Editor>,
  868    ) -> bool {
  869        if self.visible() {
  870            match self {
  871                ContextMenu::Completions(menu) => menu.select_prev(project, cx),
  872                ContextMenu::CodeActions(menu) => menu.select_prev(cx),
  873            }
  874            true
  875        } else {
  876            false
  877        }
  878    }
  879
  880    fn select_next(
  881        &mut self,
  882        project: Option<&Model<Project>>,
  883        cx: &mut ViewContext<Editor>,
  884    ) -> bool {
  885        if self.visible() {
  886            match self {
  887                ContextMenu::Completions(menu) => menu.select_next(project, cx),
  888                ContextMenu::CodeActions(menu) => menu.select_next(cx),
  889            }
  890            true
  891        } else {
  892            false
  893        }
  894    }
  895
  896    fn select_last(
  897        &mut self,
  898        project: Option<&Model<Project>>,
  899        cx: &mut ViewContext<Editor>,
  900    ) -> bool {
  901        if self.visible() {
  902            match self {
  903                ContextMenu::Completions(menu) => menu.select_last(project, cx),
  904                ContextMenu::CodeActions(menu) => menu.select_last(cx),
  905            }
  906            true
  907        } else {
  908            false
  909        }
  910    }
  911
  912    fn visible(&self) -> bool {
  913        match self {
  914            ContextMenu::Completions(menu) => menu.visible(),
  915            ContextMenu::CodeActions(menu) => menu.visible(),
  916        }
  917    }
  918
  919    fn render(
  920        &self,
  921        cursor_position: DisplayPoint,
  922        style: EditorStyle,
  923        workspace: Option<WeakView<Workspace>>,
  924        cx: &mut ViewContext<Editor>,
  925    ) -> (DisplayPoint, AnyElement<Editor>) {
  926        todo!()
  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    ) {
 1259        todo!("old implementation below")
 1260    }
 1261    // ) -> AnyElement<Editor> {
 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.focused {
 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    //             enum CodeActions {}
 4401    //             Some(
 4402    //                 MouseEventHandler::new::<CodeActions, _>(0, cx, |state, _| {
 4403    //                     Svg::new("icons/bolt.svg").with_color(
 4404    //                         style
 4405    //                             .code_actions
 4406    //                             .indicator
 4407    //                             .in_state(is_active)
 4408    //                             .style_for(state)
 4409    //                             .color,
 4410    //                     )
 4411    //                 })
 4412    //                 .with_cursor_style(CursorStyle::PointingHand)
 4413    //                 .with_padding(Padding::uniform(3.))
 4414    //                 .on_down(MouseButton::Left, |_, this, cx| {
 4415    //                     this.toggle_code_actions(
 4416    //                         &ToggleCodeActions {
 4417    //                             deployed_from_indicator: true,
 4418    //                         },
 4419    //                         cx,
 4420    //                     );
 4421    //                 })
 4422    //                 .into_any(),
 4423    //             )
 4424    //         } else {
 4425    //             None
 4426    //         }
 4427    //     }
 4428
 4429    //     pub fn render_fold_indicators(
 4430    //         &self,
 4431    //         fold_data: Vec<Option<(FoldStatus, u32, bool)>>,
 4432    //         style: &EditorStyle,
 4433    //         gutter_hovered: bool,
 4434    //         line_height: f32,
 4435    //         gutter_margin: f32,
 4436    //         cx: &mut ViewContext<Self>,
 4437    //     ) -> Vec<Option<AnyElement<Self>>> {
 4438    //         enum FoldIndicators {}
 4439
 4440    //         let style = style.folds.clone();
 4441
 4442    //         fold_data
 4443    //             .iter()
 4444    //             .enumerate()
 4445    //             .map(|(ix, fold_data)| {
 4446    //                 fold_data
 4447    //                     .map(|(fold_status, buffer_row, active)| {
 4448    //                         (active || gutter_hovered || fold_status == FoldStatus::Folded).then(|| {
 4449    //                             MouseEventHandler::new::<FoldIndicators, _>(
 4450    //                                 ix as usize,
 4451    //                                 cx,
 4452    //                                 |mouse_state, _| {
 4453    //                                     Svg::new(match fold_status {
 4454    //                                         FoldStatus::Folded => style.folded_icon.clone(),
 4455    //                                         FoldStatus::Foldable => style.foldable_icon.clone(),
 4456    //                                     })
 4457    //                                     .with_color(
 4458    //                                         style
 4459    //                                             .indicator
 4460    //                                             .in_state(fold_status == FoldStatus::Folded)
 4461    //                                             .style_for(mouse_state)
 4462    //                                             .color,
 4463    //                                     )
 4464    //                                     .constrained()
 4465    //                                     .with_width(gutter_margin * style.icon_margin_scale)
 4466    //                                     .aligned()
 4467    //                                     .constrained()
 4468    //                                     .with_height(line_height)
 4469    //                                     .with_width(gutter_margin)
 4470    //                                     .aligned()
 4471    //                                 },
 4472    //                             )
 4473    //                             .with_cursor_style(CursorStyle::PointingHand)
 4474    //                             .with_padding(Padding::uniform(3.))
 4475    //                             .on_click(MouseButton::Left, {
 4476    //                                 move |_, editor, cx| match fold_status {
 4477    //                                     FoldStatus::Folded => {
 4478    //                                         editor.unfold_at(&UnfoldAt { buffer_row }, cx);
 4479    //                                     }
 4480    //                                     FoldStatus::Foldable => {
 4481    //                                         editor.fold_at(&FoldAt { buffer_row }, cx);
 4482    //                                     }
 4483    //                                 }
 4484    //                             })
 4485    //                             .into_any()
 4486    //                         })
 4487    //                     })
 4488    //                     .flatten()
 4489    //             })
 4490    //             .collect()
 4491    //     }
 4492
 4493    pub fn context_menu_visible(&self) -> bool {
 4494        false
 4495        // todo!("context menu")
 4496        // self.context_menu
 4497        //     .read()
 4498        //     .as_ref()
 4499        //     .map_or(false, |menu| menu.visible())
 4500    }
 4501
 4502    //     pub fn render_context_menu(
 4503    //         &self,
 4504    //         cursor_position: DisplayPoint,
 4505    //         style: EditorStyle,
 4506    //         cx: &mut ViewContext<Editor>,
 4507    //     ) -> Option<(DisplayPoint, AnyElement<Editor>)> {
 4508    //         self.context_menu.read().as_ref().map(|menu| {
 4509    //             menu.render(
 4510    //                 cursor_position,
 4511    //                 style,
 4512    //                 self.workspace.as_ref().map(|(w, _)| w.clone()),
 4513    //                 cx,
 4514    //             )
 4515    //         })
 4516    //     }
 4517
 4518    fn hide_context_menu(&mut self, cx: &mut ViewContext<Self>) -> Option<ContextMenu> {
 4519        cx.notify();
 4520        self.completion_tasks.clear();
 4521        let context_menu = self.context_menu.write().take();
 4522        if context_menu.is_some() {
 4523            self.update_visible_copilot_suggestion(cx);
 4524        }
 4525        context_menu
 4526    }
 4527
 4528    pub fn insert_snippet(
 4529        &mut self,
 4530        insertion_ranges: &[Range<usize>],
 4531        snippet: Snippet,
 4532        cx: &mut ViewContext<Self>,
 4533    ) -> Result<()> {
 4534        let tabstops = self.buffer.update(cx, |buffer, cx| {
 4535            let snippet_text: Arc<str> = snippet.text.clone().into();
 4536            buffer.edit(
 4537                insertion_ranges
 4538                    .iter()
 4539                    .cloned()
 4540                    .map(|range| (range, snippet_text.clone())),
 4541                Some(AutoindentMode::EachLine),
 4542                cx,
 4543            );
 4544
 4545            let snapshot = &*buffer.read(cx);
 4546            let snippet = &snippet;
 4547            snippet
 4548                .tabstops
 4549                .iter()
 4550                .map(|tabstop| {
 4551                    let mut tabstop_ranges = tabstop
 4552                        .iter()
 4553                        .flat_map(|tabstop_range| {
 4554                            let mut delta = 0_isize;
 4555                            insertion_ranges.iter().map(move |insertion_range| {
 4556                                let insertion_start = insertion_range.start as isize + delta;
 4557                                delta +=
 4558                                    snippet.text.len() as isize - insertion_range.len() as isize;
 4559
 4560                                let start = snapshot.anchor_before(
 4561                                    (insertion_start + tabstop_range.start) as usize,
 4562                                );
 4563                                let end = snapshot
 4564                                    .anchor_after((insertion_start + tabstop_range.end) as usize);
 4565                                start..end
 4566                            })
 4567                        })
 4568                        .collect::<Vec<_>>();
 4569                    tabstop_ranges.sort_unstable_by(|a, b| a.start.cmp(&b.start, snapshot));
 4570                    tabstop_ranges
 4571                })
 4572                .collect::<Vec<_>>()
 4573        });
 4574
 4575        if let Some(tabstop) = tabstops.first() {
 4576            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 4577                s.select_ranges(tabstop.iter().cloned());
 4578            });
 4579            self.snippet_stack.push(SnippetState {
 4580                active_index: 0,
 4581                ranges: tabstops,
 4582            });
 4583        }
 4584
 4585        Ok(())
 4586    }
 4587
 4588    pub fn move_to_next_snippet_tabstop(&mut self, cx: &mut ViewContext<Self>) -> bool {
 4589        self.move_to_snippet_tabstop(Bias::Right, cx)
 4590    }
 4591
 4592    pub fn move_to_prev_snippet_tabstop(&mut self, cx: &mut ViewContext<Self>) -> bool {
 4593        self.move_to_snippet_tabstop(Bias::Left, cx)
 4594    }
 4595
 4596    pub fn move_to_snippet_tabstop(&mut self, bias: Bias, cx: &mut ViewContext<Self>) -> bool {
 4597        if let Some(mut snippet) = self.snippet_stack.pop() {
 4598            match bias {
 4599                Bias::Left => {
 4600                    if snippet.active_index > 0 {
 4601                        snippet.active_index -= 1;
 4602                    } else {
 4603                        self.snippet_stack.push(snippet);
 4604                        return false;
 4605                    }
 4606                }
 4607                Bias::Right => {
 4608                    if snippet.active_index + 1 < snippet.ranges.len() {
 4609                        snippet.active_index += 1;
 4610                    } else {
 4611                        self.snippet_stack.push(snippet);
 4612                        return false;
 4613                    }
 4614                }
 4615            }
 4616            if let Some(current_ranges) = snippet.ranges.get(snippet.active_index) {
 4617                self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 4618                    s.select_anchor_ranges(current_ranges.iter().cloned())
 4619                });
 4620                // If snippet state is not at the last tabstop, push it back on the stack
 4621                if snippet.active_index + 1 < snippet.ranges.len() {
 4622                    self.snippet_stack.push(snippet);
 4623                }
 4624                return true;
 4625            }
 4626        }
 4627
 4628        false
 4629    }
 4630
 4631    pub fn clear(&mut self, cx: &mut ViewContext<Self>) {
 4632        self.transact(cx, |this, cx| {
 4633            this.select_all(&SelectAll, cx);
 4634            this.insert("", cx);
 4635        });
 4636    }
 4637
 4638    pub fn backspace(&mut self, _: &Backspace, cx: &mut ViewContext<Self>) {
 4639        self.transact(cx, |this, cx| {
 4640            this.select_autoclose_pair(cx);
 4641            let mut selections = this.selections.all::<Point>(cx);
 4642            if !this.selections.line_mode {
 4643                let display_map = this.display_map.update(cx, |map, cx| map.snapshot(cx));
 4644                for selection in &mut selections {
 4645                    if selection.is_empty() {
 4646                        let old_head = selection.head();
 4647                        let mut new_head =
 4648                            movement::left(&display_map, old_head.to_display_point(&display_map))
 4649                                .to_point(&display_map);
 4650                        if let Some((buffer, line_buffer_range)) = display_map
 4651                            .buffer_snapshot
 4652                            .buffer_line_for_row(old_head.row)
 4653                        {
 4654                            let indent_size =
 4655                                buffer.indent_size_for_line(line_buffer_range.start.row);
 4656                            let indent_len = match indent_size.kind {
 4657                                IndentKind::Space => {
 4658                                    buffer.settings_at(line_buffer_range.start, cx).tab_size
 4659                                }
 4660                                IndentKind::Tab => NonZeroU32::new(1).unwrap(),
 4661                            };
 4662                            if old_head.column <= indent_size.len && old_head.column > 0 {
 4663                                let indent_len = indent_len.get();
 4664                                new_head = cmp::min(
 4665                                    new_head,
 4666                                    Point::new(
 4667                                        old_head.row,
 4668                                        ((old_head.column - 1) / indent_len) * indent_len,
 4669                                    ),
 4670                                );
 4671                            }
 4672                        }
 4673
 4674                        selection.set_head(new_head, SelectionGoal::None);
 4675                    }
 4676                }
 4677            }
 4678
 4679            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
 4680            this.insert("", cx);
 4681            this.refresh_copilot_suggestions(true, cx);
 4682        });
 4683    }
 4684
 4685    pub fn delete(&mut self, _: &Delete, cx: &mut ViewContext<Self>) {
 4686        self.transact(cx, |this, cx| {
 4687            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 4688                let line_mode = s.line_mode;
 4689                s.move_with(|map, selection| {
 4690                    if selection.is_empty() && !line_mode {
 4691                        let cursor = movement::right(map, selection.head());
 4692                        selection.end = cursor;
 4693                        selection.reversed = true;
 4694                        selection.goal = SelectionGoal::None;
 4695                    }
 4696                })
 4697            });
 4698            this.insert("", cx);
 4699            this.refresh_copilot_suggestions(true, cx);
 4700        });
 4701    }
 4702
 4703    pub fn tab_prev(&mut self, _: &TabPrev, cx: &mut ViewContext<Self>) {
 4704        if self.move_to_prev_snippet_tabstop(cx) {
 4705            return;
 4706        }
 4707
 4708        self.outdent(&Outdent, cx);
 4709    }
 4710
 4711    pub fn tab(&mut self, _: &Tab, cx: &mut ViewContext<Self>) {
 4712        if self.move_to_next_snippet_tabstop(cx) {
 4713            return;
 4714        }
 4715
 4716        let mut selections = self.selections.all_adjusted(cx);
 4717        let buffer = self.buffer.read(cx);
 4718        let snapshot = buffer.snapshot(cx);
 4719        let rows_iter = selections.iter().map(|s| s.head().row);
 4720        let suggested_indents = snapshot.suggested_indents(rows_iter, cx);
 4721
 4722        let mut edits = Vec::new();
 4723        let mut prev_edited_row = 0;
 4724        let mut row_delta = 0;
 4725        for selection in &mut selections {
 4726            if selection.start.row != prev_edited_row {
 4727                row_delta = 0;
 4728            }
 4729            prev_edited_row = selection.end.row;
 4730
 4731            // If the selection is non-empty, then increase the indentation of the selected lines.
 4732            if !selection.is_empty() {
 4733                row_delta =
 4734                    Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
 4735                continue;
 4736            }
 4737
 4738            // If the selection is empty and the cursor is in the leading whitespace before the
 4739            // suggested indentation, then auto-indent the line.
 4740            let cursor = selection.head();
 4741            let current_indent = snapshot.indent_size_for_line(cursor.row);
 4742            if let Some(suggested_indent) = suggested_indents.get(&cursor.row).copied() {
 4743                if cursor.column < suggested_indent.len
 4744                    && cursor.column <= current_indent.len
 4745                    && current_indent.len <= suggested_indent.len
 4746                {
 4747                    selection.start = Point::new(cursor.row, suggested_indent.len);
 4748                    selection.end = selection.start;
 4749                    if row_delta == 0 {
 4750                        edits.extend(Buffer::edit_for_indent_size_adjustment(
 4751                            cursor.row,
 4752                            current_indent,
 4753                            suggested_indent,
 4754                        ));
 4755                        row_delta = suggested_indent.len - current_indent.len;
 4756                    }
 4757                    continue;
 4758                }
 4759            }
 4760
 4761            // Accept copilot suggestion if there is only one selection and the cursor is not
 4762            // in the leading whitespace.
 4763            if self.selections.count() == 1
 4764                && cursor.column >= current_indent.len
 4765                && self.has_active_copilot_suggestion(cx)
 4766            {
 4767                self.accept_copilot_suggestion(cx);
 4768                return;
 4769            }
 4770
 4771            // Otherwise, insert a hard or soft tab.
 4772            let settings = buffer.settings_at(cursor, cx);
 4773            let tab_size = if settings.hard_tabs {
 4774                IndentSize::tab()
 4775            } else {
 4776                let tab_size = settings.tab_size.get();
 4777                let char_column = snapshot
 4778                    .text_for_range(Point::new(cursor.row, 0)..cursor)
 4779                    .flat_map(str::chars)
 4780                    .count()
 4781                    + row_delta as usize;
 4782                let chars_to_next_tab_stop = tab_size - (char_column as u32 % tab_size);
 4783                IndentSize::spaces(chars_to_next_tab_stop)
 4784            };
 4785            selection.start = Point::new(cursor.row, cursor.column + row_delta + tab_size.len);
 4786            selection.end = selection.start;
 4787            edits.push((cursor..cursor, tab_size.chars().collect::<String>()));
 4788            row_delta += tab_size.len;
 4789        }
 4790
 4791        self.transact(cx, |this, cx| {
 4792            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
 4793            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
 4794            this.refresh_copilot_suggestions(true, cx);
 4795        });
 4796    }
 4797
 4798    pub fn indent(&mut self, _: &Indent, cx: &mut ViewContext<Self>) {
 4799        let mut selections = self.selections.all::<Point>(cx);
 4800        let mut prev_edited_row = 0;
 4801        let mut row_delta = 0;
 4802        let mut edits = Vec::new();
 4803        let buffer = self.buffer.read(cx);
 4804        let snapshot = buffer.snapshot(cx);
 4805        for selection in &mut selections {
 4806            if selection.start.row != prev_edited_row {
 4807                row_delta = 0;
 4808            }
 4809            prev_edited_row = selection.end.row;
 4810
 4811            row_delta =
 4812                Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
 4813        }
 4814
 4815        self.transact(cx, |this, cx| {
 4816            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
 4817            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
 4818        });
 4819    }
 4820
 4821    fn indent_selection(
 4822        buffer: &MultiBuffer,
 4823        snapshot: &MultiBufferSnapshot,
 4824        selection: &mut Selection<Point>,
 4825        edits: &mut Vec<(Range<Point>, String)>,
 4826        delta_for_start_row: u32,
 4827        cx: &AppContext,
 4828    ) -> u32 {
 4829        let settings = buffer.settings_at(selection.start, cx);
 4830        let tab_size = settings.tab_size.get();
 4831        let indent_kind = if settings.hard_tabs {
 4832            IndentKind::Tab
 4833        } else {
 4834            IndentKind::Space
 4835        };
 4836        let mut start_row = selection.start.row;
 4837        let mut end_row = selection.end.row + 1;
 4838
 4839        // If a selection ends at the beginning of a line, don't indent
 4840        // that last line.
 4841        if selection.end.column == 0 {
 4842            end_row -= 1;
 4843        }
 4844
 4845        // Avoid re-indenting a row that has already been indented by a
 4846        // previous selection, but still update this selection's column
 4847        // to reflect that indentation.
 4848        if delta_for_start_row > 0 {
 4849            start_row += 1;
 4850            selection.start.column += delta_for_start_row;
 4851            if selection.end.row == selection.start.row {
 4852                selection.end.column += delta_for_start_row;
 4853            }
 4854        }
 4855
 4856        let mut delta_for_end_row = 0;
 4857        for row in start_row..end_row {
 4858            let current_indent = snapshot.indent_size_for_line(row);
 4859            let indent_delta = match (current_indent.kind, indent_kind) {
 4860                (IndentKind::Space, IndentKind::Space) => {
 4861                    let columns_to_next_tab_stop = tab_size - (current_indent.len % tab_size);
 4862                    IndentSize::spaces(columns_to_next_tab_stop)
 4863                }
 4864                (IndentKind::Tab, IndentKind::Space) => IndentSize::spaces(tab_size),
 4865                (_, IndentKind::Tab) => IndentSize::tab(),
 4866            };
 4867
 4868            let row_start = Point::new(row, 0);
 4869            edits.push((
 4870                row_start..row_start,
 4871                indent_delta.chars().collect::<String>(),
 4872            ));
 4873
 4874            // Update this selection's endpoints to reflect the indentation.
 4875            if row == selection.start.row {
 4876                selection.start.column += indent_delta.len;
 4877            }
 4878            if row == selection.end.row {
 4879                selection.end.column += indent_delta.len;
 4880                delta_for_end_row = indent_delta.len;
 4881            }
 4882        }
 4883
 4884        if selection.start.row == selection.end.row {
 4885            delta_for_start_row + delta_for_end_row
 4886        } else {
 4887            delta_for_end_row
 4888        }
 4889    }
 4890
 4891    pub fn outdent(&mut self, _: &Outdent, cx: &mut ViewContext<Self>) {
 4892        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 4893        let selections = self.selections.all::<Point>(cx);
 4894        let mut deletion_ranges = Vec::new();
 4895        let mut last_outdent = None;
 4896        {
 4897            let buffer = self.buffer.read(cx);
 4898            let snapshot = buffer.snapshot(cx);
 4899            for selection in &selections {
 4900                let settings = buffer.settings_at(selection.start, cx);
 4901                let tab_size = settings.tab_size.get();
 4902                let mut rows = selection.spanned_rows(false, &display_map);
 4903
 4904                // Avoid re-outdenting a row that has already been outdented by a
 4905                // previous selection.
 4906                if let Some(last_row) = last_outdent {
 4907                    if last_row == rows.start {
 4908                        rows.start += 1;
 4909                    }
 4910                }
 4911
 4912                for row in rows {
 4913                    let indent_size = snapshot.indent_size_for_line(row);
 4914                    if indent_size.len > 0 {
 4915                        let deletion_len = match indent_size.kind {
 4916                            IndentKind::Space => {
 4917                                let columns_to_prev_tab_stop = indent_size.len % tab_size;
 4918                                if columns_to_prev_tab_stop == 0 {
 4919                                    tab_size
 4920                                } else {
 4921                                    columns_to_prev_tab_stop
 4922                                }
 4923                            }
 4924                            IndentKind::Tab => 1,
 4925                        };
 4926                        deletion_ranges.push(Point::new(row, 0)..Point::new(row, deletion_len));
 4927                        last_outdent = Some(row);
 4928                    }
 4929                }
 4930            }
 4931        }
 4932
 4933        self.transact(cx, |this, cx| {
 4934            this.buffer.update(cx, |buffer, cx| {
 4935                let empty_str: Arc<str> = "".into();
 4936                buffer.edit(
 4937                    deletion_ranges
 4938                        .into_iter()
 4939                        .map(|range| (range, empty_str.clone())),
 4940                    None,
 4941                    cx,
 4942                );
 4943            });
 4944            let selections = this.selections.all::<usize>(cx);
 4945            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
 4946        });
 4947    }
 4948
 4949    pub fn delete_line(&mut self, _: &DeleteLine, cx: &mut ViewContext<Self>) {
 4950        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 4951        let selections = self.selections.all::<Point>(cx);
 4952
 4953        let mut new_cursors = Vec::new();
 4954        let mut edit_ranges = Vec::new();
 4955        let mut selections = selections.iter().peekable();
 4956        while let Some(selection) = selections.next() {
 4957            let mut rows = selection.spanned_rows(false, &display_map);
 4958            let goal_display_column = selection.head().to_display_point(&display_map).column();
 4959
 4960            // Accumulate contiguous regions of rows that we want to delete.
 4961            while let Some(next_selection) = selections.peek() {
 4962                let next_rows = next_selection.spanned_rows(false, &display_map);
 4963                if next_rows.start <= rows.end {
 4964                    rows.end = next_rows.end;
 4965                    selections.next().unwrap();
 4966                } else {
 4967                    break;
 4968                }
 4969            }
 4970
 4971            let buffer = &display_map.buffer_snapshot;
 4972            let mut edit_start = Point::new(rows.start, 0).to_offset(buffer);
 4973            let edit_end;
 4974            let cursor_buffer_row;
 4975            if buffer.max_point().row >= rows.end {
 4976                // If there's a line after the range, delete the \n from the end of the row range
 4977                // and position the cursor on the next line.
 4978                edit_end = Point::new(rows.end, 0).to_offset(buffer);
 4979                cursor_buffer_row = rows.end;
 4980            } else {
 4981                // If there isn't a line after the range, delete the \n from the line before the
 4982                // start of the row range and position the cursor there.
 4983                edit_start = edit_start.saturating_sub(1);
 4984                edit_end = buffer.len();
 4985                cursor_buffer_row = rows.start.saturating_sub(1);
 4986            }
 4987
 4988            let mut cursor = Point::new(cursor_buffer_row, 0).to_display_point(&display_map);
 4989            *cursor.column_mut() =
 4990                cmp::min(goal_display_column, display_map.line_len(cursor.row()));
 4991
 4992            new_cursors.push((
 4993                selection.id,
 4994                buffer.anchor_after(cursor.to_point(&display_map)),
 4995            ));
 4996            edit_ranges.push(edit_start..edit_end);
 4997        }
 4998
 4999        self.transact(cx, |this, cx| {
 5000            let buffer = this.buffer.update(cx, |buffer, cx| {
 5001                let empty_str: Arc<str> = "".into();
 5002                buffer.edit(
 5003                    edit_ranges
 5004                        .into_iter()
 5005                        .map(|range| (range, empty_str.clone())),
 5006                    None,
 5007                    cx,
 5008                );
 5009                buffer.snapshot(cx)
 5010            });
 5011            let new_selections = new_cursors
 5012                .into_iter()
 5013                .map(|(id, cursor)| {
 5014                    let cursor = cursor.to_point(&buffer);
 5015                    Selection {
 5016                        id,
 5017                        start: cursor,
 5018                        end: cursor,
 5019                        reversed: false,
 5020                        goal: SelectionGoal::None,
 5021                    }
 5022                })
 5023                .collect();
 5024
 5025            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5026                s.select(new_selections);
 5027            });
 5028        });
 5029    }
 5030
 5031    pub fn join_lines(&mut self, _: &JoinLines, cx: &mut ViewContext<Self>) {
 5032        let mut row_ranges = Vec::<Range<u32>>::new();
 5033        for selection in self.selections.all::<Point>(cx) {
 5034            let start = selection.start.row;
 5035            let end = if selection.start.row == selection.end.row {
 5036                selection.start.row + 1
 5037            } else {
 5038                selection.end.row
 5039            };
 5040
 5041            if let Some(last_row_range) = row_ranges.last_mut() {
 5042                if start <= last_row_range.end {
 5043                    last_row_range.end = end;
 5044                    continue;
 5045                }
 5046            }
 5047            row_ranges.push(start..end);
 5048        }
 5049
 5050        let snapshot = self.buffer.read(cx).snapshot(cx);
 5051        let mut cursor_positions = Vec::new();
 5052        for row_range in &row_ranges {
 5053            let anchor = snapshot.anchor_before(Point::new(
 5054                row_range.end - 1,
 5055                snapshot.line_len(row_range.end - 1),
 5056            ));
 5057            cursor_positions.push(anchor.clone()..anchor);
 5058        }
 5059
 5060        self.transact(cx, |this, cx| {
 5061            for row_range in row_ranges.into_iter().rev() {
 5062                for row in row_range.rev() {
 5063                    let end_of_line = Point::new(row, snapshot.line_len(row));
 5064                    let indent = snapshot.indent_size_for_line(row + 1);
 5065                    let start_of_next_line = Point::new(row + 1, indent.len);
 5066
 5067                    let replace = if snapshot.line_len(row + 1) > indent.len {
 5068                        " "
 5069                    } else {
 5070                        ""
 5071                    };
 5072
 5073                    this.buffer.update(cx, |buffer, cx| {
 5074                        buffer.edit([(end_of_line..start_of_next_line, replace)], None, cx)
 5075                    });
 5076                }
 5077            }
 5078
 5079            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5080                s.select_anchor_ranges(cursor_positions)
 5081            });
 5082        });
 5083    }
 5084
 5085    pub fn sort_lines_case_sensitive(
 5086        &mut self,
 5087        _: &SortLinesCaseSensitive,
 5088        cx: &mut ViewContext<Self>,
 5089    ) {
 5090        self.manipulate_lines(cx, |lines| lines.sort())
 5091    }
 5092
 5093    pub fn sort_lines_case_insensitive(
 5094        &mut self,
 5095        _: &SortLinesCaseInsensitive,
 5096        cx: &mut ViewContext<Self>,
 5097    ) {
 5098        self.manipulate_lines(cx, |lines| lines.sort_by_key(|line| line.to_lowercase()))
 5099    }
 5100
 5101    pub fn reverse_lines(&mut self, _: &ReverseLines, cx: &mut ViewContext<Self>) {
 5102        self.manipulate_lines(cx, |lines| lines.reverse())
 5103    }
 5104
 5105    pub fn shuffle_lines(&mut self, _: &ShuffleLines, cx: &mut ViewContext<Self>) {
 5106        self.manipulate_lines(cx, |lines| lines.shuffle(&mut thread_rng()))
 5107    }
 5108
 5109    fn manipulate_lines<Fn>(&mut self, cx: &mut ViewContext<Self>, mut callback: Fn)
 5110    where
 5111        Fn: FnMut(&mut [&str]),
 5112    {
 5113        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 5114        let buffer = self.buffer.read(cx).snapshot(cx);
 5115
 5116        let mut edits = Vec::new();
 5117
 5118        let selections = self.selections.all::<Point>(cx);
 5119        let mut selections = selections.iter().peekable();
 5120        let mut contiguous_row_selections = Vec::new();
 5121        let mut new_selections = Vec::new();
 5122
 5123        while let Some(selection) = selections.next() {
 5124            let (start_row, end_row) = consume_contiguous_rows(
 5125                &mut contiguous_row_selections,
 5126                selection,
 5127                &display_map,
 5128                &mut selections,
 5129            );
 5130
 5131            let start_point = Point::new(start_row, 0);
 5132            let end_point = Point::new(end_row - 1, buffer.line_len(end_row - 1));
 5133            let text = buffer
 5134                .text_for_range(start_point..end_point)
 5135                .collect::<String>();
 5136            let mut lines = text.split("\n").collect_vec();
 5137
 5138            let lines_len = lines.len();
 5139            callback(&mut lines);
 5140
 5141            // This is a current limitation with selections.
 5142            // If we wanted to support removing or adding lines, we'd need to fix the logic associated with selections.
 5143            debug_assert!(
 5144                lines.len() == lines_len,
 5145                "callback should not change the number of lines"
 5146            );
 5147
 5148            edits.push((start_point..end_point, lines.join("\n")));
 5149            let start_anchor = buffer.anchor_after(start_point);
 5150            let end_anchor = buffer.anchor_before(end_point);
 5151
 5152            // Make selection and push
 5153            new_selections.push(Selection {
 5154                id: selection.id,
 5155                start: start_anchor.to_offset(&buffer),
 5156                end: end_anchor.to_offset(&buffer),
 5157                goal: SelectionGoal::None,
 5158                reversed: selection.reversed,
 5159            });
 5160        }
 5161
 5162        self.transact(cx, |this, cx| {
 5163            this.buffer.update(cx, |buffer, cx| {
 5164                buffer.edit(edits, None, cx);
 5165            });
 5166
 5167            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5168                s.select(new_selections);
 5169            });
 5170
 5171            this.request_autoscroll(Autoscroll::fit(), cx);
 5172        });
 5173    }
 5174
 5175    pub fn convert_to_upper_case(&mut self, _: &ConvertToUpperCase, cx: &mut ViewContext<Self>) {
 5176        self.manipulate_text(cx, |text| text.to_uppercase())
 5177    }
 5178
 5179    pub fn convert_to_lower_case(&mut self, _: &ConvertToLowerCase, cx: &mut ViewContext<Self>) {
 5180        self.manipulate_text(cx, |text| text.to_lowercase())
 5181    }
 5182
 5183    pub fn convert_to_title_case(&mut self, _: &ConvertToTitleCase, cx: &mut ViewContext<Self>) {
 5184        self.manipulate_text(cx, |text| {
 5185            // Hack to get around the fact that to_case crate doesn't support '\n' as a word boundary
 5186            // https://github.com/rutrum/convert-case/issues/16
 5187            text.split("\n")
 5188                .map(|line| line.to_case(Case::Title))
 5189                .join("\n")
 5190        })
 5191    }
 5192
 5193    pub fn convert_to_snake_case(&mut self, _: &ConvertToSnakeCase, cx: &mut ViewContext<Self>) {
 5194        self.manipulate_text(cx, |text| text.to_case(Case::Snake))
 5195    }
 5196
 5197    pub fn convert_to_kebab_case(&mut self, _: &ConvertToKebabCase, cx: &mut ViewContext<Self>) {
 5198        self.manipulate_text(cx, |text| text.to_case(Case::Kebab))
 5199    }
 5200
 5201    pub fn convert_to_upper_camel_case(
 5202        &mut self,
 5203        _: &ConvertToUpperCamelCase,
 5204        cx: &mut ViewContext<Self>,
 5205    ) {
 5206        self.manipulate_text(cx, |text| {
 5207            // Hack to get around the fact that to_case crate doesn't support '\n' as a word boundary
 5208            // https://github.com/rutrum/convert-case/issues/16
 5209            text.split("\n")
 5210                .map(|line| line.to_case(Case::UpperCamel))
 5211                .join("\n")
 5212        })
 5213    }
 5214
 5215    pub fn convert_to_lower_camel_case(
 5216        &mut self,
 5217        _: &ConvertToLowerCamelCase,
 5218        cx: &mut ViewContext<Self>,
 5219    ) {
 5220        self.manipulate_text(cx, |text| text.to_case(Case::Camel))
 5221    }
 5222
 5223    fn manipulate_text<Fn>(&mut self, cx: &mut ViewContext<Self>, mut callback: Fn)
 5224    where
 5225        Fn: FnMut(&str) -> String,
 5226    {
 5227        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 5228        let buffer = self.buffer.read(cx).snapshot(cx);
 5229
 5230        let mut new_selections = Vec::new();
 5231        let mut edits = Vec::new();
 5232        let mut selection_adjustment = 0i32;
 5233
 5234        for selection in self.selections.all::<usize>(cx) {
 5235            let selection_is_empty = selection.is_empty();
 5236
 5237            let (start, end) = if selection_is_empty {
 5238                let word_range = movement::surrounding_word(
 5239                    &display_map,
 5240                    selection.start.to_display_point(&display_map),
 5241                );
 5242                let start = word_range.start.to_offset(&display_map, Bias::Left);
 5243                let end = word_range.end.to_offset(&display_map, Bias::Left);
 5244                (start, end)
 5245            } else {
 5246                (selection.start, selection.end)
 5247            };
 5248
 5249            let text = buffer.text_for_range(start..end).collect::<String>();
 5250            let old_length = text.len() as i32;
 5251            let text = callback(&text);
 5252
 5253            new_selections.push(Selection {
 5254                start: (start as i32 - selection_adjustment) as usize,
 5255                end: ((start + text.len()) as i32 - selection_adjustment) as usize,
 5256                goal: SelectionGoal::None,
 5257                ..selection
 5258            });
 5259
 5260            selection_adjustment += old_length - text.len() as i32;
 5261
 5262            edits.push((start..end, text));
 5263        }
 5264
 5265        self.transact(cx, |this, cx| {
 5266            this.buffer.update(cx, |buffer, cx| {
 5267                buffer.edit(edits, None, cx);
 5268            });
 5269
 5270            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5271                s.select(new_selections);
 5272            });
 5273
 5274            this.request_autoscroll(Autoscroll::fit(), cx);
 5275        });
 5276    }
 5277
 5278    pub fn duplicate_line(&mut self, _: &DuplicateLine, cx: &mut ViewContext<Self>) {
 5279        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 5280        let buffer = &display_map.buffer_snapshot;
 5281        let selections = self.selections.all::<Point>(cx);
 5282
 5283        let mut edits = Vec::new();
 5284        let mut selections_iter = selections.iter().peekable();
 5285        while let Some(selection) = selections_iter.next() {
 5286            // Avoid duplicating the same lines twice.
 5287            let mut rows = selection.spanned_rows(false, &display_map);
 5288
 5289            while let Some(next_selection) = selections_iter.peek() {
 5290                let next_rows = next_selection.spanned_rows(false, &display_map);
 5291                if next_rows.start < rows.end {
 5292                    rows.end = next_rows.end;
 5293                    selections_iter.next().unwrap();
 5294                } else {
 5295                    break;
 5296                }
 5297            }
 5298
 5299            // Copy the text from the selected row region and splice it at the start of the region.
 5300            let start = Point::new(rows.start, 0);
 5301            let end = Point::new(rows.end - 1, buffer.line_len(rows.end - 1));
 5302            let text = buffer
 5303                .text_for_range(start..end)
 5304                .chain(Some("\n"))
 5305                .collect::<String>();
 5306            edits.push((start..start, text));
 5307        }
 5308
 5309        self.transact(cx, |this, cx| {
 5310            this.buffer.update(cx, |buffer, cx| {
 5311                buffer.edit(edits, None, cx);
 5312            });
 5313
 5314            this.request_autoscroll(Autoscroll::fit(), cx);
 5315        });
 5316    }
 5317
 5318    pub fn move_line_up(&mut self, _: &MoveLineUp, cx: &mut ViewContext<Self>) {
 5319        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 5320        let buffer = self.buffer.read(cx).snapshot(cx);
 5321
 5322        let mut edits = Vec::new();
 5323        let mut unfold_ranges = Vec::new();
 5324        let mut refold_ranges = Vec::new();
 5325
 5326        let selections = self.selections.all::<Point>(cx);
 5327        let mut selections = selections.iter().peekable();
 5328        let mut contiguous_row_selections = Vec::new();
 5329        let mut new_selections = Vec::new();
 5330
 5331        while let Some(selection) = selections.next() {
 5332            // Find all the selections that span a contiguous row range
 5333            let (start_row, end_row) = consume_contiguous_rows(
 5334                &mut contiguous_row_selections,
 5335                selection,
 5336                &display_map,
 5337                &mut selections,
 5338            );
 5339
 5340            // Move the text spanned by the row range to be before the line preceding the row range
 5341            if start_row > 0 {
 5342                let range_to_move = Point::new(start_row - 1, buffer.line_len(start_row - 1))
 5343                    ..Point::new(end_row - 1, buffer.line_len(end_row - 1));
 5344                let insertion_point = display_map
 5345                    .prev_line_boundary(Point::new(start_row - 1, 0))
 5346                    .0;
 5347
 5348                // Don't move lines across excerpts
 5349                if buffer
 5350                    .excerpt_boundaries_in_range((
 5351                        Bound::Excluded(insertion_point),
 5352                        Bound::Included(range_to_move.end),
 5353                    ))
 5354                    .next()
 5355                    .is_none()
 5356                {
 5357                    let text = buffer
 5358                        .text_for_range(range_to_move.clone())
 5359                        .flat_map(|s| s.chars())
 5360                        .skip(1)
 5361                        .chain(['\n'])
 5362                        .collect::<String>();
 5363
 5364                    edits.push((
 5365                        buffer.anchor_after(range_to_move.start)
 5366                            ..buffer.anchor_before(range_to_move.end),
 5367                        String::new(),
 5368                    ));
 5369                    let insertion_anchor = buffer.anchor_after(insertion_point);
 5370                    edits.push((insertion_anchor..insertion_anchor, text));
 5371
 5372                    let row_delta = range_to_move.start.row - insertion_point.row + 1;
 5373
 5374                    // Move selections up
 5375                    new_selections.extend(contiguous_row_selections.drain(..).map(
 5376                        |mut selection| {
 5377                            selection.start.row -= row_delta;
 5378                            selection.end.row -= row_delta;
 5379                            selection
 5380                        },
 5381                    ));
 5382
 5383                    // Move folds up
 5384                    unfold_ranges.push(range_to_move.clone());
 5385                    for fold in display_map.folds_in_range(
 5386                        buffer.anchor_before(range_to_move.start)
 5387                            ..buffer.anchor_after(range_to_move.end),
 5388                    ) {
 5389                        let mut start = fold.start.to_point(&buffer);
 5390                        let mut end = fold.end.to_point(&buffer);
 5391                        start.row -= row_delta;
 5392                        end.row -= row_delta;
 5393                        refold_ranges.push(start..end);
 5394                    }
 5395                }
 5396            }
 5397
 5398            // If we didn't move line(s), preserve the existing selections
 5399            new_selections.append(&mut contiguous_row_selections);
 5400        }
 5401
 5402        self.transact(cx, |this, cx| {
 5403            this.unfold_ranges(unfold_ranges, true, true, cx);
 5404            this.buffer.update(cx, |buffer, cx| {
 5405                for (range, text) in edits {
 5406                    buffer.edit([(range, text)], None, cx);
 5407                }
 5408            });
 5409            this.fold_ranges(refold_ranges, true, cx);
 5410            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5411                s.select(new_selections);
 5412            })
 5413        });
 5414    }
 5415
 5416    pub fn move_line_down(&mut self, _: &MoveLineDown, cx: &mut ViewContext<Self>) {
 5417        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 5418        let buffer = self.buffer.read(cx).snapshot(cx);
 5419
 5420        let mut edits = Vec::new();
 5421        let mut unfold_ranges = Vec::new();
 5422        let mut refold_ranges = Vec::new();
 5423
 5424        let selections = self.selections.all::<Point>(cx);
 5425        let mut selections = selections.iter().peekable();
 5426        let mut contiguous_row_selections = Vec::new();
 5427        let mut new_selections = Vec::new();
 5428
 5429        while let Some(selection) = selections.next() {
 5430            // Find all the selections that span a contiguous row range
 5431            let (start_row, end_row) = consume_contiguous_rows(
 5432                &mut contiguous_row_selections,
 5433                selection,
 5434                &display_map,
 5435                &mut selections,
 5436            );
 5437
 5438            // Move the text spanned by the row range to be after the last line of the row range
 5439            if end_row <= buffer.max_point().row {
 5440                let range_to_move = Point::new(start_row, 0)..Point::new(end_row, 0);
 5441                let insertion_point = display_map.next_line_boundary(Point::new(end_row, 0)).0;
 5442
 5443                // Don't move lines across excerpt boundaries
 5444                if buffer
 5445                    .excerpt_boundaries_in_range((
 5446                        Bound::Excluded(range_to_move.start),
 5447                        Bound::Included(insertion_point),
 5448                    ))
 5449                    .next()
 5450                    .is_none()
 5451                {
 5452                    let mut text = String::from("\n");
 5453                    text.extend(buffer.text_for_range(range_to_move.clone()));
 5454                    text.pop(); // Drop trailing newline
 5455                    edits.push((
 5456                        buffer.anchor_after(range_to_move.start)
 5457                            ..buffer.anchor_before(range_to_move.end),
 5458                        String::new(),
 5459                    ));
 5460                    let insertion_anchor = buffer.anchor_after(insertion_point);
 5461                    edits.push((insertion_anchor..insertion_anchor, text));
 5462
 5463                    let row_delta = insertion_point.row - range_to_move.end.row + 1;
 5464
 5465                    // Move selections down
 5466                    new_selections.extend(contiguous_row_selections.drain(..).map(
 5467                        |mut selection| {
 5468                            selection.start.row += row_delta;
 5469                            selection.end.row += row_delta;
 5470                            selection
 5471                        },
 5472                    ));
 5473
 5474                    // Move folds down
 5475                    unfold_ranges.push(range_to_move.clone());
 5476                    for fold in display_map.folds_in_range(
 5477                        buffer.anchor_before(range_to_move.start)
 5478                            ..buffer.anchor_after(range_to_move.end),
 5479                    ) {
 5480                        let mut start = fold.start.to_point(&buffer);
 5481                        let mut end = fold.end.to_point(&buffer);
 5482                        start.row += row_delta;
 5483                        end.row += row_delta;
 5484                        refold_ranges.push(start..end);
 5485                    }
 5486                }
 5487            }
 5488
 5489            // If we didn't move line(s), preserve the existing selections
 5490            new_selections.append(&mut contiguous_row_selections);
 5491        }
 5492
 5493        self.transact(cx, |this, cx| {
 5494            this.unfold_ranges(unfold_ranges, true, true, cx);
 5495            this.buffer.update(cx, |buffer, cx| {
 5496                for (range, text) in edits {
 5497                    buffer.edit([(range, text)], None, cx);
 5498                }
 5499            });
 5500            this.fold_ranges(refold_ranges, true, cx);
 5501            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(new_selections));
 5502        });
 5503    }
 5504
 5505    pub fn transpose(&mut self, _: &Transpose, cx: &mut ViewContext<Self>) {
 5506        let text_layout_details = &self.text_layout_details(cx);
 5507        self.transact(cx, |this, cx| {
 5508            let edits = this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5509                let mut edits: Vec<(Range<usize>, String)> = Default::default();
 5510                let line_mode = s.line_mode;
 5511                s.move_with(|display_map, selection| {
 5512                    if !selection.is_empty() || line_mode {
 5513                        return;
 5514                    }
 5515
 5516                    let mut head = selection.head();
 5517                    let mut transpose_offset = head.to_offset(display_map, Bias::Right);
 5518                    if head.column() == display_map.line_len(head.row()) {
 5519                        transpose_offset = display_map
 5520                            .buffer_snapshot
 5521                            .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
 5522                    }
 5523
 5524                    if transpose_offset == 0 {
 5525                        return;
 5526                    }
 5527
 5528                    *head.column_mut() += 1;
 5529                    head = display_map.clip_point(head, Bias::Right);
 5530                    let goal = SelectionGoal::HorizontalPosition(
 5531                        display_map.x_for_point(head, &text_layout_details).into(),
 5532                    );
 5533                    selection.collapse_to(head, goal);
 5534
 5535                    let transpose_start = display_map
 5536                        .buffer_snapshot
 5537                        .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
 5538                    if edits.last().map_or(true, |e| e.0.end <= transpose_start) {
 5539                        let transpose_end = display_map
 5540                            .buffer_snapshot
 5541                            .clip_offset(transpose_offset + 1, Bias::Right);
 5542                        if let Some(ch) =
 5543                            display_map.buffer_snapshot.chars_at(transpose_start).next()
 5544                        {
 5545                            edits.push((transpose_start..transpose_offset, String::new()));
 5546                            edits.push((transpose_end..transpose_end, ch.to_string()));
 5547                        }
 5548                    }
 5549                });
 5550                edits
 5551            });
 5552            this.buffer
 5553                .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
 5554            let selections = this.selections.all::<usize>(cx);
 5555            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5556                s.select(selections);
 5557            });
 5558        });
 5559    }
 5560
 5561    pub fn cut(&mut self, _: &Cut, cx: &mut ViewContext<Self>) {
 5562        let mut text = String::new();
 5563        let buffer = self.buffer.read(cx).snapshot(cx);
 5564        let mut selections = self.selections.all::<Point>(cx);
 5565        let mut clipboard_selections = Vec::with_capacity(selections.len());
 5566        {
 5567            let max_point = buffer.max_point();
 5568            let mut is_first = true;
 5569            for selection in &mut selections {
 5570                let is_entire_line = selection.is_empty() || self.selections.line_mode;
 5571                if is_entire_line {
 5572                    selection.start = Point::new(selection.start.row, 0);
 5573                    selection.end = cmp::min(max_point, Point::new(selection.end.row + 1, 0));
 5574                    selection.goal = SelectionGoal::None;
 5575                }
 5576                if is_first {
 5577                    is_first = false;
 5578                } else {
 5579                    text += "\n";
 5580                }
 5581                let mut len = 0;
 5582                for chunk in buffer.text_for_range(selection.start..selection.end) {
 5583                    text.push_str(chunk);
 5584                    len += chunk.len();
 5585                }
 5586                clipboard_selections.push(ClipboardSelection {
 5587                    len,
 5588                    is_entire_line,
 5589                    first_line_indent: buffer.indent_size_for_line(selection.start.row).len,
 5590                });
 5591            }
 5592        }
 5593
 5594        self.transact(cx, |this, cx| {
 5595            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5596                s.select(selections);
 5597            });
 5598            this.insert("", cx);
 5599            cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
 5600        });
 5601    }
 5602
 5603    pub fn copy(&mut self, _: &Copy, cx: &mut ViewContext<Self>) {
 5604        let selections = self.selections.all::<Point>(cx);
 5605        let buffer = self.buffer.read(cx).read(cx);
 5606        let mut text = String::new();
 5607
 5608        let mut clipboard_selections = Vec::with_capacity(selections.len());
 5609        {
 5610            let max_point = buffer.max_point();
 5611            let mut is_first = true;
 5612            for selection in selections.iter() {
 5613                let mut start = selection.start;
 5614                let mut end = selection.end;
 5615                let is_entire_line = selection.is_empty() || self.selections.line_mode;
 5616                if is_entire_line {
 5617                    start = Point::new(start.row, 0);
 5618                    end = cmp::min(max_point, Point::new(end.row + 1, 0));
 5619                }
 5620                if is_first {
 5621                    is_first = false;
 5622                } else {
 5623                    text += "\n";
 5624                }
 5625                let mut len = 0;
 5626                for chunk in buffer.text_for_range(start..end) {
 5627                    text.push_str(chunk);
 5628                    len += chunk.len();
 5629                }
 5630                clipboard_selections.push(ClipboardSelection {
 5631                    len,
 5632                    is_entire_line,
 5633                    first_line_indent: buffer.indent_size_for_line(start.row).len,
 5634                });
 5635            }
 5636        }
 5637
 5638        cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
 5639    }
 5640
 5641    pub fn paste(&mut self, _: &Paste, cx: &mut ViewContext<Self>) {
 5642        self.transact(cx, |this, cx| {
 5643            if let Some(item) = cx.read_from_clipboard() {
 5644                let clipboard_text = Cow::Borrowed(item.text());
 5645                if let Some(mut clipboard_selections) = item.metadata::<Vec<ClipboardSelection>>() {
 5646                    let old_selections = this.selections.all::<usize>(cx);
 5647                    let all_selections_were_entire_line =
 5648                        clipboard_selections.iter().all(|s| s.is_entire_line);
 5649                    let first_selection_indent_column =
 5650                        clipboard_selections.first().map(|s| s.first_line_indent);
 5651                    if clipboard_selections.len() != old_selections.len() {
 5652                        clipboard_selections.drain(..);
 5653                    }
 5654
 5655                    this.buffer.update(cx, |buffer, cx| {
 5656                        let snapshot = buffer.read(cx);
 5657                        let mut start_offset = 0;
 5658                        let mut edits = Vec::new();
 5659                        let mut original_indent_columns = Vec::new();
 5660                        let line_mode = this.selections.line_mode;
 5661                        for (ix, selection) in old_selections.iter().enumerate() {
 5662                            let to_insert;
 5663                            let entire_line;
 5664                            let original_indent_column;
 5665                            if let Some(clipboard_selection) = clipboard_selections.get(ix) {
 5666                                let end_offset = start_offset + clipboard_selection.len;
 5667                                to_insert = &clipboard_text[start_offset..end_offset];
 5668                                entire_line = clipboard_selection.is_entire_line;
 5669                                start_offset = end_offset + 1;
 5670                                original_indent_column =
 5671                                    Some(clipboard_selection.first_line_indent);
 5672                            } else {
 5673                                to_insert = clipboard_text.as_str();
 5674                                entire_line = all_selections_were_entire_line;
 5675                                original_indent_column = first_selection_indent_column
 5676                            }
 5677
 5678                            // If the corresponding selection was empty when this slice of the
 5679                            // clipboard text was written, then the entire line containing the
 5680                            // selection was copied. If this selection is also currently empty,
 5681                            // then paste the line before the current line of the buffer.
 5682                            let range = if selection.is_empty() && !line_mode && entire_line {
 5683                                let column = selection.start.to_point(&snapshot).column as usize;
 5684                                let line_start = selection.start - column;
 5685                                line_start..line_start
 5686                            } else {
 5687                                selection.range()
 5688                            };
 5689
 5690                            edits.push((range, to_insert));
 5691                            original_indent_columns.extend(original_indent_column);
 5692                        }
 5693                        drop(snapshot);
 5694
 5695                        buffer.edit(
 5696                            edits,
 5697                            Some(AutoindentMode::Block {
 5698                                original_indent_columns,
 5699                            }),
 5700                            cx,
 5701                        );
 5702                    });
 5703
 5704                    let selections = this.selections.all::<usize>(cx);
 5705                    this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
 5706                } else {
 5707                    this.insert(&clipboard_text, cx);
 5708                }
 5709            }
 5710        });
 5711    }
 5712
 5713    pub fn undo(&mut self, _: &Undo, cx: &mut ViewContext<Self>) {
 5714        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.undo(cx)) {
 5715            if let Some((selections, _)) = self.selection_history.transaction(tx_id).cloned() {
 5716                self.change_selections(None, cx, |s| {
 5717                    s.select_anchors(selections.to_vec());
 5718                });
 5719            }
 5720            self.request_autoscroll(Autoscroll::fit(), cx);
 5721            self.unmark_text(cx);
 5722            self.refresh_copilot_suggestions(true, cx);
 5723            cx.emit(Event::Edited);
 5724        }
 5725    }
 5726
 5727    pub fn redo(&mut self, _: &Redo, cx: &mut ViewContext<Self>) {
 5728        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.redo(cx)) {
 5729            if let Some((_, Some(selections))) = self.selection_history.transaction(tx_id).cloned()
 5730            {
 5731                self.change_selections(None, cx, |s| {
 5732                    s.select_anchors(selections.to_vec());
 5733                });
 5734            }
 5735            self.request_autoscroll(Autoscroll::fit(), cx);
 5736            self.unmark_text(cx);
 5737            self.refresh_copilot_suggestions(true, cx);
 5738            cx.emit(Event::Edited);
 5739        }
 5740    }
 5741
 5742    pub fn finalize_last_transaction(&mut self, cx: &mut ViewContext<Self>) {
 5743        self.buffer
 5744            .update(cx, |buffer, cx| buffer.finalize_last_transaction(cx));
 5745    }
 5746
 5747    pub fn move_left(&mut self, _: &MoveLeft, cx: &mut ViewContext<Self>) {
 5748        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5749            let line_mode = s.line_mode;
 5750            s.move_with(|map, selection| {
 5751                let cursor = if selection.is_empty() && !line_mode {
 5752                    movement::left(map, selection.start)
 5753                } else {
 5754                    selection.start
 5755                };
 5756                selection.collapse_to(cursor, SelectionGoal::None);
 5757            });
 5758        })
 5759    }
 5760
 5761    pub fn select_left(&mut self, _: &SelectLeft, cx: &mut ViewContext<Self>) {
 5762        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5763            s.move_heads_with(|map, head, _| (movement::left(map, head), SelectionGoal::None));
 5764        })
 5765    }
 5766
 5767    pub fn move_right(&mut self, _: &MoveRight, cx: &mut ViewContext<Self>) {
 5768        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5769            let line_mode = s.line_mode;
 5770            s.move_with(|map, selection| {
 5771                let cursor = if selection.is_empty() && !line_mode {
 5772                    movement::right(map, selection.end)
 5773                } else {
 5774                    selection.end
 5775                };
 5776                selection.collapse_to(cursor, SelectionGoal::None)
 5777            });
 5778        })
 5779    }
 5780
 5781    pub fn select_right(&mut self, _: &SelectRight, cx: &mut ViewContext<Self>) {
 5782        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5783            s.move_heads_with(|map, head, _| (movement::right(map, head), SelectionGoal::None));
 5784        })
 5785    }
 5786
 5787    pub fn move_up(&mut self, _: &MoveUp, cx: &mut ViewContext<Self>) {
 5788        if self.take_rename(true, cx).is_some() {
 5789            return;
 5790        }
 5791
 5792        if matches!(self.mode, EditorMode::SingleLine) {
 5793            cx.propagate();
 5794            return;
 5795        }
 5796
 5797        let text_layout_details = &self.text_layout_details(cx);
 5798
 5799        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5800            let line_mode = s.line_mode;
 5801            s.move_with(|map, selection| {
 5802                if !selection.is_empty() && !line_mode {
 5803                    selection.goal = SelectionGoal::None;
 5804                }
 5805                let (cursor, goal) = movement::up(
 5806                    map,
 5807                    selection.start,
 5808                    selection.goal,
 5809                    false,
 5810                    &text_layout_details,
 5811                );
 5812                selection.collapse_to(cursor, goal);
 5813            });
 5814        })
 5815    }
 5816
 5817    pub fn move_page_up(&mut self, action: &MovePageUp, cx: &mut ViewContext<Self>) {
 5818        if self.take_rename(true, cx).is_some() {
 5819            return;
 5820        }
 5821
 5822        if matches!(self.mode, EditorMode::SingleLine) {
 5823            cx.propagate();
 5824            return;
 5825        }
 5826
 5827        let row_count = if let Some(row_count) = self.visible_line_count() {
 5828            row_count as u32 - 1
 5829        } else {
 5830            return;
 5831        };
 5832
 5833        let autoscroll = if action.center_cursor {
 5834            Autoscroll::center()
 5835        } else {
 5836            Autoscroll::fit()
 5837        };
 5838
 5839        let text_layout_details = &self.text_layout_details(cx);
 5840
 5841        self.change_selections(Some(autoscroll), cx, |s| {
 5842            let line_mode = s.line_mode;
 5843            s.move_with(|map, selection| {
 5844                if !selection.is_empty() && !line_mode {
 5845                    selection.goal = SelectionGoal::None;
 5846                }
 5847                let (cursor, goal) = movement::up_by_rows(
 5848                    map,
 5849                    selection.end,
 5850                    row_count,
 5851                    selection.goal,
 5852                    false,
 5853                    &text_layout_details,
 5854                );
 5855                selection.collapse_to(cursor, goal);
 5856            });
 5857        });
 5858    }
 5859
 5860    pub fn select_up(&mut self, _: &SelectUp, cx: &mut ViewContext<Self>) {
 5861        let text_layout_details = &self.text_layout_details(cx);
 5862        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5863            s.move_heads_with(|map, head, goal| {
 5864                movement::up(map, head, goal, false, &text_layout_details)
 5865            })
 5866        })
 5867    }
 5868
 5869    pub fn move_down(&mut self, _: &MoveDown, cx: &mut ViewContext<Self>) {
 5870        self.take_rename(true, cx);
 5871
 5872        if self.mode == EditorMode::SingleLine {
 5873            cx.propagate();
 5874            return;
 5875        }
 5876
 5877        let text_layout_details = &self.text_layout_details(cx);
 5878        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5879            let line_mode = s.line_mode;
 5880            s.move_with(|map, selection| {
 5881                if !selection.is_empty() && !line_mode {
 5882                    selection.goal = SelectionGoal::None;
 5883                }
 5884                let (cursor, goal) = movement::down(
 5885                    map,
 5886                    selection.end,
 5887                    selection.goal,
 5888                    false,
 5889                    &text_layout_details,
 5890                );
 5891                selection.collapse_to(cursor, goal);
 5892            });
 5893        });
 5894    }
 5895
 5896    pub fn move_page_down(&mut self, action: &MovePageDown, cx: &mut ViewContext<Self>) {
 5897        if self.take_rename(true, cx).is_some() {
 5898            return;
 5899        }
 5900
 5901        if self
 5902            .context_menu
 5903            .write()
 5904            .as_mut()
 5905            .map(|menu| menu.select_last(self.project.as_ref(), cx))
 5906            .unwrap_or(false)
 5907        {
 5908            return;
 5909        }
 5910
 5911        if matches!(self.mode, EditorMode::SingleLine) {
 5912            cx.propagate();
 5913            return;
 5914        }
 5915
 5916        let row_count = if let Some(row_count) = self.visible_line_count() {
 5917            row_count as u32 - 1
 5918        } else {
 5919            return;
 5920        };
 5921
 5922        let autoscroll = if action.center_cursor {
 5923            Autoscroll::center()
 5924        } else {
 5925            Autoscroll::fit()
 5926        };
 5927
 5928        let text_layout_details = &self.text_layout_details(cx);
 5929        self.change_selections(Some(autoscroll), cx, |s| {
 5930            let line_mode = s.line_mode;
 5931            s.move_with(|map, selection| {
 5932                if !selection.is_empty() && !line_mode {
 5933                    selection.goal = SelectionGoal::None;
 5934                }
 5935                let (cursor, goal) = movement::down_by_rows(
 5936                    map,
 5937                    selection.end,
 5938                    row_count,
 5939                    selection.goal,
 5940                    false,
 5941                    &text_layout_details,
 5942                );
 5943                selection.collapse_to(cursor, goal);
 5944            });
 5945        });
 5946    }
 5947
 5948    pub fn select_down(&mut self, _: &SelectDown, cx: &mut ViewContext<Self>) {
 5949        let text_layout_details = &self.text_layout_details(cx);
 5950        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5951            s.move_heads_with(|map, head, goal| {
 5952                movement::down(map, head, goal, false, &text_layout_details)
 5953            })
 5954        });
 5955    }
 5956
 5957    //     pub fn context_menu_first(&mut self, _: &ContextMenuFirst, cx: &mut ViewContext<Self>) {
 5958    //         if let Some(context_menu) = self.context_menu.write().as_mut() {
 5959    //             context_menu.select_first(self.project.as_ref(), cx);
 5960    //         }
 5961    //     }
 5962
 5963    //     pub fn context_menu_prev(&mut self, _: &ContextMenuPrev, cx: &mut ViewContext<Self>) {
 5964    //         if let Some(context_menu) = self.context_menu.write().as_mut() {
 5965    //             context_menu.select_prev(self.project.as_ref(), cx);
 5966    //         }
 5967    //     }
 5968
 5969    //     pub fn context_menu_next(&mut self, _: &ContextMenuNext, cx: &mut ViewContext<Self>) {
 5970    //         if let Some(context_menu) = self.context_menu.write().as_mut() {
 5971    //             context_menu.select_next(self.project.as_ref(), cx);
 5972    //         }
 5973    //     }
 5974
 5975    //     pub fn context_menu_last(&mut self, _: &ContextMenuLast, cx: &mut ViewContext<Self>) {
 5976    //         if let Some(context_menu) = self.context_menu.write().as_mut() {
 5977    //             context_menu.select_last(self.project.as_ref(), cx);
 5978    //         }
 5979    //     }
 5980
 5981    pub fn move_to_previous_word_start(
 5982        &mut self,
 5983        _: &MoveToPreviousWordStart,
 5984        cx: &mut ViewContext<Self>,
 5985    ) {
 5986        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5987            s.move_cursors_with(|map, head, _| {
 5988                (
 5989                    movement::previous_word_start(map, head),
 5990                    SelectionGoal::None,
 5991                )
 5992            });
 5993        })
 5994    }
 5995
 5996    pub fn move_to_previous_subword_start(
 5997        &mut self,
 5998        _: &MoveToPreviousSubwordStart,
 5999        cx: &mut ViewContext<Self>,
 6000    ) {
 6001        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6002            s.move_cursors_with(|map, head, _| {
 6003                (
 6004                    movement::previous_subword_start(map, head),
 6005                    SelectionGoal::None,
 6006                )
 6007            });
 6008        })
 6009    }
 6010
 6011    pub fn select_to_previous_word_start(
 6012        &mut self,
 6013        _: &SelectToPreviousWordStart,
 6014        cx: &mut ViewContext<Self>,
 6015    ) {
 6016        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6017            s.move_heads_with(|map, head, _| {
 6018                (
 6019                    movement::previous_word_start(map, head),
 6020                    SelectionGoal::None,
 6021                )
 6022            });
 6023        })
 6024    }
 6025
 6026    pub fn select_to_previous_subword_start(
 6027        &mut self,
 6028        _: &SelectToPreviousSubwordStart,
 6029        cx: &mut ViewContext<Self>,
 6030    ) {
 6031        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6032            s.move_heads_with(|map, head, _| {
 6033                (
 6034                    movement::previous_subword_start(map, head),
 6035                    SelectionGoal::None,
 6036                )
 6037            });
 6038        })
 6039    }
 6040
 6041    pub fn delete_to_previous_word_start(
 6042        &mut self,
 6043        _: &DeleteToPreviousWordStart,
 6044        cx: &mut ViewContext<Self>,
 6045    ) {
 6046        self.transact(cx, |this, cx| {
 6047            this.select_autoclose_pair(cx);
 6048            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6049                let line_mode = s.line_mode;
 6050                s.move_with(|map, selection| {
 6051                    if selection.is_empty() && !line_mode {
 6052                        let cursor = movement::previous_word_start(map, selection.head());
 6053                        selection.set_head(cursor, SelectionGoal::None);
 6054                    }
 6055                });
 6056            });
 6057            this.insert("", cx);
 6058        });
 6059    }
 6060
 6061    pub fn delete_to_previous_subword_start(
 6062        &mut self,
 6063        _: &DeleteToPreviousSubwordStart,
 6064        cx: &mut ViewContext<Self>,
 6065    ) {
 6066        self.transact(cx, |this, cx| {
 6067            this.select_autoclose_pair(cx);
 6068            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6069                let line_mode = s.line_mode;
 6070                s.move_with(|map, selection| {
 6071                    if selection.is_empty() && !line_mode {
 6072                        let cursor = movement::previous_subword_start(map, selection.head());
 6073                        selection.set_head(cursor, SelectionGoal::None);
 6074                    }
 6075                });
 6076            });
 6077            this.insert("", cx);
 6078        });
 6079    }
 6080
 6081    pub fn move_to_next_word_end(&mut self, _: &MoveToNextWordEnd, cx: &mut ViewContext<Self>) {
 6082        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6083            s.move_cursors_with(|map, head, _| {
 6084                (movement::next_word_end(map, head), SelectionGoal::None)
 6085            });
 6086        })
 6087    }
 6088
 6089    pub fn move_to_next_subword_end(
 6090        &mut self,
 6091        _: &MoveToNextSubwordEnd,
 6092        cx: &mut ViewContext<Self>,
 6093    ) {
 6094        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6095            s.move_cursors_with(|map, head, _| {
 6096                (movement::next_subword_end(map, head), SelectionGoal::None)
 6097            });
 6098        })
 6099    }
 6100
 6101    pub fn select_to_next_word_end(&mut self, _: &SelectToNextWordEnd, cx: &mut ViewContext<Self>) {
 6102        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6103            s.move_heads_with(|map, head, _| {
 6104                (movement::next_word_end(map, head), SelectionGoal::None)
 6105            });
 6106        })
 6107    }
 6108
 6109    pub fn select_to_next_subword_end(
 6110        &mut self,
 6111        _: &SelectToNextSubwordEnd,
 6112        cx: &mut ViewContext<Self>,
 6113    ) {
 6114        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6115            s.move_heads_with(|map, head, _| {
 6116                (movement::next_subword_end(map, head), SelectionGoal::None)
 6117            });
 6118        })
 6119    }
 6120
 6121    pub fn delete_to_next_word_end(&mut self, _: &DeleteToNextWordEnd, cx: &mut ViewContext<Self>) {
 6122        self.transact(cx, |this, cx| {
 6123            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6124                let line_mode = s.line_mode;
 6125                s.move_with(|map, selection| {
 6126                    if selection.is_empty() && !line_mode {
 6127                        let cursor = movement::next_word_end(map, selection.head());
 6128                        selection.set_head(cursor, SelectionGoal::None);
 6129                    }
 6130                });
 6131            });
 6132            this.insert("", cx);
 6133        });
 6134    }
 6135
 6136    pub fn delete_to_next_subword_end(
 6137        &mut self,
 6138        _: &DeleteToNextSubwordEnd,
 6139        cx: &mut ViewContext<Self>,
 6140    ) {
 6141        self.transact(cx, |this, cx| {
 6142            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6143                s.move_with(|map, selection| {
 6144                    if selection.is_empty() {
 6145                        let cursor = movement::next_subword_end(map, selection.head());
 6146                        selection.set_head(cursor, SelectionGoal::None);
 6147                    }
 6148                });
 6149            });
 6150            this.insert("", cx);
 6151        });
 6152    }
 6153
 6154    pub fn move_to_beginning_of_line(
 6155        &mut self,
 6156        _: &MoveToBeginningOfLine,
 6157        cx: &mut ViewContext<Self>,
 6158    ) {
 6159        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6160            s.move_cursors_with(|map, head, _| {
 6161                (
 6162                    movement::indented_line_beginning(map, head, true),
 6163                    SelectionGoal::None,
 6164                )
 6165            });
 6166        })
 6167    }
 6168
 6169    pub fn select_to_beginning_of_line(
 6170        &mut self,
 6171        action: &SelectToBeginningOfLine,
 6172        cx: &mut ViewContext<Self>,
 6173    ) {
 6174        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6175            s.move_heads_with(|map, head, _| {
 6176                (
 6177                    movement::indented_line_beginning(map, head, action.stop_at_soft_wraps),
 6178                    SelectionGoal::None,
 6179                )
 6180            });
 6181        });
 6182    }
 6183
 6184    pub fn delete_to_beginning_of_line(
 6185        &mut self,
 6186        _: &DeleteToBeginningOfLine,
 6187        cx: &mut ViewContext<Self>,
 6188    ) {
 6189        self.transact(cx, |this, cx| {
 6190            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6191                s.move_with(|_, selection| {
 6192                    selection.reversed = true;
 6193                });
 6194            });
 6195
 6196            this.select_to_beginning_of_line(
 6197                &SelectToBeginningOfLine {
 6198                    stop_at_soft_wraps: false,
 6199                },
 6200                cx,
 6201            );
 6202            this.backspace(&Backspace, cx);
 6203        });
 6204    }
 6205
 6206    pub fn move_to_end_of_line(&mut self, _: &MoveToEndOfLine, cx: &mut ViewContext<Self>) {
 6207        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6208            s.move_cursors_with(|map, head, _| {
 6209                (movement::line_end(map, head, true), SelectionGoal::None)
 6210            });
 6211        })
 6212    }
 6213
 6214    pub fn select_to_end_of_line(
 6215        &mut self,
 6216        action: &SelectToEndOfLine,
 6217        cx: &mut ViewContext<Self>,
 6218    ) {
 6219        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6220            s.move_heads_with(|map, head, _| {
 6221                (
 6222                    movement::line_end(map, head, action.stop_at_soft_wraps),
 6223                    SelectionGoal::None,
 6224                )
 6225            });
 6226        })
 6227    }
 6228
 6229    pub fn delete_to_end_of_line(&mut self, _: &DeleteToEndOfLine, cx: &mut ViewContext<Self>) {
 6230        self.transact(cx, |this, cx| {
 6231            this.select_to_end_of_line(
 6232                &SelectToEndOfLine {
 6233                    stop_at_soft_wraps: false,
 6234                },
 6235                cx,
 6236            );
 6237            this.delete(&Delete, cx);
 6238        });
 6239    }
 6240
 6241    pub fn cut_to_end_of_line(&mut self, _: &CutToEndOfLine, cx: &mut ViewContext<Self>) {
 6242        self.transact(cx, |this, cx| {
 6243            this.select_to_end_of_line(
 6244                &SelectToEndOfLine {
 6245                    stop_at_soft_wraps: false,
 6246                },
 6247                cx,
 6248            );
 6249            this.cut(&Cut, cx);
 6250        });
 6251    }
 6252
 6253    pub fn move_to_start_of_paragraph(
 6254        &mut self,
 6255        _: &MoveToStartOfParagraph,
 6256        cx: &mut ViewContext<Self>,
 6257    ) {
 6258        if matches!(self.mode, EditorMode::SingleLine) {
 6259            cx.propagate();
 6260            return;
 6261        }
 6262
 6263        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6264            s.move_with(|map, selection| {
 6265                selection.collapse_to(
 6266                    movement::start_of_paragraph(map, selection.head(), 1),
 6267                    SelectionGoal::None,
 6268                )
 6269            });
 6270        })
 6271    }
 6272
 6273    pub fn move_to_end_of_paragraph(
 6274        &mut self,
 6275        _: &MoveToEndOfParagraph,
 6276        cx: &mut ViewContext<Self>,
 6277    ) {
 6278        if matches!(self.mode, EditorMode::SingleLine) {
 6279            cx.propagate();
 6280            return;
 6281        }
 6282
 6283        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6284            s.move_with(|map, selection| {
 6285                selection.collapse_to(
 6286                    movement::end_of_paragraph(map, selection.head(), 1),
 6287                    SelectionGoal::None,
 6288                )
 6289            });
 6290        })
 6291    }
 6292
 6293    pub fn select_to_start_of_paragraph(
 6294        &mut self,
 6295        _: &SelectToStartOfParagraph,
 6296        cx: &mut ViewContext<Self>,
 6297    ) {
 6298        if matches!(self.mode, EditorMode::SingleLine) {
 6299            cx.propagate();
 6300            return;
 6301        }
 6302
 6303        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6304            s.move_heads_with(|map, head, _| {
 6305                (
 6306                    movement::start_of_paragraph(map, head, 1),
 6307                    SelectionGoal::None,
 6308                )
 6309            });
 6310        })
 6311    }
 6312
 6313    pub fn select_to_end_of_paragraph(
 6314        &mut self,
 6315        _: &SelectToEndOfParagraph,
 6316        cx: &mut ViewContext<Self>,
 6317    ) {
 6318        if matches!(self.mode, EditorMode::SingleLine) {
 6319            cx.propagate();
 6320            return;
 6321        }
 6322
 6323        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6324            s.move_heads_with(|map, head, _| {
 6325                (
 6326                    movement::end_of_paragraph(map, head, 1),
 6327                    SelectionGoal::None,
 6328                )
 6329            });
 6330        })
 6331    }
 6332
 6333    pub fn move_to_beginning(&mut self, _: &MoveToBeginning, cx: &mut ViewContext<Self>) {
 6334        if matches!(self.mode, EditorMode::SingleLine) {
 6335            cx.propagate();
 6336            return;
 6337        }
 6338
 6339        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6340            s.select_ranges(vec![0..0]);
 6341        });
 6342    }
 6343
 6344    pub fn select_to_beginning(&mut self, _: &SelectToBeginning, cx: &mut ViewContext<Self>) {
 6345        let mut selection = self.selections.last::<Point>(cx);
 6346        selection.set_head(Point::zero(), SelectionGoal::None);
 6347
 6348        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6349            s.select(vec![selection]);
 6350        });
 6351    }
 6352
 6353    pub fn move_to_end(&mut self, _: &MoveToEnd, cx: &mut ViewContext<Self>) {
 6354        if matches!(self.mode, EditorMode::SingleLine) {
 6355            cx.propagate();
 6356            return;
 6357        }
 6358
 6359        let cursor = self.buffer.read(cx).read(cx).len();
 6360        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6361            s.select_ranges(vec![cursor..cursor])
 6362        });
 6363    }
 6364
 6365    pub fn set_nav_history(&mut self, nav_history: Option<ItemNavHistory>) {
 6366        self.nav_history = nav_history;
 6367    }
 6368
 6369    pub fn nav_history(&self) -> Option<&ItemNavHistory> {
 6370        self.nav_history.as_ref()
 6371    }
 6372
 6373    fn push_to_nav_history(
 6374        &mut self,
 6375        cursor_anchor: Anchor,
 6376        new_position: Option<Point>,
 6377        cx: &mut ViewContext<Self>,
 6378    ) {
 6379        if let Some(nav_history) = self.nav_history.as_mut() {
 6380            let buffer = self.buffer.read(cx).read(cx);
 6381            let cursor_position = cursor_anchor.to_point(&buffer);
 6382            let scroll_state = self.scroll_manager.anchor();
 6383            let scroll_top_row = scroll_state.top_row(&buffer);
 6384            drop(buffer);
 6385
 6386            if let Some(new_position) = new_position {
 6387                let row_delta = (new_position.row as i64 - cursor_position.row as i64).abs();
 6388                if row_delta < MIN_NAVIGATION_HISTORY_ROW_DELTA {
 6389                    return;
 6390                }
 6391            }
 6392
 6393            nav_history.push(
 6394                Some(NavigationData {
 6395                    cursor_anchor,
 6396                    cursor_position,
 6397                    scroll_anchor: scroll_state,
 6398                    scroll_top_row,
 6399                }),
 6400                cx,
 6401            );
 6402        }
 6403    }
 6404
 6405    pub fn select_to_end(&mut self, _: &SelectToEnd, cx: &mut ViewContext<Self>) {
 6406        let buffer = self.buffer.read(cx).snapshot(cx);
 6407        let mut selection = self.selections.first::<usize>(cx);
 6408        selection.set_head(buffer.len(), SelectionGoal::None);
 6409        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6410            s.select(vec![selection]);
 6411        });
 6412    }
 6413
 6414    pub fn select_all(&mut self, _: &SelectAll, cx: &mut ViewContext<Self>) {
 6415        let end = self.buffer.read(cx).read(cx).len();
 6416        self.change_selections(None, cx, |s| {
 6417            s.select_ranges(vec![0..end]);
 6418        });
 6419    }
 6420
 6421    pub fn select_line(&mut self, _: &SelectLine, cx: &mut ViewContext<Self>) {
 6422        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 6423        let mut selections = self.selections.all::<Point>(cx);
 6424        let max_point = display_map.buffer_snapshot.max_point();
 6425        for selection in &mut selections {
 6426            let rows = selection.spanned_rows(true, &display_map);
 6427            selection.start = Point::new(rows.start, 0);
 6428            selection.end = cmp::min(max_point, Point::new(rows.end, 0));
 6429            selection.reversed = false;
 6430        }
 6431        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6432            s.select(selections);
 6433        });
 6434    }
 6435
 6436    pub fn split_selection_into_lines(
 6437        &mut self,
 6438        _: &SplitSelectionIntoLines,
 6439        cx: &mut ViewContext<Self>,
 6440    ) {
 6441        let mut to_unfold = Vec::new();
 6442        let mut new_selection_ranges = Vec::new();
 6443        {
 6444            let selections = self.selections.all::<Point>(cx);
 6445            let buffer = self.buffer.read(cx).read(cx);
 6446            for selection in selections {
 6447                for row in selection.start.row..selection.end.row {
 6448                    let cursor = Point::new(row, buffer.line_len(row));
 6449                    new_selection_ranges.push(cursor..cursor);
 6450                }
 6451                new_selection_ranges.push(selection.end..selection.end);
 6452                to_unfold.push(selection.start..selection.end);
 6453            }
 6454        }
 6455        self.unfold_ranges(to_unfold, true, true, cx);
 6456        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6457            s.select_ranges(new_selection_ranges);
 6458        });
 6459    }
 6460
 6461    pub fn add_selection_above(&mut self, _: &AddSelectionAbove, cx: &mut ViewContext<Self>) {
 6462        self.add_selection(true, cx);
 6463    }
 6464
 6465    pub fn add_selection_below(&mut self, _: &AddSelectionBelow, cx: &mut ViewContext<Self>) {
 6466        self.add_selection(false, cx);
 6467    }
 6468
 6469    fn add_selection(&mut self, above: bool, cx: &mut ViewContext<Self>) {
 6470        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 6471        let mut selections = self.selections.all::<Point>(cx);
 6472        let text_layout_details = self.text_layout_details(cx);
 6473        let mut state = self.add_selections_state.take().unwrap_or_else(|| {
 6474            let oldest_selection = selections.iter().min_by_key(|s| s.id).unwrap().clone();
 6475            let range = oldest_selection.display_range(&display_map).sorted();
 6476
 6477            let start_x = display_map.x_for_point(range.start, &text_layout_details);
 6478            let end_x = display_map.x_for_point(range.end, &text_layout_details);
 6479            let positions = start_x.min(end_x)..start_x.max(end_x);
 6480
 6481            selections.clear();
 6482            let mut stack = Vec::new();
 6483            for row in range.start.row()..=range.end.row() {
 6484                if let Some(selection) = self.selections.build_columnar_selection(
 6485                    &display_map,
 6486                    row,
 6487                    &positions,
 6488                    oldest_selection.reversed,
 6489                    &text_layout_details,
 6490                ) {
 6491                    stack.push(selection.id);
 6492                    selections.push(selection);
 6493                }
 6494            }
 6495
 6496            if above {
 6497                stack.reverse();
 6498            }
 6499
 6500            AddSelectionsState { above, stack }
 6501        });
 6502
 6503        let last_added_selection = *state.stack.last().unwrap();
 6504        let mut new_selections = Vec::new();
 6505        if above == state.above {
 6506            let end_row = if above {
 6507                0
 6508            } else {
 6509                display_map.max_point().row()
 6510            };
 6511
 6512            'outer: for selection in selections {
 6513                if selection.id == last_added_selection {
 6514                    let range = selection.display_range(&display_map).sorted();
 6515                    debug_assert_eq!(range.start.row(), range.end.row());
 6516                    let mut row = range.start.row();
 6517                    let positions = if let SelectionGoal::HorizontalRange { start, end } =
 6518                        selection.goal
 6519                    {
 6520                        px(start)..px(end)
 6521                    } else {
 6522                        let start_x = display_map.x_for_point(range.start, &text_layout_details);
 6523                        let end_x = display_map.x_for_point(range.end, &text_layout_details);
 6524                        start_x.min(end_x)..start_x.max(end_x)
 6525                    };
 6526
 6527                    while row != end_row {
 6528                        if above {
 6529                            row -= 1;
 6530                        } else {
 6531                            row += 1;
 6532                        }
 6533
 6534                        if let Some(new_selection) = self.selections.build_columnar_selection(
 6535                            &display_map,
 6536                            row,
 6537                            &positions,
 6538                            selection.reversed,
 6539                            &text_layout_details,
 6540                        ) {
 6541                            state.stack.push(new_selection.id);
 6542                            if above {
 6543                                new_selections.push(new_selection);
 6544                                new_selections.push(selection);
 6545                            } else {
 6546                                new_selections.push(selection);
 6547                                new_selections.push(new_selection);
 6548                            }
 6549
 6550                            continue 'outer;
 6551                        }
 6552                    }
 6553                }
 6554
 6555                new_selections.push(selection);
 6556            }
 6557        } else {
 6558            new_selections = selections;
 6559            new_selections.retain(|s| s.id != last_added_selection);
 6560            state.stack.pop();
 6561        }
 6562
 6563        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6564            s.select(new_selections);
 6565        });
 6566        if state.stack.len() > 1 {
 6567            self.add_selections_state = Some(state);
 6568        }
 6569    }
 6570
 6571    pub fn select_next_match_internal(
 6572        &mut self,
 6573        display_map: &DisplaySnapshot,
 6574        replace_newest: bool,
 6575        autoscroll: Option<Autoscroll>,
 6576        cx: &mut ViewContext<Self>,
 6577    ) -> Result<()> {
 6578        fn select_next_match_ranges(
 6579            this: &mut Editor,
 6580            range: Range<usize>,
 6581            replace_newest: bool,
 6582            auto_scroll: Option<Autoscroll>,
 6583            cx: &mut ViewContext<Editor>,
 6584        ) {
 6585            this.unfold_ranges([range.clone()], false, true, cx);
 6586            this.change_selections(auto_scroll, cx, |s| {
 6587                if replace_newest {
 6588                    s.delete(s.newest_anchor().id);
 6589                }
 6590                s.insert_range(range.clone());
 6591            });
 6592        }
 6593
 6594        let buffer = &display_map.buffer_snapshot;
 6595        let mut selections = self.selections.all::<usize>(cx);
 6596        if let Some(mut select_next_state) = self.select_next_state.take() {
 6597            let query = &select_next_state.query;
 6598            if !select_next_state.done {
 6599                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
 6600                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
 6601                let mut next_selected_range = None;
 6602
 6603                let bytes_after_last_selection =
 6604                    buffer.bytes_in_range(last_selection.end..buffer.len());
 6605                let bytes_before_first_selection = buffer.bytes_in_range(0..first_selection.start);
 6606                let query_matches = query
 6607                    .stream_find_iter(bytes_after_last_selection)
 6608                    .map(|result| (last_selection.end, result))
 6609                    .chain(
 6610                        query
 6611                            .stream_find_iter(bytes_before_first_selection)
 6612                            .map(|result| (0, result)),
 6613                    );
 6614
 6615                for (start_offset, query_match) in query_matches {
 6616                    let query_match = query_match.unwrap(); // can only fail due to I/O
 6617                    let offset_range =
 6618                        start_offset + query_match.start()..start_offset + query_match.end();
 6619                    let display_range = offset_range.start.to_display_point(&display_map)
 6620                        ..offset_range.end.to_display_point(&display_map);
 6621
 6622                    if !select_next_state.wordwise
 6623                        || (!movement::is_inside_word(&display_map, display_range.start)
 6624                            && !movement::is_inside_word(&display_map, display_range.end))
 6625                    {
 6626                        if selections
 6627                            .iter()
 6628                            .find(|selection| selection.range().overlaps(&offset_range))
 6629                            .is_none()
 6630                        {
 6631                            next_selected_range = Some(offset_range);
 6632                            break;
 6633                        }
 6634                    }
 6635                }
 6636
 6637                if let Some(next_selected_range) = next_selected_range {
 6638                    select_next_match_ranges(
 6639                        self,
 6640                        next_selected_range,
 6641                        replace_newest,
 6642                        autoscroll,
 6643                        cx,
 6644                    );
 6645                } else {
 6646                    select_next_state.done = true;
 6647                }
 6648            }
 6649
 6650            self.select_next_state = Some(select_next_state);
 6651        } else if selections.len() == 1 {
 6652            let selection = selections.last_mut().unwrap();
 6653            if selection.start == selection.end {
 6654                let word_range = movement::surrounding_word(
 6655                    &display_map,
 6656                    selection.start.to_display_point(&display_map),
 6657                );
 6658                selection.start = word_range.start.to_offset(&display_map, Bias::Left);
 6659                selection.end = word_range.end.to_offset(&display_map, Bias::Left);
 6660                selection.goal = SelectionGoal::None;
 6661                selection.reversed = false;
 6662
 6663                let query = buffer
 6664                    .text_for_range(selection.start..selection.end)
 6665                    .collect::<String>();
 6666
 6667                let is_empty = query.is_empty();
 6668                let select_state = SelectNextState {
 6669                    query: AhoCorasick::new(&[query])?,
 6670                    wordwise: true,
 6671                    done: is_empty,
 6672                };
 6673                select_next_match_ranges(
 6674                    self,
 6675                    selection.start..selection.end,
 6676                    replace_newest,
 6677                    autoscroll,
 6678                    cx,
 6679                );
 6680                self.select_next_state = Some(select_state);
 6681            } else {
 6682                let query = buffer
 6683                    .text_for_range(selection.start..selection.end)
 6684                    .collect::<String>();
 6685                self.select_next_state = Some(SelectNextState {
 6686                    query: AhoCorasick::new(&[query])?,
 6687                    wordwise: false,
 6688                    done: false,
 6689                });
 6690                self.select_next_match_internal(display_map, replace_newest, autoscroll, cx)?;
 6691            }
 6692        }
 6693        Ok(())
 6694    }
 6695
 6696    pub fn select_all_matches(
 6697        &mut self,
 6698        action: &SelectAllMatches,
 6699        cx: &mut ViewContext<Self>,
 6700    ) -> Result<()> {
 6701        self.push_to_selection_history();
 6702        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 6703
 6704        loop {
 6705            self.select_next_match_internal(&display_map, action.replace_newest, None, cx)?;
 6706
 6707            if self
 6708                .select_next_state
 6709                .as_ref()
 6710                .map(|selection_state| selection_state.done)
 6711                .unwrap_or(true)
 6712            {
 6713                break;
 6714            }
 6715        }
 6716
 6717        Ok(())
 6718    }
 6719
 6720    pub fn select_next(&mut self, action: &SelectNext, cx: &mut ViewContext<Self>) -> Result<()> {
 6721        self.push_to_selection_history();
 6722        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 6723        self.select_next_match_internal(
 6724            &display_map,
 6725            action.replace_newest,
 6726            Some(Autoscroll::newest()),
 6727            cx,
 6728        )?;
 6729        Ok(())
 6730    }
 6731
 6732    pub fn select_previous(
 6733        &mut self,
 6734        action: &SelectPrevious,
 6735        cx: &mut ViewContext<Self>,
 6736    ) -> Result<()> {
 6737        self.push_to_selection_history();
 6738        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 6739        let buffer = &display_map.buffer_snapshot;
 6740        let mut selections = self.selections.all::<usize>(cx);
 6741        if let Some(mut select_prev_state) = self.select_prev_state.take() {
 6742            let query = &select_prev_state.query;
 6743            if !select_prev_state.done {
 6744                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
 6745                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
 6746                let mut next_selected_range = None;
 6747                // When we're iterating matches backwards, the oldest match will actually be the furthest one in the buffer.
 6748                let bytes_before_last_selection =
 6749                    buffer.reversed_bytes_in_range(0..last_selection.start);
 6750                let bytes_after_first_selection =
 6751                    buffer.reversed_bytes_in_range(first_selection.end..buffer.len());
 6752                let query_matches = query
 6753                    .stream_find_iter(bytes_before_last_selection)
 6754                    .map(|result| (last_selection.start, result))
 6755                    .chain(
 6756                        query
 6757                            .stream_find_iter(bytes_after_first_selection)
 6758                            .map(|result| (buffer.len(), result)),
 6759                    );
 6760                for (end_offset, query_match) in query_matches {
 6761                    let query_match = query_match.unwrap(); // can only fail due to I/O
 6762                    let offset_range =
 6763                        end_offset - query_match.end()..end_offset - query_match.start();
 6764                    let display_range = offset_range.start.to_display_point(&display_map)
 6765                        ..offset_range.end.to_display_point(&display_map);
 6766
 6767                    if !select_prev_state.wordwise
 6768                        || (!movement::is_inside_word(&display_map, display_range.start)
 6769                            && !movement::is_inside_word(&display_map, display_range.end))
 6770                    {
 6771                        next_selected_range = Some(offset_range);
 6772                        break;
 6773                    }
 6774                }
 6775
 6776                if let Some(next_selected_range) = next_selected_range {
 6777                    self.unfold_ranges([next_selected_range.clone()], false, true, cx);
 6778                    self.change_selections(Some(Autoscroll::newest()), cx, |s| {
 6779                        if action.replace_newest {
 6780                            s.delete(s.newest_anchor().id);
 6781                        }
 6782                        s.insert_range(next_selected_range);
 6783                    });
 6784                } else {
 6785                    select_prev_state.done = true;
 6786                }
 6787            }
 6788
 6789            self.select_prev_state = Some(select_prev_state);
 6790        } else if selections.len() == 1 {
 6791            let selection = selections.last_mut().unwrap();
 6792            if selection.start == selection.end {
 6793                let word_range = movement::surrounding_word(
 6794                    &display_map,
 6795                    selection.start.to_display_point(&display_map),
 6796                );
 6797                selection.start = word_range.start.to_offset(&display_map, Bias::Left);
 6798                selection.end = word_range.end.to_offset(&display_map, Bias::Left);
 6799                selection.goal = SelectionGoal::None;
 6800                selection.reversed = false;
 6801
 6802                let query = buffer
 6803                    .text_for_range(selection.start..selection.end)
 6804                    .collect::<String>();
 6805                let query = query.chars().rev().collect::<String>();
 6806                let select_state = SelectNextState {
 6807                    query: AhoCorasick::new(&[query])?,
 6808                    wordwise: true,
 6809                    done: false,
 6810                };
 6811                self.unfold_ranges([selection.start..selection.end], false, true, cx);
 6812                self.change_selections(Some(Autoscroll::newest()), cx, |s| {
 6813                    s.select(selections);
 6814                });
 6815                self.select_prev_state = Some(select_state);
 6816            } else {
 6817                let query = buffer
 6818                    .text_for_range(selection.start..selection.end)
 6819                    .collect::<String>();
 6820                let query = query.chars().rev().collect::<String>();
 6821                self.select_prev_state = Some(SelectNextState {
 6822                    query: AhoCorasick::new(&[query])?,
 6823                    wordwise: false,
 6824                    done: false,
 6825                });
 6826                self.select_previous(action, cx)?;
 6827            }
 6828        }
 6829        Ok(())
 6830    }
 6831
 6832    pub fn toggle_comments(&mut self, action: &ToggleComments, cx: &mut ViewContext<Self>) {
 6833        let text_layout_details = &self.text_layout_details(cx);
 6834        self.transact(cx, |this, cx| {
 6835            let mut selections = this.selections.all::<Point>(cx);
 6836            let mut edits = Vec::new();
 6837            let mut selection_edit_ranges = Vec::new();
 6838            let mut last_toggled_row = None;
 6839            let snapshot = this.buffer.read(cx).read(cx);
 6840            let empty_str: Arc<str> = "".into();
 6841            let mut suffixes_inserted = Vec::new();
 6842
 6843            fn comment_prefix_range(
 6844                snapshot: &MultiBufferSnapshot,
 6845                row: u32,
 6846                comment_prefix: &str,
 6847                comment_prefix_whitespace: &str,
 6848            ) -> Range<Point> {
 6849                let start = Point::new(row, snapshot.indent_size_for_line(row).len);
 6850
 6851                let mut line_bytes = snapshot
 6852                    .bytes_in_range(start..snapshot.max_point())
 6853                    .flatten()
 6854                    .copied();
 6855
 6856                // If this line currently begins with the line comment prefix, then record
 6857                // the range containing the prefix.
 6858                if line_bytes
 6859                    .by_ref()
 6860                    .take(comment_prefix.len())
 6861                    .eq(comment_prefix.bytes())
 6862                {
 6863                    // Include any whitespace that matches the comment prefix.
 6864                    let matching_whitespace_len = line_bytes
 6865                        .zip(comment_prefix_whitespace.bytes())
 6866                        .take_while(|(a, b)| a == b)
 6867                        .count() as u32;
 6868                    let end = Point::new(
 6869                        start.row,
 6870                        start.column + comment_prefix.len() as u32 + matching_whitespace_len,
 6871                    );
 6872                    start..end
 6873                } else {
 6874                    start..start
 6875                }
 6876            }
 6877
 6878            fn comment_suffix_range(
 6879                snapshot: &MultiBufferSnapshot,
 6880                row: u32,
 6881                comment_suffix: &str,
 6882                comment_suffix_has_leading_space: bool,
 6883            ) -> Range<Point> {
 6884                let end = Point::new(row, snapshot.line_len(row));
 6885                let suffix_start_column = end.column.saturating_sub(comment_suffix.len() as u32);
 6886
 6887                let mut line_end_bytes = snapshot
 6888                    .bytes_in_range(Point::new(end.row, suffix_start_column.saturating_sub(1))..end)
 6889                    .flatten()
 6890                    .copied();
 6891
 6892                let leading_space_len = if suffix_start_column > 0
 6893                    && line_end_bytes.next() == Some(b' ')
 6894                    && comment_suffix_has_leading_space
 6895                {
 6896                    1
 6897                } else {
 6898                    0
 6899                };
 6900
 6901                // If this line currently begins with the line comment prefix, then record
 6902                // the range containing the prefix.
 6903                if line_end_bytes.by_ref().eq(comment_suffix.bytes()) {
 6904                    let start = Point::new(end.row, suffix_start_column - leading_space_len);
 6905                    start..end
 6906                } else {
 6907                    end..end
 6908                }
 6909            }
 6910
 6911            // TODO: Handle selections that cross excerpts
 6912            for selection in &mut selections {
 6913                let start_column = snapshot.indent_size_for_line(selection.start.row).len;
 6914                let language = if let Some(language) =
 6915                    snapshot.language_scope_at(Point::new(selection.start.row, start_column))
 6916                {
 6917                    language
 6918                } else {
 6919                    continue;
 6920                };
 6921
 6922                selection_edit_ranges.clear();
 6923
 6924                // If multiple selections contain a given row, avoid processing that
 6925                // row more than once.
 6926                let mut start_row = selection.start.row;
 6927                if last_toggled_row == Some(start_row) {
 6928                    start_row += 1;
 6929                }
 6930                let end_row =
 6931                    if selection.end.row > selection.start.row && selection.end.column == 0 {
 6932                        selection.end.row - 1
 6933                    } else {
 6934                        selection.end.row
 6935                    };
 6936                last_toggled_row = Some(end_row);
 6937
 6938                if start_row > end_row {
 6939                    continue;
 6940                }
 6941
 6942                // If the language has line comments, toggle those.
 6943                if let Some(full_comment_prefix) = language.line_comment_prefix() {
 6944                    // Split the comment prefix's trailing whitespace into a separate string,
 6945                    // as that portion won't be used for detecting if a line is a comment.
 6946                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
 6947                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
 6948                    let mut all_selection_lines_are_comments = true;
 6949
 6950                    for row in start_row..=end_row {
 6951                        if snapshot.is_line_blank(row) && start_row < end_row {
 6952                            continue;
 6953                        }
 6954
 6955                        let prefix_range = comment_prefix_range(
 6956                            snapshot.deref(),
 6957                            row,
 6958                            comment_prefix,
 6959                            comment_prefix_whitespace,
 6960                        );
 6961                        if prefix_range.is_empty() {
 6962                            all_selection_lines_are_comments = false;
 6963                        }
 6964                        selection_edit_ranges.push(prefix_range);
 6965                    }
 6966
 6967                    if all_selection_lines_are_comments {
 6968                        edits.extend(
 6969                            selection_edit_ranges
 6970                                .iter()
 6971                                .cloned()
 6972                                .map(|range| (range, empty_str.clone())),
 6973                        );
 6974                    } else {
 6975                        let min_column = selection_edit_ranges
 6976                            .iter()
 6977                            .map(|r| r.start.column)
 6978                            .min()
 6979                            .unwrap_or(0);
 6980                        edits.extend(selection_edit_ranges.iter().map(|range| {
 6981                            let position = Point::new(range.start.row, min_column);
 6982                            (position..position, full_comment_prefix.clone())
 6983                        }));
 6984                    }
 6985                } else if let Some((full_comment_prefix, comment_suffix)) =
 6986                    language.block_comment_delimiters()
 6987                {
 6988                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
 6989                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
 6990                    let prefix_range = comment_prefix_range(
 6991                        snapshot.deref(),
 6992                        start_row,
 6993                        comment_prefix,
 6994                        comment_prefix_whitespace,
 6995                    );
 6996                    let suffix_range = comment_suffix_range(
 6997                        snapshot.deref(),
 6998                        end_row,
 6999                        comment_suffix.trim_start_matches(' '),
 7000                        comment_suffix.starts_with(' '),
 7001                    );
 7002
 7003                    if prefix_range.is_empty() || suffix_range.is_empty() {
 7004                        edits.push((
 7005                            prefix_range.start..prefix_range.start,
 7006                            full_comment_prefix.clone(),
 7007                        ));
 7008                        edits.push((suffix_range.end..suffix_range.end, comment_suffix.clone()));
 7009                        suffixes_inserted.push((end_row, comment_suffix.len()));
 7010                    } else {
 7011                        edits.push((prefix_range, empty_str.clone()));
 7012                        edits.push((suffix_range, empty_str.clone()));
 7013                    }
 7014                } else {
 7015                    continue;
 7016                }
 7017            }
 7018
 7019            drop(snapshot);
 7020            this.buffer.update(cx, |buffer, cx| {
 7021                buffer.edit(edits, None, cx);
 7022            });
 7023
 7024            // Adjust selections so that they end before any comment suffixes that
 7025            // were inserted.
 7026            let mut suffixes_inserted = suffixes_inserted.into_iter().peekable();
 7027            let mut selections = this.selections.all::<Point>(cx);
 7028            let snapshot = this.buffer.read(cx).read(cx);
 7029            for selection in &mut selections {
 7030                while let Some((row, suffix_len)) = suffixes_inserted.peek().copied() {
 7031                    match row.cmp(&selection.end.row) {
 7032                        Ordering::Less => {
 7033                            suffixes_inserted.next();
 7034                            continue;
 7035                        }
 7036                        Ordering::Greater => break,
 7037                        Ordering::Equal => {
 7038                            if selection.end.column == snapshot.line_len(row) {
 7039                                if selection.is_empty() {
 7040                                    selection.start.column -= suffix_len as u32;
 7041                                }
 7042                                selection.end.column -= suffix_len as u32;
 7043                            }
 7044                            break;
 7045                        }
 7046                    }
 7047                }
 7048            }
 7049
 7050            drop(snapshot);
 7051            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
 7052
 7053            let selections = this.selections.all::<Point>(cx);
 7054            let selections_on_single_row = selections.windows(2).all(|selections| {
 7055                selections[0].start.row == selections[1].start.row
 7056                    && selections[0].end.row == selections[1].end.row
 7057                    && selections[0].start.row == selections[0].end.row
 7058            });
 7059            let selections_selecting = selections
 7060                .iter()
 7061                .any(|selection| selection.start != selection.end);
 7062            let advance_downwards = action.advance_downwards
 7063                && selections_on_single_row
 7064                && !selections_selecting
 7065                && this.mode != EditorMode::SingleLine;
 7066
 7067            if advance_downwards {
 7068                let snapshot = this.buffer.read(cx).snapshot(cx);
 7069
 7070                this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7071                    s.move_cursors_with(|display_snapshot, display_point, _| {
 7072                        let mut point = display_point.to_point(display_snapshot);
 7073                        point.row += 1;
 7074                        point = snapshot.clip_point(point, Bias::Left);
 7075                        let display_point = point.to_display_point(display_snapshot);
 7076                        let goal = SelectionGoal::HorizontalPosition(
 7077                            display_snapshot
 7078                                .x_for_point(display_point, &text_layout_details)
 7079                                .into(),
 7080                        );
 7081                        (display_point, goal)
 7082                    })
 7083                });
 7084            }
 7085        });
 7086    }
 7087
 7088    pub fn select_larger_syntax_node(
 7089        &mut self,
 7090        _: &SelectLargerSyntaxNode,
 7091        cx: &mut ViewContext<Self>,
 7092    ) {
 7093        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 7094        let buffer = self.buffer.read(cx).snapshot(cx);
 7095        let old_selections = self.selections.all::<usize>(cx).into_boxed_slice();
 7096
 7097        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
 7098        let mut selected_larger_node = false;
 7099        let new_selections = old_selections
 7100            .iter()
 7101            .map(|selection| {
 7102                let old_range = selection.start..selection.end;
 7103                let mut new_range = old_range.clone();
 7104                while let Some(containing_range) =
 7105                    buffer.range_for_syntax_ancestor(new_range.clone())
 7106                {
 7107                    new_range = containing_range;
 7108                    if !display_map.intersects_fold(new_range.start)
 7109                        && !display_map.intersects_fold(new_range.end)
 7110                    {
 7111                        break;
 7112                    }
 7113                }
 7114
 7115                selected_larger_node |= new_range != old_range;
 7116                Selection {
 7117                    id: selection.id,
 7118                    start: new_range.start,
 7119                    end: new_range.end,
 7120                    goal: SelectionGoal::None,
 7121                    reversed: selection.reversed,
 7122                }
 7123            })
 7124            .collect::<Vec<_>>();
 7125
 7126        if selected_larger_node {
 7127            stack.push(old_selections);
 7128            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7129                s.select(new_selections);
 7130            });
 7131        }
 7132        self.select_larger_syntax_node_stack = stack;
 7133    }
 7134
 7135    pub fn select_smaller_syntax_node(
 7136        &mut self,
 7137        _: &SelectSmallerSyntaxNode,
 7138        cx: &mut ViewContext<Self>,
 7139    ) {
 7140        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
 7141        if let Some(selections) = stack.pop() {
 7142            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7143                s.select(selections.to_vec());
 7144            });
 7145        }
 7146        self.select_larger_syntax_node_stack = stack;
 7147    }
 7148
 7149    pub fn move_to_enclosing_bracket(
 7150        &mut self,
 7151        _: &MoveToEnclosingBracket,
 7152        cx: &mut ViewContext<Self>,
 7153    ) {
 7154        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7155            s.move_offsets_with(|snapshot, selection| {
 7156                let Some(enclosing_bracket_ranges) =
 7157                    snapshot.enclosing_bracket_ranges(selection.start..selection.end)
 7158                else {
 7159                    return;
 7160                };
 7161
 7162                let mut best_length = usize::MAX;
 7163                let mut best_inside = false;
 7164                let mut best_in_bracket_range = false;
 7165                let mut best_destination = None;
 7166                for (open, close) in enclosing_bracket_ranges {
 7167                    let close = close.to_inclusive();
 7168                    let length = close.end() - open.start;
 7169                    let inside = selection.start >= open.end && selection.end <= *close.start();
 7170                    let in_bracket_range = open.to_inclusive().contains(&selection.head())
 7171                        || close.contains(&selection.head());
 7172
 7173                    // If best is next to a bracket and current isn't, skip
 7174                    if !in_bracket_range && best_in_bracket_range {
 7175                        continue;
 7176                    }
 7177
 7178                    // Prefer smaller lengths unless best is inside and current isn't
 7179                    if length > best_length && (best_inside || !inside) {
 7180                        continue;
 7181                    }
 7182
 7183                    best_length = length;
 7184                    best_inside = inside;
 7185                    best_in_bracket_range = in_bracket_range;
 7186                    best_destination = Some(
 7187                        if close.contains(&selection.start) && close.contains(&selection.end) {
 7188                            if inside {
 7189                                open.end
 7190                            } else {
 7191                                open.start
 7192                            }
 7193                        } else {
 7194                            if inside {
 7195                                *close.start()
 7196                            } else {
 7197                                *close.end()
 7198                            }
 7199                        },
 7200                    );
 7201                }
 7202
 7203                if let Some(destination) = best_destination {
 7204                    selection.collapse_to(destination, SelectionGoal::None);
 7205                }
 7206            })
 7207        });
 7208    }
 7209
 7210    pub fn undo_selection(&mut self, _: &UndoSelection, cx: &mut ViewContext<Self>) {
 7211        self.end_selection(cx);
 7212        self.selection_history.mode = SelectionHistoryMode::Undoing;
 7213        if let Some(entry) = self.selection_history.undo_stack.pop_back() {
 7214            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
 7215            self.select_next_state = entry.select_next_state;
 7216            self.select_prev_state = entry.select_prev_state;
 7217            self.add_selections_state = entry.add_selections_state;
 7218            self.request_autoscroll(Autoscroll::newest(), cx);
 7219        }
 7220        self.selection_history.mode = SelectionHistoryMode::Normal;
 7221    }
 7222
 7223    pub fn redo_selection(&mut self, _: &RedoSelection, cx: &mut ViewContext<Self>) {
 7224        self.end_selection(cx);
 7225        self.selection_history.mode = SelectionHistoryMode::Redoing;
 7226        if let Some(entry) = self.selection_history.redo_stack.pop_back() {
 7227            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
 7228            self.select_next_state = entry.select_next_state;
 7229            self.select_prev_state = entry.select_prev_state;
 7230            self.add_selections_state = entry.add_selections_state;
 7231            self.request_autoscroll(Autoscroll::newest(), cx);
 7232        }
 7233        self.selection_history.mode = SelectionHistoryMode::Normal;
 7234    }
 7235
 7236    fn go_to_diagnostic(&mut self, _: &GoToDiagnostic, cx: &mut ViewContext<Self>) {
 7237        self.go_to_diagnostic_impl(Direction::Next, cx)
 7238    }
 7239
 7240    fn go_to_prev_diagnostic(&mut self, _: &GoToPrevDiagnostic, cx: &mut ViewContext<Self>) {
 7241        self.go_to_diagnostic_impl(Direction::Prev, cx)
 7242    }
 7243
 7244    pub fn go_to_diagnostic_impl(&mut self, direction: Direction, cx: &mut ViewContext<Self>) {
 7245        let buffer = self.buffer.read(cx).snapshot(cx);
 7246        let selection = self.selections.newest::<usize>(cx);
 7247
 7248        // If there is an active Diagnostic Popover. Jump to it's diagnostic instead.
 7249        if direction == Direction::Next {
 7250            if let Some(popover) = self.hover_state.diagnostic_popover.as_ref() {
 7251                let (group_id, jump_to) = popover.activation_info();
 7252                if self.activate_diagnostics(group_id, cx) {
 7253                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7254                        let mut new_selection = s.newest_anchor().clone();
 7255                        new_selection.collapse_to(jump_to, SelectionGoal::None);
 7256                        s.select_anchors(vec![new_selection.clone()]);
 7257                    });
 7258                }
 7259                return;
 7260            }
 7261        }
 7262
 7263        let mut active_primary_range = self.active_diagnostics.as_ref().map(|active_diagnostics| {
 7264            active_diagnostics
 7265                .primary_range
 7266                .to_offset(&buffer)
 7267                .to_inclusive()
 7268        });
 7269        let mut search_start = if let Some(active_primary_range) = active_primary_range.as_ref() {
 7270            if active_primary_range.contains(&selection.head()) {
 7271                *active_primary_range.end()
 7272            } else {
 7273                selection.head()
 7274            }
 7275        } else {
 7276            selection.head()
 7277        };
 7278
 7279        loop {
 7280            let mut diagnostics = if direction == Direction::Prev {
 7281                buffer.diagnostics_in_range::<_, usize>(0..search_start, true)
 7282            } else {
 7283                buffer.diagnostics_in_range::<_, usize>(search_start..buffer.len(), false)
 7284            };
 7285            let group = diagnostics.find_map(|entry| {
 7286                if entry.diagnostic.is_primary
 7287                    && entry.diagnostic.severity <= DiagnosticSeverity::WARNING
 7288                    && !entry.range.is_empty()
 7289                    && Some(entry.range.end) != active_primary_range.as_ref().map(|r| *r.end())
 7290                    && !entry.range.contains(&search_start)
 7291                {
 7292                    Some((entry.range, entry.diagnostic.group_id))
 7293                } else {
 7294                    None
 7295                }
 7296            });
 7297
 7298            if let Some((primary_range, group_id)) = group {
 7299                if self.activate_diagnostics(group_id, cx) {
 7300                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7301                        s.select(vec![Selection {
 7302                            id: selection.id,
 7303                            start: primary_range.start,
 7304                            end: primary_range.start,
 7305                            reversed: false,
 7306                            goal: SelectionGoal::None,
 7307                        }]);
 7308                    });
 7309                }
 7310                break;
 7311            } else {
 7312                // Cycle around to the start of the buffer, potentially moving back to the start of
 7313                // the currently active diagnostic.
 7314                active_primary_range.take();
 7315                if direction == Direction::Prev {
 7316                    if search_start == buffer.len() {
 7317                        break;
 7318                    } else {
 7319                        search_start = buffer.len();
 7320                    }
 7321                } else if search_start == 0 {
 7322                    break;
 7323                } else {
 7324                    search_start = 0;
 7325                }
 7326            }
 7327        }
 7328    }
 7329
 7330    fn go_to_hunk(&mut self, _: &GoToHunk, cx: &mut ViewContext<Self>) {
 7331        let snapshot = self
 7332            .display_map
 7333            .update(cx, |display_map, cx| display_map.snapshot(cx));
 7334        let selection = self.selections.newest::<Point>(cx);
 7335
 7336        if !self.seek_in_direction(
 7337            &snapshot,
 7338            selection.head(),
 7339            false,
 7340            snapshot
 7341                .buffer_snapshot
 7342                .git_diff_hunks_in_range((selection.head().row + 1)..u32::MAX),
 7343            cx,
 7344        ) {
 7345            let wrapped_point = Point::zero();
 7346            self.seek_in_direction(
 7347                &snapshot,
 7348                wrapped_point,
 7349                true,
 7350                snapshot
 7351                    .buffer_snapshot
 7352                    .git_diff_hunks_in_range((wrapped_point.row + 1)..u32::MAX),
 7353                cx,
 7354            );
 7355        }
 7356    }
 7357
 7358    fn go_to_prev_hunk(&mut self, _: &GoToPrevHunk, cx: &mut ViewContext<Self>) {
 7359        let snapshot = self
 7360            .display_map
 7361            .update(cx, |display_map, cx| display_map.snapshot(cx));
 7362        let selection = self.selections.newest::<Point>(cx);
 7363
 7364        if !self.seek_in_direction(
 7365            &snapshot,
 7366            selection.head(),
 7367            false,
 7368            snapshot
 7369                .buffer_snapshot
 7370                .git_diff_hunks_in_range_rev(0..selection.head().row),
 7371            cx,
 7372        ) {
 7373            let wrapped_point = snapshot.buffer_snapshot.max_point();
 7374            self.seek_in_direction(
 7375                &snapshot,
 7376                wrapped_point,
 7377                true,
 7378                snapshot
 7379                    .buffer_snapshot
 7380                    .git_diff_hunks_in_range_rev(0..wrapped_point.row),
 7381                cx,
 7382            );
 7383        }
 7384    }
 7385
 7386    fn seek_in_direction(
 7387        &mut self,
 7388        snapshot: &DisplaySnapshot,
 7389        initial_point: Point,
 7390        is_wrapped: bool,
 7391        hunks: impl Iterator<Item = DiffHunk<u32>>,
 7392        cx: &mut ViewContext<Editor>,
 7393    ) -> bool {
 7394        let display_point = initial_point.to_display_point(snapshot);
 7395        let mut hunks = hunks
 7396            .map(|hunk| diff_hunk_to_display(hunk, &snapshot))
 7397            .filter(|hunk| {
 7398                if is_wrapped {
 7399                    true
 7400                } else {
 7401                    !hunk.contains_display_row(display_point.row())
 7402                }
 7403            })
 7404            .dedup();
 7405
 7406        if let Some(hunk) = hunks.next() {
 7407            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7408                let row = hunk.start_display_row();
 7409                let point = DisplayPoint::new(row, 0);
 7410                s.select_display_ranges([point..point]);
 7411            });
 7412
 7413            true
 7414        } else {
 7415            false
 7416        }
 7417    }
 7418
 7419    pub fn go_to_definition(&mut self, _: &GoToDefinition, cx: &mut ViewContext<Self>) {
 7420        self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, false, cx);
 7421    }
 7422
 7423    pub fn go_to_type_definition(&mut self, _: &GoToTypeDefinition, cx: &mut ViewContext<Self>) {
 7424        self.go_to_definition_of_kind(GotoDefinitionKind::Type, false, cx);
 7425    }
 7426
 7427    pub fn go_to_definition_split(&mut self, _: &GoToDefinitionSplit, cx: &mut ViewContext<Self>) {
 7428        self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, true, cx);
 7429    }
 7430
 7431    pub fn go_to_type_definition_split(
 7432        &mut self,
 7433        _: &GoToTypeDefinitionSplit,
 7434        cx: &mut ViewContext<Self>,
 7435    ) {
 7436        self.go_to_definition_of_kind(GotoDefinitionKind::Type, true, cx);
 7437    }
 7438
 7439    fn go_to_definition_of_kind(
 7440        &mut self,
 7441        kind: GotoDefinitionKind,
 7442        split: bool,
 7443        cx: &mut ViewContext<Self>,
 7444    ) {
 7445        let Some(workspace) = self.workspace() else {
 7446            return;
 7447        };
 7448        let buffer = self.buffer.read(cx);
 7449        let head = self.selections.newest::<usize>(cx).head();
 7450        let (buffer, head) = if let Some(text_anchor) = buffer.text_anchor_for_position(head, cx) {
 7451            text_anchor
 7452        } else {
 7453            return;
 7454        };
 7455
 7456        let project = workspace.read(cx).project().clone();
 7457        let definitions = project.update(cx, |project, cx| match kind {
 7458            GotoDefinitionKind::Symbol => project.definition(&buffer, head, cx),
 7459            GotoDefinitionKind::Type => project.type_definition(&buffer, head, cx),
 7460        });
 7461
 7462        cx.spawn(|editor, mut cx| async move {
 7463            let definitions = definitions.await?;
 7464            editor.update(&mut cx, |editor, cx| {
 7465                editor.navigate_to_definitions(
 7466                    definitions
 7467                        .into_iter()
 7468                        .map(GoToDefinitionLink::Text)
 7469                        .collect(),
 7470                    split,
 7471                    cx,
 7472                );
 7473            })?;
 7474            Ok::<(), anyhow::Error>(())
 7475        })
 7476        .detach_and_log_err(cx);
 7477    }
 7478
 7479    pub fn navigate_to_definitions(
 7480        &mut self,
 7481        mut definitions: Vec<GoToDefinitionLink>,
 7482        split: bool,
 7483        cx: &mut ViewContext<Editor>,
 7484    ) {
 7485        let Some(workspace) = self.workspace() else {
 7486            return;
 7487        };
 7488        let pane = workspace.read(cx).active_pane().clone();
 7489        // If there is one definition, just open it directly
 7490        if definitions.len() == 1 {
 7491            let definition = definitions.pop().unwrap();
 7492            let target_task = match definition {
 7493                GoToDefinitionLink::Text(link) => Task::Ready(Some(Ok(Some(link.target)))),
 7494                GoToDefinitionLink::InlayHint(lsp_location, server_id) => {
 7495                    self.compute_target_location(lsp_location, server_id, cx)
 7496                }
 7497            };
 7498            cx.spawn(|editor, mut cx| async move {
 7499                let target = target_task.await.context("target resolution task")?;
 7500                if let Some(target) = target {
 7501                    editor.update(&mut cx, |editor, cx| {
 7502                        let range = target.range.to_offset(target.buffer.read(cx));
 7503                        let range = editor.range_for_match(&range);
 7504                        if Some(&target.buffer) == editor.buffer.read(cx).as_singleton().as_ref() {
 7505                            editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7506                                s.select_ranges([range]);
 7507                            });
 7508                        } else {
 7509                            cx.window_context().defer(move |cx| {
 7510                                let target_editor: View<Self> =
 7511                                    workspace.update(cx, |workspace, cx| {
 7512                                        if split {
 7513                                            workspace.split_project_item(target.buffer.clone(), cx)
 7514                                        } else {
 7515                                            workspace.open_project_item(target.buffer.clone(), cx)
 7516                                        }
 7517                                    });
 7518                                target_editor.update(cx, |target_editor, cx| {
 7519                                    // When selecting a definition in a different buffer, disable the nav history
 7520                                    // to avoid creating a history entry at the previous cursor location.
 7521                                    pane.update(cx, |pane, _| pane.disable_history());
 7522                                    target_editor.change_selections(
 7523                                        Some(Autoscroll::fit()),
 7524                                        cx,
 7525                                        |s| {
 7526                                            s.select_ranges([range]);
 7527                                        },
 7528                                    );
 7529                                    pane.update(cx, |pane, _| pane.enable_history());
 7530                                });
 7531                            });
 7532                        }
 7533                    })
 7534                } else {
 7535                    Ok(())
 7536                }
 7537            })
 7538            .detach_and_log_err(cx);
 7539        } else if !definitions.is_empty() {
 7540            let replica_id = self.replica_id(cx);
 7541            cx.spawn(|editor, mut cx| async move {
 7542                let (title, location_tasks) = editor
 7543                    .update(&mut cx, |editor, cx| {
 7544                        let title = definitions
 7545                            .iter()
 7546                            .find_map(|definition| match definition {
 7547                                GoToDefinitionLink::Text(link) => {
 7548                                    link.origin.as_ref().map(|origin| {
 7549                                        let buffer = origin.buffer.read(cx);
 7550                                        format!(
 7551                                            "Definitions for {}",
 7552                                            buffer
 7553                                                .text_for_range(origin.range.clone())
 7554                                                .collect::<String>()
 7555                                        )
 7556                                    })
 7557                                }
 7558                                GoToDefinitionLink::InlayHint(_, _) => None,
 7559                            })
 7560                            .unwrap_or("Definitions".to_string());
 7561                        let location_tasks = definitions
 7562                            .into_iter()
 7563                            .map(|definition| match definition {
 7564                                GoToDefinitionLink::Text(link) => {
 7565                                    Task::Ready(Some(Ok(Some(link.target))))
 7566                                }
 7567                                GoToDefinitionLink::InlayHint(lsp_location, server_id) => {
 7568                                    editor.compute_target_location(lsp_location, server_id, cx)
 7569                                }
 7570                            })
 7571                            .collect::<Vec<_>>();
 7572                        (title, location_tasks)
 7573                    })
 7574                    .context("location tasks preparation")?;
 7575
 7576                let locations = futures::future::join_all(location_tasks)
 7577                    .await
 7578                    .into_iter()
 7579                    .filter_map(|location| location.transpose())
 7580                    .collect::<Result<_>>()
 7581                    .context("location tasks")?;
 7582                workspace.update(&mut cx, |workspace, cx| {
 7583                    Self::open_locations_in_multibuffer(
 7584                        workspace, locations, replica_id, title, split, cx,
 7585                    )
 7586                });
 7587
 7588                anyhow::Ok(())
 7589            })
 7590            .detach_and_log_err(cx);
 7591        }
 7592    }
 7593
 7594    fn compute_target_location(
 7595        &self,
 7596        lsp_location: lsp::Location,
 7597        server_id: LanguageServerId,
 7598        cx: &mut ViewContext<Editor>,
 7599    ) -> Task<anyhow::Result<Option<Location>>> {
 7600        let Some(project) = self.project.clone() else {
 7601            return Task::Ready(Some(Ok(None)));
 7602        };
 7603
 7604        cx.spawn(move |editor, mut cx| async move {
 7605            let location_task = editor.update(&mut cx, |editor, cx| {
 7606                project.update(cx, |project, cx| {
 7607                    let language_server_name =
 7608                        editor.buffer.read(cx).as_singleton().and_then(|buffer| {
 7609                            project
 7610                                .language_server_for_buffer(buffer.read(cx), server_id, cx)
 7611                                .map(|(_, lsp_adapter)| {
 7612                                    LanguageServerName(Arc::from(lsp_adapter.name()))
 7613                                })
 7614                        });
 7615                    language_server_name.map(|language_server_name| {
 7616                        project.open_local_buffer_via_lsp(
 7617                            lsp_location.uri.clone(),
 7618                            server_id,
 7619                            language_server_name,
 7620                            cx,
 7621                        )
 7622                    })
 7623                })
 7624            })?;
 7625            let location = match location_task {
 7626                Some(task) => Some({
 7627                    let target_buffer_handle = task.await.context("open local buffer")?;
 7628                    let range = target_buffer_handle.update(&mut cx, |target_buffer, _| {
 7629                        let target_start = target_buffer
 7630                            .clip_point_utf16(point_from_lsp(lsp_location.range.start), Bias::Left);
 7631                        let target_end = target_buffer
 7632                            .clip_point_utf16(point_from_lsp(lsp_location.range.end), Bias::Left);
 7633                        target_buffer.anchor_after(target_start)
 7634                            ..target_buffer.anchor_before(target_end)
 7635                    })?;
 7636                    Location {
 7637                        buffer: target_buffer_handle,
 7638                        range,
 7639                    }
 7640                }),
 7641                None => None,
 7642            };
 7643            Ok(location)
 7644        })
 7645    }
 7646
 7647    //     pub fn find_all_references(
 7648    //         workspace: &mut Workspace,
 7649    //         _: &FindAllReferences,
 7650    //         cx: &mut ViewContext<Workspace>,
 7651    //     ) -> Option<Task<Result<()>>> {
 7652    //         let active_item = workspace.active_item(cx)?;
 7653    //         let editor_handle = active_item.act_as::<Self>(cx)?;
 7654
 7655    //         let editor = editor_handle.read(cx);
 7656    //         let buffer = editor.buffer.read(cx);
 7657    //         let head = editor.selections.newest::<usize>(cx).head();
 7658    //         let (buffer, head) = buffer.text_anchor_for_position(head, cx)?;
 7659    //         let replica_id = editor.replica_id(cx);
 7660
 7661    //         let project = workspace.project().clone();
 7662    //         let references = project.update(cx, |project, cx| project.references(&buffer, head, cx));
 7663    //         Some(cx.spawn_labeled(
 7664    //             "Finding All References...",
 7665    //             |workspace, mut cx| async move {
 7666    //                 let locations = references.await?;
 7667    //                 if locations.is_empty() {
 7668    //                     return Ok(());
 7669    //                 }
 7670
 7671    //                 workspace.update(&mut cx, |workspace, cx| {
 7672    //                     let title = locations
 7673    //                         .first()
 7674    //                         .as_ref()
 7675    //                         .map(|location| {
 7676    //                             let buffer = location.buffer.read(cx);
 7677    //                             format!(
 7678    //                                 "References to `{}`",
 7679    //                                 buffer
 7680    //                                     .text_for_range(location.range.clone())
 7681    //                                     .collect::<String>()
 7682    //                             )
 7683    //                         })
 7684    //                         .unwrap();
 7685    //                     Self::open_locations_in_multibuffer(
 7686    //                         workspace, locations, replica_id, title, false, cx,
 7687    //                     );
 7688    //                 })?;
 7689
 7690    //                 Ok(())
 7691    //             },
 7692    //         ))
 7693    //     }
 7694
 7695    /// Opens a multibuffer with the given project locations in it
 7696    pub fn open_locations_in_multibuffer(
 7697        workspace: &mut Workspace,
 7698        mut locations: Vec<Location>,
 7699        replica_id: ReplicaId,
 7700        title: String,
 7701        split: bool,
 7702        cx: &mut ViewContext<Workspace>,
 7703    ) {
 7704        // If there are multiple definitions, open them in a multibuffer
 7705        locations.sort_by_key(|location| location.buffer.read(cx).remote_id());
 7706        let mut locations = locations.into_iter().peekable();
 7707        let mut ranges_to_highlight = Vec::new();
 7708
 7709        let excerpt_buffer = cx.build_model(|cx| {
 7710            let mut multibuffer = MultiBuffer::new(replica_id);
 7711            while let Some(location) = locations.next() {
 7712                let buffer = location.buffer.read(cx);
 7713                let mut ranges_for_buffer = Vec::new();
 7714                let range = location.range.to_offset(buffer);
 7715                ranges_for_buffer.push(range.clone());
 7716
 7717                while let Some(next_location) = locations.peek() {
 7718                    if next_location.buffer == location.buffer {
 7719                        ranges_for_buffer.push(next_location.range.to_offset(buffer));
 7720                        locations.next();
 7721                    } else {
 7722                        break;
 7723                    }
 7724                }
 7725
 7726                ranges_for_buffer.sort_by_key(|range| (range.start, Reverse(range.end)));
 7727                ranges_to_highlight.extend(multibuffer.push_excerpts_with_context_lines(
 7728                    location.buffer.clone(),
 7729                    ranges_for_buffer,
 7730                    1,
 7731                    cx,
 7732                ))
 7733            }
 7734
 7735            multibuffer.with_title(title)
 7736        });
 7737
 7738        let editor = cx.build_view(|cx| {
 7739            Editor::for_multibuffer(excerpt_buffer, Some(workspace.project().clone()), cx)
 7740        });
 7741        editor.update(cx, |editor, cx| {
 7742            editor.highlight_background::<Self>(
 7743                ranges_to_highlight,
 7744                |theme| todo!("theme.editor.highlighted_line_background"),
 7745                cx,
 7746            );
 7747        });
 7748        if split {
 7749            workspace.split_item(SplitDirection::Right, Box::new(editor), cx);
 7750        } else {
 7751            workspace.add_item(Box::new(editor), cx);
 7752        }
 7753    }
 7754
 7755    // pub fn rename(&mut self, _: &Rename, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
 7756    //     use language::ToOffset as _;
 7757
 7758    //     let project = self.project.clone()?;
 7759    //     let selection = self.selections.newest_anchor().clone();
 7760    //     let (cursor_buffer, cursor_buffer_position) = self
 7761    //         .buffer
 7762    //         .read(cx)
 7763    //         .text_anchor_for_position(selection.head(), cx)?;
 7764    //     let (tail_buffer, _) = self
 7765    //         .buffer
 7766    //         .read(cx)
 7767    //         .text_anchor_for_position(selection.tail(), cx)?;
 7768    //     if tail_buffer != cursor_buffer {
 7769    //         return None;
 7770    //     }
 7771
 7772    //     let snapshot = cursor_buffer.read(cx).snapshot();
 7773    //     let cursor_buffer_offset = cursor_buffer_position.to_offset(&snapshot);
 7774    //     let prepare_rename = project.update(cx, |project, cx| {
 7775    //         project.prepare_rename(cursor_buffer, cursor_buffer_offset, cx)
 7776    //     });
 7777
 7778    //     Some(cx.spawn(|this, mut cx| async move {
 7779    //         let rename_range = if let Some(range) = prepare_rename.await? {
 7780    //             Some(range)
 7781    //         } else {
 7782    //             this.update(&mut cx, |this, cx| {
 7783    //                 let buffer = this.buffer.read(cx).snapshot(cx);
 7784    //                 let mut buffer_highlights = this
 7785    //                     .document_highlights_for_position(selection.head(), &buffer)
 7786    //                     .filter(|highlight| {
 7787    //                         highlight.start.excerpt_id == selection.head().excerpt_id
 7788    //                             && highlight.end.excerpt_id == selection.head().excerpt_id
 7789    //                     });
 7790    //                 buffer_highlights
 7791    //                     .next()
 7792    //                     .map(|highlight| highlight.start.text_anchor..highlight.end.text_anchor)
 7793    //             })?
 7794    //         };
 7795    //         if let Some(rename_range) = rename_range {
 7796    //             let rename_buffer_range = rename_range.to_offset(&snapshot);
 7797    //             let cursor_offset_in_rename_range =
 7798    //                 cursor_buffer_offset.saturating_sub(rename_buffer_range.start);
 7799
 7800    //             this.update(&mut cx, |this, cx| {
 7801    //                 this.take_rename(false, cx);
 7802    //                 let buffer = this.buffer.read(cx).read(cx);
 7803    //                 let cursor_offset = selection.head().to_offset(&buffer);
 7804    //                 let rename_start = cursor_offset.saturating_sub(cursor_offset_in_rename_range);
 7805    //                 let rename_end = rename_start + rename_buffer_range.len();
 7806    //                 let range = buffer.anchor_before(rename_start)..buffer.anchor_after(rename_end);
 7807    //                 let mut old_highlight_id = None;
 7808    //                 let old_name: Arc<str> = buffer
 7809    //                     .chunks(rename_start..rename_end, true)
 7810    //                     .map(|chunk| {
 7811    //                         if old_highlight_id.is_none() {
 7812    //                             old_highlight_id = chunk.syntax_highlight_id;
 7813    //                         }
 7814    //                         chunk.text
 7815    //                     })
 7816    //                     .collect::<String>()
 7817    //                     .into();
 7818
 7819    //                 drop(buffer);
 7820
 7821    //                 // Position the selection in the rename editor so that it matches the current selection.
 7822    //                 this.show_local_selections = false;
 7823    //                 let rename_editor = cx.build_view(|cx| {
 7824    //                     let mut editor = Editor::single_line(cx);
 7825    //                     if let Some(old_highlight_id) = old_highlight_id {
 7826    //                         editor.override_text_style =
 7827    //                             Some(Box::new(move |style| old_highlight_id.style(&style.syntax)));
 7828    //                     }
 7829    //                     editor.buffer.update(cx, |buffer, cx| {
 7830    //                         buffer.edit([(0..0, old_name.clone())], None, cx)
 7831    //                     });
 7832    //                     editor.select_all(&SelectAll, cx);
 7833    //                     editor
 7834    //                 });
 7835
 7836    //                 let ranges = this
 7837    //                     .clear_background_highlights::<DocumentHighlightWrite>(cx)
 7838    //                     .into_iter()
 7839    //                     .flat_map(|(_, ranges)| ranges.into_iter())
 7840    //                     .chain(
 7841    //                         this.clear_background_highlights::<DocumentHighlightRead>(cx)
 7842    //                             .into_iter()
 7843    //                             .flat_map(|(_, ranges)| ranges.into_iter()),
 7844    //                     )
 7845    //                     .collect();
 7846
 7847    //                 this.highlight_text::<Rename>(
 7848    //                     ranges,
 7849    //                     HighlightStyle {
 7850    //                         fade_out: Some(style.rename_fade),
 7851    //                         ..Default::default()
 7852    //                     },
 7853    //                     cx,
 7854    //                 );
 7855    //                 cx.focus(&rename_editor);
 7856    //                 let block_id = this.insert_blocks(
 7857    //                     [BlockProperties {
 7858    //                         style: BlockStyle::Flex,
 7859    //                         position: range.start.clone(),
 7860    //                         height: 1,
 7861    //                         render: Arc::new({
 7862    //                             let editor = rename_editor.clone();
 7863    //                             move |cx: &mut BlockContext| {
 7864    //                                 ChildView::new(&editor, cx)
 7865    //                                     .contained()
 7866    //                                     .with_padding_left(cx.anchor_x)
 7867    //                                     .into_any()
 7868    //                             }
 7869    //                         }),
 7870    //                         disposition: BlockDisposition::Below,
 7871    //                     }],
 7872    //                     Some(Autoscroll::fit()),
 7873    //                     cx,
 7874    //                 )[0];
 7875    //                 this.pending_rename = Some(RenameState {
 7876    //                     range,
 7877    //                     old_name,
 7878    //                     editor: rename_editor,
 7879    //                     block_id,
 7880    //                 });
 7881    //             })?;
 7882    //         }
 7883
 7884    //         Ok(())
 7885    //     }))
 7886    // }
 7887
 7888    //     pub fn confirm_rename(
 7889    //         workspace: &mut Workspace,
 7890    //         _: &ConfirmRename,
 7891    //         cx: &mut ViewContext<Workspace>,
 7892    //     ) -> Option<Task<Result<()>>> {
 7893    //         let editor = workspace.active_item(cx)?.act_as::<Editor>(cx)?;
 7894
 7895    //         let (buffer, range, old_name, new_name) = editor.update(cx, |editor, cx| {
 7896    //             let rename = editor.take_rename(false, cx)?;
 7897    //             let buffer = editor.buffer.read(cx);
 7898    //             let (start_buffer, start) =
 7899    //                 buffer.text_anchor_for_position(rename.range.start.clone(), cx)?;
 7900    //             let (end_buffer, end) =
 7901    //                 buffer.text_anchor_for_position(rename.range.end.clone(), cx)?;
 7902    //             if start_buffer == end_buffer {
 7903    //                 let new_name = rename.editor.read(cx).text(cx);
 7904    //                 Some((start_buffer, start..end, rename.old_name, new_name))
 7905    //             } else {
 7906    //                 None
 7907    //             }
 7908    //         })?;
 7909
 7910    //         let rename = workspace.project().clone().update(cx, |project, cx| {
 7911    //             project.perform_rename(buffer.clone(), range.start, new_name.clone(), true, cx)
 7912    //         });
 7913
 7914    //         let editor = editor.downgrade();
 7915    //         Some(cx.spawn(|workspace, mut cx| async move {
 7916    //             let project_transaction = rename.await?;
 7917    //             Self::open_project_transaction(
 7918    //                 &editor,
 7919    //                 workspace,
 7920    //                 project_transaction,
 7921    //                 format!("Rename: {} → {}", old_name, new_name),
 7922    //                 cx.clone(),
 7923    //             )
 7924    //             .await?;
 7925
 7926    //             editor.update(&mut cx, |editor, cx| {
 7927    //                 editor.refresh_document_highlights(cx);
 7928    //             })?;
 7929    //             Ok(())
 7930    //         }))
 7931    //     }
 7932
 7933    fn take_rename(
 7934        &mut self,
 7935        moving_cursor: bool,
 7936        cx: &mut ViewContext<Self>,
 7937    ) -> Option<RenameState> {
 7938        let rename = self.pending_rename.take()?;
 7939        self.remove_blocks(
 7940            [rename.block_id].into_iter().collect(),
 7941            Some(Autoscroll::fit()),
 7942            cx,
 7943        );
 7944        self.clear_highlights::<Rename>(cx);
 7945        self.show_local_selections = true;
 7946
 7947        if moving_cursor {
 7948            let rename_editor = rename.editor.read(cx);
 7949            let cursor_in_rename_editor = rename_editor.selections.newest::<usize>(cx).head();
 7950
 7951            // Update the selection to match the position of the selection inside
 7952            // the rename editor.
 7953            let snapshot = self.buffer.read(cx).read(cx);
 7954            let rename_range = rename.range.to_offset(&snapshot);
 7955            let cursor_in_editor = snapshot
 7956                .clip_offset(rename_range.start + cursor_in_rename_editor, Bias::Left)
 7957                .min(rename_range.end);
 7958            drop(snapshot);
 7959
 7960            self.change_selections(None, cx, |s| {
 7961                s.select_ranges(vec![cursor_in_editor..cursor_in_editor])
 7962            });
 7963        } else {
 7964            self.refresh_document_highlights(cx);
 7965        }
 7966
 7967        Some(rename)
 7968    }
 7969
 7970    #[cfg(any(test, feature = "test-support"))]
 7971    pub fn pending_rename(&self) -> Option<&RenameState> {
 7972        self.pending_rename.as_ref()
 7973    }
 7974
 7975    fn format(&mut self, _: &Format, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
 7976        let project = match &self.project {
 7977            Some(project) => project.clone(),
 7978            None => return None,
 7979        };
 7980
 7981        Some(self.perform_format(project, FormatTrigger::Manual, cx))
 7982    }
 7983
 7984    fn perform_format(
 7985        &mut self,
 7986        project: Model<Project>,
 7987        trigger: FormatTrigger,
 7988        cx: &mut ViewContext<Self>,
 7989    ) -> Task<Result<()>> {
 7990        let buffer = self.buffer().clone();
 7991        let buffers = buffer.read(cx).all_buffers();
 7992
 7993        let mut timeout = cx.background_executor().timer(FORMAT_TIMEOUT).fuse();
 7994        let format = project.update(cx, |project, cx| project.format(buffers, true, trigger, cx));
 7995
 7996        cx.spawn(|_, mut cx| async move {
 7997            let transaction = futures::select_biased! {
 7998                _ = timeout => {
 7999                    log::warn!("timed out waiting for formatting");
 8000                    None
 8001                }
 8002                transaction = format.log_err().fuse() => transaction,
 8003            };
 8004
 8005            buffer.update(&mut cx, |buffer, cx| {
 8006                if let Some(transaction) = transaction {
 8007                    if !buffer.is_singleton() {
 8008                        buffer.push_transaction(&transaction.0, cx);
 8009                    }
 8010                }
 8011
 8012                cx.notify();
 8013            });
 8014
 8015            Ok(())
 8016        })
 8017    }
 8018
 8019    fn restart_language_server(&mut self, _: &RestartLanguageServer, cx: &mut ViewContext<Self>) {
 8020        if let Some(project) = self.project.clone() {
 8021            self.buffer.update(cx, |multi_buffer, cx| {
 8022                project.update(cx, |project, cx| {
 8023                    project.restart_language_servers_for_buffers(multi_buffer.all_buffers(), cx);
 8024                });
 8025            })
 8026        }
 8027    }
 8028
 8029    fn show_character_palette(&mut self, _: &ShowCharacterPalette, cx: &mut ViewContext<Self>) {
 8030        cx.show_character_palette();
 8031    }
 8032
 8033    fn refresh_active_diagnostics(&mut self, cx: &mut ViewContext<Editor>) {
 8034        if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
 8035            let buffer = self.buffer.read(cx).snapshot(cx);
 8036            let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
 8037            let is_valid = buffer
 8038                .diagnostics_in_range::<_, usize>(active_diagnostics.primary_range.clone(), false)
 8039                .any(|entry| {
 8040                    entry.diagnostic.is_primary
 8041                        && !entry.range.is_empty()
 8042                        && entry.range.start == primary_range_start
 8043                        && entry.diagnostic.message == active_diagnostics.primary_message
 8044                });
 8045
 8046            if is_valid != active_diagnostics.is_valid {
 8047                active_diagnostics.is_valid = is_valid;
 8048                let mut new_styles = HashMap::default();
 8049                for (block_id, diagnostic) in &active_diagnostics.blocks {
 8050                    new_styles.insert(
 8051                        *block_id,
 8052                        diagnostic_block_renderer(diagnostic.clone(), is_valid),
 8053                    );
 8054                }
 8055                self.display_map
 8056                    .update(cx, |display_map, _| display_map.replace_blocks(new_styles));
 8057            }
 8058        }
 8059    }
 8060
 8061    fn activate_diagnostics(&mut self, group_id: usize, cx: &mut ViewContext<Self>) -> bool {
 8062        self.dismiss_diagnostics(cx);
 8063        self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
 8064            let buffer = self.buffer.read(cx).snapshot(cx);
 8065
 8066            let mut primary_range = None;
 8067            let mut primary_message = None;
 8068            let mut group_end = Point::zero();
 8069            let diagnostic_group = buffer
 8070                .diagnostic_group::<Point>(group_id)
 8071                .map(|entry| {
 8072                    if entry.range.end > group_end {
 8073                        group_end = entry.range.end;
 8074                    }
 8075                    if entry.diagnostic.is_primary {
 8076                        primary_range = Some(entry.range.clone());
 8077                        primary_message = Some(entry.diagnostic.message.clone());
 8078                    }
 8079                    entry
 8080                })
 8081                .collect::<Vec<_>>();
 8082            let primary_range = primary_range?;
 8083            let primary_message = primary_message?;
 8084            let primary_range =
 8085                buffer.anchor_after(primary_range.start)..buffer.anchor_before(primary_range.end);
 8086
 8087            let blocks = display_map
 8088                .insert_blocks(
 8089                    diagnostic_group.iter().map(|entry| {
 8090                        let diagnostic = entry.diagnostic.clone();
 8091                        let message_height = diagnostic.message.lines().count() as u8;
 8092                        BlockProperties {
 8093                            style: BlockStyle::Fixed,
 8094                            position: buffer.anchor_after(entry.range.start),
 8095                            height: message_height,
 8096                            render: diagnostic_block_renderer(diagnostic, true),
 8097                            disposition: BlockDisposition::Below,
 8098                        }
 8099                    }),
 8100                    cx,
 8101                )
 8102                .into_iter()
 8103                .zip(diagnostic_group.into_iter().map(|entry| entry.diagnostic))
 8104                .collect();
 8105
 8106            Some(ActiveDiagnosticGroup {
 8107                primary_range,
 8108                primary_message,
 8109                blocks,
 8110                is_valid: true,
 8111            })
 8112        });
 8113        self.active_diagnostics.is_some()
 8114    }
 8115
 8116    fn dismiss_diagnostics(&mut self, cx: &mut ViewContext<Self>) {
 8117        if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
 8118            self.display_map.update(cx, |display_map, cx| {
 8119                display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx);
 8120            });
 8121            cx.notify();
 8122        }
 8123    }
 8124
 8125    pub fn set_selections_from_remote(
 8126        &mut self,
 8127        selections: Vec<Selection<Anchor>>,
 8128        pending_selection: Option<Selection<Anchor>>,
 8129        cx: &mut ViewContext<Self>,
 8130    ) {
 8131        let old_cursor_position = self.selections.newest_anchor().head();
 8132        self.selections.change_with(cx, |s| {
 8133            s.select_anchors(selections);
 8134            if let Some(pending_selection) = pending_selection {
 8135                s.set_pending(pending_selection, SelectMode::Character);
 8136            } else {
 8137                s.clear_pending();
 8138            }
 8139        });
 8140        self.selections_did_change(false, &old_cursor_position, cx);
 8141    }
 8142
 8143    fn push_to_selection_history(&mut self) {
 8144        self.selection_history.push(SelectionHistoryEntry {
 8145            selections: self.selections.disjoint_anchors(),
 8146            select_next_state: self.select_next_state.clone(),
 8147            select_prev_state: self.select_prev_state.clone(),
 8148            add_selections_state: self.add_selections_state.clone(),
 8149        });
 8150    }
 8151
 8152    pub fn transact(
 8153        &mut self,
 8154        cx: &mut ViewContext<Self>,
 8155        update: impl FnOnce(&mut Self, &mut ViewContext<Self>),
 8156    ) -> Option<TransactionId> {
 8157        self.start_transaction_at(Instant::now(), cx);
 8158        update(self, cx);
 8159        self.end_transaction_at(Instant::now(), cx)
 8160    }
 8161
 8162    fn start_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
 8163        self.end_selection(cx);
 8164        if let Some(tx_id) = self
 8165            .buffer
 8166            .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx))
 8167        {
 8168            self.selection_history
 8169                .insert_transaction(tx_id, self.selections.disjoint_anchors());
 8170        }
 8171    }
 8172
 8173    fn end_transaction_at(
 8174        &mut self,
 8175        now: Instant,
 8176        cx: &mut ViewContext<Self>,
 8177    ) -> Option<TransactionId> {
 8178        if let Some(tx_id) = self
 8179            .buffer
 8180            .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
 8181        {
 8182            if let Some((_, end_selections)) = self.selection_history.transaction_mut(tx_id) {
 8183                *end_selections = Some(self.selections.disjoint_anchors());
 8184            } else {
 8185                log::error!("unexpectedly ended a transaction that wasn't started by this editor");
 8186            }
 8187
 8188            cx.emit(Event::Edited);
 8189            Some(tx_id)
 8190        } else {
 8191            None
 8192        }
 8193    }
 8194
 8195    pub fn fold(&mut self, _: &Fold, cx: &mut ViewContext<Self>) {
 8196        let mut fold_ranges = Vec::new();
 8197
 8198        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8199
 8200        let selections = self.selections.all_adjusted(cx);
 8201        for selection in selections {
 8202            let range = selection.range().sorted();
 8203            let buffer_start_row = range.start.row;
 8204
 8205            for row in (0..=range.end.row).rev() {
 8206                let fold_range = display_map.foldable_range(row);
 8207
 8208                if let Some(fold_range) = fold_range {
 8209                    if fold_range.end.row >= buffer_start_row {
 8210                        fold_ranges.push(fold_range);
 8211                        if row <= range.start.row {
 8212                            break;
 8213                        }
 8214                    }
 8215                }
 8216            }
 8217        }
 8218
 8219        self.fold_ranges(fold_ranges, true, cx);
 8220    }
 8221
 8222    pub fn fold_at(&mut self, fold_at: &FoldAt, cx: &mut ViewContext<Self>) {
 8223        let buffer_row = fold_at.buffer_row;
 8224        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8225
 8226        if let Some(fold_range) = display_map.foldable_range(buffer_row) {
 8227            let autoscroll = self
 8228                .selections
 8229                .all::<Point>(cx)
 8230                .iter()
 8231                .any(|selection| fold_range.overlaps(&selection.range()));
 8232
 8233            self.fold_ranges(std::iter::once(fold_range), autoscroll, cx);
 8234        }
 8235    }
 8236
 8237    pub fn unfold_lines(&mut self, _: &UnfoldLines, cx: &mut ViewContext<Self>) {
 8238        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8239        let buffer = &display_map.buffer_snapshot;
 8240        let selections = self.selections.all::<Point>(cx);
 8241        let ranges = selections
 8242            .iter()
 8243            .map(|s| {
 8244                let range = s.display_range(&display_map).sorted();
 8245                let mut start = range.start.to_point(&display_map);
 8246                let mut end = range.end.to_point(&display_map);
 8247                start.column = 0;
 8248                end.column = buffer.line_len(end.row);
 8249                start..end
 8250            })
 8251            .collect::<Vec<_>>();
 8252
 8253        self.unfold_ranges(ranges, true, true, cx);
 8254    }
 8255
 8256    pub fn unfold_at(&mut self, unfold_at: &UnfoldAt, cx: &mut ViewContext<Self>) {
 8257        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8258
 8259        let intersection_range = Point::new(unfold_at.buffer_row, 0)
 8260            ..Point::new(
 8261                unfold_at.buffer_row,
 8262                display_map.buffer_snapshot.line_len(unfold_at.buffer_row),
 8263            );
 8264
 8265        let autoscroll = self
 8266            .selections
 8267            .all::<Point>(cx)
 8268            .iter()
 8269            .any(|selection| selection.range().overlaps(&intersection_range));
 8270
 8271        self.unfold_ranges(std::iter::once(intersection_range), true, autoscroll, cx)
 8272    }
 8273
 8274    pub fn fold_selected_ranges(&mut self, _: &FoldSelectedRanges, cx: &mut ViewContext<Self>) {
 8275        let selections = self.selections.all::<Point>(cx);
 8276        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8277        let line_mode = self.selections.line_mode;
 8278        let ranges = selections.into_iter().map(|s| {
 8279            if line_mode {
 8280                let start = Point::new(s.start.row, 0);
 8281                let end = Point::new(s.end.row, display_map.buffer_snapshot.line_len(s.end.row));
 8282                start..end
 8283            } else {
 8284                s.start..s.end
 8285            }
 8286        });
 8287        self.fold_ranges(ranges, true, cx);
 8288    }
 8289
 8290    pub fn fold_ranges<T: ToOffset + Clone>(
 8291        &mut self,
 8292        ranges: impl IntoIterator<Item = Range<T>>,
 8293        auto_scroll: bool,
 8294        cx: &mut ViewContext<Self>,
 8295    ) {
 8296        let mut ranges = ranges.into_iter().peekable();
 8297        if ranges.peek().is_some() {
 8298            self.display_map.update(cx, |map, cx| map.fold(ranges, cx));
 8299
 8300            if auto_scroll {
 8301                self.request_autoscroll(Autoscroll::fit(), cx);
 8302            }
 8303
 8304            cx.notify();
 8305        }
 8306    }
 8307
 8308    pub fn unfold_ranges<T: ToOffset + Clone>(
 8309        &mut self,
 8310        ranges: impl IntoIterator<Item = Range<T>>,
 8311        inclusive: bool,
 8312        auto_scroll: bool,
 8313        cx: &mut ViewContext<Self>,
 8314    ) {
 8315        let mut ranges = ranges.into_iter().peekable();
 8316        if ranges.peek().is_some() {
 8317            self.display_map
 8318                .update(cx, |map, cx| map.unfold(ranges, inclusive, cx));
 8319            if auto_scroll {
 8320                self.request_autoscroll(Autoscroll::fit(), cx);
 8321            }
 8322
 8323            cx.notify();
 8324        }
 8325    }
 8326
 8327    pub fn set_gutter_hovered(&mut self, hovered: bool, cx: &mut ViewContext<Self>) {
 8328        if hovered != self.gutter_hovered {
 8329            self.gutter_hovered = hovered;
 8330            cx.notify();
 8331        }
 8332    }
 8333
 8334    pub fn insert_blocks(
 8335        &mut self,
 8336        blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
 8337        autoscroll: Option<Autoscroll>,
 8338        cx: &mut ViewContext<Self>,
 8339    ) -> Vec<BlockId> {
 8340        let blocks = self
 8341            .display_map
 8342            .update(cx, |display_map, cx| display_map.insert_blocks(blocks, cx));
 8343        if let Some(autoscroll) = autoscroll {
 8344            self.request_autoscroll(autoscroll, cx);
 8345        }
 8346        blocks
 8347    }
 8348
 8349    pub fn replace_blocks(
 8350        &mut self,
 8351        blocks: HashMap<BlockId, RenderBlock>,
 8352        autoscroll: Option<Autoscroll>,
 8353        cx: &mut ViewContext<Self>,
 8354    ) {
 8355        self.display_map
 8356            .update(cx, |display_map, _| display_map.replace_blocks(blocks));
 8357        if let Some(autoscroll) = autoscroll {
 8358            self.request_autoscroll(autoscroll, cx);
 8359        }
 8360    }
 8361
 8362    pub fn remove_blocks(
 8363        &mut self,
 8364        block_ids: HashSet<BlockId>,
 8365        autoscroll: Option<Autoscroll>,
 8366        cx: &mut ViewContext<Self>,
 8367    ) {
 8368        self.display_map.update(cx, |display_map, cx| {
 8369            display_map.remove_blocks(block_ids, cx)
 8370        });
 8371        if let Some(autoscroll) = autoscroll {
 8372            self.request_autoscroll(autoscroll, cx);
 8373        }
 8374    }
 8375
 8376    pub fn longest_row(&self, cx: &mut AppContext) -> u32 {
 8377        self.display_map
 8378            .update(cx, |map, cx| map.snapshot(cx))
 8379            .longest_row()
 8380    }
 8381
 8382    pub fn max_point(&self, cx: &mut AppContext) -> DisplayPoint {
 8383        self.display_map
 8384            .update(cx, |map, cx| map.snapshot(cx))
 8385            .max_point()
 8386    }
 8387
 8388    pub fn text(&self, cx: &AppContext) -> String {
 8389        self.buffer.read(cx).read(cx).text()
 8390    }
 8391
 8392    pub fn set_text(&mut self, text: impl Into<Arc<str>>, cx: &mut ViewContext<Self>) {
 8393        self.transact(cx, |this, cx| {
 8394            this.buffer
 8395                .read(cx)
 8396                .as_singleton()
 8397                .expect("you can only call set_text on editors for singleton buffers")
 8398                .update(cx, |buffer, cx| buffer.set_text(text, cx));
 8399        });
 8400    }
 8401
 8402    pub fn display_text(&self, cx: &mut AppContext) -> String {
 8403        self.display_map
 8404            .update(cx, |map, cx| map.snapshot(cx))
 8405            .text()
 8406    }
 8407
 8408    pub fn wrap_guides(&self, cx: &AppContext) -> SmallVec<[(usize, bool); 2]> {
 8409        let mut wrap_guides = smallvec::smallvec![];
 8410
 8411        if self.show_wrap_guides == Some(false) {
 8412            return wrap_guides;
 8413        }
 8414
 8415        let settings = self.buffer.read(cx).settings_at(0, cx);
 8416        if settings.show_wrap_guides {
 8417            if let SoftWrap::Column(soft_wrap) = self.soft_wrap_mode(cx) {
 8418                wrap_guides.push((soft_wrap as usize, true));
 8419            }
 8420            wrap_guides.extend(settings.wrap_guides.iter().map(|guide| (*guide, false)))
 8421        }
 8422
 8423        wrap_guides
 8424    }
 8425
 8426    pub fn soft_wrap_mode(&self, cx: &AppContext) -> SoftWrap {
 8427        let settings = self.buffer.read(cx).settings_at(0, cx);
 8428        let mode = self
 8429            .soft_wrap_mode_override
 8430            .unwrap_or_else(|| settings.soft_wrap);
 8431        match mode {
 8432            language_settings::SoftWrap::None => SoftWrap::None,
 8433            language_settings::SoftWrap::EditorWidth => SoftWrap::EditorWidth,
 8434            language_settings::SoftWrap::PreferredLineLength => {
 8435                SoftWrap::Column(settings.preferred_line_length)
 8436            }
 8437        }
 8438    }
 8439
 8440    pub fn set_soft_wrap_mode(
 8441        &mut self,
 8442        mode: language_settings::SoftWrap,
 8443        cx: &mut ViewContext<Self>,
 8444    ) {
 8445        self.soft_wrap_mode_override = Some(mode);
 8446        cx.notify();
 8447    }
 8448
 8449    pub fn set_wrap_width(&self, width: Option<Pixels>, cx: &mut AppContext) -> bool {
 8450        self.display_map
 8451            .update(cx, |map, cx| map.set_wrap_width(width, cx))
 8452    }
 8453
 8454    pub fn toggle_soft_wrap(&mut self, _: &ToggleSoftWrap, cx: &mut ViewContext<Self>) {
 8455        if self.soft_wrap_mode_override.is_some() {
 8456            self.soft_wrap_mode_override.take();
 8457        } else {
 8458            let soft_wrap = match self.soft_wrap_mode(cx) {
 8459                SoftWrap::None => language_settings::SoftWrap::EditorWidth,
 8460                SoftWrap::EditorWidth | SoftWrap::Column(_) => language_settings::SoftWrap::None,
 8461            };
 8462            self.soft_wrap_mode_override = Some(soft_wrap);
 8463        }
 8464        cx.notify();
 8465    }
 8466
 8467    pub fn set_show_gutter(&mut self, show_gutter: bool, cx: &mut ViewContext<Self>) {
 8468        self.show_gutter = show_gutter;
 8469        cx.notify();
 8470    }
 8471
 8472    pub fn set_show_wrap_guides(&mut self, show_gutter: bool, cx: &mut ViewContext<Self>) {
 8473        self.show_wrap_guides = Some(show_gutter);
 8474        cx.notify();
 8475    }
 8476
 8477    pub fn reveal_in_finder(&mut self, _: &RevealInFinder, cx: &mut ViewContext<Self>) {
 8478        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
 8479            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
 8480                cx.reveal_path(&file.abs_path(cx));
 8481            }
 8482        }
 8483    }
 8484
 8485    pub fn copy_path(&mut self, _: &CopyPath, cx: &mut ViewContext<Self>) {
 8486        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
 8487            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
 8488                if let Some(path) = file.abs_path(cx).to_str() {
 8489                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
 8490                }
 8491            }
 8492        }
 8493    }
 8494
 8495    pub fn copy_relative_path(&mut self, _: &CopyRelativePath, cx: &mut ViewContext<Self>) {
 8496        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
 8497            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
 8498                if let Some(path) = file.path().to_str() {
 8499                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
 8500                }
 8501            }
 8502        }
 8503    }
 8504
 8505    pub fn highlight_rows(&mut self, rows: Option<Range<u32>>) {
 8506        self.highlighted_rows = rows;
 8507    }
 8508
 8509    pub fn highlighted_rows(&self) -> Option<Range<u32>> {
 8510        self.highlighted_rows.clone()
 8511    }
 8512
 8513    pub fn highlight_background<T: 'static>(
 8514        &mut self,
 8515        ranges: Vec<Range<Anchor>>,
 8516        color_fetcher: fn(&ThemeColors) -> Hsla,
 8517        cx: &mut ViewContext<Self>,
 8518    ) {
 8519        self.background_highlights
 8520            .insert(TypeId::of::<T>(), (color_fetcher, ranges));
 8521        cx.notify();
 8522    }
 8523
 8524    pub fn highlight_inlay_background<T: 'static>(
 8525        &mut self,
 8526        ranges: Vec<InlayHighlight>,
 8527        color_fetcher: fn(&ThemeColors) -> Hsla,
 8528        cx: &mut ViewContext<Self>,
 8529    ) {
 8530        // TODO: no actual highlights happen for inlays currently, find a way to do that
 8531        self.inlay_background_highlights
 8532            .insert(Some(TypeId::of::<T>()), (color_fetcher, ranges));
 8533        cx.notify();
 8534    }
 8535
 8536    pub fn clear_background_highlights<T: 'static>(
 8537        &mut self,
 8538        cx: &mut ViewContext<Self>,
 8539    ) -> Option<BackgroundHighlight> {
 8540        let text_highlights = self.background_highlights.remove(&TypeId::of::<T>());
 8541        let inlay_highlights = self
 8542            .inlay_background_highlights
 8543            .remove(&Some(TypeId::of::<T>()));
 8544        if text_highlights.is_some() || inlay_highlights.is_some() {
 8545            cx.notify();
 8546        }
 8547        text_highlights
 8548    }
 8549
 8550    #[cfg(feature = "test-support")]
 8551    pub fn all_text_background_highlights(
 8552        &mut self,
 8553        cx: &mut ViewContext<Self>,
 8554    ) -> Vec<(Range<DisplayPoint>, Hsla)> {
 8555        let snapshot = self.snapshot(cx);
 8556        let buffer = &snapshot.buffer_snapshot;
 8557        let start = buffer.anchor_before(0);
 8558        let end = buffer.anchor_after(buffer.len());
 8559        let theme = cx.theme().colors();
 8560        self.background_highlights_in_range(start..end, &snapshot, theme)
 8561    }
 8562
 8563    fn document_highlights_for_position<'a>(
 8564        &'a self,
 8565        position: Anchor,
 8566        buffer: &'a MultiBufferSnapshot,
 8567    ) -> impl 'a + Iterator<Item = &Range<Anchor>> {
 8568        let read_highlights = self
 8569            .background_highlights
 8570            .get(&TypeId::of::<DocumentHighlightRead>())
 8571            .map(|h| &h.1);
 8572        let write_highlights = self
 8573            .background_highlights
 8574            .get(&TypeId::of::<DocumentHighlightWrite>())
 8575            .map(|h| &h.1);
 8576        let left_position = position.bias_left(buffer);
 8577        let right_position = position.bias_right(buffer);
 8578        read_highlights
 8579            .into_iter()
 8580            .chain(write_highlights)
 8581            .flat_map(move |ranges| {
 8582                let start_ix = match ranges.binary_search_by(|probe| {
 8583                    let cmp = probe.end.cmp(&left_position, buffer);
 8584                    if cmp.is_ge() {
 8585                        Ordering::Greater
 8586                    } else {
 8587                        Ordering::Less
 8588                    }
 8589                }) {
 8590                    Ok(i) | Err(i) => i,
 8591                };
 8592
 8593                let right_position = right_position.clone();
 8594                ranges[start_ix..]
 8595                    .iter()
 8596                    .take_while(move |range| range.start.cmp(&right_position, buffer).is_le())
 8597            })
 8598    }
 8599
 8600    pub fn background_highlights_in_range(
 8601        &self,
 8602        search_range: Range<Anchor>,
 8603        display_snapshot: &DisplaySnapshot,
 8604        theme: &ThemeColors,
 8605    ) -> Vec<(Range<DisplayPoint>, Hsla)> {
 8606        let mut results = Vec::new();
 8607        for (color_fetcher, ranges) in self.background_highlights.values() {
 8608            let color = color_fetcher(theme);
 8609            let start_ix = match ranges.binary_search_by(|probe| {
 8610                let cmp = probe
 8611                    .end
 8612                    .cmp(&search_range.start, &display_snapshot.buffer_snapshot);
 8613                if cmp.is_gt() {
 8614                    Ordering::Greater
 8615                } else {
 8616                    Ordering::Less
 8617                }
 8618            }) {
 8619                Ok(i) | Err(i) => i,
 8620            };
 8621            for range in &ranges[start_ix..] {
 8622                if range
 8623                    .start
 8624                    .cmp(&search_range.end, &display_snapshot.buffer_snapshot)
 8625                    .is_ge()
 8626                {
 8627                    break;
 8628                }
 8629
 8630                let start = range.start.to_display_point(&display_snapshot);
 8631                let end = range.end.to_display_point(&display_snapshot);
 8632                results.push((start..end, color))
 8633            }
 8634        }
 8635        results
 8636    }
 8637
 8638    pub fn background_highlight_row_ranges<T: 'static>(
 8639        &self,
 8640        search_range: Range<Anchor>,
 8641        display_snapshot: &DisplaySnapshot,
 8642        count: usize,
 8643    ) -> Vec<RangeInclusive<DisplayPoint>> {
 8644        let mut results = Vec::new();
 8645        let Some((_, ranges)) = self.background_highlights.get(&TypeId::of::<T>()) else {
 8646            return vec![];
 8647        };
 8648
 8649        let start_ix = match ranges.binary_search_by(|probe| {
 8650            let cmp = probe
 8651                .end
 8652                .cmp(&search_range.start, &display_snapshot.buffer_snapshot);
 8653            if cmp.is_gt() {
 8654                Ordering::Greater
 8655            } else {
 8656                Ordering::Less
 8657            }
 8658        }) {
 8659            Ok(i) | Err(i) => i,
 8660        };
 8661        let mut push_region = |start: Option<Point>, end: Option<Point>| {
 8662            if let (Some(start_display), Some(end_display)) = (start, end) {
 8663                results.push(
 8664                    start_display.to_display_point(display_snapshot)
 8665                        ..=end_display.to_display_point(display_snapshot),
 8666                );
 8667            }
 8668        };
 8669        let mut start_row: Option<Point> = None;
 8670        let mut end_row: Option<Point> = None;
 8671        if ranges.len() > count {
 8672            return Vec::new();
 8673        }
 8674        for range in &ranges[start_ix..] {
 8675            if range
 8676                .start
 8677                .cmp(&search_range.end, &display_snapshot.buffer_snapshot)
 8678                .is_ge()
 8679            {
 8680                break;
 8681            }
 8682            let end = range.end.to_point(&display_snapshot.buffer_snapshot);
 8683            if let Some(current_row) = &end_row {
 8684                if end.row == current_row.row {
 8685                    continue;
 8686                }
 8687            }
 8688            let start = range.start.to_point(&display_snapshot.buffer_snapshot);
 8689            if start_row.is_none() {
 8690                assert_eq!(end_row, None);
 8691                start_row = Some(start);
 8692                end_row = Some(end);
 8693                continue;
 8694            }
 8695            if let Some(current_end) = end_row.as_mut() {
 8696                if start.row > current_end.row + 1 {
 8697                    push_region(start_row, end_row);
 8698                    start_row = Some(start);
 8699                    end_row = Some(end);
 8700                } else {
 8701                    // Merge two hunks.
 8702                    *current_end = end;
 8703                }
 8704            } else {
 8705                unreachable!();
 8706            }
 8707        }
 8708        // We might still have a hunk that was not rendered (if there was a search hit on the last line)
 8709        push_region(start_row, end_row);
 8710        results
 8711    }
 8712
 8713    pub fn highlight_text<T: 'static>(
 8714        &mut self,
 8715        ranges: Vec<Range<Anchor>>,
 8716        style: HighlightStyle,
 8717        cx: &mut ViewContext<Self>,
 8718    ) {
 8719        self.display_map.update(cx, |map, _| {
 8720            map.highlight_text(TypeId::of::<T>(), ranges, style)
 8721        });
 8722        cx.notify();
 8723    }
 8724
 8725    pub fn highlight_inlays<T: 'static>(
 8726        &mut self,
 8727        highlights: Vec<InlayHighlight>,
 8728        style: HighlightStyle,
 8729        cx: &mut ViewContext<Self>,
 8730    ) {
 8731        self.display_map.update(cx, |map, _| {
 8732            map.highlight_inlays(TypeId::of::<T>(), highlights, style)
 8733        });
 8734        cx.notify();
 8735    }
 8736
 8737    pub fn text_highlights<'a, T: 'static>(
 8738        &'a self,
 8739        cx: &'a AppContext,
 8740    ) -> Option<(HighlightStyle, &'a [Range<Anchor>])> {
 8741        self.display_map.read(cx).text_highlights(TypeId::of::<T>())
 8742    }
 8743
 8744    pub fn clear_highlights<T: 'static>(&mut self, cx: &mut ViewContext<Self>) {
 8745        let cleared = self
 8746            .display_map
 8747            .update(cx, |map, _| map.clear_highlights(TypeId::of::<T>()));
 8748        if cleared {
 8749            cx.notify();
 8750        }
 8751    }
 8752
 8753    pub fn show_local_cursors(&self, cx: &WindowContext) -> bool {
 8754        self.blink_manager.read(cx).visible() && self.focus_handle.is_focused(cx)
 8755    }
 8756
 8757    fn on_buffer_changed(&mut self, _: Model<MultiBuffer>, cx: &mut ViewContext<Self>) {
 8758        cx.notify();
 8759    }
 8760
 8761    fn on_buffer_event(
 8762        &mut self,
 8763        multibuffer: Model<MultiBuffer>,
 8764        event: &multi_buffer::Event,
 8765        cx: &mut ViewContext<Self>,
 8766    ) {
 8767        match event {
 8768            multi_buffer::Event::Edited {
 8769                sigleton_buffer_edited,
 8770            } => {
 8771                self.refresh_active_diagnostics(cx);
 8772                self.refresh_code_actions(cx);
 8773                if self.has_active_copilot_suggestion(cx) {
 8774                    self.update_visible_copilot_suggestion(cx);
 8775                }
 8776                cx.emit(Event::BufferEdited);
 8777                cx.emit(ItemEvent::Edit);
 8778                cx.emit(ItemEvent::UpdateBreadcrumbs);
 8779                cx.emit(SearchEvent::MatchesInvalidated);
 8780
 8781                if *sigleton_buffer_edited {
 8782                    if let Some(project) = &self.project {
 8783                        let project = project.read(cx);
 8784                        let languages_affected = multibuffer
 8785                            .read(cx)
 8786                            .all_buffers()
 8787                            .into_iter()
 8788                            .filter_map(|buffer| {
 8789                                let buffer = buffer.read(cx);
 8790                                let language = buffer.language()?;
 8791                                if project.is_local()
 8792                                    && project.language_servers_for_buffer(buffer, cx).count() == 0
 8793                                {
 8794                                    None
 8795                                } else {
 8796                                    Some(language)
 8797                                }
 8798                            })
 8799                            .cloned()
 8800                            .collect::<HashSet<_>>();
 8801                        if !languages_affected.is_empty() {
 8802                            self.refresh_inlay_hints(
 8803                                InlayHintRefreshReason::BufferEdited(languages_affected),
 8804                                cx,
 8805                            );
 8806                        }
 8807                    }
 8808                }
 8809            }
 8810            multi_buffer::Event::ExcerptsAdded {
 8811                buffer,
 8812                predecessor,
 8813                excerpts,
 8814            } => {
 8815                cx.emit(Event::ExcerptsAdded {
 8816                    buffer: buffer.clone(),
 8817                    predecessor: *predecessor,
 8818                    excerpts: excerpts.clone(),
 8819                });
 8820                self.refresh_inlay_hints(InlayHintRefreshReason::NewLinesShown, cx);
 8821            }
 8822            multi_buffer::Event::ExcerptsRemoved { ids } => {
 8823                self.refresh_inlay_hints(InlayHintRefreshReason::ExcerptsRemoved(ids.clone()), cx);
 8824                cx.emit(Event::ExcerptsRemoved { ids: ids.clone() })
 8825            }
 8826            multi_buffer::Event::Reparsed => {
 8827                cx.emit(ItemEvent::UpdateBreadcrumbs);
 8828            }
 8829            multi_buffer::Event::DirtyChanged => {
 8830                cx.emit(ItemEvent::UpdateTab);
 8831            }
 8832            multi_buffer::Event::Saved
 8833            | multi_buffer::Event::FileHandleChanged
 8834            | multi_buffer::Event::Reloaded => {
 8835                cx.emit(ItemEvent::UpdateTab);
 8836                cx.emit(ItemEvent::UpdateBreadcrumbs);
 8837            }
 8838            multi_buffer::Event::DiffBaseChanged => cx.emit(Event::DiffBaseChanged),
 8839            multi_buffer::Event::Closed => cx.emit(ItemEvent::CloseItem),
 8840            multi_buffer::Event::DiagnosticsUpdated => {
 8841                self.refresh_active_diagnostics(cx);
 8842            }
 8843            _ => {}
 8844        };
 8845    }
 8846
 8847    fn on_display_map_changed(&mut self, _: Model<DisplayMap>, cx: &mut ViewContext<Self>) {
 8848        cx.notify();
 8849    }
 8850
 8851    fn settings_changed(&mut self, cx: &mut ViewContext<Self>) {
 8852        self.refresh_copilot_suggestions(true, cx);
 8853        self.refresh_inlay_hints(
 8854            InlayHintRefreshReason::SettingsChange(inlay_hint_settings(
 8855                self.selections.newest_anchor().head(),
 8856                &self.buffer.read(cx).snapshot(cx),
 8857                cx,
 8858            )),
 8859            cx,
 8860        );
 8861    }
 8862
 8863    //     pub fn set_searchable(&mut self, searchable: bool) {
 8864    //         self.searchable = searchable;
 8865    //     }
 8866
 8867    //     pub fn searchable(&self) -> bool {
 8868    //         self.searchable
 8869    //     }
 8870
 8871    //     fn open_excerpts(workspace: &mut Workspace, _: &OpenExcerpts, cx: &mut ViewContext<Workspace>) {
 8872    //         let active_item = workspace.active_item(cx);
 8873    //         let editor_handle = if let Some(editor) = active_item
 8874    //             .as_ref()
 8875    //             .and_then(|item| item.act_as::<Self>(cx))
 8876    //         {
 8877    //             editor
 8878    //         } else {
 8879    //             cx.propagate();
 8880    //             return;
 8881    //         };
 8882
 8883    //         let editor = editor_handle.read(cx);
 8884    //         let buffer = editor.buffer.read(cx);
 8885    //         if buffer.is_singleton() {
 8886    //             cx.propagate();
 8887    //             return;
 8888    //         }
 8889
 8890    //         let mut new_selections_by_buffer = HashMap::default();
 8891    //         for selection in editor.selections.all::<usize>(cx) {
 8892    //             for (buffer, mut range, _) in
 8893    //                 buffer.range_to_buffer_ranges(selection.start..selection.end, cx)
 8894    //             {
 8895    //                 if selection.reversed {
 8896    //                     mem::swap(&mut range.start, &mut range.end);
 8897    //                 }
 8898    //                 new_selections_by_buffer
 8899    //                     .entry(buffer)
 8900    //                     .or_insert(Vec::new())
 8901    //                     .push(range)
 8902    //             }
 8903    //         }
 8904
 8905    //         editor_handle.update(cx, |editor, cx| {
 8906    //             editor.push_to_nav_history(editor.selections.newest_anchor().head(), None, cx);
 8907    //         });
 8908    //         let pane = workspace.active_pane().clone();
 8909    //         pane.update(cx, |pane, _| pane.disable_history());
 8910
 8911    //         // We defer the pane interaction because we ourselves are a workspace item
 8912    //         // and activating a new item causes the pane to call a method on us reentrantly,
 8913    //         // which panics if we're on the stack.
 8914    //         cx.defer(move |workspace, cx| {
 8915    //             for (buffer, ranges) in new_selections_by_buffer.into_iter() {
 8916    //                 let editor = workspace.open_project_item::<Self>(buffer, cx);
 8917    //                 editor.update(cx, |editor, cx| {
 8918    //                     editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
 8919    //                         s.select_ranges(ranges);
 8920    //                     });
 8921    //                 });
 8922    //             }
 8923
 8924    //             pane.update(cx, |pane, _| pane.enable_history());
 8925    //         });
 8926    //     }
 8927
 8928    //     fn jump(
 8929    //         workspace: &mut Workspace,
 8930    //         path: ProjectPath,
 8931    //         position: Point,
 8932    //         anchor: language::Anchor,
 8933    //         cx: &mut ViewContext<Workspace>,
 8934    //     ) {
 8935    //         let editor = workspace.open_path(path, None, true, cx);
 8936    //         cx.spawn(|_, mut cx| async move {
 8937    //             let editor = editor
 8938    //                 .await?
 8939    //                 .downcast::<Editor>()
 8940    //                 .ok_or_else(|| anyhow!("opened item was not an editor"))?
 8941    //                 .downgrade();
 8942    //             editor.update(&mut cx, |editor, cx| {
 8943    //                 let buffer = editor
 8944    //                     .buffer()
 8945    //                     .read(cx)
 8946    //                     .as_singleton()
 8947    //                     .ok_or_else(|| anyhow!("cannot jump in a multi-buffer"))?;
 8948    //                 let buffer = buffer.read(cx);
 8949    //                 let cursor = if buffer.can_resolve(&anchor) {
 8950    //                     language::ToPoint::to_point(&anchor, buffer)
 8951    //                 } else {
 8952    //                     buffer.clip_point(position, Bias::Left)
 8953    //                 };
 8954
 8955    //                 let nav_history = editor.nav_history.take();
 8956    //                 editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
 8957    //                     s.select_ranges([cursor..cursor]);
 8958    //                 });
 8959    //                 editor.nav_history = nav_history;
 8960
 8961    //                 anyhow::Ok(())
 8962    //             })??;
 8963
 8964    //             anyhow::Ok(())
 8965    //         })
 8966    //         .detach_and_log_err(cx);
 8967    //     }
 8968
 8969    fn marked_text_ranges(&self, cx: &AppContext) -> Option<Vec<Range<OffsetUtf16>>> {
 8970        let snapshot = self.buffer.read(cx).read(cx);
 8971        let (_, ranges) = self.text_highlights::<InputComposition>(cx)?;
 8972        Some(
 8973            ranges
 8974                .iter()
 8975                .map(move |range| {
 8976                    range.start.to_offset_utf16(&snapshot)..range.end.to_offset_utf16(&snapshot)
 8977                })
 8978                .collect(),
 8979        )
 8980    }
 8981
 8982    fn selection_replacement_ranges(
 8983        &self,
 8984        range: Range<OffsetUtf16>,
 8985        cx: &AppContext,
 8986    ) -> Vec<Range<OffsetUtf16>> {
 8987        let selections = self.selections.all::<OffsetUtf16>(cx);
 8988        let newest_selection = selections
 8989            .iter()
 8990            .max_by_key(|selection| selection.id)
 8991            .unwrap();
 8992        let start_delta = range.start.0 as isize - newest_selection.start.0 as isize;
 8993        let end_delta = range.end.0 as isize - newest_selection.end.0 as isize;
 8994        let snapshot = self.buffer.read(cx).read(cx);
 8995        selections
 8996            .into_iter()
 8997            .map(|mut selection| {
 8998                selection.start.0 =
 8999                    (selection.start.0 as isize).saturating_add(start_delta) as usize;
 9000                selection.end.0 = (selection.end.0 as isize).saturating_add(end_delta) as usize;
 9001                snapshot.clip_offset_utf16(selection.start, Bias::Left)
 9002                    ..snapshot.clip_offset_utf16(selection.end, Bias::Right)
 9003            })
 9004            .collect()
 9005    }
 9006
 9007    fn report_copilot_event(
 9008        &self,
 9009        suggestion_id: Option<String>,
 9010        suggestion_accepted: bool,
 9011        cx: &AppContext,
 9012    ) {
 9013        let Some(project) = &self.project else { return };
 9014
 9015        // If None, we are either getting suggestions in a new, unsaved file, or in a file without an extension
 9016        let file_extension = self
 9017            .buffer
 9018            .read(cx)
 9019            .as_singleton()
 9020            .and_then(|b| b.read(cx).file())
 9021            .and_then(|file| Path::new(file.file_name(cx)).extension())
 9022            .and_then(|e| e.to_str())
 9023            .map(|a| a.to_string());
 9024
 9025        let telemetry = project.read(cx).client().telemetry().clone();
 9026        let telemetry_settings = *TelemetrySettings::get_global(cx);
 9027
 9028        let event = ClickhouseEvent::Copilot {
 9029            suggestion_id,
 9030            suggestion_accepted,
 9031            file_extension,
 9032        };
 9033        telemetry.report_clickhouse_event(event, telemetry_settings);
 9034    }
 9035
 9036    #[cfg(any(test, feature = "test-support"))]
 9037    fn report_editor_event(
 9038        &self,
 9039        _operation: &'static str,
 9040        _file_extension: Option<String>,
 9041        _cx: &AppContext,
 9042    ) {
 9043    }
 9044
 9045    #[cfg(not(any(test, feature = "test-support")))]
 9046    fn report_editor_event(
 9047        &self,
 9048        operation: &'static str,
 9049        file_extension: Option<String>,
 9050        cx: &AppContext,
 9051    ) {
 9052        let Some(project) = &self.project else { return };
 9053
 9054        // If None, we are in a file without an extension
 9055        let file = self
 9056            .buffer
 9057            .read(cx)
 9058            .as_singleton()
 9059            .and_then(|b| b.read(cx).file());
 9060        let file_extension = file_extension.or(file
 9061            .as_ref()
 9062            .and_then(|file| Path::new(file.file_name(cx)).extension())
 9063            .and_then(|e| e.to_str())
 9064            .map(|a| a.to_string()));
 9065
 9066        let vim_mode = cx
 9067            .global::<SettingsStore>()
 9068            .raw_user_settings()
 9069            .get("vim_mode")
 9070            == Some(&serde_json::Value::Bool(true));
 9071        let telemetry_settings = *TelemetrySettings::get_global(cx);
 9072        let copilot_enabled = all_language_settings(file, cx).copilot_enabled(None, None);
 9073        let copilot_enabled_for_language = self
 9074            .buffer
 9075            .read(cx)
 9076            .settings_at(0, cx)
 9077            .show_copilot_suggestions;
 9078
 9079        let telemetry = project.read(cx).client().telemetry().clone();
 9080        let event = ClickhouseEvent::Editor {
 9081            file_extension,
 9082            vim_mode,
 9083            operation,
 9084            copilot_enabled,
 9085            copilot_enabled_for_language,
 9086        };
 9087        telemetry.report_clickhouse_event(event, telemetry_settings)
 9088    }
 9089
 9090    /// Copy the highlighted chunks to the clipboard as JSON. The format is an array of lines,
 9091    /// with each line being an array of {text, highlight} objects.
 9092    fn copy_highlight_json(&mut self, _: &CopyHighlightJson, cx: &mut ViewContext<Self>) {
 9093        let Some(buffer) = self.buffer.read(cx).as_singleton() else {
 9094            return;
 9095        };
 9096
 9097        #[derive(Serialize)]
 9098        struct Chunk<'a> {
 9099            text: String,
 9100            highlight: Option<&'a str>,
 9101        }
 9102
 9103        let snapshot = buffer.read(cx).snapshot();
 9104        let range = self
 9105            .selected_text_range(cx)
 9106            .and_then(|selected_range| {
 9107                if selected_range.is_empty() {
 9108                    None
 9109                } else {
 9110                    Some(selected_range)
 9111                }
 9112            })
 9113            .unwrap_or_else(|| 0..snapshot.len());
 9114
 9115        let chunks = snapshot.chunks(range, true);
 9116        let mut lines = Vec::new();
 9117        let mut line: VecDeque<Chunk> = VecDeque::new();
 9118
 9119        let Some(style) = self.style.as_ref() else {
 9120            return;
 9121        };
 9122
 9123        for chunk in chunks {
 9124            let highlight = chunk
 9125                .syntax_highlight_id
 9126                .and_then(|id| id.name(&style.syntax));
 9127            let mut chunk_lines = chunk.text.split("\n").peekable();
 9128            while let Some(text) = chunk_lines.next() {
 9129                let mut merged_with_last_token = false;
 9130                if let Some(last_token) = line.back_mut() {
 9131                    if last_token.highlight == highlight {
 9132                        last_token.text.push_str(text);
 9133                        merged_with_last_token = true;
 9134                    }
 9135                }
 9136
 9137                if !merged_with_last_token {
 9138                    line.push_back(Chunk {
 9139                        text: text.into(),
 9140                        highlight,
 9141                    });
 9142                }
 9143
 9144                if chunk_lines.peek().is_some() {
 9145                    if line.len() > 1 && line.front().unwrap().text.is_empty() {
 9146                        line.pop_front();
 9147                    }
 9148                    if line.len() > 1 && line.back().unwrap().text.is_empty() {
 9149                        line.pop_back();
 9150                    }
 9151
 9152                    lines.push(mem::take(&mut line));
 9153                }
 9154            }
 9155        }
 9156
 9157        let Some(lines) = serde_json::to_string_pretty(&lines).log_err() else {
 9158            return;
 9159        };
 9160        cx.write_to_clipboard(ClipboardItem::new(lines));
 9161    }
 9162
 9163    pub fn inlay_hint_cache(&self) -> &InlayHintCache {
 9164        &self.inlay_hint_cache
 9165    }
 9166
 9167    pub fn replay_insert_event(
 9168        &mut self,
 9169        text: &str,
 9170        relative_utf16_range: Option<Range<isize>>,
 9171        cx: &mut ViewContext<Self>,
 9172    ) {
 9173        if !self.input_enabled {
 9174            cx.emit(Event::InputIgnored { text: text.into() });
 9175            return;
 9176        }
 9177        if let Some(relative_utf16_range) = relative_utf16_range {
 9178            let selections = self.selections.all::<OffsetUtf16>(cx);
 9179            self.change_selections(None, cx, |s| {
 9180                let new_ranges = selections.into_iter().map(|range| {
 9181                    let start = OffsetUtf16(
 9182                        range
 9183                            .head()
 9184                            .0
 9185                            .saturating_add_signed(relative_utf16_range.start),
 9186                    );
 9187                    let end = OffsetUtf16(
 9188                        range
 9189                            .head()
 9190                            .0
 9191                            .saturating_add_signed(relative_utf16_range.end),
 9192                    );
 9193                    start..end
 9194                });
 9195                s.select_ranges(new_ranges);
 9196            });
 9197        }
 9198
 9199        self.handle_input(text, cx);
 9200    }
 9201
 9202    pub fn supports_inlay_hints(&self, cx: &AppContext) -> bool {
 9203        let Some(project) = self.project.as_ref() else {
 9204            return false;
 9205        };
 9206        let project = project.read(cx);
 9207
 9208        let mut supports = false;
 9209        self.buffer().read(cx).for_each_buffer(|buffer| {
 9210            if !supports {
 9211                supports = project
 9212                    .language_servers_for_buffer(buffer.read(cx), cx)
 9213                    .any(
 9214                        |(_, server)| match server.capabilities().inlay_hint_provider {
 9215                            Some(lsp::OneOf::Left(enabled)) => enabled,
 9216                            Some(lsp::OneOf::Right(_)) => true,
 9217                            None => false,
 9218                        },
 9219                    )
 9220            }
 9221        });
 9222        supports
 9223    }
 9224
 9225    pub fn focus(&self, cx: &mut WindowContext) {
 9226        cx.focus(&self.focus_handle)
 9227    }
 9228
 9229    fn handle_focus_in(&mut self, cx: &mut ViewContext<Self>) {
 9230        if self.focus_handle.is_focused(cx) {
 9231            // todo!()
 9232            // let focused_event = EditorFocused(cx.handle());
 9233            // cx.emit_global(focused_event);
 9234            cx.emit(Event::Focused);
 9235        }
 9236        if let Some(rename) = self.pending_rename.as_ref() {
 9237            let rename_editor_focus_handle = rename.editor.read(cx).focus_handle.clone();
 9238            cx.focus(&rename_editor_focus_handle);
 9239        } else if self.focus_handle.is_focused(cx) {
 9240            self.blink_manager.update(cx, BlinkManager::enable);
 9241            self.buffer.update(cx, |buffer, cx| {
 9242                buffer.finalize_last_transaction(cx);
 9243                if self.leader_peer_id.is_none() {
 9244                    buffer.set_active_selections(
 9245                        &self.selections.disjoint_anchors(),
 9246                        self.selections.line_mode,
 9247                        self.cursor_shape,
 9248                        cx,
 9249                    );
 9250                }
 9251            });
 9252        }
 9253    }
 9254
 9255    fn handle_focus_out(&mut self, cx: &mut ViewContext<Self>) {
 9256        // todo!()
 9257        // let blurred_event = EditorBlurred(cx.handle());
 9258        // cx.emit_global(blurred_event);
 9259        self.blink_manager.update(cx, BlinkManager::disable);
 9260        self.buffer
 9261            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
 9262        self.hide_context_menu(cx);
 9263        hide_hover(self, cx);
 9264        cx.emit(Event::Blurred);
 9265        cx.notify();
 9266    }
 9267}
 9268
 9269pub trait CollaborationHub {
 9270    fn collaborators<'a>(&self, cx: &'a AppContext) -> &'a HashMap<PeerId, Collaborator>;
 9271    fn user_participant_indices<'a>(
 9272        &self,
 9273        cx: &'a AppContext,
 9274    ) -> &'a HashMap<u64, ParticipantIndex>;
 9275}
 9276
 9277impl CollaborationHub for Model<Project> {
 9278    fn collaborators<'a>(&self, cx: &'a AppContext) -> &'a HashMap<PeerId, Collaborator> {
 9279        self.read(cx).collaborators()
 9280    }
 9281
 9282    fn user_participant_indices<'a>(
 9283        &self,
 9284        cx: &'a AppContext,
 9285    ) -> &'a HashMap<u64, ParticipantIndex> {
 9286        self.read(cx).user_store().read(cx).participant_indices()
 9287    }
 9288}
 9289
 9290fn inlay_hint_settings(
 9291    location: Anchor,
 9292    snapshot: &MultiBufferSnapshot,
 9293    cx: &mut ViewContext<'_, Editor>,
 9294) -> InlayHintSettings {
 9295    let file = snapshot.file_at(location);
 9296    let language = snapshot.language_at(location);
 9297    let settings = all_language_settings(file, cx);
 9298    settings
 9299        .language(language.map(|l| l.name()).as_deref())
 9300        .inlay_hints
 9301}
 9302
 9303fn consume_contiguous_rows(
 9304    contiguous_row_selections: &mut Vec<Selection<Point>>,
 9305    selection: &Selection<Point>,
 9306    display_map: &DisplaySnapshot,
 9307    selections: &mut std::iter::Peekable<std::slice::Iter<Selection<Point>>>,
 9308) -> (u32, u32) {
 9309    contiguous_row_selections.push(selection.clone());
 9310    let start_row = selection.start.row;
 9311    let mut end_row = ending_row(selection, display_map);
 9312
 9313    while let Some(next_selection) = selections.peek() {
 9314        if next_selection.start.row <= end_row {
 9315            end_row = ending_row(next_selection, display_map);
 9316            contiguous_row_selections.push(selections.next().unwrap().clone());
 9317        } else {
 9318            break;
 9319        }
 9320    }
 9321    (start_row, end_row)
 9322}
 9323
 9324fn ending_row(next_selection: &Selection<Point>, display_map: &DisplaySnapshot) -> u32 {
 9325    if next_selection.end.column > 0 || next_selection.is_empty() {
 9326        display_map.next_line_boundary(next_selection.end).0.row + 1
 9327    } else {
 9328        next_selection.end.row
 9329    }
 9330}
 9331
 9332impl EditorSnapshot {
 9333    pub fn remote_selections_in_range<'a>(
 9334        &'a self,
 9335        range: &'a Range<Anchor>,
 9336        collaboration_hub: &dyn CollaborationHub,
 9337        cx: &'a AppContext,
 9338    ) -> impl 'a + Iterator<Item = RemoteSelection> {
 9339        let participant_indices = collaboration_hub.user_participant_indices(cx);
 9340        let collaborators_by_peer_id = collaboration_hub.collaborators(cx);
 9341        let collaborators_by_replica_id = collaborators_by_peer_id
 9342            .iter()
 9343            .map(|(_, collaborator)| (collaborator.replica_id, collaborator))
 9344            .collect::<HashMap<_, _>>();
 9345        self.buffer_snapshot
 9346            .remote_selections_in_range(range)
 9347            .filter_map(move |(replica_id, line_mode, cursor_shape, selection)| {
 9348                let collaborator = collaborators_by_replica_id.get(&replica_id)?;
 9349                let participant_index = participant_indices.get(&collaborator.user_id).copied();
 9350                Some(RemoteSelection {
 9351                    replica_id,
 9352                    selection,
 9353                    cursor_shape,
 9354                    line_mode,
 9355                    participant_index,
 9356                    peer_id: collaborator.peer_id,
 9357                })
 9358            })
 9359    }
 9360
 9361    pub fn language_at<T: ToOffset>(&self, position: T) -> Option<&Arc<Language>> {
 9362        self.display_snapshot.buffer_snapshot.language_at(position)
 9363    }
 9364
 9365    pub fn is_focused(&self) -> bool {
 9366        self.is_focused
 9367    }
 9368
 9369    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
 9370        self.placeholder_text.as_ref()
 9371    }
 9372
 9373    pub fn scroll_position(&self) -> gpui::Point<f32> {
 9374        self.scroll_anchor.scroll_position(&self.display_snapshot)
 9375    }
 9376}
 9377
 9378impl Deref for EditorSnapshot {
 9379    type Target = DisplaySnapshot;
 9380
 9381    fn deref(&self) -> &Self::Target {
 9382        &self.display_snapshot
 9383    }
 9384}
 9385
 9386#[derive(Clone, Debug, PartialEq, Eq)]
 9387pub enum Event {
 9388    InputIgnored {
 9389        text: Arc<str>,
 9390    },
 9391    InputHandled {
 9392        utf16_range_to_replace: Option<Range<isize>>,
 9393        text: Arc<str>,
 9394    },
 9395    ExcerptsAdded {
 9396        buffer: Model<Buffer>,
 9397        predecessor: ExcerptId,
 9398        excerpts: Vec<(ExcerptId, ExcerptRange<language::Anchor>)>,
 9399    },
 9400    ExcerptsRemoved {
 9401        ids: Vec<ExcerptId>,
 9402    },
 9403    BufferEdited,
 9404    Edited,
 9405    Focused,
 9406    Blurred,
 9407    DiffBaseChanged,
 9408    SelectionsChanged {
 9409        local: bool,
 9410    },
 9411    ScrollPositionChanged {
 9412        local: bool,
 9413        autoscroll: bool,
 9414    },
 9415}
 9416
 9417pub struct EditorFocused(pub View<Editor>);
 9418pub struct EditorBlurred(pub View<Editor>);
 9419pub struct EditorReleased(pub WeakView<Editor>);
 9420
 9421// impl Entity for Editor {
 9422//     type Event = Event;
 9423
 9424//     fn release(&mut self, cx: &mut AppContext) {
 9425//         cx.emit_global(EditorReleased(self.handle.clone()));
 9426//     }
 9427// }
 9428//
 9429impl EventEmitter<Event> for Editor {}
 9430
 9431impl Render for Editor {
 9432    type Element = EditorElement;
 9433
 9434    fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
 9435        let settings = ThemeSettings::get_global(cx);
 9436        let text_style = match self.mode {
 9437            EditorMode::SingleLine => {
 9438                TextStyle {
 9439                    color: cx.theme().colors().text,
 9440                    font_family: "Zed Sans".into(), // todo!()
 9441                    font_features: FontFeatures::default(),
 9442                    font_size: rems(1.0).into(),
 9443                    font_weight: FontWeight::NORMAL,
 9444                    font_style: FontStyle::Normal,
 9445                    line_height: relative(1.3).into(), // TODO relative(settings.buffer_line_height.value()),
 9446                    underline: None,
 9447                }
 9448            }
 9449
 9450            EditorMode::AutoHeight { max_lines } => todo!(),
 9451
 9452            EditorMode::Full => TextStyle {
 9453                color: cx.theme().colors().text,
 9454                font_family: settings.buffer_font.family.clone(),
 9455                font_features: settings.buffer_font.features,
 9456                font_size: settings.buffer_font_size.into(),
 9457                font_weight: FontWeight::NORMAL,
 9458                font_style: FontStyle::Normal,
 9459                line_height: relative(settings.buffer_line_height.value()),
 9460                underline: None,
 9461            },
 9462        };
 9463
 9464        let background = match self.mode {
 9465            EditorMode::SingleLine => cx.theme().system().transparent,
 9466            EditorMode::AutoHeight { max_lines } => cx.theme().system().transparent,
 9467            EditorMode::Full => cx.theme().colors().editor_background,
 9468        };
 9469
 9470        EditorElement::new(EditorStyle {
 9471            background,
 9472            local_player: cx.theme().players().local(),
 9473            text: text_style,
 9474            scrollbar_width: px(12.),
 9475            syntax: cx.theme().syntax().clone(),
 9476            diagnostic_style: cx.theme().diagnostic_style(),
 9477        })
 9478    }
 9479}
 9480
 9481// impl View for Editor {
 9482//     fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
 9483//         let style = self.style(cx);
 9484//         let font_changed = self.display_map.update(cx, |map, cx| {
 9485//             map.set_fold_ellipses_color(style.folds.ellipses.text_color);
 9486//             map.set_font_with_size(style.text.font_id, style.text.font_size, cx)
 9487//         });
 9488
 9489//         if font_changed {
 9490//             cx.defer(move |editor, cx: &mut ViewContext<Editor>| {
 9491//                 hide_hover(editor, cx);
 9492//                 hide_link_definition(editor, cx);
 9493//             });
 9494//         }
 9495
 9496//         Stack::new()
 9497//             .with_child(EditorElement::new(style.clone()))
 9498//             .with_child(ChildView::new(&self.mouse_context_menu, cx))
 9499//             .into_any()
 9500//     }
 9501
 9502//     fn ui_name() -> &'static str {
 9503//         "Editor"
 9504//     }
 9505
 9506//     fn focus_in(&mut self, focused: AnyView, cx: &mut ViewContext<Self>) {
 9507//         if cx.is_self_focused() {
 9508//             let focused_event = EditorFocused(cx.handle());
 9509//             cx.emit(Event::Focused);
 9510//             cx.emit_global(focused_event);
 9511//         }
 9512//         if let Some(rename) = self.pending_rename.as_ref() {
 9513//             cx.focus(&rename.editor);
 9514//         } else if cx.is_self_focused() || !focused.is::<Editor>() {
 9515//             if !self.focused {
 9516//                 self.blink_manager.update(cx, BlinkManager::enable);
 9517//             }
 9518//             self.focused = true;
 9519//             self.buffer.update(cx, |buffer, cx| {
 9520//                 buffer.finalize_last_transaction(cx);
 9521//                 if self.leader_peer_id.is_none() {
 9522//                     buffer.set_active_selections(
 9523//                         &self.selections.disjoint_anchors(),
 9524//                         self.selections.line_mode,
 9525//                         self.cursor_shape,
 9526//                         cx,
 9527//                     );
 9528//                 }
 9529//             });
 9530//         }
 9531//     }
 9532
 9533//     fn focus_out(&mut self, _: AnyView, cx: &mut ViewContext<Self>) {
 9534//         let blurred_event = EditorBlurred(cx.handle());
 9535//         cx.emit_global(blurred_event);
 9536//         self.focused = false;
 9537//         self.blink_manager.update(cx, BlinkManager::disable);
 9538//         self.buffer
 9539//             .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
 9540//         self.hide_context_menu(cx);
 9541//         hide_hover(self, cx);
 9542//         cx.emit(Event::Blurred);
 9543//         cx.notify();
 9544//     }
 9545
 9546//     fn modifiers_changed(
 9547//         &mut self,
 9548//         event: &gpui::platform::ModifiersChangedEvent,
 9549//         cx: &mut ViewContext<Self>,
 9550//     ) -> bool {
 9551//         let pending_selection = self.has_pending_selection();
 9552
 9553//         if let Some(point) = &self.link_go_to_definition_state.last_trigger_point {
 9554//             if event.cmd && !pending_selection {
 9555//                 let point = point.clone();
 9556//                 let snapshot = self.snapshot(cx);
 9557//                 let kind = point.definition_kind(event.shift);
 9558
 9559//                 show_link_definition(kind, self, point, snapshot, cx);
 9560//                 return false;
 9561//             }
 9562//         }
 9563
 9564//         {
 9565//             if self.link_go_to_definition_state.symbol_range.is_some()
 9566//                 || !self.link_go_to_definition_state.definitions.is_empty()
 9567//             {
 9568//                 self.link_go_to_definition_state.symbol_range.take();
 9569//                 self.link_go_to_definition_state.definitions.clear();
 9570//                 cx.notify();
 9571//             }
 9572
 9573//             self.link_go_to_definition_state.task = None;
 9574
 9575//             self.clear_highlights::<LinkGoToDefinitionState>(cx);
 9576//         }
 9577
 9578//         false
 9579//     }
 9580
 9581impl InputHandler for Editor {
 9582    fn text_for_range(
 9583        &mut self,
 9584        range_utf16: Range<usize>,
 9585        cx: &mut ViewContext<Self>,
 9586    ) -> Option<String> {
 9587        Some(
 9588            self.buffer
 9589                .read(cx)
 9590                .read(cx)
 9591                .text_for_range(OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end))
 9592                .collect(),
 9593        )
 9594    }
 9595
 9596    fn selected_text_range(&mut self, cx: &mut ViewContext<Self>) -> Option<Range<usize>> {
 9597        // Prevent the IME menu from appearing when holding down an alphabetic key
 9598        // while input is disabled.
 9599        if !self.input_enabled {
 9600            return None;
 9601        }
 9602
 9603        let range = self.selections.newest::<OffsetUtf16>(cx).range();
 9604        Some(range.start.0..range.end.0)
 9605    }
 9606
 9607    fn marked_text_range(&self, cx: &mut ViewContext<Self>) -> Option<Range<usize>> {
 9608        let snapshot = self.buffer.read(cx).read(cx);
 9609        let range = self.text_highlights::<InputComposition>(cx)?.1.get(0)?;
 9610        Some(range.start.to_offset_utf16(&snapshot).0..range.end.to_offset_utf16(&snapshot).0)
 9611    }
 9612
 9613    fn unmark_text(&mut self, cx: &mut ViewContext<Self>) {
 9614        self.clear_highlights::<InputComposition>(cx);
 9615        self.ime_transaction.take();
 9616    }
 9617
 9618    fn replace_text_in_range(
 9619        &mut self,
 9620        range_utf16: Option<Range<usize>>,
 9621        text: &str,
 9622        cx: &mut ViewContext<Self>,
 9623    ) {
 9624        if !self.input_enabled {
 9625            cx.emit(Event::InputIgnored { text: text.into() });
 9626            return;
 9627        }
 9628
 9629        self.transact(cx, |this, cx| {
 9630            let new_selected_ranges = if let Some(range_utf16) = range_utf16 {
 9631                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
 9632                Some(this.selection_replacement_ranges(range_utf16, cx))
 9633            } else {
 9634                this.marked_text_ranges(cx)
 9635            };
 9636
 9637            let range_to_replace = new_selected_ranges.as_ref().and_then(|ranges_to_replace| {
 9638                let newest_selection_id = this.selections.newest_anchor().id;
 9639                this.selections
 9640                    .all::<OffsetUtf16>(cx)
 9641                    .iter()
 9642                    .zip(ranges_to_replace.iter())
 9643                    .find_map(|(selection, range)| {
 9644                        if selection.id == newest_selection_id {
 9645                            Some(
 9646                                (range.start.0 as isize - selection.head().0 as isize)
 9647                                    ..(range.end.0 as isize - selection.head().0 as isize),
 9648                            )
 9649                        } else {
 9650                            None
 9651                        }
 9652                    })
 9653            });
 9654
 9655            cx.emit(Event::InputHandled {
 9656                utf16_range_to_replace: range_to_replace,
 9657                text: text.into(),
 9658            });
 9659
 9660            if let Some(new_selected_ranges) = new_selected_ranges {
 9661                this.change_selections(None, cx, |selections| {
 9662                    selections.select_ranges(new_selected_ranges)
 9663                });
 9664            }
 9665
 9666            this.handle_input(text, cx);
 9667        });
 9668
 9669        if let Some(transaction) = self.ime_transaction {
 9670            self.buffer.update(cx, |buffer, cx| {
 9671                buffer.group_until_transaction(transaction, cx);
 9672            });
 9673        }
 9674
 9675        self.unmark_text(cx);
 9676    }
 9677
 9678    fn replace_and_mark_text_in_range(
 9679        &mut self,
 9680        range_utf16: Option<Range<usize>>,
 9681        text: &str,
 9682        new_selected_range_utf16: Option<Range<usize>>,
 9683        cx: &mut ViewContext<Self>,
 9684    ) {
 9685        if !self.input_enabled {
 9686            cx.emit(Event::InputIgnored { text: text.into() });
 9687            return;
 9688        }
 9689
 9690        let transaction = self.transact(cx, |this, cx| {
 9691            let ranges_to_replace = if let Some(mut marked_ranges) = this.marked_text_ranges(cx) {
 9692                let snapshot = this.buffer.read(cx).read(cx);
 9693                if let Some(relative_range_utf16) = range_utf16.as_ref() {
 9694                    for marked_range in &mut marked_ranges {
 9695                        marked_range.end.0 = marked_range.start.0 + relative_range_utf16.end;
 9696                        marked_range.start.0 += relative_range_utf16.start;
 9697                        marked_range.start =
 9698                            snapshot.clip_offset_utf16(marked_range.start, Bias::Left);
 9699                        marked_range.end =
 9700                            snapshot.clip_offset_utf16(marked_range.end, Bias::Right);
 9701                    }
 9702                }
 9703                Some(marked_ranges)
 9704            } else if let Some(range_utf16) = range_utf16 {
 9705                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
 9706                Some(this.selection_replacement_ranges(range_utf16, cx))
 9707            } else {
 9708                None
 9709            };
 9710
 9711            let range_to_replace = ranges_to_replace.as_ref().and_then(|ranges_to_replace| {
 9712                let newest_selection_id = this.selections.newest_anchor().id;
 9713                this.selections
 9714                    .all::<OffsetUtf16>(cx)
 9715                    .iter()
 9716                    .zip(ranges_to_replace.iter())
 9717                    .find_map(|(selection, range)| {
 9718                        if selection.id == newest_selection_id {
 9719                            Some(
 9720                                (range.start.0 as isize - selection.head().0 as isize)
 9721                                    ..(range.end.0 as isize - selection.head().0 as isize),
 9722                            )
 9723                        } else {
 9724                            None
 9725                        }
 9726                    })
 9727            });
 9728
 9729            cx.emit(Event::InputHandled {
 9730                utf16_range_to_replace: range_to_replace,
 9731                text: text.into(),
 9732            });
 9733
 9734            if let Some(ranges) = ranges_to_replace {
 9735                this.change_selections(None, cx, |s| s.select_ranges(ranges));
 9736            }
 9737
 9738            let marked_ranges = {
 9739                let snapshot = this.buffer.read(cx).read(cx);
 9740                this.selections
 9741                    .disjoint_anchors()
 9742                    .iter()
 9743                    .map(|selection| {
 9744                        selection.start.bias_left(&*snapshot)..selection.end.bias_right(&*snapshot)
 9745                    })
 9746                    .collect::<Vec<_>>()
 9747            };
 9748
 9749            if text.is_empty() {
 9750                this.unmark_text(cx);
 9751            } else {
 9752                this.highlight_text::<InputComposition>(
 9753                    marked_ranges.clone(),
 9754                    HighlightStyle::default(), // todo!() this.style(cx).composition_mark,
 9755                    cx,
 9756                );
 9757            }
 9758
 9759            this.handle_input(text, cx);
 9760
 9761            if let Some(new_selected_range) = new_selected_range_utf16 {
 9762                let snapshot = this.buffer.read(cx).read(cx);
 9763                let new_selected_ranges = marked_ranges
 9764                    .into_iter()
 9765                    .map(|marked_range| {
 9766                        let insertion_start = marked_range.start.to_offset_utf16(&snapshot).0;
 9767                        let new_start = OffsetUtf16(new_selected_range.start + insertion_start);
 9768                        let new_end = OffsetUtf16(new_selected_range.end + insertion_start);
 9769                        snapshot.clip_offset_utf16(new_start, Bias::Left)
 9770                            ..snapshot.clip_offset_utf16(new_end, Bias::Right)
 9771                    })
 9772                    .collect::<Vec<_>>();
 9773
 9774                drop(snapshot);
 9775                this.change_selections(None, cx, |selections| {
 9776                    selections.select_ranges(new_selected_ranges)
 9777                });
 9778            }
 9779        });
 9780
 9781        self.ime_transaction = self.ime_transaction.or(transaction);
 9782        if let Some(transaction) = self.ime_transaction {
 9783            self.buffer.update(cx, |buffer, cx| {
 9784                buffer.group_until_transaction(transaction, cx);
 9785            });
 9786        }
 9787
 9788        if self.text_highlights::<InputComposition>(cx).is_none() {
 9789            self.ime_transaction.take();
 9790        }
 9791    }
 9792
 9793    fn bounds_for_range(
 9794        &mut self,
 9795        range_utf16: Range<usize>,
 9796        element_bounds: gpui::Bounds<Pixels>,
 9797        cx: &mut ViewContext<Self>,
 9798    ) -> Option<gpui::Bounds<Pixels>> {
 9799        let text_layout_details = self.text_layout_details(cx);
 9800        let style = &text_layout_details.editor_style;
 9801        let font_id = cx.text_system().font_id(&style.text.font()).unwrap();
 9802        let font_size = style.text.font_size.to_pixels(cx.rem_size());
 9803        let line_height = style.text.line_height_in_pixels(cx.rem_size());
 9804        let em_width = cx
 9805            .text_system()
 9806            .typographic_bounds(font_id, font_size, 'm')
 9807            .unwrap()
 9808            .size
 9809            .width;
 9810
 9811        let snapshot = self.snapshot(cx);
 9812        let scroll_position = snapshot.scroll_position();
 9813        let scroll_left = scroll_position.x * em_width;
 9814
 9815        let start = OffsetUtf16(range_utf16.start).to_display_point(&snapshot);
 9816        let x = snapshot.x_for_point(start, &text_layout_details) - scroll_left + self.gutter_width;
 9817        let y = line_height * (start.row() as f32 - scroll_position.y);
 9818
 9819        Some(Bounds {
 9820            origin: element_bounds.origin + point(x, y),
 9821            size: size(em_width, line_height),
 9822        })
 9823    }
 9824}
 9825
 9826// fn build_style(
 9827//     settings: &ThemeSettings,
 9828//     get_field_editor_theme: Option<&GetFieldEditorTheme>,
 9829//     override_text_style: Option<&OverrideTextStyle>,
 9830//     cx: &mut AppContext,
 9831// ) -> EditorStyle {
 9832//     let font_cache = cx.font_cache();
 9833//     let line_height_scalar = settings.line_height();
 9834//     let theme_id = settings.theme.meta.id;
 9835//     let mut theme = settings.theme.editor.clone();
 9836//     let mut style = if let Some(get_field_editor_theme) = get_field_editor_theme {
 9837//         let field_editor_theme = get_field_editor_theme(&settings.theme);
 9838//         theme.text_color = field_editor_theme.text.color;
 9839//         theme.selection = field_editor_theme.selection;
 9840//         theme.background = field_editor_theme
 9841//             .container
 9842//             .background_color
 9843//             .unwrap_or_default();
 9844//         EditorStyle {
 9845//             text: field_editor_theme.text,
 9846//             placeholder_text: field_editor_theme.placeholder_text,
 9847//             line_height_scalar,
 9848//             theme,
 9849//             theme_id,
 9850//         }
 9851//     } else {
 9852//         todo!();
 9853//         // let font_family_id = settings.buffer_font_family;
 9854//         // let font_family_name = cx.font_cache().family_name(font_family_id).unwrap();
 9855//         // let font_properties = Default::default();
 9856//         // let font_id = font_cache
 9857//         //     .select_font(font_family_id, &font_properties)
 9858//         //     .unwrap();
 9859//         // let font_size = settings.buffer_font_size(cx);
 9860//         // EditorStyle {
 9861//         //     text: TextStyle {
 9862//         //         color: settings.theme.editor.text_color,
 9863//         //         font_family_name,
 9864//         //         font_family_id,
 9865//         //         font_id,
 9866//         //         font_size,
 9867//         //         font_properties,
 9868//         //         underline: Default::default(),
 9869//         //         soft_wrap: false,
 9870//         //     },
 9871//         //     placeholder_text: None,
 9872//         //     line_height_scalar,
 9873//         //     theme,
 9874//         //     theme_id,
 9875//         // }
 9876//     };
 9877
 9878//     if let Some(highlight_style) = override_text_style.and_then(|build_style| build_style(&style)) {
 9879//         if let Some(highlighted) = style
 9880//             .text
 9881//             .clone()
 9882//             .highlight(highlight_style, font_cache)
 9883//             .log_err()
 9884//         {
 9885//             style.text = highlighted;
 9886//         }
 9887//     }
 9888
 9889//     style
 9890// }
 9891
 9892trait SelectionExt {
 9893    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize>;
 9894    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point>;
 9895    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
 9896    fn spanned_rows(&self, include_end_if_at_line_start: bool, map: &DisplaySnapshot)
 9897        -> Range<u32>;
 9898}
 9899
 9900impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
 9901    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
 9902        let start = self.start.to_point(buffer);
 9903        let end = self.end.to_point(buffer);
 9904        if self.reversed {
 9905            end..start
 9906        } else {
 9907            start..end
 9908        }
 9909    }
 9910
 9911    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
 9912        let start = self.start.to_offset(buffer);
 9913        let end = self.end.to_offset(buffer);
 9914        if self.reversed {
 9915            end..start
 9916        } else {
 9917            start..end
 9918        }
 9919    }
 9920
 9921    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
 9922        let start = self
 9923            .start
 9924            .to_point(&map.buffer_snapshot)
 9925            .to_display_point(map);
 9926        let end = self
 9927            .end
 9928            .to_point(&map.buffer_snapshot)
 9929            .to_display_point(map);
 9930        if self.reversed {
 9931            end..start
 9932        } else {
 9933            start..end
 9934        }
 9935    }
 9936
 9937    fn spanned_rows(
 9938        &self,
 9939        include_end_if_at_line_start: bool,
 9940        map: &DisplaySnapshot,
 9941    ) -> Range<u32> {
 9942        let start = self.start.to_point(&map.buffer_snapshot);
 9943        let mut end = self.end.to_point(&map.buffer_snapshot);
 9944        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
 9945            end.row -= 1;
 9946        }
 9947
 9948        let buffer_start = map.prev_line_boundary(start).0;
 9949        let buffer_end = map.next_line_boundary(end).0;
 9950        buffer_start.row..buffer_end.row + 1
 9951    }
 9952}
 9953
 9954impl<T: InvalidationRegion> InvalidationStack<T> {
 9955    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
 9956    where
 9957        S: Clone + ToOffset,
 9958    {
 9959        while let Some(region) = self.last() {
 9960            let all_selections_inside_invalidation_ranges =
 9961                if selections.len() == region.ranges().len() {
 9962                    selections
 9963                        .iter()
 9964                        .zip(region.ranges().iter().map(|r| r.to_offset(buffer)))
 9965                        .all(|(selection, invalidation_range)| {
 9966                            let head = selection.head().to_offset(buffer);
 9967                            invalidation_range.start <= head && invalidation_range.end >= head
 9968                        })
 9969                } else {
 9970                    false
 9971                };
 9972
 9973            if all_selections_inside_invalidation_ranges {
 9974                break;
 9975            } else {
 9976                self.pop();
 9977            }
 9978        }
 9979    }
 9980}
 9981
 9982impl<T> Default for InvalidationStack<T> {
 9983    fn default() -> Self {
 9984        Self(Default::default())
 9985    }
 9986}
 9987
 9988impl<T> Deref for InvalidationStack<T> {
 9989    type Target = Vec<T>;
 9990
 9991    fn deref(&self) -> &Self::Target {
 9992        &self.0
 9993    }
 9994}
 9995
 9996impl<T> DerefMut for InvalidationStack<T> {
 9997    fn deref_mut(&mut self) -> &mut Self::Target {
 9998        &mut self.0
 9999    }
10000}
10001
10002impl InvalidationRegion for SnippetState {
10003    fn ranges(&self) -> &[Range<Anchor>] {
10004        &self.ranges[self.active_index]
10005    }
10006}
10007
10008// impl Deref for EditorStyle {
10009//     type Target = theme::Editor;
10010
10011//     fn deref(&self) -> &Self::Target {
10012//         &self.theme
10013//     }
10014// }
10015
10016pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> RenderBlock {
10017    let mut highlighted_lines = Vec::new();
10018
10019    for (index, line) in diagnostic.message.lines().enumerate() {
10020        let line = match &diagnostic.source {
10021            Some(source) if index == 0 => {
10022                let source_highlight = Vec::from_iter(0..source.len());
10023                highlight_diagnostic_message(source_highlight, &format!("{source}: {line}"))
10024            }
10025
10026            _ => highlight_diagnostic_message(Vec::new(), line),
10027        };
10028        highlighted_lines.push(line);
10029    }
10030    let message = diagnostic.message;
10031    Arc::new(move |cx: &mut BlockContext| {
10032        todo!()
10033        // let message = message.clone();
10034        // let settings = ThemeSettings::get_global(cx);
10035        // let tooltip_style = settings.theme.tooltip.clone();
10036        // let theme = &settings.theme.editor;
10037        // let style = diagnostic_style(diagnostic.severity, is_valid, theme);
10038        // let font_size = (style.text_scale_factor * settings.buffer_font_size(cx)).round();
10039        // let anchor_x = cx.anchor_x;
10040        // enum BlockContextToolip {}
10041        // MouseEventHandler::new::<BlockContext, _>(cx.block_id, cx, |_, _| {
10042        //     Flex::column()
10043        //         .with_children(highlighted_lines.iter().map(|(line, highlights)| {
10044        //             Label::new(
10045        //                 line.clone(),
10046        //                 style.message.clone().with_font_size(font_size),
10047        //             )
10048        //             .with_highlights(highlights.clone())
10049        //             .contained()
10050        //             .with_margin_left(anchor_x)
10051        //         }))
10052        //         .aligned()
10053        //         .left()
10054        //         .into_any()
10055        // })
10056        // .with_cursor_style(CursorStyle::PointingHand)
10057        // .on_click(MouseButton::Left, move |_, _, cx| {
10058        //     cx.write_to_clipboard(ClipboardItem::new(message.clone()));
10059        // })
10060        // // We really need to rethink this ID system...
10061        // .with_tooltip::<BlockContextToolip>(
10062        //     cx.block_id,
10063        //     "Copy diagnostic message",
10064        //     None,
10065        //     tooltip_style,
10066        //     cx,
10067        // )
10068        // .into_any()
10069    })
10070}
10071
10072pub fn highlight_diagnostic_message(
10073    initial_highlights: Vec<usize>,
10074    message: &str,
10075) -> (String, Vec<usize>) {
10076    let mut message_without_backticks = String::new();
10077    let mut prev_offset = 0;
10078    let mut inside_block = false;
10079    let mut highlights = initial_highlights;
10080    for (match_ix, (offset, _)) in message
10081        .match_indices('`')
10082        .chain([(message.len(), "")])
10083        .enumerate()
10084    {
10085        message_without_backticks.push_str(&message[prev_offset..offset]);
10086        if inside_block {
10087            highlights.extend(prev_offset - match_ix..offset - match_ix);
10088        }
10089
10090        inside_block = !inside_block;
10091        prev_offset = offset + 1;
10092    }
10093
10094    (message_without_backticks, highlights)
10095}
10096
10097pub fn diagnostic_style(
10098    severity: DiagnosticSeverity,
10099    valid: bool,
10100    style: &DiagnosticStyle,
10101) -> Hsla {
10102    match (severity, valid) {
10103        (DiagnosticSeverity::ERROR, true) => style.error,
10104        (DiagnosticSeverity::ERROR, false) => style.error,
10105        (DiagnosticSeverity::WARNING, true) => style.warning,
10106        (DiagnosticSeverity::WARNING, false) => style.warning,
10107        (DiagnosticSeverity::INFORMATION, true) => style.info,
10108        (DiagnosticSeverity::INFORMATION, false) => style.info,
10109        (DiagnosticSeverity::HINT, true) => style.info,
10110        (DiagnosticSeverity::HINT, false) => style.info,
10111        _ => style.ignored,
10112    }
10113}
10114
10115// pub fn combine_syntax_and_fuzzy_match_highlights(
10116//     text: &str,
10117//     default_style: HighlightStyle,
10118//     syntax_ranges: impl Iterator<Item = (Range<usize>, HighlightStyle)>,
10119//     match_indices: &[usize],
10120// ) -> Vec<(Range<usize>, HighlightStyle)> {
10121//     let mut result = Vec::new();
10122//     let mut match_indices = match_indices.iter().copied().peekable();
10123
10124//     for (range, mut syntax_highlight) in syntax_ranges.chain([(usize::MAX..0, Default::default())])
10125//     {
10126//         syntax_highlight.weight = None;
10127
10128//         // Add highlights for any fuzzy match characters before the next
10129//         // syntax highlight range.
10130//         while let Some(&match_index) = match_indices.peek() {
10131//             if match_index >= range.start {
10132//                 break;
10133//             }
10134//             match_indices.next();
10135//             let end_index = char_ix_after(match_index, text);
10136//             let mut match_style = default_style;
10137//             match_style.weight = Some(FontWeight::BOLD);
10138//             result.push((match_index..end_index, match_style));
10139//         }
10140
10141//         if range.start == usize::MAX {
10142//             break;
10143//         }
10144
10145//         // Add highlights for any fuzzy match characters within the
10146//         // syntax highlight range.
10147//         let mut offset = range.start;
10148//         while let Some(&match_index) = match_indices.peek() {
10149//             if match_index >= range.end {
10150//                 break;
10151//             }
10152
10153//             match_indices.next();
10154//             if match_index > offset {
10155//                 result.push((offset..match_index, syntax_highlight));
10156//             }
10157
10158//             let mut end_index = char_ix_after(match_index, text);
10159//             while let Some(&next_match_index) = match_indices.peek() {
10160//                 if next_match_index == end_index && next_match_index < range.end {
10161//                     end_index = char_ix_after(next_match_index, text);
10162//                     match_indices.next();
10163//                 } else {
10164//                     break;
10165//                 }
10166//             }
10167
10168//             let mut match_style = syntax_highlight;
10169//             match_style.weight = Some(FontWeight::BOLD);
10170//             result.push((match_index..end_index, match_style));
10171//             offset = end_index;
10172//         }
10173
10174//         if offset < range.end {
10175//             result.push((offset..range.end, syntax_highlight));
10176//         }
10177//     }
10178
10179//     fn char_ix_after(ix: usize, text: &str) -> usize {
10180//         ix + text[ix..].chars().next().unwrap().len_utf8()
10181//     }
10182
10183//     result
10184// }
10185
10186// pub fn styled_runs_for_code_label<'a>(
10187//     label: &'a CodeLabel,
10188//     syntax_theme: &'a theme::SyntaxTheme,
10189// ) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
10190//     let fade_out = HighlightStyle {
10191//         fade_out: Some(0.35),
10192//         ..Default::default()
10193//     };
10194
10195//     let mut prev_end = label.filter_range.end;
10196//     label
10197//         .runs
10198//         .iter()
10199//         .enumerate()
10200//         .flat_map(move |(ix, (range, highlight_id))| {
10201//             let style = if let Some(style) = highlight_id.style(syntax_theme) {
10202//                 style
10203//             } else {
10204//                 return Default::default();
10205//             };
10206//             let mut muted_style = style;
10207//             muted_style.highlight(fade_out);
10208
10209//             let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
10210//             if range.start >= label.filter_range.end {
10211//                 if range.start > prev_end {
10212//                     runs.push((prev_end..range.start, fade_out));
10213//                 }
10214//                 runs.push((range.clone(), muted_style));
10215//             } else if range.end <= label.filter_range.end {
10216//                 runs.push((range.clone(), style));
10217//             } else {
10218//                 runs.push((range.start..label.filter_range.end, style));
10219//                 runs.push((label.filter_range.end..range.end, muted_style));
10220//             }
10221//             prev_end = cmp::max(prev_end, range.end);
10222
10223//             if ix + 1 == label.runs.len() && label.text.len() > prev_end {
10224//                 runs.push((prev_end..label.text.len(), fade_out));
10225//             }
10226
10227//             runs
10228//         })
10229
10230pub fn split_words<'a>(text: &'a str) -> impl std::iter::Iterator<Item = &'a str> + 'a {
10231    let mut index = 0;
10232    let mut codepoints = text.char_indices().peekable();
10233
10234    std::iter::from_fn(move || {
10235        let start_index = index;
10236        while let Some((new_index, codepoint)) = codepoints.next() {
10237            index = new_index + codepoint.len_utf8();
10238            let current_upper = codepoint.is_uppercase();
10239            let next_upper = codepoints
10240                .peek()
10241                .map(|(_, c)| c.is_uppercase())
10242                .unwrap_or(false);
10243
10244            if !current_upper && next_upper {
10245                return Some(&text[start_index..index]);
10246            }
10247        }
10248
10249        index = text.len();
10250        if start_index < text.len() {
10251            return Some(&text[start_index..]);
10252        }
10253        None
10254    })
10255    .flat_map(|word| word.split_inclusive('_'))
10256    .flat_map(|word| word.split_inclusive('-'))
10257}
10258
10259trait RangeToAnchorExt {
10260    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor>;
10261}
10262
10263impl<T: ToOffset> RangeToAnchorExt for Range<T> {
10264    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor> {
10265        snapshot.anchor_after(self.start)..snapshot.anchor_before(self.end)
10266    }
10267}