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