editor.rs

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