editor.rs

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