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