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, WhiteSpace, 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, CodeLabel, Completion,
   58    CursorShape, Diagnostic, Documentation, IndentKind, IndentSize, Language, LanguageRegistry,
   59    LanguageServerName, OffsetRangeExt, Point, Selection, SelectionGoal, TransactionId,
   60};
   61use lazy_static::lazy_static;
   62use link_go_to_definition::{GoToDefinitionLink, InlayHighlight, LinkGoToDefinitionState};
   63use lsp::{DiagnosticSeverity, 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::{h_stack, 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) {
  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 {
 1227        let settings = EditorSettings::get_global(cx);
 1228        let show_completion_documentation = settings.show_completion_documentation;
 1229
 1230        let widest_completion_ix = self
 1231            .matches
 1232            .iter()
 1233            .enumerate()
 1234            .max_by_key(|(_, mat)| {
 1235                let completions = self.completions.read();
 1236                let completion = &completions[mat.candidate_id];
 1237                let documentation = &completion.documentation;
 1238
 1239                let mut len = completion.label.text.chars().count();
 1240                if let Some(Documentation::SingleLine(text)) = documentation {
 1241                    if show_completion_documentation {
 1242                        len += text.chars().count();
 1243                    }
 1244                }
 1245
 1246                len
 1247            })
 1248            .map(|(ix, _)| ix);
 1249
 1250        let completions = self.completions.clone();
 1251        let matches = self.matches.clone();
 1252        let selected_item = self.selected_item;
 1253
 1254        let list = uniform_list(
 1255            cx.view().clone(),
 1256            "completions",
 1257            matches.len(),
 1258            move |editor, range, cx| {
 1259                let start_ix = range.start;
 1260                let completions_guard = completions.read();
 1261
 1262                matches[range]
 1263                    .iter()
 1264                    .enumerate()
 1265                    .map(|(ix, mat)| {
 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                        // todo!("highlights")
 1277                        // let highlights = combine_syntax_and_fuzzy_match_highlights(
 1278                        //     &completion.label.text,
 1279                        //     style.text.color.into(),
 1280                        //     styled_runs_for_code_label(&completion.label, &style.syntax),
 1281                        //     &mat.positions,
 1282                        // )
 1283
 1284                        // todo!("documentation")
 1285                        // MouseEventHandler::new::<CompletionTag, _>(mat.candidate_id, cx, |state, _| {
 1286                        //     let completion_label = HighlightedLabel::new(
 1287                        //         completion.label.text.clone(),
 1288                        //         combine_syntax_and_fuzzy_match_highlights(
 1289                        //             &completion.label.text,
 1290                        //             style.text.color.into(),
 1291                        //             styled_runs_for_code_label(&completion.label, &style.syntax),
 1292                        //             &mat.positions,
 1293                        //         ),
 1294                        //     );
 1295                        //     Text::new(completion.label.text.clone(), style.text.clone())
 1296                        //         .with_soft_wrap(false)
 1297                        //         .with_highlights();
 1298
 1299                        //     if let Some(Documentation::SingleLine(text)) = documentation {
 1300                        //         h_stack()
 1301                        //             .child(completion_label)
 1302                        //             .with_children((|| {
 1303                        //                 let text_style = TextStyle {
 1304                        //                     color: style.autocomplete.inline_docs_color,
 1305                        //                     font_size: style.text.font_size
 1306                        //                         * style.autocomplete.inline_docs_size_percent,
 1307                        //                     ..style.text.clone()
 1308                        //                 };
 1309
 1310                        //                 let label = Text::new(text.clone(), text_style)
 1311                        //                     .aligned()
 1312                        //                     .constrained()
 1313                        //                     .dynamically(move |constraint, _, _| gpui::SizeConstraint {
 1314                        //                         min: constraint.min,
 1315                        //                         max: vec2f(constraint.max.x(), constraint.min.y()),
 1316                        //                     });
 1317
 1318                        //                 if Some(item_ix) == widest_completion_ix {
 1319                        //                     Some(
 1320                        //                         label
 1321                        //                             .contained()
 1322                        //                             .with_style(style.autocomplete.inline_docs_container)
 1323                        //                             .into_any(),
 1324                        //                     )
 1325                        //                 } else {
 1326                        //                     Some(label.flex_float().into_any())
 1327                        //                 }
 1328                        //             })())
 1329                        //             .into_any()
 1330                        //     } else {
 1331                        //         completion_label.into_any()
 1332                        //     }
 1333                        //     .contained()
 1334                        //     .with_style(item_style)
 1335                        //     .constrained()
 1336                        //     .dynamically(move |constraint, _, _| {
 1337                        //         if Some(item_ix) == widest_completion_ix {
 1338                        //             constraint
 1339                        //         } else {
 1340                        //             gpui::SizeConstraint {
 1341                        //                 min: constraint.min,
 1342                        //                 max: constraint.min,
 1343                        //             }
 1344                        //         }
 1345                        //     })
 1346                        // })
 1347                        // .with_cursor_style(CursorStyle::PointingHand)
 1348                        // .on_down(MouseButton::Left, move |_, this, cx| {
 1349                        //     this.confirm_completion(
 1350                        //         &ConfirmCompletion {
 1351                        //             item_ix: Some(item_ix),
 1352                        //         },
 1353                        //         cx,
 1354                        //     )
 1355                        //     .map(|task| task.detach());
 1356                        // })
 1357                        // .constrained()
 1358                        //
 1359                        div()
 1360                            .id(mat.candidate_id)
 1361                            .whitespace_nowrap()
 1362                            .overflow_hidden()
 1363                            .bg(gpui::green())
 1364                            .hover(|style| style.bg(gpui::blue()))
 1365                            .when(item_ix == selected_item, |div| div.bg(gpui::red()))
 1366                            .child(SharedString::from(completion.label.text.clone()))
 1367                            .min_w(px(300.))
 1368                            .max_w(px(700.))
 1369                    })
 1370                    .collect()
 1371            },
 1372        )
 1373        .with_width_from_item(widest_completion_ix);
 1374
 1375        list.render_into_any()
 1376        // todo!("multiline documentation")
 1377        //     enum MultiLineDocumentation {}
 1378
 1379        //     Flex::row()
 1380        //         .with_child(list.flex(1., false))
 1381        //         .with_children({
 1382        //             let mat = &self.matches[selected_item];
 1383        //             let completions = self.completions.read();
 1384        //             let completion = &completions[mat.candidate_id];
 1385        //             let documentation = &completion.documentation;
 1386
 1387        //             match documentation {
 1388        //                 Some(Documentation::MultiLinePlainText(text)) => Some(
 1389        //                     Flex::column()
 1390        //                         .scrollable::<MultiLineDocumentation>(0, None, cx)
 1391        //                         .with_child(
 1392        //                             Text::new(text.clone(), style.text.clone()).with_soft_wrap(true),
 1393        //                         )
 1394        //                         .contained()
 1395        //                         .with_style(style.autocomplete.alongside_docs_container)
 1396        //                         .constrained()
 1397        //                         .with_max_width(style.autocomplete.alongside_docs_max_width)
 1398        //                         .flex(1., false),
 1399        //                 ),
 1400
 1401        //                 Some(Documentation::MultiLineMarkdown(parsed)) => Some(
 1402        //                     Flex::column()
 1403        //                         .scrollable::<MultiLineDocumentation>(0, None, cx)
 1404        //                         .with_child(render_parsed_markdown::<MultiLineDocumentation>(
 1405        //                             parsed, &style, workspace, cx,
 1406        //                         ))
 1407        //                         .contained()
 1408        //                         .with_style(style.autocomplete.alongside_docs_container)
 1409        //                         .constrained()
 1410        //                         .with_max_width(style.autocomplete.alongside_docs_max_width)
 1411        //                         .flex(1., false),
 1412        //                 ),
 1413
 1414        //                 _ => None,
 1415        //             }
 1416        //         })
 1417        //         .contained()
 1418        //         .with_style(style.autocomplete.container)
 1419        //         .into_any()
 1420    }
 1421
 1422    pub async fn filter(&mut self, query: Option<&str>, executor: BackgroundExecutor) {
 1423        let mut matches = if let Some(query) = query {
 1424            fuzzy::match_strings(
 1425                &self.match_candidates,
 1426                query,
 1427                query.chars().any(|c| c.is_uppercase()),
 1428                100,
 1429                &Default::default(),
 1430                executor,
 1431            )
 1432            .await
 1433        } else {
 1434            self.match_candidates
 1435                .iter()
 1436                .enumerate()
 1437                .map(|(candidate_id, candidate)| StringMatch {
 1438                    candidate_id,
 1439                    score: Default::default(),
 1440                    positions: Default::default(),
 1441                    string: candidate.string.clone(),
 1442                })
 1443                .collect()
 1444        };
 1445
 1446        // Remove all candidates where the query's start does not match the start of any word in the candidate
 1447        if let Some(query) = query {
 1448            if let Some(query_start) = query.chars().next() {
 1449                matches.retain(|string_match| {
 1450                    split_words(&string_match.string).any(|word| {
 1451                        // Check that the first codepoint of the word as lowercase matches the first
 1452                        // codepoint of the query as lowercase
 1453                        word.chars()
 1454                            .flat_map(|codepoint| codepoint.to_lowercase())
 1455                            .zip(query_start.to_lowercase())
 1456                            .all(|(word_cp, query_cp)| word_cp == query_cp)
 1457                    })
 1458                });
 1459            }
 1460        }
 1461
 1462        let completions = self.completions.read();
 1463        matches.sort_unstable_by_key(|mat| {
 1464            let completion = &completions[mat.candidate_id];
 1465            (
 1466                completion.lsp_completion.sort_text.as_ref(),
 1467                Reverse(OrderedFloat(mat.score)),
 1468                completion.sort_key(),
 1469            )
 1470        });
 1471        drop(completions);
 1472
 1473        for mat in &mut matches {
 1474            let completions = self.completions.read();
 1475            let filter_start = completions[mat.candidate_id].label.filter_range.start;
 1476            for position in &mut mat.positions {
 1477                *position += filter_start;
 1478            }
 1479        }
 1480
 1481        self.matches = matches.into();
 1482        self.selected_item = 0;
 1483    }
 1484}
 1485
 1486#[derive(Clone)]
 1487struct CodeActionsMenu {
 1488    actions: Arc<[CodeAction]>,
 1489    buffer: Model<Buffer>,
 1490    selected_item: usize,
 1491    scroll_handle: UniformListScrollHandle,
 1492    deployed_from_indicator: bool,
 1493}
 1494
 1495impl CodeActionsMenu {
 1496    fn select_first(&mut self, cx: &mut ViewContext<Editor>) {
 1497        self.selected_item = 0;
 1498        self.scroll_handle.scroll_to_item(self.selected_item);
 1499        cx.notify()
 1500    }
 1501
 1502    fn select_prev(&mut self, cx: &mut ViewContext<Editor>) {
 1503        if self.selected_item > 0 {
 1504            self.selected_item -= 1;
 1505        } else {
 1506            self.selected_item = self.actions.len() - 1;
 1507        }
 1508        self.scroll_handle.scroll_to_item(self.selected_item);
 1509        cx.notify();
 1510    }
 1511
 1512    fn select_next(&mut self, cx: &mut ViewContext<Editor>) {
 1513        if self.selected_item + 1 < self.actions.len() {
 1514            self.selected_item += 1;
 1515        } else {
 1516            self.selected_item = 0;
 1517        }
 1518        self.scroll_handle.scroll_to_item(self.selected_item);
 1519        cx.notify();
 1520    }
 1521
 1522    fn select_last(&mut self, cx: &mut ViewContext<Editor>) {
 1523        self.selected_item = self.actions.len() - 1;
 1524        self.scroll_handle.scroll_to_item(self.selected_item);
 1525        cx.notify()
 1526    }
 1527
 1528    fn visible(&self) -> bool {
 1529        !self.actions.is_empty()
 1530    }
 1531
 1532    fn render(
 1533        &self,
 1534        mut cursor_position: DisplayPoint,
 1535        style: &EditorStyle,
 1536        cx: &mut ViewContext<Editor>,
 1537    ) -> (DisplayPoint, AnyElement) {
 1538        let actions = self.actions.clone();
 1539        let selected_item = self.selected_item;
 1540
 1541        let element = uniform_list(
 1542            cx.view().clone(),
 1543            "code_actions_menu",
 1544            self.actions.len(),
 1545            move |this, range, cx| {
 1546                actions[range.clone()]
 1547                    .iter()
 1548                    .enumerate()
 1549                    .map(|(ix, action)| {
 1550                        let item_ix = range.start + ix;
 1551                        let selected = selected_item == item_ix;
 1552                        let colors = cx.theme().colors();
 1553                        div()
 1554                            .px_2()
 1555                            .text_ui()
 1556                            .text_color(colors.text)
 1557                            .when(selected, |style| {
 1558                                style
 1559                                    .bg(colors.element_active)
 1560                                    .text_color(colors.text_accent)
 1561                            })
 1562                            .hover(|style| {
 1563                                style
 1564                                    .bg(colors.element_hover)
 1565                                    .text_color(colors.text_accent)
 1566                            })
 1567                            .on_mouse_down(
 1568                                MouseButton::Left,
 1569                                cx.listener(move |editor, _, cx| {
 1570                                    cx.stop_propagation();
 1571                                    editor
 1572                                        .confirm_code_action(
 1573                                            &ConfirmCodeAction {
 1574                                                item_ix: Some(item_ix),
 1575                                            },
 1576                                            cx,
 1577                                        )
 1578                                        .map(|task| task.detach_and_log_err(cx));
 1579                                }),
 1580                            )
 1581                            // TASK: It would be good to make lsp_action.title a SharedString to avoid allocating here.
 1582                            .child(SharedString::from(action.lsp_action.title.clone()))
 1583                    })
 1584                    .collect()
 1585            },
 1586        )
 1587        .elevation_1(cx)
 1588        .px_2()
 1589        .py_1()
 1590        .with_width_from_item(
 1591            self.actions
 1592                .iter()
 1593                .enumerate()
 1594                .max_by_key(|(_, action)| action.lsp_action.title.chars().count())
 1595                .map(|(ix, _)| ix),
 1596        )
 1597        .render_into_any();
 1598
 1599        if self.deployed_from_indicator {
 1600            *cursor_position.column_mut() = 0;
 1601        }
 1602
 1603        (cursor_position, element)
 1604    }
 1605}
 1606
 1607pub struct CopilotState {
 1608    excerpt_id: Option<ExcerptId>,
 1609    pending_refresh: Task<Option<()>>,
 1610    pending_cycling_refresh: Task<Option<()>>,
 1611    cycled: bool,
 1612    completions: Vec<copilot::Completion>,
 1613    active_completion_index: usize,
 1614    suggestion: Option<Inlay>,
 1615}
 1616
 1617impl Default for CopilotState {
 1618    fn default() -> Self {
 1619        Self {
 1620            excerpt_id: None,
 1621            pending_cycling_refresh: Task::ready(Some(())),
 1622            pending_refresh: Task::ready(Some(())),
 1623            completions: Default::default(),
 1624            active_completion_index: 0,
 1625            cycled: false,
 1626            suggestion: None,
 1627        }
 1628    }
 1629}
 1630
 1631impl CopilotState {
 1632    fn active_completion(&self) -> Option<&copilot::Completion> {
 1633        self.completions.get(self.active_completion_index)
 1634    }
 1635
 1636    fn text_for_active_completion(
 1637        &self,
 1638        cursor: Anchor,
 1639        buffer: &MultiBufferSnapshot,
 1640    ) -> Option<&str> {
 1641        use language::ToOffset as _;
 1642
 1643        let completion = self.active_completion()?;
 1644        let excerpt_id = self.excerpt_id?;
 1645        let completion_buffer = buffer.buffer_for_excerpt(excerpt_id)?;
 1646        if excerpt_id != cursor.excerpt_id
 1647            || !completion.range.start.is_valid(completion_buffer)
 1648            || !completion.range.end.is_valid(completion_buffer)
 1649        {
 1650            return None;
 1651        }
 1652
 1653        let mut completion_range = completion.range.to_offset(&completion_buffer);
 1654        let prefix_len = Self::common_prefix(
 1655            completion_buffer.chars_for_range(completion_range.clone()),
 1656            completion.text.chars(),
 1657        );
 1658        completion_range.start += prefix_len;
 1659        let suffix_len = Self::common_prefix(
 1660            completion_buffer.reversed_chars_for_range(completion_range.clone()),
 1661            completion.text[prefix_len..].chars().rev(),
 1662        );
 1663        completion_range.end = completion_range.end.saturating_sub(suffix_len);
 1664
 1665        if completion_range.is_empty()
 1666            && completion_range.start == cursor.text_anchor.to_offset(&completion_buffer)
 1667        {
 1668            Some(&completion.text[prefix_len..completion.text.len() - suffix_len])
 1669        } else {
 1670            None
 1671        }
 1672    }
 1673
 1674    fn cycle_completions(&mut self, direction: Direction) {
 1675        match direction {
 1676            Direction::Prev => {
 1677                self.active_completion_index = if self.active_completion_index == 0 {
 1678                    self.completions.len().saturating_sub(1)
 1679                } else {
 1680                    self.active_completion_index - 1
 1681                };
 1682            }
 1683            Direction::Next => {
 1684                if self.completions.len() == 0 {
 1685                    self.active_completion_index = 0
 1686                } else {
 1687                    self.active_completion_index =
 1688                        (self.active_completion_index + 1) % self.completions.len();
 1689                }
 1690            }
 1691        }
 1692    }
 1693
 1694    fn push_completion(&mut self, new_completion: copilot::Completion) {
 1695        for completion in &self.completions {
 1696            if completion.text == new_completion.text && completion.range == new_completion.range {
 1697                return;
 1698            }
 1699        }
 1700        self.completions.push(new_completion);
 1701    }
 1702
 1703    fn common_prefix<T1: Iterator<Item = char>, T2: Iterator<Item = char>>(a: T1, b: T2) -> usize {
 1704        a.zip(b)
 1705            .take_while(|(a, b)| a == b)
 1706            .map(|(a, _)| a.len_utf8())
 1707            .sum()
 1708    }
 1709}
 1710
 1711#[derive(Debug)]
 1712struct ActiveDiagnosticGroup {
 1713    primary_range: Range<Anchor>,
 1714    primary_message: String,
 1715    blocks: HashMap<BlockId, Diagnostic>,
 1716    is_valid: bool,
 1717}
 1718
 1719#[derive(Serialize, Deserialize)]
 1720pub struct ClipboardSelection {
 1721    pub len: usize,
 1722    pub is_entire_line: bool,
 1723    pub first_line_indent: u32,
 1724}
 1725
 1726#[derive(Debug)]
 1727pub struct NavigationData {
 1728    cursor_anchor: Anchor,
 1729    cursor_position: Point,
 1730    scroll_anchor: ScrollAnchor,
 1731    scroll_top_row: u32,
 1732}
 1733
 1734pub struct EditorCreated(pub View<Editor>);
 1735
 1736enum GotoDefinitionKind {
 1737    Symbol,
 1738    Type,
 1739}
 1740
 1741#[derive(Debug, Clone)]
 1742enum InlayHintRefreshReason {
 1743    Toggle(bool),
 1744    SettingsChange(InlayHintSettings),
 1745    NewLinesShown,
 1746    BufferEdited(HashSet<Arc<Language>>),
 1747    RefreshRequested,
 1748    ExcerptsRemoved(Vec<ExcerptId>),
 1749}
 1750impl InlayHintRefreshReason {
 1751    fn description(&self) -> &'static str {
 1752        match self {
 1753            Self::Toggle(_) => "toggle",
 1754            Self::SettingsChange(_) => "settings change",
 1755            Self::NewLinesShown => "new lines shown",
 1756            Self::BufferEdited(_) => "buffer edited",
 1757            Self::RefreshRequested => "refresh requested",
 1758            Self::ExcerptsRemoved(_) => "excerpts removed",
 1759        }
 1760    }
 1761}
 1762
 1763impl Editor {
 1764    pub fn single_line(cx: &mut ViewContext<Self>) -> Self {
 1765        let buffer = cx.build_model(|cx| Buffer::new(0, cx.entity_id().as_u64(), String::new()));
 1766        let buffer = cx.build_model(|cx| MultiBuffer::singleton(buffer, cx));
 1767        Self::new(EditorMode::SingleLine, buffer, None, cx)
 1768    }
 1769
 1770    //     pub fn multi_line(
 1771    //         field_editor_style: Option<Arc<GetFieldEditorTheme>>,
 1772    //         cx: &mut ViewContext<Self>,
 1773    //     ) -> Self {
 1774    //         let buffer = cx.build_model(|cx| Buffer::new(0, cx.model_id() as u64, String::new()));
 1775    //         let buffer = cx.build_model(|cx| MultiBuffer::singleton(buffer, cx));
 1776    //         Self::new(EditorMode::Full, buffer, None, field_editor_style, cx)
 1777    //     }
 1778
 1779    //     pub fn auto_height(
 1780    //         max_lines: usize,
 1781    //         field_editor_style: Option<Arc<GetFieldEditorTheme>>,
 1782    //         cx: &mut ViewContext<Self>,
 1783    //     ) -> Self {
 1784    //         let buffer = cx.build_model(|cx| Buffer::new(0, cx.model_id() as u64, String::new()));
 1785    //         let buffer = cx.build_model(|cx| MultiBuffer::singleton(buffer, cx));
 1786    //         Self::new(
 1787    //             EditorMode::AutoHeight { max_lines },
 1788    //             buffer,
 1789    //             None,
 1790    //             field_editor_style,
 1791    //             cx,
 1792    //         )
 1793    //     }
 1794
 1795    pub fn for_buffer(
 1796        buffer: Model<Buffer>,
 1797        project: Option<Model<Project>>,
 1798        cx: &mut ViewContext<Self>,
 1799    ) -> Self {
 1800        let buffer = cx.build_model(|cx| MultiBuffer::singleton(buffer, cx));
 1801        Self::new(EditorMode::Full, buffer, project, cx)
 1802    }
 1803
 1804    pub fn for_multibuffer(
 1805        buffer: Model<MultiBuffer>,
 1806        project: Option<Model<Project>>,
 1807        cx: &mut ViewContext<Self>,
 1808    ) -> Self {
 1809        Self::new(EditorMode::Full, buffer, project, cx)
 1810    }
 1811
 1812    pub fn clone(&self, cx: &mut ViewContext<Self>) -> Self {
 1813        let mut clone = Self::new(
 1814            self.mode,
 1815            self.buffer.clone(),
 1816            self.project.clone(),
 1817            // todo!
 1818            // self.get_field_editor_theme.clone(),
 1819            cx,
 1820        );
 1821        self.display_map.update(cx, |display_map, cx| {
 1822            let snapshot = display_map.snapshot(cx);
 1823            clone.display_map.update(cx, |display_map, cx| {
 1824                display_map.set_state(&snapshot, cx);
 1825            });
 1826        });
 1827        clone.selections.clone_state(&self.selections);
 1828        clone.scroll_manager.clone_state(&self.scroll_manager);
 1829        clone.searchable = self.searchable;
 1830        clone
 1831    }
 1832
 1833    fn new(
 1834        mode: EditorMode,
 1835        buffer: Model<MultiBuffer>,
 1836        project: Option<Model<Project>>,
 1837        // todo!()
 1838        // get_field_editor_theme: Option<Arc<GetFieldEditorTheme>>,
 1839        cx: &mut ViewContext<Self>,
 1840    ) -> Self {
 1841        // let editor_view_id = cx.view_id();
 1842        let style = cx.text_style();
 1843        let font_size = style.font_size.to_pixels(cx.rem_size());
 1844        let display_map = cx.build_model(|cx| {
 1845            // todo!()
 1846            // let settings = settings::get::<ThemeSettings>(cx);
 1847            // let style = build_style(settings, get_field_editor_theme.as_deref(), None, cx);
 1848            DisplayMap::new(buffer.clone(), style.font(), font_size, None, 2, 1, cx)
 1849        });
 1850
 1851        let selections = SelectionsCollection::new(display_map.clone(), buffer.clone());
 1852
 1853        let blink_manager = cx.build_model(|cx| BlinkManager::new(CURSOR_BLINK_INTERVAL, cx));
 1854
 1855        let soft_wrap_mode_override =
 1856            (mode == EditorMode::SingleLine).then(|| language_settings::SoftWrap::None);
 1857
 1858        let mut project_subscriptions = Vec::new();
 1859        if mode == EditorMode::Full {
 1860            if let Some(project) = project.as_ref() {
 1861                if buffer.read(cx).is_singleton() {
 1862                    project_subscriptions.push(cx.observe(project, |_, _, cx| {
 1863                        cx.emit(ItemEvent::UpdateTab);
 1864                        cx.emit(ItemEvent::UpdateBreadcrumbs);
 1865                    }));
 1866                }
 1867                project_subscriptions.push(cx.subscribe(project, |editor, _, event, cx| {
 1868                    if let project::Event::RefreshInlayHints = event {
 1869                        editor.refresh_inlay_hints(InlayHintRefreshReason::RefreshRequested, cx);
 1870                    };
 1871                }));
 1872            }
 1873        }
 1874
 1875        let inlay_hint_settings = inlay_hint_settings(
 1876            selections.newest_anchor().head(),
 1877            &buffer.read(cx).snapshot(cx),
 1878            cx,
 1879        );
 1880
 1881        let focus_handle = cx.focus_handle();
 1882        cx.on_focus(&focus_handle, Self::handle_focus).detach();
 1883        cx.on_blur(&focus_handle, Self::handle_blur).detach();
 1884
 1885        let mut this = Self {
 1886            handle: cx.view().downgrade(),
 1887            focus_handle,
 1888            buffer: buffer.clone(),
 1889            display_map: display_map.clone(),
 1890            selections,
 1891            scroll_manager: ScrollManager::new(),
 1892            columnar_selection_tail: None,
 1893            add_selections_state: None,
 1894            select_next_state: None,
 1895            select_prev_state: None,
 1896            selection_history: Default::default(),
 1897            autoclose_regions: Default::default(),
 1898            snippet_stack: Default::default(),
 1899            select_larger_syntax_node_stack: Vec::new(),
 1900            ime_transaction: Default::default(),
 1901            active_diagnostics: None,
 1902            soft_wrap_mode_override,
 1903            // get_field_editor_theme,
 1904            collaboration_hub: project.clone().map(|project| Box::new(project) as _),
 1905            project,
 1906            blink_manager: blink_manager.clone(),
 1907            show_local_selections: true,
 1908            mode,
 1909            show_gutter: mode == EditorMode::Full,
 1910            show_wrap_guides: None,
 1911            placeholder_text: None,
 1912            highlighted_rows: None,
 1913            background_highlights: Default::default(),
 1914            inlay_background_highlights: Default::default(),
 1915            nav_history: None,
 1916            context_menu: RwLock::new(None),
 1917            // mouse_context_menu: cx
 1918            //     .add_view(|cx| context_menu::ContextMenu::new(editor_view_id, cx)),
 1919            completion_tasks: Default::default(),
 1920            next_completion_id: 0,
 1921            next_inlay_id: 0,
 1922            available_code_actions: Default::default(),
 1923            code_actions_task: Default::default(),
 1924            document_highlights_task: Default::default(),
 1925            pending_rename: Default::default(),
 1926            searchable: true,
 1927            // override_text_style: None,
 1928            cursor_shape: Default::default(),
 1929            autoindent_mode: Some(AutoindentMode::EachLine),
 1930            collapse_matches: false,
 1931            workspace: None,
 1932            keymap_context_layers: Default::default(),
 1933            input_enabled: true,
 1934            read_only: false,
 1935            leader_peer_id: None,
 1936            remote_id: None,
 1937            hover_state: Default::default(),
 1938            link_go_to_definition_state: Default::default(),
 1939            copilot_state: Default::default(),
 1940            inlay_hint_cache: InlayHintCache::new(inlay_hint_settings),
 1941            gutter_hovered: false,
 1942            pixel_position_of_newest_cursor: None,
 1943            gutter_width: Default::default(),
 1944            style: None,
 1945            _subscriptions: vec![
 1946                cx.observe(&buffer, Self::on_buffer_changed),
 1947                cx.subscribe(&buffer, Self::on_buffer_event),
 1948                cx.observe(&display_map, Self::on_display_map_changed),
 1949                cx.observe(&blink_manager, |_, _, cx| cx.notify()),
 1950                cx.observe_global::<SettingsStore>(Self::settings_changed),
 1951                cx.observe_window_activation(|editor, cx| {
 1952                    let active = cx.is_window_active();
 1953                    editor.blink_manager.update(cx, |blink_manager, cx| {
 1954                        if active {
 1955                            blink_manager.enable(cx);
 1956                        } else {
 1957                            blink_manager.show_cursor(cx);
 1958                            blink_manager.disable(cx);
 1959                        }
 1960                    });
 1961                }),
 1962            ],
 1963        };
 1964
 1965        this._subscriptions.extend(project_subscriptions);
 1966
 1967        this.end_selection(cx);
 1968        this.scroll_manager.show_scrollbar(cx);
 1969
 1970        // todo!("use a different mechanism")
 1971        // let editor_created_event = EditorCreated(cx.handle());
 1972        // cx.emit_global(editor_created_event);
 1973
 1974        if mode == EditorMode::Full {
 1975            let should_auto_hide_scrollbars = cx.should_auto_hide_scrollbars();
 1976            cx.set_global(ScrollbarAutoHide(should_auto_hide_scrollbars));
 1977        }
 1978
 1979        this.report_editor_event("open", None, cx);
 1980        this
 1981    }
 1982
 1983    fn dispatch_context(&self, cx: &AppContext) -> KeyContext {
 1984        let mut dispatch_context = KeyContext::default();
 1985        dispatch_context.add("Editor");
 1986        let mode = match self.mode {
 1987            EditorMode::SingleLine => "single_line",
 1988            EditorMode::AutoHeight { .. } => "auto_height",
 1989            EditorMode::Full => "full",
 1990        };
 1991        dispatch_context.set("mode", mode);
 1992        if self.pending_rename.is_some() {
 1993            dispatch_context.add("renaming");
 1994        }
 1995        if self.context_menu_visible() {
 1996            match self.context_menu.read().as_ref() {
 1997                Some(ContextMenu::Completions(_)) => {
 1998                    dispatch_context.add("menu");
 1999                    dispatch_context.add("showing_completions")
 2000                }
 2001                Some(ContextMenu::CodeActions(_)) => {
 2002                    dispatch_context.add("menu");
 2003                    dispatch_context.add("showing_code_actions")
 2004                }
 2005                None => {}
 2006            }
 2007        }
 2008
 2009        for layer in self.keymap_context_layers.values() {
 2010            dispatch_context.extend(layer);
 2011        }
 2012
 2013        if let Some(extension) = self
 2014            .buffer
 2015            .read(cx)
 2016            .as_singleton()
 2017            .and_then(|buffer| buffer.read(cx).file()?.path().extension()?.to_str())
 2018        {
 2019            dispatch_context.set("extension", extension.to_string());
 2020        }
 2021
 2022        dispatch_context
 2023    }
 2024
 2025    pub fn new_file(
 2026        workspace: &mut Workspace,
 2027        _: &workspace::NewFile,
 2028        cx: &mut ViewContext<Workspace>,
 2029    ) {
 2030        let project = workspace.project().clone();
 2031        if project.read(cx).is_remote() {
 2032            cx.propagate();
 2033        } else if let Some(buffer) = project
 2034            .update(cx, |project, cx| project.create_buffer("", None, cx))
 2035            .log_err()
 2036        {
 2037            workspace.add_item(
 2038                Box::new(cx.build_view(|cx| Editor::for_buffer(buffer, Some(project.clone()), cx))),
 2039                cx,
 2040            );
 2041        }
 2042    }
 2043
 2044    //     pub fn new_file_in_direction(
 2045    //         workspace: &mut Workspace,
 2046    //         action: &workspace::NewFileInDirection,
 2047    //         cx: &mut ViewContext<Workspace>,
 2048    //     ) {
 2049    //         let project = workspace.project().clone();
 2050    //         if project.read(cx).is_remote() {
 2051    //             cx.propagate();
 2052    //         } else if let Some(buffer) = project
 2053    //             .update(cx, |project, cx| project.create_buffer("", None, cx))
 2054    //             .log_err()
 2055    //         {
 2056    //             workspace.split_item(
 2057    //                 action.0,
 2058    //                 Box::new(cx.add_view(|cx| Editor::for_buffer(buffer, Some(project.clone()), cx))),
 2059    //                 cx,
 2060    //             );
 2061    //         }
 2062    //     }
 2063
 2064    pub fn replica_id(&self, cx: &AppContext) -> ReplicaId {
 2065        self.buffer.read(cx).replica_id()
 2066    }
 2067
 2068    //     pub fn leader_peer_id(&self) -> Option<PeerId> {
 2069    //         self.leader_peer_id
 2070    //     }
 2071
 2072    pub fn buffer(&self) -> &Model<MultiBuffer> {
 2073        &self.buffer
 2074    }
 2075
 2076    fn workspace(&self) -> Option<View<Workspace>> {
 2077        self.workspace.as_ref()?.0.upgrade()
 2078    }
 2079
 2080    pub fn title<'a>(&self, cx: &'a AppContext) -> Cow<'a, str> {
 2081        self.buffer().read(cx).title(cx)
 2082    }
 2083
 2084    pub fn snapshot(&mut self, cx: &mut WindowContext) -> EditorSnapshot {
 2085        EditorSnapshot {
 2086            mode: self.mode,
 2087            show_gutter: self.show_gutter,
 2088            display_snapshot: self.display_map.update(cx, |map, cx| map.snapshot(cx)),
 2089            scroll_anchor: self.scroll_manager.anchor(),
 2090            ongoing_scroll: self.scroll_manager.ongoing_scroll(),
 2091            placeholder_text: self.placeholder_text.clone(),
 2092            is_focused: self.focus_handle.is_focused(cx),
 2093        }
 2094    }
 2095
 2096    //     pub fn language_at<'a, T: ToOffset>(
 2097    //         &self,
 2098    //         point: T,
 2099    //         cx: &'a AppContext,
 2100    //     ) -> Option<Arc<Language>> {
 2101    //         self.buffer.read(cx).language_at(point, cx)
 2102    //     }
 2103
 2104    //     pub fn file_at<'a, T: ToOffset>(&self, point: T, cx: &'a AppContext) -> Option<Arc<dyn File>> {
 2105    //         self.buffer.read(cx).read(cx).file_at(point).cloned()
 2106    //     }
 2107
 2108    //     pub fn active_excerpt(
 2109    //         &self,
 2110    //         cx: &AppContext,
 2111    //     ) -> Option<(ExcerptId, Model<Buffer>, Range<text::Anchor>)> {
 2112    //         self.buffer
 2113    //             .read(cx)
 2114    //             .excerpt_containing(self.selections.newest_anchor().head(), cx)
 2115    //     }
 2116
 2117    //     pub fn style(&self, cx: &AppContext) -> EditorStyle {
 2118    //         build_style(
 2119    //             settings::get::<ThemeSettings>(cx),
 2120    //             self.get_field_editor_theme.as_deref(),
 2121    //             self.override_text_style.as_deref(),
 2122    //             cx,
 2123    //         )
 2124    //     }
 2125
 2126    pub fn mode(&self) -> EditorMode {
 2127        self.mode
 2128    }
 2129
 2130    pub fn collaboration_hub(&self) -> Option<&dyn CollaborationHub> {
 2131        self.collaboration_hub.as_deref()
 2132    }
 2133
 2134    pub fn set_collaboration_hub(&mut self, hub: Box<dyn CollaborationHub>) {
 2135        self.collaboration_hub = Some(hub);
 2136    }
 2137
 2138    pub fn set_placeholder_text(
 2139        &mut self,
 2140        placeholder_text: impl Into<Arc<str>>,
 2141        cx: &mut ViewContext<Self>,
 2142    ) {
 2143        self.placeholder_text = Some(placeholder_text.into());
 2144        cx.notify();
 2145    }
 2146
 2147    //     pub fn set_cursor_shape(&mut self, cursor_shape: CursorShape, cx: &mut ViewContext<Self>) {
 2148    //         self.cursor_shape = cursor_shape;
 2149    //         cx.notify();
 2150    //     }
 2151
 2152    //     pub fn set_collapse_matches(&mut self, collapse_matches: bool) {
 2153    //         self.collapse_matches = collapse_matches;
 2154    //     }
 2155
 2156    pub fn range_for_match<T: std::marker::Copy>(&self, range: &Range<T>) -> Range<T> {
 2157        if self.collapse_matches {
 2158            return range.start..range.start;
 2159        }
 2160        range.clone()
 2161    }
 2162
 2163    //     pub fn set_clip_at_line_ends(&mut self, clip: bool, cx: &mut ViewContext<Self>) {
 2164    //         if self.display_map.read(cx).clip_at_line_ends != clip {
 2165    //             self.display_map
 2166    //                 .update(cx, |map, _| map.clip_at_line_ends = clip);
 2167    //         }
 2168    //     }
 2169
 2170    //     pub fn set_keymap_context_layer<Tag: 'static>(
 2171    //         &mut self,
 2172    //         context: KeymapContext,
 2173    //         cx: &mut ViewContext<Self>,
 2174    //     ) {
 2175    //         self.keymap_context_layers
 2176    //             .insert(TypeId::of::<Tag>(), context);
 2177    //         cx.notify();
 2178    //     }
 2179
 2180    //     pub fn remove_keymap_context_layer<Tag: 'static>(&mut self, cx: &mut ViewContext<Self>) {
 2181    //         self.keymap_context_layers.remove(&TypeId::of::<Tag>());
 2182    //         cx.notify();
 2183    //     }
 2184
 2185    //     pub fn set_input_enabled(&mut self, input_enabled: bool) {
 2186    //         self.input_enabled = input_enabled;
 2187    //     }
 2188
 2189    //     pub fn set_autoindent(&mut self, autoindent: bool) {
 2190    //         if autoindent {
 2191    //             self.autoindent_mode = Some(AutoindentMode::EachLine);
 2192    //         } else {
 2193    //             self.autoindent_mode = None;
 2194    //         }
 2195    //     }
 2196
 2197    //     pub fn read_only(&self) -> bool {
 2198    //         self.read_only
 2199    //     }
 2200
 2201    //     pub fn set_read_only(&mut self, read_only: bool) {
 2202    //         self.read_only = read_only;
 2203    //     }
 2204
 2205    //     pub fn set_field_editor_style(
 2206    //         &mut self,
 2207    //         style: Option<Arc<GetFieldEditorTheme>>,
 2208    //         cx: &mut ViewContext<Self>,
 2209    //     ) {
 2210    //         self.get_field_editor_theme = style;
 2211    //         cx.notify();
 2212    //     }
 2213
 2214    fn selections_did_change(
 2215        &mut self,
 2216        local: bool,
 2217        old_cursor_position: &Anchor,
 2218        cx: &mut ViewContext<Self>,
 2219    ) {
 2220        if self.focus_handle.is_focused(cx) && self.leader_peer_id.is_none() {
 2221            self.buffer.update(cx, |buffer, cx| {
 2222                buffer.set_active_selections(
 2223                    &self.selections.disjoint_anchors(),
 2224                    self.selections.line_mode,
 2225                    self.cursor_shape,
 2226                    cx,
 2227                )
 2228            });
 2229        }
 2230
 2231        let display_map = self
 2232            .display_map
 2233            .update(cx, |display_map, cx| display_map.snapshot(cx));
 2234        let buffer = &display_map.buffer_snapshot;
 2235        self.add_selections_state = None;
 2236        self.select_next_state = None;
 2237        self.select_prev_state = None;
 2238        self.select_larger_syntax_node_stack.clear();
 2239        self.invalidate_autoclose_regions(&self.selections.disjoint_anchors(), buffer);
 2240        self.snippet_stack
 2241            .invalidate(&self.selections.disjoint_anchors(), buffer);
 2242        self.take_rename(false, cx);
 2243
 2244        let new_cursor_position = self.selections.newest_anchor().head();
 2245
 2246        self.push_to_nav_history(
 2247            old_cursor_position.clone(),
 2248            Some(new_cursor_position.to_point(buffer)),
 2249            cx,
 2250        );
 2251
 2252        if local {
 2253            let new_cursor_position = self.selections.newest_anchor().head();
 2254            let mut context_menu = self.context_menu.write();
 2255            let completion_menu = match context_menu.as_ref() {
 2256                Some(ContextMenu::Completions(menu)) => Some(menu),
 2257
 2258                _ => {
 2259                    *context_menu = None;
 2260                    None
 2261                }
 2262            };
 2263
 2264            if let Some(completion_menu) = completion_menu {
 2265                let cursor_position = new_cursor_position.to_offset(buffer);
 2266                let (word_range, kind) =
 2267                    buffer.surrounding_word(completion_menu.initial_position.clone());
 2268                if kind == Some(CharKind::Word)
 2269                    && word_range.to_inclusive().contains(&cursor_position)
 2270                {
 2271                    let mut completion_menu = completion_menu.clone();
 2272                    drop(context_menu);
 2273
 2274                    let query = Self::completion_query(buffer, cursor_position);
 2275                    cx.spawn(move |this, mut cx| async move {
 2276                        completion_menu
 2277                            .filter(query.as_deref(), cx.background_executor().clone())
 2278                            .await;
 2279
 2280                        this.update(&mut cx, |this, cx| {
 2281                            let mut context_menu = this.context_menu.write();
 2282                            let Some(ContextMenu::Completions(menu)) = context_menu.as_ref() else {
 2283                                return;
 2284                            };
 2285
 2286                            if menu.id > completion_menu.id {
 2287                                return;
 2288                            }
 2289
 2290                            *context_menu = Some(ContextMenu::Completions(completion_menu));
 2291                            drop(context_menu);
 2292                            cx.notify();
 2293                        })
 2294                    })
 2295                    .detach();
 2296
 2297                    self.show_completions(&ShowCompletions, cx);
 2298                } else {
 2299                    drop(context_menu);
 2300                    self.hide_context_menu(cx);
 2301                }
 2302            } else {
 2303                drop(context_menu);
 2304            }
 2305
 2306            hide_hover(self, cx);
 2307
 2308            if old_cursor_position.to_display_point(&display_map).row()
 2309                != new_cursor_position.to_display_point(&display_map).row()
 2310            {
 2311                self.available_code_actions.take();
 2312            }
 2313            self.refresh_code_actions(cx);
 2314            self.refresh_document_highlights(cx);
 2315            refresh_matching_bracket_highlights(self, cx);
 2316            self.discard_copilot_suggestion(cx);
 2317        }
 2318
 2319        self.blink_manager.update(cx, BlinkManager::pause_blinking);
 2320        cx.emit(EditorEvent::SelectionsChanged { local });
 2321        cx.emit(SearchEvent::MatchesInvalidated);
 2322
 2323        if self.selections.disjoint_anchors().len() == 1 {
 2324            cx.emit(SearchEvent::ActiveMatchChanged)
 2325        }
 2326
 2327        if local {
 2328            cx.emit(ItemEvent::UpdateBreadcrumbs);
 2329        }
 2330
 2331        cx.notify();
 2332    }
 2333
 2334    pub fn change_selections<R>(
 2335        &mut self,
 2336        autoscroll: Option<Autoscroll>,
 2337        cx: &mut ViewContext<Self>,
 2338        change: impl FnOnce(&mut MutableSelectionsCollection<'_>) -> R,
 2339    ) -> R {
 2340        let old_cursor_position = self.selections.newest_anchor().head();
 2341        self.push_to_selection_history();
 2342
 2343        let (changed, result) = self.selections.change_with(cx, change);
 2344
 2345        if changed {
 2346            if let Some(autoscroll) = autoscroll {
 2347                self.request_autoscroll(autoscroll, cx);
 2348            }
 2349            self.selections_did_change(true, &old_cursor_position, cx);
 2350        }
 2351
 2352        result
 2353    }
 2354
 2355    pub fn edit<I, S, T>(&mut self, edits: I, cx: &mut ViewContext<Self>)
 2356    where
 2357        I: IntoIterator<Item = (Range<S>, T)>,
 2358        S: ToOffset,
 2359        T: Into<Arc<str>>,
 2360    {
 2361        if self.read_only {
 2362            return;
 2363        }
 2364
 2365        self.buffer
 2366            .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
 2367    }
 2368
 2369    pub fn edit_with_autoindent<I, S, T>(&mut self, edits: I, cx: &mut ViewContext<Self>)
 2370    where
 2371        I: IntoIterator<Item = (Range<S>, T)>,
 2372        S: ToOffset,
 2373        T: Into<Arc<str>>,
 2374    {
 2375        if self.read_only {
 2376            return;
 2377        }
 2378
 2379        self.buffer.update(cx, |buffer, cx| {
 2380            buffer.edit(edits, self.autoindent_mode.clone(), cx)
 2381        });
 2382    }
 2383
 2384    pub fn edit_with_block_indent<I, S, T>(
 2385        &mut self,
 2386        edits: I,
 2387        original_indent_columns: Vec<u32>,
 2388        cx: &mut ViewContext<Self>,
 2389    ) where
 2390        I: IntoIterator<Item = (Range<S>, T)>,
 2391        S: ToOffset,
 2392        T: Into<Arc<str>>,
 2393    {
 2394        if self.read_only {
 2395            return;
 2396        }
 2397
 2398        self.buffer.update(cx, |buffer, cx| {
 2399            buffer.edit(
 2400                edits,
 2401                Some(AutoindentMode::Block {
 2402                    original_indent_columns,
 2403                }),
 2404                cx,
 2405            )
 2406        });
 2407    }
 2408
 2409    fn select(&mut self, phase: SelectPhase, cx: &mut ViewContext<Self>) {
 2410        self.hide_context_menu(cx);
 2411
 2412        match phase {
 2413            SelectPhase::Begin {
 2414                position,
 2415                add,
 2416                click_count,
 2417            } => self.begin_selection(position, add, click_count, cx),
 2418            SelectPhase::BeginColumnar {
 2419                position,
 2420                goal_column,
 2421            } => self.begin_columnar_selection(position, goal_column, cx),
 2422            SelectPhase::Extend {
 2423                position,
 2424                click_count,
 2425            } => self.extend_selection(position, click_count, cx),
 2426            SelectPhase::Update {
 2427                position,
 2428                goal_column,
 2429                scroll_position,
 2430            } => self.update_selection(position, goal_column, scroll_position, cx),
 2431            SelectPhase::End => self.end_selection(cx),
 2432        }
 2433    }
 2434
 2435    fn extend_selection(
 2436        &mut self,
 2437        position: DisplayPoint,
 2438        click_count: usize,
 2439        cx: &mut ViewContext<Self>,
 2440    ) {
 2441        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 2442        let tail = self.selections.newest::<usize>(cx).tail();
 2443        self.begin_selection(position, false, click_count, cx);
 2444
 2445        let position = position.to_offset(&display_map, Bias::Left);
 2446        let tail_anchor = display_map.buffer_snapshot.anchor_before(tail);
 2447
 2448        let mut pending_selection = self
 2449            .selections
 2450            .pending_anchor()
 2451            .expect("extend_selection not called with pending selection");
 2452        if position >= tail {
 2453            pending_selection.start = tail_anchor;
 2454        } else {
 2455            pending_selection.end = tail_anchor;
 2456            pending_selection.reversed = true;
 2457        }
 2458
 2459        let mut pending_mode = self.selections.pending_mode().unwrap();
 2460        match &mut pending_mode {
 2461            SelectMode::Word(range) | SelectMode::Line(range) => *range = tail_anchor..tail_anchor,
 2462            _ => {}
 2463        }
 2464
 2465        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 2466            s.set_pending(pending_selection, pending_mode)
 2467        });
 2468    }
 2469
 2470    fn begin_selection(
 2471        &mut self,
 2472        position: DisplayPoint,
 2473        add: bool,
 2474        click_count: usize,
 2475        cx: &mut ViewContext<Self>,
 2476    ) {
 2477        if !self.focus_handle.is_focused(cx) {
 2478            cx.focus(&self.focus_handle);
 2479        }
 2480
 2481        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 2482        let buffer = &display_map.buffer_snapshot;
 2483        let newest_selection = self.selections.newest_anchor().clone();
 2484        let position = display_map.clip_point(position, Bias::Left);
 2485
 2486        let start;
 2487        let end;
 2488        let mode;
 2489        let auto_scroll;
 2490        match click_count {
 2491            1 => {
 2492                start = buffer.anchor_before(position.to_point(&display_map));
 2493                end = start.clone();
 2494                mode = SelectMode::Character;
 2495                auto_scroll = true;
 2496            }
 2497            2 => {
 2498                let range = movement::surrounding_word(&display_map, position);
 2499                start = buffer.anchor_before(range.start.to_point(&display_map));
 2500                end = buffer.anchor_before(range.end.to_point(&display_map));
 2501                mode = SelectMode::Word(start.clone()..end.clone());
 2502                auto_scroll = true;
 2503            }
 2504            3 => {
 2505                let position = display_map
 2506                    .clip_point(position, Bias::Left)
 2507                    .to_point(&display_map);
 2508                let line_start = display_map.prev_line_boundary(position).0;
 2509                let next_line_start = buffer.clip_point(
 2510                    display_map.next_line_boundary(position).0 + Point::new(1, 0),
 2511                    Bias::Left,
 2512                );
 2513                start = buffer.anchor_before(line_start);
 2514                end = buffer.anchor_before(next_line_start);
 2515                mode = SelectMode::Line(start.clone()..end.clone());
 2516                auto_scroll = true;
 2517            }
 2518            _ => {
 2519                start = buffer.anchor_before(0);
 2520                end = buffer.anchor_before(buffer.len());
 2521                mode = SelectMode::All;
 2522                auto_scroll = false;
 2523            }
 2524        }
 2525
 2526        self.change_selections(auto_scroll.then(|| Autoscroll::newest()), cx, |s| {
 2527            if !add {
 2528                s.clear_disjoint();
 2529            } else if click_count > 1 {
 2530                s.delete(newest_selection.id)
 2531            }
 2532
 2533            s.set_pending_anchor_range(start..end, mode);
 2534        });
 2535    }
 2536
 2537    fn begin_columnar_selection(
 2538        &mut self,
 2539        position: DisplayPoint,
 2540        goal_column: u32,
 2541        cx: &mut ViewContext<Self>,
 2542    ) {
 2543        if !self.focus_handle.is_focused(cx) {
 2544            cx.focus(&self.focus_handle);
 2545        }
 2546
 2547        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 2548        let tail = self.selections.newest::<Point>(cx).tail();
 2549        self.columnar_selection_tail = Some(display_map.buffer_snapshot.anchor_before(tail));
 2550
 2551        self.select_columns(
 2552            tail.to_display_point(&display_map),
 2553            position,
 2554            goal_column,
 2555            &display_map,
 2556            cx,
 2557        );
 2558    }
 2559
 2560    fn update_selection(
 2561        &mut self,
 2562        position: DisplayPoint,
 2563        goal_column: u32,
 2564        scroll_position: gpui::Point<f32>,
 2565        cx: &mut ViewContext<Self>,
 2566    ) {
 2567        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 2568
 2569        if let Some(tail) = self.columnar_selection_tail.as_ref() {
 2570            let tail = tail.to_display_point(&display_map);
 2571            self.select_columns(tail, position, goal_column, &display_map, cx);
 2572        } else if let Some(mut pending) = self.selections.pending_anchor() {
 2573            let buffer = self.buffer.read(cx).snapshot(cx);
 2574            let head;
 2575            let tail;
 2576            let mode = self.selections.pending_mode().unwrap();
 2577            match &mode {
 2578                SelectMode::Character => {
 2579                    head = position.to_point(&display_map);
 2580                    tail = pending.tail().to_point(&buffer);
 2581                }
 2582                SelectMode::Word(original_range) => {
 2583                    let original_display_range = original_range.start.to_display_point(&display_map)
 2584                        ..original_range.end.to_display_point(&display_map);
 2585                    let original_buffer_range = original_display_range.start.to_point(&display_map)
 2586                        ..original_display_range.end.to_point(&display_map);
 2587                    if movement::is_inside_word(&display_map, position)
 2588                        || original_display_range.contains(&position)
 2589                    {
 2590                        let word_range = movement::surrounding_word(&display_map, position);
 2591                        if word_range.start < original_display_range.start {
 2592                            head = word_range.start.to_point(&display_map);
 2593                        } else {
 2594                            head = word_range.end.to_point(&display_map);
 2595                        }
 2596                    } else {
 2597                        head = position.to_point(&display_map);
 2598                    }
 2599
 2600                    if head <= original_buffer_range.start {
 2601                        tail = original_buffer_range.end;
 2602                    } else {
 2603                        tail = original_buffer_range.start;
 2604                    }
 2605                }
 2606                SelectMode::Line(original_range) => {
 2607                    let original_range = original_range.to_point(&display_map.buffer_snapshot);
 2608
 2609                    let position = display_map
 2610                        .clip_point(position, Bias::Left)
 2611                        .to_point(&display_map);
 2612                    let line_start = display_map.prev_line_boundary(position).0;
 2613                    let next_line_start = buffer.clip_point(
 2614                        display_map.next_line_boundary(position).0 + Point::new(1, 0),
 2615                        Bias::Left,
 2616                    );
 2617
 2618                    if line_start < original_range.start {
 2619                        head = line_start
 2620                    } else {
 2621                        head = next_line_start
 2622                    }
 2623
 2624                    if head <= original_range.start {
 2625                        tail = original_range.end;
 2626                    } else {
 2627                        tail = original_range.start;
 2628                    }
 2629                }
 2630                SelectMode::All => {
 2631                    return;
 2632                }
 2633            };
 2634
 2635            if head < tail {
 2636                pending.start = buffer.anchor_before(head);
 2637                pending.end = buffer.anchor_before(tail);
 2638                pending.reversed = true;
 2639            } else {
 2640                pending.start = buffer.anchor_before(tail);
 2641                pending.end = buffer.anchor_before(head);
 2642                pending.reversed = false;
 2643            }
 2644
 2645            self.change_selections(None, cx, |s| {
 2646                s.set_pending(pending, mode);
 2647            });
 2648        } else {
 2649            log::error!("update_selection dispatched with no pending selection");
 2650            return;
 2651        }
 2652
 2653        self.set_scroll_position(scroll_position, cx);
 2654        cx.notify();
 2655    }
 2656
 2657    fn end_selection(&mut self, cx: &mut ViewContext<Self>) {
 2658        self.columnar_selection_tail.take();
 2659        if self.selections.pending_anchor().is_some() {
 2660            let selections = self.selections.all::<usize>(cx);
 2661            self.change_selections(None, cx, |s| {
 2662                s.select(selections);
 2663                s.clear_pending();
 2664            });
 2665        }
 2666    }
 2667
 2668    fn select_columns(
 2669        &mut self,
 2670        tail: DisplayPoint,
 2671        head: DisplayPoint,
 2672        goal_column: u32,
 2673        display_map: &DisplaySnapshot,
 2674        cx: &mut ViewContext<Self>,
 2675    ) {
 2676        let start_row = cmp::min(tail.row(), head.row());
 2677        let end_row = cmp::max(tail.row(), head.row());
 2678        let start_column = cmp::min(tail.column(), goal_column);
 2679        let end_column = cmp::max(tail.column(), goal_column);
 2680        let reversed = start_column < tail.column();
 2681
 2682        let selection_ranges = (start_row..=end_row)
 2683            .filter_map(|row| {
 2684                if start_column <= display_map.line_len(row) && !display_map.is_block_line(row) {
 2685                    let start = display_map
 2686                        .clip_point(DisplayPoint::new(row, start_column), Bias::Left)
 2687                        .to_point(display_map);
 2688                    let end = display_map
 2689                        .clip_point(DisplayPoint::new(row, end_column), Bias::Right)
 2690                        .to_point(display_map);
 2691                    if reversed {
 2692                        Some(end..start)
 2693                    } else {
 2694                        Some(start..end)
 2695                    }
 2696                } else {
 2697                    None
 2698                }
 2699            })
 2700            .collect::<Vec<_>>();
 2701
 2702        self.change_selections(None, cx, |s| {
 2703            s.select_ranges(selection_ranges);
 2704        });
 2705        cx.notify();
 2706    }
 2707
 2708    pub fn has_pending_nonempty_selection(&self) -> bool {
 2709        let pending_nonempty_selection = match self.selections.pending_anchor() {
 2710            Some(Selection { start, end, .. }) => start != end,
 2711            None => false,
 2712        };
 2713        pending_nonempty_selection || self.columnar_selection_tail.is_some()
 2714    }
 2715
 2716    pub fn has_pending_selection(&self) -> bool {
 2717        self.selections.pending_anchor().is_some() || self.columnar_selection_tail.is_some()
 2718    }
 2719
 2720    pub fn cancel(&mut self, _: &Cancel, cx: &mut ViewContext<Self>) {
 2721        if self.take_rename(false, cx).is_some() {
 2722            return;
 2723        }
 2724
 2725        if hide_hover(self, cx) {
 2726            return;
 2727        }
 2728
 2729        if self.hide_context_menu(cx).is_some() {
 2730            return;
 2731        }
 2732
 2733        if self.discard_copilot_suggestion(cx) {
 2734            return;
 2735        }
 2736
 2737        if self.snippet_stack.pop().is_some() {
 2738            return;
 2739        }
 2740
 2741        if self.mode == EditorMode::Full {
 2742            if self.active_diagnostics.is_some() {
 2743                self.dismiss_diagnostics(cx);
 2744                return;
 2745            }
 2746
 2747            if self.change_selections(Some(Autoscroll::fit()), cx, |s| s.try_cancel()) {
 2748                return;
 2749            }
 2750        }
 2751
 2752        cx.propagate();
 2753    }
 2754
 2755    pub fn handle_input(&mut self, text: &str, cx: &mut ViewContext<Self>) {
 2756        let text: Arc<str> = text.into();
 2757
 2758        if self.read_only {
 2759            return;
 2760        }
 2761
 2762        let selections = self.selections.all_adjusted(cx);
 2763        let mut brace_inserted = false;
 2764        let mut edits = Vec::new();
 2765        let mut new_selections = Vec::with_capacity(selections.len());
 2766        let mut new_autoclose_regions = Vec::new();
 2767        let snapshot = self.buffer.read(cx).read(cx);
 2768
 2769        for (selection, autoclose_region) in
 2770            self.selections_with_autoclose_regions(selections, &snapshot)
 2771        {
 2772            if let Some(scope) = snapshot.language_scope_at(selection.head()) {
 2773                // Determine if the inserted text matches the opening or closing
 2774                // bracket of any of this language's bracket pairs.
 2775                let mut bracket_pair = None;
 2776                let mut is_bracket_pair_start = false;
 2777                if !text.is_empty() {
 2778                    // `text` can be empty when an user is using IME (e.g. Chinese Wubi Simplified)
 2779                    //  and they are removing the character that triggered IME popup.
 2780                    for (pair, enabled) in scope.brackets() {
 2781                        if enabled && pair.close && pair.start.ends_with(text.as_ref()) {
 2782                            bracket_pair = Some(pair.clone());
 2783                            is_bracket_pair_start = true;
 2784                            break;
 2785                        } else if pair.end.as_str() == text.as_ref() {
 2786                            bracket_pair = Some(pair.clone());
 2787                            break;
 2788                        }
 2789                    }
 2790                }
 2791
 2792                if let Some(bracket_pair) = bracket_pair {
 2793                    if selection.is_empty() {
 2794                        if is_bracket_pair_start {
 2795                            let prefix_len = bracket_pair.start.len() - text.len();
 2796
 2797                            // If the inserted text is a suffix of an opening bracket and the
 2798                            // selection is preceded by the rest of the opening bracket, then
 2799                            // insert the closing bracket.
 2800                            let following_text_allows_autoclose = snapshot
 2801                                .chars_at(selection.start)
 2802                                .next()
 2803                                .map_or(true, |c| scope.should_autoclose_before(c));
 2804                            let preceding_text_matches_prefix = prefix_len == 0
 2805                                || (selection.start.column >= (prefix_len as u32)
 2806                                    && snapshot.contains_str_at(
 2807                                        Point::new(
 2808                                            selection.start.row,
 2809                                            selection.start.column - (prefix_len as u32),
 2810                                        ),
 2811                                        &bracket_pair.start[..prefix_len],
 2812                                    ));
 2813                            if following_text_allows_autoclose && preceding_text_matches_prefix {
 2814                                let anchor = snapshot.anchor_before(selection.end);
 2815                                new_selections.push((selection.map(|_| anchor), text.len()));
 2816                                new_autoclose_regions.push((
 2817                                    anchor,
 2818                                    text.len(),
 2819                                    selection.id,
 2820                                    bracket_pair.clone(),
 2821                                ));
 2822                                edits.push((
 2823                                    selection.range(),
 2824                                    format!("{}{}", text, bracket_pair.end).into(),
 2825                                ));
 2826                                brace_inserted = true;
 2827                                continue;
 2828                            }
 2829                        }
 2830
 2831                        if let Some(region) = autoclose_region {
 2832                            // If the selection is followed by an auto-inserted closing bracket,
 2833                            // then don't insert that closing bracket again; just move the selection
 2834                            // past the closing bracket.
 2835                            let should_skip = selection.end == region.range.end.to_point(&snapshot)
 2836                                && text.as_ref() == region.pair.end.as_str();
 2837                            if should_skip {
 2838                                let anchor = snapshot.anchor_after(selection.end);
 2839                                new_selections
 2840                                    .push((selection.map(|_| anchor), region.pair.end.len()));
 2841                                continue;
 2842                            }
 2843                        }
 2844                    }
 2845                    // If an opening bracket is 1 character long and is typed while
 2846                    // text is selected, then surround that text with the bracket pair.
 2847                    else if is_bracket_pair_start && bracket_pair.start.chars().count() == 1 {
 2848                        edits.push((selection.start..selection.start, text.clone()));
 2849                        edits.push((
 2850                            selection.end..selection.end,
 2851                            bracket_pair.end.as_str().into(),
 2852                        ));
 2853                        brace_inserted = true;
 2854                        new_selections.push((
 2855                            Selection {
 2856                                id: selection.id,
 2857                                start: snapshot.anchor_after(selection.start),
 2858                                end: snapshot.anchor_before(selection.end),
 2859                                reversed: selection.reversed,
 2860                                goal: selection.goal,
 2861                            },
 2862                            0,
 2863                        ));
 2864                        continue;
 2865                    }
 2866                }
 2867            }
 2868
 2869            // If not handling any auto-close operation, then just replace the selected
 2870            // text with the given input and move the selection to the end of the
 2871            // newly inserted text.
 2872            let anchor = snapshot.anchor_after(selection.end);
 2873            new_selections.push((selection.map(|_| anchor), 0));
 2874            edits.push((selection.start..selection.end, text.clone()));
 2875        }
 2876
 2877        drop(snapshot);
 2878        self.transact(cx, |this, cx| {
 2879            this.buffer.update(cx, |buffer, cx| {
 2880                buffer.edit(edits, this.autoindent_mode.clone(), cx);
 2881            });
 2882
 2883            let new_anchor_selections = new_selections.iter().map(|e| &e.0);
 2884            let new_selection_deltas = new_selections.iter().map(|e| e.1);
 2885            let snapshot = this.buffer.read(cx).read(cx);
 2886            let new_selections = resolve_multiple::<usize, _>(new_anchor_selections, &snapshot)
 2887                .zip(new_selection_deltas)
 2888                .map(|(selection, delta)| Selection {
 2889                    id: selection.id,
 2890                    start: selection.start + delta,
 2891                    end: selection.end + delta,
 2892                    reversed: selection.reversed,
 2893                    goal: SelectionGoal::None,
 2894                })
 2895                .collect::<Vec<_>>();
 2896
 2897            let mut i = 0;
 2898            for (position, delta, selection_id, pair) in new_autoclose_regions {
 2899                let position = position.to_offset(&snapshot) + delta;
 2900                let start = snapshot.anchor_before(position);
 2901                let end = snapshot.anchor_after(position);
 2902                while let Some(existing_state) = this.autoclose_regions.get(i) {
 2903                    match existing_state.range.start.cmp(&start, &snapshot) {
 2904                        Ordering::Less => i += 1,
 2905                        Ordering::Greater => break,
 2906                        Ordering::Equal => match end.cmp(&existing_state.range.end, &snapshot) {
 2907                            Ordering::Less => i += 1,
 2908                            Ordering::Equal => break,
 2909                            Ordering::Greater => break,
 2910                        },
 2911                    }
 2912                }
 2913                this.autoclose_regions.insert(
 2914                    i,
 2915                    AutocloseRegion {
 2916                        selection_id,
 2917                        range: start..end,
 2918                        pair,
 2919                    },
 2920                );
 2921            }
 2922
 2923            drop(snapshot);
 2924            let had_active_copilot_suggestion = this.has_active_copilot_suggestion(cx);
 2925            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(new_selections));
 2926
 2927            if !brace_inserted && EditorSettings::get_global(cx).use_on_type_format {
 2928                if let Some(on_type_format_task) =
 2929                    this.trigger_on_type_formatting(text.to_string(), cx)
 2930                {
 2931                    on_type_format_task.detach_and_log_err(cx);
 2932                }
 2933            }
 2934
 2935            if had_active_copilot_suggestion {
 2936                this.refresh_copilot_suggestions(true, cx);
 2937                if !this.has_active_copilot_suggestion(cx) {
 2938                    this.trigger_completion_on_input(&text, cx);
 2939                }
 2940            } else {
 2941                this.trigger_completion_on_input(&text, cx);
 2942                this.refresh_copilot_suggestions(true, cx);
 2943            }
 2944        });
 2945    }
 2946
 2947    pub fn newline(&mut self, _: &Newline, cx: &mut ViewContext<Self>) {
 2948        self.transact(cx, |this, cx| {
 2949            let (edits, selection_fixup_info): (Vec<_>, Vec<_>) = {
 2950                let selections = this.selections.all::<usize>(cx);
 2951                let multi_buffer = this.buffer.read(cx);
 2952                let buffer = multi_buffer.snapshot(cx);
 2953                selections
 2954                    .iter()
 2955                    .map(|selection| {
 2956                        let start_point = selection.start.to_point(&buffer);
 2957                        let mut indent = buffer.indent_size_for_line(start_point.row);
 2958                        indent.len = cmp::min(indent.len, start_point.column);
 2959                        let start = selection.start;
 2960                        let end = selection.end;
 2961                        let is_cursor = start == end;
 2962                        let language_scope = buffer.language_scope_at(start);
 2963                        let (comment_delimiter, insert_extra_newline) = if let Some(language) =
 2964                            &language_scope
 2965                        {
 2966                            let leading_whitespace_len = buffer
 2967                                .reversed_chars_at(start)
 2968                                .take_while(|c| c.is_whitespace() && *c != '\n')
 2969                                .map(|c| c.len_utf8())
 2970                                .sum::<usize>();
 2971
 2972                            let trailing_whitespace_len = buffer
 2973                                .chars_at(end)
 2974                                .take_while(|c| c.is_whitespace() && *c != '\n')
 2975                                .map(|c| c.len_utf8())
 2976                                .sum::<usize>();
 2977
 2978                            let insert_extra_newline =
 2979                                language.brackets().any(|(pair, enabled)| {
 2980                                    let pair_start = pair.start.trim_end();
 2981                                    let pair_end = pair.end.trim_start();
 2982
 2983                                    enabled
 2984                                        && pair.newline
 2985                                        && buffer.contains_str_at(
 2986                                            end + trailing_whitespace_len,
 2987                                            pair_end,
 2988                                        )
 2989                                        && buffer.contains_str_at(
 2990                                            (start - leading_whitespace_len)
 2991                                                .saturating_sub(pair_start.len()),
 2992                                            pair_start,
 2993                                        )
 2994                                });
 2995                            // Comment extension on newline is allowed only for cursor selections
 2996                            let comment_delimiter = language.line_comment_prefix().filter(|_| {
 2997                                let is_comment_extension_enabled =
 2998                                    multi_buffer.settings_at(0, cx).extend_comment_on_newline;
 2999                                is_cursor && is_comment_extension_enabled
 3000                            });
 3001                            let comment_delimiter = if let Some(delimiter) = comment_delimiter {
 3002                                buffer
 3003                                    .buffer_line_for_row(start_point.row)
 3004                                    .is_some_and(|(snapshot, range)| {
 3005                                        let mut index_of_first_non_whitespace = 0;
 3006                                        let line_starts_with_comment = snapshot
 3007                                            .chars_for_range(range)
 3008                                            .skip_while(|c| {
 3009                                                let should_skip = c.is_whitespace();
 3010                                                if should_skip {
 3011                                                    index_of_first_non_whitespace += 1;
 3012                                                }
 3013                                                should_skip
 3014                                            })
 3015                                            .take(delimiter.len())
 3016                                            .eq(delimiter.chars());
 3017                                        let cursor_is_placed_after_comment_marker =
 3018                                            index_of_first_non_whitespace + delimiter.len()
 3019                                                <= start_point.column as usize;
 3020                                        line_starts_with_comment
 3021                                            && cursor_is_placed_after_comment_marker
 3022                                    })
 3023                                    .then(|| delimiter.clone())
 3024                            } else {
 3025                                None
 3026                            };
 3027                            (comment_delimiter, insert_extra_newline)
 3028                        } else {
 3029                            (None, false)
 3030                        };
 3031
 3032                        let capacity_for_delimiter = comment_delimiter
 3033                            .as_deref()
 3034                            .map(str::len)
 3035                            .unwrap_or_default();
 3036                        let mut new_text =
 3037                            String::with_capacity(1 + capacity_for_delimiter + indent.len as usize);
 3038                        new_text.push_str("\n");
 3039                        new_text.extend(indent.chars());
 3040                        if let Some(delimiter) = &comment_delimiter {
 3041                            new_text.push_str(&delimiter);
 3042                        }
 3043                        if insert_extra_newline {
 3044                            new_text = new_text.repeat(2);
 3045                        }
 3046
 3047                        let anchor = buffer.anchor_after(end);
 3048                        let new_selection = selection.map(|_| anchor);
 3049                        (
 3050                            (start..end, new_text),
 3051                            (insert_extra_newline, new_selection),
 3052                        )
 3053                    })
 3054                    .unzip()
 3055            };
 3056
 3057            this.edit_with_autoindent(edits, cx);
 3058            let buffer = this.buffer.read(cx).snapshot(cx);
 3059            let new_selections = selection_fixup_info
 3060                .into_iter()
 3061                .map(|(extra_newline_inserted, new_selection)| {
 3062                    let mut cursor = new_selection.end.to_point(&buffer);
 3063                    if extra_newline_inserted {
 3064                        cursor.row -= 1;
 3065                        cursor.column = buffer.line_len(cursor.row);
 3066                    }
 3067                    new_selection.map(|_| cursor)
 3068                })
 3069                .collect();
 3070
 3071            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(new_selections));
 3072            this.refresh_copilot_suggestions(true, cx);
 3073        });
 3074    }
 3075
 3076    pub fn newline_above(&mut self, _: &NewlineAbove, cx: &mut ViewContext<Self>) {
 3077        let buffer = self.buffer.read(cx);
 3078        let snapshot = buffer.snapshot(cx);
 3079
 3080        let mut edits = Vec::new();
 3081        let mut rows = Vec::new();
 3082        let mut rows_inserted = 0;
 3083
 3084        for selection in self.selections.all_adjusted(cx) {
 3085            let cursor = selection.head();
 3086            let row = cursor.row;
 3087
 3088            let start_of_line = snapshot.clip_point(Point::new(row, 0), Bias::Left);
 3089
 3090            let newline = "\n".to_string();
 3091            edits.push((start_of_line..start_of_line, newline));
 3092
 3093            rows.push(row + rows_inserted);
 3094            rows_inserted += 1;
 3095        }
 3096
 3097        self.transact(cx, |editor, cx| {
 3098            editor.edit(edits, cx);
 3099
 3100            editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
 3101                let mut index = 0;
 3102                s.move_cursors_with(|map, _, _| {
 3103                    let row = rows[index];
 3104                    index += 1;
 3105
 3106                    let point = Point::new(row, 0);
 3107                    let boundary = map.next_line_boundary(point).1;
 3108                    let clipped = map.clip_point(boundary, Bias::Left);
 3109
 3110                    (clipped, SelectionGoal::None)
 3111                });
 3112            });
 3113
 3114            let mut indent_edits = Vec::new();
 3115            let multibuffer_snapshot = editor.buffer.read(cx).snapshot(cx);
 3116            for row in rows {
 3117                let indents = multibuffer_snapshot.suggested_indents(row..row + 1, cx);
 3118                for (row, indent) in indents {
 3119                    if indent.len == 0 {
 3120                        continue;
 3121                    }
 3122
 3123                    let text = match indent.kind {
 3124                        IndentKind::Space => " ".repeat(indent.len as usize),
 3125                        IndentKind::Tab => "\t".repeat(indent.len as usize),
 3126                    };
 3127                    let point = Point::new(row, 0);
 3128                    indent_edits.push((point..point, text));
 3129                }
 3130            }
 3131            editor.edit(indent_edits, cx);
 3132        });
 3133    }
 3134
 3135    pub fn newline_below(&mut self, _: &NewlineBelow, cx: &mut ViewContext<Self>) {
 3136        let buffer = self.buffer.read(cx);
 3137        let snapshot = buffer.snapshot(cx);
 3138
 3139        let mut edits = Vec::new();
 3140        let mut rows = Vec::new();
 3141        let mut rows_inserted = 0;
 3142
 3143        for selection in self.selections.all_adjusted(cx) {
 3144            let cursor = selection.head();
 3145            let row = cursor.row;
 3146
 3147            let point = Point::new(row + 1, 0);
 3148            let start_of_line = snapshot.clip_point(point, Bias::Left);
 3149
 3150            let newline = "\n".to_string();
 3151            edits.push((start_of_line..start_of_line, newline));
 3152
 3153            rows_inserted += 1;
 3154            rows.push(row + rows_inserted);
 3155        }
 3156
 3157        self.transact(cx, |editor, cx| {
 3158            editor.edit(edits, cx);
 3159
 3160            editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
 3161                let mut index = 0;
 3162                s.move_cursors_with(|map, _, _| {
 3163                    let row = rows[index];
 3164                    index += 1;
 3165
 3166                    let point = Point::new(row, 0);
 3167                    let boundary = map.next_line_boundary(point).1;
 3168                    let clipped = map.clip_point(boundary, Bias::Left);
 3169
 3170                    (clipped, SelectionGoal::None)
 3171                });
 3172            });
 3173
 3174            let mut indent_edits = Vec::new();
 3175            let multibuffer_snapshot = editor.buffer.read(cx).snapshot(cx);
 3176            for row in rows {
 3177                let indents = multibuffer_snapshot.suggested_indents(row..row + 1, cx);
 3178                for (row, indent) in indents {
 3179                    if indent.len == 0 {
 3180                        continue;
 3181                    }
 3182
 3183                    let text = match indent.kind {
 3184                        IndentKind::Space => " ".repeat(indent.len as usize),
 3185                        IndentKind::Tab => "\t".repeat(indent.len as usize),
 3186                    };
 3187                    let point = Point::new(row, 0);
 3188                    indent_edits.push((point..point, text));
 3189                }
 3190            }
 3191            editor.edit(indent_edits, cx);
 3192        });
 3193    }
 3194
 3195    pub fn insert(&mut self, text: &str, cx: &mut ViewContext<Self>) {
 3196        self.insert_with_autoindent_mode(
 3197            text,
 3198            Some(AutoindentMode::Block {
 3199                original_indent_columns: Vec::new(),
 3200            }),
 3201            cx,
 3202        );
 3203    }
 3204
 3205    fn insert_with_autoindent_mode(
 3206        &mut self,
 3207        text: &str,
 3208        autoindent_mode: Option<AutoindentMode>,
 3209        cx: &mut ViewContext<Self>,
 3210    ) {
 3211        if self.read_only {
 3212            return;
 3213        }
 3214
 3215        let text: Arc<str> = text.into();
 3216        self.transact(cx, |this, cx| {
 3217            let old_selections = this.selections.all_adjusted(cx);
 3218            let selection_anchors = this.buffer.update(cx, |buffer, cx| {
 3219                let anchors = {
 3220                    let snapshot = buffer.read(cx);
 3221                    old_selections
 3222                        .iter()
 3223                        .map(|s| {
 3224                            let anchor = snapshot.anchor_after(s.head());
 3225                            s.map(|_| anchor)
 3226                        })
 3227                        .collect::<Vec<_>>()
 3228                };
 3229                buffer.edit(
 3230                    old_selections
 3231                        .iter()
 3232                        .map(|s| (s.start..s.end, text.clone())),
 3233                    autoindent_mode,
 3234                    cx,
 3235                );
 3236                anchors
 3237            });
 3238
 3239            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 3240                s.select_anchors(selection_anchors);
 3241            })
 3242        });
 3243    }
 3244
 3245    fn trigger_completion_on_input(&mut self, text: &str, cx: &mut ViewContext<Self>) {
 3246        if !EditorSettings::get_global(cx).show_completions_on_input {
 3247            return;
 3248        }
 3249
 3250        let selection = self.selections.newest_anchor();
 3251        if self
 3252            .buffer
 3253            .read(cx)
 3254            .is_completion_trigger(selection.head(), text, cx)
 3255        {
 3256            self.show_completions(&ShowCompletions, cx);
 3257        } else {
 3258            self.hide_context_menu(cx);
 3259        }
 3260    }
 3261
 3262    /// If any empty selections is touching the start of its innermost containing autoclose
 3263    /// region, expand it to select the brackets.
 3264    fn select_autoclose_pair(&mut self, cx: &mut ViewContext<Self>) {
 3265        let selections = self.selections.all::<usize>(cx);
 3266        let buffer = self.buffer.read(cx).read(cx);
 3267        let mut new_selections = Vec::new();
 3268        for (mut selection, region) in self.selections_with_autoclose_regions(selections, &buffer) {
 3269            if let (Some(region), true) = (region, selection.is_empty()) {
 3270                let mut range = region.range.to_offset(&buffer);
 3271                if selection.start == range.start {
 3272                    if range.start >= region.pair.start.len() {
 3273                        range.start -= region.pair.start.len();
 3274                        if buffer.contains_str_at(range.start, &region.pair.start) {
 3275                            if buffer.contains_str_at(range.end, &region.pair.end) {
 3276                                range.end += region.pair.end.len();
 3277                                selection.start = range.start;
 3278                                selection.end = range.end;
 3279                            }
 3280                        }
 3281                    }
 3282                }
 3283            }
 3284            new_selections.push(selection);
 3285        }
 3286
 3287        drop(buffer);
 3288        self.change_selections(None, cx, |selections| selections.select(new_selections));
 3289    }
 3290
 3291    /// Iterate the given selections, and for each one, find the smallest surrounding
 3292    /// autoclose region. This uses the ordering of the selections and the autoclose
 3293    /// regions to avoid repeated comparisons.
 3294    fn selections_with_autoclose_regions<'a, D: ToOffset + Clone>(
 3295        &'a self,
 3296        selections: impl IntoIterator<Item = Selection<D>>,
 3297        buffer: &'a MultiBufferSnapshot,
 3298    ) -> impl Iterator<Item = (Selection<D>, Option<&'a AutocloseRegion>)> {
 3299        let mut i = 0;
 3300        let mut regions = self.autoclose_regions.as_slice();
 3301        selections.into_iter().map(move |selection| {
 3302            let range = selection.start.to_offset(buffer)..selection.end.to_offset(buffer);
 3303
 3304            let mut enclosing = None;
 3305            while let Some(pair_state) = regions.get(i) {
 3306                if pair_state.range.end.to_offset(buffer) < range.start {
 3307                    regions = &regions[i + 1..];
 3308                    i = 0;
 3309                } else if pair_state.range.start.to_offset(buffer) > range.end {
 3310                    break;
 3311                } else {
 3312                    if pair_state.selection_id == selection.id {
 3313                        enclosing = Some(pair_state);
 3314                    }
 3315                    i += 1;
 3316                }
 3317            }
 3318
 3319            (selection.clone(), enclosing)
 3320        })
 3321    }
 3322
 3323    /// Remove any autoclose regions that no longer contain their selection.
 3324    fn invalidate_autoclose_regions(
 3325        &mut self,
 3326        mut selections: &[Selection<Anchor>],
 3327        buffer: &MultiBufferSnapshot,
 3328    ) {
 3329        self.autoclose_regions.retain(|state| {
 3330            let mut i = 0;
 3331            while let Some(selection) = selections.get(i) {
 3332                if selection.end.cmp(&state.range.start, buffer).is_lt() {
 3333                    selections = &selections[1..];
 3334                    continue;
 3335                }
 3336                if selection.start.cmp(&state.range.end, buffer).is_gt() {
 3337                    break;
 3338                }
 3339                if selection.id == state.selection_id {
 3340                    return true;
 3341                } else {
 3342                    i += 1;
 3343                }
 3344            }
 3345            false
 3346        });
 3347    }
 3348
 3349    fn completion_query(buffer: &MultiBufferSnapshot, position: impl ToOffset) -> Option<String> {
 3350        let offset = position.to_offset(buffer);
 3351        let (word_range, kind) = buffer.surrounding_word(offset);
 3352        if offset > word_range.start && kind == Some(CharKind::Word) {
 3353            Some(
 3354                buffer
 3355                    .text_for_range(word_range.start..offset)
 3356                    .collect::<String>(),
 3357            )
 3358        } else {
 3359            None
 3360        }
 3361    }
 3362
 3363    pub fn toggle_inlay_hints(&mut self, _: &ToggleInlayHints, cx: &mut ViewContext<Self>) {
 3364        self.refresh_inlay_hints(
 3365            InlayHintRefreshReason::Toggle(!self.inlay_hint_cache.enabled),
 3366            cx,
 3367        );
 3368    }
 3369
 3370    pub fn inlay_hints_enabled(&self) -> bool {
 3371        self.inlay_hint_cache.enabled
 3372    }
 3373
 3374    fn refresh_inlay_hints(&mut self, reason: InlayHintRefreshReason, cx: &mut ViewContext<Self>) {
 3375        if self.project.is_none() || self.mode != EditorMode::Full {
 3376            return;
 3377        }
 3378
 3379        let reason_description = reason.description();
 3380        let (invalidate_cache, required_languages) = match reason {
 3381            InlayHintRefreshReason::Toggle(enabled) => {
 3382                self.inlay_hint_cache.enabled = enabled;
 3383                if enabled {
 3384                    (InvalidationStrategy::RefreshRequested, None)
 3385                } else {
 3386                    self.inlay_hint_cache.clear();
 3387                    self.splice_inlay_hints(
 3388                        self.visible_inlay_hints(cx)
 3389                            .iter()
 3390                            .map(|inlay| inlay.id)
 3391                            .collect(),
 3392                        Vec::new(),
 3393                        cx,
 3394                    );
 3395                    return;
 3396                }
 3397            }
 3398            InlayHintRefreshReason::SettingsChange(new_settings) => {
 3399                match self.inlay_hint_cache.update_settings(
 3400                    &self.buffer,
 3401                    new_settings,
 3402                    self.visible_inlay_hints(cx),
 3403                    cx,
 3404                ) {
 3405                    ControlFlow::Break(Some(InlaySplice {
 3406                        to_remove,
 3407                        to_insert,
 3408                    })) => {
 3409                        self.splice_inlay_hints(to_remove, to_insert, cx);
 3410                        return;
 3411                    }
 3412                    ControlFlow::Break(None) => return,
 3413                    ControlFlow::Continue(()) => (InvalidationStrategy::RefreshRequested, None),
 3414                }
 3415            }
 3416            InlayHintRefreshReason::ExcerptsRemoved(excerpts_removed) => {
 3417                if let Some(InlaySplice {
 3418                    to_remove,
 3419                    to_insert,
 3420                }) = self.inlay_hint_cache.remove_excerpts(excerpts_removed)
 3421                {
 3422                    self.splice_inlay_hints(to_remove, to_insert, cx);
 3423                }
 3424                return;
 3425            }
 3426            InlayHintRefreshReason::NewLinesShown => (InvalidationStrategy::None, None),
 3427            InlayHintRefreshReason::BufferEdited(buffer_languages) => {
 3428                (InvalidationStrategy::BufferEdited, Some(buffer_languages))
 3429            }
 3430            InlayHintRefreshReason::RefreshRequested => {
 3431                (InvalidationStrategy::RefreshRequested, None)
 3432            }
 3433        };
 3434
 3435        if let Some(InlaySplice {
 3436            to_remove,
 3437            to_insert,
 3438        }) = self.inlay_hint_cache.spawn_hint_refresh(
 3439            reason_description,
 3440            self.excerpt_visible_offsets(required_languages.as_ref(), cx),
 3441            invalidate_cache,
 3442            cx,
 3443        ) {
 3444            self.splice_inlay_hints(to_remove, to_insert, cx);
 3445        }
 3446    }
 3447
 3448    fn visible_inlay_hints(&self, cx: &ViewContext<'_, Editor>) -> Vec<Inlay> {
 3449        self.display_map
 3450            .read(cx)
 3451            .current_inlays()
 3452            .filter(move |inlay| {
 3453                Some(inlay.id) != self.copilot_state.suggestion.as_ref().map(|h| h.id)
 3454            })
 3455            .cloned()
 3456            .collect()
 3457    }
 3458
 3459    pub fn excerpt_visible_offsets(
 3460        &self,
 3461        restrict_to_languages: Option<&HashSet<Arc<Language>>>,
 3462        cx: &mut ViewContext<Editor>,
 3463    ) -> HashMap<ExcerptId, (Model<Buffer>, clock::Global, Range<usize>)> {
 3464        let multi_buffer = self.buffer().read(cx);
 3465        let multi_buffer_snapshot = multi_buffer.snapshot(cx);
 3466        let multi_buffer_visible_start = self
 3467            .scroll_manager
 3468            .anchor()
 3469            .anchor
 3470            .to_point(&multi_buffer_snapshot);
 3471        let multi_buffer_visible_end = multi_buffer_snapshot.clip_point(
 3472            multi_buffer_visible_start
 3473                + Point::new(self.visible_line_count().unwrap_or(0.).ceil() as u32, 0),
 3474            Bias::Left,
 3475        );
 3476        let multi_buffer_visible_range = multi_buffer_visible_start..multi_buffer_visible_end;
 3477        multi_buffer
 3478            .range_to_buffer_ranges(multi_buffer_visible_range, cx)
 3479            .into_iter()
 3480            .filter(|(_, excerpt_visible_range, _)| !excerpt_visible_range.is_empty())
 3481            .filter_map(|(buffer_handle, excerpt_visible_range, excerpt_id)| {
 3482                let buffer = buffer_handle.read(cx);
 3483                let language = buffer.language()?;
 3484                if let Some(restrict_to_languages) = restrict_to_languages {
 3485                    if !restrict_to_languages.contains(language) {
 3486                        return None;
 3487                    }
 3488                }
 3489                Some((
 3490                    excerpt_id,
 3491                    (
 3492                        buffer_handle,
 3493                        buffer.version().clone(),
 3494                        excerpt_visible_range,
 3495                    ),
 3496                ))
 3497            })
 3498            .collect()
 3499    }
 3500
 3501    pub fn text_layout_details(&self, cx: &WindowContext) -> TextLayoutDetails {
 3502        TextLayoutDetails {
 3503            text_system: cx.text_system().clone(),
 3504            editor_style: self.style.clone().unwrap(),
 3505            rem_size: cx.rem_size(),
 3506        }
 3507    }
 3508
 3509    fn splice_inlay_hints(
 3510        &self,
 3511        to_remove: Vec<InlayId>,
 3512        to_insert: Vec<Inlay>,
 3513        cx: &mut ViewContext<Self>,
 3514    ) {
 3515        self.display_map.update(cx, |display_map, cx| {
 3516            display_map.splice_inlays(to_remove, to_insert, cx);
 3517        });
 3518        cx.notify();
 3519    }
 3520
 3521    fn trigger_on_type_formatting(
 3522        &self,
 3523        input: String,
 3524        cx: &mut ViewContext<Self>,
 3525    ) -> Option<Task<Result<()>>> {
 3526        if input.len() != 1 {
 3527            return None;
 3528        }
 3529
 3530        let project = self.project.as_ref()?;
 3531        let position = self.selections.newest_anchor().head();
 3532        let (buffer, buffer_position) = self
 3533            .buffer
 3534            .read(cx)
 3535            .text_anchor_for_position(position.clone(), cx)?;
 3536
 3537        // OnTypeFormatting returns a list of edits, no need to pass them between Zed instances,
 3538        // hence we do LSP request & edit on host side only — add formats to host's history.
 3539        let push_to_lsp_host_history = true;
 3540        // If this is not the host, append its history with new edits.
 3541        let push_to_client_history = project.read(cx).is_remote();
 3542
 3543        let on_type_formatting = project.update(cx, |project, cx| {
 3544            project.on_type_format(
 3545                buffer.clone(),
 3546                buffer_position,
 3547                input,
 3548                push_to_lsp_host_history,
 3549                cx,
 3550            )
 3551        });
 3552        Some(cx.spawn(|editor, mut cx| async move {
 3553            if let Some(transaction) = on_type_formatting.await? {
 3554                if push_to_client_history {
 3555                    buffer.update(&mut cx, |buffer, _| {
 3556                        buffer.push_transaction(transaction, Instant::now());
 3557                    });
 3558                }
 3559                editor.update(&mut cx, |editor, cx| {
 3560                    editor.refresh_document_highlights(cx);
 3561                })?;
 3562            }
 3563            Ok(())
 3564        }))
 3565    }
 3566
 3567    fn show_completions(&mut self, _: &ShowCompletions, cx: &mut ViewContext<Self>) {
 3568        if self.pending_rename.is_some() {
 3569            return;
 3570        }
 3571
 3572        let project = if let Some(project) = self.project.clone() {
 3573            project
 3574        } else {
 3575            return;
 3576        };
 3577
 3578        let position = self.selections.newest_anchor().head();
 3579        let (buffer, buffer_position) = if let Some(output) = self
 3580            .buffer
 3581            .read(cx)
 3582            .text_anchor_for_position(position.clone(), cx)
 3583        {
 3584            output
 3585        } else {
 3586            return;
 3587        };
 3588
 3589        let query = Self::completion_query(&self.buffer.read(cx).read(cx), position.clone());
 3590        let completions = project.update(cx, |project, cx| {
 3591            project.completions(&buffer, buffer_position, cx)
 3592        });
 3593
 3594        let id = post_inc(&mut self.next_completion_id);
 3595        let task = cx.spawn(|this, mut cx| {
 3596            async move {
 3597                let menu = if let Some(completions) = completions.await.log_err() {
 3598                    let mut menu = CompletionsMenu {
 3599                        id,
 3600                        initial_position: position,
 3601                        match_candidates: completions
 3602                            .iter()
 3603                            .enumerate()
 3604                            .map(|(id, completion)| {
 3605                                StringMatchCandidate::new(
 3606                                    id,
 3607                                    completion.label.text[completion.label.filter_range.clone()]
 3608                                        .into(),
 3609                                )
 3610                            })
 3611                            .collect(),
 3612                        buffer,
 3613                        completions: Arc::new(RwLock::new(completions.into())),
 3614                        matches: Vec::new().into(),
 3615                        selected_item: 0,
 3616                        scroll_handle: UniformListScrollHandle::new(),
 3617                    };
 3618                    menu.filter(query.as_deref(), cx.background_executor().clone())
 3619                        .await;
 3620                    if menu.matches.is_empty() {
 3621                        None
 3622                    } else {
 3623                        _ = this.update(&mut cx, |editor, cx| {
 3624                            menu.pre_resolve_completion_documentation(editor.project.clone(), cx);
 3625                        });
 3626                        Some(menu)
 3627                    }
 3628                } else {
 3629                    None
 3630                };
 3631
 3632                this.update(&mut cx, |this, cx| {
 3633                    this.completion_tasks.retain(|(task_id, _)| *task_id > id);
 3634
 3635                    let mut context_menu = this.context_menu.write();
 3636                    match context_menu.as_ref() {
 3637                        None => {}
 3638
 3639                        Some(ContextMenu::Completions(prev_menu)) => {
 3640                            if prev_menu.id > id {
 3641                                return;
 3642                            }
 3643                        }
 3644
 3645                        _ => return,
 3646                    }
 3647
 3648                    if this.focus_handle.is_focused(cx) && menu.is_some() {
 3649                        let menu = menu.unwrap();
 3650                        *context_menu = Some(ContextMenu::Completions(menu));
 3651                        drop(context_menu);
 3652                        this.discard_copilot_suggestion(cx);
 3653                        cx.notify();
 3654                    } else if this.completion_tasks.is_empty() {
 3655                        // If there are no more completion tasks and the last menu was
 3656                        // empty, we should hide it. If it was already hidden, we should
 3657                        // also show the copilot suggestion when available.
 3658                        drop(context_menu);
 3659                        if this.hide_context_menu(cx).is_none() {
 3660                            this.update_visible_copilot_suggestion(cx);
 3661                        }
 3662                    }
 3663                })?;
 3664
 3665                Ok::<_, anyhow::Error>(())
 3666            }
 3667            .log_err()
 3668        });
 3669        self.completion_tasks.push((id, task));
 3670    }
 3671
 3672    //     pub fn confirm_completion(
 3673    //         &mut self,
 3674    //         action: &ConfirmCompletion,
 3675    //         cx: &mut ViewContext<Self>,
 3676    //     ) -> Option<Task<Result<()>>> {
 3677    //         use language::ToOffset as _;
 3678
 3679    //         let completions_menu = if let ContextMenu::Completions(menu) = self.hide_context_menu(cx)? {
 3680    //             menu
 3681    //         } else {
 3682    //             return None;
 3683    //         };
 3684
 3685    //         let mat = completions_menu
 3686    //             .matches
 3687    //             .get(action.item_ix.unwrap_or(completions_menu.selected_item))?;
 3688    //         let buffer_handle = completions_menu.buffer;
 3689    //         let completions = completions_menu.completions.read();
 3690    //         let completion = completions.get(mat.candidate_id)?;
 3691
 3692    //         let snippet;
 3693    //         let text;
 3694    //         if completion.is_snippet() {
 3695    //             snippet = Some(Snippet::parse(&completion.new_text).log_err()?);
 3696    //             text = snippet.as_ref().unwrap().text.clone();
 3697    //         } else {
 3698    //             snippet = None;
 3699    //             text = completion.new_text.clone();
 3700    //         };
 3701    //         let selections = self.selections.all::<usize>(cx);
 3702    //         let buffer = buffer_handle.read(cx);
 3703    //         let old_range = completion.old_range.to_offset(buffer);
 3704    //         let old_text = buffer.text_for_range(old_range.clone()).collect::<String>();
 3705
 3706    //         let newest_selection = self.selections.newest_anchor();
 3707    //         if newest_selection.start.buffer_id != Some(buffer_handle.read(cx).remote_id()) {
 3708    //             return None;
 3709    //         }
 3710
 3711    //         let lookbehind = newest_selection
 3712    //             .start
 3713    //             .text_anchor
 3714    //             .to_offset(buffer)
 3715    //             .saturating_sub(old_range.start);
 3716    //         let lookahead = old_range
 3717    //             .end
 3718    //             .saturating_sub(newest_selection.end.text_anchor.to_offset(buffer));
 3719    //         let mut common_prefix_len = old_text
 3720    //             .bytes()
 3721    //             .zip(text.bytes())
 3722    //             .take_while(|(a, b)| a == b)
 3723    //             .count();
 3724
 3725    //         let snapshot = self.buffer.read(cx).snapshot(cx);
 3726    //         let mut range_to_replace: Option<Range<isize>> = None;
 3727    //         let mut ranges = Vec::new();
 3728    //         for selection in &selections {
 3729    //             if snapshot.contains_str_at(selection.start.saturating_sub(lookbehind), &old_text) {
 3730    //                 let start = selection.start.saturating_sub(lookbehind);
 3731    //                 let end = selection.end + lookahead;
 3732    //                 if selection.id == newest_selection.id {
 3733    //                     range_to_replace = Some(
 3734    //                         ((start + common_prefix_len) as isize - selection.start as isize)
 3735    //                             ..(end as isize - selection.start as isize),
 3736    //                     );
 3737    //                 }
 3738    //                 ranges.push(start + common_prefix_len..end);
 3739    //             } else {
 3740    //                 common_prefix_len = 0;
 3741    //                 ranges.clear();
 3742    //                 ranges.extend(selections.iter().map(|s| {
 3743    //                     if s.id == newest_selection.id {
 3744    //                         range_to_replace = Some(
 3745    //                             old_range.start.to_offset_utf16(&snapshot).0 as isize
 3746    //                                 - selection.start as isize
 3747    //                                 ..old_range.end.to_offset_utf16(&snapshot).0 as isize
 3748    //                                     - selection.start as isize,
 3749    //                         );
 3750    //                         old_range.clone()
 3751    //                     } else {
 3752    //                         s.start..s.end
 3753    //                     }
 3754    //                 }));
 3755    //                 break;
 3756    //             }
 3757    //         }
 3758    //         let text = &text[common_prefix_len..];
 3759
 3760    //         cx.emit(Event::InputHandled {
 3761    //             utf16_range_to_replace: range_to_replace,
 3762    //             text: text.into(),
 3763    //         });
 3764
 3765    //         self.transact(cx, |this, cx| {
 3766    //             if let Some(mut snippet) = snippet {
 3767    //                 snippet.text = text.to_string();
 3768    //                 for tabstop in snippet.tabstops.iter_mut().flatten() {
 3769    //                     tabstop.start -= common_prefix_len as isize;
 3770    //                     tabstop.end -= common_prefix_len as isize;
 3771    //                 }
 3772
 3773    //                 this.insert_snippet(&ranges, snippet, cx).log_err();
 3774    //             } else {
 3775    //                 this.buffer.update(cx, |buffer, cx| {
 3776    //                     buffer.edit(
 3777    //                         ranges.iter().map(|range| (range.clone(), text)),
 3778    //                         this.autoindent_mode.clone(),
 3779    //                         cx,
 3780    //                     );
 3781    //                 });
 3782    //             }
 3783
 3784    //             this.refresh_copilot_suggestions(true, cx);
 3785    //         });
 3786
 3787    //         let project = self.project.clone()?;
 3788    //         let apply_edits = project.update(cx, |project, cx| {
 3789    //             project.apply_additional_edits_for_completion(
 3790    //                 buffer_handle,
 3791    //                 completion.clone(),
 3792    //                 true,
 3793    //                 cx,
 3794    //             )
 3795    //         });
 3796    //         Some(cx.foreground().spawn(async move {
 3797    //             apply_edits.await?;
 3798    //             Ok(())
 3799    //         }))
 3800    //     }
 3801
 3802    pub fn toggle_code_actions(&mut self, action: &ToggleCodeActions, cx: &mut ViewContext<Self>) {
 3803        let mut context_menu = self.context_menu.write();
 3804        if matches!(context_menu.as_ref(), Some(ContextMenu::CodeActions(_))) {
 3805            *context_menu = None;
 3806            cx.notify();
 3807            return;
 3808        }
 3809        drop(context_menu);
 3810
 3811        let deployed_from_indicator = action.deployed_from_indicator;
 3812        let mut task = self.code_actions_task.take();
 3813        cx.spawn(|this, mut cx| async move {
 3814            while let Some(prev_task) = task {
 3815                prev_task.await;
 3816                task = this.update(&mut cx, |this, _| this.code_actions_task.take())?;
 3817            }
 3818
 3819            this.update(&mut cx, |this, cx| {
 3820                if this.focus_handle.is_focused(cx) {
 3821                    if let Some((buffer, actions)) = this.available_code_actions.clone() {
 3822                        this.completion_tasks.clear();
 3823                        this.discard_copilot_suggestion(cx);
 3824                        *this.context_menu.write() =
 3825                            Some(ContextMenu::CodeActions(CodeActionsMenu {
 3826                                buffer,
 3827                                actions,
 3828                                selected_item: Default::default(),
 3829                                scroll_handle: UniformListScrollHandle::default(),
 3830                                deployed_from_indicator,
 3831                            }));
 3832                        cx.notify();
 3833                    }
 3834                }
 3835            })?;
 3836
 3837            Ok::<_, anyhow::Error>(())
 3838        })
 3839        .detach_and_log_err(cx);
 3840    }
 3841
 3842    pub fn confirm_code_action(
 3843        &mut self,
 3844        action: &ConfirmCodeAction,
 3845        cx: &mut ViewContext<Self>,
 3846    ) -> Option<Task<Result<()>>> {
 3847        let actions_menu = if let ContextMenu::CodeActions(menu) = self.hide_context_menu(cx)? {
 3848            menu
 3849        } else {
 3850            return None;
 3851        };
 3852        let action_ix = action.item_ix.unwrap_or(actions_menu.selected_item);
 3853        let action = actions_menu.actions.get(action_ix)?.clone();
 3854        let title = action.lsp_action.title.clone();
 3855        let buffer = actions_menu.buffer;
 3856        let workspace = self.workspace()?;
 3857
 3858        let apply_code_actions = workspace
 3859            .read(cx)
 3860            .project()
 3861            .clone()
 3862            .update(cx, |project, cx| {
 3863                project.apply_code_action(buffer, action, true, cx)
 3864            });
 3865        let workspace = workspace.downgrade();
 3866        Some(cx.spawn(|editor, cx| async move {
 3867            let project_transaction = apply_code_actions.await?;
 3868            Self::open_project_transaction(&editor, workspace, project_transaction, title, cx).await
 3869        }))
 3870    }
 3871
 3872    async fn open_project_transaction(
 3873        this: &WeakView<Editor>,
 3874        workspace: WeakView<Workspace>,
 3875        transaction: ProjectTransaction,
 3876        title: String,
 3877        mut cx: AsyncWindowContext,
 3878    ) -> Result<()> {
 3879        let replica_id = this.update(&mut cx, |this, cx| this.replica_id(cx))?;
 3880
 3881        let mut entries = transaction.0.into_iter().collect::<Vec<_>>();
 3882        cx.update(|_, cx| {
 3883            entries.sort_unstable_by_key(|(buffer, _)| {
 3884                buffer.read(cx).file().map(|f| f.path().clone())
 3885            });
 3886        })?;
 3887
 3888        // If the project transaction's edits are all contained within this editor, then
 3889        // avoid opening a new editor to display them.
 3890
 3891        if let Some((buffer, transaction)) = entries.first() {
 3892            if entries.len() == 1 {
 3893                let excerpt = this.update(&mut cx, |editor, cx| {
 3894                    editor
 3895                        .buffer()
 3896                        .read(cx)
 3897                        .excerpt_containing(editor.selections.newest_anchor().head(), cx)
 3898                })?;
 3899                if let Some((_, excerpted_buffer, excerpt_range)) = excerpt {
 3900                    if excerpted_buffer == *buffer {
 3901                        let all_edits_within_excerpt = buffer.read_with(&cx, |buffer, _| {
 3902                            let excerpt_range = excerpt_range.to_offset(buffer);
 3903                            buffer
 3904                                .edited_ranges_for_transaction::<usize>(transaction)
 3905                                .all(|range| {
 3906                                    excerpt_range.start <= range.start
 3907                                        && excerpt_range.end >= range.end
 3908                                })
 3909                        })?;
 3910
 3911                        if all_edits_within_excerpt {
 3912                            return Ok(());
 3913                        }
 3914                    }
 3915                }
 3916            }
 3917        } else {
 3918            return Ok(());
 3919        }
 3920
 3921        let mut ranges_to_highlight = Vec::new();
 3922        let excerpt_buffer = cx.build_model(|cx| {
 3923            let mut multibuffer = MultiBuffer::new(replica_id).with_title(title);
 3924            for (buffer_handle, transaction) in &entries {
 3925                let buffer = buffer_handle.read(cx);
 3926                ranges_to_highlight.extend(
 3927                    multibuffer.push_excerpts_with_context_lines(
 3928                        buffer_handle.clone(),
 3929                        buffer
 3930                            .edited_ranges_for_transaction::<usize>(transaction)
 3931                            .collect(),
 3932                        1,
 3933                        cx,
 3934                    ),
 3935                );
 3936            }
 3937            multibuffer.push_transaction(entries.iter().map(|(b, t)| (b, t)), cx);
 3938            multibuffer
 3939        })?;
 3940
 3941        workspace.update(&mut cx, |workspace, cx| {
 3942            let project = workspace.project().clone();
 3943            let editor =
 3944                cx.build_view(|cx| Editor::for_multibuffer(excerpt_buffer, Some(project), cx));
 3945            workspace.add_item(Box::new(editor.clone()), cx);
 3946            editor.update(cx, |editor, cx| {
 3947                editor.highlight_background::<Self>(
 3948                    ranges_to_highlight,
 3949                    |theme| theme.editor_highlighted_line_background,
 3950                    cx,
 3951                );
 3952            });
 3953        })?;
 3954
 3955        Ok(())
 3956    }
 3957
 3958    fn refresh_code_actions(&mut self, cx: &mut ViewContext<Self>) -> Option<()> {
 3959        let project = self.project.clone()?;
 3960        let buffer = self.buffer.read(cx);
 3961        let newest_selection = self.selections.newest_anchor().clone();
 3962        let (start_buffer, start) = buffer.text_anchor_for_position(newest_selection.start, cx)?;
 3963        let (end_buffer, end) = buffer.text_anchor_for_position(newest_selection.end, cx)?;
 3964        if start_buffer != end_buffer {
 3965            return None;
 3966        }
 3967
 3968        self.code_actions_task = Some(cx.spawn(|this, mut cx| async move {
 3969            cx.background_executor()
 3970                .timer(CODE_ACTIONS_DEBOUNCE_TIMEOUT)
 3971                .await;
 3972
 3973            let actions = if let Ok(code_actions) = project.update(&mut cx, |project, cx| {
 3974                project.code_actions(&start_buffer, start..end, cx)
 3975            }) {
 3976                code_actions.await.log_err()
 3977            } else {
 3978                None
 3979            };
 3980
 3981            this.update(&mut cx, |this, cx| {
 3982                this.available_code_actions = actions.and_then(|actions| {
 3983                    if actions.is_empty() {
 3984                        None
 3985                    } else {
 3986                        Some((start_buffer, actions.into()))
 3987                    }
 3988                });
 3989                cx.notify();
 3990            })
 3991            .log_err();
 3992        }));
 3993        None
 3994    }
 3995
 3996    fn refresh_document_highlights(&mut self, cx: &mut ViewContext<Self>) -> Option<()> {
 3997        if self.pending_rename.is_some() {
 3998            return None;
 3999        }
 4000
 4001        let project = self.project.clone()?;
 4002        let buffer = self.buffer.read(cx);
 4003        let newest_selection = self.selections.newest_anchor().clone();
 4004        let cursor_position = newest_selection.head();
 4005        let (cursor_buffer, cursor_buffer_position) =
 4006            buffer.text_anchor_for_position(cursor_position.clone(), cx)?;
 4007        let (tail_buffer, _) = buffer.text_anchor_for_position(newest_selection.tail(), cx)?;
 4008        if cursor_buffer != tail_buffer {
 4009            return None;
 4010        }
 4011
 4012        self.document_highlights_task = Some(cx.spawn(|this, mut cx| async move {
 4013            cx.background_executor()
 4014                .timer(DOCUMENT_HIGHLIGHTS_DEBOUNCE_TIMEOUT)
 4015                .await;
 4016
 4017            let highlights = if let Some(highlights) = project
 4018                .update(&mut cx, |project, cx| {
 4019                    project.document_highlights(&cursor_buffer, cursor_buffer_position, cx)
 4020                })
 4021                .log_err()
 4022            {
 4023                highlights.await.log_err()
 4024            } else {
 4025                None
 4026            };
 4027
 4028            if let Some(highlights) = highlights {
 4029                this.update(&mut cx, |this, cx| {
 4030                    if this.pending_rename.is_some() {
 4031                        return;
 4032                    }
 4033
 4034                    let buffer_id = cursor_position.buffer_id;
 4035                    let buffer = this.buffer.read(cx);
 4036                    if !buffer
 4037                        .text_anchor_for_position(cursor_position, cx)
 4038                        .map_or(false, |(buffer, _)| buffer == cursor_buffer)
 4039                    {
 4040                        return;
 4041                    }
 4042
 4043                    let cursor_buffer_snapshot = cursor_buffer.read(cx);
 4044                    let mut write_ranges = Vec::new();
 4045                    let mut read_ranges = Vec::new();
 4046                    for highlight in highlights {
 4047                        for (excerpt_id, excerpt_range) in
 4048                            buffer.excerpts_for_buffer(&cursor_buffer, cx)
 4049                        {
 4050                            let start = highlight
 4051                                .range
 4052                                .start
 4053                                .max(&excerpt_range.context.start, cursor_buffer_snapshot);
 4054                            let end = highlight
 4055                                .range
 4056                                .end
 4057                                .min(&excerpt_range.context.end, cursor_buffer_snapshot);
 4058                            if start.cmp(&end, cursor_buffer_snapshot).is_ge() {
 4059                                continue;
 4060                            }
 4061
 4062                            let range = Anchor {
 4063                                buffer_id,
 4064                                excerpt_id: excerpt_id.clone(),
 4065                                text_anchor: start,
 4066                            }..Anchor {
 4067                                buffer_id,
 4068                                excerpt_id,
 4069                                text_anchor: end,
 4070                            };
 4071                            if highlight.kind == lsp::DocumentHighlightKind::WRITE {
 4072                                write_ranges.push(range);
 4073                            } else {
 4074                                read_ranges.push(range);
 4075                            }
 4076                        }
 4077                    }
 4078
 4079                    this.highlight_background::<DocumentHighlightRead>(
 4080                        read_ranges,
 4081                        |theme| theme.editor_document_highlight_read_background,
 4082                        cx,
 4083                    );
 4084                    this.highlight_background::<DocumentHighlightWrite>(
 4085                        write_ranges,
 4086                        |theme| theme.editor_document_highlight_write_background,
 4087                        cx,
 4088                    );
 4089                    cx.notify();
 4090                })
 4091                .log_err();
 4092            }
 4093        }));
 4094        None
 4095    }
 4096
 4097    fn refresh_copilot_suggestions(
 4098        &mut self,
 4099        debounce: bool,
 4100        cx: &mut ViewContext<Self>,
 4101    ) -> Option<()> {
 4102        let copilot = Copilot::global(cx)?;
 4103        if self.mode != EditorMode::Full || !copilot.read(cx).status().is_authorized() {
 4104            self.clear_copilot_suggestions(cx);
 4105            return None;
 4106        }
 4107        self.update_visible_copilot_suggestion(cx);
 4108
 4109        let snapshot = self.buffer.read(cx).snapshot(cx);
 4110        let cursor = self.selections.newest_anchor().head();
 4111        if !self.is_copilot_enabled_at(cursor, &snapshot, cx) {
 4112            self.clear_copilot_suggestions(cx);
 4113            return None;
 4114        }
 4115
 4116        let (buffer, buffer_position) =
 4117            self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
 4118        self.copilot_state.pending_refresh = cx.spawn(|this, mut cx| async move {
 4119            if debounce {
 4120                cx.background_executor()
 4121                    .timer(COPILOT_DEBOUNCE_TIMEOUT)
 4122                    .await;
 4123            }
 4124
 4125            let completions = copilot
 4126                .update(&mut cx, |copilot, cx| {
 4127                    copilot.completions(&buffer, buffer_position, cx)
 4128                })
 4129                .log_err()
 4130                .unwrap_or(Task::ready(Ok(Vec::new())))
 4131                .await
 4132                .log_err()
 4133                .into_iter()
 4134                .flatten()
 4135                .collect_vec();
 4136
 4137            this.update(&mut cx, |this, cx| {
 4138                if !completions.is_empty() {
 4139                    this.copilot_state.cycled = false;
 4140                    this.copilot_state.pending_cycling_refresh = Task::ready(None);
 4141                    this.copilot_state.completions.clear();
 4142                    this.copilot_state.active_completion_index = 0;
 4143                    this.copilot_state.excerpt_id = Some(cursor.excerpt_id);
 4144                    for completion in completions {
 4145                        this.copilot_state.push_completion(completion);
 4146                    }
 4147                    this.update_visible_copilot_suggestion(cx);
 4148                }
 4149            })
 4150            .log_err()?;
 4151            Some(())
 4152        });
 4153
 4154        Some(())
 4155    }
 4156
 4157    fn cycle_copilot_suggestions(
 4158        &mut self,
 4159        direction: Direction,
 4160        cx: &mut ViewContext<Self>,
 4161    ) -> Option<()> {
 4162        let copilot = Copilot::global(cx)?;
 4163        if self.mode != EditorMode::Full || !copilot.read(cx).status().is_authorized() {
 4164            return None;
 4165        }
 4166
 4167        if self.copilot_state.cycled {
 4168            self.copilot_state.cycle_completions(direction);
 4169            self.update_visible_copilot_suggestion(cx);
 4170        } else {
 4171            let cursor = self.selections.newest_anchor().head();
 4172            let (buffer, buffer_position) =
 4173                self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
 4174            self.copilot_state.pending_cycling_refresh = cx.spawn(|this, mut cx| async move {
 4175                let completions = copilot
 4176                    .update(&mut cx, |copilot, cx| {
 4177                        copilot.completions_cycling(&buffer, buffer_position, cx)
 4178                    })
 4179                    .log_err()?
 4180                    .await;
 4181
 4182                this.update(&mut cx, |this, cx| {
 4183                    this.copilot_state.cycled = true;
 4184                    for completion in completions.log_err().into_iter().flatten() {
 4185                        this.copilot_state.push_completion(completion);
 4186                    }
 4187                    this.copilot_state.cycle_completions(direction);
 4188                    this.update_visible_copilot_suggestion(cx);
 4189                })
 4190                .log_err()?;
 4191
 4192                Some(())
 4193            });
 4194        }
 4195
 4196        Some(())
 4197    }
 4198
 4199    fn copilot_suggest(&mut self, _: &copilot::Suggest, cx: &mut ViewContext<Self>) {
 4200        if !self.has_active_copilot_suggestion(cx) {
 4201            self.refresh_copilot_suggestions(false, cx);
 4202            return;
 4203        }
 4204
 4205        self.update_visible_copilot_suggestion(cx);
 4206    }
 4207
 4208    fn next_copilot_suggestion(&mut self, _: &copilot::NextSuggestion, cx: &mut ViewContext<Self>) {
 4209        if self.has_active_copilot_suggestion(cx) {
 4210            self.cycle_copilot_suggestions(Direction::Next, cx);
 4211        } else {
 4212            let is_copilot_disabled = self.refresh_copilot_suggestions(false, cx).is_none();
 4213            if is_copilot_disabled {
 4214                cx.propagate();
 4215            }
 4216        }
 4217    }
 4218
 4219    fn previous_copilot_suggestion(
 4220        &mut self,
 4221        _: &copilot::PreviousSuggestion,
 4222        cx: &mut ViewContext<Self>,
 4223    ) {
 4224        if self.has_active_copilot_suggestion(cx) {
 4225            self.cycle_copilot_suggestions(Direction::Prev, cx);
 4226        } else {
 4227            let is_copilot_disabled = self.refresh_copilot_suggestions(false, cx).is_none();
 4228            if is_copilot_disabled {
 4229                cx.propagate();
 4230            }
 4231        }
 4232    }
 4233
 4234    fn accept_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) -> bool {
 4235        if let Some(suggestion) = self.take_active_copilot_suggestion(cx) {
 4236            if let Some((copilot, completion)) =
 4237                Copilot::global(cx).zip(self.copilot_state.active_completion())
 4238            {
 4239                copilot
 4240                    .update(cx, |copilot, cx| copilot.accept_completion(completion, cx))
 4241                    .detach_and_log_err(cx);
 4242
 4243                self.report_copilot_event(Some(completion.uuid.clone()), true, cx)
 4244            }
 4245            cx.emit(EditorEvent::InputHandled {
 4246                utf16_range_to_replace: None,
 4247                text: suggestion.text.to_string().into(),
 4248            });
 4249            self.insert_with_autoindent_mode(&suggestion.text.to_string(), None, cx);
 4250            cx.notify();
 4251            true
 4252        } else {
 4253            false
 4254        }
 4255    }
 4256
 4257    fn discard_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) -> bool {
 4258        if let Some(suggestion) = self.take_active_copilot_suggestion(cx) {
 4259            if let Some(copilot) = Copilot::global(cx) {
 4260                copilot
 4261                    .update(cx, |copilot, cx| {
 4262                        copilot.discard_completions(&self.copilot_state.completions, cx)
 4263                    })
 4264                    .detach_and_log_err(cx);
 4265
 4266                self.report_copilot_event(None, false, cx)
 4267            }
 4268
 4269            self.display_map.update(cx, |map, cx| {
 4270                map.splice_inlays(vec![suggestion.id], Vec::new(), cx)
 4271            });
 4272            cx.notify();
 4273            true
 4274        } else {
 4275            false
 4276        }
 4277    }
 4278
 4279    fn is_copilot_enabled_at(
 4280        &self,
 4281        location: Anchor,
 4282        snapshot: &MultiBufferSnapshot,
 4283        cx: &mut ViewContext<Self>,
 4284    ) -> bool {
 4285        let file = snapshot.file_at(location);
 4286        let language = snapshot.language_at(location);
 4287        let settings = all_language_settings(file, cx);
 4288        settings.copilot_enabled(language, file.map(|f| f.path().as_ref()))
 4289    }
 4290
 4291    fn has_active_copilot_suggestion(&self, cx: &AppContext) -> bool {
 4292        if let Some(suggestion) = self.copilot_state.suggestion.as_ref() {
 4293            let buffer = self.buffer.read(cx).read(cx);
 4294            suggestion.position.is_valid(&buffer)
 4295        } else {
 4296            false
 4297        }
 4298    }
 4299
 4300    fn take_active_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) -> Option<Inlay> {
 4301        let suggestion = self.copilot_state.suggestion.take()?;
 4302        self.display_map.update(cx, |map, cx| {
 4303            map.splice_inlays(vec![suggestion.id], Default::default(), cx);
 4304        });
 4305        let buffer = self.buffer.read(cx).read(cx);
 4306
 4307        if suggestion.position.is_valid(&buffer) {
 4308            Some(suggestion)
 4309        } else {
 4310            None
 4311        }
 4312    }
 4313
 4314    fn update_visible_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) {
 4315        let snapshot = self.buffer.read(cx).snapshot(cx);
 4316        let selection = self.selections.newest_anchor();
 4317        let cursor = selection.head();
 4318
 4319        if self.context_menu.read().is_some()
 4320            || !self.completion_tasks.is_empty()
 4321            || selection.start != selection.end
 4322        {
 4323            self.discard_copilot_suggestion(cx);
 4324        } else if let Some(text) = self
 4325            .copilot_state
 4326            .text_for_active_completion(cursor, &snapshot)
 4327        {
 4328            let text = Rope::from(text);
 4329            let mut to_remove = Vec::new();
 4330            if let Some(suggestion) = self.copilot_state.suggestion.take() {
 4331                to_remove.push(suggestion.id);
 4332            }
 4333
 4334            let suggestion_inlay =
 4335                Inlay::suggestion(post_inc(&mut self.next_inlay_id), cursor, text);
 4336            self.copilot_state.suggestion = Some(suggestion_inlay.clone());
 4337            self.display_map.update(cx, move |map, cx| {
 4338                map.splice_inlays(to_remove, vec![suggestion_inlay], cx)
 4339            });
 4340            cx.notify();
 4341        } else {
 4342            self.discard_copilot_suggestion(cx);
 4343        }
 4344    }
 4345
 4346    fn clear_copilot_suggestions(&mut self, cx: &mut ViewContext<Self>) {
 4347        self.copilot_state = Default::default();
 4348        self.discard_copilot_suggestion(cx);
 4349    }
 4350
 4351    pub fn render_code_actions_indicator(
 4352        &self,
 4353        style: &EditorStyle,
 4354        is_active: bool,
 4355        cx: &mut ViewContext<Self>,
 4356    ) -> Option<IconButton> {
 4357        if self.available_code_actions.is_some() {
 4358            Some(
 4359                IconButton::new("code_actions_indicator", ui::Icon::Bolt).on_click(cx.listener(
 4360                    |editor, e, cx| {
 4361                        editor.toggle_code_actions(
 4362                            &ToggleCodeActions {
 4363                                deployed_from_indicator: true,
 4364                            },
 4365                            cx,
 4366                        );
 4367                    },
 4368                )),
 4369            )
 4370        } else {
 4371            None
 4372        }
 4373    }
 4374
 4375    pub fn render_fold_indicators(
 4376        &self,
 4377        fold_data: Vec<Option<(FoldStatus, u32, bool)>>,
 4378        style: &EditorStyle,
 4379        gutter_hovered: bool,
 4380        line_height: Pixels,
 4381        gutter_margin: Pixels,
 4382        cx: &mut ViewContext<Self>,
 4383    ) -> Vec<Option<IconButton>> {
 4384        fold_data
 4385            .iter()
 4386            .enumerate()
 4387            .map(|(ix, fold_data)| {
 4388                fold_data
 4389                    .map(|(fold_status, buffer_row, active)| {
 4390                        (active || gutter_hovered || fold_status == FoldStatus::Folded).then(|| {
 4391                            let icon = match fold_status {
 4392                                FoldStatus::Folded => ui::Icon::ChevronRight,
 4393                                FoldStatus::Foldable => ui::Icon::ChevronDown,
 4394                            };
 4395                            IconButton::new(ix as usize, icon)
 4396                                .on_click(cx.listener(move |editor, e, cx| match fold_status {
 4397                                    FoldStatus::Folded => {
 4398                                        editor.unfold_at(&UnfoldAt { buffer_row }, cx);
 4399                                    }
 4400                                    FoldStatus::Foldable => {
 4401                                        editor.fold_at(&FoldAt { buffer_row }, cx);
 4402                                    }
 4403                                }))
 4404                                .color(ui::Color::Muted)
 4405                        })
 4406                    })
 4407                    .flatten()
 4408            })
 4409            .collect()
 4410    }
 4411
 4412    pub fn context_menu_visible(&self) -> bool {
 4413        self.context_menu
 4414            .read()
 4415            .as_ref()
 4416            .map_or(false, |menu| menu.visible())
 4417    }
 4418
 4419    pub fn render_context_menu(
 4420        &self,
 4421        cursor_position: DisplayPoint,
 4422        style: &EditorStyle,
 4423        cx: &mut ViewContext<Editor>,
 4424    ) -> Option<(DisplayPoint, AnyElement)> {
 4425        self.context_menu.read().as_ref().map(|menu| {
 4426            menu.render(
 4427                cursor_position,
 4428                style,
 4429                self.workspace.as_ref().map(|(w, _)| w.clone()),
 4430                cx,
 4431            )
 4432        })
 4433    }
 4434
 4435    fn hide_context_menu(&mut self, cx: &mut ViewContext<Self>) -> Option<ContextMenu> {
 4436        cx.notify();
 4437        self.completion_tasks.clear();
 4438        let context_menu = self.context_menu.write().take();
 4439        if context_menu.is_some() {
 4440            self.update_visible_copilot_suggestion(cx);
 4441        }
 4442        context_menu
 4443    }
 4444
 4445    pub fn insert_snippet(
 4446        &mut self,
 4447        insertion_ranges: &[Range<usize>],
 4448        snippet: Snippet,
 4449        cx: &mut ViewContext<Self>,
 4450    ) -> Result<()> {
 4451        let tabstops = self.buffer.update(cx, |buffer, cx| {
 4452            let snippet_text: Arc<str> = snippet.text.clone().into();
 4453            buffer.edit(
 4454                insertion_ranges
 4455                    .iter()
 4456                    .cloned()
 4457                    .map(|range| (range, snippet_text.clone())),
 4458                Some(AutoindentMode::EachLine),
 4459                cx,
 4460            );
 4461
 4462            let snapshot = &*buffer.read(cx);
 4463            let snippet = &snippet;
 4464            snippet
 4465                .tabstops
 4466                .iter()
 4467                .map(|tabstop| {
 4468                    let mut tabstop_ranges = tabstop
 4469                        .iter()
 4470                        .flat_map(|tabstop_range| {
 4471                            let mut delta = 0_isize;
 4472                            insertion_ranges.iter().map(move |insertion_range| {
 4473                                let insertion_start = insertion_range.start as isize + delta;
 4474                                delta +=
 4475                                    snippet.text.len() as isize - insertion_range.len() as isize;
 4476
 4477                                let start = snapshot.anchor_before(
 4478                                    (insertion_start + tabstop_range.start) as usize,
 4479                                );
 4480                                let end = snapshot
 4481                                    .anchor_after((insertion_start + tabstop_range.end) as usize);
 4482                                start..end
 4483                            })
 4484                        })
 4485                        .collect::<Vec<_>>();
 4486                    tabstop_ranges.sort_unstable_by(|a, b| a.start.cmp(&b.start, snapshot));
 4487                    tabstop_ranges
 4488                })
 4489                .collect::<Vec<_>>()
 4490        });
 4491
 4492        if let Some(tabstop) = tabstops.first() {
 4493            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 4494                s.select_ranges(tabstop.iter().cloned());
 4495            });
 4496            self.snippet_stack.push(SnippetState {
 4497                active_index: 0,
 4498                ranges: tabstops,
 4499            });
 4500        }
 4501
 4502        Ok(())
 4503    }
 4504
 4505    pub fn move_to_next_snippet_tabstop(&mut self, cx: &mut ViewContext<Self>) -> bool {
 4506        self.move_to_snippet_tabstop(Bias::Right, cx)
 4507    }
 4508
 4509    pub fn move_to_prev_snippet_tabstop(&mut self, cx: &mut ViewContext<Self>) -> bool {
 4510        self.move_to_snippet_tabstop(Bias::Left, cx)
 4511    }
 4512
 4513    pub fn move_to_snippet_tabstop(&mut self, bias: Bias, cx: &mut ViewContext<Self>) -> bool {
 4514        if let Some(mut snippet) = self.snippet_stack.pop() {
 4515            match bias {
 4516                Bias::Left => {
 4517                    if snippet.active_index > 0 {
 4518                        snippet.active_index -= 1;
 4519                    } else {
 4520                        self.snippet_stack.push(snippet);
 4521                        return false;
 4522                    }
 4523                }
 4524                Bias::Right => {
 4525                    if snippet.active_index + 1 < snippet.ranges.len() {
 4526                        snippet.active_index += 1;
 4527                    } else {
 4528                        self.snippet_stack.push(snippet);
 4529                        return false;
 4530                    }
 4531                }
 4532            }
 4533            if let Some(current_ranges) = snippet.ranges.get(snippet.active_index) {
 4534                self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 4535                    s.select_anchor_ranges(current_ranges.iter().cloned())
 4536                });
 4537                // If snippet state is not at the last tabstop, push it back on the stack
 4538                if snippet.active_index + 1 < snippet.ranges.len() {
 4539                    self.snippet_stack.push(snippet);
 4540                }
 4541                return true;
 4542            }
 4543        }
 4544
 4545        false
 4546    }
 4547
 4548    pub fn clear(&mut self, cx: &mut ViewContext<Self>) {
 4549        self.transact(cx, |this, cx| {
 4550            this.select_all(&SelectAll, cx);
 4551            this.insert("", cx);
 4552        });
 4553    }
 4554
 4555    pub fn backspace(&mut self, _: &Backspace, cx: &mut ViewContext<Self>) {
 4556        self.transact(cx, |this, cx| {
 4557            this.select_autoclose_pair(cx);
 4558            let mut selections = this.selections.all::<Point>(cx);
 4559            if !this.selections.line_mode {
 4560                let display_map = this.display_map.update(cx, |map, cx| map.snapshot(cx));
 4561                for selection in &mut selections {
 4562                    if selection.is_empty() {
 4563                        let old_head = selection.head();
 4564                        let mut new_head =
 4565                            movement::left(&display_map, old_head.to_display_point(&display_map))
 4566                                .to_point(&display_map);
 4567                        if let Some((buffer, line_buffer_range)) = display_map
 4568                            .buffer_snapshot
 4569                            .buffer_line_for_row(old_head.row)
 4570                        {
 4571                            let indent_size =
 4572                                buffer.indent_size_for_line(line_buffer_range.start.row);
 4573                            let indent_len = match indent_size.kind {
 4574                                IndentKind::Space => {
 4575                                    buffer.settings_at(line_buffer_range.start, cx).tab_size
 4576                                }
 4577                                IndentKind::Tab => NonZeroU32::new(1).unwrap(),
 4578                            };
 4579                            if old_head.column <= indent_size.len && old_head.column > 0 {
 4580                                let indent_len = indent_len.get();
 4581                                new_head = cmp::min(
 4582                                    new_head,
 4583                                    Point::new(
 4584                                        old_head.row,
 4585                                        ((old_head.column - 1) / indent_len) * indent_len,
 4586                                    ),
 4587                                );
 4588                            }
 4589                        }
 4590
 4591                        selection.set_head(new_head, SelectionGoal::None);
 4592                    }
 4593                }
 4594            }
 4595
 4596            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
 4597            this.insert("", cx);
 4598            this.refresh_copilot_suggestions(true, cx);
 4599        });
 4600    }
 4601
 4602    pub fn delete(&mut self, _: &Delete, cx: &mut ViewContext<Self>) {
 4603        self.transact(cx, |this, cx| {
 4604            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 4605                let line_mode = s.line_mode;
 4606                s.move_with(|map, selection| {
 4607                    if selection.is_empty() && !line_mode {
 4608                        let cursor = movement::right(map, selection.head());
 4609                        selection.end = cursor;
 4610                        selection.reversed = true;
 4611                        selection.goal = SelectionGoal::None;
 4612                    }
 4613                })
 4614            });
 4615            this.insert("", cx);
 4616            this.refresh_copilot_suggestions(true, cx);
 4617        });
 4618    }
 4619
 4620    pub fn tab_prev(&mut self, _: &TabPrev, cx: &mut ViewContext<Self>) {
 4621        if self.move_to_prev_snippet_tabstop(cx) {
 4622            return;
 4623        }
 4624
 4625        self.outdent(&Outdent, cx);
 4626    }
 4627
 4628    pub fn tab(&mut self, _: &Tab, cx: &mut ViewContext<Self>) {
 4629        if self.move_to_next_snippet_tabstop(cx) {
 4630            return;
 4631        }
 4632
 4633        let mut selections = self.selections.all_adjusted(cx);
 4634        let buffer = self.buffer.read(cx);
 4635        let snapshot = buffer.snapshot(cx);
 4636        let rows_iter = selections.iter().map(|s| s.head().row);
 4637        let suggested_indents = snapshot.suggested_indents(rows_iter, cx);
 4638
 4639        let mut edits = Vec::new();
 4640        let mut prev_edited_row = 0;
 4641        let mut row_delta = 0;
 4642        for selection in &mut selections {
 4643            if selection.start.row != prev_edited_row {
 4644                row_delta = 0;
 4645            }
 4646            prev_edited_row = selection.end.row;
 4647
 4648            // If the selection is non-empty, then increase the indentation of the selected lines.
 4649            if !selection.is_empty() {
 4650                row_delta =
 4651                    Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
 4652                continue;
 4653            }
 4654
 4655            // If the selection is empty and the cursor is in the leading whitespace before the
 4656            // suggested indentation, then auto-indent the line.
 4657            let cursor = selection.head();
 4658            let current_indent = snapshot.indent_size_for_line(cursor.row);
 4659            if let Some(suggested_indent) = suggested_indents.get(&cursor.row).copied() {
 4660                if cursor.column < suggested_indent.len
 4661                    && cursor.column <= current_indent.len
 4662                    && current_indent.len <= suggested_indent.len
 4663                {
 4664                    selection.start = Point::new(cursor.row, suggested_indent.len);
 4665                    selection.end = selection.start;
 4666                    if row_delta == 0 {
 4667                        edits.extend(Buffer::edit_for_indent_size_adjustment(
 4668                            cursor.row,
 4669                            current_indent,
 4670                            suggested_indent,
 4671                        ));
 4672                        row_delta = suggested_indent.len - current_indent.len;
 4673                    }
 4674                    continue;
 4675                }
 4676            }
 4677
 4678            // Accept copilot suggestion if there is only one selection and the cursor is not
 4679            // in the leading whitespace.
 4680            if self.selections.count() == 1
 4681                && cursor.column >= current_indent.len
 4682                && self.has_active_copilot_suggestion(cx)
 4683            {
 4684                self.accept_copilot_suggestion(cx);
 4685                return;
 4686            }
 4687
 4688            // Otherwise, insert a hard or soft tab.
 4689            let settings = buffer.settings_at(cursor, cx);
 4690            let tab_size = if settings.hard_tabs {
 4691                IndentSize::tab()
 4692            } else {
 4693                let tab_size = settings.tab_size.get();
 4694                let char_column = snapshot
 4695                    .text_for_range(Point::new(cursor.row, 0)..cursor)
 4696                    .flat_map(str::chars)
 4697                    .count()
 4698                    + row_delta as usize;
 4699                let chars_to_next_tab_stop = tab_size - (char_column as u32 % tab_size);
 4700                IndentSize::spaces(chars_to_next_tab_stop)
 4701            };
 4702            selection.start = Point::new(cursor.row, cursor.column + row_delta + tab_size.len);
 4703            selection.end = selection.start;
 4704            edits.push((cursor..cursor, tab_size.chars().collect::<String>()));
 4705            row_delta += tab_size.len;
 4706        }
 4707
 4708        self.transact(cx, |this, cx| {
 4709            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
 4710            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
 4711            this.refresh_copilot_suggestions(true, cx);
 4712        });
 4713    }
 4714
 4715    pub fn indent(&mut self, _: &Indent, cx: &mut ViewContext<Self>) {
 4716        let mut selections = self.selections.all::<Point>(cx);
 4717        let mut prev_edited_row = 0;
 4718        let mut row_delta = 0;
 4719        let mut edits = Vec::new();
 4720        let buffer = self.buffer.read(cx);
 4721        let snapshot = buffer.snapshot(cx);
 4722        for selection in &mut selections {
 4723            if selection.start.row != prev_edited_row {
 4724                row_delta = 0;
 4725            }
 4726            prev_edited_row = selection.end.row;
 4727
 4728            row_delta =
 4729                Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
 4730        }
 4731
 4732        self.transact(cx, |this, cx| {
 4733            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
 4734            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
 4735        });
 4736    }
 4737
 4738    fn indent_selection(
 4739        buffer: &MultiBuffer,
 4740        snapshot: &MultiBufferSnapshot,
 4741        selection: &mut Selection<Point>,
 4742        edits: &mut Vec<(Range<Point>, String)>,
 4743        delta_for_start_row: u32,
 4744        cx: &AppContext,
 4745    ) -> u32 {
 4746        let settings = buffer.settings_at(selection.start, cx);
 4747        let tab_size = settings.tab_size.get();
 4748        let indent_kind = if settings.hard_tabs {
 4749            IndentKind::Tab
 4750        } else {
 4751            IndentKind::Space
 4752        };
 4753        let mut start_row = selection.start.row;
 4754        let mut end_row = selection.end.row + 1;
 4755
 4756        // If a selection ends at the beginning of a line, don't indent
 4757        // that last line.
 4758        if selection.end.column == 0 {
 4759            end_row -= 1;
 4760        }
 4761
 4762        // Avoid re-indenting a row that has already been indented by a
 4763        // previous selection, but still update this selection's column
 4764        // to reflect that indentation.
 4765        if delta_for_start_row > 0 {
 4766            start_row += 1;
 4767            selection.start.column += delta_for_start_row;
 4768            if selection.end.row == selection.start.row {
 4769                selection.end.column += delta_for_start_row;
 4770            }
 4771        }
 4772
 4773        let mut delta_for_end_row = 0;
 4774        for row in start_row..end_row {
 4775            let current_indent = snapshot.indent_size_for_line(row);
 4776            let indent_delta = match (current_indent.kind, indent_kind) {
 4777                (IndentKind::Space, IndentKind::Space) => {
 4778                    let columns_to_next_tab_stop = tab_size - (current_indent.len % tab_size);
 4779                    IndentSize::spaces(columns_to_next_tab_stop)
 4780                }
 4781                (IndentKind::Tab, IndentKind::Space) => IndentSize::spaces(tab_size),
 4782                (_, IndentKind::Tab) => IndentSize::tab(),
 4783            };
 4784
 4785            let row_start = Point::new(row, 0);
 4786            edits.push((
 4787                row_start..row_start,
 4788                indent_delta.chars().collect::<String>(),
 4789            ));
 4790
 4791            // Update this selection's endpoints to reflect the indentation.
 4792            if row == selection.start.row {
 4793                selection.start.column += indent_delta.len;
 4794            }
 4795            if row == selection.end.row {
 4796                selection.end.column += indent_delta.len;
 4797                delta_for_end_row = indent_delta.len;
 4798            }
 4799        }
 4800
 4801        if selection.start.row == selection.end.row {
 4802            delta_for_start_row + delta_for_end_row
 4803        } else {
 4804            delta_for_end_row
 4805        }
 4806    }
 4807
 4808    pub fn outdent(&mut self, _: &Outdent, cx: &mut ViewContext<Self>) {
 4809        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 4810        let selections = self.selections.all::<Point>(cx);
 4811        let mut deletion_ranges = Vec::new();
 4812        let mut last_outdent = None;
 4813        {
 4814            let buffer = self.buffer.read(cx);
 4815            let snapshot = buffer.snapshot(cx);
 4816            for selection in &selections {
 4817                let settings = buffer.settings_at(selection.start, cx);
 4818                let tab_size = settings.tab_size.get();
 4819                let mut rows = selection.spanned_rows(false, &display_map);
 4820
 4821                // Avoid re-outdenting a row that has already been outdented by a
 4822                // previous selection.
 4823                if let Some(last_row) = last_outdent {
 4824                    if last_row == rows.start {
 4825                        rows.start += 1;
 4826                    }
 4827                }
 4828
 4829                for row in rows {
 4830                    let indent_size = snapshot.indent_size_for_line(row);
 4831                    if indent_size.len > 0 {
 4832                        let deletion_len = match indent_size.kind {
 4833                            IndentKind::Space => {
 4834                                let columns_to_prev_tab_stop = indent_size.len % tab_size;
 4835                                if columns_to_prev_tab_stop == 0 {
 4836                                    tab_size
 4837                                } else {
 4838                                    columns_to_prev_tab_stop
 4839                                }
 4840                            }
 4841                            IndentKind::Tab => 1,
 4842                        };
 4843                        deletion_ranges.push(Point::new(row, 0)..Point::new(row, deletion_len));
 4844                        last_outdent = Some(row);
 4845                    }
 4846                }
 4847            }
 4848        }
 4849
 4850        self.transact(cx, |this, cx| {
 4851            this.buffer.update(cx, |buffer, cx| {
 4852                let empty_str: Arc<str> = "".into();
 4853                buffer.edit(
 4854                    deletion_ranges
 4855                        .into_iter()
 4856                        .map(|range| (range, empty_str.clone())),
 4857                    None,
 4858                    cx,
 4859                );
 4860            });
 4861            let selections = this.selections.all::<usize>(cx);
 4862            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
 4863        });
 4864    }
 4865
 4866    pub fn delete_line(&mut self, _: &DeleteLine, cx: &mut ViewContext<Self>) {
 4867        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 4868        let selections = self.selections.all::<Point>(cx);
 4869
 4870        let mut new_cursors = Vec::new();
 4871        let mut edit_ranges = Vec::new();
 4872        let mut selections = selections.iter().peekable();
 4873        while let Some(selection) = selections.next() {
 4874            let mut rows = selection.spanned_rows(false, &display_map);
 4875            let goal_display_column = selection.head().to_display_point(&display_map).column();
 4876
 4877            // Accumulate contiguous regions of rows that we want to delete.
 4878            while let Some(next_selection) = selections.peek() {
 4879                let next_rows = next_selection.spanned_rows(false, &display_map);
 4880                if next_rows.start <= rows.end {
 4881                    rows.end = next_rows.end;
 4882                    selections.next().unwrap();
 4883                } else {
 4884                    break;
 4885                }
 4886            }
 4887
 4888            let buffer = &display_map.buffer_snapshot;
 4889            let mut edit_start = Point::new(rows.start, 0).to_offset(buffer);
 4890            let edit_end;
 4891            let cursor_buffer_row;
 4892            if buffer.max_point().row >= rows.end {
 4893                // If there's a line after the range, delete the \n from the end of the row range
 4894                // and position the cursor on the next line.
 4895                edit_end = Point::new(rows.end, 0).to_offset(buffer);
 4896                cursor_buffer_row = rows.end;
 4897            } else {
 4898                // If there isn't a line after the range, delete the \n from the line before the
 4899                // start of the row range and position the cursor there.
 4900                edit_start = edit_start.saturating_sub(1);
 4901                edit_end = buffer.len();
 4902                cursor_buffer_row = rows.start.saturating_sub(1);
 4903            }
 4904
 4905            let mut cursor = Point::new(cursor_buffer_row, 0).to_display_point(&display_map);
 4906            *cursor.column_mut() =
 4907                cmp::min(goal_display_column, display_map.line_len(cursor.row()));
 4908
 4909            new_cursors.push((
 4910                selection.id,
 4911                buffer.anchor_after(cursor.to_point(&display_map)),
 4912            ));
 4913            edit_ranges.push(edit_start..edit_end);
 4914        }
 4915
 4916        self.transact(cx, |this, cx| {
 4917            let buffer = this.buffer.update(cx, |buffer, cx| {
 4918                let empty_str: Arc<str> = "".into();
 4919                buffer.edit(
 4920                    edit_ranges
 4921                        .into_iter()
 4922                        .map(|range| (range, empty_str.clone())),
 4923                    None,
 4924                    cx,
 4925                );
 4926                buffer.snapshot(cx)
 4927            });
 4928            let new_selections = new_cursors
 4929                .into_iter()
 4930                .map(|(id, cursor)| {
 4931                    let cursor = cursor.to_point(&buffer);
 4932                    Selection {
 4933                        id,
 4934                        start: cursor,
 4935                        end: cursor,
 4936                        reversed: false,
 4937                        goal: SelectionGoal::None,
 4938                    }
 4939                })
 4940                .collect();
 4941
 4942            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 4943                s.select(new_selections);
 4944            });
 4945        });
 4946    }
 4947
 4948    pub fn join_lines(&mut self, _: &JoinLines, cx: &mut ViewContext<Self>) {
 4949        let mut row_ranges = Vec::<Range<u32>>::new();
 4950        for selection in self.selections.all::<Point>(cx) {
 4951            let start = selection.start.row;
 4952            let end = if selection.start.row == selection.end.row {
 4953                selection.start.row + 1
 4954            } else {
 4955                selection.end.row
 4956            };
 4957
 4958            if let Some(last_row_range) = row_ranges.last_mut() {
 4959                if start <= last_row_range.end {
 4960                    last_row_range.end = end;
 4961                    continue;
 4962                }
 4963            }
 4964            row_ranges.push(start..end);
 4965        }
 4966
 4967        let snapshot = self.buffer.read(cx).snapshot(cx);
 4968        let mut cursor_positions = Vec::new();
 4969        for row_range in &row_ranges {
 4970            let anchor = snapshot.anchor_before(Point::new(
 4971                row_range.end - 1,
 4972                snapshot.line_len(row_range.end - 1),
 4973            ));
 4974            cursor_positions.push(anchor.clone()..anchor);
 4975        }
 4976
 4977        self.transact(cx, |this, cx| {
 4978            for row_range in row_ranges.into_iter().rev() {
 4979                for row in row_range.rev() {
 4980                    let end_of_line = Point::new(row, snapshot.line_len(row));
 4981                    let indent = snapshot.indent_size_for_line(row + 1);
 4982                    let start_of_next_line = Point::new(row + 1, indent.len);
 4983
 4984                    let replace = if snapshot.line_len(row + 1) > indent.len {
 4985                        " "
 4986                    } else {
 4987                        ""
 4988                    };
 4989
 4990                    this.buffer.update(cx, |buffer, cx| {
 4991                        buffer.edit([(end_of_line..start_of_next_line, replace)], None, cx)
 4992                    });
 4993                }
 4994            }
 4995
 4996            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 4997                s.select_anchor_ranges(cursor_positions)
 4998            });
 4999        });
 5000    }
 5001
 5002    pub fn sort_lines_case_sensitive(
 5003        &mut self,
 5004        _: &SortLinesCaseSensitive,
 5005        cx: &mut ViewContext<Self>,
 5006    ) {
 5007        self.manipulate_lines(cx, |lines| lines.sort())
 5008    }
 5009
 5010    pub fn sort_lines_case_insensitive(
 5011        &mut self,
 5012        _: &SortLinesCaseInsensitive,
 5013        cx: &mut ViewContext<Self>,
 5014    ) {
 5015        self.manipulate_lines(cx, |lines| lines.sort_by_key(|line| line.to_lowercase()))
 5016    }
 5017
 5018    pub fn reverse_lines(&mut self, _: &ReverseLines, cx: &mut ViewContext<Self>) {
 5019        self.manipulate_lines(cx, |lines| lines.reverse())
 5020    }
 5021
 5022    pub fn shuffle_lines(&mut self, _: &ShuffleLines, cx: &mut ViewContext<Self>) {
 5023        self.manipulate_lines(cx, |lines| lines.shuffle(&mut thread_rng()))
 5024    }
 5025
 5026    fn manipulate_lines<Fn>(&mut self, cx: &mut ViewContext<Self>, mut callback: Fn)
 5027    where
 5028        Fn: FnMut(&mut [&str]),
 5029    {
 5030        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 5031        let buffer = self.buffer.read(cx).snapshot(cx);
 5032
 5033        let mut edits = Vec::new();
 5034
 5035        let selections = self.selections.all::<Point>(cx);
 5036        let mut selections = selections.iter().peekable();
 5037        let mut contiguous_row_selections = Vec::new();
 5038        let mut new_selections = Vec::new();
 5039
 5040        while let Some(selection) = selections.next() {
 5041            let (start_row, end_row) = consume_contiguous_rows(
 5042                &mut contiguous_row_selections,
 5043                selection,
 5044                &display_map,
 5045                &mut selections,
 5046            );
 5047
 5048            let start_point = Point::new(start_row, 0);
 5049            let end_point = Point::new(end_row - 1, buffer.line_len(end_row - 1));
 5050            let text = buffer
 5051                .text_for_range(start_point..end_point)
 5052                .collect::<String>();
 5053            let mut lines = text.split("\n").collect_vec();
 5054
 5055            let lines_len = lines.len();
 5056            callback(&mut lines);
 5057
 5058            // This is a current limitation with selections.
 5059            // If we wanted to support removing or adding lines, we'd need to fix the logic associated with selections.
 5060            debug_assert!(
 5061                lines.len() == lines_len,
 5062                "callback should not change the number of lines"
 5063            );
 5064
 5065            edits.push((start_point..end_point, lines.join("\n")));
 5066            let start_anchor = buffer.anchor_after(start_point);
 5067            let end_anchor = buffer.anchor_before(end_point);
 5068
 5069            // Make selection and push
 5070            new_selections.push(Selection {
 5071                id: selection.id,
 5072                start: start_anchor.to_offset(&buffer),
 5073                end: end_anchor.to_offset(&buffer),
 5074                goal: SelectionGoal::None,
 5075                reversed: selection.reversed,
 5076            });
 5077        }
 5078
 5079        self.transact(cx, |this, cx| {
 5080            this.buffer.update(cx, |buffer, cx| {
 5081                buffer.edit(edits, None, cx);
 5082            });
 5083
 5084            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5085                s.select(new_selections);
 5086            });
 5087
 5088            this.request_autoscroll(Autoscroll::fit(), cx);
 5089        });
 5090    }
 5091
 5092    pub fn convert_to_upper_case(&mut self, _: &ConvertToUpperCase, cx: &mut ViewContext<Self>) {
 5093        self.manipulate_text(cx, |text| text.to_uppercase())
 5094    }
 5095
 5096    pub fn convert_to_lower_case(&mut self, _: &ConvertToLowerCase, cx: &mut ViewContext<Self>) {
 5097        self.manipulate_text(cx, |text| text.to_lowercase())
 5098    }
 5099
 5100    pub fn convert_to_title_case(&mut self, _: &ConvertToTitleCase, cx: &mut ViewContext<Self>) {
 5101        self.manipulate_text(cx, |text| {
 5102            // Hack to get around the fact that to_case crate doesn't support '\n' as a word boundary
 5103            // https://github.com/rutrum/convert-case/issues/16
 5104            text.split("\n")
 5105                .map(|line| line.to_case(Case::Title))
 5106                .join("\n")
 5107        })
 5108    }
 5109
 5110    pub fn convert_to_snake_case(&mut self, _: &ConvertToSnakeCase, cx: &mut ViewContext<Self>) {
 5111        self.manipulate_text(cx, |text| text.to_case(Case::Snake))
 5112    }
 5113
 5114    pub fn convert_to_kebab_case(&mut self, _: &ConvertToKebabCase, cx: &mut ViewContext<Self>) {
 5115        self.manipulate_text(cx, |text| text.to_case(Case::Kebab))
 5116    }
 5117
 5118    pub fn convert_to_upper_camel_case(
 5119        &mut self,
 5120        _: &ConvertToUpperCamelCase,
 5121        cx: &mut ViewContext<Self>,
 5122    ) {
 5123        self.manipulate_text(cx, |text| {
 5124            // Hack to get around the fact that to_case crate doesn't support '\n' as a word boundary
 5125            // https://github.com/rutrum/convert-case/issues/16
 5126            text.split("\n")
 5127                .map(|line| line.to_case(Case::UpperCamel))
 5128                .join("\n")
 5129        })
 5130    }
 5131
 5132    pub fn convert_to_lower_camel_case(
 5133        &mut self,
 5134        _: &ConvertToLowerCamelCase,
 5135        cx: &mut ViewContext<Self>,
 5136    ) {
 5137        self.manipulate_text(cx, |text| text.to_case(Case::Camel))
 5138    }
 5139
 5140    fn manipulate_text<Fn>(&mut self, cx: &mut ViewContext<Self>, mut callback: Fn)
 5141    where
 5142        Fn: FnMut(&str) -> String,
 5143    {
 5144        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 5145        let buffer = self.buffer.read(cx).snapshot(cx);
 5146
 5147        let mut new_selections = Vec::new();
 5148        let mut edits = Vec::new();
 5149        let mut selection_adjustment = 0i32;
 5150
 5151        for selection in self.selections.all::<usize>(cx) {
 5152            let selection_is_empty = selection.is_empty();
 5153
 5154            let (start, end) = if selection_is_empty {
 5155                let word_range = movement::surrounding_word(
 5156                    &display_map,
 5157                    selection.start.to_display_point(&display_map),
 5158                );
 5159                let start = word_range.start.to_offset(&display_map, Bias::Left);
 5160                let end = word_range.end.to_offset(&display_map, Bias::Left);
 5161                (start, end)
 5162            } else {
 5163                (selection.start, selection.end)
 5164            };
 5165
 5166            let text = buffer.text_for_range(start..end).collect::<String>();
 5167            let old_length = text.len() as i32;
 5168            let text = callback(&text);
 5169
 5170            new_selections.push(Selection {
 5171                start: (start as i32 - selection_adjustment) as usize,
 5172                end: ((start + text.len()) as i32 - selection_adjustment) as usize,
 5173                goal: SelectionGoal::None,
 5174                ..selection
 5175            });
 5176
 5177            selection_adjustment += old_length - text.len() as i32;
 5178
 5179            edits.push((start..end, text));
 5180        }
 5181
 5182        self.transact(cx, |this, cx| {
 5183            this.buffer.update(cx, |buffer, cx| {
 5184                buffer.edit(edits, None, cx);
 5185            });
 5186
 5187            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5188                s.select(new_selections);
 5189            });
 5190
 5191            this.request_autoscroll(Autoscroll::fit(), cx);
 5192        });
 5193    }
 5194
 5195    pub fn duplicate_line(&mut self, _: &DuplicateLine, cx: &mut ViewContext<Self>) {
 5196        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 5197        let buffer = &display_map.buffer_snapshot;
 5198        let selections = self.selections.all::<Point>(cx);
 5199
 5200        let mut edits = Vec::new();
 5201        let mut selections_iter = selections.iter().peekable();
 5202        while let Some(selection) = selections_iter.next() {
 5203            // Avoid duplicating the same lines twice.
 5204            let mut rows = selection.spanned_rows(false, &display_map);
 5205
 5206            while let Some(next_selection) = selections_iter.peek() {
 5207                let next_rows = next_selection.spanned_rows(false, &display_map);
 5208                if next_rows.start < rows.end {
 5209                    rows.end = next_rows.end;
 5210                    selections_iter.next().unwrap();
 5211                } else {
 5212                    break;
 5213                }
 5214            }
 5215
 5216            // Copy the text from the selected row region and splice it at the start of the region.
 5217            let start = Point::new(rows.start, 0);
 5218            let end = Point::new(rows.end - 1, buffer.line_len(rows.end - 1));
 5219            let text = buffer
 5220                .text_for_range(start..end)
 5221                .chain(Some("\n"))
 5222                .collect::<String>();
 5223            edits.push((start..start, text));
 5224        }
 5225
 5226        self.transact(cx, |this, cx| {
 5227            this.buffer.update(cx, |buffer, cx| {
 5228                buffer.edit(edits, None, cx);
 5229            });
 5230
 5231            this.request_autoscroll(Autoscroll::fit(), cx);
 5232        });
 5233    }
 5234
 5235    pub fn move_line_up(&mut self, _: &MoveLineUp, cx: &mut ViewContext<Self>) {
 5236        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 5237        let buffer = self.buffer.read(cx).snapshot(cx);
 5238
 5239        let mut edits = Vec::new();
 5240        let mut unfold_ranges = Vec::new();
 5241        let mut refold_ranges = Vec::new();
 5242
 5243        let selections = self.selections.all::<Point>(cx);
 5244        let mut selections = selections.iter().peekable();
 5245        let mut contiguous_row_selections = Vec::new();
 5246        let mut new_selections = Vec::new();
 5247
 5248        while let Some(selection) = selections.next() {
 5249            // Find all the selections that span a contiguous row range
 5250            let (start_row, end_row) = consume_contiguous_rows(
 5251                &mut contiguous_row_selections,
 5252                selection,
 5253                &display_map,
 5254                &mut selections,
 5255            );
 5256
 5257            // Move the text spanned by the row range to be before the line preceding the row range
 5258            if start_row > 0 {
 5259                let range_to_move = Point::new(start_row - 1, buffer.line_len(start_row - 1))
 5260                    ..Point::new(end_row - 1, buffer.line_len(end_row - 1));
 5261                let insertion_point = display_map
 5262                    .prev_line_boundary(Point::new(start_row - 1, 0))
 5263                    .0;
 5264
 5265                // Don't move lines across excerpts
 5266                if buffer
 5267                    .excerpt_boundaries_in_range((
 5268                        Bound::Excluded(insertion_point),
 5269                        Bound::Included(range_to_move.end),
 5270                    ))
 5271                    .next()
 5272                    .is_none()
 5273                {
 5274                    let text = buffer
 5275                        .text_for_range(range_to_move.clone())
 5276                        .flat_map(|s| s.chars())
 5277                        .skip(1)
 5278                        .chain(['\n'])
 5279                        .collect::<String>();
 5280
 5281                    edits.push((
 5282                        buffer.anchor_after(range_to_move.start)
 5283                            ..buffer.anchor_before(range_to_move.end),
 5284                        String::new(),
 5285                    ));
 5286                    let insertion_anchor = buffer.anchor_after(insertion_point);
 5287                    edits.push((insertion_anchor..insertion_anchor, text));
 5288
 5289                    let row_delta = range_to_move.start.row - insertion_point.row + 1;
 5290
 5291                    // Move selections up
 5292                    new_selections.extend(contiguous_row_selections.drain(..).map(
 5293                        |mut selection| {
 5294                            selection.start.row -= row_delta;
 5295                            selection.end.row -= row_delta;
 5296                            selection
 5297                        },
 5298                    ));
 5299
 5300                    // Move folds up
 5301                    unfold_ranges.push(range_to_move.clone());
 5302                    for fold in display_map.folds_in_range(
 5303                        buffer.anchor_before(range_to_move.start)
 5304                            ..buffer.anchor_after(range_to_move.end),
 5305                    ) {
 5306                        let mut start = fold.range.start.to_point(&buffer);
 5307                        let mut end = fold.range.end.to_point(&buffer);
 5308                        start.row -= row_delta;
 5309                        end.row -= row_delta;
 5310                        refold_ranges.push(start..end);
 5311                    }
 5312                }
 5313            }
 5314
 5315            // If we didn't move line(s), preserve the existing selections
 5316            new_selections.append(&mut contiguous_row_selections);
 5317        }
 5318
 5319        self.transact(cx, |this, cx| {
 5320            this.unfold_ranges(unfold_ranges, true, true, cx);
 5321            this.buffer.update(cx, |buffer, cx| {
 5322                for (range, text) in edits {
 5323                    buffer.edit([(range, text)], None, cx);
 5324                }
 5325            });
 5326            this.fold_ranges(refold_ranges, true, cx);
 5327            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5328                s.select(new_selections);
 5329            })
 5330        });
 5331    }
 5332
 5333    pub fn move_line_down(&mut self, _: &MoveLineDown, cx: &mut ViewContext<Self>) {
 5334        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 5335        let buffer = self.buffer.read(cx).snapshot(cx);
 5336
 5337        let mut edits = Vec::new();
 5338        let mut unfold_ranges = Vec::new();
 5339        let mut refold_ranges = Vec::new();
 5340
 5341        let selections = self.selections.all::<Point>(cx);
 5342        let mut selections = selections.iter().peekable();
 5343        let mut contiguous_row_selections = Vec::new();
 5344        let mut new_selections = Vec::new();
 5345
 5346        while let Some(selection) = selections.next() {
 5347            // Find all the selections that span a contiguous row range
 5348            let (start_row, end_row) = consume_contiguous_rows(
 5349                &mut contiguous_row_selections,
 5350                selection,
 5351                &display_map,
 5352                &mut selections,
 5353            );
 5354
 5355            // Move the text spanned by the row range to be after the last line of the row range
 5356            if end_row <= buffer.max_point().row {
 5357                let range_to_move = Point::new(start_row, 0)..Point::new(end_row, 0);
 5358                let insertion_point = display_map.next_line_boundary(Point::new(end_row, 0)).0;
 5359
 5360                // Don't move lines across excerpt boundaries
 5361                if buffer
 5362                    .excerpt_boundaries_in_range((
 5363                        Bound::Excluded(range_to_move.start),
 5364                        Bound::Included(insertion_point),
 5365                    ))
 5366                    .next()
 5367                    .is_none()
 5368                {
 5369                    let mut text = String::from("\n");
 5370                    text.extend(buffer.text_for_range(range_to_move.clone()));
 5371                    text.pop(); // Drop trailing newline
 5372                    edits.push((
 5373                        buffer.anchor_after(range_to_move.start)
 5374                            ..buffer.anchor_before(range_to_move.end),
 5375                        String::new(),
 5376                    ));
 5377                    let insertion_anchor = buffer.anchor_after(insertion_point);
 5378                    edits.push((insertion_anchor..insertion_anchor, text));
 5379
 5380                    let row_delta = insertion_point.row - range_to_move.end.row + 1;
 5381
 5382                    // Move selections down
 5383                    new_selections.extend(contiguous_row_selections.drain(..).map(
 5384                        |mut selection| {
 5385                            selection.start.row += row_delta;
 5386                            selection.end.row += row_delta;
 5387                            selection
 5388                        },
 5389                    ));
 5390
 5391                    // Move folds down
 5392                    unfold_ranges.push(range_to_move.clone());
 5393                    for fold in display_map.folds_in_range(
 5394                        buffer.anchor_before(range_to_move.start)
 5395                            ..buffer.anchor_after(range_to_move.end),
 5396                    ) {
 5397                        let mut start = fold.range.start.to_point(&buffer);
 5398                        let mut end = fold.range.end.to_point(&buffer);
 5399                        start.row += row_delta;
 5400                        end.row += row_delta;
 5401                        refold_ranges.push(start..end);
 5402                    }
 5403                }
 5404            }
 5405
 5406            // If we didn't move line(s), preserve the existing selections
 5407            new_selections.append(&mut contiguous_row_selections);
 5408        }
 5409
 5410        self.transact(cx, |this, cx| {
 5411            this.unfold_ranges(unfold_ranges, true, true, cx);
 5412            this.buffer.update(cx, |buffer, cx| {
 5413                for (range, text) in edits {
 5414                    buffer.edit([(range, text)], None, cx);
 5415                }
 5416            });
 5417            this.fold_ranges(refold_ranges, true, cx);
 5418            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(new_selections));
 5419        });
 5420    }
 5421
 5422    pub fn transpose(&mut self, _: &Transpose, cx: &mut ViewContext<Self>) {
 5423        let text_layout_details = &self.text_layout_details(cx);
 5424        self.transact(cx, |this, cx| {
 5425            let edits = this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5426                let mut edits: Vec<(Range<usize>, String)> = Default::default();
 5427                let line_mode = s.line_mode;
 5428                s.move_with(|display_map, selection| {
 5429                    if !selection.is_empty() || line_mode {
 5430                        return;
 5431                    }
 5432
 5433                    let mut head = selection.head();
 5434                    let mut transpose_offset = head.to_offset(display_map, Bias::Right);
 5435                    if head.column() == display_map.line_len(head.row()) {
 5436                        transpose_offset = display_map
 5437                            .buffer_snapshot
 5438                            .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
 5439                    }
 5440
 5441                    if transpose_offset == 0 {
 5442                        return;
 5443                    }
 5444
 5445                    *head.column_mut() += 1;
 5446                    head = display_map.clip_point(head, Bias::Right);
 5447                    let goal = SelectionGoal::HorizontalPosition(
 5448                        display_map
 5449                            .x_for_display_point(head, &text_layout_details)
 5450                            .into(),
 5451                    );
 5452                    selection.collapse_to(head, goal);
 5453
 5454                    let transpose_start = display_map
 5455                        .buffer_snapshot
 5456                        .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
 5457                    if edits.last().map_or(true, |e| e.0.end <= transpose_start) {
 5458                        let transpose_end = display_map
 5459                            .buffer_snapshot
 5460                            .clip_offset(transpose_offset + 1, Bias::Right);
 5461                        if let Some(ch) =
 5462                            display_map.buffer_snapshot.chars_at(transpose_start).next()
 5463                        {
 5464                            edits.push((transpose_start..transpose_offset, String::new()));
 5465                            edits.push((transpose_end..transpose_end, ch.to_string()));
 5466                        }
 5467                    }
 5468                });
 5469                edits
 5470            });
 5471            this.buffer
 5472                .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
 5473            let selections = this.selections.all::<usize>(cx);
 5474            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5475                s.select(selections);
 5476            });
 5477        });
 5478    }
 5479
 5480    pub fn cut(&mut self, _: &Cut, cx: &mut ViewContext<Self>) {
 5481        let mut text = String::new();
 5482        let buffer = self.buffer.read(cx).snapshot(cx);
 5483        let mut selections = self.selections.all::<Point>(cx);
 5484        let mut clipboard_selections = Vec::with_capacity(selections.len());
 5485        {
 5486            let max_point = buffer.max_point();
 5487            let mut is_first = true;
 5488            for selection in &mut selections {
 5489                let is_entire_line = selection.is_empty() || self.selections.line_mode;
 5490                if is_entire_line {
 5491                    selection.start = Point::new(selection.start.row, 0);
 5492                    selection.end = cmp::min(max_point, Point::new(selection.end.row + 1, 0));
 5493                    selection.goal = SelectionGoal::None;
 5494                }
 5495                if is_first {
 5496                    is_first = false;
 5497                } else {
 5498                    text += "\n";
 5499                }
 5500                let mut len = 0;
 5501                for chunk in buffer.text_for_range(selection.start..selection.end) {
 5502                    text.push_str(chunk);
 5503                    len += chunk.len();
 5504                }
 5505                clipboard_selections.push(ClipboardSelection {
 5506                    len,
 5507                    is_entire_line,
 5508                    first_line_indent: buffer.indent_size_for_line(selection.start.row).len,
 5509                });
 5510            }
 5511        }
 5512
 5513        self.transact(cx, |this, cx| {
 5514            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5515                s.select(selections);
 5516            });
 5517            this.insert("", cx);
 5518            cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
 5519        });
 5520    }
 5521
 5522    pub fn copy(&mut self, _: &Copy, cx: &mut ViewContext<Self>) {
 5523        let selections = self.selections.all::<Point>(cx);
 5524        let buffer = self.buffer.read(cx).read(cx);
 5525        let mut text = String::new();
 5526
 5527        let mut clipboard_selections = Vec::with_capacity(selections.len());
 5528        {
 5529            let max_point = buffer.max_point();
 5530            let mut is_first = true;
 5531            for selection in selections.iter() {
 5532                let mut start = selection.start;
 5533                let mut end = selection.end;
 5534                let is_entire_line = selection.is_empty() || self.selections.line_mode;
 5535                if is_entire_line {
 5536                    start = Point::new(start.row, 0);
 5537                    end = cmp::min(max_point, Point::new(end.row + 1, 0));
 5538                }
 5539                if is_first {
 5540                    is_first = false;
 5541                } else {
 5542                    text += "\n";
 5543                }
 5544                let mut len = 0;
 5545                for chunk in buffer.text_for_range(start..end) {
 5546                    text.push_str(chunk);
 5547                    len += chunk.len();
 5548                }
 5549                clipboard_selections.push(ClipboardSelection {
 5550                    len,
 5551                    is_entire_line,
 5552                    first_line_indent: buffer.indent_size_for_line(start.row).len,
 5553                });
 5554            }
 5555        }
 5556
 5557        cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
 5558    }
 5559
 5560    pub fn paste(&mut self, _: &Paste, cx: &mut ViewContext<Self>) {
 5561        self.transact(cx, |this, cx| {
 5562            if let Some(item) = cx.read_from_clipboard() {
 5563                let clipboard_text = Cow::Borrowed(item.text());
 5564                if let Some(mut clipboard_selections) = item.metadata::<Vec<ClipboardSelection>>() {
 5565                    let old_selections = this.selections.all::<usize>(cx);
 5566                    let all_selections_were_entire_line =
 5567                        clipboard_selections.iter().all(|s| s.is_entire_line);
 5568                    let first_selection_indent_column =
 5569                        clipboard_selections.first().map(|s| s.first_line_indent);
 5570                    if clipboard_selections.len() != old_selections.len() {
 5571                        clipboard_selections.drain(..);
 5572                    }
 5573
 5574                    this.buffer.update(cx, |buffer, cx| {
 5575                        let snapshot = buffer.read(cx);
 5576                        let mut start_offset = 0;
 5577                        let mut edits = Vec::new();
 5578                        let mut original_indent_columns = Vec::new();
 5579                        let line_mode = this.selections.line_mode;
 5580                        for (ix, selection) in old_selections.iter().enumerate() {
 5581                            let to_insert;
 5582                            let entire_line;
 5583                            let original_indent_column;
 5584                            if let Some(clipboard_selection) = clipboard_selections.get(ix) {
 5585                                let end_offset = start_offset + clipboard_selection.len;
 5586                                to_insert = &clipboard_text[start_offset..end_offset];
 5587                                entire_line = clipboard_selection.is_entire_line;
 5588                                start_offset = end_offset + 1;
 5589                                original_indent_column =
 5590                                    Some(clipboard_selection.first_line_indent);
 5591                            } else {
 5592                                to_insert = clipboard_text.as_str();
 5593                                entire_line = all_selections_were_entire_line;
 5594                                original_indent_column = first_selection_indent_column
 5595                            }
 5596
 5597                            // If the corresponding selection was empty when this slice of the
 5598                            // clipboard text was written, then the entire line containing the
 5599                            // selection was copied. If this selection is also currently empty,
 5600                            // then paste the line before the current line of the buffer.
 5601                            let range = if selection.is_empty() && !line_mode && entire_line {
 5602                                let column = selection.start.to_point(&snapshot).column as usize;
 5603                                let line_start = selection.start - column;
 5604                                line_start..line_start
 5605                            } else {
 5606                                selection.range()
 5607                            };
 5608
 5609                            edits.push((range, to_insert));
 5610                            original_indent_columns.extend(original_indent_column);
 5611                        }
 5612                        drop(snapshot);
 5613
 5614                        buffer.edit(
 5615                            edits,
 5616                            Some(AutoindentMode::Block {
 5617                                original_indent_columns,
 5618                            }),
 5619                            cx,
 5620                        );
 5621                    });
 5622
 5623                    let selections = this.selections.all::<usize>(cx);
 5624                    this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
 5625                } else {
 5626                    this.insert(&clipboard_text, cx);
 5627                }
 5628            }
 5629        });
 5630    }
 5631
 5632    pub fn undo(&mut self, _: &Undo, cx: &mut ViewContext<Self>) {
 5633        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.undo(cx)) {
 5634            if let Some((selections, _)) = self.selection_history.transaction(tx_id).cloned() {
 5635                self.change_selections(None, cx, |s| {
 5636                    s.select_anchors(selections.to_vec());
 5637                });
 5638            }
 5639            self.request_autoscroll(Autoscroll::fit(), cx);
 5640            self.unmark_text(cx);
 5641            self.refresh_copilot_suggestions(true, cx);
 5642            cx.emit(EditorEvent::Edited);
 5643        }
 5644    }
 5645
 5646    pub fn redo(&mut self, _: &Redo, cx: &mut ViewContext<Self>) {
 5647        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.redo(cx)) {
 5648            if let Some((_, Some(selections))) = self.selection_history.transaction(tx_id).cloned()
 5649            {
 5650                self.change_selections(None, cx, |s| {
 5651                    s.select_anchors(selections.to_vec());
 5652                });
 5653            }
 5654            self.request_autoscroll(Autoscroll::fit(), cx);
 5655            self.unmark_text(cx);
 5656            self.refresh_copilot_suggestions(true, cx);
 5657            cx.emit(EditorEvent::Edited);
 5658        }
 5659    }
 5660
 5661    pub fn finalize_last_transaction(&mut self, cx: &mut ViewContext<Self>) {
 5662        self.buffer
 5663            .update(cx, |buffer, cx| buffer.finalize_last_transaction(cx));
 5664    }
 5665
 5666    pub fn move_left(&mut self, _: &MoveLeft, cx: &mut ViewContext<Self>) {
 5667        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5668            let line_mode = s.line_mode;
 5669            s.move_with(|map, selection| {
 5670                let cursor = if selection.is_empty() && !line_mode {
 5671                    movement::left(map, selection.start)
 5672                } else {
 5673                    selection.start
 5674                };
 5675                selection.collapse_to(cursor, SelectionGoal::None);
 5676            });
 5677        })
 5678    }
 5679
 5680    pub fn select_left(&mut self, _: &SelectLeft, cx: &mut ViewContext<Self>) {
 5681        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5682            s.move_heads_with(|map, head, _| (movement::left(map, head), SelectionGoal::None));
 5683        })
 5684    }
 5685
 5686    pub fn move_right(&mut self, _: &MoveRight, cx: &mut ViewContext<Self>) {
 5687        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5688            let line_mode = s.line_mode;
 5689            s.move_with(|map, selection| {
 5690                let cursor = if selection.is_empty() && !line_mode {
 5691                    movement::right(map, selection.end)
 5692                } else {
 5693                    selection.end
 5694                };
 5695                selection.collapse_to(cursor, SelectionGoal::None)
 5696            });
 5697        })
 5698    }
 5699
 5700    pub fn select_right(&mut self, _: &SelectRight, cx: &mut ViewContext<Self>) {
 5701        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5702            s.move_heads_with(|map, head, _| (movement::right(map, head), SelectionGoal::None));
 5703        })
 5704    }
 5705
 5706    pub fn move_up(&mut self, _: &MoveUp, cx: &mut ViewContext<Self>) {
 5707        if self.take_rename(true, cx).is_some() {
 5708            return;
 5709        }
 5710
 5711        if matches!(self.mode, EditorMode::SingleLine) {
 5712            cx.propagate();
 5713            return;
 5714        }
 5715
 5716        let text_layout_details = &self.text_layout_details(cx);
 5717
 5718        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5719            let line_mode = s.line_mode;
 5720            s.move_with(|map, selection| {
 5721                if !selection.is_empty() && !line_mode {
 5722                    selection.goal = SelectionGoal::None;
 5723                }
 5724                let (cursor, goal) = movement::up(
 5725                    map,
 5726                    selection.start,
 5727                    selection.goal,
 5728                    false,
 5729                    &text_layout_details,
 5730                );
 5731                selection.collapse_to(cursor, goal);
 5732            });
 5733        })
 5734    }
 5735
 5736    pub fn move_page_up(&mut self, action: &MovePageUp, cx: &mut ViewContext<Self>) {
 5737        if self.take_rename(true, cx).is_some() {
 5738            return;
 5739        }
 5740
 5741        if matches!(self.mode, EditorMode::SingleLine) {
 5742            cx.propagate();
 5743            return;
 5744        }
 5745
 5746        let row_count = if let Some(row_count) = self.visible_line_count() {
 5747            row_count as u32 - 1
 5748        } else {
 5749            return;
 5750        };
 5751
 5752        let autoscroll = if action.center_cursor {
 5753            Autoscroll::center()
 5754        } else {
 5755            Autoscroll::fit()
 5756        };
 5757
 5758        let text_layout_details = &self.text_layout_details(cx);
 5759
 5760        self.change_selections(Some(autoscroll), cx, |s| {
 5761            let line_mode = s.line_mode;
 5762            s.move_with(|map, selection| {
 5763                if !selection.is_empty() && !line_mode {
 5764                    selection.goal = SelectionGoal::None;
 5765                }
 5766                let (cursor, goal) = movement::up_by_rows(
 5767                    map,
 5768                    selection.end,
 5769                    row_count,
 5770                    selection.goal,
 5771                    false,
 5772                    &text_layout_details,
 5773                );
 5774                selection.collapse_to(cursor, goal);
 5775            });
 5776        });
 5777    }
 5778
 5779    pub fn select_up(&mut self, _: &SelectUp, cx: &mut ViewContext<Self>) {
 5780        let text_layout_details = &self.text_layout_details(cx);
 5781        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5782            s.move_heads_with(|map, head, goal| {
 5783                movement::up(map, head, goal, false, &text_layout_details)
 5784            })
 5785        })
 5786    }
 5787
 5788    pub fn move_down(&mut self, _: &MoveDown, cx: &mut ViewContext<Self>) {
 5789        self.take_rename(true, cx);
 5790
 5791        if self.mode == EditorMode::SingleLine {
 5792            cx.propagate();
 5793            return;
 5794        }
 5795
 5796        let text_layout_details = &self.text_layout_details(cx);
 5797        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5798            let line_mode = s.line_mode;
 5799            s.move_with(|map, selection| {
 5800                if !selection.is_empty() && !line_mode {
 5801                    selection.goal = SelectionGoal::None;
 5802                }
 5803                let (cursor, goal) = movement::down(
 5804                    map,
 5805                    selection.end,
 5806                    selection.goal,
 5807                    false,
 5808                    &text_layout_details,
 5809                );
 5810                selection.collapse_to(cursor, goal);
 5811            });
 5812        });
 5813    }
 5814
 5815    pub fn move_page_down(&mut self, action: &MovePageDown, cx: &mut ViewContext<Self>) {
 5816        if self.take_rename(true, cx).is_some() {
 5817            return;
 5818        }
 5819
 5820        if self
 5821            .context_menu
 5822            .write()
 5823            .as_mut()
 5824            .map(|menu| menu.select_last(self.project.as_ref(), cx))
 5825            .unwrap_or(false)
 5826        {
 5827            return;
 5828        }
 5829
 5830        if matches!(self.mode, EditorMode::SingleLine) {
 5831            cx.propagate();
 5832            return;
 5833        }
 5834
 5835        let row_count = if let Some(row_count) = self.visible_line_count() {
 5836            row_count as u32 - 1
 5837        } else {
 5838            return;
 5839        };
 5840
 5841        let autoscroll = if action.center_cursor {
 5842            Autoscroll::center()
 5843        } else {
 5844            Autoscroll::fit()
 5845        };
 5846
 5847        let text_layout_details = &self.text_layout_details(cx);
 5848        self.change_selections(Some(autoscroll), cx, |s| {
 5849            let line_mode = s.line_mode;
 5850            s.move_with(|map, selection| {
 5851                if !selection.is_empty() && !line_mode {
 5852                    selection.goal = SelectionGoal::None;
 5853                }
 5854                let (cursor, goal) = movement::down_by_rows(
 5855                    map,
 5856                    selection.end,
 5857                    row_count,
 5858                    selection.goal,
 5859                    false,
 5860                    &text_layout_details,
 5861                );
 5862                selection.collapse_to(cursor, goal);
 5863            });
 5864        });
 5865    }
 5866
 5867    pub fn select_down(&mut self, _: &SelectDown, cx: &mut ViewContext<Self>) {
 5868        let text_layout_details = &self.text_layout_details(cx);
 5869        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5870            s.move_heads_with(|map, head, goal| {
 5871                movement::down(map, head, goal, false, &text_layout_details)
 5872            })
 5873        });
 5874    }
 5875
 5876    pub fn context_menu_first(&mut self, _: &ContextMenuFirst, cx: &mut ViewContext<Self>) {
 5877        if let Some(context_menu) = self.context_menu.write().as_mut() {
 5878            context_menu.select_first(self.project.as_ref(), cx);
 5879        }
 5880    }
 5881
 5882    pub fn context_menu_prev(&mut self, _: &ContextMenuPrev, cx: &mut ViewContext<Self>) {
 5883        if let Some(context_menu) = self.context_menu.write().as_mut() {
 5884            context_menu.select_prev(self.project.as_ref(), cx);
 5885        }
 5886    }
 5887
 5888    pub fn context_menu_next(&mut self, _: &ContextMenuNext, cx: &mut ViewContext<Self>) {
 5889        if let Some(context_menu) = self.context_menu.write().as_mut() {
 5890            context_menu.select_next(self.project.as_ref(), cx);
 5891        }
 5892    }
 5893
 5894    pub fn context_menu_last(&mut self, _: &ContextMenuLast, cx: &mut ViewContext<Self>) {
 5895        if let Some(context_menu) = self.context_menu.write().as_mut() {
 5896            context_menu.select_last(self.project.as_ref(), cx);
 5897        }
 5898    }
 5899
 5900    pub fn move_to_previous_word_start(
 5901        &mut self,
 5902        _: &MoveToPreviousWordStart,
 5903        cx: &mut ViewContext<Self>,
 5904    ) {
 5905        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5906            s.move_cursors_with(|map, head, _| {
 5907                (
 5908                    movement::previous_word_start(map, head),
 5909                    SelectionGoal::None,
 5910                )
 5911            });
 5912        })
 5913    }
 5914
 5915    pub fn move_to_previous_subword_start(
 5916        &mut self,
 5917        _: &MoveToPreviousSubwordStart,
 5918        cx: &mut ViewContext<Self>,
 5919    ) {
 5920        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5921            s.move_cursors_with(|map, head, _| {
 5922                (
 5923                    movement::previous_subword_start(map, head),
 5924                    SelectionGoal::None,
 5925                )
 5926            });
 5927        })
 5928    }
 5929
 5930    pub fn select_to_previous_word_start(
 5931        &mut self,
 5932        _: &SelectToPreviousWordStart,
 5933        cx: &mut ViewContext<Self>,
 5934    ) {
 5935        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5936            s.move_heads_with(|map, head, _| {
 5937                (
 5938                    movement::previous_word_start(map, head),
 5939                    SelectionGoal::None,
 5940                )
 5941            });
 5942        })
 5943    }
 5944
 5945    pub fn select_to_previous_subword_start(
 5946        &mut self,
 5947        _: &SelectToPreviousSubwordStart,
 5948        cx: &mut ViewContext<Self>,
 5949    ) {
 5950        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5951            s.move_heads_with(|map, head, _| {
 5952                (
 5953                    movement::previous_subword_start(map, head),
 5954                    SelectionGoal::None,
 5955                )
 5956            });
 5957        })
 5958    }
 5959
 5960    pub fn delete_to_previous_word_start(
 5961        &mut self,
 5962        _: &DeleteToPreviousWordStart,
 5963        cx: &mut ViewContext<Self>,
 5964    ) {
 5965        self.transact(cx, |this, cx| {
 5966            this.select_autoclose_pair(cx);
 5967            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5968                let line_mode = s.line_mode;
 5969                s.move_with(|map, selection| {
 5970                    if selection.is_empty() && !line_mode {
 5971                        let cursor = movement::previous_word_start(map, selection.head());
 5972                        selection.set_head(cursor, SelectionGoal::None);
 5973                    }
 5974                });
 5975            });
 5976            this.insert("", cx);
 5977        });
 5978    }
 5979
 5980    pub fn delete_to_previous_subword_start(
 5981        &mut self,
 5982        _: &DeleteToPreviousSubwordStart,
 5983        cx: &mut ViewContext<Self>,
 5984    ) {
 5985        self.transact(cx, |this, cx| {
 5986            this.select_autoclose_pair(cx);
 5987            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 5988                let line_mode = s.line_mode;
 5989                s.move_with(|map, selection| {
 5990                    if selection.is_empty() && !line_mode {
 5991                        let cursor = movement::previous_subword_start(map, selection.head());
 5992                        selection.set_head(cursor, SelectionGoal::None);
 5993                    }
 5994                });
 5995            });
 5996            this.insert("", cx);
 5997        });
 5998    }
 5999
 6000    pub fn move_to_next_word_end(&mut self, _: &MoveToNextWordEnd, cx: &mut ViewContext<Self>) {
 6001        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6002            s.move_cursors_with(|map, head, _| {
 6003                (movement::next_word_end(map, head), SelectionGoal::None)
 6004            });
 6005        })
 6006    }
 6007
 6008    pub fn move_to_next_subword_end(
 6009        &mut self,
 6010        _: &MoveToNextSubwordEnd,
 6011        cx: &mut ViewContext<Self>,
 6012    ) {
 6013        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6014            s.move_cursors_with(|map, head, _| {
 6015                (movement::next_subword_end(map, head), SelectionGoal::None)
 6016            });
 6017        })
 6018    }
 6019
 6020    pub fn select_to_next_word_end(&mut self, _: &SelectToNextWordEnd, cx: &mut ViewContext<Self>) {
 6021        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6022            s.move_heads_with(|map, head, _| {
 6023                (movement::next_word_end(map, head), SelectionGoal::None)
 6024            });
 6025        })
 6026    }
 6027
 6028    pub fn select_to_next_subword_end(
 6029        &mut self,
 6030        _: &SelectToNextSubwordEnd,
 6031        cx: &mut ViewContext<Self>,
 6032    ) {
 6033        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6034            s.move_heads_with(|map, head, _| {
 6035                (movement::next_subword_end(map, head), SelectionGoal::None)
 6036            });
 6037        })
 6038    }
 6039
 6040    pub fn delete_to_next_word_end(&mut self, _: &DeleteToNextWordEnd, cx: &mut ViewContext<Self>) {
 6041        self.transact(cx, |this, cx| {
 6042            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6043                let line_mode = s.line_mode;
 6044                s.move_with(|map, selection| {
 6045                    if selection.is_empty() && !line_mode {
 6046                        let cursor = movement::next_word_end(map, selection.head());
 6047                        selection.set_head(cursor, SelectionGoal::None);
 6048                    }
 6049                });
 6050            });
 6051            this.insert("", cx);
 6052        });
 6053    }
 6054
 6055    pub fn delete_to_next_subword_end(
 6056        &mut self,
 6057        _: &DeleteToNextSubwordEnd,
 6058        cx: &mut ViewContext<Self>,
 6059    ) {
 6060        self.transact(cx, |this, cx| {
 6061            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6062                s.move_with(|map, selection| {
 6063                    if selection.is_empty() {
 6064                        let cursor = movement::next_subword_end(map, selection.head());
 6065                        selection.set_head(cursor, SelectionGoal::None);
 6066                    }
 6067                });
 6068            });
 6069            this.insert("", cx);
 6070        });
 6071    }
 6072
 6073    pub fn move_to_beginning_of_line(
 6074        &mut self,
 6075        _: &MoveToBeginningOfLine,
 6076        cx: &mut ViewContext<Self>,
 6077    ) {
 6078        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6079            s.move_cursors_with(|map, head, _| {
 6080                (
 6081                    movement::indented_line_beginning(map, head, true),
 6082                    SelectionGoal::None,
 6083                )
 6084            });
 6085        })
 6086    }
 6087
 6088    pub fn select_to_beginning_of_line(
 6089        &mut self,
 6090        action: &SelectToBeginningOfLine,
 6091        cx: &mut ViewContext<Self>,
 6092    ) {
 6093        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6094            s.move_heads_with(|map, head, _| {
 6095                (
 6096                    movement::indented_line_beginning(map, head, action.stop_at_soft_wraps),
 6097                    SelectionGoal::None,
 6098                )
 6099            });
 6100        });
 6101    }
 6102
 6103    pub fn delete_to_beginning_of_line(
 6104        &mut self,
 6105        _: &DeleteToBeginningOfLine,
 6106        cx: &mut ViewContext<Self>,
 6107    ) {
 6108        self.transact(cx, |this, cx| {
 6109            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6110                s.move_with(|_, selection| {
 6111                    selection.reversed = true;
 6112                });
 6113            });
 6114
 6115            this.select_to_beginning_of_line(
 6116                &SelectToBeginningOfLine {
 6117                    stop_at_soft_wraps: false,
 6118                },
 6119                cx,
 6120            );
 6121            this.backspace(&Backspace, cx);
 6122        });
 6123    }
 6124
 6125    pub fn move_to_end_of_line(&mut self, _: &MoveToEndOfLine, cx: &mut ViewContext<Self>) {
 6126        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6127            s.move_cursors_with(|map, head, _| {
 6128                (movement::line_end(map, head, true), SelectionGoal::None)
 6129            });
 6130        })
 6131    }
 6132
 6133    pub fn select_to_end_of_line(
 6134        &mut self,
 6135        action: &SelectToEndOfLine,
 6136        cx: &mut ViewContext<Self>,
 6137    ) {
 6138        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6139            s.move_heads_with(|map, head, _| {
 6140                (
 6141                    movement::line_end(map, head, action.stop_at_soft_wraps),
 6142                    SelectionGoal::None,
 6143                )
 6144            });
 6145        })
 6146    }
 6147
 6148    pub fn delete_to_end_of_line(&mut self, _: &DeleteToEndOfLine, cx: &mut ViewContext<Self>) {
 6149        self.transact(cx, |this, cx| {
 6150            this.select_to_end_of_line(
 6151                &SelectToEndOfLine {
 6152                    stop_at_soft_wraps: false,
 6153                },
 6154                cx,
 6155            );
 6156            this.delete(&Delete, cx);
 6157        });
 6158    }
 6159
 6160    pub fn cut_to_end_of_line(&mut self, _: &CutToEndOfLine, cx: &mut ViewContext<Self>) {
 6161        self.transact(cx, |this, cx| {
 6162            this.select_to_end_of_line(
 6163                &SelectToEndOfLine {
 6164                    stop_at_soft_wraps: false,
 6165                },
 6166                cx,
 6167            );
 6168            this.cut(&Cut, cx);
 6169        });
 6170    }
 6171
 6172    pub fn move_to_start_of_paragraph(
 6173        &mut self,
 6174        _: &MoveToStartOfParagraph,
 6175        cx: &mut ViewContext<Self>,
 6176    ) {
 6177        if matches!(self.mode, EditorMode::SingleLine) {
 6178            cx.propagate();
 6179            return;
 6180        }
 6181
 6182        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6183            s.move_with(|map, selection| {
 6184                selection.collapse_to(
 6185                    movement::start_of_paragraph(map, selection.head(), 1),
 6186                    SelectionGoal::None,
 6187                )
 6188            });
 6189        })
 6190    }
 6191
 6192    pub fn move_to_end_of_paragraph(
 6193        &mut self,
 6194        _: &MoveToEndOfParagraph,
 6195        cx: &mut ViewContext<Self>,
 6196    ) {
 6197        if matches!(self.mode, EditorMode::SingleLine) {
 6198            cx.propagate();
 6199            return;
 6200        }
 6201
 6202        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6203            s.move_with(|map, selection| {
 6204                selection.collapse_to(
 6205                    movement::end_of_paragraph(map, selection.head(), 1),
 6206                    SelectionGoal::None,
 6207                )
 6208            });
 6209        })
 6210    }
 6211
 6212    pub fn select_to_start_of_paragraph(
 6213        &mut self,
 6214        _: &SelectToStartOfParagraph,
 6215        cx: &mut ViewContext<Self>,
 6216    ) {
 6217        if matches!(self.mode, EditorMode::SingleLine) {
 6218            cx.propagate();
 6219            return;
 6220        }
 6221
 6222        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6223            s.move_heads_with(|map, head, _| {
 6224                (
 6225                    movement::start_of_paragraph(map, head, 1),
 6226                    SelectionGoal::None,
 6227                )
 6228            });
 6229        })
 6230    }
 6231
 6232    pub fn select_to_end_of_paragraph(
 6233        &mut self,
 6234        _: &SelectToEndOfParagraph,
 6235        cx: &mut ViewContext<Self>,
 6236    ) {
 6237        if matches!(self.mode, EditorMode::SingleLine) {
 6238            cx.propagate();
 6239            return;
 6240        }
 6241
 6242        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6243            s.move_heads_with(|map, head, _| {
 6244                (
 6245                    movement::end_of_paragraph(map, head, 1),
 6246                    SelectionGoal::None,
 6247                )
 6248            });
 6249        })
 6250    }
 6251
 6252    pub fn move_to_beginning(&mut self, _: &MoveToBeginning, cx: &mut ViewContext<Self>) {
 6253        if matches!(self.mode, EditorMode::SingleLine) {
 6254            cx.propagate();
 6255            return;
 6256        }
 6257
 6258        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6259            s.select_ranges(vec![0..0]);
 6260        });
 6261    }
 6262
 6263    pub fn select_to_beginning(&mut self, _: &SelectToBeginning, cx: &mut ViewContext<Self>) {
 6264        let mut selection = self.selections.last::<Point>(cx);
 6265        selection.set_head(Point::zero(), SelectionGoal::None);
 6266
 6267        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6268            s.select(vec![selection]);
 6269        });
 6270    }
 6271
 6272    pub fn move_to_end(&mut self, _: &MoveToEnd, cx: &mut ViewContext<Self>) {
 6273        if matches!(self.mode, EditorMode::SingleLine) {
 6274            cx.propagate();
 6275            return;
 6276        }
 6277
 6278        let cursor = self.buffer.read(cx).read(cx).len();
 6279        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6280            s.select_ranges(vec![cursor..cursor])
 6281        });
 6282    }
 6283
 6284    pub fn set_nav_history(&mut self, nav_history: Option<ItemNavHistory>) {
 6285        self.nav_history = nav_history;
 6286    }
 6287
 6288    pub fn nav_history(&self) -> Option<&ItemNavHistory> {
 6289        self.nav_history.as_ref()
 6290    }
 6291
 6292    fn push_to_nav_history(
 6293        &mut self,
 6294        cursor_anchor: Anchor,
 6295        new_position: Option<Point>,
 6296        cx: &mut ViewContext<Self>,
 6297    ) {
 6298        if let Some(nav_history) = self.nav_history.as_mut() {
 6299            let buffer = self.buffer.read(cx).read(cx);
 6300            let cursor_position = cursor_anchor.to_point(&buffer);
 6301            let scroll_state = self.scroll_manager.anchor();
 6302            let scroll_top_row = scroll_state.top_row(&buffer);
 6303            drop(buffer);
 6304
 6305            if let Some(new_position) = new_position {
 6306                let row_delta = (new_position.row as i64 - cursor_position.row as i64).abs();
 6307                if row_delta < MIN_NAVIGATION_HISTORY_ROW_DELTA {
 6308                    return;
 6309                }
 6310            }
 6311
 6312            nav_history.push(
 6313                Some(NavigationData {
 6314                    cursor_anchor,
 6315                    cursor_position,
 6316                    scroll_anchor: scroll_state,
 6317                    scroll_top_row,
 6318                }),
 6319                cx,
 6320            );
 6321        }
 6322    }
 6323
 6324    pub fn select_to_end(&mut self, _: &SelectToEnd, cx: &mut ViewContext<Self>) {
 6325        let buffer = self.buffer.read(cx).snapshot(cx);
 6326        let mut selection = self.selections.first::<usize>(cx);
 6327        selection.set_head(buffer.len(), SelectionGoal::None);
 6328        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6329            s.select(vec![selection]);
 6330        });
 6331    }
 6332
 6333    pub fn select_all(&mut self, _: &SelectAll, cx: &mut ViewContext<Self>) {
 6334        let end = self.buffer.read(cx).read(cx).len();
 6335        self.change_selections(None, cx, |s| {
 6336            s.select_ranges(vec![0..end]);
 6337        });
 6338    }
 6339
 6340    pub fn select_line(&mut self, _: &SelectLine, cx: &mut ViewContext<Self>) {
 6341        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 6342        let mut selections = self.selections.all::<Point>(cx);
 6343        let max_point = display_map.buffer_snapshot.max_point();
 6344        for selection in &mut selections {
 6345            let rows = selection.spanned_rows(true, &display_map);
 6346            selection.start = Point::new(rows.start, 0);
 6347            selection.end = cmp::min(max_point, Point::new(rows.end, 0));
 6348            selection.reversed = false;
 6349        }
 6350        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6351            s.select(selections);
 6352        });
 6353    }
 6354
 6355    pub fn split_selection_into_lines(
 6356        &mut self,
 6357        _: &SplitSelectionIntoLines,
 6358        cx: &mut ViewContext<Self>,
 6359    ) {
 6360        let mut to_unfold = Vec::new();
 6361        let mut new_selection_ranges = Vec::new();
 6362        {
 6363            let selections = self.selections.all::<Point>(cx);
 6364            let buffer = self.buffer.read(cx).read(cx);
 6365            for selection in selections {
 6366                for row in selection.start.row..selection.end.row {
 6367                    let cursor = Point::new(row, buffer.line_len(row));
 6368                    new_selection_ranges.push(cursor..cursor);
 6369                }
 6370                new_selection_ranges.push(selection.end..selection.end);
 6371                to_unfold.push(selection.start..selection.end);
 6372            }
 6373        }
 6374        self.unfold_ranges(to_unfold, true, true, cx);
 6375        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6376            s.select_ranges(new_selection_ranges);
 6377        });
 6378    }
 6379
 6380    pub fn add_selection_above(&mut self, _: &AddSelectionAbove, cx: &mut ViewContext<Self>) {
 6381        self.add_selection(true, cx);
 6382    }
 6383
 6384    pub fn add_selection_below(&mut self, _: &AddSelectionBelow, cx: &mut ViewContext<Self>) {
 6385        self.add_selection(false, cx);
 6386    }
 6387
 6388    fn add_selection(&mut self, above: bool, cx: &mut ViewContext<Self>) {
 6389        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 6390        let mut selections = self.selections.all::<Point>(cx);
 6391        let text_layout_details = self.text_layout_details(cx);
 6392        let mut state = self.add_selections_state.take().unwrap_or_else(|| {
 6393            let oldest_selection = selections.iter().min_by_key(|s| s.id).unwrap().clone();
 6394            let range = oldest_selection.display_range(&display_map).sorted();
 6395
 6396            let start_x = display_map.x_for_display_point(range.start, &text_layout_details);
 6397            let end_x = display_map.x_for_display_point(range.end, &text_layout_details);
 6398            let positions = start_x.min(end_x)..start_x.max(end_x);
 6399
 6400            selections.clear();
 6401            let mut stack = Vec::new();
 6402            for row in range.start.row()..=range.end.row() {
 6403                if let Some(selection) = self.selections.build_columnar_selection(
 6404                    &display_map,
 6405                    row,
 6406                    &positions,
 6407                    oldest_selection.reversed,
 6408                    &text_layout_details,
 6409                ) {
 6410                    stack.push(selection.id);
 6411                    selections.push(selection);
 6412                }
 6413            }
 6414
 6415            if above {
 6416                stack.reverse();
 6417            }
 6418
 6419            AddSelectionsState { above, stack }
 6420        });
 6421
 6422        let last_added_selection = *state.stack.last().unwrap();
 6423        let mut new_selections = Vec::new();
 6424        if above == state.above {
 6425            let end_row = if above {
 6426                0
 6427            } else {
 6428                display_map.max_point().row()
 6429            };
 6430
 6431            'outer: for selection in selections {
 6432                if selection.id == last_added_selection {
 6433                    let range = selection.display_range(&display_map).sorted();
 6434                    debug_assert_eq!(range.start.row(), range.end.row());
 6435                    let mut row = range.start.row();
 6436                    let positions =
 6437                        if let SelectionGoal::HorizontalRange { start, end } = selection.goal {
 6438                            px(start)..px(end)
 6439                        } else {
 6440                            let start_x =
 6441                                display_map.x_for_display_point(range.start, &text_layout_details);
 6442                            let end_x =
 6443                                display_map.x_for_display_point(range.end, &text_layout_details);
 6444                            start_x.min(end_x)..start_x.max(end_x)
 6445                        };
 6446
 6447                    while row != end_row {
 6448                        if above {
 6449                            row -= 1;
 6450                        } else {
 6451                            row += 1;
 6452                        }
 6453
 6454                        if let Some(new_selection) = self.selections.build_columnar_selection(
 6455                            &display_map,
 6456                            row,
 6457                            &positions,
 6458                            selection.reversed,
 6459                            &text_layout_details,
 6460                        ) {
 6461                            state.stack.push(new_selection.id);
 6462                            if above {
 6463                                new_selections.push(new_selection);
 6464                                new_selections.push(selection);
 6465                            } else {
 6466                                new_selections.push(selection);
 6467                                new_selections.push(new_selection);
 6468                            }
 6469
 6470                            continue 'outer;
 6471                        }
 6472                    }
 6473                }
 6474
 6475                new_selections.push(selection);
 6476            }
 6477        } else {
 6478            new_selections = selections;
 6479            new_selections.retain(|s| s.id != last_added_selection);
 6480            state.stack.pop();
 6481        }
 6482
 6483        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6484            s.select(new_selections);
 6485        });
 6486        if state.stack.len() > 1 {
 6487            self.add_selections_state = Some(state);
 6488        }
 6489    }
 6490
 6491    pub fn select_next_match_internal(
 6492        &mut self,
 6493        display_map: &DisplaySnapshot,
 6494        replace_newest: bool,
 6495        autoscroll: Option<Autoscroll>,
 6496        cx: &mut ViewContext<Self>,
 6497    ) -> Result<()> {
 6498        fn select_next_match_ranges(
 6499            this: &mut Editor,
 6500            range: Range<usize>,
 6501            replace_newest: bool,
 6502            auto_scroll: Option<Autoscroll>,
 6503            cx: &mut ViewContext<Editor>,
 6504        ) {
 6505            this.unfold_ranges([range.clone()], false, true, cx);
 6506            this.change_selections(auto_scroll, cx, |s| {
 6507                if replace_newest {
 6508                    s.delete(s.newest_anchor().id);
 6509                }
 6510                s.insert_range(range.clone());
 6511            });
 6512        }
 6513
 6514        let buffer = &display_map.buffer_snapshot;
 6515        let mut selections = self.selections.all::<usize>(cx);
 6516        if let Some(mut select_next_state) = self.select_next_state.take() {
 6517            let query = &select_next_state.query;
 6518            if !select_next_state.done {
 6519                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
 6520                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
 6521                let mut next_selected_range = None;
 6522
 6523                let bytes_after_last_selection =
 6524                    buffer.bytes_in_range(last_selection.end..buffer.len());
 6525                let bytes_before_first_selection = buffer.bytes_in_range(0..first_selection.start);
 6526                let query_matches = query
 6527                    .stream_find_iter(bytes_after_last_selection)
 6528                    .map(|result| (last_selection.end, result))
 6529                    .chain(
 6530                        query
 6531                            .stream_find_iter(bytes_before_first_selection)
 6532                            .map(|result| (0, result)),
 6533                    );
 6534
 6535                for (start_offset, query_match) in query_matches {
 6536                    let query_match = query_match.unwrap(); // can only fail due to I/O
 6537                    let offset_range =
 6538                        start_offset + query_match.start()..start_offset + query_match.end();
 6539                    let display_range = offset_range.start.to_display_point(&display_map)
 6540                        ..offset_range.end.to_display_point(&display_map);
 6541
 6542                    if !select_next_state.wordwise
 6543                        || (!movement::is_inside_word(&display_map, display_range.start)
 6544                            && !movement::is_inside_word(&display_map, display_range.end))
 6545                    {
 6546                        if selections
 6547                            .iter()
 6548                            .find(|selection| selection.range().overlaps(&offset_range))
 6549                            .is_none()
 6550                        {
 6551                            next_selected_range = Some(offset_range);
 6552                            break;
 6553                        }
 6554                    }
 6555                }
 6556
 6557                if let Some(next_selected_range) = next_selected_range {
 6558                    select_next_match_ranges(
 6559                        self,
 6560                        next_selected_range,
 6561                        replace_newest,
 6562                        autoscroll,
 6563                        cx,
 6564                    );
 6565                } else {
 6566                    select_next_state.done = true;
 6567                }
 6568            }
 6569
 6570            self.select_next_state = Some(select_next_state);
 6571        } else if selections.len() == 1 {
 6572            let selection = selections.last_mut().unwrap();
 6573            if selection.start == selection.end {
 6574                let word_range = movement::surrounding_word(
 6575                    &display_map,
 6576                    selection.start.to_display_point(&display_map),
 6577                );
 6578                selection.start = word_range.start.to_offset(&display_map, Bias::Left);
 6579                selection.end = word_range.end.to_offset(&display_map, Bias::Left);
 6580                selection.goal = SelectionGoal::None;
 6581                selection.reversed = false;
 6582
 6583                let query = buffer
 6584                    .text_for_range(selection.start..selection.end)
 6585                    .collect::<String>();
 6586
 6587                let is_empty = query.is_empty();
 6588                let select_state = SelectNextState {
 6589                    query: AhoCorasick::new(&[query])?,
 6590                    wordwise: true,
 6591                    done: is_empty,
 6592                };
 6593                select_next_match_ranges(
 6594                    self,
 6595                    selection.start..selection.end,
 6596                    replace_newest,
 6597                    autoscroll,
 6598                    cx,
 6599                );
 6600                self.select_next_state = Some(select_state);
 6601            } else {
 6602                let query = buffer
 6603                    .text_for_range(selection.start..selection.end)
 6604                    .collect::<String>();
 6605                self.select_next_state = Some(SelectNextState {
 6606                    query: AhoCorasick::new(&[query])?,
 6607                    wordwise: false,
 6608                    done: false,
 6609                });
 6610                self.select_next_match_internal(display_map, replace_newest, autoscroll, cx)?;
 6611            }
 6612        }
 6613        Ok(())
 6614    }
 6615
 6616    pub fn select_all_matches(
 6617        &mut self,
 6618        action: &SelectAllMatches,
 6619        cx: &mut ViewContext<Self>,
 6620    ) -> Result<()> {
 6621        self.push_to_selection_history();
 6622        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 6623
 6624        loop {
 6625            self.select_next_match_internal(&display_map, action.replace_newest, None, cx)?;
 6626
 6627            if self
 6628                .select_next_state
 6629                .as_ref()
 6630                .map(|selection_state| selection_state.done)
 6631                .unwrap_or(true)
 6632            {
 6633                break;
 6634            }
 6635        }
 6636
 6637        Ok(())
 6638    }
 6639
 6640    pub fn select_next(&mut self, action: &SelectNext, cx: &mut ViewContext<Self>) -> Result<()> {
 6641        self.push_to_selection_history();
 6642        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 6643        self.select_next_match_internal(
 6644            &display_map,
 6645            action.replace_newest,
 6646            Some(Autoscroll::newest()),
 6647            cx,
 6648        )?;
 6649        Ok(())
 6650    }
 6651
 6652    pub fn select_previous(
 6653        &mut self,
 6654        action: &SelectPrevious,
 6655        cx: &mut ViewContext<Self>,
 6656    ) -> Result<()> {
 6657        self.push_to_selection_history();
 6658        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 6659        let buffer = &display_map.buffer_snapshot;
 6660        let mut selections = self.selections.all::<usize>(cx);
 6661        if let Some(mut select_prev_state) = self.select_prev_state.take() {
 6662            let query = &select_prev_state.query;
 6663            if !select_prev_state.done {
 6664                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
 6665                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
 6666                let mut next_selected_range = None;
 6667                // When we're iterating matches backwards, the oldest match will actually be the furthest one in the buffer.
 6668                let bytes_before_last_selection =
 6669                    buffer.reversed_bytes_in_range(0..last_selection.start);
 6670                let bytes_after_first_selection =
 6671                    buffer.reversed_bytes_in_range(first_selection.end..buffer.len());
 6672                let query_matches = query
 6673                    .stream_find_iter(bytes_before_last_selection)
 6674                    .map(|result| (last_selection.start, result))
 6675                    .chain(
 6676                        query
 6677                            .stream_find_iter(bytes_after_first_selection)
 6678                            .map(|result| (buffer.len(), result)),
 6679                    );
 6680                for (end_offset, query_match) in query_matches {
 6681                    let query_match = query_match.unwrap(); // can only fail due to I/O
 6682                    let offset_range =
 6683                        end_offset - query_match.end()..end_offset - query_match.start();
 6684                    let display_range = offset_range.start.to_display_point(&display_map)
 6685                        ..offset_range.end.to_display_point(&display_map);
 6686
 6687                    if !select_prev_state.wordwise
 6688                        || (!movement::is_inside_word(&display_map, display_range.start)
 6689                            && !movement::is_inside_word(&display_map, display_range.end))
 6690                    {
 6691                        next_selected_range = Some(offset_range);
 6692                        break;
 6693                    }
 6694                }
 6695
 6696                if let Some(next_selected_range) = next_selected_range {
 6697                    self.unfold_ranges([next_selected_range.clone()], false, true, cx);
 6698                    self.change_selections(Some(Autoscroll::newest()), cx, |s| {
 6699                        if action.replace_newest {
 6700                            s.delete(s.newest_anchor().id);
 6701                        }
 6702                        s.insert_range(next_selected_range);
 6703                    });
 6704                } else {
 6705                    select_prev_state.done = true;
 6706                }
 6707            }
 6708
 6709            self.select_prev_state = Some(select_prev_state);
 6710        } else if selections.len() == 1 {
 6711            let selection = selections.last_mut().unwrap();
 6712            if selection.start == selection.end {
 6713                let word_range = movement::surrounding_word(
 6714                    &display_map,
 6715                    selection.start.to_display_point(&display_map),
 6716                );
 6717                selection.start = word_range.start.to_offset(&display_map, Bias::Left);
 6718                selection.end = word_range.end.to_offset(&display_map, Bias::Left);
 6719                selection.goal = SelectionGoal::None;
 6720                selection.reversed = false;
 6721
 6722                let query = buffer
 6723                    .text_for_range(selection.start..selection.end)
 6724                    .collect::<String>();
 6725                let query = query.chars().rev().collect::<String>();
 6726                let select_state = SelectNextState {
 6727                    query: AhoCorasick::new(&[query])?,
 6728                    wordwise: true,
 6729                    done: false,
 6730                };
 6731                self.unfold_ranges([selection.start..selection.end], false, true, cx);
 6732                self.change_selections(Some(Autoscroll::newest()), cx, |s| {
 6733                    s.select(selections);
 6734                });
 6735                self.select_prev_state = Some(select_state);
 6736            } else {
 6737                let query = buffer
 6738                    .text_for_range(selection.start..selection.end)
 6739                    .collect::<String>();
 6740                let query = query.chars().rev().collect::<String>();
 6741                self.select_prev_state = Some(SelectNextState {
 6742                    query: AhoCorasick::new(&[query])?,
 6743                    wordwise: false,
 6744                    done: false,
 6745                });
 6746                self.select_previous(action, cx)?;
 6747            }
 6748        }
 6749        Ok(())
 6750    }
 6751
 6752    pub fn toggle_comments(&mut self, action: &ToggleComments, cx: &mut ViewContext<Self>) {
 6753        let text_layout_details = &self.text_layout_details(cx);
 6754        self.transact(cx, |this, cx| {
 6755            let mut selections = this.selections.all::<Point>(cx);
 6756            let mut edits = Vec::new();
 6757            let mut selection_edit_ranges = Vec::new();
 6758            let mut last_toggled_row = None;
 6759            let snapshot = this.buffer.read(cx).read(cx);
 6760            let empty_str: Arc<str> = "".into();
 6761            let mut suffixes_inserted = Vec::new();
 6762
 6763            fn comment_prefix_range(
 6764                snapshot: &MultiBufferSnapshot,
 6765                row: u32,
 6766                comment_prefix: &str,
 6767                comment_prefix_whitespace: &str,
 6768            ) -> Range<Point> {
 6769                let start = Point::new(row, snapshot.indent_size_for_line(row).len);
 6770
 6771                let mut line_bytes = snapshot
 6772                    .bytes_in_range(start..snapshot.max_point())
 6773                    .flatten()
 6774                    .copied();
 6775
 6776                // If this line currently begins with the line comment prefix, then record
 6777                // the range containing the prefix.
 6778                if line_bytes
 6779                    .by_ref()
 6780                    .take(comment_prefix.len())
 6781                    .eq(comment_prefix.bytes())
 6782                {
 6783                    // Include any whitespace that matches the comment prefix.
 6784                    let matching_whitespace_len = line_bytes
 6785                        .zip(comment_prefix_whitespace.bytes())
 6786                        .take_while(|(a, b)| a == b)
 6787                        .count() as u32;
 6788                    let end = Point::new(
 6789                        start.row,
 6790                        start.column + comment_prefix.len() as u32 + matching_whitespace_len,
 6791                    );
 6792                    start..end
 6793                } else {
 6794                    start..start
 6795                }
 6796            }
 6797
 6798            fn comment_suffix_range(
 6799                snapshot: &MultiBufferSnapshot,
 6800                row: u32,
 6801                comment_suffix: &str,
 6802                comment_suffix_has_leading_space: bool,
 6803            ) -> Range<Point> {
 6804                let end = Point::new(row, snapshot.line_len(row));
 6805                let suffix_start_column = end.column.saturating_sub(comment_suffix.len() as u32);
 6806
 6807                let mut line_end_bytes = snapshot
 6808                    .bytes_in_range(Point::new(end.row, suffix_start_column.saturating_sub(1))..end)
 6809                    .flatten()
 6810                    .copied();
 6811
 6812                let leading_space_len = if suffix_start_column > 0
 6813                    && line_end_bytes.next() == Some(b' ')
 6814                    && comment_suffix_has_leading_space
 6815                {
 6816                    1
 6817                } else {
 6818                    0
 6819                };
 6820
 6821                // If this line currently begins with the line comment prefix, then record
 6822                // the range containing the prefix.
 6823                if line_end_bytes.by_ref().eq(comment_suffix.bytes()) {
 6824                    let start = Point::new(end.row, suffix_start_column - leading_space_len);
 6825                    start..end
 6826                } else {
 6827                    end..end
 6828                }
 6829            }
 6830
 6831            // TODO: Handle selections that cross excerpts
 6832            for selection in &mut selections {
 6833                let start_column = snapshot.indent_size_for_line(selection.start.row).len;
 6834                let language = if let Some(language) =
 6835                    snapshot.language_scope_at(Point::new(selection.start.row, start_column))
 6836                {
 6837                    language
 6838                } else {
 6839                    continue;
 6840                };
 6841
 6842                selection_edit_ranges.clear();
 6843
 6844                // If multiple selections contain a given row, avoid processing that
 6845                // row more than once.
 6846                let mut start_row = selection.start.row;
 6847                if last_toggled_row == Some(start_row) {
 6848                    start_row += 1;
 6849                }
 6850                let end_row =
 6851                    if selection.end.row > selection.start.row && selection.end.column == 0 {
 6852                        selection.end.row - 1
 6853                    } else {
 6854                        selection.end.row
 6855                    };
 6856                last_toggled_row = Some(end_row);
 6857
 6858                if start_row > end_row {
 6859                    continue;
 6860                }
 6861
 6862                // If the language has line comments, toggle those.
 6863                if let Some(full_comment_prefix) = language.line_comment_prefix() {
 6864                    // Split the comment prefix's trailing whitespace into a separate string,
 6865                    // as that portion won't be used for detecting if a line is a comment.
 6866                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
 6867                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
 6868                    let mut all_selection_lines_are_comments = true;
 6869
 6870                    for row in start_row..=end_row {
 6871                        if snapshot.is_line_blank(row) && start_row < end_row {
 6872                            continue;
 6873                        }
 6874
 6875                        let prefix_range = comment_prefix_range(
 6876                            snapshot.deref(),
 6877                            row,
 6878                            comment_prefix,
 6879                            comment_prefix_whitespace,
 6880                        );
 6881                        if prefix_range.is_empty() {
 6882                            all_selection_lines_are_comments = false;
 6883                        }
 6884                        selection_edit_ranges.push(prefix_range);
 6885                    }
 6886
 6887                    if all_selection_lines_are_comments {
 6888                        edits.extend(
 6889                            selection_edit_ranges
 6890                                .iter()
 6891                                .cloned()
 6892                                .map(|range| (range, empty_str.clone())),
 6893                        );
 6894                    } else {
 6895                        let min_column = selection_edit_ranges
 6896                            .iter()
 6897                            .map(|r| r.start.column)
 6898                            .min()
 6899                            .unwrap_or(0);
 6900                        edits.extend(selection_edit_ranges.iter().map(|range| {
 6901                            let position = Point::new(range.start.row, min_column);
 6902                            (position..position, full_comment_prefix.clone())
 6903                        }));
 6904                    }
 6905                } else if let Some((full_comment_prefix, comment_suffix)) =
 6906                    language.block_comment_delimiters()
 6907                {
 6908                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
 6909                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
 6910                    let prefix_range = comment_prefix_range(
 6911                        snapshot.deref(),
 6912                        start_row,
 6913                        comment_prefix,
 6914                        comment_prefix_whitespace,
 6915                    );
 6916                    let suffix_range = comment_suffix_range(
 6917                        snapshot.deref(),
 6918                        end_row,
 6919                        comment_suffix.trim_start_matches(' '),
 6920                        comment_suffix.starts_with(' '),
 6921                    );
 6922
 6923                    if prefix_range.is_empty() || suffix_range.is_empty() {
 6924                        edits.push((
 6925                            prefix_range.start..prefix_range.start,
 6926                            full_comment_prefix.clone(),
 6927                        ));
 6928                        edits.push((suffix_range.end..suffix_range.end, comment_suffix.clone()));
 6929                        suffixes_inserted.push((end_row, comment_suffix.len()));
 6930                    } else {
 6931                        edits.push((prefix_range, empty_str.clone()));
 6932                        edits.push((suffix_range, empty_str.clone()));
 6933                    }
 6934                } else {
 6935                    continue;
 6936                }
 6937            }
 6938
 6939            drop(snapshot);
 6940            this.buffer.update(cx, |buffer, cx| {
 6941                buffer.edit(edits, None, cx);
 6942            });
 6943
 6944            // Adjust selections so that they end before any comment suffixes that
 6945            // were inserted.
 6946            let mut suffixes_inserted = suffixes_inserted.into_iter().peekable();
 6947            let mut selections = this.selections.all::<Point>(cx);
 6948            let snapshot = this.buffer.read(cx).read(cx);
 6949            for selection in &mut selections {
 6950                while let Some((row, suffix_len)) = suffixes_inserted.peek().copied() {
 6951                    match row.cmp(&selection.end.row) {
 6952                        Ordering::Less => {
 6953                            suffixes_inserted.next();
 6954                            continue;
 6955                        }
 6956                        Ordering::Greater => break,
 6957                        Ordering::Equal => {
 6958                            if selection.end.column == snapshot.line_len(row) {
 6959                                if selection.is_empty() {
 6960                                    selection.start.column -= suffix_len as u32;
 6961                                }
 6962                                selection.end.column -= suffix_len as u32;
 6963                            }
 6964                            break;
 6965                        }
 6966                    }
 6967                }
 6968            }
 6969
 6970            drop(snapshot);
 6971            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
 6972
 6973            let selections = this.selections.all::<Point>(cx);
 6974            let selections_on_single_row = selections.windows(2).all(|selections| {
 6975                selections[0].start.row == selections[1].start.row
 6976                    && selections[0].end.row == selections[1].end.row
 6977                    && selections[0].start.row == selections[0].end.row
 6978            });
 6979            let selections_selecting = selections
 6980                .iter()
 6981                .any(|selection| selection.start != selection.end);
 6982            let advance_downwards = action.advance_downwards
 6983                && selections_on_single_row
 6984                && !selections_selecting
 6985                && this.mode != EditorMode::SingleLine;
 6986
 6987            if advance_downwards {
 6988                let snapshot = this.buffer.read(cx).snapshot(cx);
 6989
 6990                this.change_selections(Some(Autoscroll::fit()), cx, |s| {
 6991                    s.move_cursors_with(|display_snapshot, display_point, _| {
 6992                        let mut point = display_point.to_point(display_snapshot);
 6993                        point.row += 1;
 6994                        point = snapshot.clip_point(point, Bias::Left);
 6995                        let display_point = point.to_display_point(display_snapshot);
 6996                        let goal = SelectionGoal::HorizontalPosition(
 6997                            display_snapshot
 6998                                .x_for_display_point(display_point, &text_layout_details)
 6999                                .into(),
 7000                        );
 7001                        (display_point, goal)
 7002                    })
 7003                });
 7004            }
 7005        });
 7006    }
 7007
 7008    pub fn select_larger_syntax_node(
 7009        &mut self,
 7010        _: &SelectLargerSyntaxNode,
 7011        cx: &mut ViewContext<Self>,
 7012    ) {
 7013        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 7014        let buffer = self.buffer.read(cx).snapshot(cx);
 7015        let old_selections = self.selections.all::<usize>(cx).into_boxed_slice();
 7016
 7017        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
 7018        let mut selected_larger_node = false;
 7019        let new_selections = old_selections
 7020            .iter()
 7021            .map(|selection| {
 7022                let old_range = selection.start..selection.end;
 7023                let mut new_range = old_range.clone();
 7024                while let Some(containing_range) =
 7025                    buffer.range_for_syntax_ancestor(new_range.clone())
 7026                {
 7027                    new_range = containing_range;
 7028                    if !display_map.intersects_fold(new_range.start)
 7029                        && !display_map.intersects_fold(new_range.end)
 7030                    {
 7031                        break;
 7032                    }
 7033                }
 7034
 7035                selected_larger_node |= new_range != old_range;
 7036                Selection {
 7037                    id: selection.id,
 7038                    start: new_range.start,
 7039                    end: new_range.end,
 7040                    goal: SelectionGoal::None,
 7041                    reversed: selection.reversed,
 7042                }
 7043            })
 7044            .collect::<Vec<_>>();
 7045
 7046        if selected_larger_node {
 7047            stack.push(old_selections);
 7048            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7049                s.select(new_selections);
 7050            });
 7051        }
 7052        self.select_larger_syntax_node_stack = stack;
 7053    }
 7054
 7055    pub fn select_smaller_syntax_node(
 7056        &mut self,
 7057        _: &SelectSmallerSyntaxNode,
 7058        cx: &mut ViewContext<Self>,
 7059    ) {
 7060        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
 7061        if let Some(selections) = stack.pop() {
 7062            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7063                s.select(selections.to_vec());
 7064            });
 7065        }
 7066        self.select_larger_syntax_node_stack = stack;
 7067    }
 7068
 7069    pub fn move_to_enclosing_bracket(
 7070        &mut self,
 7071        _: &MoveToEnclosingBracket,
 7072        cx: &mut ViewContext<Self>,
 7073    ) {
 7074        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7075            s.move_offsets_with(|snapshot, selection| {
 7076                let Some(enclosing_bracket_ranges) =
 7077                    snapshot.enclosing_bracket_ranges(selection.start..selection.end)
 7078                else {
 7079                    return;
 7080                };
 7081
 7082                let mut best_length = usize::MAX;
 7083                let mut best_inside = false;
 7084                let mut best_in_bracket_range = false;
 7085                let mut best_destination = None;
 7086                for (open, close) in enclosing_bracket_ranges {
 7087                    let close = close.to_inclusive();
 7088                    let length = close.end() - open.start;
 7089                    let inside = selection.start >= open.end && selection.end <= *close.start();
 7090                    let in_bracket_range = open.to_inclusive().contains(&selection.head())
 7091                        || close.contains(&selection.head());
 7092
 7093                    // If best is next to a bracket and current isn't, skip
 7094                    if !in_bracket_range && best_in_bracket_range {
 7095                        continue;
 7096                    }
 7097
 7098                    // Prefer smaller lengths unless best is inside and current isn't
 7099                    if length > best_length && (best_inside || !inside) {
 7100                        continue;
 7101                    }
 7102
 7103                    best_length = length;
 7104                    best_inside = inside;
 7105                    best_in_bracket_range = in_bracket_range;
 7106                    best_destination = Some(
 7107                        if close.contains(&selection.start) && close.contains(&selection.end) {
 7108                            if inside {
 7109                                open.end
 7110                            } else {
 7111                                open.start
 7112                            }
 7113                        } else {
 7114                            if inside {
 7115                                *close.start()
 7116                            } else {
 7117                                *close.end()
 7118                            }
 7119                        },
 7120                    );
 7121                }
 7122
 7123                if let Some(destination) = best_destination {
 7124                    selection.collapse_to(destination, SelectionGoal::None);
 7125                }
 7126            })
 7127        });
 7128    }
 7129
 7130    pub fn undo_selection(&mut self, _: &UndoSelection, cx: &mut ViewContext<Self>) {
 7131        self.end_selection(cx);
 7132        self.selection_history.mode = SelectionHistoryMode::Undoing;
 7133        if let Some(entry) = self.selection_history.undo_stack.pop_back() {
 7134            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
 7135            self.select_next_state = entry.select_next_state;
 7136            self.select_prev_state = entry.select_prev_state;
 7137            self.add_selections_state = entry.add_selections_state;
 7138            self.request_autoscroll(Autoscroll::newest(), cx);
 7139        }
 7140        self.selection_history.mode = SelectionHistoryMode::Normal;
 7141    }
 7142
 7143    pub fn redo_selection(&mut self, _: &RedoSelection, cx: &mut ViewContext<Self>) {
 7144        self.end_selection(cx);
 7145        self.selection_history.mode = SelectionHistoryMode::Redoing;
 7146        if let Some(entry) = self.selection_history.redo_stack.pop_back() {
 7147            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
 7148            self.select_next_state = entry.select_next_state;
 7149            self.select_prev_state = entry.select_prev_state;
 7150            self.add_selections_state = entry.add_selections_state;
 7151            self.request_autoscroll(Autoscroll::newest(), cx);
 7152        }
 7153        self.selection_history.mode = SelectionHistoryMode::Normal;
 7154    }
 7155
 7156    fn go_to_diagnostic(&mut self, _: &GoToDiagnostic, cx: &mut ViewContext<Self>) {
 7157        self.go_to_diagnostic_impl(Direction::Next, cx)
 7158    }
 7159
 7160    fn go_to_prev_diagnostic(&mut self, _: &GoToPrevDiagnostic, cx: &mut ViewContext<Self>) {
 7161        self.go_to_diagnostic_impl(Direction::Prev, cx)
 7162    }
 7163
 7164    pub fn go_to_diagnostic_impl(&mut self, direction: Direction, cx: &mut ViewContext<Self>) {
 7165        let buffer = self.buffer.read(cx).snapshot(cx);
 7166        let selection = self.selections.newest::<usize>(cx);
 7167
 7168        // If there is an active Diagnostic Popover. Jump to it's diagnostic instead.
 7169        if direction == Direction::Next {
 7170            if let Some(popover) = self.hover_state.diagnostic_popover.as_ref() {
 7171                let (group_id, jump_to) = popover.activation_info();
 7172                if self.activate_diagnostics(group_id, cx) {
 7173                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7174                        let mut new_selection = s.newest_anchor().clone();
 7175                        new_selection.collapse_to(jump_to, SelectionGoal::None);
 7176                        s.select_anchors(vec![new_selection.clone()]);
 7177                    });
 7178                }
 7179                return;
 7180            }
 7181        }
 7182
 7183        let mut active_primary_range = self.active_diagnostics.as_ref().map(|active_diagnostics| {
 7184            active_diagnostics
 7185                .primary_range
 7186                .to_offset(&buffer)
 7187                .to_inclusive()
 7188        });
 7189        let mut search_start = if let Some(active_primary_range) = active_primary_range.as_ref() {
 7190            if active_primary_range.contains(&selection.head()) {
 7191                *active_primary_range.end()
 7192            } else {
 7193                selection.head()
 7194            }
 7195        } else {
 7196            selection.head()
 7197        };
 7198
 7199        loop {
 7200            let mut diagnostics = if direction == Direction::Prev {
 7201                buffer.diagnostics_in_range::<_, usize>(0..search_start, true)
 7202            } else {
 7203                buffer.diagnostics_in_range::<_, usize>(search_start..buffer.len(), false)
 7204            };
 7205            let group = diagnostics.find_map(|entry| {
 7206                if entry.diagnostic.is_primary
 7207                    && entry.diagnostic.severity <= DiagnosticSeverity::WARNING
 7208                    && !entry.range.is_empty()
 7209                    && Some(entry.range.end) != active_primary_range.as_ref().map(|r| *r.end())
 7210                    && !entry.range.contains(&search_start)
 7211                {
 7212                    Some((entry.range, entry.diagnostic.group_id))
 7213                } else {
 7214                    None
 7215                }
 7216            });
 7217
 7218            if let Some((primary_range, group_id)) = group {
 7219                if self.activate_diagnostics(group_id, cx) {
 7220                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7221                        s.select(vec![Selection {
 7222                            id: selection.id,
 7223                            start: primary_range.start,
 7224                            end: primary_range.start,
 7225                            reversed: false,
 7226                            goal: SelectionGoal::None,
 7227                        }]);
 7228                    });
 7229                }
 7230                break;
 7231            } else {
 7232                // Cycle around to the start of the buffer, potentially moving back to the start of
 7233                // the currently active diagnostic.
 7234                active_primary_range.take();
 7235                if direction == Direction::Prev {
 7236                    if search_start == buffer.len() {
 7237                        break;
 7238                    } else {
 7239                        search_start = buffer.len();
 7240                    }
 7241                } else if search_start == 0 {
 7242                    break;
 7243                } else {
 7244                    search_start = 0;
 7245                }
 7246            }
 7247        }
 7248    }
 7249
 7250    fn go_to_hunk(&mut self, _: &GoToHunk, cx: &mut ViewContext<Self>) {
 7251        let snapshot = self
 7252            .display_map
 7253            .update(cx, |display_map, cx| display_map.snapshot(cx));
 7254        let selection = self.selections.newest::<Point>(cx);
 7255
 7256        if !self.seek_in_direction(
 7257            &snapshot,
 7258            selection.head(),
 7259            false,
 7260            snapshot
 7261                .buffer_snapshot
 7262                .git_diff_hunks_in_range((selection.head().row + 1)..u32::MAX),
 7263            cx,
 7264        ) {
 7265            let wrapped_point = Point::zero();
 7266            self.seek_in_direction(
 7267                &snapshot,
 7268                wrapped_point,
 7269                true,
 7270                snapshot
 7271                    .buffer_snapshot
 7272                    .git_diff_hunks_in_range((wrapped_point.row + 1)..u32::MAX),
 7273                cx,
 7274            );
 7275        }
 7276    }
 7277
 7278    fn go_to_prev_hunk(&mut self, _: &GoToPrevHunk, cx: &mut ViewContext<Self>) {
 7279        let snapshot = self
 7280            .display_map
 7281            .update(cx, |display_map, cx| display_map.snapshot(cx));
 7282        let selection = self.selections.newest::<Point>(cx);
 7283
 7284        if !self.seek_in_direction(
 7285            &snapshot,
 7286            selection.head(),
 7287            false,
 7288            snapshot
 7289                .buffer_snapshot
 7290                .git_diff_hunks_in_range_rev(0..selection.head().row),
 7291            cx,
 7292        ) {
 7293            let wrapped_point = snapshot.buffer_snapshot.max_point();
 7294            self.seek_in_direction(
 7295                &snapshot,
 7296                wrapped_point,
 7297                true,
 7298                snapshot
 7299                    .buffer_snapshot
 7300                    .git_diff_hunks_in_range_rev(0..wrapped_point.row),
 7301                cx,
 7302            );
 7303        }
 7304    }
 7305
 7306    fn seek_in_direction(
 7307        &mut self,
 7308        snapshot: &DisplaySnapshot,
 7309        initial_point: Point,
 7310        is_wrapped: bool,
 7311        hunks: impl Iterator<Item = DiffHunk<u32>>,
 7312        cx: &mut ViewContext<Editor>,
 7313    ) -> bool {
 7314        let display_point = initial_point.to_display_point(snapshot);
 7315        let mut hunks = hunks
 7316            .map(|hunk| diff_hunk_to_display(hunk, &snapshot))
 7317            .filter(|hunk| {
 7318                if is_wrapped {
 7319                    true
 7320                } else {
 7321                    !hunk.contains_display_row(display_point.row())
 7322                }
 7323            })
 7324            .dedup();
 7325
 7326        if let Some(hunk) = hunks.next() {
 7327            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7328                let row = hunk.start_display_row();
 7329                let point = DisplayPoint::new(row, 0);
 7330                s.select_display_ranges([point..point]);
 7331            });
 7332
 7333            true
 7334        } else {
 7335            false
 7336        }
 7337    }
 7338
 7339    pub fn go_to_definition(&mut self, _: &GoToDefinition, cx: &mut ViewContext<Self>) {
 7340        self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, false, cx);
 7341    }
 7342
 7343    pub fn go_to_type_definition(&mut self, _: &GoToTypeDefinition, cx: &mut ViewContext<Self>) {
 7344        self.go_to_definition_of_kind(GotoDefinitionKind::Type, false, cx);
 7345    }
 7346
 7347    pub fn go_to_definition_split(&mut self, _: &GoToDefinitionSplit, cx: &mut ViewContext<Self>) {
 7348        self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, true, cx);
 7349    }
 7350
 7351    pub fn go_to_type_definition_split(
 7352        &mut self,
 7353        _: &GoToTypeDefinitionSplit,
 7354        cx: &mut ViewContext<Self>,
 7355    ) {
 7356        self.go_to_definition_of_kind(GotoDefinitionKind::Type, true, cx);
 7357    }
 7358
 7359    fn go_to_definition_of_kind(
 7360        &mut self,
 7361        kind: GotoDefinitionKind,
 7362        split: bool,
 7363        cx: &mut ViewContext<Self>,
 7364    ) {
 7365        let Some(workspace) = self.workspace() else {
 7366            return;
 7367        };
 7368        let buffer = self.buffer.read(cx);
 7369        let head = self.selections.newest::<usize>(cx).head();
 7370        let (buffer, head) = if let Some(text_anchor) = buffer.text_anchor_for_position(head, cx) {
 7371            text_anchor
 7372        } else {
 7373            return;
 7374        };
 7375
 7376        let project = workspace.read(cx).project().clone();
 7377        let definitions = project.update(cx, |project, cx| match kind {
 7378            GotoDefinitionKind::Symbol => project.definition(&buffer, head, cx),
 7379            GotoDefinitionKind::Type => project.type_definition(&buffer, head, cx),
 7380        });
 7381
 7382        cx.spawn(|editor, mut cx| async move {
 7383            let definitions = definitions.await?;
 7384            editor.update(&mut cx, |editor, cx| {
 7385                editor.navigate_to_definitions(
 7386                    definitions
 7387                        .into_iter()
 7388                        .map(GoToDefinitionLink::Text)
 7389                        .collect(),
 7390                    split,
 7391                    cx,
 7392                );
 7393            })?;
 7394            Ok::<(), anyhow::Error>(())
 7395        })
 7396        .detach_and_log_err(cx);
 7397    }
 7398
 7399    pub fn navigate_to_definitions(
 7400        &mut self,
 7401        mut definitions: Vec<GoToDefinitionLink>,
 7402        split: bool,
 7403        cx: &mut ViewContext<Editor>,
 7404    ) {
 7405        let Some(workspace) = self.workspace() else {
 7406            return;
 7407        };
 7408        let pane = workspace.read(cx).active_pane().clone();
 7409        // If there is one definition, just open it directly
 7410        if definitions.len() == 1 {
 7411            let definition = definitions.pop().unwrap();
 7412            let target_task = match definition {
 7413                GoToDefinitionLink::Text(link) => Task::Ready(Some(Ok(Some(link.target)))),
 7414                GoToDefinitionLink::InlayHint(lsp_location, server_id) => {
 7415                    self.compute_target_location(lsp_location, server_id, cx)
 7416                }
 7417            };
 7418            cx.spawn(|editor, mut cx| async move {
 7419                let target = target_task.await.context("target resolution task")?;
 7420                if let Some(target) = target {
 7421                    editor.update(&mut cx, |editor, cx| {
 7422                        let range = target.range.to_offset(target.buffer.read(cx));
 7423                        let range = editor.range_for_match(&range);
 7424                        if Some(&target.buffer) == editor.buffer.read(cx).as_singleton().as_ref() {
 7425                            editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7426                                s.select_ranges([range]);
 7427                            });
 7428                        } else {
 7429                            cx.window_context().defer(move |cx| {
 7430                                let target_editor: View<Self> =
 7431                                    workspace.update(cx, |workspace, cx| {
 7432                                        if split {
 7433                                            workspace.split_project_item(target.buffer.clone(), cx)
 7434                                        } else {
 7435                                            workspace.open_project_item(target.buffer.clone(), cx)
 7436                                        }
 7437                                    });
 7438                                target_editor.update(cx, |target_editor, cx| {
 7439                                    // When selecting a definition in a different buffer, disable the nav history
 7440                                    // to avoid creating a history entry at the previous cursor location.
 7441                                    pane.update(cx, |pane, _| pane.disable_history());
 7442                                    target_editor.change_selections(
 7443                                        Some(Autoscroll::fit()),
 7444                                        cx,
 7445                                        |s| {
 7446                                            s.select_ranges([range]);
 7447                                        },
 7448                                    );
 7449                                    pane.update(cx, |pane, _| pane.enable_history());
 7450                                });
 7451                            });
 7452                        }
 7453                    })
 7454                } else {
 7455                    Ok(())
 7456                }
 7457            })
 7458            .detach_and_log_err(cx);
 7459        } else if !definitions.is_empty() {
 7460            let replica_id = self.replica_id(cx);
 7461            cx.spawn(|editor, mut cx| async move {
 7462                let (title, location_tasks) = editor
 7463                    .update(&mut cx, |editor, cx| {
 7464                        let title = definitions
 7465                            .iter()
 7466                            .find_map(|definition| match definition {
 7467                                GoToDefinitionLink::Text(link) => {
 7468                                    link.origin.as_ref().map(|origin| {
 7469                                        let buffer = origin.buffer.read(cx);
 7470                                        format!(
 7471                                            "Definitions for {}",
 7472                                            buffer
 7473                                                .text_for_range(origin.range.clone())
 7474                                                .collect::<String>()
 7475                                        )
 7476                                    })
 7477                                }
 7478                                GoToDefinitionLink::InlayHint(_, _) => None,
 7479                            })
 7480                            .unwrap_or("Definitions".to_string());
 7481                        let location_tasks = definitions
 7482                            .into_iter()
 7483                            .map(|definition| match definition {
 7484                                GoToDefinitionLink::Text(link) => {
 7485                                    Task::Ready(Some(Ok(Some(link.target))))
 7486                                }
 7487                                GoToDefinitionLink::InlayHint(lsp_location, server_id) => {
 7488                                    editor.compute_target_location(lsp_location, server_id, cx)
 7489                                }
 7490                            })
 7491                            .collect::<Vec<_>>();
 7492                        (title, location_tasks)
 7493                    })
 7494                    .context("location tasks preparation")?;
 7495
 7496                let locations = futures::future::join_all(location_tasks)
 7497                    .await
 7498                    .into_iter()
 7499                    .filter_map(|location| location.transpose())
 7500                    .collect::<Result<_>>()
 7501                    .context("location tasks")?;
 7502                workspace.update(&mut cx, |workspace, cx| {
 7503                    Self::open_locations_in_multibuffer(
 7504                        workspace, locations, replica_id, title, split, cx,
 7505                    )
 7506                });
 7507
 7508                anyhow::Ok(())
 7509            })
 7510            .detach_and_log_err(cx);
 7511        }
 7512    }
 7513
 7514    fn compute_target_location(
 7515        &self,
 7516        lsp_location: lsp::Location,
 7517        server_id: LanguageServerId,
 7518        cx: &mut ViewContext<Editor>,
 7519    ) -> Task<anyhow::Result<Option<Location>>> {
 7520        let Some(project) = self.project.clone() else {
 7521            return Task::Ready(Some(Ok(None)));
 7522        };
 7523
 7524        cx.spawn(move |editor, mut cx| async move {
 7525            let location_task = editor.update(&mut cx, |editor, cx| {
 7526                project.update(cx, |project, cx| {
 7527                    let language_server_name =
 7528                        editor.buffer.read(cx).as_singleton().and_then(|buffer| {
 7529                            project
 7530                                .language_server_for_buffer(buffer.read(cx), server_id, cx)
 7531                                .map(|(_, lsp_adapter)| {
 7532                                    LanguageServerName(Arc::from(lsp_adapter.name()))
 7533                                })
 7534                        });
 7535                    language_server_name.map(|language_server_name| {
 7536                        project.open_local_buffer_via_lsp(
 7537                            lsp_location.uri.clone(),
 7538                            server_id,
 7539                            language_server_name,
 7540                            cx,
 7541                        )
 7542                    })
 7543                })
 7544            })?;
 7545            let location = match location_task {
 7546                Some(task) => Some({
 7547                    let target_buffer_handle = task.await.context("open local buffer")?;
 7548                    let range = target_buffer_handle.update(&mut cx, |target_buffer, _| {
 7549                        let target_start = target_buffer
 7550                            .clip_point_utf16(point_from_lsp(lsp_location.range.start), Bias::Left);
 7551                        let target_end = target_buffer
 7552                            .clip_point_utf16(point_from_lsp(lsp_location.range.end), Bias::Left);
 7553                        target_buffer.anchor_after(target_start)
 7554                            ..target_buffer.anchor_before(target_end)
 7555                    })?;
 7556                    Location {
 7557                        buffer: target_buffer_handle,
 7558                        range,
 7559                    }
 7560                }),
 7561                None => None,
 7562            };
 7563            Ok(location)
 7564        })
 7565    }
 7566
 7567    pub fn find_all_references(
 7568        &mut self,
 7569        _: &FindAllReferences,
 7570        cx: &mut ViewContext<Self>,
 7571    ) -> Option<Task<Result<()>>> {
 7572        let buffer = self.buffer.read(cx);
 7573        let head = self.selections.newest::<usize>(cx).head();
 7574        let (buffer, head) = buffer.text_anchor_for_position(head, cx)?;
 7575        let replica_id = self.replica_id(cx);
 7576
 7577        let workspace = self.workspace()?;
 7578        let project = workspace.read(cx).project().clone();
 7579        let references = project.update(cx, |project, cx| project.references(&buffer, head, cx));
 7580        Some(cx.spawn(|_, mut cx| async move {
 7581            let locations = references.await?;
 7582            if locations.is_empty() {
 7583                return Ok(());
 7584            }
 7585
 7586            workspace.update(&mut cx, |workspace, cx| {
 7587                let title = locations
 7588                    .first()
 7589                    .as_ref()
 7590                    .map(|location| {
 7591                        let buffer = location.buffer.read(cx);
 7592                        format!(
 7593                            "References to `{}`",
 7594                            buffer
 7595                                .text_for_range(location.range.clone())
 7596                                .collect::<String>()
 7597                        )
 7598                    })
 7599                    .unwrap();
 7600                Self::open_locations_in_multibuffer(
 7601                    workspace, locations, replica_id, title, false, cx,
 7602                );
 7603            })?;
 7604
 7605            Ok(())
 7606        }))
 7607    }
 7608
 7609    /// Opens a multibuffer with the given project locations in it
 7610    pub fn open_locations_in_multibuffer(
 7611        workspace: &mut Workspace,
 7612        mut locations: Vec<Location>,
 7613        replica_id: ReplicaId,
 7614        title: String,
 7615        split: bool,
 7616        cx: &mut ViewContext<Workspace>,
 7617    ) {
 7618        // If there are multiple definitions, open them in a multibuffer
 7619        locations.sort_by_key(|location| location.buffer.read(cx).remote_id());
 7620        let mut locations = locations.into_iter().peekable();
 7621        let mut ranges_to_highlight = Vec::new();
 7622
 7623        let excerpt_buffer = cx.build_model(|cx| {
 7624            let mut multibuffer = MultiBuffer::new(replica_id);
 7625            while let Some(location) = locations.next() {
 7626                let buffer = location.buffer.read(cx);
 7627                let mut ranges_for_buffer = Vec::new();
 7628                let range = location.range.to_offset(buffer);
 7629                ranges_for_buffer.push(range.clone());
 7630
 7631                while let Some(next_location) = locations.peek() {
 7632                    if next_location.buffer == location.buffer {
 7633                        ranges_for_buffer.push(next_location.range.to_offset(buffer));
 7634                        locations.next();
 7635                    } else {
 7636                        break;
 7637                    }
 7638                }
 7639
 7640                ranges_for_buffer.sort_by_key(|range| (range.start, Reverse(range.end)));
 7641                ranges_to_highlight.extend(multibuffer.push_excerpts_with_context_lines(
 7642                    location.buffer.clone(),
 7643                    ranges_for_buffer,
 7644                    1,
 7645                    cx,
 7646                ))
 7647            }
 7648
 7649            multibuffer.with_title(title)
 7650        });
 7651
 7652        let editor = cx.build_view(|cx| {
 7653            Editor::for_multibuffer(excerpt_buffer, Some(workspace.project().clone()), cx)
 7654        });
 7655        editor.update(cx, |editor, cx| {
 7656            editor.highlight_background::<Self>(
 7657                ranges_to_highlight,
 7658                |theme| theme.editor_highlighted_line_background,
 7659                cx,
 7660            );
 7661        });
 7662        if split {
 7663            workspace.split_item(SplitDirection::Right, Box::new(editor), cx);
 7664        } else {
 7665            workspace.add_item(Box::new(editor), cx);
 7666        }
 7667    }
 7668
 7669    pub fn rename(&mut self, _: &Rename, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
 7670        use language::ToOffset as _;
 7671
 7672        let project = self.project.clone()?;
 7673        let selection = self.selections.newest_anchor().clone();
 7674        let (cursor_buffer, cursor_buffer_position) = self
 7675            .buffer
 7676            .read(cx)
 7677            .text_anchor_for_position(selection.head(), cx)?;
 7678        let (tail_buffer, _) = self
 7679            .buffer
 7680            .read(cx)
 7681            .text_anchor_for_position(selection.tail(), cx)?;
 7682        if tail_buffer != cursor_buffer {
 7683            return None;
 7684        }
 7685
 7686        let snapshot = cursor_buffer.read(cx).snapshot();
 7687        let cursor_buffer_offset = cursor_buffer_position.to_offset(&snapshot);
 7688        let prepare_rename = project.update(cx, |project, cx| {
 7689            project.prepare_rename(cursor_buffer, cursor_buffer_offset, cx)
 7690        });
 7691
 7692        Some(cx.spawn(|this, mut cx| async move {
 7693            let rename_range = if let Some(range) = prepare_rename.await? {
 7694                Some(range)
 7695            } else {
 7696                this.update(&mut cx, |this, cx| {
 7697                    let buffer = this.buffer.read(cx).snapshot(cx);
 7698                    let mut buffer_highlights = this
 7699                        .document_highlights_for_position(selection.head(), &buffer)
 7700                        .filter(|highlight| {
 7701                            highlight.start.excerpt_id == selection.head().excerpt_id
 7702                                && highlight.end.excerpt_id == selection.head().excerpt_id
 7703                        });
 7704                    buffer_highlights
 7705                        .next()
 7706                        .map(|highlight| highlight.start.text_anchor..highlight.end.text_anchor)
 7707                })?
 7708            };
 7709            if let Some(rename_range) = rename_range {
 7710                let rename_buffer_range = rename_range.to_offset(&snapshot);
 7711                let cursor_offset_in_rename_range =
 7712                    cursor_buffer_offset.saturating_sub(rename_buffer_range.start);
 7713
 7714                this.update(&mut cx, |this, cx| {
 7715                    this.take_rename(false, cx);
 7716                    let buffer = this.buffer.read(cx).read(cx);
 7717                    let cursor_offset = selection.head().to_offset(&buffer);
 7718                    let rename_start = cursor_offset.saturating_sub(cursor_offset_in_rename_range);
 7719                    let rename_end = rename_start + rename_buffer_range.len();
 7720                    let range = buffer.anchor_before(rename_start)..buffer.anchor_after(rename_end);
 7721                    let mut old_highlight_id = None;
 7722                    let old_name: Arc<str> = buffer
 7723                        .chunks(rename_start..rename_end, true)
 7724                        .map(|chunk| {
 7725                            if old_highlight_id.is_none() {
 7726                                old_highlight_id = chunk.syntax_highlight_id;
 7727                            }
 7728                            chunk.text
 7729                        })
 7730                        .collect::<String>()
 7731                        .into();
 7732
 7733                    drop(buffer);
 7734
 7735                    // Position the selection in the rename editor so that it matches the current selection.
 7736                    this.show_local_selections = false;
 7737                    let rename_editor = cx.build_view(|cx| {
 7738                        let mut editor = Editor::single_line(cx);
 7739                        editor.buffer.update(cx, |buffer, cx| {
 7740                            buffer.edit([(0..0, old_name.clone())], None, cx)
 7741                        });
 7742                        editor.select_all(&SelectAll, cx);
 7743                        editor
 7744                    });
 7745
 7746                    let ranges = this
 7747                        .clear_background_highlights::<DocumentHighlightWrite>(cx)
 7748                        .into_iter()
 7749                        .flat_map(|(_, ranges)| ranges.into_iter())
 7750                        .chain(
 7751                            this.clear_background_highlights::<DocumentHighlightRead>(cx)
 7752                                .into_iter()
 7753                                .flat_map(|(_, ranges)| ranges.into_iter()),
 7754                        )
 7755                        .collect();
 7756
 7757                    this.highlight_text::<Rename>(
 7758                        ranges,
 7759                        HighlightStyle {
 7760                            fade_out: Some(0.6),
 7761                            ..Default::default()
 7762                        },
 7763                        cx,
 7764                    );
 7765                    let rename_focus_handle = rename_editor.focus_handle(cx);
 7766                    cx.focus(&rename_focus_handle);
 7767                    let block_id = this.insert_blocks(
 7768                        [BlockProperties {
 7769                            style: BlockStyle::Flex,
 7770                            position: range.start.clone(),
 7771                            height: 1,
 7772                            render: Arc::new({
 7773                                let rename_editor = rename_editor.clone();
 7774                                move |cx: &mut BlockContext| {
 7775                                    let mut text_style = cx.editor_style.text.clone();
 7776                                    if let Some(highlight_style) = old_highlight_id
 7777                                        .and_then(|h| h.style(&cx.editor_style.syntax))
 7778                                    {
 7779                                        text_style = text_style.highlight(highlight_style);
 7780                                    }
 7781                                    div()
 7782                                        .pl(cx.anchor_x)
 7783                                        .child(EditorElement::new(
 7784                                            &rename_editor,
 7785                                            EditorStyle {
 7786                                                background: cx.theme().system().transparent,
 7787                                                local_player: cx.editor_style.local_player,
 7788                                                text: text_style,
 7789                                                scrollbar_width: cx.editor_style.scrollbar_width,
 7790                                                syntax: cx.editor_style.syntax.clone(),
 7791                                                diagnostic_style: cx
 7792                                                    .editor_style
 7793                                                    .diagnostic_style
 7794                                                    .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 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                white_space: WhiteSpace::Normal,
 9402            },
 9403
 9404            EditorMode::AutoHeight { max_lines } => todo!(),
 9405
 9406            EditorMode::Full => TextStyle {
 9407                color: cx.theme().colors().text,
 9408                font_family: settings.buffer_font.family.clone(),
 9409                font_features: settings.buffer_font.features,
 9410                font_size: settings.buffer_font_size.into(),
 9411                font_weight: FontWeight::NORMAL,
 9412                font_style: FontStyle::Normal,
 9413                line_height: relative(settings.buffer_line_height.value()),
 9414                underline: None,
 9415                white_space: WhiteSpace::Normal,
 9416            },
 9417        };
 9418
 9419        let background = match self.mode {
 9420            EditorMode::SingleLine => cx.theme().system().transparent,
 9421            EditorMode::AutoHeight { max_lines } => cx.theme().system().transparent,
 9422            EditorMode::Full => cx.theme().colors().editor_background,
 9423        };
 9424
 9425        EditorElement::new(
 9426            cx.view(),
 9427            EditorStyle {
 9428                background,
 9429                local_player: cx.theme().players().local(),
 9430                text: text_style,
 9431                scrollbar_width: px(12.),
 9432                syntax: cx.theme().syntax().clone(),
 9433                diagnostic_style: cx.theme().diagnostic_style(),
 9434            },
 9435        )
 9436    }
 9437}
 9438
 9439// impl View for Editor {
 9440//     fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
 9441//         let style = self.style(cx);
 9442//         let font_changed = self.display_map.update(cx, |map, cx| {
 9443//             map.set_fold_ellipses_color(style.folds.ellipses.text_color);
 9444//             map.set_font_with_size(style.text.font_id, style.text.font_size, cx)
 9445//         });
 9446
 9447//         if font_changed {
 9448//             cx.defer(move |editor, cx: &mut ViewContext<Editor>| {
 9449//                 hide_hover(editor, cx);
 9450//                 hide_link_definition(editor, cx);
 9451//             });
 9452//         }
 9453
 9454//         Stack::new()
 9455//             .with_child(EditorElement::new(style.clone()))
 9456//             .with_child(ChildView::new(&self.mouse_context_menu, cx))
 9457//             .into_any()
 9458//     }
 9459
 9460//     fn ui_name() -> &'static str {
 9461//         "Editor"
 9462//     }
 9463
 9464//     fn focus_in(&mut self, focused: AnyView, cx: &mut ViewContext<Self>) {
 9465//         if cx.is_self_focused() {
 9466//             let focused_event = EditorFocused(cx.handle());
 9467//             cx.emit(Event::Focused);
 9468//             cx.emit_global(focused_event);
 9469//         }
 9470//         if let Some(rename) = self.pending_rename.as_ref() {
 9471//             cx.focus(&rename.editor);
 9472//         } else if cx.is_self_focused() || !focused.is::<Editor>() {
 9473//             if !self.focused {
 9474//                 self.blink_manager.update(cx, BlinkManager::enable);
 9475//             }
 9476//             self.focused = true;
 9477//             self.buffer.update(cx, |buffer, cx| {
 9478//                 buffer.finalize_last_transaction(cx);
 9479//                 if self.leader_peer_id.is_none() {
 9480//                     buffer.set_active_selections(
 9481//                         &self.selections.disjoint_anchors(),
 9482//                         self.selections.line_mode,
 9483//                         self.cursor_shape,
 9484//                         cx,
 9485//                     );
 9486//                 }
 9487//             });
 9488//         }
 9489//     }
 9490
 9491//     fn focus_out(&mut self, _: AnyView, cx: &mut ViewContext<Self>) {
 9492//         let blurred_event = EditorBlurred(cx.handle());
 9493//         cx.emit_global(blurred_event);
 9494//         self.focused = false;
 9495//         self.blink_manager.update(cx, BlinkManager::disable);
 9496//         self.buffer
 9497//             .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
 9498//         self.hide_context_menu(cx);
 9499//         hide_hover(self, cx);
 9500//         cx.emit(Event::Blurred);
 9501//         cx.notify();
 9502//     }
 9503
 9504//     fn modifiers_changed(
 9505//         &mut self,
 9506//         event: &gpui::platform::ModifiersChangedEvent,
 9507//         cx: &mut ViewContext<Self>,
 9508//     ) -> bool {
 9509//         let pending_selection = self.has_pending_selection();
 9510
 9511//         if let Some(point) = &self.link_go_to_definition_state.last_trigger_point {
 9512//             if event.cmd && !pending_selection {
 9513//                 let point = point.clone();
 9514//                 let snapshot = self.snapshot(cx);
 9515//                 let kind = point.definition_kind(event.shift);
 9516
 9517//                 show_link_definition(kind, self, point, snapshot, cx);
 9518//                 return false;
 9519//             }
 9520//         }
 9521
 9522//         {
 9523//             if self.link_go_to_definition_state.symbol_range.is_some()
 9524//                 || !self.link_go_to_definition_state.definitions.is_empty()
 9525//             {
 9526//                 self.link_go_to_definition_state.symbol_range.take();
 9527//                 self.link_go_to_definition_state.definitions.clear();
 9528//                 cx.notify();
 9529//             }
 9530
 9531//             self.link_go_to_definition_state.task = None;
 9532
 9533//             self.clear_highlights::<LinkGoToDefinitionState>(cx);
 9534//         }
 9535
 9536//         false
 9537//     }
 9538
 9539impl InputHandler for Editor {
 9540    fn text_for_range(
 9541        &mut self,
 9542        range_utf16: Range<usize>,
 9543        cx: &mut ViewContext<Self>,
 9544    ) -> Option<String> {
 9545        Some(
 9546            self.buffer
 9547                .read(cx)
 9548                .read(cx)
 9549                .text_for_range(OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end))
 9550                .collect(),
 9551        )
 9552    }
 9553
 9554    fn selected_text_range(&mut self, cx: &mut ViewContext<Self>) -> Option<Range<usize>> {
 9555        // Prevent the IME menu from appearing when holding down an alphabetic key
 9556        // while input is disabled.
 9557        if !self.input_enabled {
 9558            return None;
 9559        }
 9560
 9561        let range = self.selections.newest::<OffsetUtf16>(cx).range();
 9562        Some(range.start.0..range.end.0)
 9563    }
 9564
 9565    fn marked_text_range(&self, cx: &mut ViewContext<Self>) -> Option<Range<usize>> {
 9566        let snapshot = self.buffer.read(cx).read(cx);
 9567        let range = self.text_highlights::<InputComposition>(cx)?.1.get(0)?;
 9568        Some(range.start.to_offset_utf16(&snapshot).0..range.end.to_offset_utf16(&snapshot).0)
 9569    }
 9570
 9571    fn unmark_text(&mut self, cx: &mut ViewContext<Self>) {
 9572        self.clear_highlights::<InputComposition>(cx);
 9573        self.ime_transaction.take();
 9574    }
 9575
 9576    fn replace_text_in_range(
 9577        &mut self,
 9578        range_utf16: Option<Range<usize>>,
 9579        text: &str,
 9580        cx: &mut ViewContext<Self>,
 9581    ) {
 9582        if !self.input_enabled {
 9583            cx.emit(EditorEvent::InputIgnored { text: text.into() });
 9584            return;
 9585        }
 9586
 9587        self.transact(cx, |this, cx| {
 9588            let new_selected_ranges = if let Some(range_utf16) = range_utf16 {
 9589                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
 9590                Some(this.selection_replacement_ranges(range_utf16, cx))
 9591            } else {
 9592                this.marked_text_ranges(cx)
 9593            };
 9594
 9595            let range_to_replace = new_selected_ranges.as_ref().and_then(|ranges_to_replace| {
 9596                let newest_selection_id = this.selections.newest_anchor().id;
 9597                this.selections
 9598                    .all::<OffsetUtf16>(cx)
 9599                    .iter()
 9600                    .zip(ranges_to_replace.iter())
 9601                    .find_map(|(selection, range)| {
 9602                        if selection.id == newest_selection_id {
 9603                            Some(
 9604                                (range.start.0 as isize - selection.head().0 as isize)
 9605                                    ..(range.end.0 as isize - selection.head().0 as isize),
 9606                            )
 9607                        } else {
 9608                            None
 9609                        }
 9610                    })
 9611            });
 9612
 9613            cx.emit(EditorEvent::InputHandled {
 9614                utf16_range_to_replace: range_to_replace,
 9615                text: text.into(),
 9616            });
 9617
 9618            if let Some(new_selected_ranges) = new_selected_ranges {
 9619                this.change_selections(None, cx, |selections| {
 9620                    selections.select_ranges(new_selected_ranges)
 9621                });
 9622            }
 9623
 9624            this.handle_input(text, cx);
 9625        });
 9626
 9627        if let Some(transaction) = self.ime_transaction {
 9628            self.buffer.update(cx, |buffer, cx| {
 9629                buffer.group_until_transaction(transaction, cx);
 9630            });
 9631        }
 9632
 9633        self.unmark_text(cx);
 9634    }
 9635
 9636    fn replace_and_mark_text_in_range(
 9637        &mut self,
 9638        range_utf16: Option<Range<usize>>,
 9639        text: &str,
 9640        new_selected_range_utf16: Option<Range<usize>>,
 9641        cx: &mut ViewContext<Self>,
 9642    ) {
 9643        if !self.input_enabled {
 9644            cx.emit(EditorEvent::InputIgnored { text: text.into() });
 9645            return;
 9646        }
 9647
 9648        let transaction = self.transact(cx, |this, cx| {
 9649            let ranges_to_replace = if let Some(mut marked_ranges) = this.marked_text_ranges(cx) {
 9650                let snapshot = this.buffer.read(cx).read(cx);
 9651                if let Some(relative_range_utf16) = range_utf16.as_ref() {
 9652                    for marked_range in &mut marked_ranges {
 9653                        marked_range.end.0 = marked_range.start.0 + relative_range_utf16.end;
 9654                        marked_range.start.0 += relative_range_utf16.start;
 9655                        marked_range.start =
 9656                            snapshot.clip_offset_utf16(marked_range.start, Bias::Left);
 9657                        marked_range.end =
 9658                            snapshot.clip_offset_utf16(marked_range.end, Bias::Right);
 9659                    }
 9660                }
 9661                Some(marked_ranges)
 9662            } else if let Some(range_utf16) = range_utf16 {
 9663                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
 9664                Some(this.selection_replacement_ranges(range_utf16, cx))
 9665            } else {
 9666                None
 9667            };
 9668
 9669            let range_to_replace = ranges_to_replace.as_ref().and_then(|ranges_to_replace| {
 9670                let newest_selection_id = this.selections.newest_anchor().id;
 9671                this.selections
 9672                    .all::<OffsetUtf16>(cx)
 9673                    .iter()
 9674                    .zip(ranges_to_replace.iter())
 9675                    .find_map(|(selection, range)| {
 9676                        if selection.id == newest_selection_id {
 9677                            Some(
 9678                                (range.start.0 as isize - selection.head().0 as isize)
 9679                                    ..(range.end.0 as isize - selection.head().0 as isize),
 9680                            )
 9681                        } else {
 9682                            None
 9683                        }
 9684                    })
 9685            });
 9686
 9687            cx.emit(EditorEvent::InputHandled {
 9688                utf16_range_to_replace: range_to_replace,
 9689                text: text.into(),
 9690            });
 9691
 9692            if let Some(ranges) = ranges_to_replace {
 9693                this.change_selections(None, cx, |s| s.select_ranges(ranges));
 9694            }
 9695
 9696            let marked_ranges = {
 9697                let snapshot = this.buffer.read(cx).read(cx);
 9698                this.selections
 9699                    .disjoint_anchors()
 9700                    .iter()
 9701                    .map(|selection| {
 9702                        selection.start.bias_left(&*snapshot)..selection.end.bias_right(&*snapshot)
 9703                    })
 9704                    .collect::<Vec<_>>()
 9705            };
 9706
 9707            if text.is_empty() {
 9708                this.unmark_text(cx);
 9709            } else {
 9710                this.highlight_text::<InputComposition>(
 9711                    marked_ranges.clone(),
 9712                    HighlightStyle::default(), // todo!() this.style(cx).composition_mark,
 9713                    cx,
 9714                );
 9715            }
 9716
 9717            this.handle_input(text, cx);
 9718
 9719            if let Some(new_selected_range) = new_selected_range_utf16 {
 9720                let snapshot = this.buffer.read(cx).read(cx);
 9721                let new_selected_ranges = marked_ranges
 9722                    .into_iter()
 9723                    .map(|marked_range| {
 9724                        let insertion_start = marked_range.start.to_offset_utf16(&snapshot).0;
 9725                        let new_start = OffsetUtf16(new_selected_range.start + insertion_start);
 9726                        let new_end = OffsetUtf16(new_selected_range.end + insertion_start);
 9727                        snapshot.clip_offset_utf16(new_start, Bias::Left)
 9728                            ..snapshot.clip_offset_utf16(new_end, Bias::Right)
 9729                    })
 9730                    .collect::<Vec<_>>();
 9731
 9732                drop(snapshot);
 9733                this.change_selections(None, cx, |selections| {
 9734                    selections.select_ranges(new_selected_ranges)
 9735                });
 9736            }
 9737        });
 9738
 9739        self.ime_transaction = self.ime_transaction.or(transaction);
 9740        if let Some(transaction) = self.ime_transaction {
 9741            self.buffer.update(cx, |buffer, cx| {
 9742                buffer.group_until_transaction(transaction, cx);
 9743            });
 9744        }
 9745
 9746        if self.text_highlights::<InputComposition>(cx).is_none() {
 9747            self.ime_transaction.take();
 9748        }
 9749    }
 9750
 9751    fn bounds_for_range(
 9752        &mut self,
 9753        range_utf16: Range<usize>,
 9754        element_bounds: gpui::Bounds<Pixels>,
 9755        cx: &mut ViewContext<Self>,
 9756    ) -> Option<gpui::Bounds<Pixels>> {
 9757        let text_layout_details = self.text_layout_details(cx);
 9758        let style = &text_layout_details.editor_style;
 9759        let font_id = cx.text_system().font_id(&style.text.font()).unwrap();
 9760        let font_size = style.text.font_size.to_pixels(cx.rem_size());
 9761        let line_height = style.text.line_height_in_pixels(cx.rem_size());
 9762        let em_width = cx
 9763            .text_system()
 9764            .typographic_bounds(font_id, font_size, 'm')
 9765            .unwrap()
 9766            .size
 9767            .width;
 9768
 9769        let snapshot = self.snapshot(cx);
 9770        let scroll_position = snapshot.scroll_position();
 9771        let scroll_left = scroll_position.x * em_width;
 9772
 9773        let start = OffsetUtf16(range_utf16.start).to_display_point(&snapshot);
 9774        let x = snapshot.x_for_display_point(start, &text_layout_details) - scroll_left
 9775            + self.gutter_width;
 9776        let y = line_height * (start.row() as f32 - scroll_position.y);
 9777
 9778        Some(Bounds {
 9779            origin: element_bounds.origin + point(x, y),
 9780            size: size(em_width, line_height),
 9781        })
 9782    }
 9783}
 9784
 9785// fn build_style(
 9786//     settings: &ThemeSettings,
 9787//     get_field_editor_theme: Option<&GetFieldEditorTheme>,
 9788//     override_text_style: Option<&OverrideTextStyle>,
 9789//     cx: &mut AppContext,
 9790// ) -> EditorStyle {
 9791//     let font_cache = cx.font_cache();
 9792//     let line_height_scalar = settings.line_height();
 9793//     let theme_id = settings.theme.meta.id;
 9794//     let mut theme = settings.theme.editor.clone();
 9795//     let mut style = if let Some(get_field_editor_theme) = get_field_editor_theme {
 9796//         let field_editor_theme = get_field_editor_theme(&settings.theme);
 9797//         theme.text_color = field_editor_theme.text.color;
 9798//         theme.selection = field_editor_theme.selection;
 9799//         theme.background = field_editor_theme
 9800//             .container
 9801//             .background_color
 9802//             .unwrap_or_default();
 9803//         EditorStyle {
 9804//             text: field_editor_theme.text,
 9805//             placeholder_text: field_editor_theme.placeholder_text,
 9806//             line_height_scalar,
 9807//             theme,
 9808//             theme_id,
 9809//         }
 9810//     } else {
 9811//         todo!();
 9812//         // let font_family_id = settings.buffer_font_family;
 9813//         // let font_family_name = cx.font_cache().family_name(font_family_id).unwrap();
 9814//         // let font_properties = Default::default();
 9815//         // let font_id = font_cache
 9816//         //     .select_font(font_family_id, &font_properties)
 9817//         //     .unwrap();
 9818//         // let font_size = settings.buffer_font_size(cx);
 9819//         // EditorStyle {
 9820//         //     text: TextStyle {
 9821//         //         color: settings.theme.editor.text_color,
 9822//         //         font_family_name,
 9823//         //         font_family_id,
 9824//         //         font_id,
 9825//         //         font_size,
 9826//         //         font_properties,
 9827//         //         underline: Default::default(),
 9828//         //         soft_wrap: false,
 9829//         //     },
 9830//         //     placeholder_text: None,
 9831//         //     line_height_scalar,
 9832//         //     theme,
 9833//         //     theme_id,
 9834//         // }
 9835//     };
 9836
 9837//     if let Some(highlight_style) = override_text_style.and_then(|build_style| build_style(&style)) {
 9838//         if let Some(highlighted) = style
 9839//             .text
 9840//             .clone()
 9841//             .highlight(highlight_style, font_cache)
 9842//             .log_err()
 9843//         {
 9844//             style.text = highlighted;
 9845//         }
 9846//     }
 9847
 9848//     style
 9849// }
 9850
 9851trait SelectionExt {
 9852    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize>;
 9853    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point>;
 9854    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
 9855    fn spanned_rows(&self, include_end_if_at_line_start: bool, map: &DisplaySnapshot)
 9856        -> Range<u32>;
 9857}
 9858
 9859impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
 9860    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
 9861        let start = self.start.to_point(buffer);
 9862        let end = self.end.to_point(buffer);
 9863        if self.reversed {
 9864            end..start
 9865        } else {
 9866            start..end
 9867        }
 9868    }
 9869
 9870    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
 9871        let start = self.start.to_offset(buffer);
 9872        let end = self.end.to_offset(buffer);
 9873        if self.reversed {
 9874            end..start
 9875        } else {
 9876            start..end
 9877        }
 9878    }
 9879
 9880    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
 9881        let start = self
 9882            .start
 9883            .to_point(&map.buffer_snapshot)
 9884            .to_display_point(map);
 9885        let end = self
 9886            .end
 9887            .to_point(&map.buffer_snapshot)
 9888            .to_display_point(map);
 9889        if self.reversed {
 9890            end..start
 9891        } else {
 9892            start..end
 9893        }
 9894    }
 9895
 9896    fn spanned_rows(
 9897        &self,
 9898        include_end_if_at_line_start: bool,
 9899        map: &DisplaySnapshot,
 9900    ) -> Range<u32> {
 9901        let start = self.start.to_point(&map.buffer_snapshot);
 9902        let mut end = self.end.to_point(&map.buffer_snapshot);
 9903        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
 9904            end.row -= 1;
 9905        }
 9906
 9907        let buffer_start = map.prev_line_boundary(start).0;
 9908        let buffer_end = map.next_line_boundary(end).0;
 9909        buffer_start.row..buffer_end.row + 1
 9910    }
 9911}
 9912
 9913impl<T: InvalidationRegion> InvalidationStack<T> {
 9914    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
 9915    where
 9916        S: Clone + ToOffset,
 9917    {
 9918        while let Some(region) = self.last() {
 9919            let all_selections_inside_invalidation_ranges =
 9920                if selections.len() == region.ranges().len() {
 9921                    selections
 9922                        .iter()
 9923                        .zip(region.ranges().iter().map(|r| r.to_offset(buffer)))
 9924                        .all(|(selection, invalidation_range)| {
 9925                            let head = selection.head().to_offset(buffer);
 9926                            invalidation_range.start <= head && invalidation_range.end >= head
 9927                        })
 9928                } else {
 9929                    false
 9930                };
 9931
 9932            if all_selections_inside_invalidation_ranges {
 9933                break;
 9934            } else {
 9935                self.pop();
 9936            }
 9937        }
 9938    }
 9939}
 9940
 9941impl<T> Default for InvalidationStack<T> {
 9942    fn default() -> Self {
 9943        Self(Default::default())
 9944    }
 9945}
 9946
 9947impl<T> Deref for InvalidationStack<T> {
 9948    type Target = Vec<T>;
 9949
 9950    fn deref(&self) -> &Self::Target {
 9951        &self.0
 9952    }
 9953}
 9954
 9955impl<T> DerefMut for InvalidationStack<T> {
 9956    fn deref_mut(&mut self) -> &mut Self::Target {
 9957        &mut self.0
 9958    }
 9959}
 9960
 9961impl InvalidationRegion for SnippetState {
 9962    fn ranges(&self) -> &[Range<Anchor>] {
 9963        &self.ranges[self.active_index]
 9964    }
 9965}
 9966
 9967// impl Deref for EditorStyle {
 9968//     type Target = theme::Editor;
 9969
 9970//     fn deref(&self) -> &Self::Target {
 9971//         &self.theme
 9972//     }
 9973// }
 9974
 9975pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> RenderBlock {
 9976    let mut highlighted_lines = Vec::new();
 9977
 9978    for (index, line) in diagnostic.message.lines().enumerate() {
 9979        let line = match &diagnostic.source {
 9980            Some(source) if index == 0 => {
 9981                let source_highlight = Vec::from_iter(0..source.len());
 9982                highlight_diagnostic_message(source_highlight, &format!("{source}: {line}"))
 9983            }
 9984
 9985            _ => highlight_diagnostic_message(Vec::new(), line),
 9986        };
 9987        highlighted_lines.push(line);
 9988    }
 9989    let message = diagnostic.message;
 9990    Arc::new(move |cx: &mut BlockContext| {
 9991        let message = message.clone();
 9992        v_stack()
 9993            .id(cx.block_id)
 9994            .size_full()
 9995            .bg(gpui::red())
 9996            .children(highlighted_lines.iter().map(|(line, highlights)| {
 9997                div()
 9998                    .child(HighlightedLabel::new(line.clone(), highlights.clone()))
 9999                    .ml(cx.anchor_x)
10000            }))
10001            .cursor_pointer()
10002            .on_click(cx.listener(move |_, _, cx| {
10003                cx.write_to_clipboard(ClipboardItem::new(message.clone()));
10004            }))
10005            .tooltip(|cx| Tooltip::text("Copy diagnostic message", cx))
10006            .render_into_any()
10007    })
10008}
10009
10010pub fn highlight_diagnostic_message(
10011    initial_highlights: Vec<usize>,
10012    message: &str,
10013) -> (String, Vec<usize>) {
10014    let mut message_without_backticks = String::new();
10015    let mut prev_offset = 0;
10016    let mut inside_block = false;
10017    let mut highlights = initial_highlights;
10018    for (match_ix, (offset, _)) in message
10019        .match_indices('`')
10020        .chain([(message.len(), "")])
10021        .enumerate()
10022    {
10023        message_without_backticks.push_str(&message[prev_offset..offset]);
10024        if inside_block {
10025            highlights.extend(prev_offset - match_ix..offset - match_ix);
10026        }
10027
10028        inside_block = !inside_block;
10029        prev_offset = offset + 1;
10030    }
10031
10032    (message_without_backticks, highlights)
10033}
10034
10035pub fn diagnostic_style(
10036    severity: DiagnosticSeverity,
10037    valid: bool,
10038    style: &DiagnosticStyle,
10039) -> Hsla {
10040    match (severity, valid) {
10041        (DiagnosticSeverity::ERROR, true) => style.error,
10042        (DiagnosticSeverity::ERROR, false) => style.error,
10043        (DiagnosticSeverity::WARNING, true) => style.warning,
10044        (DiagnosticSeverity::WARNING, false) => style.warning,
10045        (DiagnosticSeverity::INFORMATION, true) => style.info,
10046        (DiagnosticSeverity::INFORMATION, false) => style.info,
10047        (DiagnosticSeverity::HINT, true) => style.info,
10048        (DiagnosticSeverity::HINT, false) => style.info,
10049        _ => style.ignored,
10050    }
10051}
10052
10053pub fn combine_syntax_and_fuzzy_match_highlights(
10054    text: &str,
10055    default_style: HighlightStyle,
10056    syntax_ranges: impl Iterator<Item = (Range<usize>, HighlightStyle)>,
10057    match_indices: &[usize],
10058) -> Vec<(Range<usize>, HighlightStyle)> {
10059    let mut result = Vec::new();
10060    let mut match_indices = match_indices.iter().copied().peekable();
10061
10062    for (range, mut syntax_highlight) in syntax_ranges.chain([(usize::MAX..0, Default::default())])
10063    {
10064        syntax_highlight.font_weight = None;
10065
10066        // Add highlights for any fuzzy match characters before the next
10067        // syntax highlight range.
10068        while let Some(&match_index) = match_indices.peek() {
10069            if match_index >= range.start {
10070                break;
10071            }
10072            match_indices.next();
10073            let end_index = char_ix_after(match_index, text);
10074            let mut match_style = default_style;
10075            match_style.font_weight = Some(FontWeight::BOLD);
10076            result.push((match_index..end_index, match_style));
10077        }
10078
10079        if range.start == usize::MAX {
10080            break;
10081        }
10082
10083        // Add highlights for any fuzzy match characters within the
10084        // syntax highlight range.
10085        let mut offset = range.start;
10086        while let Some(&match_index) = match_indices.peek() {
10087            if match_index >= range.end {
10088                break;
10089            }
10090
10091            match_indices.next();
10092            if match_index > offset {
10093                result.push((offset..match_index, syntax_highlight));
10094            }
10095
10096            let mut end_index = char_ix_after(match_index, text);
10097            while let Some(&next_match_index) = match_indices.peek() {
10098                if next_match_index == end_index && next_match_index < range.end {
10099                    end_index = char_ix_after(next_match_index, text);
10100                    match_indices.next();
10101                } else {
10102                    break;
10103                }
10104            }
10105
10106            let mut match_style = syntax_highlight;
10107            match_style.font_weight = Some(FontWeight::BOLD);
10108            result.push((match_index..end_index, match_style));
10109            offset = end_index;
10110        }
10111
10112        if offset < range.end {
10113            result.push((offset..range.end, syntax_highlight));
10114        }
10115    }
10116
10117    fn char_ix_after(ix: usize, text: &str) -> usize {
10118        ix + text[ix..].chars().next().unwrap().len_utf8()
10119    }
10120
10121    result
10122}
10123
10124pub fn styled_runs_for_code_label<'a>(
10125    label: &'a CodeLabel,
10126    syntax_theme: &'a theme::SyntaxTheme,
10127) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
10128    let fade_out = HighlightStyle {
10129        fade_out: Some(0.35),
10130        ..Default::default()
10131    };
10132
10133    let mut prev_end = label.filter_range.end;
10134    label
10135        .runs
10136        .iter()
10137        .enumerate()
10138        .flat_map(move |(ix, (range, highlight_id))| {
10139            let style = if let Some(style) = highlight_id.style(syntax_theme) {
10140                style
10141            } else {
10142                return Default::default();
10143            };
10144            let mut muted_style = style;
10145            muted_style.highlight(fade_out);
10146
10147            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
10148            if range.start >= label.filter_range.end {
10149                if range.start > prev_end {
10150                    runs.push((prev_end..range.start, fade_out));
10151                }
10152                runs.push((range.clone(), muted_style));
10153            } else if range.end <= label.filter_range.end {
10154                runs.push((range.clone(), style));
10155            } else {
10156                runs.push((range.start..label.filter_range.end, style));
10157                runs.push((label.filter_range.end..range.end, muted_style));
10158            }
10159            prev_end = cmp::max(prev_end, range.end);
10160
10161            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
10162                runs.push((prev_end..label.text.len(), fade_out));
10163            }
10164
10165            runs
10166        })
10167}
10168
10169pub fn split_words<'a>(text: &'a str) -> impl std::iter::Iterator<Item = &'a str> + 'a {
10170    let mut index = 0;
10171    let mut codepoints = text.char_indices().peekable();
10172
10173    std::iter::from_fn(move || {
10174        let start_index = index;
10175        while let Some((new_index, codepoint)) = codepoints.next() {
10176            index = new_index + codepoint.len_utf8();
10177            let current_upper = codepoint.is_uppercase();
10178            let next_upper = codepoints
10179                .peek()
10180                .map(|(_, c)| c.is_uppercase())
10181                .unwrap_or(false);
10182
10183            if !current_upper && next_upper {
10184                return Some(&text[start_index..index]);
10185            }
10186        }
10187
10188        index = text.len();
10189        if start_index < text.len() {
10190            return Some(&text[start_index..]);
10191        }
10192        None
10193    })
10194    .flat_map(|word| word.split_inclusive('_'))
10195    .flat_map(|word| word.split_inclusive('-'))
10196}
10197
10198trait RangeToAnchorExt {
10199    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor>;
10200}
10201
10202impl<T: ToOffset> RangeToAnchorExt for Range<T> {
10203    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor> {
10204        snapshot.anchor_after(self.start)..snapshot.anchor_before(self.end)
10205    }
10206}