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