editor.rs

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