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