editor.rs

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