editor.rs

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