editor.rs

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