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