editor.rs

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