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