editor.rs

    1#![allow(unused)]
    2mod blink_manager;
    3pub mod display_map;
    4mod editor_settings;
    5mod element;
    6mod inlay_hint_cache;
    7
    8mod git;
    9mod highlight_matching_bracket;
   10mod hover_popover;
   11pub mod items;
   12mod link_go_to_definition;
   13mod mouse_context_menu;
   14pub mod movement;
   15mod persistence;
   16pub mod scroll;
   17pub mod selections_collection;
   18
   19#[cfg(test)]
   20mod editor_tests;
   21#[cfg(any(test, feature = "test-support"))]
   22pub mod test;
   23use ::git::diff::DiffHunk;
   24use aho_corasick::AhoCorasick;
   25use anyhow::{Context as _, Result};
   26use blink_manager::BlinkManager;
   27use client::{ClickhouseEvent, Client, Collaborator, ParticipantIndex, TelemetrySettings};
   28use clock::ReplicaId;
   29use collections::{BTreeMap, Bound, HashMap, HashSet, VecDeque};
   30use convert_case::{Case, Casing};
   31use copilot::Copilot;
   32pub use display_map::DisplayPoint;
   33use display_map::*;
   34pub use editor_settings::EditorSettings;
   35pub use element::{
   36    Cursor, EditorElement, HighlightedRange, HighlightedRangeLine, LineWithInvisibles,
   37};
   38use futures::FutureExt;
   39use fuzzy::{StringMatch, StringMatchCandidate};
   40use git::diff_hunk_to_display;
   41use gpui::{
   42    action, actions, div, point, px, relative, rems, size, uniform_list, AnyElement, AppContext,
   43    AsyncWindowContext, BackgroundExecutor, Bounds, ClipboardItem, Component, Context,
   44    EventEmitter, FocusHandle, FontFeatures, FontStyle, FontWeight, HighlightStyle, Hsla,
   45    InputHandler, KeyContext, Model, MouseButton, ParentElement, Pixels, Render,
   46    StatelessInteractive, Styled, Subscription, Task, TextStyle, UniformListScrollHandle, View,
   47    ViewContext, VisualContext, WeakView, WindowContext,
   48};
   49use highlight_matching_bracket::refresh_matching_bracket_highlights;
   50use hover_popover::{hide_hover, HoverState};
   51use inlay_hint_cache::{InlayHintCache, InlaySplice, InvalidationStrategy};
   52pub use items::MAX_TAB_TITLE_LEN;
   53use itertools::Itertools;
   54pub use language::{char_kind, CharKind};
   55use language::{
   56    language_settings::{self, all_language_settings, InlayHintSettings},
   57    point_from_lsp, AutoindentMode, BracketPair, Buffer, CodeAction, Completion, CursorShape,
   58    Diagnostic, IndentKind, IndentSize, Language, LanguageRegistry, LanguageServerName,
   59    OffsetRangeExt, Point, Selection, SelectionGoal, TransactionId,
   60};
   61use lazy_static::lazy_static;
   62use link_go_to_definition::{GoToDefinitionLink, InlayHighlight, LinkGoToDefinitionState};
   63use lsp::{DiagnosticSeverity, Documentation, LanguageServerId};
   64use movement::TextLayoutDetails;
   65use multi_buffer::ToOffsetUtf16;
   66pub use multi_buffer::{
   67    Anchor, AnchorRangeExt, ExcerptId, ExcerptRange, MultiBuffer, MultiBufferSnapshot, ToOffset,
   68    ToPoint,
   69};
   70use ordered_float::OrderedFloat;
   71use parking_lot::{Mutex, RwLock};
   72use project::{FormatTrigger, Location, Project, ProjectTransaction};
   73use rand::prelude::*;
   74use rpc::proto::*;
   75use scroll::{
   76    autoscroll::Autoscroll, OngoingScroll, ScrollAnchor, ScrollManager, ScrollbarAutoHide,
   77};
   78use selections_collection::{resolve_multiple, MutableSelectionsCollection, SelectionsCollection};
   79use serde::{Deserialize, Serialize};
   80use settings::{Settings, SettingsStore};
   81use smallvec::SmallVec;
   82use snippet::Snippet;
   83use std::{
   84    any::TypeId,
   85    borrow::Cow,
   86    cmp::{self, Ordering, Reverse},
   87    mem,
   88    num::NonZeroU32,
   89    ops::{ControlFlow, Deref, DerefMut, Range, RangeInclusive},
   90    path::Path,
   91    sync::Arc,
   92    time::{Duration, Instant},
   93};
   94pub use sum_tree::Bias;
   95use sum_tree::TreeMap;
   96use text::{OffsetUtf16, Rope};
   97use theme::{
   98    ActiveTheme, DiagnosticStyle, PlayerColor, SyntaxTheme, Theme, ThemeColors, ThemeSettings,
   99};
  100use ui::{IconButton, StyledExt};
  101use util::{post_inc, RangeExt, ResultExt, TryFutureExt};
  102use workspace::{
  103    item::ItemEvent, searchable::SearchEvent, ItemNavHistory, SplitDirection, ViewId, Workspace,
  104};
  105
  106const CURSOR_BLINK_INTERVAL: Duration = Duration::from_millis(500);
  107const MAX_LINE_LEN: usize = 1024;
  108const MIN_NAVIGATION_HISTORY_ROW_DELTA: i64 = 10;
  109const MAX_SELECTION_HISTORY_LEN: usize = 1024;
  110const COPILOT_DEBOUNCE_TIMEOUT: Duration = Duration::from_millis(75);
  111pub const CODE_ACTIONS_DEBOUNCE_TIMEOUT: Duration = Duration::from_millis(250);
  112pub const DOCUMENT_HIGHLIGHTS_DEBOUNCE_TIMEOUT: Duration = Duration::from_millis(75);
  113
  114pub const FORMAT_TIMEOUT: Duration = Duration::from_secs(2);
  115
  116// pub fn render_parsed_markdown<Tag: 'static>(
  117//     parsed: &language::ParsedMarkdown,
  118//     editor_style: &EditorStyle,
  119//     workspace: Option<WeakView<Workspace>>,
  120//     cx: &mut ViewContext<Editor>,
  121// ) -> Text {
  122//     enum RenderedMarkdown {}
  123
  124//     let parsed = parsed.clone();
  125//     let view_id = cx.view_id();
  126//     let code_span_background_color = editor_style.document_highlight_read_background;
  127
  128//     let mut region_id = 0;
  129
  130//     todo!()
  131//     // Text::new(parsed.text, editor_style.text.clone())
  132//     //     .with_highlights(
  133//     //         parsed
  134//     //             .highlights
  135//     //             .iter()
  136//     //             .filter_map(|(range, highlight)| {
  137//     //                 let highlight = highlight.to_highlight_style(&editor_style.syntax)?;
  138//     //                 Some((range.clone(), highlight))
  139//     //             })
  140//     //             .collect::<Vec<_>>(),
  141//     //     )
  142//     //     .with_custom_runs(parsed.region_ranges, move |ix, bounds, cx| {
  143//     //         region_id += 1;
  144//     //         let region = parsed.regions[ix].clone();
  145
  146//     //         if let Some(link) = region.link {
  147//     //             cx.scene().push_cursor_region(CursorRegion {
  148//     //                 bounds,
  149//     //                 style: CursorStyle::PointingHand,
  150//     //             });
  151//     //             cx.scene().push_mouse_region(
  152//     //                 MouseRegion::new::<(RenderedMarkdown, Tag)>(view_id, region_id, bounds)
  153//     //                     .on_down::<Editor, _>(MouseButton::Left, move |_, _, cx| match &link {
  154//     //                         markdown::Link::Web { url } => cx.platform().open_url(url),
  155//     //                         markdown::Link::Path { path } => {
  156//     //                             if let Some(workspace) = &workspace {
  157//     //                                 _ = workspace.update(cx, |workspace, cx| {
  158//     //                                     workspace.open_abs_path(path.clone(), false, cx).detach();
  159//     //                                 });
  160//     //                             }
  161//     //                         }
  162//     //                     }),
  163//     //             );
  164//     //         }
  165
  166//     //         if region.code {
  167//     //             cx.draw_quad(Quad {
  168//     //                 bounds,
  169//     //                 background: Some(code_span_background_color),
  170//     //                 corner_radii: (2.0).into(),
  171//     //                 order: todo!(),
  172//     //                 content_mask: todo!(),
  173//     //                 border_color: todo!(),
  174//     //                 border_widths: todo!(),
  175//     //             });
  176//     //         }
  177//     //     })
  178//     //     .with_soft_wrap(true)
  179// }
  180
  181#[action]
  182pub struct SelectNext {
  183    #[serde(default)]
  184    pub replace_newest: bool,
  185}
  186
  187#[action]
  188pub struct SelectPrevious {
  189    #[serde(default)]
  190    pub replace_newest: bool,
  191}
  192
  193#[action]
  194pub struct SelectAllMatches {
  195    #[serde(default)]
  196    pub replace_newest: bool,
  197}
  198
  199#[action]
  200pub struct SelectToBeginningOfLine {
  201    #[serde(default)]
  202    stop_at_soft_wraps: bool,
  203}
  204
  205#[action]
  206pub struct MovePageUp {
  207    #[serde(default)]
  208    center_cursor: bool,
  209}
  210
  211#[action]
  212pub struct MovePageDown {
  213    #[serde(default)]
  214    center_cursor: bool,
  215}
  216
  217#[action]
  218pub struct SelectToEndOfLine {
  219    #[serde(default)]
  220    stop_at_soft_wraps: bool,
  221}
  222
  223#[action]
  224pub struct ToggleCodeActions {
  225    #[serde(default)]
  226    pub deployed_from_indicator: bool,
  227}
  228
  229#[action]
  230pub struct ConfirmCompletion {
  231    #[serde(default)]
  232    pub item_ix: Option<usize>,
  233}
  234
  235#[action]
  236pub struct ConfirmCodeAction {
  237    #[serde(default)]
  238    pub item_ix: Option<usize>,
  239}
  240
  241#[action]
  242pub struct ToggleComments {
  243    #[serde(default)]
  244    pub advance_downwards: bool,
  245}
  246
  247#[action]
  248pub struct FoldAt {
  249    pub buffer_row: u32,
  250}
  251
  252#[action]
  253pub struct UnfoldAt {
  254    pub buffer_row: u32,
  255}
  256
  257#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
  258pub enum InlayId {
  259    Suggestion(usize),
  260    Hint(usize),
  261}
  262
  263impl InlayId {
  264    fn id(&self) -> usize {
  265        match self {
  266            Self::Suggestion(id) => *id,
  267            Self::Hint(id) => *id,
  268        }
  269    }
  270}
  271
  272actions!(
  273    AddSelectionAbove,
  274    AddSelectionBelow,
  275    Backspace,
  276    Cancel,
  277    ConfirmRename,
  278    ContextMenuFirst,
  279    ContextMenuLast,
  280    ContextMenuNext,
  281    ContextMenuPrev,
  282    ConvertToKebabCase,
  283    ConvertToLowerCamelCase,
  284    ConvertToLowerCase,
  285    ConvertToSnakeCase,
  286    ConvertToTitleCase,
  287    ConvertToUpperCamelCase,
  288    ConvertToUpperCase,
  289    Copy,
  290    CopyHighlightJson,
  291    CopyPath,
  292    CopyRelativePath,
  293    Cut,
  294    CutToEndOfLine,
  295    Delete,
  296    DeleteLine,
  297    DeleteToBeginningOfLine,
  298    DeleteToEndOfLine,
  299    DeleteToNextSubwordEnd,
  300    DeleteToNextWordEnd,
  301    DeleteToPreviousSubwordStart,
  302    DeleteToPreviousWordStart,
  303    DuplicateLine,
  304    FindAllReferences,
  305    Fold,
  306    FoldSelectedRanges,
  307    Format,
  308    GoToDefinition,
  309    GoToDefinitionSplit,
  310    GoToDiagnostic,
  311    GoToHunk,
  312    GoToPrevDiagnostic,
  313    GoToPrevHunk,
  314    GoToTypeDefinition,
  315    GoToTypeDefinitionSplit,
  316    HalfPageDown,
  317    HalfPageUp,
  318    Hover,
  319    Indent,
  320    JoinLines,
  321    LineDown,
  322    LineUp,
  323    MoveDown,
  324    MoveLeft,
  325    MoveLineDown,
  326    MoveLineUp,
  327    MoveRight,
  328    MoveToBeginning,
  329    MoveToBeginningOfLine,
  330    MoveToEnclosingBracket,
  331    MoveToEnd,
  332    MoveToEndOfLine,
  333    MoveToEndOfParagraph,
  334    MoveToNextSubwordEnd,
  335    MoveToNextWordEnd,
  336    MoveToPreviousSubwordStart,
  337    MoveToPreviousWordStart,
  338    MoveToStartOfParagraph,
  339    MoveUp,
  340    Newline,
  341    NewlineAbove,
  342    NewlineBelow,
  343    NextScreen,
  344    OpenExcerpts,
  345    Outdent,
  346    PageDown,
  347    PageUp,
  348    Paste,
  349    Redo,
  350    RedoSelection,
  351    Rename,
  352    RestartLanguageServer,
  353    RevealInFinder,
  354    ReverseLines,
  355    ScrollCursorBottom,
  356    ScrollCursorCenter,
  357    ScrollCursorTop,
  358    SelectAll,
  359    SelectDown,
  360    SelectLargerSyntaxNode,
  361    SelectLeft,
  362    SelectLine,
  363    SelectRight,
  364    SelectSmallerSyntaxNode,
  365    SelectToBeginning,
  366    SelectToEnd,
  367    SelectToEndOfParagraph,
  368    SelectToNextSubwordEnd,
  369    SelectToNextWordEnd,
  370    SelectToPreviousSubwordStart,
  371    SelectToPreviousWordStart,
  372    SelectToStartOfParagraph,
  373    SelectUp,
  374    ShowCharacterPalette,
  375    ShowCompletions,
  376    ShuffleLines,
  377    SortLinesCaseInsensitive,
  378    SortLinesCaseSensitive,
  379    SplitSelectionIntoLines,
  380    Tab,
  381    TabPrev,
  382    ToggleInlayHints,
  383    ToggleSoftWrap,
  384    Transpose,
  385    Undo,
  386    UndoSelection,
  387    UnfoldLines,
  388);
  389
  390enum DocumentHighlightRead {}
  391enum DocumentHighlightWrite {}
  392enum InputComposition {}
  393
  394#[derive(Copy, Clone, PartialEq, Eq)]
  395pub enum Direction {
  396    Prev,
  397    Next,
  398}
  399
  400pub fn init_settings(cx: &mut AppContext) {
  401    EditorSettings::register(cx);
  402}
  403
  404pub fn init(cx: &mut AppContext) {
  405    init_settings(cx);
  406    // cx.register_action_type(Editor::new_file);
  407    // cx.register_action_type(Editor::new_file_in_direction);
  408    // cx.register_action_type(Editor::cancel);
  409    // cx.register_action_type(Editor::newline);
  410    // cx.register_action_type(Editor::newline_above);
  411    // cx.register_action_type(Editor::newline_below);
  412    // cx.register_action_type(Editor::backspace);
  413    // cx.register_action_type(Editor::delete);
  414    // cx.register_action_type(Editor::tab);
  415    // cx.register_action_type(Editor::tab_prev);
  416    // cx.register_action_type(Editor::indent);
  417    // cx.register_action_type(Editor::outdent);
  418    // cx.register_action_type(Editor::delete_line);
  419    // cx.register_action_type(Editor::join_lines);
  420    // cx.register_action_type(Editor::sort_lines_case_sensitive);
  421    // cx.register_action_type(Editor::sort_lines_case_insensitive);
  422    // cx.register_action_type(Editor::reverse_lines);
  423    // cx.register_action_type(Editor::shuffle_lines);
  424    // cx.register_action_type(Editor::convert_to_upper_case);
  425    // cx.register_action_type(Editor::convert_to_lower_case);
  426    // cx.register_action_type(Editor::convert_to_title_case);
  427    // cx.register_action_type(Editor::convert_to_snake_case);
  428    // cx.register_action_type(Editor::convert_to_kebab_case);
  429    // cx.register_action_type(Editor::convert_to_upper_camel_case);
  430    // cx.register_action_type(Editor::convert_to_lower_camel_case);
  431    // cx.register_action_type(Editor::delete_to_previous_word_start);
  432    // cx.register_action_type(Editor::delete_to_previous_subword_start);
  433    // cx.register_action_type(Editor::delete_to_next_word_end);
  434    // cx.register_action_type(Editor::delete_to_next_subword_end);
  435    // cx.register_action_type(Editor::delete_to_beginning_of_line);
  436    // cx.register_action_type(Editor::delete_to_end_of_line);
  437    // cx.register_action_type(Editor::cut_to_end_of_line);
  438    // cx.register_action_type(Editor::duplicate_line);
  439    // cx.register_action_type(Editor::move_line_up);
  440    // cx.register_action_type(Editor::move_line_down);
  441    // cx.register_action_type(Editor::transpose);
  442    // cx.register_action_type(Editor::cut);
  443    // cx.register_action_type(Editor::copy);
  444    // cx.register_action_type(Editor::paste);
  445    // cx.register_action_type(Editor::undo);
  446    // cx.register_action_type(Editor::redo);
  447    // cx.register_action_type(Editor::move_page_up);
  448    // cx.register_action_type::<MoveDown>();
  449    // cx.register_action_type(Editor::move_page_down);
  450    // cx.register_action_type(Editor::next_screen);
  451    // cx.register_action_type::<MoveLeft>();
  452    // cx.register_action_type::<MoveRight>();
  453    // cx.register_action_type(Editor::move_to_previous_word_start);
  454    // cx.register_action_type(Editor::move_to_previous_subword_start);
  455    // cx.register_action_type(Editor::move_to_next_word_end);
  456    // cx.register_action_type(Editor::move_to_next_subword_end);
  457    // cx.register_action_type(Editor::move_to_beginning_of_line);
  458    // cx.register_action_type(Editor::move_to_end_of_line);
  459    // cx.register_action_type(Editor::move_to_start_of_paragraph);
  460    // cx.register_action_type(Editor::move_to_end_of_paragraph);
  461    // cx.register_action_type(Editor::move_to_beginning);
  462    // cx.register_action_type(Editor::move_to_end);
  463    // cx.register_action_type(Editor::select_up);
  464    // cx.register_action_type(Editor::select_down);
  465    // cx.register_action_type(Editor::select_left);
  466    // cx.register_action_type(Editor::select_right);
  467    // cx.register_action_type(Editor::select_to_previous_word_start);
  468    // cx.register_action_type(Editor::select_to_previous_subword_start);
  469    // cx.register_action_type(Editor::select_to_next_word_end);
  470    // cx.register_action_type(Editor::select_to_next_subword_end);
  471    // cx.register_action_type(Editor::select_to_beginning_of_line);
  472    // cx.register_action_type(Editor::select_to_end_of_line);
  473    // cx.register_action_type(Editor::select_to_start_of_paragraph);
  474    // cx.register_action_type(Editor::select_to_end_of_paragraph);
  475    // cx.register_action_type(Editor::select_to_beginning);
  476    // cx.register_action_type(Editor::select_to_end);
  477    // cx.register_action_type(Editor::select_all);
  478    // cx.register_action_type(Editor::select_all_matches);
  479    // cx.register_action_type(Editor::select_line);
  480    // cx.register_action_type(Editor::split_selection_into_lines);
  481    // cx.register_action_type(Editor::add_selection_above);
  482    // cx.register_action_type(Editor::add_selection_below);
  483    // cx.register_action_type(Editor::select_next);
  484    // cx.register_action_type(Editor::select_previous);
  485    // cx.register_action_type(Editor::toggle_comments);
  486    // cx.register_action_type(Editor::select_larger_syntax_node);
  487    // cx.register_action_type(Editor::select_smaller_syntax_node);
  488    // cx.register_action_type(Editor::move_to_enclosing_bracket);
  489    // cx.register_action_type(Editor::undo_selection);
  490    // cx.register_action_type(Editor::redo_selection);
  491    // cx.register_action_type(Editor::go_to_diagnostic);
  492    // cx.register_action_type(Editor::go_to_prev_diagnostic);
  493    // cx.register_action_type(Editor::go_to_hunk);
  494    // cx.register_action_type(Editor::go_to_prev_hunk);
  495    // cx.register_action_type(Editor::go_to_definition);
  496    // cx.register_action_type(Editor::go_to_definition_split);
  497    // cx.register_action_type(Editor::go_to_type_definition);
  498    // cx.register_action_type(Editor::go_to_type_definition_split);
  499    // cx.register_action_type(Editor::fold);
  500    // cx.register_action_type(Editor::fold_at);
  501    // cx.register_action_type(Editor::unfold_lines);
  502    // cx.register_action_type(Editor::unfold_at);
  503    // cx.register_action_type(Editor::gutter_hover);
  504    // cx.register_action_type(Editor::fold_selected_ranges);
  505    // cx.register_action_type(Editor::show_completions);
  506    // cx.register_action_type(Editor::toggle_code_actions);
  507    // cx.register_action_type(Editor::open_excerpts);
  508    // cx.register_action_type(Editor::toggle_soft_wrap);
  509    // cx.register_action_type(Editor::toggle_inlay_hints);
  510    // cx.register_action_type(Editor::reveal_in_finder);
  511    // cx.register_action_type(Editor::copy_path);
  512    // cx.register_action_type(Editor::copy_relative_path);
  513    // cx.register_action_type(Editor::copy_highlight_json);
  514    // cx.add_async_action(Editor::format);
  515    // cx.register_action_type(Editor::restart_language_server);
  516    // cx.register_action_type(Editor::show_character_palette);
  517    // cx.add_async_action(Editor::confirm_completion);
  518    // cx.add_async_action(Editor::confirm_code_action);
  519    // cx.add_async_action(Editor::rename);
  520    // cx.add_async_action(Editor::confirm_rename);
  521    // cx.add_async_action(Editor::find_all_references);
  522    // cx.register_action_type(Editor::next_copilot_suggestion);
  523    // cx.register_action_type(Editor::previous_copilot_suggestion);
  524    // cx.register_action_type(Editor::copilot_suggest);
  525    // cx.register_action_type(Editor::context_menu_first);
  526    // cx.register_action_type(Editor::context_menu_prev);
  527    // cx.register_action_type(Editor::context_menu_next);
  528    // cx.register_action_type(Editor::context_menu_last);
  529
  530    hover_popover::init(cx);
  531
  532    workspace::register_project_item::<Editor>(cx);
  533    workspace::register_followable_item::<Editor>(cx);
  534    workspace::register_deserializable_item::<Editor>(cx);
  535}
  536
  537trait InvalidationRegion {
  538    fn ranges(&self) -> &[Range<Anchor>];
  539}
  540
  541#[derive(Clone, Debug, PartialEq)]
  542pub enum SelectPhase {
  543    Begin {
  544        position: DisplayPoint,
  545        add: bool,
  546        click_count: usize,
  547    },
  548    BeginColumnar {
  549        position: DisplayPoint,
  550        goal_column: u32,
  551    },
  552    Extend {
  553        position: DisplayPoint,
  554        click_count: usize,
  555    },
  556    Update {
  557        position: DisplayPoint,
  558        goal_column: u32,
  559        scroll_position: gpui::Point<f32>,
  560    },
  561    End,
  562}
  563
  564#[derive(Clone, Debug)]
  565pub enum SelectMode {
  566    Character,
  567    Word(Range<Anchor>),
  568    Line(Range<Anchor>),
  569    All,
  570}
  571
  572#[derive(Copy, Clone, PartialEq, Eq, Debug)]
  573pub enum EditorMode {
  574    SingleLine,
  575    AutoHeight { max_lines: usize },
  576    Full,
  577}
  578
  579#[derive(Clone, Debug)]
  580pub enum SoftWrap {
  581    None,
  582    EditorWidth,
  583    Column(u32),
  584}
  585
  586#[derive(Clone)]
  587pub struct EditorStyle {
  588    pub background: Hsla,
  589    pub local_player: PlayerColor,
  590    pub text: TextStyle,
  591    pub scrollbar_width: Pixels,
  592    pub syntax: Arc<SyntaxTheme>,
  593    pub diagnostic_style: DiagnosticStyle,
  594}
  595
  596type CompletionId = usize;
  597
  598// type GetFieldEditorTheme = dyn Fn(&theme::Theme) -> theme::FieldEditor;
  599// type OverrideTextStyle = dyn Fn(&EditorStyle) -> Option<HighlightStyle>;
  600
  601type BackgroundHighlight = (fn(&ThemeColors) -> Hsla, Vec<Range<Anchor>>);
  602type InlayBackgroundHighlight = (fn(&ThemeColors) -> Hsla, Vec<InlayHighlight>);
  603
  604pub struct Editor {
  605    handle: WeakView<Self>,
  606    focus_handle: FocusHandle,
  607    buffer: Model<MultiBuffer>,
  608    display_map: Model<DisplayMap>,
  609    pub selections: SelectionsCollection,
  610    pub scroll_manager: ScrollManager,
  611    columnar_selection_tail: Option<Anchor>,
  612    add_selections_state: Option<AddSelectionsState>,
  613    select_next_state: Option<SelectNextState>,
  614    select_prev_state: Option<SelectNextState>,
  615    selection_history: SelectionHistory,
  616    autoclose_regions: Vec<AutocloseRegion>,
  617    snippet_stack: InvalidationStack<SnippetState>,
  618    select_larger_syntax_node_stack: Vec<Box<[Selection<usize>]>>,
  619    ime_transaction: Option<TransactionId>,
  620    active_diagnostics: Option<ActiveDiagnosticGroup>,
  621    soft_wrap_mode_override: Option<language_settings::SoftWrap>,
  622    // get_field_editor_theme: Option<Arc<GetFieldEditorTheme>>,
  623    // override_text_style: Option<Box<OverrideTextStyle>>,
  624    project: Option<Model<Project>>,
  625    collaboration_hub: Option<Box<dyn CollaborationHub>>,
  626    blink_manager: Model<BlinkManager>,
  627    pub show_local_selections: bool,
  628    mode: EditorMode,
  629    show_gutter: bool,
  630    show_wrap_guides: Option<bool>,
  631    placeholder_text: Option<Arc<str>>,
  632    highlighted_rows: Option<Range<u32>>,
  633    background_highlights: BTreeMap<TypeId, BackgroundHighlight>,
  634    inlay_background_highlights: TreeMap<Option<TypeId>, InlayBackgroundHighlight>,
  635    nav_history: Option<ItemNavHistory>,
  636    context_menu: RwLock<Option<ContextMenu>>,
  637    // mouse_context_menu: View<context_menu::ContextMenu>,
  638    completion_tasks: Vec<(CompletionId, Task<Option<()>>)>,
  639    next_completion_id: CompletionId,
  640    available_code_actions: Option<(Model<Buffer>, Arc<[CodeAction]>)>,
  641    code_actions_task: Option<Task<()>>,
  642    document_highlights_task: Option<Task<()>>,
  643    pending_rename: Option<RenameState>,
  644    searchable: bool,
  645    cursor_shape: CursorShape,
  646    collapse_matches: bool,
  647    autoindent_mode: Option<AutoindentMode>,
  648    workspace: Option<(WeakView<Workspace>, i64)>,
  649    keymap_context_layers: BTreeMap<TypeId, 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.add_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    //         workspace: &mut Workspace,
 7593    //         _: &FindAllReferences,
 7594    //         cx: &mut ViewContext<Workspace>,
 7595    //     ) -> Option<Task<Result<()>>> {
 7596    //         let active_item = workspace.active_item(cx)?;
 7597    //         let editor_handle = active_item.act_as::<Self>(cx)?;
 7598
 7599    //         let editor = editor_handle.read(cx);
 7600    //         let buffer = editor.buffer.read(cx);
 7601    //         let head = editor.selections.newest::<usize>(cx).head();
 7602    //         let (buffer, head) = buffer.text_anchor_for_position(head, cx)?;
 7603    //         let replica_id = editor.replica_id(cx);
 7604
 7605    //         let project = workspace.project().clone();
 7606    //         let references = project.update(cx, |project, cx| project.references(&buffer, head, cx));
 7607    //         Some(cx.spawn_labeled(
 7608    //             "Finding All References...",
 7609    //             |workspace, mut cx| async move {
 7610    //                 let locations = references.await?;
 7611    //                 if locations.is_empty() {
 7612    //                     return Ok(());
 7613    //                 }
 7614
 7615    //                 workspace.update(&mut cx, |workspace, cx| {
 7616    //                     let title = locations
 7617    //                         .first()
 7618    //                         .as_ref()
 7619    //                         .map(|location| {
 7620    //                             let buffer = location.buffer.read(cx);
 7621    //                             format!(
 7622    //                                 "References to `{}`",
 7623    //                                 buffer
 7624    //                                     .text_for_range(location.range.clone())
 7625    //                                     .collect::<String>()
 7626    //                             )
 7627    //                         })
 7628    //                         .unwrap();
 7629    //                     Self::open_locations_in_multibuffer(
 7630    //                         workspace, locations, replica_id, title, false, cx,
 7631    //                     );
 7632    //                 })?;
 7633
 7634    //                 Ok(())
 7635    //             },
 7636    //         ))
 7637    //     }
 7638
 7639    /// Opens a multibuffer with the given project locations in it
 7640    pub fn open_locations_in_multibuffer(
 7641        workspace: &mut Workspace,
 7642        mut locations: Vec<Location>,
 7643        replica_id: ReplicaId,
 7644        title: String,
 7645        split: bool,
 7646        cx: &mut ViewContext<Workspace>,
 7647    ) {
 7648        // If there are multiple definitions, open them in a multibuffer
 7649        locations.sort_by_key(|location| location.buffer.read(cx).remote_id());
 7650        let mut locations = locations.into_iter().peekable();
 7651        let mut ranges_to_highlight = Vec::new();
 7652
 7653        let excerpt_buffer = cx.build_model(|cx| {
 7654            let mut multibuffer = MultiBuffer::new(replica_id);
 7655            while let Some(location) = locations.next() {
 7656                let buffer = location.buffer.read(cx);
 7657                let mut ranges_for_buffer = Vec::new();
 7658                let range = location.range.to_offset(buffer);
 7659                ranges_for_buffer.push(range.clone());
 7660
 7661                while let Some(next_location) = locations.peek() {
 7662                    if next_location.buffer == location.buffer {
 7663                        ranges_for_buffer.push(next_location.range.to_offset(buffer));
 7664                        locations.next();
 7665                    } else {
 7666                        break;
 7667                    }
 7668                }
 7669
 7670                ranges_for_buffer.sort_by_key(|range| (range.start, Reverse(range.end)));
 7671                ranges_to_highlight.extend(multibuffer.push_excerpts_with_context_lines(
 7672                    location.buffer.clone(),
 7673                    ranges_for_buffer,
 7674                    1,
 7675                    cx,
 7676                ))
 7677            }
 7678
 7679            multibuffer.with_title(title)
 7680        });
 7681
 7682        let editor = cx.build_view(|cx| {
 7683            Editor::for_multibuffer(excerpt_buffer, Some(workspace.project().clone()), cx)
 7684        });
 7685        editor.update(cx, |editor, cx| {
 7686            editor.highlight_background::<Self>(
 7687                ranges_to_highlight,
 7688                |theme| todo!("theme.editor.highlighted_line_background"),
 7689                cx,
 7690            );
 7691        });
 7692        if split {
 7693            workspace.split_item(SplitDirection::Right, Box::new(editor), cx);
 7694        } else {
 7695            workspace.add_item(Box::new(editor), cx);
 7696        }
 7697    }
 7698
 7699    // pub fn rename(&mut self, _: &Rename, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
 7700    //     use language::ToOffset as _;
 7701
 7702    //     let project = self.project.clone()?;
 7703    //     let selection = self.selections.newest_anchor().clone();
 7704    //     let (cursor_buffer, cursor_buffer_position) = self
 7705    //         .buffer
 7706    //         .read(cx)
 7707    //         .text_anchor_for_position(selection.head(), cx)?;
 7708    //     let (tail_buffer, _) = self
 7709    //         .buffer
 7710    //         .read(cx)
 7711    //         .text_anchor_for_position(selection.tail(), cx)?;
 7712    //     if tail_buffer != cursor_buffer {
 7713    //         return None;
 7714    //     }
 7715
 7716    //     let snapshot = cursor_buffer.read(cx).snapshot();
 7717    //     let cursor_buffer_offset = cursor_buffer_position.to_offset(&snapshot);
 7718    //     let prepare_rename = project.update(cx, |project, cx| {
 7719    //         project.prepare_rename(cursor_buffer, cursor_buffer_offset, cx)
 7720    //     });
 7721
 7722    //     Some(cx.spawn(|this, mut cx| async move {
 7723    //         let rename_range = if let Some(range) = prepare_rename.await? {
 7724    //             Some(range)
 7725    //         } else {
 7726    //             this.update(&mut cx, |this, cx| {
 7727    //                 let buffer = this.buffer.read(cx).snapshot(cx);
 7728    //                 let mut buffer_highlights = this
 7729    //                     .document_highlights_for_position(selection.head(), &buffer)
 7730    //                     .filter(|highlight| {
 7731    //                         highlight.start.excerpt_id == selection.head().excerpt_id
 7732    //                             && highlight.end.excerpt_id == selection.head().excerpt_id
 7733    //                     });
 7734    //                 buffer_highlights
 7735    //                     .next()
 7736    //                     .map(|highlight| highlight.start.text_anchor..highlight.end.text_anchor)
 7737    //             })?
 7738    //         };
 7739    //         if let Some(rename_range) = rename_range {
 7740    //             let rename_buffer_range = rename_range.to_offset(&snapshot);
 7741    //             let cursor_offset_in_rename_range =
 7742    //                 cursor_buffer_offset.saturating_sub(rename_buffer_range.start);
 7743
 7744    //             this.update(&mut cx, |this, cx| {
 7745    //                 this.take_rename(false, cx);
 7746    //                 let buffer = this.buffer.read(cx).read(cx);
 7747    //                 let cursor_offset = selection.head().to_offset(&buffer);
 7748    //                 let rename_start = cursor_offset.saturating_sub(cursor_offset_in_rename_range);
 7749    //                 let rename_end = rename_start + rename_buffer_range.len();
 7750    //                 let range = buffer.anchor_before(rename_start)..buffer.anchor_after(rename_end);
 7751    //                 let mut old_highlight_id = None;
 7752    //                 let old_name: Arc<str> = buffer
 7753    //                     .chunks(rename_start..rename_end, true)
 7754    //                     .map(|chunk| {
 7755    //                         if old_highlight_id.is_none() {
 7756    //                             old_highlight_id = chunk.syntax_highlight_id;
 7757    //                         }
 7758    //                         chunk.text
 7759    //                     })
 7760    //                     .collect::<String>()
 7761    //                     .into();
 7762
 7763    //                 drop(buffer);
 7764
 7765    //                 // Position the selection in the rename editor so that it matches the current selection.
 7766    //                 this.show_local_selections = false;
 7767    //                 let rename_editor = cx.build_view(|cx| {
 7768    //                     let mut editor = Editor::single_line(cx);
 7769    //                     if let Some(old_highlight_id) = old_highlight_id {
 7770    //                         editor.override_text_style =
 7771    //                             Some(Box::new(move |style| old_highlight_id.style(&style.syntax)));
 7772    //                     }
 7773    //                     editor.buffer.update(cx, |buffer, cx| {
 7774    //                         buffer.edit([(0..0, old_name.clone())], None, cx)
 7775    //                     });
 7776    //                     editor.select_all(&SelectAll, cx);
 7777    //                     editor
 7778    //                 });
 7779
 7780    //                 let ranges = this
 7781    //                     .clear_background_highlights::<DocumentHighlightWrite>(cx)
 7782    //                     .into_iter()
 7783    //                     .flat_map(|(_, ranges)| ranges.into_iter())
 7784    //                     .chain(
 7785    //                         this.clear_background_highlights::<DocumentHighlightRead>(cx)
 7786    //                             .into_iter()
 7787    //                             .flat_map(|(_, ranges)| ranges.into_iter()),
 7788    //                     )
 7789    //                     .collect();
 7790
 7791    //                 this.highlight_text::<Rename>(
 7792    //                     ranges,
 7793    //                     HighlightStyle {
 7794    //                         fade_out: Some(style.rename_fade),
 7795    //                         ..Default::default()
 7796    //                     },
 7797    //                     cx,
 7798    //                 );
 7799    //                 cx.focus(&rename_editor);
 7800    //                 let block_id = this.insert_blocks(
 7801    //                     [BlockProperties {
 7802    //                         style: BlockStyle::Flex,
 7803    //                         position: range.start.clone(),
 7804    //                         height: 1,
 7805    //                         render: Arc::new({
 7806    //                             let editor = rename_editor.clone();
 7807    //                             move |cx: &mut BlockContext| {
 7808    //                                 ChildView::new(&editor, cx)
 7809    //                                     .contained()
 7810    //                                     .with_padding_left(cx.anchor_x)
 7811    //                                     .into_any()
 7812    //                             }
 7813    //                         }),
 7814    //                         disposition: BlockDisposition::Below,
 7815    //                     }],
 7816    //                     Some(Autoscroll::fit()),
 7817    //                     cx,
 7818    //                 )[0];
 7819    //                 this.pending_rename = Some(RenameState {
 7820    //                     range,
 7821    //                     old_name,
 7822    //                     editor: rename_editor,
 7823    //                     block_id,
 7824    //                 });
 7825    //             })?;
 7826    //         }
 7827
 7828    //         Ok(())
 7829    //     }))
 7830    // }
 7831
 7832    //     pub fn confirm_rename(
 7833    //         workspace: &mut Workspace,
 7834    //         _: &ConfirmRename,
 7835    //         cx: &mut ViewContext<Workspace>,
 7836    //     ) -> Option<Task<Result<()>>> {
 7837    //         let editor = workspace.active_item(cx)?.act_as::<Editor>(cx)?;
 7838
 7839    //         let (buffer, range, old_name, new_name) = editor.update(cx, |editor, cx| {
 7840    //             let rename = editor.take_rename(false, cx)?;
 7841    //             let buffer = editor.buffer.read(cx);
 7842    //             let (start_buffer, start) =
 7843    //                 buffer.text_anchor_for_position(rename.range.start.clone(), cx)?;
 7844    //             let (end_buffer, end) =
 7845    //                 buffer.text_anchor_for_position(rename.range.end.clone(), cx)?;
 7846    //             if start_buffer == end_buffer {
 7847    //                 let new_name = rename.editor.read(cx).text(cx);
 7848    //                 Some((start_buffer, start..end, rename.old_name, new_name))
 7849    //             } else {
 7850    //                 None
 7851    //             }
 7852    //         })?;
 7853
 7854    //         let rename = workspace.project().clone().update(cx, |project, cx| {
 7855    //             project.perform_rename(buffer.clone(), range.start, new_name.clone(), true, cx)
 7856    //         });
 7857
 7858    //         let editor = editor.downgrade();
 7859    //         Some(cx.spawn(|workspace, mut cx| async move {
 7860    //             let project_transaction = rename.await?;
 7861    //             Self::open_project_transaction(
 7862    //                 &editor,
 7863    //                 workspace,
 7864    //                 project_transaction,
 7865    //                 format!("Rename: {} → {}", old_name, new_name),
 7866    //                 cx.clone(),
 7867    //             )
 7868    //             .await?;
 7869
 7870    //             editor.update(&mut cx, |editor, cx| {
 7871    //                 editor.refresh_document_highlights(cx);
 7872    //             })?;
 7873    //             Ok(())
 7874    //         }))
 7875    //     }
 7876
 7877    fn take_rename(
 7878        &mut self,
 7879        moving_cursor: bool,
 7880        cx: &mut ViewContext<Self>,
 7881    ) -> Option<RenameState> {
 7882        let rename = self.pending_rename.take()?;
 7883        self.remove_blocks(
 7884            [rename.block_id].into_iter().collect(),
 7885            Some(Autoscroll::fit()),
 7886            cx,
 7887        );
 7888        self.clear_highlights::<Rename>(cx);
 7889        self.show_local_selections = true;
 7890
 7891        if moving_cursor {
 7892            let rename_editor = rename.editor.read(cx);
 7893            let cursor_in_rename_editor = rename_editor.selections.newest::<usize>(cx).head();
 7894
 7895            // Update the selection to match the position of the selection inside
 7896            // the rename editor.
 7897            let snapshot = self.buffer.read(cx).read(cx);
 7898            let rename_range = rename.range.to_offset(&snapshot);
 7899            let cursor_in_editor = snapshot
 7900                .clip_offset(rename_range.start + cursor_in_rename_editor, Bias::Left)
 7901                .min(rename_range.end);
 7902            drop(snapshot);
 7903
 7904            self.change_selections(None, cx, |s| {
 7905                s.select_ranges(vec![cursor_in_editor..cursor_in_editor])
 7906            });
 7907        } else {
 7908            self.refresh_document_highlights(cx);
 7909        }
 7910
 7911        Some(rename)
 7912    }
 7913
 7914    #[cfg(any(test, feature = "test-support"))]
 7915    pub fn pending_rename(&self) -> Option<&RenameState> {
 7916        self.pending_rename.as_ref()
 7917    }
 7918
 7919    fn format(&mut self, _: &Format, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
 7920        let project = match &self.project {
 7921            Some(project) => project.clone(),
 7922            None => return None,
 7923        };
 7924
 7925        Some(self.perform_format(project, FormatTrigger::Manual, cx))
 7926    }
 7927
 7928    fn perform_format(
 7929        &mut self,
 7930        project: Model<Project>,
 7931        trigger: FormatTrigger,
 7932        cx: &mut ViewContext<Self>,
 7933    ) -> Task<Result<()>> {
 7934        let buffer = self.buffer().clone();
 7935        let buffers = buffer.read(cx).all_buffers();
 7936
 7937        let mut timeout = cx.background_executor().timer(FORMAT_TIMEOUT).fuse();
 7938        let format = project.update(cx, |project, cx| project.format(buffers, true, trigger, cx));
 7939
 7940        cx.spawn(|_, mut cx| async move {
 7941            let transaction = futures::select_biased! {
 7942                _ = timeout => {
 7943                    log::warn!("timed out waiting for formatting");
 7944                    None
 7945                }
 7946                transaction = format.log_err().fuse() => transaction,
 7947            };
 7948
 7949            buffer.update(&mut cx, |buffer, cx| {
 7950                if let Some(transaction) = transaction {
 7951                    if !buffer.is_singleton() {
 7952                        buffer.push_transaction(&transaction.0, cx);
 7953                    }
 7954                }
 7955
 7956                cx.notify();
 7957            });
 7958
 7959            Ok(())
 7960        })
 7961    }
 7962
 7963    fn restart_language_server(&mut self, _: &RestartLanguageServer, cx: &mut ViewContext<Self>) {
 7964        if let Some(project) = self.project.clone() {
 7965            self.buffer.update(cx, |multi_buffer, cx| {
 7966                project.update(cx, |project, cx| {
 7967                    project.restart_language_servers_for_buffers(multi_buffer.all_buffers(), cx);
 7968                });
 7969            })
 7970        }
 7971    }
 7972
 7973    fn show_character_palette(&mut self, _: &ShowCharacterPalette, cx: &mut ViewContext<Self>) {
 7974        cx.show_character_palette();
 7975    }
 7976
 7977    fn refresh_active_diagnostics(&mut self, cx: &mut ViewContext<Editor>) {
 7978        if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
 7979            let buffer = self.buffer.read(cx).snapshot(cx);
 7980            let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
 7981            let is_valid = buffer
 7982                .diagnostics_in_range::<_, usize>(active_diagnostics.primary_range.clone(), false)
 7983                .any(|entry| {
 7984                    entry.diagnostic.is_primary
 7985                        && !entry.range.is_empty()
 7986                        && entry.range.start == primary_range_start
 7987                        && entry.diagnostic.message == active_diagnostics.primary_message
 7988                });
 7989
 7990            if is_valid != active_diagnostics.is_valid {
 7991                active_diagnostics.is_valid = is_valid;
 7992                let mut new_styles = HashMap::default();
 7993                for (block_id, diagnostic) in &active_diagnostics.blocks {
 7994                    new_styles.insert(
 7995                        *block_id,
 7996                        diagnostic_block_renderer(diagnostic.clone(), is_valid),
 7997                    );
 7998                }
 7999                self.display_map
 8000                    .update(cx, |display_map, _| display_map.replace_blocks(new_styles));
 8001            }
 8002        }
 8003    }
 8004
 8005    fn activate_diagnostics(&mut self, group_id: usize, cx: &mut ViewContext<Self>) -> bool {
 8006        self.dismiss_diagnostics(cx);
 8007        self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
 8008            let buffer = self.buffer.read(cx).snapshot(cx);
 8009
 8010            let mut primary_range = None;
 8011            let mut primary_message = None;
 8012            let mut group_end = Point::zero();
 8013            let diagnostic_group = buffer
 8014                .diagnostic_group::<Point>(group_id)
 8015                .map(|entry| {
 8016                    if entry.range.end > group_end {
 8017                        group_end = entry.range.end;
 8018                    }
 8019                    if entry.diagnostic.is_primary {
 8020                        primary_range = Some(entry.range.clone());
 8021                        primary_message = Some(entry.diagnostic.message.clone());
 8022                    }
 8023                    entry
 8024                })
 8025                .collect::<Vec<_>>();
 8026            let primary_range = primary_range?;
 8027            let primary_message = primary_message?;
 8028            let primary_range =
 8029                buffer.anchor_after(primary_range.start)..buffer.anchor_before(primary_range.end);
 8030
 8031            let blocks = display_map
 8032                .insert_blocks(
 8033                    diagnostic_group.iter().map(|entry| {
 8034                        let diagnostic = entry.diagnostic.clone();
 8035                        let message_height = diagnostic.message.lines().count() as u8;
 8036                        BlockProperties {
 8037                            style: BlockStyle::Fixed,
 8038                            position: buffer.anchor_after(entry.range.start),
 8039                            height: message_height,
 8040                            render: diagnostic_block_renderer(diagnostic, true),
 8041                            disposition: BlockDisposition::Below,
 8042                        }
 8043                    }),
 8044                    cx,
 8045                )
 8046                .into_iter()
 8047                .zip(diagnostic_group.into_iter().map(|entry| entry.diagnostic))
 8048                .collect();
 8049
 8050            Some(ActiveDiagnosticGroup {
 8051                primary_range,
 8052                primary_message,
 8053                blocks,
 8054                is_valid: true,
 8055            })
 8056        });
 8057        self.active_diagnostics.is_some()
 8058    }
 8059
 8060    fn dismiss_diagnostics(&mut self, cx: &mut ViewContext<Self>) {
 8061        if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
 8062            self.display_map.update(cx, |display_map, cx| {
 8063                display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx);
 8064            });
 8065            cx.notify();
 8066        }
 8067    }
 8068
 8069    pub fn set_selections_from_remote(
 8070        &mut self,
 8071        selections: Vec<Selection<Anchor>>,
 8072        pending_selection: Option<Selection<Anchor>>,
 8073        cx: &mut ViewContext<Self>,
 8074    ) {
 8075        let old_cursor_position = self.selections.newest_anchor().head();
 8076        self.selections.change_with(cx, |s| {
 8077            s.select_anchors(selections);
 8078            if let Some(pending_selection) = pending_selection {
 8079                s.set_pending(pending_selection, SelectMode::Character);
 8080            } else {
 8081                s.clear_pending();
 8082            }
 8083        });
 8084        self.selections_did_change(false, &old_cursor_position, cx);
 8085    }
 8086
 8087    fn push_to_selection_history(&mut self) {
 8088        self.selection_history.push(SelectionHistoryEntry {
 8089            selections: self.selections.disjoint_anchors(),
 8090            select_next_state: self.select_next_state.clone(),
 8091            select_prev_state: self.select_prev_state.clone(),
 8092            add_selections_state: self.add_selections_state.clone(),
 8093        });
 8094    }
 8095
 8096    pub fn transact(
 8097        &mut self,
 8098        cx: &mut ViewContext<Self>,
 8099        update: impl FnOnce(&mut Self, &mut ViewContext<Self>),
 8100    ) -> Option<TransactionId> {
 8101        self.start_transaction_at(Instant::now(), cx);
 8102        update(self, cx);
 8103        self.end_transaction_at(Instant::now(), cx)
 8104    }
 8105
 8106    fn start_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
 8107        self.end_selection(cx);
 8108        if let Some(tx_id) = self
 8109            .buffer
 8110            .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx))
 8111        {
 8112            self.selection_history
 8113                .insert_transaction(tx_id, self.selections.disjoint_anchors());
 8114        }
 8115    }
 8116
 8117    fn end_transaction_at(
 8118        &mut self,
 8119        now: Instant,
 8120        cx: &mut ViewContext<Self>,
 8121    ) -> Option<TransactionId> {
 8122        if let Some(tx_id) = self
 8123            .buffer
 8124            .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
 8125        {
 8126            if let Some((_, end_selections)) = self.selection_history.transaction_mut(tx_id) {
 8127                *end_selections = Some(self.selections.disjoint_anchors());
 8128            } else {
 8129                log::error!("unexpectedly ended a transaction that wasn't started by this editor");
 8130            }
 8131
 8132            cx.emit(Event::Edited);
 8133            Some(tx_id)
 8134        } else {
 8135            None
 8136        }
 8137    }
 8138
 8139    pub fn fold(&mut self, _: &Fold, cx: &mut ViewContext<Self>) {
 8140        let mut fold_ranges = Vec::new();
 8141
 8142        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8143
 8144        let selections = self.selections.all_adjusted(cx);
 8145        for selection in selections {
 8146            let range = selection.range().sorted();
 8147            let buffer_start_row = range.start.row;
 8148
 8149            for row in (0..=range.end.row).rev() {
 8150                let fold_range = display_map.foldable_range(row);
 8151
 8152                if let Some(fold_range) = fold_range {
 8153                    if fold_range.end.row >= buffer_start_row {
 8154                        fold_ranges.push(fold_range);
 8155                        if row <= range.start.row {
 8156                            break;
 8157                        }
 8158                    }
 8159                }
 8160            }
 8161        }
 8162
 8163        self.fold_ranges(fold_ranges, true, cx);
 8164    }
 8165
 8166    pub fn fold_at(&mut self, fold_at: &FoldAt, cx: &mut ViewContext<Self>) {
 8167        let buffer_row = fold_at.buffer_row;
 8168        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8169
 8170        if let Some(fold_range) = display_map.foldable_range(buffer_row) {
 8171            let autoscroll = self
 8172                .selections
 8173                .all::<Point>(cx)
 8174                .iter()
 8175                .any(|selection| fold_range.overlaps(&selection.range()));
 8176
 8177            self.fold_ranges(std::iter::once(fold_range), autoscroll, cx);
 8178        }
 8179    }
 8180
 8181    pub fn unfold_lines(&mut self, _: &UnfoldLines, cx: &mut ViewContext<Self>) {
 8182        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8183        let buffer = &display_map.buffer_snapshot;
 8184        let selections = self.selections.all::<Point>(cx);
 8185        let ranges = selections
 8186            .iter()
 8187            .map(|s| {
 8188                let range = s.display_range(&display_map).sorted();
 8189                let mut start = range.start.to_point(&display_map);
 8190                let mut end = range.end.to_point(&display_map);
 8191                start.column = 0;
 8192                end.column = buffer.line_len(end.row);
 8193                start..end
 8194            })
 8195            .collect::<Vec<_>>();
 8196
 8197        self.unfold_ranges(ranges, true, true, cx);
 8198    }
 8199
 8200    pub fn unfold_at(&mut self, unfold_at: &UnfoldAt, cx: &mut ViewContext<Self>) {
 8201        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8202
 8203        let intersection_range = Point::new(unfold_at.buffer_row, 0)
 8204            ..Point::new(
 8205                unfold_at.buffer_row,
 8206                display_map.buffer_snapshot.line_len(unfold_at.buffer_row),
 8207            );
 8208
 8209        let autoscroll = self
 8210            .selections
 8211            .all::<Point>(cx)
 8212            .iter()
 8213            .any(|selection| selection.range().overlaps(&intersection_range));
 8214
 8215        self.unfold_ranges(std::iter::once(intersection_range), true, autoscroll, cx)
 8216    }
 8217
 8218    pub fn fold_selected_ranges(&mut self, _: &FoldSelectedRanges, cx: &mut ViewContext<Self>) {
 8219        let selections = self.selections.all::<Point>(cx);
 8220        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8221        let line_mode = self.selections.line_mode;
 8222        let ranges = selections.into_iter().map(|s| {
 8223            if line_mode {
 8224                let start = Point::new(s.start.row, 0);
 8225                let end = Point::new(s.end.row, display_map.buffer_snapshot.line_len(s.end.row));
 8226                start..end
 8227            } else {
 8228                s.start..s.end
 8229            }
 8230        });
 8231        self.fold_ranges(ranges, true, cx);
 8232    }
 8233
 8234    pub fn fold_ranges<T: ToOffset + Clone>(
 8235        &mut self,
 8236        ranges: impl IntoIterator<Item = Range<T>>,
 8237        auto_scroll: bool,
 8238        cx: &mut ViewContext<Self>,
 8239    ) {
 8240        let mut ranges = ranges.into_iter().peekable();
 8241        if ranges.peek().is_some() {
 8242            self.display_map.update(cx, |map, cx| map.fold(ranges, cx));
 8243
 8244            if auto_scroll {
 8245                self.request_autoscroll(Autoscroll::fit(), cx);
 8246            }
 8247
 8248            cx.notify();
 8249        }
 8250    }
 8251
 8252    pub fn unfold_ranges<T: ToOffset + Clone>(
 8253        &mut self,
 8254        ranges: impl IntoIterator<Item = Range<T>>,
 8255        inclusive: bool,
 8256        auto_scroll: bool,
 8257        cx: &mut ViewContext<Self>,
 8258    ) {
 8259        let mut ranges = ranges.into_iter().peekable();
 8260        if ranges.peek().is_some() {
 8261            self.display_map
 8262                .update(cx, |map, cx| map.unfold(ranges, inclusive, cx));
 8263            if auto_scroll {
 8264                self.request_autoscroll(Autoscroll::fit(), cx);
 8265            }
 8266
 8267            cx.notify();
 8268        }
 8269    }
 8270
 8271    pub fn set_gutter_hovered(&mut self, hovered: bool, cx: &mut ViewContext<Self>) {
 8272        if hovered != self.gutter_hovered {
 8273            self.gutter_hovered = hovered;
 8274            cx.notify();
 8275        }
 8276    }
 8277
 8278    pub fn insert_blocks(
 8279        &mut self,
 8280        blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
 8281        autoscroll: Option<Autoscroll>,
 8282        cx: &mut ViewContext<Self>,
 8283    ) -> Vec<BlockId> {
 8284        let blocks = self
 8285            .display_map
 8286            .update(cx, |display_map, cx| display_map.insert_blocks(blocks, cx));
 8287        if let Some(autoscroll) = autoscroll {
 8288            self.request_autoscroll(autoscroll, cx);
 8289        }
 8290        blocks
 8291    }
 8292
 8293    pub fn replace_blocks(
 8294        &mut self,
 8295        blocks: HashMap<BlockId, RenderBlock>,
 8296        autoscroll: Option<Autoscroll>,
 8297        cx: &mut ViewContext<Self>,
 8298    ) {
 8299        self.display_map
 8300            .update(cx, |display_map, _| display_map.replace_blocks(blocks));
 8301        if let Some(autoscroll) = autoscroll {
 8302            self.request_autoscroll(autoscroll, cx);
 8303        }
 8304    }
 8305
 8306    pub fn remove_blocks(
 8307        &mut self,
 8308        block_ids: HashSet<BlockId>,
 8309        autoscroll: Option<Autoscroll>,
 8310        cx: &mut ViewContext<Self>,
 8311    ) {
 8312        self.display_map.update(cx, |display_map, cx| {
 8313            display_map.remove_blocks(block_ids, cx)
 8314        });
 8315        if let Some(autoscroll) = autoscroll {
 8316            self.request_autoscroll(autoscroll, cx);
 8317        }
 8318    }
 8319
 8320    pub fn longest_row(&self, cx: &mut AppContext) -> u32 {
 8321        self.display_map
 8322            .update(cx, |map, cx| map.snapshot(cx))
 8323            .longest_row()
 8324    }
 8325
 8326    pub fn max_point(&self, cx: &mut AppContext) -> DisplayPoint {
 8327        self.display_map
 8328            .update(cx, |map, cx| map.snapshot(cx))
 8329            .max_point()
 8330    }
 8331
 8332    pub fn text(&self, cx: &AppContext) -> String {
 8333        self.buffer.read(cx).read(cx).text()
 8334    }
 8335
 8336    pub fn set_text(&mut self, text: impl Into<Arc<str>>, cx: &mut ViewContext<Self>) {
 8337        self.transact(cx, |this, cx| {
 8338            this.buffer
 8339                .read(cx)
 8340                .as_singleton()
 8341                .expect("you can only call set_text on editors for singleton buffers")
 8342                .update(cx, |buffer, cx| buffer.set_text(text, cx));
 8343        });
 8344    }
 8345
 8346    pub fn display_text(&self, cx: &mut AppContext) -> String {
 8347        self.display_map
 8348            .update(cx, |map, cx| map.snapshot(cx))
 8349            .text()
 8350    }
 8351
 8352    pub fn wrap_guides(&self, cx: &AppContext) -> SmallVec<[(usize, bool); 2]> {
 8353        let mut wrap_guides = smallvec::smallvec![];
 8354
 8355        if self.show_wrap_guides == Some(false) {
 8356            return wrap_guides;
 8357        }
 8358
 8359        let settings = self.buffer.read(cx).settings_at(0, cx);
 8360        if settings.show_wrap_guides {
 8361            if let SoftWrap::Column(soft_wrap) = self.soft_wrap_mode(cx) {
 8362                wrap_guides.push((soft_wrap as usize, true));
 8363            }
 8364            wrap_guides.extend(settings.wrap_guides.iter().map(|guide| (*guide, false)))
 8365        }
 8366
 8367        wrap_guides
 8368    }
 8369
 8370    pub fn soft_wrap_mode(&self, cx: &AppContext) -> SoftWrap {
 8371        let settings = self.buffer.read(cx).settings_at(0, cx);
 8372        let mode = self
 8373            .soft_wrap_mode_override
 8374            .unwrap_or_else(|| settings.soft_wrap);
 8375        match mode {
 8376            language_settings::SoftWrap::None => SoftWrap::None,
 8377            language_settings::SoftWrap::EditorWidth => SoftWrap::EditorWidth,
 8378            language_settings::SoftWrap::PreferredLineLength => {
 8379                SoftWrap::Column(settings.preferred_line_length)
 8380            }
 8381        }
 8382    }
 8383
 8384    pub fn set_soft_wrap_mode(
 8385        &mut self,
 8386        mode: language_settings::SoftWrap,
 8387        cx: &mut ViewContext<Self>,
 8388    ) {
 8389        self.soft_wrap_mode_override = Some(mode);
 8390        cx.notify();
 8391    }
 8392
 8393    pub fn set_wrap_width(&self, width: Option<Pixels>, cx: &mut AppContext) -> bool {
 8394        self.display_map
 8395            .update(cx, |map, cx| map.set_wrap_width(width, cx))
 8396    }
 8397
 8398    pub fn toggle_soft_wrap(&mut self, _: &ToggleSoftWrap, cx: &mut ViewContext<Self>) {
 8399        if self.soft_wrap_mode_override.is_some() {
 8400            self.soft_wrap_mode_override.take();
 8401        } else {
 8402            let soft_wrap = match self.soft_wrap_mode(cx) {
 8403                SoftWrap::None => language_settings::SoftWrap::EditorWidth,
 8404                SoftWrap::EditorWidth | SoftWrap::Column(_) => language_settings::SoftWrap::None,
 8405            };
 8406            self.soft_wrap_mode_override = Some(soft_wrap);
 8407        }
 8408        cx.notify();
 8409    }
 8410
 8411    pub fn set_show_gutter(&mut self, show_gutter: bool, cx: &mut ViewContext<Self>) {
 8412        self.show_gutter = show_gutter;
 8413        cx.notify();
 8414    }
 8415
 8416    pub fn set_show_wrap_guides(&mut self, show_gutter: bool, cx: &mut ViewContext<Self>) {
 8417        self.show_wrap_guides = Some(show_gutter);
 8418        cx.notify();
 8419    }
 8420
 8421    pub fn reveal_in_finder(&mut self, _: &RevealInFinder, cx: &mut ViewContext<Self>) {
 8422        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
 8423            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
 8424                cx.reveal_path(&file.abs_path(cx));
 8425            }
 8426        }
 8427    }
 8428
 8429    pub fn copy_path(&mut self, _: &CopyPath, cx: &mut ViewContext<Self>) {
 8430        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
 8431            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
 8432                if let Some(path) = file.abs_path(cx).to_str() {
 8433                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
 8434                }
 8435            }
 8436        }
 8437    }
 8438
 8439    pub fn copy_relative_path(&mut self, _: &CopyRelativePath, cx: &mut ViewContext<Self>) {
 8440        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
 8441            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
 8442                if let Some(path) = file.path().to_str() {
 8443                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
 8444                }
 8445            }
 8446        }
 8447    }
 8448
 8449    pub fn highlight_rows(&mut self, rows: Option<Range<u32>>) {
 8450        self.highlighted_rows = rows;
 8451    }
 8452
 8453    pub fn highlighted_rows(&self) -> Option<Range<u32>> {
 8454        self.highlighted_rows.clone()
 8455    }
 8456
 8457    pub fn highlight_background<T: 'static>(
 8458        &mut self,
 8459        ranges: Vec<Range<Anchor>>,
 8460        color_fetcher: fn(&ThemeColors) -> Hsla,
 8461        cx: &mut ViewContext<Self>,
 8462    ) {
 8463        self.background_highlights
 8464            .insert(TypeId::of::<T>(), (color_fetcher, ranges));
 8465        cx.notify();
 8466    }
 8467
 8468    pub fn highlight_inlay_background<T: 'static>(
 8469        &mut self,
 8470        ranges: Vec<InlayHighlight>,
 8471        color_fetcher: fn(&ThemeColors) -> Hsla,
 8472        cx: &mut ViewContext<Self>,
 8473    ) {
 8474        // TODO: no actual highlights happen for inlays currently, find a way to do that
 8475        self.inlay_background_highlights
 8476            .insert(Some(TypeId::of::<T>()), (color_fetcher, ranges));
 8477        cx.notify();
 8478    }
 8479
 8480    pub fn clear_background_highlights<T: 'static>(
 8481        &mut self,
 8482        cx: &mut ViewContext<Self>,
 8483    ) -> Option<BackgroundHighlight> {
 8484        let text_highlights = self.background_highlights.remove(&TypeId::of::<T>());
 8485        let inlay_highlights = self
 8486            .inlay_background_highlights
 8487            .remove(&Some(TypeId::of::<T>()));
 8488        if text_highlights.is_some() || inlay_highlights.is_some() {
 8489            cx.notify();
 8490        }
 8491        text_highlights
 8492    }
 8493
 8494    #[cfg(feature = "test-support")]
 8495    pub fn all_text_background_highlights(
 8496        &mut self,
 8497        cx: &mut ViewContext<Self>,
 8498    ) -> Vec<(Range<DisplayPoint>, Hsla)> {
 8499        let snapshot = self.snapshot(cx);
 8500        let buffer = &snapshot.buffer_snapshot;
 8501        let start = buffer.anchor_before(0);
 8502        let end = buffer.anchor_after(buffer.len());
 8503        let theme = cx.theme().colors();
 8504        self.background_highlights_in_range(start..end, &snapshot, theme)
 8505    }
 8506
 8507    fn document_highlights_for_position<'a>(
 8508        &'a self,
 8509        position: Anchor,
 8510        buffer: &'a MultiBufferSnapshot,
 8511    ) -> impl 'a + Iterator<Item = &Range<Anchor>> {
 8512        let read_highlights = self
 8513            .background_highlights
 8514            .get(&TypeId::of::<DocumentHighlightRead>())
 8515            .map(|h| &h.1);
 8516        let write_highlights = self
 8517            .background_highlights
 8518            .get(&TypeId::of::<DocumentHighlightWrite>())
 8519            .map(|h| &h.1);
 8520        let left_position = position.bias_left(buffer);
 8521        let right_position = position.bias_right(buffer);
 8522        read_highlights
 8523            .into_iter()
 8524            .chain(write_highlights)
 8525            .flat_map(move |ranges| {
 8526                let start_ix = match ranges.binary_search_by(|probe| {
 8527                    let cmp = probe.end.cmp(&left_position, buffer);
 8528                    if cmp.is_ge() {
 8529                        Ordering::Greater
 8530                    } else {
 8531                        Ordering::Less
 8532                    }
 8533                }) {
 8534                    Ok(i) | Err(i) => i,
 8535                };
 8536
 8537                let right_position = right_position.clone();
 8538                ranges[start_ix..]
 8539                    .iter()
 8540                    .take_while(move |range| range.start.cmp(&right_position, buffer).is_le())
 8541            })
 8542    }
 8543
 8544    pub fn background_highlights_in_range(
 8545        &self,
 8546        search_range: Range<Anchor>,
 8547        display_snapshot: &DisplaySnapshot,
 8548        theme: &ThemeColors,
 8549    ) -> Vec<(Range<DisplayPoint>, Hsla)> {
 8550        let mut results = Vec::new();
 8551        for (color_fetcher, ranges) in self.background_highlights.values() {
 8552            let color = color_fetcher(theme);
 8553            let start_ix = match ranges.binary_search_by(|probe| {
 8554                let cmp = probe
 8555                    .end
 8556                    .cmp(&search_range.start, &display_snapshot.buffer_snapshot);
 8557                if cmp.is_gt() {
 8558                    Ordering::Greater
 8559                } else {
 8560                    Ordering::Less
 8561                }
 8562            }) {
 8563                Ok(i) | Err(i) => i,
 8564            };
 8565            for range in &ranges[start_ix..] {
 8566                if range
 8567                    .start
 8568                    .cmp(&search_range.end, &display_snapshot.buffer_snapshot)
 8569                    .is_ge()
 8570                {
 8571                    break;
 8572                }
 8573
 8574                let start = range.start.to_display_point(&display_snapshot);
 8575                let end = range.end.to_display_point(&display_snapshot);
 8576                results.push((start..end, color))
 8577            }
 8578        }
 8579        results
 8580    }
 8581
 8582    pub fn background_highlight_row_ranges<T: 'static>(
 8583        &self,
 8584        search_range: Range<Anchor>,
 8585        display_snapshot: &DisplaySnapshot,
 8586        count: usize,
 8587    ) -> Vec<RangeInclusive<DisplayPoint>> {
 8588        let mut results = Vec::new();
 8589        let Some((_, ranges)) = self.background_highlights.get(&TypeId::of::<T>()) else {
 8590            return vec![];
 8591        };
 8592
 8593        let start_ix = match ranges.binary_search_by(|probe| {
 8594            let cmp = probe
 8595                .end
 8596                .cmp(&search_range.start, &display_snapshot.buffer_snapshot);
 8597            if cmp.is_gt() {
 8598                Ordering::Greater
 8599            } else {
 8600                Ordering::Less
 8601            }
 8602        }) {
 8603            Ok(i) | Err(i) => i,
 8604        };
 8605        let mut push_region = |start: Option<Point>, end: Option<Point>| {
 8606            if let (Some(start_display), Some(end_display)) = (start, end) {
 8607                results.push(
 8608                    start_display.to_display_point(display_snapshot)
 8609                        ..=end_display.to_display_point(display_snapshot),
 8610                );
 8611            }
 8612        };
 8613        let mut start_row: Option<Point> = None;
 8614        let mut end_row: Option<Point> = None;
 8615        if ranges.len() > count {
 8616            return Vec::new();
 8617        }
 8618        for range in &ranges[start_ix..] {
 8619            if range
 8620                .start
 8621                .cmp(&search_range.end, &display_snapshot.buffer_snapshot)
 8622                .is_ge()
 8623            {
 8624                break;
 8625            }
 8626            let end = range.end.to_point(&display_snapshot.buffer_snapshot);
 8627            if let Some(current_row) = &end_row {
 8628                if end.row == current_row.row {
 8629                    continue;
 8630                }
 8631            }
 8632            let start = range.start.to_point(&display_snapshot.buffer_snapshot);
 8633            if start_row.is_none() {
 8634                assert_eq!(end_row, None);
 8635                start_row = Some(start);
 8636                end_row = Some(end);
 8637                continue;
 8638            }
 8639            if let Some(current_end) = end_row.as_mut() {
 8640                if start.row > current_end.row + 1 {
 8641                    push_region(start_row, end_row);
 8642                    start_row = Some(start);
 8643                    end_row = Some(end);
 8644                } else {
 8645                    // Merge two hunks.
 8646                    *current_end = end;
 8647                }
 8648            } else {
 8649                unreachable!();
 8650            }
 8651        }
 8652        // We might still have a hunk that was not rendered (if there was a search hit on the last line)
 8653        push_region(start_row, end_row);
 8654        results
 8655    }
 8656
 8657    pub fn highlight_text<T: 'static>(
 8658        &mut self,
 8659        ranges: Vec<Range<Anchor>>,
 8660        style: HighlightStyle,
 8661        cx: &mut ViewContext<Self>,
 8662    ) {
 8663        self.display_map.update(cx, |map, _| {
 8664            map.highlight_text(TypeId::of::<T>(), ranges, style)
 8665        });
 8666        cx.notify();
 8667    }
 8668
 8669    pub fn highlight_inlays<T: 'static>(
 8670        &mut self,
 8671        highlights: Vec<InlayHighlight>,
 8672        style: HighlightStyle,
 8673        cx: &mut ViewContext<Self>,
 8674    ) {
 8675        self.display_map.update(cx, |map, _| {
 8676            map.highlight_inlays(TypeId::of::<T>(), highlights, style)
 8677        });
 8678        cx.notify();
 8679    }
 8680
 8681    pub fn text_highlights<'a, T: 'static>(
 8682        &'a self,
 8683        cx: &'a AppContext,
 8684    ) -> Option<(HighlightStyle, &'a [Range<Anchor>])> {
 8685        self.display_map.read(cx).text_highlights(TypeId::of::<T>())
 8686    }
 8687
 8688    pub fn clear_highlights<T: 'static>(&mut self, cx: &mut ViewContext<Self>) {
 8689        let cleared = self
 8690            .display_map
 8691            .update(cx, |map, _| map.clear_highlights(TypeId::of::<T>()));
 8692        if cleared {
 8693            cx.notify();
 8694        }
 8695    }
 8696
 8697    pub fn show_local_cursors(&self, cx: &WindowContext) -> bool {
 8698        self.blink_manager.read(cx).visible() && self.focus_handle.is_focused(cx)
 8699    }
 8700
 8701    fn on_buffer_changed(&mut self, _: Model<MultiBuffer>, cx: &mut ViewContext<Self>) {
 8702        cx.notify();
 8703    }
 8704
 8705    fn on_buffer_event(
 8706        &mut self,
 8707        multibuffer: Model<MultiBuffer>,
 8708        event: &multi_buffer::Event,
 8709        cx: &mut ViewContext<Self>,
 8710    ) {
 8711        match event {
 8712            multi_buffer::Event::Edited {
 8713                sigleton_buffer_edited,
 8714            } => {
 8715                self.refresh_active_diagnostics(cx);
 8716                self.refresh_code_actions(cx);
 8717                if self.has_active_copilot_suggestion(cx) {
 8718                    self.update_visible_copilot_suggestion(cx);
 8719                }
 8720                cx.emit(Event::BufferEdited);
 8721                cx.emit(ItemEvent::Edit);
 8722                cx.emit(ItemEvent::UpdateBreadcrumbs);
 8723                cx.emit(SearchEvent::MatchesInvalidated);
 8724
 8725                if *sigleton_buffer_edited {
 8726                    if let Some(project) = &self.project {
 8727                        let project = project.read(cx);
 8728                        let languages_affected = multibuffer
 8729                            .read(cx)
 8730                            .all_buffers()
 8731                            .into_iter()
 8732                            .filter_map(|buffer| {
 8733                                let buffer = buffer.read(cx);
 8734                                let language = buffer.language()?;
 8735                                if project.is_local()
 8736                                    && project.language_servers_for_buffer(buffer, cx).count() == 0
 8737                                {
 8738                                    None
 8739                                } else {
 8740                                    Some(language)
 8741                                }
 8742                            })
 8743                            .cloned()
 8744                            .collect::<HashSet<_>>();
 8745                        if !languages_affected.is_empty() {
 8746                            self.refresh_inlay_hints(
 8747                                InlayHintRefreshReason::BufferEdited(languages_affected),
 8748                                cx,
 8749                            );
 8750                        }
 8751                    }
 8752                }
 8753            }
 8754            multi_buffer::Event::ExcerptsAdded {
 8755                buffer,
 8756                predecessor,
 8757                excerpts,
 8758            } => {
 8759                cx.emit(Event::ExcerptsAdded {
 8760                    buffer: buffer.clone(),
 8761                    predecessor: *predecessor,
 8762                    excerpts: excerpts.clone(),
 8763                });
 8764                self.refresh_inlay_hints(InlayHintRefreshReason::NewLinesShown, cx);
 8765            }
 8766            multi_buffer::Event::ExcerptsRemoved { ids } => {
 8767                self.refresh_inlay_hints(InlayHintRefreshReason::ExcerptsRemoved(ids.clone()), cx);
 8768                cx.emit(Event::ExcerptsRemoved { ids: ids.clone() })
 8769            }
 8770            multi_buffer::Event::Reparsed => {
 8771                cx.emit(ItemEvent::UpdateBreadcrumbs);
 8772            }
 8773            multi_buffer::Event::DirtyChanged => {
 8774                cx.emit(ItemEvent::UpdateTab);
 8775            }
 8776            multi_buffer::Event::Saved
 8777            | multi_buffer::Event::FileHandleChanged
 8778            | multi_buffer::Event::Reloaded => {
 8779                cx.emit(ItemEvent::UpdateTab);
 8780                cx.emit(ItemEvent::UpdateBreadcrumbs);
 8781            }
 8782            multi_buffer::Event::DiffBaseChanged => cx.emit(Event::DiffBaseChanged),
 8783            multi_buffer::Event::Closed => cx.emit(ItemEvent::CloseItem),
 8784            multi_buffer::Event::DiagnosticsUpdated => {
 8785                self.refresh_active_diagnostics(cx);
 8786            }
 8787            _ => {}
 8788        };
 8789    }
 8790
 8791    fn on_display_map_changed(&mut self, _: Model<DisplayMap>, cx: &mut ViewContext<Self>) {
 8792        cx.notify();
 8793    }
 8794
 8795    fn settings_changed(&mut self, cx: &mut ViewContext<Self>) {
 8796        self.refresh_copilot_suggestions(true, cx);
 8797        self.refresh_inlay_hints(
 8798            InlayHintRefreshReason::SettingsChange(inlay_hint_settings(
 8799                self.selections.newest_anchor().head(),
 8800                &self.buffer.read(cx).snapshot(cx),
 8801                cx,
 8802            )),
 8803            cx,
 8804        );
 8805    }
 8806
 8807    //     pub fn set_searchable(&mut self, searchable: bool) {
 8808    //         self.searchable = searchable;
 8809    //     }
 8810
 8811    //     pub fn searchable(&self) -> bool {
 8812    //         self.searchable
 8813    //     }
 8814
 8815    //     fn open_excerpts(workspace: &mut Workspace, _: &OpenExcerpts, cx: &mut ViewContext<Workspace>) {
 8816    //         let active_item = workspace.active_item(cx);
 8817    //         let editor_handle = if let Some(editor) = active_item
 8818    //             .as_ref()
 8819    //             .and_then(|item| item.act_as::<Self>(cx))
 8820    //         {
 8821    //             editor
 8822    //         } else {
 8823    //             cx.propagate();
 8824    //             return;
 8825    //         };
 8826
 8827    //         let editor = editor_handle.read(cx);
 8828    //         let buffer = editor.buffer.read(cx);
 8829    //         if buffer.is_singleton() {
 8830    //             cx.propagate();
 8831    //             return;
 8832    //         }
 8833
 8834    //         let mut new_selections_by_buffer = HashMap::default();
 8835    //         for selection in editor.selections.all::<usize>(cx) {
 8836    //             for (buffer, mut range, _) in
 8837    //                 buffer.range_to_buffer_ranges(selection.start..selection.end, cx)
 8838    //             {
 8839    //                 if selection.reversed {
 8840    //                     mem::swap(&mut range.start, &mut range.end);
 8841    //                 }
 8842    //                 new_selections_by_buffer
 8843    //                     .entry(buffer)
 8844    //                     .or_insert(Vec::new())
 8845    //                     .push(range)
 8846    //             }
 8847    //         }
 8848
 8849    //         editor_handle.update(cx, |editor, cx| {
 8850    //             editor.push_to_nav_history(editor.selections.newest_anchor().head(), None, cx);
 8851    //         });
 8852    //         let pane = workspace.active_pane().clone();
 8853    //         pane.update(cx, |pane, _| pane.disable_history());
 8854
 8855    //         // We defer the pane interaction because we ourselves are a workspace item
 8856    //         // and activating a new item causes the pane to call a method on us reentrantly,
 8857    //         // which panics if we're on the stack.
 8858    //         cx.defer(move |workspace, cx| {
 8859    //             for (buffer, ranges) in new_selections_by_buffer.into_iter() {
 8860    //                 let editor = workspace.open_project_item::<Self>(buffer, cx);
 8861    //                 editor.update(cx, |editor, cx| {
 8862    //                     editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
 8863    //                         s.select_ranges(ranges);
 8864    //                     });
 8865    //                 });
 8866    //             }
 8867
 8868    //             pane.update(cx, |pane, _| pane.enable_history());
 8869    //         });
 8870    //     }
 8871
 8872    //     fn jump(
 8873    //         workspace: &mut Workspace,
 8874    //         path: ProjectPath,
 8875    //         position: Point,
 8876    //         anchor: language::Anchor,
 8877    //         cx: &mut ViewContext<Workspace>,
 8878    //     ) {
 8879    //         let editor = workspace.open_path(path, None, true, cx);
 8880    //         cx.spawn(|_, mut cx| async move {
 8881    //             let editor = editor
 8882    //                 .await?
 8883    //                 .downcast::<Editor>()
 8884    //                 .ok_or_else(|| anyhow!("opened item was not an editor"))?
 8885    //                 .downgrade();
 8886    //             editor.update(&mut cx, |editor, cx| {
 8887    //                 let buffer = editor
 8888    //                     .buffer()
 8889    //                     .read(cx)
 8890    //                     .as_singleton()
 8891    //                     .ok_or_else(|| anyhow!("cannot jump in a multi-buffer"))?;
 8892    //                 let buffer = buffer.read(cx);
 8893    //                 let cursor = if buffer.can_resolve(&anchor) {
 8894    //                     language::ToPoint::to_point(&anchor, buffer)
 8895    //                 } else {
 8896    //                     buffer.clip_point(position, Bias::Left)
 8897    //                 };
 8898
 8899    //                 let nav_history = editor.nav_history.take();
 8900    //                 editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
 8901    //                     s.select_ranges([cursor..cursor]);
 8902    //                 });
 8903    //                 editor.nav_history = nav_history;
 8904
 8905    //                 anyhow::Ok(())
 8906    //             })??;
 8907
 8908    //             anyhow::Ok(())
 8909    //         })
 8910    //         .detach_and_log_err(cx);
 8911    //     }
 8912
 8913    fn marked_text_ranges(&self, cx: &AppContext) -> Option<Vec<Range<OffsetUtf16>>> {
 8914        let snapshot = self.buffer.read(cx).read(cx);
 8915        let (_, ranges) = self.text_highlights::<InputComposition>(cx)?;
 8916        Some(
 8917            ranges
 8918                .iter()
 8919                .map(move |range| {
 8920                    range.start.to_offset_utf16(&snapshot)..range.end.to_offset_utf16(&snapshot)
 8921                })
 8922                .collect(),
 8923        )
 8924    }
 8925
 8926    fn selection_replacement_ranges(
 8927        &self,
 8928        range: Range<OffsetUtf16>,
 8929        cx: &AppContext,
 8930    ) -> Vec<Range<OffsetUtf16>> {
 8931        let selections = self.selections.all::<OffsetUtf16>(cx);
 8932        let newest_selection = selections
 8933            .iter()
 8934            .max_by_key(|selection| selection.id)
 8935            .unwrap();
 8936        let start_delta = range.start.0 as isize - newest_selection.start.0 as isize;
 8937        let end_delta = range.end.0 as isize - newest_selection.end.0 as isize;
 8938        let snapshot = self.buffer.read(cx).read(cx);
 8939        selections
 8940            .into_iter()
 8941            .map(|mut selection| {
 8942                selection.start.0 =
 8943                    (selection.start.0 as isize).saturating_add(start_delta) as usize;
 8944                selection.end.0 = (selection.end.0 as isize).saturating_add(end_delta) as usize;
 8945                snapshot.clip_offset_utf16(selection.start, Bias::Left)
 8946                    ..snapshot.clip_offset_utf16(selection.end, Bias::Right)
 8947            })
 8948            .collect()
 8949    }
 8950
 8951    fn report_copilot_event(
 8952        &self,
 8953        suggestion_id: Option<String>,
 8954        suggestion_accepted: bool,
 8955        cx: &AppContext,
 8956    ) {
 8957        let Some(project) = &self.project else { return };
 8958
 8959        // If None, we are either getting suggestions in a new, unsaved file, or in a file without an extension
 8960        let file_extension = self
 8961            .buffer
 8962            .read(cx)
 8963            .as_singleton()
 8964            .and_then(|b| b.read(cx).file())
 8965            .and_then(|file| Path::new(file.file_name(cx)).extension())
 8966            .and_then(|e| e.to_str())
 8967            .map(|a| a.to_string());
 8968
 8969        let telemetry = project.read(cx).client().telemetry().clone();
 8970        let telemetry_settings = *TelemetrySettings::get_global(cx);
 8971
 8972        let event = ClickhouseEvent::Copilot {
 8973            suggestion_id,
 8974            suggestion_accepted,
 8975            file_extension,
 8976        };
 8977        telemetry.report_clickhouse_event(event, telemetry_settings);
 8978    }
 8979
 8980    #[cfg(any(test, feature = "test-support"))]
 8981    fn report_editor_event(
 8982        &self,
 8983        _operation: &'static str,
 8984        _file_extension: Option<String>,
 8985        _cx: &AppContext,
 8986    ) {
 8987    }
 8988
 8989    #[cfg(not(any(test, feature = "test-support")))]
 8990    fn report_editor_event(
 8991        &self,
 8992        operation: &'static str,
 8993        file_extension: Option<String>,
 8994        cx: &AppContext,
 8995    ) {
 8996        let Some(project) = &self.project else { return };
 8997
 8998        // If None, we are in a file without an extension
 8999        let file = self
 9000            .buffer
 9001            .read(cx)
 9002            .as_singleton()
 9003            .and_then(|b| b.read(cx).file());
 9004        let file_extension = file_extension.or(file
 9005            .as_ref()
 9006            .and_then(|file| Path::new(file.file_name(cx)).extension())
 9007            .and_then(|e| e.to_str())
 9008            .map(|a| a.to_string()));
 9009
 9010        let vim_mode = cx
 9011            .global::<SettingsStore>()
 9012            .raw_user_settings()
 9013            .get("vim_mode")
 9014            == Some(&serde_json::Value::Bool(true));
 9015        let telemetry_settings = *TelemetrySettings::get_global(cx);
 9016        let copilot_enabled = all_language_settings(file, cx).copilot_enabled(None, None);
 9017        let copilot_enabled_for_language = self
 9018            .buffer
 9019            .read(cx)
 9020            .settings_at(0, cx)
 9021            .show_copilot_suggestions;
 9022
 9023        let telemetry = project.read(cx).client().telemetry().clone();
 9024        let event = ClickhouseEvent::Editor {
 9025            file_extension,
 9026            vim_mode,
 9027            operation,
 9028            copilot_enabled,
 9029            copilot_enabled_for_language,
 9030        };
 9031        telemetry.report_clickhouse_event(event, telemetry_settings)
 9032    }
 9033
 9034    /// Copy the highlighted chunks to the clipboard as JSON. The format is an array of lines,
 9035    /// with each line being an array of {text, highlight} objects.
 9036    fn copy_highlight_json(&mut self, _: &CopyHighlightJson, cx: &mut ViewContext<Self>) {
 9037        let Some(buffer) = self.buffer.read(cx).as_singleton() else {
 9038            return;
 9039        };
 9040
 9041        #[derive(Serialize)]
 9042        struct Chunk<'a> {
 9043            text: String,
 9044            highlight: Option<&'a str>,
 9045        }
 9046
 9047        let snapshot = buffer.read(cx).snapshot();
 9048        let range = self
 9049            .selected_text_range(cx)
 9050            .and_then(|selected_range| {
 9051                if selected_range.is_empty() {
 9052                    None
 9053                } else {
 9054                    Some(selected_range)
 9055                }
 9056            })
 9057            .unwrap_or_else(|| 0..snapshot.len());
 9058
 9059        let chunks = snapshot.chunks(range, true);
 9060        let mut lines = Vec::new();
 9061        let mut line: VecDeque<Chunk> = VecDeque::new();
 9062
 9063        let Some(style) = self.style.as_ref() else {
 9064            return;
 9065        };
 9066
 9067        for chunk in chunks {
 9068            let highlight = chunk
 9069                .syntax_highlight_id
 9070                .and_then(|id| id.name(&style.syntax));
 9071            let mut chunk_lines = chunk.text.split("\n").peekable();
 9072            while let Some(text) = chunk_lines.next() {
 9073                let mut merged_with_last_token = false;
 9074                if let Some(last_token) = line.back_mut() {
 9075                    if last_token.highlight == highlight {
 9076                        last_token.text.push_str(text);
 9077                        merged_with_last_token = true;
 9078                    }
 9079                }
 9080
 9081                if !merged_with_last_token {
 9082                    line.push_back(Chunk {
 9083                        text: text.into(),
 9084                        highlight,
 9085                    });
 9086                }
 9087
 9088                if chunk_lines.peek().is_some() {
 9089                    if line.len() > 1 && line.front().unwrap().text.is_empty() {
 9090                        line.pop_front();
 9091                    }
 9092                    if line.len() > 1 && line.back().unwrap().text.is_empty() {
 9093                        line.pop_back();
 9094                    }
 9095
 9096                    lines.push(mem::take(&mut line));
 9097                }
 9098            }
 9099        }
 9100
 9101        let Some(lines) = serde_json::to_string_pretty(&lines).log_err() else {
 9102            return;
 9103        };
 9104        cx.write_to_clipboard(ClipboardItem::new(lines));
 9105    }
 9106
 9107    pub fn inlay_hint_cache(&self) -> &InlayHintCache {
 9108        &self.inlay_hint_cache
 9109    }
 9110
 9111    pub fn replay_insert_event(
 9112        &mut self,
 9113        text: &str,
 9114        relative_utf16_range: Option<Range<isize>>,
 9115        cx: &mut ViewContext<Self>,
 9116    ) {
 9117        if !self.input_enabled {
 9118            cx.emit(Event::InputIgnored { text: text.into() });
 9119            return;
 9120        }
 9121        if let Some(relative_utf16_range) = relative_utf16_range {
 9122            let selections = self.selections.all::<OffsetUtf16>(cx);
 9123            self.change_selections(None, cx, |s| {
 9124                let new_ranges = selections.into_iter().map(|range| {
 9125                    let start = OffsetUtf16(
 9126                        range
 9127                            .head()
 9128                            .0
 9129                            .saturating_add_signed(relative_utf16_range.start),
 9130                    );
 9131                    let end = OffsetUtf16(
 9132                        range
 9133                            .head()
 9134                            .0
 9135                            .saturating_add_signed(relative_utf16_range.end),
 9136                    );
 9137                    start..end
 9138                });
 9139                s.select_ranges(new_ranges);
 9140            });
 9141        }
 9142
 9143        self.handle_input(text, cx);
 9144    }
 9145
 9146    pub fn supports_inlay_hints(&self, cx: &AppContext) -> bool {
 9147        let Some(project) = self.project.as_ref() else {
 9148            return false;
 9149        };
 9150        let project = project.read(cx);
 9151
 9152        let mut supports = false;
 9153        self.buffer().read(cx).for_each_buffer(|buffer| {
 9154            if !supports {
 9155                supports = project
 9156                    .language_servers_for_buffer(buffer.read(cx), cx)
 9157                    .any(
 9158                        |(_, server)| match server.capabilities().inlay_hint_provider {
 9159                            Some(lsp::OneOf::Left(enabled)) => enabled,
 9160                            Some(lsp::OneOf::Right(_)) => true,
 9161                            None => false,
 9162                        },
 9163                    )
 9164            }
 9165        });
 9166        supports
 9167    }
 9168
 9169    pub fn focus(&self, cx: &mut WindowContext) {
 9170        cx.focus(&self.focus_handle)
 9171    }
 9172
 9173    fn handle_focus_in(&mut self, cx: &mut ViewContext<Self>) {
 9174        if self.focus_handle.is_focused(cx) {
 9175            // todo!()
 9176            // let focused_event = EditorFocused(cx.handle());
 9177            // cx.emit_global(focused_event);
 9178            cx.emit(Event::Focused);
 9179        }
 9180        if let Some(rename) = self.pending_rename.as_ref() {
 9181            let rename_editor_focus_handle = rename.editor.read(cx).focus_handle.clone();
 9182            cx.focus(&rename_editor_focus_handle);
 9183        } else if self.focus_handle.is_focused(cx) {
 9184            self.blink_manager.update(cx, BlinkManager::enable);
 9185            self.buffer.update(cx, |buffer, cx| {
 9186                buffer.finalize_last_transaction(cx);
 9187                if self.leader_peer_id.is_none() {
 9188                    buffer.set_active_selections(
 9189                        &self.selections.disjoint_anchors(),
 9190                        self.selections.line_mode,
 9191                        self.cursor_shape,
 9192                        cx,
 9193                    );
 9194                }
 9195            });
 9196        }
 9197    }
 9198
 9199    fn handle_focus_out(&mut self, cx: &mut ViewContext<Self>) {
 9200        // todo!()
 9201        // let blurred_event = EditorBlurred(cx.handle());
 9202        // cx.emit_global(blurred_event);
 9203        self.blink_manager.update(cx, BlinkManager::disable);
 9204        self.buffer
 9205            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
 9206        self.hide_context_menu(cx);
 9207        hide_hover(self, cx);
 9208        cx.emit(Event::Blurred);
 9209        cx.notify();
 9210    }
 9211}
 9212
 9213pub trait CollaborationHub {
 9214    fn collaborators<'a>(&self, cx: &'a AppContext) -> &'a HashMap<PeerId, Collaborator>;
 9215    fn user_participant_indices<'a>(
 9216        &self,
 9217        cx: &'a AppContext,
 9218    ) -> &'a HashMap<u64, ParticipantIndex>;
 9219}
 9220
 9221impl CollaborationHub for Model<Project> {
 9222    fn collaborators<'a>(&self, cx: &'a AppContext) -> &'a HashMap<PeerId, Collaborator> {
 9223        self.read(cx).collaborators()
 9224    }
 9225
 9226    fn user_participant_indices<'a>(
 9227        &self,
 9228        cx: &'a AppContext,
 9229    ) -> &'a HashMap<u64, ParticipantIndex> {
 9230        self.read(cx).user_store().read(cx).participant_indices()
 9231    }
 9232}
 9233
 9234fn inlay_hint_settings(
 9235    location: Anchor,
 9236    snapshot: &MultiBufferSnapshot,
 9237    cx: &mut ViewContext<'_, Editor>,
 9238) -> InlayHintSettings {
 9239    let file = snapshot.file_at(location);
 9240    let language = snapshot.language_at(location);
 9241    let settings = all_language_settings(file, cx);
 9242    settings
 9243        .language(language.map(|l| l.name()).as_deref())
 9244        .inlay_hints
 9245}
 9246
 9247fn consume_contiguous_rows(
 9248    contiguous_row_selections: &mut Vec<Selection<Point>>,
 9249    selection: &Selection<Point>,
 9250    display_map: &DisplaySnapshot,
 9251    selections: &mut std::iter::Peekable<std::slice::Iter<Selection<Point>>>,
 9252) -> (u32, u32) {
 9253    contiguous_row_selections.push(selection.clone());
 9254    let start_row = selection.start.row;
 9255    let mut end_row = ending_row(selection, display_map);
 9256
 9257    while let Some(next_selection) = selections.peek() {
 9258        if next_selection.start.row <= end_row {
 9259            end_row = ending_row(next_selection, display_map);
 9260            contiguous_row_selections.push(selections.next().unwrap().clone());
 9261        } else {
 9262            break;
 9263        }
 9264    }
 9265    (start_row, end_row)
 9266}
 9267
 9268fn ending_row(next_selection: &Selection<Point>, display_map: &DisplaySnapshot) -> u32 {
 9269    if next_selection.end.column > 0 || next_selection.is_empty() {
 9270        display_map.next_line_boundary(next_selection.end).0.row + 1
 9271    } else {
 9272        next_selection.end.row
 9273    }
 9274}
 9275
 9276impl EditorSnapshot {
 9277    pub fn remote_selections_in_range<'a>(
 9278        &'a self,
 9279        range: &'a Range<Anchor>,
 9280        collaboration_hub: &dyn CollaborationHub,
 9281        cx: &'a AppContext,
 9282    ) -> impl 'a + Iterator<Item = RemoteSelection> {
 9283        let participant_indices = collaboration_hub.user_participant_indices(cx);
 9284        let collaborators_by_peer_id = collaboration_hub.collaborators(cx);
 9285        let collaborators_by_replica_id = collaborators_by_peer_id
 9286            .iter()
 9287            .map(|(_, collaborator)| (collaborator.replica_id, collaborator))
 9288            .collect::<HashMap<_, _>>();
 9289        self.buffer_snapshot
 9290            .remote_selections_in_range(range)
 9291            .filter_map(move |(replica_id, line_mode, cursor_shape, selection)| {
 9292                let collaborator = collaborators_by_replica_id.get(&replica_id)?;
 9293                let participant_index = participant_indices.get(&collaborator.user_id).copied();
 9294                Some(RemoteSelection {
 9295                    replica_id,
 9296                    selection,
 9297                    cursor_shape,
 9298                    line_mode,
 9299                    participant_index,
 9300                    peer_id: collaborator.peer_id,
 9301                })
 9302            })
 9303    }
 9304
 9305    pub fn language_at<T: ToOffset>(&self, position: T) -> Option<&Arc<Language>> {
 9306        self.display_snapshot.buffer_snapshot.language_at(position)
 9307    }
 9308
 9309    pub fn is_focused(&self) -> bool {
 9310        self.is_focused
 9311    }
 9312
 9313    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
 9314        self.placeholder_text.as_ref()
 9315    }
 9316
 9317    pub fn scroll_position(&self) -> gpui::Point<f32> {
 9318        self.scroll_anchor.scroll_position(&self.display_snapshot)
 9319    }
 9320}
 9321
 9322impl Deref for EditorSnapshot {
 9323    type Target = DisplaySnapshot;
 9324
 9325    fn deref(&self) -> &Self::Target {
 9326        &self.display_snapshot
 9327    }
 9328}
 9329
 9330#[derive(Clone, Debug, PartialEq, Eq)]
 9331pub enum Event {
 9332    InputIgnored {
 9333        text: Arc<str>,
 9334    },
 9335    InputHandled {
 9336        utf16_range_to_replace: Option<Range<isize>>,
 9337        text: Arc<str>,
 9338    },
 9339    ExcerptsAdded {
 9340        buffer: Model<Buffer>,
 9341        predecessor: ExcerptId,
 9342        excerpts: Vec<(ExcerptId, ExcerptRange<language::Anchor>)>,
 9343    },
 9344    ExcerptsRemoved {
 9345        ids: Vec<ExcerptId>,
 9346    },
 9347    BufferEdited,
 9348    Edited,
 9349    Focused,
 9350    Blurred,
 9351    DiffBaseChanged,
 9352    SelectionsChanged {
 9353        local: bool,
 9354    },
 9355    ScrollPositionChanged {
 9356        local: bool,
 9357        autoscroll: bool,
 9358    },
 9359}
 9360
 9361pub struct EditorFocused(pub View<Editor>);
 9362pub struct EditorBlurred(pub View<Editor>);
 9363pub struct EditorReleased(pub WeakView<Editor>);
 9364
 9365// impl Entity for Editor {
 9366//     type Event = Event;
 9367
 9368//     fn release(&mut self, cx: &mut AppContext) {
 9369//         cx.emit_global(EditorReleased(self.handle.clone()));
 9370//     }
 9371// }
 9372//
 9373impl EventEmitter<Event> for Editor {}
 9374
 9375impl Render for Editor {
 9376    type Element = EditorElement;
 9377
 9378    fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
 9379        let settings = ThemeSettings::get_global(cx);
 9380        let text_style = match self.mode {
 9381            EditorMode::SingleLine => {
 9382                TextStyle {
 9383                    color: cx.theme().colors().text,
 9384                    font_family: "Zed Sans".into(), // todo!()
 9385                    font_features: FontFeatures::default(),
 9386                    font_size: rems(1.0).into(),
 9387                    font_weight: FontWeight::NORMAL,
 9388                    font_style: FontStyle::Normal,
 9389                    line_height: relative(1.3).into(), // TODO relative(settings.buffer_line_height.value()),
 9390                    underline: None,
 9391                }
 9392            }
 9393
 9394            EditorMode::AutoHeight { max_lines } => todo!(),
 9395
 9396            EditorMode::Full => TextStyle {
 9397                color: cx.theme().colors().text,
 9398                font_family: settings.buffer_font.family.clone(),
 9399                font_features: settings.buffer_font.features,
 9400                font_size: settings.buffer_font_size.into(),
 9401                font_weight: FontWeight::NORMAL,
 9402                font_style: FontStyle::Normal,
 9403                line_height: relative(settings.buffer_line_height.value()),
 9404                underline: None,
 9405            },
 9406        };
 9407
 9408        let background = match self.mode {
 9409            EditorMode::SingleLine => cx.theme().system().transparent,
 9410            EditorMode::AutoHeight { max_lines } => cx.theme().system().transparent,
 9411            EditorMode::Full => cx.theme().colors().editor_background,
 9412        };
 9413
 9414        EditorElement::new(EditorStyle {
 9415            background,
 9416            local_player: cx.theme().players().local(),
 9417            text: text_style,
 9418            scrollbar_width: px(12.),
 9419            syntax: cx.theme().syntax().clone(),
 9420            diagnostic_style: cx.theme().diagnostic_style(),
 9421        })
 9422    }
 9423}
 9424
 9425// impl View for Editor {
 9426//     fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
 9427//         let style = self.style(cx);
 9428//         let font_changed = self.display_map.update(cx, |map, cx| {
 9429//             map.set_fold_ellipses_color(style.folds.ellipses.text_color);
 9430//             map.set_font_with_size(style.text.font_id, style.text.font_size, cx)
 9431//         });
 9432
 9433//         if font_changed {
 9434//             cx.defer(move |editor, cx: &mut ViewContext<Editor>| {
 9435//                 hide_hover(editor, cx);
 9436//                 hide_link_definition(editor, cx);
 9437//             });
 9438//         }
 9439
 9440//         Stack::new()
 9441//             .with_child(EditorElement::new(style.clone()))
 9442//             .with_child(ChildView::new(&self.mouse_context_menu, cx))
 9443//             .into_any()
 9444//     }
 9445
 9446//     fn ui_name() -> &'static str {
 9447//         "Editor"
 9448//     }
 9449
 9450//     fn focus_in(&mut self, focused: AnyView, cx: &mut ViewContext<Self>) {
 9451//         if cx.is_self_focused() {
 9452//             let focused_event = EditorFocused(cx.handle());
 9453//             cx.emit(Event::Focused);
 9454//             cx.emit_global(focused_event);
 9455//         }
 9456//         if let Some(rename) = self.pending_rename.as_ref() {
 9457//             cx.focus(&rename.editor);
 9458//         } else if cx.is_self_focused() || !focused.is::<Editor>() {
 9459//             if !self.focused {
 9460//                 self.blink_manager.update(cx, BlinkManager::enable);
 9461//             }
 9462//             self.focused = true;
 9463//             self.buffer.update(cx, |buffer, cx| {
 9464//                 buffer.finalize_last_transaction(cx);
 9465//                 if self.leader_peer_id.is_none() {
 9466//                     buffer.set_active_selections(
 9467//                         &self.selections.disjoint_anchors(),
 9468//                         self.selections.line_mode,
 9469//                         self.cursor_shape,
 9470//                         cx,
 9471//                     );
 9472//                 }
 9473//             });
 9474//         }
 9475//     }
 9476
 9477//     fn focus_out(&mut self, _: AnyView, cx: &mut ViewContext<Self>) {
 9478//         let blurred_event = EditorBlurred(cx.handle());
 9479//         cx.emit_global(blurred_event);
 9480//         self.focused = false;
 9481//         self.blink_manager.update(cx, BlinkManager::disable);
 9482//         self.buffer
 9483//             .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
 9484//         self.hide_context_menu(cx);
 9485//         hide_hover(self, cx);
 9486//         cx.emit(Event::Blurred);
 9487//         cx.notify();
 9488//     }
 9489
 9490//     fn modifiers_changed(
 9491//         &mut self,
 9492//         event: &gpui::platform::ModifiersChangedEvent,
 9493//         cx: &mut ViewContext<Self>,
 9494//     ) -> bool {
 9495//         let pending_selection = self.has_pending_selection();
 9496
 9497//         if let Some(point) = &self.link_go_to_definition_state.last_trigger_point {
 9498//             if event.cmd && !pending_selection {
 9499//                 let point = point.clone();
 9500//                 let snapshot = self.snapshot(cx);
 9501//                 let kind = point.definition_kind(event.shift);
 9502
 9503//                 show_link_definition(kind, self, point, snapshot, cx);
 9504//                 return false;
 9505//             }
 9506//         }
 9507
 9508//         {
 9509//             if self.link_go_to_definition_state.symbol_range.is_some()
 9510//                 || !self.link_go_to_definition_state.definitions.is_empty()
 9511//             {
 9512//                 self.link_go_to_definition_state.symbol_range.take();
 9513//                 self.link_go_to_definition_state.definitions.clear();
 9514//                 cx.notify();
 9515//             }
 9516
 9517//             self.link_go_to_definition_state.task = None;
 9518
 9519//             self.clear_highlights::<LinkGoToDefinitionState>(cx);
 9520//         }
 9521
 9522//         false
 9523//     }
 9524
 9525impl InputHandler for Editor {
 9526    fn text_for_range(
 9527        &mut self,
 9528        range_utf16: Range<usize>,
 9529        cx: &mut ViewContext<Self>,
 9530    ) -> Option<String> {
 9531        Some(
 9532            self.buffer
 9533                .read(cx)
 9534                .read(cx)
 9535                .text_for_range(OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end))
 9536                .collect(),
 9537        )
 9538    }
 9539
 9540    fn selected_text_range(&mut self, cx: &mut ViewContext<Self>) -> Option<Range<usize>> {
 9541        // Prevent the IME menu from appearing when holding down an alphabetic key
 9542        // while input is disabled.
 9543        if !self.input_enabled {
 9544            return None;
 9545        }
 9546
 9547        let range = self.selections.newest::<OffsetUtf16>(cx).range();
 9548        Some(range.start.0..range.end.0)
 9549    }
 9550
 9551    fn marked_text_range(&self, cx: &mut ViewContext<Self>) -> Option<Range<usize>> {
 9552        let snapshot = self.buffer.read(cx).read(cx);
 9553        let range = self.text_highlights::<InputComposition>(cx)?.1.get(0)?;
 9554        Some(range.start.to_offset_utf16(&snapshot).0..range.end.to_offset_utf16(&snapshot).0)
 9555    }
 9556
 9557    fn unmark_text(&mut self, cx: &mut ViewContext<Self>) {
 9558        self.clear_highlights::<InputComposition>(cx);
 9559        self.ime_transaction.take();
 9560    }
 9561
 9562    fn replace_text_in_range(
 9563        &mut self,
 9564        range_utf16: Option<Range<usize>>,
 9565        text: &str,
 9566        cx: &mut ViewContext<Self>,
 9567    ) {
 9568        if !self.input_enabled {
 9569            cx.emit(Event::InputIgnored { text: text.into() });
 9570            return;
 9571        }
 9572
 9573        self.transact(cx, |this, cx| {
 9574            let new_selected_ranges = if let Some(range_utf16) = range_utf16 {
 9575                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
 9576                Some(this.selection_replacement_ranges(range_utf16, cx))
 9577            } else {
 9578                this.marked_text_ranges(cx)
 9579            };
 9580
 9581            let range_to_replace = new_selected_ranges.as_ref().and_then(|ranges_to_replace| {
 9582                let newest_selection_id = this.selections.newest_anchor().id;
 9583                this.selections
 9584                    .all::<OffsetUtf16>(cx)
 9585                    .iter()
 9586                    .zip(ranges_to_replace.iter())
 9587                    .find_map(|(selection, range)| {
 9588                        if selection.id == newest_selection_id {
 9589                            Some(
 9590                                (range.start.0 as isize - selection.head().0 as isize)
 9591                                    ..(range.end.0 as isize - selection.head().0 as isize),
 9592                            )
 9593                        } else {
 9594                            None
 9595                        }
 9596                    })
 9597            });
 9598
 9599            cx.emit(Event::InputHandled {
 9600                utf16_range_to_replace: range_to_replace,
 9601                text: text.into(),
 9602            });
 9603
 9604            if let Some(new_selected_ranges) = new_selected_ranges {
 9605                this.change_selections(None, cx, |selections| {
 9606                    selections.select_ranges(new_selected_ranges)
 9607                });
 9608            }
 9609
 9610            this.handle_input(text, cx);
 9611        });
 9612
 9613        if let Some(transaction) = self.ime_transaction {
 9614            self.buffer.update(cx, |buffer, cx| {
 9615                buffer.group_until_transaction(transaction, cx);
 9616            });
 9617        }
 9618
 9619        self.unmark_text(cx);
 9620    }
 9621
 9622    fn replace_and_mark_text_in_range(
 9623        &mut self,
 9624        range_utf16: Option<Range<usize>>,
 9625        text: &str,
 9626        new_selected_range_utf16: Option<Range<usize>>,
 9627        cx: &mut ViewContext<Self>,
 9628    ) {
 9629        if !self.input_enabled {
 9630            cx.emit(Event::InputIgnored { text: text.into() });
 9631            return;
 9632        }
 9633
 9634        let transaction = self.transact(cx, |this, cx| {
 9635            let ranges_to_replace = if let Some(mut marked_ranges) = this.marked_text_ranges(cx) {
 9636                let snapshot = this.buffer.read(cx).read(cx);
 9637                if let Some(relative_range_utf16) = range_utf16.as_ref() {
 9638                    for marked_range in &mut marked_ranges {
 9639                        marked_range.end.0 = marked_range.start.0 + relative_range_utf16.end;
 9640                        marked_range.start.0 += relative_range_utf16.start;
 9641                        marked_range.start =
 9642                            snapshot.clip_offset_utf16(marked_range.start, Bias::Left);
 9643                        marked_range.end =
 9644                            snapshot.clip_offset_utf16(marked_range.end, Bias::Right);
 9645                    }
 9646                }
 9647                Some(marked_ranges)
 9648            } else if let Some(range_utf16) = range_utf16 {
 9649                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
 9650                Some(this.selection_replacement_ranges(range_utf16, cx))
 9651            } else {
 9652                None
 9653            };
 9654
 9655            let range_to_replace = ranges_to_replace.as_ref().and_then(|ranges_to_replace| {
 9656                let newest_selection_id = this.selections.newest_anchor().id;
 9657                this.selections
 9658                    .all::<OffsetUtf16>(cx)
 9659                    .iter()
 9660                    .zip(ranges_to_replace.iter())
 9661                    .find_map(|(selection, range)| {
 9662                        if selection.id == newest_selection_id {
 9663                            Some(
 9664                                (range.start.0 as isize - selection.head().0 as isize)
 9665                                    ..(range.end.0 as isize - selection.head().0 as isize),
 9666                            )
 9667                        } else {
 9668                            None
 9669                        }
 9670                    })
 9671            });
 9672
 9673            cx.emit(Event::InputHandled {
 9674                utf16_range_to_replace: range_to_replace,
 9675                text: text.into(),
 9676            });
 9677
 9678            if let Some(ranges) = ranges_to_replace {
 9679                this.change_selections(None, cx, |s| s.select_ranges(ranges));
 9680            }
 9681
 9682            let marked_ranges = {
 9683                let snapshot = this.buffer.read(cx).read(cx);
 9684                this.selections
 9685                    .disjoint_anchors()
 9686                    .iter()
 9687                    .map(|selection| {
 9688                        selection.start.bias_left(&*snapshot)..selection.end.bias_right(&*snapshot)
 9689                    })
 9690                    .collect::<Vec<_>>()
 9691            };
 9692
 9693            if text.is_empty() {
 9694                this.unmark_text(cx);
 9695            } else {
 9696                this.highlight_text::<InputComposition>(
 9697                    marked_ranges.clone(),
 9698                    HighlightStyle::default(), // todo!() this.style(cx).composition_mark,
 9699                    cx,
 9700                );
 9701            }
 9702
 9703            this.handle_input(text, cx);
 9704
 9705            if let Some(new_selected_range) = new_selected_range_utf16 {
 9706                let snapshot = this.buffer.read(cx).read(cx);
 9707                let new_selected_ranges = marked_ranges
 9708                    .into_iter()
 9709                    .map(|marked_range| {
 9710                        let insertion_start = marked_range.start.to_offset_utf16(&snapshot).0;
 9711                        let new_start = OffsetUtf16(new_selected_range.start + insertion_start);
 9712                        let new_end = OffsetUtf16(new_selected_range.end + insertion_start);
 9713                        snapshot.clip_offset_utf16(new_start, Bias::Left)
 9714                            ..snapshot.clip_offset_utf16(new_end, Bias::Right)
 9715                    })
 9716                    .collect::<Vec<_>>();
 9717
 9718                drop(snapshot);
 9719                this.change_selections(None, cx, |selections| {
 9720                    selections.select_ranges(new_selected_ranges)
 9721                });
 9722            }
 9723        });
 9724
 9725        self.ime_transaction = self.ime_transaction.or(transaction);
 9726        if let Some(transaction) = self.ime_transaction {
 9727            self.buffer.update(cx, |buffer, cx| {
 9728                buffer.group_until_transaction(transaction, cx);
 9729            });
 9730        }
 9731
 9732        if self.text_highlights::<InputComposition>(cx).is_none() {
 9733            self.ime_transaction.take();
 9734        }
 9735    }
 9736
 9737    fn bounds_for_range(
 9738        &mut self,
 9739        range_utf16: Range<usize>,
 9740        element_bounds: gpui::Bounds<Pixels>,
 9741        cx: &mut ViewContext<Self>,
 9742    ) -> Option<gpui::Bounds<Pixels>> {
 9743        let text_layout_details = self.text_layout_details(cx);
 9744        let style = &text_layout_details.editor_style;
 9745        let font_id = cx.text_system().font_id(&style.text.font()).unwrap();
 9746        let font_size = style.text.font_size.to_pixels(cx.rem_size());
 9747        let line_height = style.text.line_height_in_pixels(cx.rem_size());
 9748        let em_width = cx
 9749            .text_system()
 9750            .typographic_bounds(font_id, font_size, 'm')
 9751            .unwrap()
 9752            .size
 9753            .width;
 9754
 9755        let snapshot = self.snapshot(cx);
 9756        let scroll_position = snapshot.scroll_position();
 9757        let scroll_left = scroll_position.x * em_width;
 9758
 9759        let start = OffsetUtf16(range_utf16.start).to_display_point(&snapshot);
 9760        let x = snapshot.x_for_point(start, &text_layout_details) - scroll_left + self.gutter_width;
 9761        let y = line_height * (start.row() as f32 - scroll_position.y);
 9762
 9763        Some(Bounds {
 9764            origin: element_bounds.origin + point(x, y),
 9765            size: size(em_width, line_height),
 9766        })
 9767    }
 9768}
 9769
 9770// fn build_style(
 9771//     settings: &ThemeSettings,
 9772//     get_field_editor_theme: Option<&GetFieldEditorTheme>,
 9773//     override_text_style: Option<&OverrideTextStyle>,
 9774//     cx: &mut AppContext,
 9775// ) -> EditorStyle {
 9776//     let font_cache = cx.font_cache();
 9777//     let line_height_scalar = settings.line_height();
 9778//     let theme_id = settings.theme.meta.id;
 9779//     let mut theme = settings.theme.editor.clone();
 9780//     let mut style = if let Some(get_field_editor_theme) = get_field_editor_theme {
 9781//         let field_editor_theme = get_field_editor_theme(&settings.theme);
 9782//         theme.text_color = field_editor_theme.text.color;
 9783//         theme.selection = field_editor_theme.selection;
 9784//         theme.background = field_editor_theme
 9785//             .container
 9786//             .background_color
 9787//             .unwrap_or_default();
 9788//         EditorStyle {
 9789//             text: field_editor_theme.text,
 9790//             placeholder_text: field_editor_theme.placeholder_text,
 9791//             line_height_scalar,
 9792//             theme,
 9793//             theme_id,
 9794//         }
 9795//     } else {
 9796//         todo!();
 9797//         // let font_family_id = settings.buffer_font_family;
 9798//         // let font_family_name = cx.font_cache().family_name(font_family_id).unwrap();
 9799//         // let font_properties = Default::default();
 9800//         // let font_id = font_cache
 9801//         //     .select_font(font_family_id, &font_properties)
 9802//         //     .unwrap();
 9803//         // let font_size = settings.buffer_font_size(cx);
 9804//         // EditorStyle {
 9805//         //     text: TextStyle {
 9806//         //         color: settings.theme.editor.text_color,
 9807//         //         font_family_name,
 9808//         //         font_family_id,
 9809//         //         font_id,
 9810//         //         font_size,
 9811//         //         font_properties,
 9812//         //         underline: Default::default(),
 9813//         //         soft_wrap: false,
 9814//         //     },
 9815//         //     placeholder_text: None,
 9816//         //     line_height_scalar,
 9817//         //     theme,
 9818//         //     theme_id,
 9819//         // }
 9820//     };
 9821
 9822//     if let Some(highlight_style) = override_text_style.and_then(|build_style| build_style(&style)) {
 9823//         if let Some(highlighted) = style
 9824//             .text
 9825//             .clone()
 9826//             .highlight(highlight_style, font_cache)
 9827//             .log_err()
 9828//         {
 9829//             style.text = highlighted;
 9830//         }
 9831//     }
 9832
 9833//     style
 9834// }
 9835
 9836trait SelectionExt {
 9837    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize>;
 9838    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point>;
 9839    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
 9840    fn spanned_rows(&self, include_end_if_at_line_start: bool, map: &DisplaySnapshot)
 9841        -> Range<u32>;
 9842}
 9843
 9844impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
 9845    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
 9846        let start = self.start.to_point(buffer);
 9847        let end = self.end.to_point(buffer);
 9848        if self.reversed {
 9849            end..start
 9850        } else {
 9851            start..end
 9852        }
 9853    }
 9854
 9855    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
 9856        let start = self.start.to_offset(buffer);
 9857        let end = self.end.to_offset(buffer);
 9858        if self.reversed {
 9859            end..start
 9860        } else {
 9861            start..end
 9862        }
 9863    }
 9864
 9865    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
 9866        let start = self
 9867            .start
 9868            .to_point(&map.buffer_snapshot)
 9869            .to_display_point(map);
 9870        let end = self
 9871            .end
 9872            .to_point(&map.buffer_snapshot)
 9873            .to_display_point(map);
 9874        if self.reversed {
 9875            end..start
 9876        } else {
 9877            start..end
 9878        }
 9879    }
 9880
 9881    fn spanned_rows(
 9882        &self,
 9883        include_end_if_at_line_start: bool,
 9884        map: &DisplaySnapshot,
 9885    ) -> Range<u32> {
 9886        let start = self.start.to_point(&map.buffer_snapshot);
 9887        let mut end = self.end.to_point(&map.buffer_snapshot);
 9888        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
 9889            end.row -= 1;
 9890        }
 9891
 9892        let buffer_start = map.prev_line_boundary(start).0;
 9893        let buffer_end = map.next_line_boundary(end).0;
 9894        buffer_start.row..buffer_end.row + 1
 9895    }
 9896}
 9897
 9898impl<T: InvalidationRegion> InvalidationStack<T> {
 9899    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
 9900    where
 9901        S: Clone + ToOffset,
 9902    {
 9903        while let Some(region) = self.last() {
 9904            let all_selections_inside_invalidation_ranges =
 9905                if selections.len() == region.ranges().len() {
 9906                    selections
 9907                        .iter()
 9908                        .zip(region.ranges().iter().map(|r| r.to_offset(buffer)))
 9909                        .all(|(selection, invalidation_range)| {
 9910                            let head = selection.head().to_offset(buffer);
 9911                            invalidation_range.start <= head && invalidation_range.end >= head
 9912                        })
 9913                } else {
 9914                    false
 9915                };
 9916
 9917            if all_selections_inside_invalidation_ranges {
 9918                break;
 9919            } else {
 9920                self.pop();
 9921            }
 9922        }
 9923    }
 9924}
 9925
 9926impl<T> Default for InvalidationStack<T> {
 9927    fn default() -> Self {
 9928        Self(Default::default())
 9929    }
 9930}
 9931
 9932impl<T> Deref for InvalidationStack<T> {
 9933    type Target = Vec<T>;
 9934
 9935    fn deref(&self) -> &Self::Target {
 9936        &self.0
 9937    }
 9938}
 9939
 9940impl<T> DerefMut for InvalidationStack<T> {
 9941    fn deref_mut(&mut self) -> &mut Self::Target {
 9942        &mut self.0
 9943    }
 9944}
 9945
 9946impl InvalidationRegion for SnippetState {
 9947    fn ranges(&self) -> &[Range<Anchor>] {
 9948        &self.ranges[self.active_index]
 9949    }
 9950}
 9951
 9952// impl Deref for EditorStyle {
 9953//     type Target = theme::Editor;
 9954
 9955//     fn deref(&self) -> &Self::Target {
 9956//         &self.theme
 9957//     }
 9958// }
 9959
 9960pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> RenderBlock {
 9961    let mut highlighted_lines = Vec::new();
 9962
 9963    for (index, line) in diagnostic.message.lines().enumerate() {
 9964        let line = match &diagnostic.source {
 9965            Some(source) if index == 0 => {
 9966                let source_highlight = Vec::from_iter(0..source.len());
 9967                highlight_diagnostic_message(source_highlight, &format!("{source}: {line}"))
 9968            }
 9969
 9970            _ => highlight_diagnostic_message(Vec::new(), line),
 9971        };
 9972        highlighted_lines.push(line);
 9973    }
 9974    let message = diagnostic.message;
 9975    Arc::new(move |cx: &mut BlockContext| {
 9976        todo!()
 9977        // let message = message.clone();
 9978        // let settings = ThemeSettings::get_global(cx);
 9979        // let tooltip_style = settings.theme.tooltip.clone();
 9980        // let theme = &settings.theme.editor;
 9981        // let style = diagnostic_style(diagnostic.severity, is_valid, theme);
 9982        // let font_size = (style.text_scale_factor * settings.buffer_font_size(cx)).round();
 9983        // let anchor_x = cx.anchor_x;
 9984        // enum BlockContextToolip {}
 9985        // MouseEventHandler::new::<BlockContext, _>(cx.block_id, cx, |_, _| {
 9986        //     Flex::column()
 9987        //         .with_children(highlighted_lines.iter().map(|(line, highlights)| {
 9988        //             Label::new(
 9989        //                 line.clone(),
 9990        //                 style.message.clone().with_font_size(font_size),
 9991        //             )
 9992        //             .with_highlights(highlights.clone())
 9993        //             .contained()
 9994        //             .with_margin_left(anchor_x)
 9995        //         }))
 9996        //         .aligned()
 9997        //         .left()
 9998        //         .into_any()
 9999        // })
10000        // .with_cursor_style(CursorStyle::PointingHand)
10001        // .on_click(MouseButton::Left, move |_, _, cx| {
10002        //     cx.write_to_clipboard(ClipboardItem::new(message.clone()));
10003        // })
10004        // // We really need to rethink this ID system...
10005        // .with_tooltip::<BlockContextToolip>(
10006        //     cx.block_id,
10007        //     "Copy diagnostic message",
10008        //     None,
10009        //     tooltip_style,
10010        //     cx,
10011        // )
10012        // .into_any()
10013    })
10014}
10015
10016pub fn highlight_diagnostic_message(
10017    initial_highlights: Vec<usize>,
10018    message: &str,
10019) -> (String, Vec<usize>) {
10020    let mut message_without_backticks = String::new();
10021    let mut prev_offset = 0;
10022    let mut inside_block = false;
10023    let mut highlights = initial_highlights;
10024    for (match_ix, (offset, _)) in message
10025        .match_indices('`')
10026        .chain([(message.len(), "")])
10027        .enumerate()
10028    {
10029        message_without_backticks.push_str(&message[prev_offset..offset]);
10030        if inside_block {
10031            highlights.extend(prev_offset - match_ix..offset - match_ix);
10032        }
10033
10034        inside_block = !inside_block;
10035        prev_offset = offset + 1;
10036    }
10037
10038    (message_without_backticks, highlights)
10039}
10040
10041pub fn diagnostic_style(
10042    severity: DiagnosticSeverity,
10043    valid: bool,
10044    style: &DiagnosticStyle,
10045) -> Hsla {
10046    match (severity, valid) {
10047        (DiagnosticSeverity::ERROR, true) => style.error,
10048        (DiagnosticSeverity::ERROR, false) => style.error,
10049        (DiagnosticSeverity::WARNING, true) => style.warning,
10050        (DiagnosticSeverity::WARNING, false) => style.warning,
10051        (DiagnosticSeverity::INFORMATION, true) => style.info,
10052        (DiagnosticSeverity::INFORMATION, false) => style.info,
10053        (DiagnosticSeverity::HINT, true) => style.info,
10054        (DiagnosticSeverity::HINT, false) => style.info,
10055        _ => style.ignored,
10056    }
10057}
10058
10059// pub fn combine_syntax_and_fuzzy_match_highlights(
10060//     text: &str,
10061//     default_style: HighlightStyle,
10062//     syntax_ranges: impl Iterator<Item = (Range<usize>, HighlightStyle)>,
10063//     match_indices: &[usize],
10064// ) -> Vec<(Range<usize>, HighlightStyle)> {
10065//     let mut result = Vec::new();
10066//     let mut match_indices = match_indices.iter().copied().peekable();
10067
10068//     for (range, mut syntax_highlight) in syntax_ranges.chain([(usize::MAX..0, Default::default())])
10069//     {
10070//         syntax_highlight.weight = None;
10071
10072//         // Add highlights for any fuzzy match characters before the next
10073//         // syntax highlight range.
10074//         while let Some(&match_index) = match_indices.peek() {
10075//             if match_index >= range.start {
10076//                 break;
10077//             }
10078//             match_indices.next();
10079//             let end_index = char_ix_after(match_index, text);
10080//             let mut match_style = default_style;
10081//             match_style.weight = Some(FontWeight::BOLD);
10082//             result.push((match_index..end_index, match_style));
10083//         }
10084
10085//         if range.start == usize::MAX {
10086//             break;
10087//         }
10088
10089//         // Add highlights for any fuzzy match characters within the
10090//         // syntax highlight range.
10091//         let mut offset = range.start;
10092//         while let Some(&match_index) = match_indices.peek() {
10093//             if match_index >= range.end {
10094//                 break;
10095//             }
10096
10097//             match_indices.next();
10098//             if match_index > offset {
10099//                 result.push((offset..match_index, syntax_highlight));
10100//             }
10101
10102//             let mut end_index = char_ix_after(match_index, text);
10103//             while let Some(&next_match_index) = match_indices.peek() {
10104//                 if next_match_index == end_index && next_match_index < range.end {
10105//                     end_index = char_ix_after(next_match_index, text);
10106//                     match_indices.next();
10107//                 } else {
10108//                     break;
10109//                 }
10110//             }
10111
10112//             let mut match_style = syntax_highlight;
10113//             match_style.weight = Some(FontWeight::BOLD);
10114//             result.push((match_index..end_index, match_style));
10115//             offset = end_index;
10116//         }
10117
10118//         if offset < range.end {
10119//             result.push((offset..range.end, syntax_highlight));
10120//         }
10121//     }
10122
10123//     fn char_ix_after(ix: usize, text: &str) -> usize {
10124//         ix + text[ix..].chars().next().unwrap().len_utf8()
10125//     }
10126
10127//     result
10128// }
10129
10130// pub fn styled_runs_for_code_label<'a>(
10131//     label: &'a CodeLabel,
10132//     syntax_theme: &'a theme::SyntaxTheme,
10133// ) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
10134//     let fade_out = HighlightStyle {
10135//         fade_out: Some(0.35),
10136//         ..Default::default()
10137//     };
10138
10139//     let mut prev_end = label.filter_range.end;
10140//     label
10141//         .runs
10142//         .iter()
10143//         .enumerate()
10144//         .flat_map(move |(ix, (range, highlight_id))| {
10145//             let style = if let Some(style) = highlight_id.style(syntax_theme) {
10146//                 style
10147//             } else {
10148//                 return Default::default();
10149//             };
10150//             let mut muted_style = style;
10151//             muted_style.highlight(fade_out);
10152
10153//             let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
10154//             if range.start >= label.filter_range.end {
10155//                 if range.start > prev_end {
10156//                     runs.push((prev_end..range.start, fade_out));
10157//                 }
10158//                 runs.push((range.clone(), muted_style));
10159//             } else if range.end <= label.filter_range.end {
10160//                 runs.push((range.clone(), style));
10161//             } else {
10162//                 runs.push((range.start..label.filter_range.end, style));
10163//                 runs.push((label.filter_range.end..range.end, muted_style));
10164//             }
10165//             prev_end = cmp::max(prev_end, range.end);
10166
10167//             if ix + 1 == label.runs.len() && label.text.len() > prev_end {
10168//                 runs.push((prev_end..label.text.len(), fade_out));
10169//             }
10170
10171//             runs
10172//         })
10173
10174pub fn split_words<'a>(text: &'a str) -> impl std::iter::Iterator<Item = &'a str> + 'a {
10175    let mut index = 0;
10176    let mut codepoints = text.char_indices().peekable();
10177
10178    std::iter::from_fn(move || {
10179        let start_index = index;
10180        while let Some((new_index, codepoint)) = codepoints.next() {
10181            index = new_index + codepoint.len_utf8();
10182            let current_upper = codepoint.is_uppercase();
10183            let next_upper = codepoints
10184                .peek()
10185                .map(|(_, c)| c.is_uppercase())
10186                .unwrap_or(false);
10187
10188            if !current_upper && next_upper {
10189                return Some(&text[start_index..index]);
10190            }
10191        }
10192
10193        index = text.len();
10194        if start_index < text.len() {
10195            return Some(&text[start_index..]);
10196        }
10197        None
10198    })
10199    .flat_map(|word| word.split_inclusive('_'))
10200    .flat_map(|word| word.split_inclusive('-'))
10201}
10202
10203trait RangeToAnchorExt {
10204    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor>;
10205}
10206
10207impl<T: ToOffset> RangeToAnchorExt for Range<T> {
10208    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor> {
10209        snapshot.anchor_after(self.start)..snapshot.anchor_before(self.end)
10210    }
10211}