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