editor.rs

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