editor.rs

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