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