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