editor.rs

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