editor.rs

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