editor.rs

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