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