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;
   14mod persistence;
   15pub mod scroll;
   16pub mod selections_collection;
   17
   18#[cfg(test)]
   19mod editor_tests;
   20#[cfg(any(test, feature = "test-support"))]
   21pub mod test;
   22
   23use ::git::diff::DiffHunk;
   24use aho_corasick::AhoCorasick;
   25use anyhow::{anyhow, Context, Result};
   26use blink_manager::BlinkManager;
   27use client::{ClickhouseEvent, Client, Collaborator, ParticipantIndex, TelemetrySettings};
   28use clock::{Global, ReplicaId};
   29use collections::{BTreeMap, Bound, HashMap, HashSet, VecDeque};
   30use convert_case::{Case, Casing};
   31use copilot::Copilot;
   32pub use display_map::DisplayPoint;
   33use display_map::*;
   34pub use editor_settings::EditorSettings;
   35pub use element::{
   36    Cursor, EditorElement, HighlightedRange, HighlightedRangeLine, LineWithInvisibles,
   37};
   38use futures::FutureExt;
   39use fuzzy::{StringMatch, StringMatchCandidate};
   40use gpui::{
   41    actions,
   42    color::Color,
   43    elements::*,
   44    executor,
   45    fonts::{self, HighlightStyle, TextStyle},
   46    geometry::vector::{vec2f, Vector2F},
   47    impl_actions,
   48    keymap_matcher::KeymapContext,
   49    platform::{CursorStyle, MouseButton},
   50    serde_json, AnyElement, AnyViewHandle, AppContext, AsyncAppContext, ClipboardItem,
   51    CursorRegion, Element, Entity, ModelHandle, MouseRegion, Subscription, Task, View, ViewContext,
   52    ViewHandle, WeakViewHandle, WindowContext,
   53};
   54use highlight_matching_bracket::refresh_matching_bracket_highlights;
   55use hover_popover::{hide_hover, HoverState};
   56use inlay_hint_cache::{InlayHintCache, InlaySplice, InvalidationStrategy};
   57pub use items::MAX_TAB_TITLE_LEN;
   58use itertools::Itertools;
   59pub use language::{char_kind, CharKind};
   60use language::{
   61    language_settings::{self, all_language_settings, InlayHintSettings},
   62    markdown, point_from_lsp, AutoindentMode, BracketPair, Buffer, CodeAction, CodeLabel,
   63    Completion, CursorShape, Diagnostic, DiagnosticSeverity, Documentation, File, IndentKind,
   64    IndentSize, Language, LanguageRegistry, LanguageServerName, OffsetRangeExt, OffsetUtf16, Point,
   65    Selection, SelectionGoal, TransactionId,
   66};
   67use link_go_to_definition::{
   68    hide_link_definition, show_link_definition, GoToDefinitionLink, InlayHighlight,
   69    LinkGoToDefinitionState,
   70};
   71use log::error;
   72use lsp::LanguageServerId;
   73use movement::TextLayoutDetails;
   74use multi_buffer::ToOffsetUtf16;
   75pub use multi_buffer::{
   76    Anchor, AnchorRangeExt, ExcerptId, ExcerptRange, MultiBuffer, MultiBufferSnapshot, ToOffset,
   77    ToPoint,
   78};
   79use ordered_float::OrderedFloat;
   80use parking_lot::RwLock;
   81use project::{FormatTrigger, Location, Project, ProjectPath, ProjectTransaction};
   82use rand::{seq::SliceRandom, thread_rng};
   83use rpc::proto::{self, PeerId};
   84use scroll::{
   85    autoscroll::Autoscroll, OngoingScroll, ScrollAnchor, ScrollManager, ScrollbarAutoHide,
   86};
   87use selections_collection::{resolve_multiple, MutableSelectionsCollection, SelectionsCollection};
   88use serde::{Deserialize, Serialize};
   89use settings::SettingsStore;
   90use smallvec::SmallVec;
   91use snippet::Snippet;
   92use std::{
   93    any::TypeId,
   94    borrow::Cow,
   95    cmp::{self, Ordering, Reverse},
   96    mem,
   97    num::NonZeroU32,
   98    ops::{ControlFlow, Deref, DerefMut, Range, RangeInclusive},
   99    path::Path,
  100    sync::Arc,
  101    time::{Duration, Instant},
  102};
  103pub use sum_tree::Bias;
  104use sum_tree::TreeMap;
  105use text::Rope;
  106use theme::{DiagnosticStyle, Theme, ThemeSettings};
  107use util::{post_inc, RangeExt, ResultExt, TryFutureExt};
  108use workspace::{ItemNavHistory, SplitDirection, ViewId, Workspace};
  109
  110use crate::git::diff_hunk_to_display;
  111
  112const CURSOR_BLINK_INTERVAL: Duration = Duration::from_millis(500);
  113const MAX_LINE_LEN: usize = 1024;
  114const MIN_NAVIGATION_HISTORY_ROW_DELTA: i64 = 10;
  115const MAX_SELECTION_HISTORY_LEN: usize = 1024;
  116const COPILOT_DEBOUNCE_TIMEOUT: Duration = Duration::from_millis(75);
  117pub const CODE_ACTIONS_DEBOUNCE_TIMEOUT: Duration = Duration::from_millis(250);
  118pub const DOCUMENT_HIGHLIGHTS_DEBOUNCE_TIMEOUT: Duration = Duration::from_millis(75);
  119
  120pub const FORMAT_TIMEOUT: Duration = Duration::from_secs(2);
  121
  122pub fn render_parsed_markdown<Tag: 'static>(
  123    parsed: &language::ParsedMarkdown,
  124    editor_style: &EditorStyle,
  125    workspace: Option<WeakViewHandle<Workspace>>,
  126    cx: &mut ViewContext<Editor>,
  127) -> Text {
  128    enum RenderedMarkdown {}
  129
  130    let parsed = parsed.clone();
  131    let view_id = cx.view_id();
  132    let code_span_background_color = editor_style.document_highlight_read_background;
  133
  134    let mut region_id = 0;
  135
  136    Text::new(parsed.text, editor_style.text.clone())
  137        .with_highlights(
  138            parsed
  139                .highlights
  140                .iter()
  141                .filter_map(|(range, highlight)| {
  142                    let highlight = highlight.to_highlight_style(&editor_style.syntax)?;
  143                    Some((range.clone(), highlight))
  144                })
  145                .collect::<Vec<_>>(),
  146        )
  147        .with_custom_runs(parsed.region_ranges, move |ix, bounds, cx| {
  148            region_id += 1;
  149            let region = parsed.regions[ix].clone();
  150
  151            if let Some(link) = region.link {
  152                cx.scene().push_cursor_region(CursorRegion {
  153                    bounds,
  154                    style: CursorStyle::PointingHand,
  155                });
  156                cx.scene().push_mouse_region(
  157                    MouseRegion::new::<(RenderedMarkdown, Tag)>(view_id, region_id, bounds)
  158                        .on_down::<Editor, _>(MouseButton::Left, move |_, _, cx| match &link {
  159                            markdown::Link::Web { url } => cx.platform().open_url(url),
  160                            markdown::Link::Path { path } => {
  161                                if let Some(workspace) = &workspace {
  162                                    _ = workspace.update(cx, |workspace, cx| {
  163                                        workspace.open_abs_path(path.clone(), false, cx).detach();
  164                                    });
  165                                }
  166                            }
  167                        }),
  168                );
  169            }
  170
  171            if region.code {
  172                cx.scene().push_quad(gpui::Quad {
  173                    bounds,
  174                    background: Some(code_span_background_color),
  175                    border: Default::default(),
  176                    corner_radii: (2.0).into(),
  177                });
  178            }
  179        })
  180        .with_soft_wrap(true)
  181}
  182
  183#[derive(Clone, Deserialize, PartialEq, Default)]
  184pub struct SelectNext {
  185    #[serde(default)]
  186    pub replace_newest: bool,
  187}
  188
  189#[derive(Clone, Deserialize, PartialEq, Default)]
  190pub struct SelectPrevious {
  191    #[serde(default)]
  192    pub replace_newest: bool,
  193}
  194
  195#[derive(Clone, Deserialize, PartialEq, Default)]
  196pub struct SelectAllMatches {
  197    #[serde(default)]
  198    pub replace_newest: bool,
  199}
  200
  201#[derive(Clone, Deserialize, PartialEq)]
  202pub struct SelectToBeginningOfLine {
  203    #[serde(default)]
  204    stop_at_soft_wraps: bool,
  205}
  206
  207#[derive(Clone, Default, Deserialize, PartialEq)]
  208pub struct MovePageUp {
  209    #[serde(default)]
  210    center_cursor: bool,
  211}
  212
  213#[derive(Clone, Default, Deserialize, PartialEq)]
  214pub struct MovePageDown {
  215    #[serde(default)]
  216    center_cursor: bool,
  217}
  218
  219#[derive(Clone, Deserialize, PartialEq)]
  220pub struct SelectToEndOfLine {
  221    #[serde(default)]
  222    stop_at_soft_wraps: bool,
  223}
  224
  225#[derive(Clone, Deserialize, PartialEq)]
  226pub struct ToggleCodeActions {
  227    #[serde(default)]
  228    pub deployed_from_indicator: bool,
  229}
  230
  231#[derive(Clone, Default, Deserialize, PartialEq)]
  232pub struct ConfirmCompletion {
  233    #[serde(default)]
  234    pub item_ix: Option<usize>,
  235}
  236
  237#[derive(Clone, Default, Deserialize, PartialEq)]
  238pub struct ConfirmCodeAction {
  239    #[serde(default)]
  240    pub item_ix: Option<usize>,
  241}
  242
  243#[derive(Clone, Default, Deserialize, PartialEq)]
  244pub struct ToggleComments {
  245    #[serde(default)]
  246    pub advance_downwards: bool,
  247}
  248
  249#[derive(Clone, Default, Deserialize, PartialEq)]
  250pub struct FoldAt {
  251    pub buffer_row: u32,
  252}
  253
  254#[derive(Clone, Default, Deserialize, PartialEq)]
  255pub struct UnfoldAt {
  256    pub buffer_row: u32,
  257}
  258
  259#[derive(Clone, Default, Deserialize, PartialEq)]
  260pub struct GutterHover {
  261    pub hovered: bool,
  262}
  263
  264#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
  265pub enum InlayId {
  266    Suggestion(usize),
  267    Hint(usize),
  268}
  269
  270impl InlayId {
  271    fn id(&self) -> usize {
  272        match self {
  273            Self::Suggestion(id) => *id,
  274            Self::Hint(id) => *id,
  275        }
  276    }
  277}
  278
  279actions!(
  280    editor,
  281    [
  282        Cancel,
  283        Backspace,
  284        Delete,
  285        Newline,
  286        NewlineAbove,
  287        NewlineBelow,
  288        GoToDiagnostic,
  289        GoToPrevDiagnostic,
  290        GoToHunk,
  291        GoToPrevHunk,
  292        Indent,
  293        Outdent,
  294        DeleteLine,
  295        DeleteToPreviousWordStart,
  296        DeleteToPreviousSubwordStart,
  297        DeleteToNextWordEnd,
  298        DeleteToNextSubwordEnd,
  299        DeleteToBeginningOfLine,
  300        DeleteToEndOfLine,
  301        CutToEndOfLine,
  302        DuplicateLine,
  303        MoveLineUp,
  304        MoveLineDown,
  305        JoinLines,
  306        SortLinesCaseSensitive,
  307        SortLinesCaseInsensitive,
  308        ReverseLines,
  309        ShuffleLines,
  310        ConvertToUpperCase,
  311        ConvertToLowerCase,
  312        ConvertToTitleCase,
  313        ConvertToSnakeCase,
  314        ConvertToKebabCase,
  315        ConvertToUpperCamelCase,
  316        ConvertToLowerCamelCase,
  317        Transpose,
  318        Cut,
  319        Copy,
  320        Paste,
  321        Undo,
  322        Redo,
  323        MoveUp,
  324        PageUp,
  325        MoveDown,
  326        PageDown,
  327        MoveLeft,
  328        MoveRight,
  329        MoveToPreviousWordStart,
  330        MoveToPreviousSubwordStart,
  331        MoveToNextWordEnd,
  332        MoveToNextSubwordEnd,
  333        MoveToBeginningOfLine,
  334        MoveToEndOfLine,
  335        MoveToStartOfParagraph,
  336        MoveToEndOfParagraph,
  337        MoveToBeginning,
  338        MoveToEnd,
  339        SelectUp,
  340        SelectDown,
  341        SelectLeft,
  342        SelectRight,
  343        SelectToPreviousWordStart,
  344        SelectToPreviousSubwordStart,
  345        SelectToNextWordEnd,
  346        SelectToNextSubwordEnd,
  347        SelectToStartOfParagraph,
  348        SelectToEndOfParagraph,
  349        SelectToBeginning,
  350        SelectToEnd,
  351        SelectAll,
  352        SelectLine,
  353        SplitSelectionIntoLines,
  354        AddSelectionAbove,
  355        AddSelectionBelow,
  356        Tab,
  357        TabPrev,
  358        ShowCharacterPalette,
  359        SelectLargerSyntaxNode,
  360        SelectSmallerSyntaxNode,
  361        GoToDefinition,
  362        GoToDefinitionSplit,
  363        GoToTypeDefinition,
  364        GoToTypeDefinitionSplit,
  365        MoveToEnclosingBracket,
  366        UndoSelection,
  367        RedoSelection,
  368        FindAllReferences,
  369        Rename,
  370        ConfirmRename,
  371        Fold,
  372        UnfoldLines,
  373        FoldSelectedRanges,
  374        ShowCompletions,
  375        OpenExcerpts,
  376        RestartLanguageServer,
  377        Hover,
  378        Format,
  379        ToggleSoftWrap,
  380        ToggleInlayHints,
  381        RevealInFinder,
  382        CopyPath,
  383        CopyRelativePath,
  384        CopyHighlightJson,
  385        ContextMenuFirst,
  386        ContextMenuPrev,
  387        ContextMenuNext,
  388        ContextMenuLast,
  389    ]
  390);
  391
  392impl_actions!(
  393    editor,
  394    [
  395        SelectNext,
  396        SelectPrevious,
  397        SelectAllMatches,
  398        SelectToBeginningOfLine,
  399        SelectToEndOfLine,
  400        ToggleCodeActions,
  401        MovePageUp,
  402        MovePageDown,
  403        ConfirmCompletion,
  404        ConfirmCodeAction,
  405        ToggleComments,
  406        FoldAt,
  407        UnfoldAt,
  408        GutterHover
  409    ]
  410);
  411
  412enum DocumentHighlightRead {}
  413enum DocumentHighlightWrite {}
  414enum InputComposition {}
  415
  416#[derive(Copy, Clone, PartialEq, Eq)]
  417pub enum Direction {
  418    Prev,
  419    Next,
  420}
  421
  422pub fn init_settings(cx: &mut AppContext) {
  423    settings::register::<EditorSettings>(cx);
  424}
  425
  426pub fn init(cx: &mut AppContext) {
  427    init_settings(cx);
  428    cx.add_action(Editor::new_file);
  429    cx.add_action(Editor::new_file_in_direction);
  430    cx.add_action(Editor::cancel);
  431    cx.add_action(Editor::newline);
  432    cx.add_action(Editor::newline_above);
  433    cx.add_action(Editor::newline_below);
  434    cx.add_action(Editor::backspace);
  435    cx.add_action(Editor::delete);
  436    cx.add_action(Editor::tab);
  437    cx.add_action(Editor::tab_prev);
  438    cx.add_action(Editor::indent);
  439    cx.add_action(Editor::outdent);
  440    cx.add_action(Editor::delete_line);
  441    cx.add_action(Editor::join_lines);
  442    cx.add_action(Editor::sort_lines_case_sensitive);
  443    cx.add_action(Editor::sort_lines_case_insensitive);
  444    cx.add_action(Editor::reverse_lines);
  445    cx.add_action(Editor::shuffle_lines);
  446    cx.add_action(Editor::convert_to_upper_case);
  447    cx.add_action(Editor::convert_to_lower_case);
  448    cx.add_action(Editor::convert_to_title_case);
  449    cx.add_action(Editor::convert_to_snake_case);
  450    cx.add_action(Editor::convert_to_kebab_case);
  451    cx.add_action(Editor::convert_to_upper_camel_case);
  452    cx.add_action(Editor::convert_to_lower_camel_case);
  453    cx.add_action(Editor::delete_to_previous_word_start);
  454    cx.add_action(Editor::delete_to_previous_subword_start);
  455    cx.add_action(Editor::delete_to_next_word_end);
  456    cx.add_action(Editor::delete_to_next_subword_end);
  457    cx.add_action(Editor::delete_to_beginning_of_line);
  458    cx.add_action(Editor::delete_to_end_of_line);
  459    cx.add_action(Editor::cut_to_end_of_line);
  460    cx.add_action(Editor::duplicate_line);
  461    cx.add_action(Editor::move_line_up);
  462    cx.add_action(Editor::move_line_down);
  463    cx.add_action(Editor::transpose);
  464    cx.add_action(Editor::cut);
  465    cx.add_action(Editor::copy);
  466    cx.add_action(Editor::paste);
  467    cx.add_action(Editor::undo);
  468    cx.add_action(Editor::redo);
  469    cx.add_action(Editor::move_up);
  470    cx.add_action(Editor::move_page_up);
  471    cx.add_action(Editor::move_down);
  472    cx.add_action(Editor::move_page_down);
  473    cx.add_action(Editor::next_screen);
  474    cx.add_action(Editor::move_left);
  475    cx.add_action(Editor::move_right);
  476    cx.add_action(Editor::move_to_previous_word_start);
  477    cx.add_action(Editor::move_to_previous_subword_start);
  478    cx.add_action(Editor::move_to_next_word_end);
  479    cx.add_action(Editor::move_to_next_subword_end);
  480    cx.add_action(Editor::move_to_beginning_of_line);
  481    cx.add_action(Editor::move_to_end_of_line);
  482    cx.add_action(Editor::move_to_start_of_paragraph);
  483    cx.add_action(Editor::move_to_end_of_paragraph);
  484    cx.add_action(Editor::move_to_beginning);
  485    cx.add_action(Editor::move_to_end);
  486    cx.add_action(Editor::select_up);
  487    cx.add_action(Editor::select_down);
  488    cx.add_action(Editor::select_left);
  489    cx.add_action(Editor::select_right);
  490    cx.add_action(Editor::select_to_previous_word_start);
  491    cx.add_action(Editor::select_to_previous_subword_start);
  492    cx.add_action(Editor::select_to_next_word_end);
  493    cx.add_action(Editor::select_to_next_subword_end);
  494    cx.add_action(Editor::select_to_beginning_of_line);
  495    cx.add_action(Editor::select_to_end_of_line);
  496    cx.add_action(Editor::select_to_start_of_paragraph);
  497    cx.add_action(Editor::select_to_end_of_paragraph);
  498    cx.add_action(Editor::select_to_beginning);
  499    cx.add_action(Editor::select_to_end);
  500    cx.add_action(Editor::select_all);
  501    cx.add_action(Editor::select_all_matches);
  502    cx.add_action(Editor::select_line);
  503    cx.add_action(Editor::split_selection_into_lines);
  504    cx.add_action(Editor::add_selection_above);
  505    cx.add_action(Editor::add_selection_below);
  506    cx.add_action(Editor::select_next);
  507    cx.add_action(Editor::select_previous);
  508    cx.add_action(Editor::toggle_comments);
  509    cx.add_action(Editor::select_larger_syntax_node);
  510    cx.add_action(Editor::select_smaller_syntax_node);
  511    cx.add_action(Editor::move_to_enclosing_bracket);
  512    cx.add_action(Editor::undo_selection);
  513    cx.add_action(Editor::redo_selection);
  514    cx.add_action(Editor::go_to_diagnostic);
  515    cx.add_action(Editor::go_to_prev_diagnostic);
  516    cx.add_action(Editor::go_to_hunk);
  517    cx.add_action(Editor::go_to_prev_hunk);
  518    cx.add_action(Editor::go_to_definition);
  519    cx.add_action(Editor::go_to_definition_split);
  520    cx.add_action(Editor::go_to_type_definition);
  521    cx.add_action(Editor::go_to_type_definition_split);
  522    cx.add_action(Editor::fold);
  523    cx.add_action(Editor::fold_at);
  524    cx.add_action(Editor::unfold_lines);
  525    cx.add_action(Editor::unfold_at);
  526    cx.add_action(Editor::gutter_hover);
  527    cx.add_action(Editor::fold_selected_ranges);
  528    cx.add_action(Editor::show_completions);
  529    cx.add_action(Editor::toggle_code_actions);
  530    cx.add_action(Editor::open_excerpts);
  531    cx.add_action(Editor::toggle_soft_wrap);
  532    cx.add_action(Editor::toggle_inlay_hints);
  533    cx.add_action(Editor::reveal_in_finder);
  534    cx.add_action(Editor::copy_path);
  535    cx.add_action(Editor::copy_relative_path);
  536    cx.add_action(Editor::copy_highlight_json);
  537    cx.add_async_action(Editor::format);
  538    cx.add_action(Editor::restart_language_server);
  539    cx.add_action(Editor::show_character_palette);
  540    cx.add_async_action(Editor::confirm_completion);
  541    cx.add_async_action(Editor::confirm_code_action);
  542    cx.add_async_action(Editor::rename);
  543    cx.add_async_action(Editor::confirm_rename);
  544    cx.add_async_action(Editor::find_all_references);
  545    cx.add_action(Editor::next_copilot_suggestion);
  546    cx.add_action(Editor::previous_copilot_suggestion);
  547    cx.add_action(Editor::copilot_suggest);
  548    cx.add_action(Editor::context_menu_first);
  549    cx.add_action(Editor::context_menu_prev);
  550    cx.add_action(Editor::context_menu_next);
  551    cx.add_action(Editor::context_menu_last);
  552
  553    hover_popover::init(cx);
  554    scroll::actions::init(cx);
  555
  556    workspace::register_project_item::<Editor>(cx);
  557    workspace::register_followable_item::<Editor>(cx);
  558    workspace::register_deserializable_item::<Editor>(cx);
  559}
  560
  561trait InvalidationRegion {
  562    fn ranges(&self) -> &[Range<Anchor>];
  563}
  564
  565#[derive(Clone, Debug, PartialEq)]
  566pub enum SelectPhase {
  567    Begin {
  568        position: DisplayPoint,
  569        add: bool,
  570        click_count: usize,
  571    },
  572    BeginColumnar {
  573        position: DisplayPoint,
  574        goal_column: u32,
  575    },
  576    Extend {
  577        position: DisplayPoint,
  578        click_count: usize,
  579    },
  580    Update {
  581        position: DisplayPoint,
  582        goal_column: u32,
  583        scroll_position: Vector2F,
  584    },
  585    End,
  586}
  587
  588#[derive(Clone, Debug)]
  589pub enum SelectMode {
  590    Character,
  591    Word(Range<Anchor>),
  592    Line(Range<Anchor>),
  593    All,
  594}
  595
  596#[derive(Copy, Clone, PartialEq, Eq, Debug)]
  597pub enum EditorMode {
  598    SingleLine,
  599    AutoHeight { max_lines: usize },
  600    Full,
  601}
  602
  603#[derive(Clone, Debug)]
  604pub enum SoftWrap {
  605    None,
  606    EditorWidth,
  607    Column(u32),
  608}
  609
  610#[derive(Clone)]
  611pub struct EditorStyle {
  612    pub text: TextStyle,
  613    pub line_height_scalar: f32,
  614    pub placeholder_text: Option<TextStyle>,
  615    pub theme: theme::Editor,
  616    pub theme_id: usize,
  617}
  618
  619type CompletionId = usize;
  620
  621type GetFieldEditorTheme = dyn Fn(&theme::Theme) -> theme::FieldEditor;
  622type OverrideTextStyle = dyn Fn(&EditorStyle) -> Option<HighlightStyle>;
  623
  624type BackgroundHighlight = (fn(&Theme) -> Color, Vec<Range<Anchor>>);
  625type InlayBackgroundHighlight = (fn(&Theme) -> Color, Vec<InlayHighlight>);
  626
  627pub struct Editor {
  628    handle: WeakViewHandle<Self>,
  629    buffer: ModelHandle<MultiBuffer>,
  630    display_map: ModelHandle<DisplayMap>,
  631    pub selections: SelectionsCollection,
  632    pub scroll_manager: ScrollManager,
  633    columnar_selection_tail: Option<Anchor>,
  634    add_selections_state: Option<AddSelectionsState>,
  635    select_next_state: Option<SelectNextState>,
  636    select_prev_state: Option<SelectNextState>,
  637    selection_history: SelectionHistory,
  638    autoclose_regions: Vec<AutocloseRegion>,
  639    snippet_stack: InvalidationStack<SnippetState>,
  640    select_larger_syntax_node_stack: Vec<Box<[Selection<usize>]>>,
  641    ime_transaction: Option<TransactionId>,
  642    active_diagnostics: Option<ActiveDiagnosticGroup>,
  643    soft_wrap_mode_override: Option<language_settings::SoftWrap>,
  644    get_field_editor_theme: Option<Arc<GetFieldEditorTheme>>,
  645    override_text_style: Option<Box<OverrideTextStyle>>,
  646    project: Option<ModelHandle<Project>>,
  647    collaboration_hub: Option<Box<dyn CollaborationHub>>,
  648    focused: bool,
  649    blink_manager: ModelHandle<BlinkManager>,
  650    pub show_local_selections: bool,
  651    mode: EditorMode,
  652    show_gutter: bool,
  653    show_wrap_guides: Option<bool>,
  654    placeholder_text: Option<Arc<str>>,
  655    highlighted_rows: Option<Range<u32>>,
  656    background_highlights: BTreeMap<TypeId, BackgroundHighlight>,
  657    inlay_background_highlights: TreeMap<Option<TypeId>, InlayBackgroundHighlight>,
  658    nav_history: Option<ItemNavHistory>,
  659    context_menu: RwLock<Option<ContextMenu>>,
  660    mouse_context_menu: ViewHandle<context_menu::ContextMenu>,
  661    completion_tasks: Vec<(CompletionId, Task<Option<()>>)>,
  662    next_completion_id: CompletionId,
  663    available_code_actions: Option<(ModelHandle<Buffer>, Arc<[CodeAction]>)>,
  664    code_actions_task: Option<Task<()>>,
  665    document_highlights_task: Option<Task<()>>,
  666    pending_rename: Option<RenameState>,
  667    searchable: bool,
  668    cursor_shape: CursorShape,
  669    collapse_matches: bool,
  670    autoindent_mode: Option<AutoindentMode>,
  671    workspace: Option<(WeakViewHandle<Workspace>, i64)>,
  672    keymap_context_layers: BTreeMap<TypeId, KeymapContext>,
  673    input_enabled: bool,
  674    read_only: bool,
  675    leader_peer_id: Option<PeerId>,
  676    remote_id: Option<ViewId>,
  677    hover_state: HoverState,
  678    gutter_hovered: bool,
  679    link_go_to_definition_state: LinkGoToDefinitionState,
  680    copilot_state: CopilotState,
  681    inlay_hint_cache: InlayHintCache,
  682    next_inlay_id: usize,
  683    _subscriptions: Vec<Subscription>,
  684    pixel_position_of_newest_cursor: Option<Vector2F>,
  685}
  686
  687pub struct EditorSnapshot {
  688    pub mode: EditorMode,
  689    pub show_gutter: bool,
  690    pub display_snapshot: DisplaySnapshot,
  691    pub placeholder_text: Option<Arc<str>>,
  692    is_focused: bool,
  693    scroll_anchor: ScrollAnchor,
  694    ongoing_scroll: OngoingScroll,
  695}
  696
  697pub struct RemoteSelection {
  698    pub replica_id: ReplicaId,
  699    pub selection: Selection<Anchor>,
  700    pub cursor_shape: CursorShape,
  701    pub peer_id: PeerId,
  702    pub line_mode: bool,
  703    pub participant_index: Option<ParticipantIndex>,
  704}
  705
  706#[derive(Clone, Debug)]
  707struct SelectionHistoryEntry {
  708    selections: Arc<[Selection<Anchor>]>,
  709    select_next_state: Option<SelectNextState>,
  710    select_prev_state: Option<SelectNextState>,
  711    add_selections_state: Option<AddSelectionsState>,
  712}
  713
  714enum SelectionHistoryMode {
  715    Normal,
  716    Undoing,
  717    Redoing,
  718}
  719
  720impl Default for SelectionHistoryMode {
  721    fn default() -> Self {
  722        Self::Normal
  723    }
  724}
  725
  726#[derive(Default)]
  727struct SelectionHistory {
  728    #[allow(clippy::type_complexity)]
  729    selections_by_transaction:
  730        HashMap<TransactionId, (Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)>,
  731    mode: SelectionHistoryMode,
  732    undo_stack: VecDeque<SelectionHistoryEntry>,
  733    redo_stack: VecDeque<SelectionHistoryEntry>,
  734}
  735
  736impl SelectionHistory {
  737    fn insert_transaction(
  738        &mut self,
  739        transaction_id: TransactionId,
  740        selections: Arc<[Selection<Anchor>]>,
  741    ) {
  742        self.selections_by_transaction
  743            .insert(transaction_id, (selections, None));
  744    }
  745
  746    #[allow(clippy::type_complexity)]
  747    fn transaction(
  748        &self,
  749        transaction_id: TransactionId,
  750    ) -> Option<&(Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)> {
  751        self.selections_by_transaction.get(&transaction_id)
  752    }
  753
  754    #[allow(clippy::type_complexity)]
  755    fn transaction_mut(
  756        &mut self,
  757        transaction_id: TransactionId,
  758    ) -> Option<&mut (Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)> {
  759        self.selections_by_transaction.get_mut(&transaction_id)
  760    }
  761
  762    fn push(&mut self, entry: SelectionHistoryEntry) {
  763        if !entry.selections.is_empty() {
  764            match self.mode {
  765                SelectionHistoryMode::Normal => {
  766                    self.push_undo(entry);
  767                    self.redo_stack.clear();
  768                }
  769                SelectionHistoryMode::Undoing => self.push_redo(entry),
  770                SelectionHistoryMode::Redoing => self.push_undo(entry),
  771            }
  772        }
  773    }
  774
  775    fn push_undo(&mut self, entry: SelectionHistoryEntry) {
  776        if self
  777            .undo_stack
  778            .back()
  779            .map_or(true, |e| e.selections != entry.selections)
  780        {
  781            self.undo_stack.push_back(entry);
  782            if self.undo_stack.len() > MAX_SELECTION_HISTORY_LEN {
  783                self.undo_stack.pop_front();
  784            }
  785        }
  786    }
  787
  788    fn push_redo(&mut self, entry: SelectionHistoryEntry) {
  789        if self
  790            .redo_stack
  791            .back()
  792            .map_or(true, |e| e.selections != entry.selections)
  793        {
  794            self.redo_stack.push_back(entry);
  795            if self.redo_stack.len() > MAX_SELECTION_HISTORY_LEN {
  796                self.redo_stack.pop_front();
  797            }
  798        }
  799    }
  800}
  801
  802#[derive(Clone, Debug)]
  803struct AddSelectionsState {
  804    above: bool,
  805    stack: Vec<usize>,
  806}
  807
  808#[derive(Clone)]
  809struct SelectNextState {
  810    query: AhoCorasick,
  811    wordwise: bool,
  812    done: bool,
  813}
  814
  815impl std::fmt::Debug for SelectNextState {
  816    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  817        f.debug_struct(std::any::type_name::<Self>())
  818            .field("wordwise", &self.wordwise)
  819            .field("done", &self.done)
  820            .finish()
  821    }
  822}
  823
  824#[derive(Debug)]
  825struct AutocloseRegion {
  826    selection_id: usize,
  827    range: Range<Anchor>,
  828    pair: BracketPair,
  829}
  830
  831#[derive(Debug)]
  832struct SnippetState {
  833    ranges: Vec<Vec<Range<Anchor>>>,
  834    active_index: usize,
  835}
  836
  837pub struct RenameState {
  838    pub range: Range<Anchor>,
  839    pub old_name: Arc<str>,
  840    pub editor: ViewHandle<Editor>,
  841    block_id: BlockId,
  842}
  843
  844struct InvalidationStack<T>(Vec<T>);
  845
  846enum ContextMenu {
  847    Completions(CompletionsMenu),
  848    CodeActions(CodeActionsMenu),
  849}
  850
  851impl ContextMenu {
  852    fn select_first(
  853        &mut self,
  854        project: Option<&ModelHandle<Project>>,
  855        cx: &mut ViewContext<Editor>,
  856    ) -> bool {
  857        if self.visible() {
  858            match self {
  859                ContextMenu::Completions(menu) => menu.select_first(project, cx),
  860                ContextMenu::CodeActions(menu) => menu.select_first(cx),
  861            }
  862            true
  863        } else {
  864            false
  865        }
  866    }
  867
  868    fn select_prev(
  869        &mut self,
  870        project: Option<&ModelHandle<Project>>,
  871        cx: &mut ViewContext<Editor>,
  872    ) -> bool {
  873        if self.visible() {
  874            match self {
  875                ContextMenu::Completions(menu) => menu.select_prev(project, cx),
  876                ContextMenu::CodeActions(menu) => menu.select_prev(cx),
  877            }
  878            true
  879        } else {
  880            false
  881        }
  882    }
  883
  884    fn select_next(
  885        &mut self,
  886        project: Option<&ModelHandle<Project>>,
  887        cx: &mut ViewContext<Editor>,
  888    ) -> bool {
  889        if self.visible() {
  890            match self {
  891                ContextMenu::Completions(menu) => menu.select_next(project, cx),
  892                ContextMenu::CodeActions(menu) => menu.select_next(cx),
  893            }
  894            true
  895        } else {
  896            false
  897        }
  898    }
  899
  900    fn select_last(
  901        &mut self,
  902        project: Option<&ModelHandle<Project>>,
  903        cx: &mut ViewContext<Editor>,
  904    ) -> bool {
  905        if self.visible() {
  906            match self {
  907                ContextMenu::Completions(menu) => menu.select_last(project, cx),
  908                ContextMenu::CodeActions(menu) => menu.select_last(cx),
  909            }
  910            true
  911        } else {
  912            false
  913        }
  914    }
  915
  916    fn visible(&self) -> bool {
  917        match self {
  918            ContextMenu::Completions(menu) => menu.visible(),
  919            ContextMenu::CodeActions(menu) => menu.visible(),
  920        }
  921    }
  922
  923    fn render(
  924        &self,
  925        cursor_position: DisplayPoint,
  926        style: EditorStyle,
  927        workspace: Option<WeakViewHandle<Workspace>>,
  928        cx: &mut ViewContext<Editor>,
  929    ) -> (DisplayPoint, AnyElement<Editor>) {
  930        match self {
  931            ContextMenu::Completions(menu) => (cursor_position, menu.render(style, workspace, cx)),
  932            ContextMenu::CodeActions(menu) => menu.render(cursor_position, style, cx),
  933        }
  934    }
  935}
  936
  937#[derive(Clone)]
  938struct CompletionsMenu {
  939    id: CompletionId,
  940    initial_position: Anchor,
  941    buffer: ModelHandle<Buffer>,
  942    completions: Arc<RwLock<Box<[Completion]>>>,
  943    match_candidates: Arc<[StringMatchCandidate]>,
  944    matches: Arc<[StringMatch]>,
  945    selected_item: usize,
  946    list: UniformListState,
  947}
  948
  949impl CompletionsMenu {
  950    fn select_first(
  951        &mut self,
  952        project: Option<&ModelHandle<Project>>,
  953        cx: &mut ViewContext<Editor>,
  954    ) {
  955        self.selected_item = 0;
  956        self.list.scroll_to(ScrollTarget::Show(self.selected_item));
  957        self.attempt_resolve_selected_completion_documentation(project, cx);
  958        cx.notify();
  959    }
  960
  961    fn select_prev(
  962        &mut self,
  963        project: Option<&ModelHandle<Project>>,
  964        cx: &mut ViewContext<Editor>,
  965    ) {
  966        if self.selected_item > 0 {
  967            self.selected_item -= 1;
  968        } else {
  969            self.selected_item = self.matches.len() - 1;
  970        }
  971        self.list.scroll_to(ScrollTarget::Show(self.selected_item));
  972        self.attempt_resolve_selected_completion_documentation(project, cx);
  973        cx.notify();
  974    }
  975
  976    fn select_next(
  977        &mut self,
  978        project: Option<&ModelHandle<Project>>,
  979        cx: &mut ViewContext<Editor>,
  980    ) {
  981        if self.selected_item + 1 < self.matches.len() {
  982            self.selected_item += 1;
  983        } else {
  984            self.selected_item = 0;
  985        }
  986        self.list.scroll_to(ScrollTarget::Show(self.selected_item));
  987        self.attempt_resolve_selected_completion_documentation(project, cx);
  988        cx.notify();
  989    }
  990
  991    fn select_last(
  992        &mut self,
  993        project: Option<&ModelHandle<Project>>,
  994        cx: &mut ViewContext<Editor>,
  995    ) {
  996        self.selected_item = self.matches.len() - 1;
  997        self.list.scroll_to(ScrollTarget::Show(self.selected_item));
  998        self.attempt_resolve_selected_completion_documentation(project, cx);
  999        cx.notify();
 1000    }
 1001
 1002    fn pre_resolve_completion_documentation(
 1003        &self,
 1004        project: Option<ModelHandle<Project>>,
 1005        cx: &mut ViewContext<Editor>,
 1006    ) {
 1007        let settings = settings::get::<EditorSettings>(cx);
 1008        if !settings.show_completion_documentation {
 1009            return;
 1010        }
 1011
 1012        let Some(project) = project else {
 1013            return;
 1014        };
 1015        let client = project.read(cx).client();
 1016        let language_registry = project.read(cx).languages().clone();
 1017
 1018        let is_remote = project.read(cx).is_remote();
 1019        let project_id = project.read(cx).remote_id();
 1020
 1021        let completions = self.completions.clone();
 1022        let completion_indices: Vec<_> = self.matches.iter().map(|m| m.candidate_id).collect();
 1023
 1024        cx.spawn(move |this, mut cx| async move {
 1025            if is_remote {
 1026                let Some(project_id) = project_id else {
 1027                    log::error!("Remote project without remote_id");
 1028                    return;
 1029                };
 1030
 1031                for completion_index in completion_indices {
 1032                    let completions_guard = completions.read();
 1033                    let completion = &completions_guard[completion_index];
 1034                    if completion.documentation.is_some() {
 1035                        continue;
 1036                    }
 1037
 1038                    let server_id = completion.server_id;
 1039                    let completion = completion.lsp_completion.clone();
 1040                    drop(completions_guard);
 1041
 1042                    Self::resolve_completion_documentation_remote(
 1043                        project_id,
 1044                        server_id,
 1045                        completions.clone(),
 1046                        completion_index,
 1047                        completion,
 1048                        client.clone(),
 1049                        language_registry.clone(),
 1050                    )
 1051                    .await;
 1052
 1053                    _ = this.update(&mut cx, |_, cx| cx.notify());
 1054                }
 1055            } else {
 1056                for completion_index in completion_indices {
 1057                    let completions_guard = completions.read();
 1058                    let completion = &completions_guard[completion_index];
 1059                    if completion.documentation.is_some() {
 1060                        continue;
 1061                    }
 1062
 1063                    let server_id = completion.server_id;
 1064                    let completion = completion.lsp_completion.clone();
 1065                    drop(completions_guard);
 1066
 1067                    let server = project.read_with(&mut cx, |project, _| {
 1068                        project.language_server_for_id(server_id)
 1069                    });
 1070                    let Some(server) = server else {
 1071                        return;
 1072                    };
 1073
 1074                    Self::resolve_completion_documentation_local(
 1075                        server,
 1076                        completions.clone(),
 1077                        completion_index,
 1078                        completion,
 1079                        language_registry.clone(),
 1080                    )
 1081                    .await;
 1082
 1083                    _ = this.update(&mut cx, |_, cx| cx.notify());
 1084                }
 1085            }
 1086        })
 1087        .detach();
 1088    }
 1089
 1090    fn attempt_resolve_selected_completion_documentation(
 1091        &mut self,
 1092        project: Option<&ModelHandle<Project>>,
 1093        cx: &mut ViewContext<Editor>,
 1094    ) {
 1095        let settings = settings::get::<EditorSettings>(cx);
 1096        if !settings.show_completion_documentation {
 1097            return;
 1098        }
 1099
 1100        let completion_index = self.matches[self.selected_item].candidate_id;
 1101        let Some(project) = project else {
 1102            return;
 1103        };
 1104        let language_registry = project.read(cx).languages().clone();
 1105
 1106        let completions = self.completions.clone();
 1107        let completions_guard = completions.read();
 1108        let completion = &completions_guard[completion_index];
 1109        if completion.documentation.is_some() {
 1110            return;
 1111        }
 1112
 1113        let server_id = completion.server_id;
 1114        let completion = completion.lsp_completion.clone();
 1115        drop(completions_guard);
 1116
 1117        if project.read(cx).is_remote() {
 1118            let Some(project_id) = project.read(cx).remote_id() else {
 1119                log::error!("Remote project without remote_id");
 1120                return;
 1121            };
 1122
 1123            let client = project.read(cx).client();
 1124
 1125            cx.spawn(move |this, mut cx| async move {
 1126                Self::resolve_completion_documentation_remote(
 1127                    project_id,
 1128                    server_id,
 1129                    completions.clone(),
 1130                    completion_index,
 1131                    completion,
 1132                    client,
 1133                    language_registry.clone(),
 1134                )
 1135                .await;
 1136
 1137                _ = this.update(&mut cx, |_, cx| cx.notify());
 1138            })
 1139            .detach();
 1140        } else {
 1141            let Some(server) = project.read(cx).language_server_for_id(server_id) else {
 1142                return;
 1143            };
 1144
 1145            cx.spawn(move |this, mut cx| async move {
 1146                Self::resolve_completion_documentation_local(
 1147                    server,
 1148                    completions,
 1149                    completion_index,
 1150                    completion,
 1151                    language_registry,
 1152                )
 1153                .await;
 1154
 1155                _ = this.update(&mut cx, |_, cx| cx.notify());
 1156            })
 1157            .detach();
 1158        }
 1159    }
 1160
 1161    async fn resolve_completion_documentation_remote(
 1162        project_id: u64,
 1163        server_id: LanguageServerId,
 1164        completions: Arc<RwLock<Box<[Completion]>>>,
 1165        completion_index: usize,
 1166        completion: lsp::CompletionItem,
 1167        client: Arc<Client>,
 1168        language_registry: Arc<LanguageRegistry>,
 1169    ) {
 1170        let request = proto::ResolveCompletionDocumentation {
 1171            project_id,
 1172            language_server_id: server_id.0 as u64,
 1173            lsp_completion: serde_json::to_string(&completion).unwrap().into_bytes(),
 1174        };
 1175
 1176        let Some(response) = client
 1177            .request(request)
 1178            .await
 1179            .context("completion documentation resolve proto request")
 1180            .log_err()
 1181        else {
 1182            return;
 1183        };
 1184
 1185        if response.text.is_empty() {
 1186            let mut completions = completions.write();
 1187            let completion = &mut completions[completion_index];
 1188            completion.documentation = Some(Documentation::Undocumented);
 1189        }
 1190
 1191        let documentation = if response.is_markdown {
 1192            Documentation::MultiLineMarkdown(
 1193                markdown::parse_markdown(&response.text, &language_registry, None).await,
 1194            )
 1195        } else if response.text.lines().count() <= 1 {
 1196            Documentation::SingleLine(response.text)
 1197        } else {
 1198            Documentation::MultiLinePlainText(response.text)
 1199        };
 1200
 1201        let mut completions = completions.write();
 1202        let completion = &mut completions[completion_index];
 1203        completion.documentation = Some(documentation);
 1204    }
 1205
 1206    async fn resolve_completion_documentation_local(
 1207        server: Arc<lsp::LanguageServer>,
 1208        completions: Arc<RwLock<Box<[Completion]>>>,
 1209        completion_index: usize,
 1210        completion: lsp::CompletionItem,
 1211        language_registry: Arc<LanguageRegistry>,
 1212    ) {
 1213        let can_resolve = server
 1214            .capabilities()
 1215            .completion_provider
 1216            .as_ref()
 1217            .and_then(|options| options.resolve_provider)
 1218            .unwrap_or(false);
 1219        if !can_resolve {
 1220            return;
 1221        }
 1222
 1223        let request = server.request::<lsp::request::ResolveCompletionItem>(completion);
 1224        let Some(completion_item) = request.await.log_err() else {
 1225            return;
 1226        };
 1227
 1228        if let Some(lsp_documentation) = completion_item.documentation {
 1229            let documentation = language::prepare_completion_documentation(
 1230                &lsp_documentation,
 1231                &language_registry,
 1232                None, // TODO: Try to reasonably work out which language the completion is for
 1233            )
 1234            .await;
 1235
 1236            let mut completions = completions.write();
 1237            let completion = &mut completions[completion_index];
 1238            completion.documentation = Some(documentation);
 1239        } else {
 1240            let mut completions = completions.write();
 1241            let completion = &mut completions[completion_index];
 1242            completion.documentation = Some(Documentation::Undocumented);
 1243        }
 1244    }
 1245
 1246    fn visible(&self) -> bool {
 1247        !self.matches.is_empty()
 1248    }
 1249
 1250    fn render(
 1251        &self,
 1252        style: EditorStyle,
 1253        workspace: Option<WeakViewHandle<Workspace>>,
 1254        cx: &mut ViewContext<Editor>,
 1255    ) -> AnyElement<Editor> {
 1256        enum CompletionTag {}
 1257
 1258        let settings = settings::get::<EditorSettings>(cx);
 1259        let show_completion_documentation = settings.show_completion_documentation;
 1260
 1261        let widest_completion_ix = self
 1262            .matches
 1263            .iter()
 1264            .enumerate()
 1265            .max_by_key(|(_, mat)| {
 1266                let completions = self.completions.read();
 1267                let completion = &completions[mat.candidate_id];
 1268                let documentation = &completion.documentation;
 1269
 1270                let mut len = completion.label.text.chars().count();
 1271                if let Some(Documentation::SingleLine(text)) = documentation {
 1272                    if show_completion_documentation {
 1273                        len += text.chars().count();
 1274                    }
 1275                }
 1276
 1277                len
 1278            })
 1279            .map(|(ix, _)| ix);
 1280
 1281        let completions = self.completions.clone();
 1282        let matches = self.matches.clone();
 1283        let selected_item = self.selected_item;
 1284
 1285        let list = UniformList::new(self.list.clone(), matches.len(), cx, {
 1286            let style = style.clone();
 1287            move |_, range, items, cx| {
 1288                let start_ix = range.start;
 1289                let completions_guard = completions.read();
 1290
 1291                for (ix, mat) in matches[range].iter().enumerate() {
 1292                    let item_ix = start_ix + ix;
 1293                    let candidate_id = mat.candidate_id;
 1294                    let completion = &completions_guard[candidate_id];
 1295
 1296                    let documentation = if show_completion_documentation {
 1297                        &completion.documentation
 1298                    } else {
 1299                        &None
 1300                    };
 1301
 1302                    items.push(
 1303                        MouseEventHandler::new::<CompletionTag, _>(
 1304                            mat.candidate_id,
 1305                            cx,
 1306                            |state, _| {
 1307                                let item_style = if item_ix == selected_item {
 1308                                    style.autocomplete.selected_item
 1309                                } else if state.hovered() {
 1310                                    style.autocomplete.hovered_item
 1311                                } else {
 1312                                    style.autocomplete.item
 1313                                };
 1314
 1315                                let completion_label =
 1316                                    Text::new(completion.label.text.clone(), style.text.clone())
 1317                                        .with_soft_wrap(false)
 1318                                        .with_highlights(
 1319                                            combine_syntax_and_fuzzy_match_highlights(
 1320                                                &completion.label.text,
 1321                                                style.text.color.into(),
 1322                                                styled_runs_for_code_label(
 1323                                                    &completion.label,
 1324                                                    &style.syntax,
 1325                                                ),
 1326                                                &mat.positions,
 1327                                            ),
 1328                                        );
 1329
 1330                                if let Some(Documentation::SingleLine(text)) = documentation {
 1331                                    Flex::row()
 1332                                        .with_child(completion_label)
 1333                                        .with_children((|| {
 1334                                            let text_style = TextStyle {
 1335                                                color: style.autocomplete.inline_docs_color,
 1336                                                font_size: style.text.font_size
 1337                                                    * style.autocomplete.inline_docs_size_percent,
 1338                                                ..style.text.clone()
 1339                                            };
 1340
 1341                                            let label = Text::new(text.clone(), text_style)
 1342                                                .aligned()
 1343                                                .constrained()
 1344                                                .dynamically(move |constraint, _, _| {
 1345                                                    gpui::SizeConstraint {
 1346                                                        min: constraint.min,
 1347                                                        max: vec2f(
 1348                                                            constraint.max.x(),
 1349                                                            constraint.min.y(),
 1350                                                        ),
 1351                                                    }
 1352                                                });
 1353
 1354                                            if Some(item_ix) == widest_completion_ix {
 1355                                                Some(
 1356                                                    label
 1357                                                        .contained()
 1358                                                        .with_style(
 1359                                                            style
 1360                                                                .autocomplete
 1361                                                                .inline_docs_container,
 1362                                                        )
 1363                                                        .into_any(),
 1364                                                )
 1365                                            } else {
 1366                                                Some(label.flex_float().into_any())
 1367                                            }
 1368                                        })())
 1369                                        .into_any()
 1370                                } else {
 1371                                    completion_label.into_any()
 1372                                }
 1373                                .contained()
 1374                                .with_style(item_style)
 1375                                .constrained()
 1376                                .dynamically(
 1377                                    move |constraint, _, _| {
 1378                                        if Some(item_ix) == widest_completion_ix {
 1379                                            constraint
 1380                                        } else {
 1381                                            gpui::SizeConstraint {
 1382                                                min: constraint.min,
 1383                                                max: constraint.min,
 1384                                            }
 1385                                        }
 1386                                    },
 1387                                )
 1388                            },
 1389                        )
 1390                        .with_cursor_style(CursorStyle::PointingHand)
 1391                        .on_down(MouseButton::Left, move |_, this, cx| {
 1392                            this.confirm_completion(
 1393                                &ConfirmCompletion {
 1394                                    item_ix: Some(item_ix),
 1395                                },
 1396                                cx,
 1397                            )
 1398                            .map(|task| task.detach());
 1399                        })
 1400                        .constrained()
 1401                        .with_min_width(style.autocomplete.completion_min_width)
 1402                        .with_max_width(style.autocomplete.completion_max_width)
 1403                        .into_any(),
 1404                    );
 1405                }
 1406            }
 1407        })
 1408        .with_width_from_item(widest_completion_ix);
 1409
 1410        enum MultiLineDocumentation {}
 1411
 1412        Flex::row()
 1413            .with_child(list.flex(1., false))
 1414            .with_children({
 1415                let mat = &self.matches[selected_item];
 1416                let completions = self.completions.read();
 1417                let completion = &completions[mat.candidate_id];
 1418                let documentation = &completion.documentation;
 1419
 1420                match documentation {
 1421                    Some(Documentation::MultiLinePlainText(text)) => Some(
 1422                        Flex::column()
 1423                            .scrollable::<MultiLineDocumentation>(0, None, cx)
 1424                            .with_child(
 1425                                Text::new(text.clone(), style.text.clone()).with_soft_wrap(true),
 1426                            )
 1427                            .contained()
 1428                            .with_style(style.autocomplete.alongside_docs_container)
 1429                            .constrained()
 1430                            .with_max_width(style.autocomplete.alongside_docs_max_width)
 1431                            .flex(1., false),
 1432                    ),
 1433
 1434                    Some(Documentation::MultiLineMarkdown(parsed)) => Some(
 1435                        Flex::column()
 1436                            .scrollable::<MultiLineDocumentation>(0, None, cx)
 1437                            .with_child(render_parsed_markdown::<MultiLineDocumentation>(
 1438                                parsed, &style, workspace, cx,
 1439                            ))
 1440                            .contained()
 1441                            .with_style(style.autocomplete.alongside_docs_container)
 1442                            .constrained()
 1443                            .with_max_width(style.autocomplete.alongside_docs_max_width)
 1444                            .flex(1., false),
 1445                    ),
 1446
 1447                    _ => None,
 1448                }
 1449            })
 1450            .contained()
 1451            .with_style(style.autocomplete.container)
 1452            .into_any()
 1453    }
 1454
 1455    pub async fn filter(&mut self, query: Option<&str>, executor: Arc<executor::Background>) {
 1456        let mut matches = if let Some(query) = query {
 1457            fuzzy::match_strings(
 1458                &self.match_candidates,
 1459                query,
 1460                query.chars().any(|c| c.is_uppercase()),
 1461                100,
 1462                &Default::default(),
 1463                executor,
 1464            )
 1465            .await
 1466        } else {
 1467            self.match_candidates
 1468                .iter()
 1469                .enumerate()
 1470                .map(|(candidate_id, candidate)| StringMatch {
 1471                    candidate_id,
 1472                    score: Default::default(),
 1473                    positions: Default::default(),
 1474                    string: candidate.string.clone(),
 1475                })
 1476                .collect()
 1477        };
 1478
 1479        // Remove all candidates where the query's start does not match the start of any word in the candidate
 1480        if let Some(query) = query {
 1481            if let Some(query_start) = query.chars().next() {
 1482                matches.retain(|string_match| {
 1483                    split_words(&string_match.string).any(|word| {
 1484                        // Check that the first codepoint of the word as lowercase matches the first
 1485                        // codepoint of the query as lowercase
 1486                        word.chars()
 1487                            .flat_map(|codepoint| codepoint.to_lowercase())
 1488                            .zip(query_start.to_lowercase())
 1489                            .all(|(word_cp, query_cp)| word_cp == query_cp)
 1490                    })
 1491                });
 1492            }
 1493        }
 1494
 1495        let completions = self.completions.read();
 1496        matches.sort_unstable_by_key(|mat| {
 1497            let completion = &completions[mat.candidate_id];
 1498            (
 1499                completion.lsp_completion.sort_text.as_ref(),
 1500                Reverse(OrderedFloat(mat.score)),
 1501                completion.sort_key(),
 1502            )
 1503        });
 1504        drop(completions);
 1505
 1506        for mat in &mut matches {
 1507            let completions = self.completions.read();
 1508            let filter_start = completions[mat.candidate_id].label.filter_range.start;
 1509            for position in &mut mat.positions {
 1510                *position += filter_start;
 1511            }
 1512        }
 1513
 1514        self.matches = matches.into();
 1515        self.selected_item = 0;
 1516    }
 1517}
 1518
 1519#[derive(Clone)]
 1520struct CodeActionsMenu {
 1521    actions: Arc<[CodeAction]>,
 1522    buffer: ModelHandle<Buffer>,
 1523    selected_item: usize,
 1524    list: UniformListState,
 1525    deployed_from_indicator: bool,
 1526}
 1527
 1528impl CodeActionsMenu {
 1529    fn select_first(&mut self, cx: &mut ViewContext<Editor>) {
 1530        self.selected_item = 0;
 1531        self.list.scroll_to(ScrollTarget::Show(self.selected_item));
 1532        cx.notify()
 1533    }
 1534
 1535    fn select_prev(&mut self, cx: &mut ViewContext<Editor>) {
 1536        if self.selected_item > 0 {
 1537            self.selected_item -= 1;
 1538        } else {
 1539            self.selected_item = self.actions.len() - 1;
 1540        }
 1541        self.list.scroll_to(ScrollTarget::Show(self.selected_item));
 1542        cx.notify();
 1543    }
 1544
 1545    fn select_next(&mut self, cx: &mut ViewContext<Editor>) {
 1546        if self.selected_item + 1 < self.actions.len() {
 1547            self.selected_item += 1;
 1548            self.list.scroll_to(ScrollTarget::Show(self.selected_item));
 1549        } else {
 1550            self.selected_item = 0;
 1551            self.list.scroll_to(ScrollTarget::Show(self.selected_item));
 1552        }
 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                    && !entry.range.contains(&search_start)
 7214                {
 7215                    Some((entry.range, entry.diagnostic.group_id))
 7216                } else {
 7217                    None
 7218                }
 7219            });
 7220
 7221            if let Some((primary_range, group_id)) = group {
 7222                if self.activate_diagnostics(group_id, cx) {
 7223                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7224                        s.select(vec![Selection {
 7225                            id: selection.id,
 7226                            start: primary_range.start,
 7227                            end: primary_range.start,
 7228                            reversed: false,
 7229                            goal: SelectionGoal::None,
 7230                        }]);
 7231                    });
 7232                }
 7233                break;
 7234            } else {
 7235                // Cycle around to the start of the buffer, potentially moving back to the start of
 7236                // the currently active diagnostic.
 7237                active_primary_range.take();
 7238                if direction == Direction::Prev {
 7239                    if search_start == buffer.len() {
 7240                        break;
 7241                    } else {
 7242                        search_start = buffer.len();
 7243                    }
 7244                } else if search_start == 0 {
 7245                    break;
 7246                } else {
 7247                    search_start = 0;
 7248                }
 7249            }
 7250        }
 7251    }
 7252
 7253    fn go_to_hunk(&mut self, _: &GoToHunk, cx: &mut ViewContext<Self>) {
 7254        let snapshot = self
 7255            .display_map
 7256            .update(cx, |display_map, cx| display_map.snapshot(cx));
 7257        let selection = self.selections.newest::<Point>(cx);
 7258
 7259        if !self.seek_in_direction(
 7260            &snapshot,
 7261            selection.head(),
 7262            false,
 7263            snapshot
 7264                .buffer_snapshot
 7265                .git_diff_hunks_in_range((selection.head().row + 1)..u32::MAX),
 7266            cx,
 7267        ) {
 7268            let wrapped_point = Point::zero();
 7269            self.seek_in_direction(
 7270                &snapshot,
 7271                wrapped_point,
 7272                true,
 7273                snapshot
 7274                    .buffer_snapshot
 7275                    .git_diff_hunks_in_range((wrapped_point.row + 1)..u32::MAX),
 7276                cx,
 7277            );
 7278        }
 7279    }
 7280
 7281    fn go_to_prev_hunk(&mut self, _: &GoToPrevHunk, cx: &mut ViewContext<Self>) {
 7282        let snapshot = self
 7283            .display_map
 7284            .update(cx, |display_map, cx| display_map.snapshot(cx));
 7285        let selection = self.selections.newest::<Point>(cx);
 7286
 7287        if !self.seek_in_direction(
 7288            &snapshot,
 7289            selection.head(),
 7290            false,
 7291            snapshot
 7292                .buffer_snapshot
 7293                .git_diff_hunks_in_range_rev(0..selection.head().row),
 7294            cx,
 7295        ) {
 7296            let wrapped_point = snapshot.buffer_snapshot.max_point();
 7297            self.seek_in_direction(
 7298                &snapshot,
 7299                wrapped_point,
 7300                true,
 7301                snapshot
 7302                    .buffer_snapshot
 7303                    .git_diff_hunks_in_range_rev(0..wrapped_point.row),
 7304                cx,
 7305            );
 7306        }
 7307    }
 7308
 7309    fn seek_in_direction(
 7310        &mut self,
 7311        snapshot: &DisplaySnapshot,
 7312        initial_point: Point,
 7313        is_wrapped: bool,
 7314        hunks: impl Iterator<Item = DiffHunk<u32>>,
 7315        cx: &mut ViewContext<Editor>,
 7316    ) -> bool {
 7317        let display_point = initial_point.to_display_point(snapshot);
 7318        let mut hunks = hunks
 7319            .map(|hunk| diff_hunk_to_display(hunk, &snapshot))
 7320            .filter(|hunk| {
 7321                if is_wrapped {
 7322                    true
 7323                } else {
 7324                    !hunk.contains_display_row(display_point.row())
 7325                }
 7326            })
 7327            .dedup();
 7328
 7329        if let Some(hunk) = hunks.next() {
 7330            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7331                let row = hunk.start_display_row();
 7332                let point = DisplayPoint::new(row, 0);
 7333                s.select_display_ranges([point..point]);
 7334            });
 7335
 7336            true
 7337        } else {
 7338            false
 7339        }
 7340    }
 7341
 7342    pub fn go_to_definition(&mut self, _: &GoToDefinition, cx: &mut ViewContext<Self>) {
 7343        self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, false, cx);
 7344    }
 7345
 7346    pub fn go_to_type_definition(&mut self, _: &GoToTypeDefinition, cx: &mut ViewContext<Self>) {
 7347        self.go_to_definition_of_kind(GotoDefinitionKind::Type, false, cx);
 7348    }
 7349
 7350    pub fn go_to_definition_split(&mut self, _: &GoToDefinitionSplit, cx: &mut ViewContext<Self>) {
 7351        self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, true, cx);
 7352    }
 7353
 7354    pub fn go_to_type_definition_split(
 7355        &mut self,
 7356        _: &GoToTypeDefinitionSplit,
 7357        cx: &mut ViewContext<Self>,
 7358    ) {
 7359        self.go_to_definition_of_kind(GotoDefinitionKind::Type, true, cx);
 7360    }
 7361
 7362    fn go_to_definition_of_kind(
 7363        &mut self,
 7364        kind: GotoDefinitionKind,
 7365        split: bool,
 7366        cx: &mut ViewContext<Self>,
 7367    ) {
 7368        let Some(workspace) = self.workspace(cx) else {
 7369            return;
 7370        };
 7371        let buffer = self.buffer.read(cx);
 7372        let head = self.selections.newest::<usize>(cx).head();
 7373        let (buffer, head) = if let Some(text_anchor) = buffer.text_anchor_for_position(head, cx) {
 7374            text_anchor
 7375        } else {
 7376            return;
 7377        };
 7378
 7379        let project = workspace.read(cx).project().clone();
 7380        let definitions = project.update(cx, |project, cx| match kind {
 7381            GotoDefinitionKind::Symbol => project.definition(&buffer, head, cx),
 7382            GotoDefinitionKind::Type => project.type_definition(&buffer, head, cx),
 7383        });
 7384
 7385        cx.spawn_labeled("Fetching Definition...", |editor, mut cx| async move {
 7386            let definitions = definitions.await?;
 7387            editor.update(&mut cx, |editor, cx| {
 7388                editor.navigate_to_definitions(
 7389                    definitions
 7390                        .into_iter()
 7391                        .map(GoToDefinitionLink::Text)
 7392                        .collect(),
 7393                    split,
 7394                    cx,
 7395                );
 7396            })?;
 7397            Ok::<(), anyhow::Error>(())
 7398        })
 7399        .detach_and_log_err(cx);
 7400    }
 7401
 7402    pub fn navigate_to_definitions(
 7403        &mut self,
 7404        mut definitions: Vec<GoToDefinitionLink>,
 7405        split: bool,
 7406        cx: &mut ViewContext<Editor>,
 7407    ) {
 7408        let Some(workspace) = self.workspace(cx) else {
 7409            return;
 7410        };
 7411        let pane = workspace.read(cx).active_pane().clone();
 7412        // If there is one definition, just open it directly
 7413        if definitions.len() == 1 {
 7414            let definition = definitions.pop().unwrap();
 7415            let target_task = match definition {
 7416                GoToDefinitionLink::Text(link) => Task::Ready(Some(Ok(Some(link.target)))),
 7417                GoToDefinitionLink::InlayHint(lsp_location, server_id) => {
 7418                    self.compute_target_location(lsp_location, server_id, cx)
 7419                }
 7420            };
 7421            cx.spawn(|editor, mut cx| async move {
 7422                let target = target_task.await.context("target resolution task")?;
 7423                if let Some(target) = target {
 7424                    editor.update(&mut cx, |editor, cx| {
 7425                        let range = target.range.to_offset(target.buffer.read(cx));
 7426                        let range = editor.range_for_match(&range);
 7427                        if Some(&target.buffer) == editor.buffer.read(cx).as_singleton().as_ref() {
 7428                            editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
 7429                                s.select_ranges([range]);
 7430                            });
 7431                        } else {
 7432                            cx.window_context().defer(move |cx| {
 7433                                let target_editor: ViewHandle<Self> =
 7434                                    workspace.update(cx, |workspace, cx| {
 7435                                        if split {
 7436                                            workspace.split_project_item(target.buffer.clone(), cx)
 7437                                        } else {
 7438                                            workspace.open_project_item(target.buffer.clone(), cx)
 7439                                        }
 7440                                    });
 7441                                target_editor.update(cx, |target_editor, cx| {
 7442                                    // When selecting a definition in a different buffer, disable the nav history
 7443                                    // to avoid creating a history entry at the previous cursor location.
 7444                                    pane.update(cx, |pane, _| pane.disable_history());
 7445                                    target_editor.change_selections(
 7446                                        Some(Autoscroll::fit()),
 7447                                        cx,
 7448                                        |s| {
 7449                                            s.select_ranges([range]);
 7450                                        },
 7451                                    );
 7452                                    pane.update(cx, |pane, _| pane.enable_history());
 7453                                });
 7454                            });
 7455                        }
 7456                    })
 7457                } else {
 7458                    Ok(())
 7459                }
 7460            })
 7461            .detach_and_log_err(cx);
 7462        } else if !definitions.is_empty() {
 7463            let replica_id = self.replica_id(cx);
 7464            cx.spawn(|editor, mut cx| async move {
 7465                let (title, location_tasks) = editor
 7466                    .update(&mut cx, |editor, cx| {
 7467                        let title = definitions
 7468                            .iter()
 7469                            .find_map(|definition| match definition {
 7470                                GoToDefinitionLink::Text(link) => {
 7471                                    link.origin.as_ref().map(|origin| {
 7472                                        let buffer = origin.buffer.read(cx);
 7473                                        format!(
 7474                                            "Definitions for {}",
 7475                                            buffer
 7476                                                .text_for_range(origin.range.clone())
 7477                                                .collect::<String>()
 7478                                        )
 7479                                    })
 7480                                }
 7481                                GoToDefinitionLink::InlayHint(_, _) => None,
 7482                            })
 7483                            .unwrap_or("Definitions".to_string());
 7484                        let location_tasks = definitions
 7485                            .into_iter()
 7486                            .map(|definition| match definition {
 7487                                GoToDefinitionLink::Text(link) => {
 7488                                    Task::Ready(Some(Ok(Some(link.target))))
 7489                                }
 7490                                GoToDefinitionLink::InlayHint(lsp_location, server_id) => {
 7491                                    editor.compute_target_location(lsp_location, server_id, cx)
 7492                                }
 7493                            })
 7494                            .collect::<Vec<_>>();
 7495                        (title, location_tasks)
 7496                    })
 7497                    .context("location tasks preparation")?;
 7498
 7499                let locations = futures::future::join_all(location_tasks)
 7500                    .await
 7501                    .into_iter()
 7502                    .filter_map(|location| location.transpose())
 7503                    .collect::<Result<_>>()
 7504                    .context("location tasks")?;
 7505                workspace.update(&mut cx, |workspace, cx| {
 7506                    Self::open_locations_in_multibuffer(
 7507                        workspace, locations, replica_id, title, split, cx,
 7508                    )
 7509                });
 7510
 7511                anyhow::Ok(())
 7512            })
 7513            .detach_and_log_err(cx);
 7514        }
 7515    }
 7516
 7517    fn compute_target_location(
 7518        &self,
 7519        lsp_location: lsp::Location,
 7520        server_id: LanguageServerId,
 7521        cx: &mut ViewContext<Editor>,
 7522    ) -> Task<anyhow::Result<Option<Location>>> {
 7523        let Some(project) = self.project.clone() else {
 7524            return Task::Ready(Some(Ok(None)));
 7525        };
 7526
 7527        cx.spawn(move |editor, mut cx| async move {
 7528            let location_task = editor.update(&mut cx, |editor, cx| {
 7529                project.update(cx, |project, cx| {
 7530                    let language_server_name =
 7531                        editor.buffer.read(cx).as_singleton().and_then(|buffer| {
 7532                            project
 7533                                .language_server_for_buffer(buffer.read(cx), server_id, cx)
 7534                                .map(|(_, lsp_adapter)| {
 7535                                    LanguageServerName(Arc::from(lsp_adapter.name()))
 7536                                })
 7537                        });
 7538                    language_server_name.map(|language_server_name| {
 7539                        project.open_local_buffer_via_lsp(
 7540                            lsp_location.uri.clone(),
 7541                            server_id,
 7542                            language_server_name,
 7543                            cx,
 7544                        )
 7545                    })
 7546                })
 7547            })?;
 7548            let location = match location_task {
 7549                Some(task) => Some({
 7550                    let target_buffer_handle = task.await.context("open local buffer")?;
 7551                    let range = {
 7552                        target_buffer_handle.update(&mut cx, |target_buffer, _| {
 7553                            let target_start = target_buffer.clip_point_utf16(
 7554                                point_from_lsp(lsp_location.range.start),
 7555                                Bias::Left,
 7556                            );
 7557                            let target_end = target_buffer.clip_point_utf16(
 7558                                point_from_lsp(lsp_location.range.end),
 7559                                Bias::Left,
 7560                            );
 7561                            target_buffer.anchor_after(target_start)
 7562                                ..target_buffer.anchor_before(target_end)
 7563                        })
 7564                    };
 7565                    Location {
 7566                        buffer: target_buffer_handle,
 7567                        range,
 7568                    }
 7569                }),
 7570                None => None,
 7571            };
 7572            Ok(location)
 7573        })
 7574    }
 7575
 7576    pub fn find_all_references(
 7577        workspace: &mut Workspace,
 7578        _: &FindAllReferences,
 7579        cx: &mut ViewContext<Workspace>,
 7580    ) -> Option<Task<Result<()>>> {
 7581        let active_item = workspace.active_item(cx)?;
 7582        let editor_handle = active_item.act_as::<Self>(cx)?;
 7583
 7584        let editor = editor_handle.read(cx);
 7585        let buffer = editor.buffer.read(cx);
 7586        let head = editor.selections.newest::<usize>(cx).head();
 7587        let (buffer, head) = buffer.text_anchor_for_position(head, cx)?;
 7588        let replica_id = editor.replica_id(cx);
 7589
 7590        let project = workspace.project().clone();
 7591        let references = project.update(cx, |project, cx| project.references(&buffer, head, cx));
 7592        Some(cx.spawn_labeled(
 7593            "Finding All References...",
 7594            |workspace, mut cx| async move {
 7595                let locations = references.await?;
 7596                if locations.is_empty() {
 7597                    return Ok(());
 7598                }
 7599
 7600                workspace.update(&mut cx, |workspace, cx| {
 7601                    let title = locations
 7602                        .first()
 7603                        .as_ref()
 7604                        .map(|location| {
 7605                            let buffer = location.buffer.read(cx);
 7606                            format!(
 7607                                "References to `{}`",
 7608                                buffer
 7609                                    .text_for_range(location.range.clone())
 7610                                    .collect::<String>()
 7611                            )
 7612                        })
 7613                        .unwrap();
 7614                    Self::open_locations_in_multibuffer(
 7615                        workspace, locations, replica_id, title, false, cx,
 7616                    );
 7617                })?;
 7618
 7619                Ok(())
 7620            },
 7621        ))
 7622    }
 7623
 7624    /// Opens a multibuffer with the given project locations in it
 7625    pub fn open_locations_in_multibuffer(
 7626        workspace: &mut Workspace,
 7627        mut locations: Vec<Location>,
 7628        replica_id: ReplicaId,
 7629        title: String,
 7630        split: bool,
 7631        cx: &mut ViewContext<Workspace>,
 7632    ) {
 7633        // If there are multiple definitions, open them in a multibuffer
 7634        locations.sort_by_key(|location| location.buffer.read(cx).remote_id());
 7635        let mut locations = locations.into_iter().peekable();
 7636        let mut ranges_to_highlight = Vec::new();
 7637
 7638        let excerpt_buffer = cx.add_model(|cx| {
 7639            let mut multibuffer = MultiBuffer::new(replica_id);
 7640            while let Some(location) = locations.next() {
 7641                let buffer = location.buffer.read(cx);
 7642                let mut ranges_for_buffer = Vec::new();
 7643                let range = location.range.to_offset(buffer);
 7644                ranges_for_buffer.push(range.clone());
 7645
 7646                while let Some(next_location) = locations.peek() {
 7647                    if next_location.buffer == location.buffer {
 7648                        ranges_for_buffer.push(next_location.range.to_offset(buffer));
 7649                        locations.next();
 7650                    } else {
 7651                        break;
 7652                    }
 7653                }
 7654
 7655                ranges_for_buffer.sort_by_key(|range| (range.start, Reverse(range.end)));
 7656                ranges_to_highlight.extend(multibuffer.push_excerpts_with_context_lines(
 7657                    location.buffer.clone(),
 7658                    ranges_for_buffer,
 7659                    1,
 7660                    cx,
 7661                ))
 7662            }
 7663
 7664            multibuffer.with_title(title)
 7665        });
 7666
 7667        let editor = cx.add_view(|cx| {
 7668            Editor::for_multibuffer(excerpt_buffer, Some(workspace.project().clone()), cx)
 7669        });
 7670        editor.update(cx, |editor, cx| {
 7671            editor.highlight_background::<Self>(
 7672                ranges_to_highlight,
 7673                |theme| theme.editor.highlighted_line_background,
 7674                cx,
 7675            );
 7676        });
 7677        if split {
 7678            workspace.split_item(SplitDirection::Right, Box::new(editor), cx);
 7679        } else {
 7680            workspace.add_item(Box::new(editor), cx);
 7681        }
 7682    }
 7683
 7684    pub fn rename(&mut self, _: &Rename, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
 7685        use language::ToOffset as _;
 7686
 7687        let project = self.project.clone()?;
 7688        let selection = self.selections.newest_anchor().clone();
 7689        let (cursor_buffer, cursor_buffer_position) = self
 7690            .buffer
 7691            .read(cx)
 7692            .text_anchor_for_position(selection.head(), cx)?;
 7693        let (tail_buffer, _) = self
 7694            .buffer
 7695            .read(cx)
 7696            .text_anchor_for_position(selection.tail(), cx)?;
 7697        if tail_buffer != cursor_buffer {
 7698            return None;
 7699        }
 7700
 7701        let snapshot = cursor_buffer.read(cx).snapshot();
 7702        let cursor_buffer_offset = cursor_buffer_position.to_offset(&snapshot);
 7703        let prepare_rename = project.update(cx, |project, cx| {
 7704            project.prepare_rename(cursor_buffer, cursor_buffer_offset, cx)
 7705        });
 7706
 7707        Some(cx.spawn(|this, mut cx| async move {
 7708            let rename_range = if let Some(range) = prepare_rename.await? {
 7709                Some(range)
 7710            } else {
 7711                this.update(&mut cx, |this, cx| {
 7712                    let buffer = this.buffer.read(cx).snapshot(cx);
 7713                    let mut buffer_highlights = this
 7714                        .document_highlights_for_position(selection.head(), &buffer)
 7715                        .filter(|highlight| {
 7716                            highlight.start.excerpt_id == selection.head().excerpt_id
 7717                                && highlight.end.excerpt_id == selection.head().excerpt_id
 7718                        });
 7719                    buffer_highlights
 7720                        .next()
 7721                        .map(|highlight| highlight.start.text_anchor..highlight.end.text_anchor)
 7722                })?
 7723            };
 7724            if let Some(rename_range) = rename_range {
 7725                let rename_buffer_range = rename_range.to_offset(&snapshot);
 7726                let cursor_offset_in_rename_range =
 7727                    cursor_buffer_offset.saturating_sub(rename_buffer_range.start);
 7728
 7729                this.update(&mut cx, |this, cx| {
 7730                    this.take_rename(false, cx);
 7731                    let style = this.style(cx);
 7732                    let buffer = this.buffer.read(cx).read(cx);
 7733                    let cursor_offset = selection.head().to_offset(&buffer);
 7734                    let rename_start = cursor_offset.saturating_sub(cursor_offset_in_rename_range);
 7735                    let rename_end = rename_start + rename_buffer_range.len();
 7736                    let range = buffer.anchor_before(rename_start)..buffer.anchor_after(rename_end);
 7737                    let mut old_highlight_id = None;
 7738                    let old_name: Arc<str> = buffer
 7739                        .chunks(rename_start..rename_end, true)
 7740                        .map(|chunk| {
 7741                            if old_highlight_id.is_none() {
 7742                                old_highlight_id = chunk.syntax_highlight_id;
 7743                            }
 7744                            chunk.text
 7745                        })
 7746                        .collect::<String>()
 7747                        .into();
 7748
 7749                    drop(buffer);
 7750
 7751                    // Position the selection in the rename editor so that it matches the current selection.
 7752                    this.show_local_selections = false;
 7753                    let rename_editor = cx.add_view(|cx| {
 7754                        let mut editor = Editor::single_line(None, cx);
 7755                        if let Some(old_highlight_id) = old_highlight_id {
 7756                            editor.override_text_style =
 7757                                Some(Box::new(move |style| old_highlight_id.style(&style.syntax)));
 7758                        }
 7759                        editor.buffer.update(cx, |buffer, cx| {
 7760                            buffer.edit([(0..0, old_name.clone())], None, cx)
 7761                        });
 7762                        editor.select_all(&SelectAll, cx);
 7763                        editor
 7764                    });
 7765
 7766                    let ranges = this
 7767                        .clear_background_highlights::<DocumentHighlightWrite>(cx)
 7768                        .into_iter()
 7769                        .flat_map(|(_, ranges)| ranges.into_iter())
 7770                        .chain(
 7771                            this.clear_background_highlights::<DocumentHighlightRead>(cx)
 7772                                .into_iter()
 7773                                .flat_map(|(_, ranges)| ranges.into_iter()),
 7774                        )
 7775                        .collect();
 7776
 7777                    this.highlight_text::<Rename>(
 7778                        ranges,
 7779                        HighlightStyle {
 7780                            fade_out: Some(style.rename_fade),
 7781                            ..Default::default()
 7782                        },
 7783                        cx,
 7784                    );
 7785                    cx.focus(&rename_editor);
 7786                    let block_id = this.insert_blocks(
 7787                        [BlockProperties {
 7788                            style: BlockStyle::Flex,
 7789                            position: range.start.clone(),
 7790                            height: 1,
 7791                            render: Arc::new({
 7792                                let editor = rename_editor.clone();
 7793                                move |cx: &mut BlockContext| {
 7794                                    ChildView::new(&editor, cx)
 7795                                        .contained()
 7796                                        .with_padding_left(cx.anchor_x)
 7797                                        .into_any()
 7798                                }
 7799                            }),
 7800                            disposition: BlockDisposition::Below,
 7801                        }],
 7802                        Some(Autoscroll::fit()),
 7803                        cx,
 7804                    )[0];
 7805                    this.pending_rename = Some(RenameState {
 7806                        range,
 7807                        old_name,
 7808                        editor: rename_editor,
 7809                        block_id,
 7810                    });
 7811                })?;
 7812            }
 7813
 7814            Ok(())
 7815        }))
 7816    }
 7817
 7818    pub fn confirm_rename(
 7819        workspace: &mut Workspace,
 7820        _: &ConfirmRename,
 7821        cx: &mut ViewContext<Workspace>,
 7822    ) -> Option<Task<Result<()>>> {
 7823        let editor = workspace.active_item(cx)?.act_as::<Editor>(cx)?;
 7824
 7825        let (buffer, range, old_name, new_name) = editor.update(cx, |editor, cx| {
 7826            let rename = editor.take_rename(false, cx)?;
 7827            let buffer = editor.buffer.read(cx);
 7828            let (start_buffer, start) =
 7829                buffer.text_anchor_for_position(rename.range.start.clone(), cx)?;
 7830            let (end_buffer, end) =
 7831                buffer.text_anchor_for_position(rename.range.end.clone(), cx)?;
 7832            if start_buffer == end_buffer {
 7833                let new_name = rename.editor.read(cx).text(cx);
 7834                Some((start_buffer, start..end, rename.old_name, new_name))
 7835            } else {
 7836                None
 7837            }
 7838        })?;
 7839
 7840        let rename = workspace.project().clone().update(cx, |project, cx| {
 7841            project.perform_rename(buffer.clone(), range.start, new_name.clone(), true, cx)
 7842        });
 7843
 7844        let editor = editor.downgrade();
 7845        Some(cx.spawn(|workspace, mut cx| async move {
 7846            let project_transaction = rename.await?;
 7847            Self::open_project_transaction(
 7848                &editor,
 7849                workspace,
 7850                project_transaction,
 7851                format!("Rename: {}{}", old_name, new_name),
 7852                cx.clone(),
 7853            )
 7854            .await?;
 7855
 7856            editor.update(&mut cx, |editor, cx| {
 7857                editor.refresh_document_highlights(cx);
 7858            })?;
 7859            Ok(())
 7860        }))
 7861    }
 7862
 7863    fn take_rename(
 7864        &mut self,
 7865        moving_cursor: bool,
 7866        cx: &mut ViewContext<Self>,
 7867    ) -> Option<RenameState> {
 7868        let rename = self.pending_rename.take()?;
 7869        self.remove_blocks(
 7870            [rename.block_id].into_iter().collect(),
 7871            Some(Autoscroll::fit()),
 7872            cx,
 7873        );
 7874        self.clear_highlights::<Rename>(cx);
 7875        self.show_local_selections = true;
 7876
 7877        if moving_cursor {
 7878            let rename_editor = rename.editor.read(cx);
 7879            let cursor_in_rename_editor = rename_editor.selections.newest::<usize>(cx).head();
 7880
 7881            // Update the selection to match the position of the selection inside
 7882            // the rename editor.
 7883            let snapshot = self.buffer.read(cx).read(cx);
 7884            let rename_range = rename.range.to_offset(&snapshot);
 7885            let cursor_in_editor = snapshot
 7886                .clip_offset(rename_range.start + cursor_in_rename_editor, Bias::Left)
 7887                .min(rename_range.end);
 7888            drop(snapshot);
 7889
 7890            self.change_selections(None, cx, |s| {
 7891                s.select_ranges(vec![cursor_in_editor..cursor_in_editor])
 7892            });
 7893        } else {
 7894            self.refresh_document_highlights(cx);
 7895        }
 7896
 7897        Some(rename)
 7898    }
 7899
 7900    #[cfg(any(test, feature = "test-support"))]
 7901    pub fn pending_rename(&self) -> Option<&RenameState> {
 7902        self.pending_rename.as_ref()
 7903    }
 7904
 7905    fn format(&mut self, _: &Format, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
 7906        let project = match &self.project {
 7907            Some(project) => project.clone(),
 7908            None => return None,
 7909        };
 7910
 7911        Some(self.perform_format(project, FormatTrigger::Manual, cx))
 7912    }
 7913
 7914    fn perform_format(
 7915        &mut self,
 7916        project: ModelHandle<Project>,
 7917        trigger: FormatTrigger,
 7918        cx: &mut ViewContext<Self>,
 7919    ) -> Task<Result<()>> {
 7920        let buffer = self.buffer().clone();
 7921        let buffers = buffer.read(cx).all_buffers();
 7922
 7923        let mut timeout = cx.background().timer(FORMAT_TIMEOUT).fuse();
 7924        let format = project.update(cx, |project, cx| project.format(buffers, true, trigger, cx));
 7925
 7926        cx.spawn(|_, mut cx| async move {
 7927            let transaction = futures::select_biased! {
 7928                _ = timeout => {
 7929                    log::warn!("timed out waiting for formatting");
 7930                    None
 7931                }
 7932                transaction = format.log_err().fuse() => transaction,
 7933            };
 7934
 7935            buffer.update(&mut cx, |buffer, cx| {
 7936                if let Some(transaction) = transaction {
 7937                    if !buffer.is_singleton() {
 7938                        buffer.push_transaction(&transaction.0, cx);
 7939                    }
 7940                }
 7941
 7942                cx.notify();
 7943            });
 7944
 7945            Ok(())
 7946        })
 7947    }
 7948
 7949    fn restart_language_server(&mut self, _: &RestartLanguageServer, cx: &mut ViewContext<Self>) {
 7950        if let Some(project) = self.project.clone() {
 7951            self.buffer.update(cx, |multi_buffer, cx| {
 7952                project.update(cx, |project, cx| {
 7953                    project.restart_language_servers_for_buffers(multi_buffer.all_buffers(), cx);
 7954                });
 7955            })
 7956        }
 7957    }
 7958
 7959    fn show_character_palette(&mut self, _: &ShowCharacterPalette, cx: &mut ViewContext<Self>) {
 7960        cx.show_character_palette();
 7961    }
 7962
 7963    fn refresh_active_diagnostics(&mut self, cx: &mut ViewContext<Editor>) {
 7964        if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
 7965            let buffer = self.buffer.read(cx).snapshot(cx);
 7966            let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
 7967            let is_valid = buffer
 7968                .diagnostics_in_range::<_, usize>(active_diagnostics.primary_range.clone(), false)
 7969                .any(|entry| {
 7970                    entry.diagnostic.is_primary
 7971                        && !entry.range.is_empty()
 7972                        && entry.range.start == primary_range_start
 7973                        && entry.diagnostic.message == active_diagnostics.primary_message
 7974                });
 7975
 7976            if is_valid != active_diagnostics.is_valid {
 7977                active_diagnostics.is_valid = is_valid;
 7978                let mut new_styles = HashMap::default();
 7979                for (block_id, diagnostic) in &active_diagnostics.blocks {
 7980                    new_styles.insert(
 7981                        *block_id,
 7982                        diagnostic_block_renderer(diagnostic.clone(), is_valid),
 7983                    );
 7984                }
 7985                self.display_map
 7986                    .update(cx, |display_map, _| display_map.replace_blocks(new_styles));
 7987            }
 7988        }
 7989    }
 7990
 7991    fn activate_diagnostics(&mut self, group_id: usize, cx: &mut ViewContext<Self>) -> bool {
 7992        self.dismiss_diagnostics(cx);
 7993        self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
 7994            let buffer = self.buffer.read(cx).snapshot(cx);
 7995
 7996            let mut primary_range = None;
 7997            let mut primary_message = None;
 7998            let mut group_end = Point::zero();
 7999            let diagnostic_group = buffer
 8000                .diagnostic_group::<Point>(group_id)
 8001                .map(|entry| {
 8002                    if entry.range.end > group_end {
 8003                        group_end = entry.range.end;
 8004                    }
 8005                    if entry.diagnostic.is_primary {
 8006                        primary_range = Some(entry.range.clone());
 8007                        primary_message = Some(entry.diagnostic.message.clone());
 8008                    }
 8009                    entry
 8010                })
 8011                .collect::<Vec<_>>();
 8012            let primary_range = primary_range?;
 8013            let primary_message = primary_message?;
 8014            let primary_range =
 8015                buffer.anchor_after(primary_range.start)..buffer.anchor_before(primary_range.end);
 8016
 8017            let blocks = display_map
 8018                .insert_blocks(
 8019                    diagnostic_group.iter().map(|entry| {
 8020                        let diagnostic = entry.diagnostic.clone();
 8021                        let message_height = diagnostic.message.lines().count() as u8;
 8022                        BlockProperties {
 8023                            style: BlockStyle::Fixed,
 8024                            position: buffer.anchor_after(entry.range.start),
 8025                            height: message_height,
 8026                            render: diagnostic_block_renderer(diagnostic, true),
 8027                            disposition: BlockDisposition::Below,
 8028                        }
 8029                    }),
 8030                    cx,
 8031                )
 8032                .into_iter()
 8033                .zip(diagnostic_group.into_iter().map(|entry| entry.diagnostic))
 8034                .collect();
 8035
 8036            Some(ActiveDiagnosticGroup {
 8037                primary_range,
 8038                primary_message,
 8039                blocks,
 8040                is_valid: true,
 8041            })
 8042        });
 8043        self.active_diagnostics.is_some()
 8044    }
 8045
 8046    fn dismiss_diagnostics(&mut self, cx: &mut ViewContext<Self>) {
 8047        if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
 8048            self.display_map.update(cx, |display_map, cx| {
 8049                display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx);
 8050            });
 8051            cx.notify();
 8052        }
 8053    }
 8054
 8055    pub fn set_selections_from_remote(
 8056        &mut self,
 8057        selections: Vec<Selection<Anchor>>,
 8058        pending_selection: Option<Selection<Anchor>>,
 8059        cx: &mut ViewContext<Self>,
 8060    ) {
 8061        let old_cursor_position = self.selections.newest_anchor().head();
 8062        self.selections.change_with(cx, |s| {
 8063            s.select_anchors(selections);
 8064            if let Some(pending_selection) = pending_selection {
 8065                s.set_pending(pending_selection, SelectMode::Character);
 8066            } else {
 8067                s.clear_pending();
 8068            }
 8069        });
 8070        self.selections_did_change(false, &old_cursor_position, cx);
 8071    }
 8072
 8073    fn push_to_selection_history(&mut self) {
 8074        self.selection_history.push(SelectionHistoryEntry {
 8075            selections: self.selections.disjoint_anchors(),
 8076            select_next_state: self.select_next_state.clone(),
 8077            select_prev_state: self.select_prev_state.clone(),
 8078            add_selections_state: self.add_selections_state.clone(),
 8079        });
 8080    }
 8081
 8082    pub fn transact(
 8083        &mut self,
 8084        cx: &mut ViewContext<Self>,
 8085        update: impl FnOnce(&mut Self, &mut ViewContext<Self>),
 8086    ) -> Option<TransactionId> {
 8087        self.start_transaction_at(Instant::now(), cx);
 8088        update(self, cx);
 8089        self.end_transaction_at(Instant::now(), cx)
 8090    }
 8091
 8092    fn start_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
 8093        self.end_selection(cx);
 8094        if let Some(tx_id) = self
 8095            .buffer
 8096            .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx))
 8097        {
 8098            self.selection_history
 8099                .insert_transaction(tx_id, self.selections.disjoint_anchors());
 8100        }
 8101    }
 8102
 8103    fn end_transaction_at(
 8104        &mut self,
 8105        now: Instant,
 8106        cx: &mut ViewContext<Self>,
 8107    ) -> Option<TransactionId> {
 8108        if let Some(tx_id) = self
 8109            .buffer
 8110            .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
 8111        {
 8112            if let Some((_, end_selections)) = self.selection_history.transaction_mut(tx_id) {
 8113                *end_selections = Some(self.selections.disjoint_anchors());
 8114            } else {
 8115                error!("unexpectedly ended a transaction that wasn't started by this editor");
 8116            }
 8117
 8118            cx.emit(Event::Edited);
 8119            Some(tx_id)
 8120        } else {
 8121            None
 8122        }
 8123    }
 8124
 8125    pub fn fold(&mut self, _: &Fold, cx: &mut ViewContext<Self>) {
 8126        let mut fold_ranges = Vec::new();
 8127
 8128        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8129
 8130        let selections = self.selections.all_adjusted(cx);
 8131        for selection in selections {
 8132            let range = selection.range().sorted();
 8133            let buffer_start_row = range.start.row;
 8134
 8135            for row in (0..=range.end.row).rev() {
 8136                let fold_range = display_map.foldable_range(row);
 8137
 8138                if let Some(fold_range) = fold_range {
 8139                    if fold_range.end.row >= buffer_start_row {
 8140                        fold_ranges.push(fold_range);
 8141                        if row <= range.start.row {
 8142                            break;
 8143                        }
 8144                    }
 8145                }
 8146            }
 8147        }
 8148
 8149        self.fold_ranges(fold_ranges, true, cx);
 8150    }
 8151
 8152    pub fn fold_at(&mut self, fold_at: &FoldAt, cx: &mut ViewContext<Self>) {
 8153        let buffer_row = fold_at.buffer_row;
 8154        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8155
 8156        if let Some(fold_range) = display_map.foldable_range(buffer_row) {
 8157            let autoscroll = self
 8158                .selections
 8159                .all::<Point>(cx)
 8160                .iter()
 8161                .any(|selection| fold_range.overlaps(&selection.range()));
 8162
 8163            self.fold_ranges(std::iter::once(fold_range), autoscroll, cx);
 8164        }
 8165    }
 8166
 8167    pub fn unfold_lines(&mut self, _: &UnfoldLines, cx: &mut ViewContext<Self>) {
 8168        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8169        let buffer = &display_map.buffer_snapshot;
 8170        let selections = self.selections.all::<Point>(cx);
 8171        let ranges = selections
 8172            .iter()
 8173            .map(|s| {
 8174                let range = s.display_range(&display_map).sorted();
 8175                let mut start = range.start.to_point(&display_map);
 8176                let mut end = range.end.to_point(&display_map);
 8177                start.column = 0;
 8178                end.column = buffer.line_len(end.row);
 8179                start..end
 8180            })
 8181            .collect::<Vec<_>>();
 8182
 8183        self.unfold_ranges(ranges, true, true, cx);
 8184    }
 8185
 8186    pub fn unfold_at(&mut self, unfold_at: &UnfoldAt, cx: &mut ViewContext<Self>) {
 8187        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8188
 8189        let intersection_range = Point::new(unfold_at.buffer_row, 0)
 8190            ..Point::new(
 8191                unfold_at.buffer_row,
 8192                display_map.buffer_snapshot.line_len(unfold_at.buffer_row),
 8193            );
 8194
 8195        let autoscroll = self
 8196            .selections
 8197            .all::<Point>(cx)
 8198            .iter()
 8199            .any(|selection| selection.range().overlaps(&intersection_range));
 8200
 8201        self.unfold_ranges(std::iter::once(intersection_range), true, autoscroll, cx)
 8202    }
 8203
 8204    pub fn fold_selected_ranges(&mut self, _: &FoldSelectedRanges, cx: &mut ViewContext<Self>) {
 8205        let selections = self.selections.all::<Point>(cx);
 8206        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
 8207        let line_mode = self.selections.line_mode;
 8208        let ranges = selections.into_iter().map(|s| {
 8209            if line_mode {
 8210                let start = Point::new(s.start.row, 0);
 8211                let end = Point::new(s.end.row, display_map.buffer_snapshot.line_len(s.end.row));
 8212                start..end
 8213            } else {
 8214                s.start..s.end
 8215            }
 8216        });
 8217        self.fold_ranges(ranges, true, cx);
 8218    }
 8219
 8220    pub fn fold_ranges<T: ToOffset + Clone>(
 8221        &mut self,
 8222        ranges: impl IntoIterator<Item = Range<T>>,
 8223        auto_scroll: bool,
 8224        cx: &mut ViewContext<Self>,
 8225    ) {
 8226        let mut ranges = ranges.into_iter().peekable();
 8227        if ranges.peek().is_some() {
 8228            self.display_map.update(cx, |map, cx| map.fold(ranges, cx));
 8229
 8230            if auto_scroll {
 8231                self.request_autoscroll(Autoscroll::fit(), cx);
 8232            }
 8233
 8234            cx.notify();
 8235        }
 8236    }
 8237
 8238    pub fn unfold_ranges<T: ToOffset + Clone>(
 8239        &mut self,
 8240        ranges: impl IntoIterator<Item = Range<T>>,
 8241        inclusive: bool,
 8242        auto_scroll: bool,
 8243        cx: &mut ViewContext<Self>,
 8244    ) {
 8245        let mut ranges = ranges.into_iter().peekable();
 8246        if ranges.peek().is_some() {
 8247            self.display_map
 8248                .update(cx, |map, cx| map.unfold(ranges, inclusive, cx));
 8249            if auto_scroll {
 8250                self.request_autoscroll(Autoscroll::fit(), cx);
 8251            }
 8252
 8253            cx.notify();
 8254        }
 8255    }
 8256
 8257    pub fn gutter_hover(
 8258        &mut self,
 8259        GutterHover { hovered }: &GutterHover,
 8260        cx: &mut ViewContext<Self>,
 8261    ) {
 8262        self.gutter_hovered = *hovered;
 8263        cx.notify();
 8264    }
 8265
 8266    pub fn insert_blocks(
 8267        &mut self,
 8268        blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
 8269        autoscroll: Option<Autoscroll>,
 8270        cx: &mut ViewContext<Self>,
 8271    ) -> Vec<BlockId> {
 8272        let blocks = self
 8273            .display_map
 8274            .update(cx, |display_map, cx| display_map.insert_blocks(blocks, cx));
 8275        if let Some(autoscroll) = autoscroll {
 8276            self.request_autoscroll(autoscroll, cx);
 8277        }
 8278        blocks
 8279    }
 8280
 8281    pub fn replace_blocks(
 8282        &mut self,
 8283        blocks: HashMap<BlockId, RenderBlock>,
 8284        autoscroll: Option<Autoscroll>,
 8285        cx: &mut ViewContext<Self>,
 8286    ) {
 8287        self.display_map
 8288            .update(cx, |display_map, _| display_map.replace_blocks(blocks));
 8289        if let Some(autoscroll) = autoscroll {
 8290            self.request_autoscroll(autoscroll, cx);
 8291        }
 8292    }
 8293
 8294    pub fn remove_blocks(
 8295        &mut self,
 8296        block_ids: HashSet<BlockId>,
 8297        autoscroll: Option<Autoscroll>,
 8298        cx: &mut ViewContext<Self>,
 8299    ) {
 8300        self.display_map.update(cx, |display_map, cx| {
 8301            display_map.remove_blocks(block_ids, cx)
 8302        });
 8303        if let Some(autoscroll) = autoscroll {
 8304            self.request_autoscroll(autoscroll, cx);
 8305        }
 8306    }
 8307
 8308    pub fn longest_row(&self, cx: &mut AppContext) -> u32 {
 8309        self.display_map
 8310            .update(cx, |map, cx| map.snapshot(cx))
 8311            .longest_row()
 8312    }
 8313
 8314    pub fn max_point(&self, cx: &mut AppContext) -> DisplayPoint {
 8315        self.display_map
 8316            .update(cx, |map, cx| map.snapshot(cx))
 8317            .max_point()
 8318    }
 8319
 8320    pub fn text(&self, cx: &AppContext) -> String {
 8321        self.buffer.read(cx).read(cx).text()
 8322    }
 8323
 8324    pub fn set_text(&mut self, text: impl Into<Arc<str>>, cx: &mut ViewContext<Self>) {
 8325        self.transact(cx, |this, cx| {
 8326            this.buffer
 8327                .read(cx)
 8328                .as_singleton()
 8329                .expect("you can only call set_text on editors for singleton buffers")
 8330                .update(cx, |buffer, cx| buffer.set_text(text, cx));
 8331        });
 8332    }
 8333
 8334    pub fn display_text(&self, cx: &mut AppContext) -> String {
 8335        self.display_map
 8336            .update(cx, |map, cx| map.snapshot(cx))
 8337            .text()
 8338    }
 8339
 8340    pub fn wrap_guides(&self, cx: &AppContext) -> SmallVec<[(usize, bool); 2]> {
 8341        let mut wrap_guides = smallvec::smallvec![];
 8342
 8343        if self.show_wrap_guides == Some(false) {
 8344            return wrap_guides;
 8345        }
 8346
 8347        let settings = self.buffer.read(cx).settings_at(0, cx);
 8348        if settings.show_wrap_guides {
 8349            if let SoftWrap::Column(soft_wrap) = self.soft_wrap_mode(cx) {
 8350                wrap_guides.push((soft_wrap as usize, true));
 8351            }
 8352            wrap_guides.extend(settings.wrap_guides.iter().map(|guide| (*guide, false)))
 8353        }
 8354
 8355        wrap_guides
 8356    }
 8357
 8358    pub fn soft_wrap_mode(&self, cx: &AppContext) -> SoftWrap {
 8359        let settings = self.buffer.read(cx).settings_at(0, cx);
 8360        let mode = self
 8361            .soft_wrap_mode_override
 8362            .unwrap_or_else(|| settings.soft_wrap);
 8363        match mode {
 8364            language_settings::SoftWrap::None => SoftWrap::None,
 8365            language_settings::SoftWrap::EditorWidth => SoftWrap::EditorWidth,
 8366            language_settings::SoftWrap::PreferredLineLength => {
 8367                SoftWrap::Column(settings.preferred_line_length)
 8368            }
 8369        }
 8370    }
 8371
 8372    pub fn set_soft_wrap_mode(
 8373        &mut self,
 8374        mode: language_settings::SoftWrap,
 8375        cx: &mut ViewContext<Self>,
 8376    ) {
 8377        self.soft_wrap_mode_override = Some(mode);
 8378        cx.notify();
 8379    }
 8380
 8381    pub fn set_wrap_width(&self, width: Option<f32>, cx: &mut AppContext) -> bool {
 8382        self.display_map
 8383            .update(cx, |map, cx| map.set_wrap_width(width, cx))
 8384    }
 8385
 8386    pub fn toggle_soft_wrap(&mut self, _: &ToggleSoftWrap, cx: &mut ViewContext<Self>) {
 8387        if self.soft_wrap_mode_override.is_some() {
 8388            self.soft_wrap_mode_override.take();
 8389        } else {
 8390            let soft_wrap = match self.soft_wrap_mode(cx) {
 8391                SoftWrap::None => language_settings::SoftWrap::EditorWidth,
 8392                SoftWrap::EditorWidth | SoftWrap::Column(_) => language_settings::SoftWrap::None,
 8393            };
 8394            self.soft_wrap_mode_override = Some(soft_wrap);
 8395        }
 8396        cx.notify();
 8397    }
 8398
 8399    pub fn set_show_gutter(&mut self, show_gutter: bool, cx: &mut ViewContext<Self>) {
 8400        self.show_gutter = show_gutter;
 8401        cx.notify();
 8402    }
 8403
 8404    pub fn set_show_wrap_guides(&mut self, show_gutter: bool, cx: &mut ViewContext<Self>) {
 8405        self.show_wrap_guides = Some(show_gutter);
 8406        cx.notify();
 8407    }
 8408
 8409    pub fn reveal_in_finder(&mut self, _: &RevealInFinder, cx: &mut ViewContext<Self>) {
 8410        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
 8411            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
 8412                cx.reveal_path(&file.abs_path(cx));
 8413            }
 8414        }
 8415    }
 8416
 8417    pub fn copy_path(&mut self, _: &CopyPath, cx: &mut ViewContext<Self>) {
 8418        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
 8419            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
 8420                if let Some(path) = file.abs_path(cx).to_str() {
 8421                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
 8422                }
 8423            }
 8424        }
 8425    }
 8426
 8427    pub fn copy_relative_path(&mut self, _: &CopyRelativePath, cx: &mut ViewContext<Self>) {
 8428        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
 8429            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
 8430                if let Some(path) = file.path().to_str() {
 8431                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
 8432                }
 8433            }
 8434        }
 8435    }
 8436
 8437    pub fn highlight_rows(&mut self, rows: Option<Range<u32>>) {
 8438        self.highlighted_rows = rows;
 8439    }
 8440
 8441    pub fn highlighted_rows(&self) -> Option<Range<u32>> {
 8442        self.highlighted_rows.clone()
 8443    }
 8444
 8445    pub fn highlight_background<T: 'static>(
 8446        &mut self,
 8447        ranges: Vec<Range<Anchor>>,
 8448        color_fetcher: fn(&Theme) -> Color,
 8449        cx: &mut ViewContext<Self>,
 8450    ) {
 8451        self.background_highlights
 8452            .insert(TypeId::of::<T>(), (color_fetcher, ranges));
 8453        cx.notify();
 8454    }
 8455
 8456    pub fn highlight_inlay_background<T: 'static>(
 8457        &mut self,
 8458        ranges: Vec<InlayHighlight>,
 8459        color_fetcher: fn(&Theme) -> Color,
 8460        cx: &mut ViewContext<Self>,
 8461    ) {
 8462        // TODO: no actual highlights happen for inlays currently, find a way to do that
 8463        self.inlay_background_highlights
 8464            .insert(Some(TypeId::of::<T>()), (color_fetcher, ranges));
 8465        cx.notify();
 8466    }
 8467
 8468    pub fn clear_background_highlights<T: 'static>(
 8469        &mut self,
 8470        cx: &mut ViewContext<Self>,
 8471    ) -> Option<BackgroundHighlight> {
 8472        let text_highlights = self.background_highlights.remove(&TypeId::of::<T>());
 8473        let inlay_highlights = self
 8474            .inlay_background_highlights
 8475            .remove(&Some(TypeId::of::<T>()));
 8476        if text_highlights.is_some() || inlay_highlights.is_some() {
 8477            cx.notify();
 8478        }
 8479        text_highlights
 8480    }
 8481
 8482    #[cfg(feature = "test-support")]
 8483    pub fn all_text_background_highlights(
 8484        &mut self,
 8485        cx: &mut ViewContext<Self>,
 8486    ) -> Vec<(Range<DisplayPoint>, Color)> {
 8487        let snapshot = self.snapshot(cx);
 8488        let buffer = &snapshot.buffer_snapshot;
 8489        let start = buffer.anchor_before(0);
 8490        let end = buffer.anchor_after(buffer.len());
 8491        let theme = theme::current(cx);
 8492        self.background_highlights_in_range(start..end, &snapshot, theme.as_ref())
 8493    }
 8494
 8495    fn document_highlights_for_position<'a>(
 8496        &'a self,
 8497        position: Anchor,
 8498        buffer: &'a MultiBufferSnapshot,
 8499    ) -> impl 'a + Iterator<Item = &Range<Anchor>> {
 8500        let read_highlights = self
 8501            .background_highlights
 8502            .get(&TypeId::of::<DocumentHighlightRead>())
 8503            .map(|h| &h.1);
 8504        let write_highlights = self
 8505            .background_highlights
 8506            .get(&TypeId::of::<DocumentHighlightWrite>())
 8507            .map(|h| &h.1);
 8508        let left_position = position.bias_left(buffer);
 8509        let right_position = position.bias_right(buffer);
 8510        read_highlights
 8511            .into_iter()
 8512            .chain(write_highlights)
 8513            .flat_map(move |ranges| {
 8514                let start_ix = match ranges.binary_search_by(|probe| {
 8515                    let cmp = probe.end.cmp(&left_position, buffer);
 8516                    if cmp.is_ge() {
 8517                        Ordering::Greater
 8518                    } else {
 8519                        Ordering::Less
 8520                    }
 8521                }) {
 8522                    Ok(i) | Err(i) => i,
 8523                };
 8524
 8525                let right_position = right_position.clone();
 8526                ranges[start_ix..]
 8527                    .iter()
 8528                    .take_while(move |range| range.start.cmp(&right_position, buffer).is_le())
 8529            })
 8530    }
 8531
 8532    pub fn background_highlights_in_range(
 8533        &self,
 8534        search_range: Range<Anchor>,
 8535        display_snapshot: &DisplaySnapshot,
 8536        theme: &Theme,
 8537    ) -> Vec<(Range<DisplayPoint>, Color)> {
 8538        let mut results = Vec::new();
 8539        for (color_fetcher, ranges) in self.background_highlights.values() {
 8540            let color = color_fetcher(theme);
 8541            let start_ix = match ranges.binary_search_by(|probe| {
 8542                let cmp = probe
 8543                    .end
 8544                    .cmp(&search_range.start, &display_snapshot.buffer_snapshot);
 8545                if cmp.is_gt() {
 8546                    Ordering::Greater
 8547                } else {
 8548                    Ordering::Less
 8549                }
 8550            }) {
 8551                Ok(i) | Err(i) => i,
 8552            };
 8553            for range in &ranges[start_ix..] {
 8554                if range
 8555                    .start
 8556                    .cmp(&search_range.end, &display_snapshot.buffer_snapshot)
 8557                    .is_ge()
 8558                {
 8559                    break;
 8560                }
 8561
 8562                let start = range.start.to_display_point(&display_snapshot);
 8563                let end = range.end.to_display_point(&display_snapshot);
 8564                results.push((start..end, color))
 8565            }
 8566        }
 8567        results
 8568    }
 8569
 8570    pub fn background_highlight_row_ranges<T: 'static>(
 8571        &self,
 8572        search_range: Range<Anchor>,
 8573        display_snapshot: &DisplaySnapshot,
 8574        count: usize,
 8575    ) -> Vec<RangeInclusive<DisplayPoint>> {
 8576        let mut results = Vec::new();
 8577        let Some((_, ranges)) = self.background_highlights.get(&TypeId::of::<T>()) else {
 8578            return vec![];
 8579        };
 8580
 8581        let start_ix = match ranges.binary_search_by(|probe| {
 8582            let cmp = probe
 8583                .end
 8584                .cmp(&search_range.start, &display_snapshot.buffer_snapshot);
 8585            if cmp.is_gt() {
 8586                Ordering::Greater
 8587            } else {
 8588                Ordering::Less
 8589            }
 8590        }) {
 8591            Ok(i) | Err(i) => i,
 8592        };
 8593        let mut push_region = |start: Option<Point>, end: Option<Point>| {
 8594            if let (Some(start_display), Some(end_display)) = (start, end) {
 8595                results.push(
 8596                    start_display.to_display_point(display_snapshot)
 8597                        ..=end_display.to_display_point(display_snapshot),
 8598                );
 8599            }
 8600        };
 8601        let mut start_row: Option<Point> = None;
 8602        let mut end_row: Option<Point> = None;
 8603        if ranges.len() > count {
 8604            return Vec::new();
 8605        }
 8606        for range in &ranges[start_ix..] {
 8607            if range
 8608                .start
 8609                .cmp(&search_range.end, &display_snapshot.buffer_snapshot)
 8610                .is_ge()
 8611            {
 8612                break;
 8613            }
 8614            let end = range.end.to_point(&display_snapshot.buffer_snapshot);
 8615            if let Some(current_row) = &end_row {
 8616                if end.row == current_row.row {
 8617                    continue;
 8618                }
 8619            }
 8620            let start = range.start.to_point(&display_snapshot.buffer_snapshot);
 8621            if start_row.is_none() {
 8622                assert_eq!(end_row, None);
 8623                start_row = Some(start);
 8624                end_row = Some(end);
 8625                continue;
 8626            }
 8627            if let Some(current_end) = end_row.as_mut() {
 8628                if start.row > current_end.row + 1 {
 8629                    push_region(start_row, end_row);
 8630                    start_row = Some(start);
 8631                    end_row = Some(end);
 8632                } else {
 8633                    // Merge two hunks.
 8634                    *current_end = end;
 8635                }
 8636            } else {
 8637                unreachable!();
 8638            }
 8639        }
 8640        // We might still have a hunk that was not rendered (if there was a search hit on the last line)
 8641        push_region(start_row, end_row);
 8642        results
 8643    }
 8644
 8645    pub fn highlight_text<T: 'static>(
 8646        &mut self,
 8647        ranges: Vec<Range<Anchor>>,
 8648        style: HighlightStyle,
 8649        cx: &mut ViewContext<Self>,
 8650    ) {
 8651        self.display_map.update(cx, |map, _| {
 8652            map.highlight_text(TypeId::of::<T>(), ranges, style)
 8653        });
 8654        cx.notify();
 8655    }
 8656
 8657    pub fn highlight_inlays<T: 'static>(
 8658        &mut self,
 8659        highlights: Vec<InlayHighlight>,
 8660        style: HighlightStyle,
 8661        cx: &mut ViewContext<Self>,
 8662    ) {
 8663        self.display_map.update(cx, |map, _| {
 8664            map.highlight_inlays(TypeId::of::<T>(), highlights, style)
 8665        });
 8666        cx.notify();
 8667    }
 8668
 8669    pub fn text_highlights<'a, T: 'static>(
 8670        &'a self,
 8671        cx: &'a AppContext,
 8672    ) -> Option<(HighlightStyle, &'a [Range<Anchor>])> {
 8673        self.display_map.read(cx).text_highlights(TypeId::of::<T>())
 8674    }
 8675
 8676    pub fn clear_highlights<T: 'static>(&mut self, cx: &mut ViewContext<Self>) {
 8677        let cleared = self
 8678            .display_map
 8679            .update(cx, |map, _| map.clear_highlights(TypeId::of::<T>()));
 8680        if cleared {
 8681            cx.notify();
 8682        }
 8683    }
 8684
 8685    pub fn show_local_cursors(&self, cx: &AppContext) -> bool {
 8686        self.blink_manager.read(cx).visible() && self.focused
 8687    }
 8688
 8689    fn on_buffer_changed(&mut self, _: ModelHandle<MultiBuffer>, cx: &mut ViewContext<Self>) {
 8690        cx.notify();
 8691    }
 8692
 8693    fn on_buffer_event(
 8694        &mut self,
 8695        multibuffer: ModelHandle<MultiBuffer>,
 8696        event: &multi_buffer::Event,
 8697        cx: &mut ViewContext<Self>,
 8698    ) {
 8699        match event {
 8700            multi_buffer::Event::Edited {
 8701                sigleton_buffer_edited,
 8702            } => {
 8703                self.refresh_active_diagnostics(cx);
 8704                self.refresh_code_actions(cx);
 8705                if self.has_active_copilot_suggestion(cx) {
 8706                    self.update_visible_copilot_suggestion(cx);
 8707                }
 8708                cx.emit(Event::BufferEdited);
 8709
 8710                if *sigleton_buffer_edited {
 8711                    if let Some(project) = &self.project {
 8712                        let project = project.read(cx);
 8713                        let languages_affected = multibuffer
 8714                            .read(cx)
 8715                            .all_buffers()
 8716                            .into_iter()
 8717                            .filter_map(|buffer| {
 8718                                let buffer = buffer.read(cx);
 8719                                let language = buffer.language()?;
 8720                                if project.is_local()
 8721                                    && project.language_servers_for_buffer(buffer, cx).count() == 0
 8722                                {
 8723                                    None
 8724                                } else {
 8725                                    Some(language)
 8726                                }
 8727                            })
 8728                            .cloned()
 8729                            .collect::<HashSet<_>>();
 8730                        if !languages_affected.is_empty() {
 8731                            self.refresh_inlay_hints(
 8732                                InlayHintRefreshReason::BufferEdited(languages_affected),
 8733                                cx,
 8734                            );
 8735                        }
 8736                    }
 8737                }
 8738            }
 8739            multi_buffer::Event::ExcerptsAdded {
 8740                buffer,
 8741                predecessor,
 8742                excerpts,
 8743            } => {
 8744                cx.emit(Event::ExcerptsAdded {
 8745                    buffer: buffer.clone(),
 8746                    predecessor: *predecessor,
 8747                    excerpts: excerpts.clone(),
 8748                });
 8749                self.refresh_inlay_hints(InlayHintRefreshReason::NewLinesShown, cx);
 8750            }
 8751            multi_buffer::Event::ExcerptsRemoved { ids } => {
 8752                self.refresh_inlay_hints(InlayHintRefreshReason::ExcerptsRemoved(ids.clone()), cx);
 8753                cx.emit(Event::ExcerptsRemoved { ids: ids.clone() })
 8754            }
 8755            multi_buffer::Event::Reparsed => cx.emit(Event::Reparsed),
 8756            multi_buffer::Event::DirtyChanged => cx.emit(Event::DirtyChanged),
 8757            multi_buffer::Event::Saved => cx.emit(Event::Saved),
 8758            multi_buffer::Event::FileHandleChanged => cx.emit(Event::TitleChanged),
 8759            multi_buffer::Event::Reloaded => cx.emit(Event::TitleChanged),
 8760            multi_buffer::Event::DiffBaseChanged => cx.emit(Event::DiffBaseChanged),
 8761            multi_buffer::Event::Closed => cx.emit(Event::Closed),
 8762            multi_buffer::Event::DiagnosticsUpdated => {
 8763                self.refresh_active_diagnostics(cx);
 8764            }
 8765            _ => {}
 8766        };
 8767    }
 8768
 8769    fn on_display_map_changed(&mut self, _: ModelHandle<DisplayMap>, cx: &mut ViewContext<Self>) {
 8770        cx.notify();
 8771    }
 8772
 8773    fn settings_changed(&mut self, cx: &mut ViewContext<Self>) {
 8774        self.refresh_copilot_suggestions(true, cx);
 8775        self.refresh_inlay_hints(
 8776            InlayHintRefreshReason::SettingsChange(inlay_hint_settings(
 8777                self.selections.newest_anchor().head(),
 8778                &self.buffer.read(cx).snapshot(cx),
 8779                cx,
 8780            )),
 8781            cx,
 8782        );
 8783    }
 8784
 8785    pub fn set_searchable(&mut self, searchable: bool) {
 8786        self.searchable = searchable;
 8787    }
 8788
 8789    pub fn searchable(&self) -> bool {
 8790        self.searchable
 8791    }
 8792
 8793    fn open_excerpts(workspace: &mut Workspace, _: &OpenExcerpts, cx: &mut ViewContext<Workspace>) {
 8794        let active_item = workspace.active_item(cx);
 8795        let editor_handle = if let Some(editor) = active_item
 8796            .as_ref()
 8797            .and_then(|item| item.act_as::<Self>(cx))
 8798        {
 8799            editor
 8800        } else {
 8801            cx.propagate_action();
 8802            return;
 8803        };
 8804
 8805        let editor = editor_handle.read(cx);
 8806        let buffer = editor.buffer.read(cx);
 8807        if buffer.is_singleton() {
 8808            cx.propagate_action();
 8809            return;
 8810        }
 8811
 8812        let mut new_selections_by_buffer = HashMap::default();
 8813        for selection in editor.selections.all::<usize>(cx) {
 8814            for (buffer, mut range, _) in
 8815                buffer.range_to_buffer_ranges(selection.start..selection.end, cx)
 8816            {
 8817                if selection.reversed {
 8818                    mem::swap(&mut range.start, &mut range.end);
 8819                }
 8820                new_selections_by_buffer
 8821                    .entry(buffer)
 8822                    .or_insert(Vec::new())
 8823                    .push(range)
 8824            }
 8825        }
 8826
 8827        editor_handle.update(cx, |editor, cx| {
 8828            editor.push_to_nav_history(editor.selections.newest_anchor().head(), None, cx);
 8829        });
 8830        let pane = workspace.active_pane().clone();
 8831        pane.update(cx, |pane, _| pane.disable_history());
 8832
 8833        // We defer the pane interaction because we ourselves are a workspace item
 8834        // and activating a new item causes the pane to call a method on us reentrantly,
 8835        // which panics if we're on the stack.
 8836        cx.defer(move |workspace, cx| {
 8837            for (buffer, ranges) in new_selections_by_buffer.into_iter() {
 8838                let editor = workspace.open_project_item::<Self>(buffer, cx);
 8839                editor.update(cx, |editor, cx| {
 8840                    editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
 8841                        s.select_ranges(ranges);
 8842                    });
 8843                });
 8844            }
 8845
 8846            pane.update(cx, |pane, _| pane.enable_history());
 8847        });
 8848    }
 8849
 8850    fn jump(
 8851        workspace: &mut Workspace,
 8852        path: ProjectPath,
 8853        position: Point,
 8854        anchor: language::Anchor,
 8855        cx: &mut ViewContext<Workspace>,
 8856    ) {
 8857        let editor = workspace.open_path(path, None, true, cx);
 8858        cx.spawn(|_, mut cx| async move {
 8859            let editor = editor
 8860                .await?
 8861                .downcast::<Editor>()
 8862                .ok_or_else(|| anyhow!("opened item was not an editor"))?
 8863                .downgrade();
 8864            editor.update(&mut cx, |editor, cx| {
 8865                let buffer = editor
 8866                    .buffer()
 8867                    .read(cx)
 8868                    .as_singleton()
 8869                    .ok_or_else(|| anyhow!("cannot jump in a multi-buffer"))?;
 8870                let buffer = buffer.read(cx);
 8871                let cursor = if buffer.can_resolve(&anchor) {
 8872                    language::ToPoint::to_point(&anchor, buffer)
 8873                } else {
 8874                    buffer.clip_point(position, Bias::Left)
 8875                };
 8876
 8877                let nav_history = editor.nav_history.take();
 8878                editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
 8879                    s.select_ranges([cursor..cursor]);
 8880                });
 8881                editor.nav_history = nav_history;
 8882
 8883                anyhow::Ok(())
 8884            })??;
 8885
 8886            anyhow::Ok(())
 8887        })
 8888        .detach_and_log_err(cx);
 8889    }
 8890
 8891    fn marked_text_ranges(&self, cx: &AppContext) -> Option<Vec<Range<OffsetUtf16>>> {
 8892        let snapshot = self.buffer.read(cx).read(cx);
 8893        let (_, ranges) = self.text_highlights::<InputComposition>(cx)?;
 8894        Some(
 8895            ranges
 8896                .iter()
 8897                .map(move |range| {
 8898                    range.start.to_offset_utf16(&snapshot)..range.end.to_offset_utf16(&snapshot)
 8899                })
 8900                .collect(),
 8901        )
 8902    }
 8903
 8904    fn selection_replacement_ranges(
 8905        &self,
 8906        range: Range<OffsetUtf16>,
 8907        cx: &AppContext,
 8908    ) -> Vec<Range<OffsetUtf16>> {
 8909        let selections = self.selections.all::<OffsetUtf16>(cx);
 8910        let newest_selection = selections
 8911            .iter()
 8912            .max_by_key(|selection| selection.id)
 8913            .unwrap();
 8914        let start_delta = range.start.0 as isize - newest_selection.start.0 as isize;
 8915        let end_delta = range.end.0 as isize - newest_selection.end.0 as isize;
 8916        let snapshot = self.buffer.read(cx).read(cx);
 8917        selections
 8918            .into_iter()
 8919            .map(|mut selection| {
 8920                selection.start.0 =
 8921                    (selection.start.0 as isize).saturating_add(start_delta) as usize;
 8922                selection.end.0 = (selection.end.0 as isize).saturating_add(end_delta) as usize;
 8923                snapshot.clip_offset_utf16(selection.start, Bias::Left)
 8924                    ..snapshot.clip_offset_utf16(selection.end, Bias::Right)
 8925            })
 8926            .collect()
 8927    }
 8928
 8929    fn report_copilot_event(
 8930        &self,
 8931        suggestion_id: Option<String>,
 8932        suggestion_accepted: bool,
 8933        cx: &AppContext,
 8934    ) {
 8935        let Some(project) = &self.project else { return };
 8936
 8937        // If None, we are either getting suggestions in a new, unsaved file, or in a file without an extension
 8938        let file_extension = self
 8939            .buffer
 8940            .read(cx)
 8941            .as_singleton()
 8942            .and_then(|b| b.read(cx).file())
 8943            .and_then(|file| Path::new(file.file_name(cx)).extension())
 8944            .and_then(|e| e.to_str())
 8945            .map(|a| a.to_string());
 8946
 8947        let telemetry = project.read(cx).client().telemetry().clone();
 8948        let telemetry_settings = *settings::get::<TelemetrySettings>(cx);
 8949
 8950        let event = ClickhouseEvent::Copilot {
 8951            suggestion_id,
 8952            suggestion_accepted,
 8953            file_extension,
 8954        };
 8955        telemetry.report_clickhouse_event(event, telemetry_settings);
 8956    }
 8957
 8958    #[cfg(any(test, feature = "test-support"))]
 8959    fn report_editor_event(
 8960        &self,
 8961        _operation: &'static str,
 8962        _file_extension: Option<String>,
 8963        _cx: &AppContext,
 8964    ) {
 8965    }
 8966
 8967    #[cfg(not(any(test, feature = "test-support")))]
 8968    fn report_editor_event(
 8969        &self,
 8970        operation: &'static str,
 8971        file_extension: Option<String>,
 8972        cx: &AppContext,
 8973    ) {
 8974        let Some(project) = &self.project else { return };
 8975
 8976        // If None, we are in a file without an extension
 8977        let file = self
 8978            .buffer
 8979            .read(cx)
 8980            .as_singleton()
 8981            .and_then(|b| b.read(cx).file());
 8982        let file_extension = file_extension.or(file
 8983            .as_ref()
 8984            .and_then(|file| Path::new(file.file_name(cx)).extension())
 8985            .and_then(|e| e.to_str())
 8986            .map(|a| a.to_string()));
 8987
 8988        let vim_mode = cx
 8989            .global::<SettingsStore>()
 8990            .raw_user_settings()
 8991            .get("vim_mode")
 8992            == Some(&serde_json::Value::Bool(true));
 8993        let telemetry_settings = *settings::get::<TelemetrySettings>(cx);
 8994        let copilot_enabled = all_language_settings(file, cx).copilot_enabled(None, None);
 8995        let copilot_enabled_for_language = self
 8996            .buffer
 8997            .read(cx)
 8998            .settings_at(0, cx)
 8999            .show_copilot_suggestions;
 9000
 9001        let telemetry = project.read(cx).client().telemetry().clone();
 9002        let event = ClickhouseEvent::Editor {
 9003            file_extension,
 9004            vim_mode,
 9005            operation,
 9006            copilot_enabled,
 9007            copilot_enabled_for_language,
 9008        };
 9009        telemetry.report_clickhouse_event(event, telemetry_settings)
 9010    }
 9011
 9012    /// Copy the highlighted chunks to the clipboard as JSON. The format is an array of lines,
 9013    /// with each line being an array of {text, highlight} objects.
 9014    fn copy_highlight_json(&mut self, _: &CopyHighlightJson, cx: &mut ViewContext<Self>) {
 9015        let Some(buffer) = self.buffer.read(cx).as_singleton() else {
 9016            return;
 9017        };
 9018
 9019        #[derive(Serialize)]
 9020        struct Chunk<'a> {
 9021            text: String,
 9022            highlight: Option<&'a str>,
 9023        }
 9024
 9025        let snapshot = buffer.read(cx).snapshot();
 9026        let range = self
 9027            .selected_text_range(cx)
 9028            .and_then(|selected_range| {
 9029                if selected_range.is_empty() {
 9030                    None
 9031                } else {
 9032                    Some(selected_range)
 9033                }
 9034            })
 9035            .unwrap_or_else(|| 0..snapshot.len());
 9036
 9037        let chunks = snapshot.chunks(range, true);
 9038        let mut lines = Vec::new();
 9039        let mut line: VecDeque<Chunk> = VecDeque::new();
 9040
 9041        let theme = &theme::current(cx).editor.syntax;
 9042
 9043        for chunk in chunks {
 9044            let highlight = chunk.syntax_highlight_id.and_then(|id| id.name(theme));
 9045            let mut chunk_lines = chunk.text.split("\n").peekable();
 9046            while let Some(text) = chunk_lines.next() {
 9047                let mut merged_with_last_token = false;
 9048                if let Some(last_token) = line.back_mut() {
 9049                    if last_token.highlight == highlight {
 9050                        last_token.text.push_str(text);
 9051                        merged_with_last_token = true;
 9052                    }
 9053                }
 9054
 9055                if !merged_with_last_token {
 9056                    line.push_back(Chunk {
 9057                        text: text.into(),
 9058                        highlight,
 9059                    });
 9060                }
 9061
 9062                if chunk_lines.peek().is_some() {
 9063                    if line.len() > 1 && line.front().unwrap().text.is_empty() {
 9064                        line.pop_front();
 9065                    }
 9066                    if line.len() > 1 && line.back().unwrap().text.is_empty() {
 9067                        line.pop_back();
 9068                    }
 9069
 9070                    lines.push(mem::take(&mut line));
 9071                }
 9072            }
 9073        }
 9074
 9075        let Some(lines) = serde_json::to_string_pretty(&lines).log_err() else {
 9076            return;
 9077        };
 9078        cx.write_to_clipboard(ClipboardItem::new(lines));
 9079    }
 9080
 9081    pub fn inlay_hint_cache(&self) -> &InlayHintCache {
 9082        &self.inlay_hint_cache
 9083    }
 9084
 9085    pub fn replay_insert_event(
 9086        &mut self,
 9087        text: &str,
 9088        relative_utf16_range: Option<Range<isize>>,
 9089        cx: &mut ViewContext<Self>,
 9090    ) {
 9091        if !self.input_enabled {
 9092            cx.emit(Event::InputIgnored { text: text.into() });
 9093            return;
 9094        }
 9095        if let Some(relative_utf16_range) = relative_utf16_range {
 9096            let selections = self.selections.all::<OffsetUtf16>(cx);
 9097            self.change_selections(None, cx, |s| {
 9098                let new_ranges = selections.into_iter().map(|range| {
 9099                    let start = OffsetUtf16(
 9100                        range
 9101                            .head()
 9102                            .0
 9103                            .saturating_add_signed(relative_utf16_range.start),
 9104                    );
 9105                    let end = OffsetUtf16(
 9106                        range
 9107                            .head()
 9108                            .0
 9109                            .saturating_add_signed(relative_utf16_range.end),
 9110                    );
 9111                    start..end
 9112                });
 9113                s.select_ranges(new_ranges);
 9114            });
 9115        }
 9116
 9117        self.handle_input(text, cx);
 9118    }
 9119
 9120    pub fn supports_inlay_hints(&self, cx: &AppContext) -> bool {
 9121        let Some(project) = self.project.as_ref() else {
 9122            return false;
 9123        };
 9124        let project = project.read(cx);
 9125
 9126        let mut supports = false;
 9127        self.buffer().read(cx).for_each_buffer(|buffer| {
 9128            if !supports {
 9129                supports = project
 9130                    .language_servers_for_buffer(buffer.read(cx), cx)
 9131                    .any(
 9132                        |(_, server)| match server.capabilities().inlay_hint_provider {
 9133                            Some(lsp::OneOf::Left(enabled)) => enabled,
 9134                            Some(lsp::OneOf::Right(_)) => true,
 9135                            None => false,
 9136                        },
 9137                    )
 9138            }
 9139        });
 9140        supports
 9141    }
 9142}
 9143
 9144pub trait CollaborationHub {
 9145    fn collaborators<'a>(&self, cx: &'a AppContext) -> &'a HashMap<PeerId, Collaborator>;
 9146    fn user_participant_indices<'a>(
 9147        &self,
 9148        cx: &'a AppContext,
 9149    ) -> &'a HashMap<u64, ParticipantIndex>;
 9150}
 9151
 9152impl CollaborationHub for ModelHandle<Project> {
 9153    fn collaborators<'a>(&self, cx: &'a AppContext) -> &'a HashMap<PeerId, Collaborator> {
 9154        self.read(cx).collaborators()
 9155    }
 9156
 9157    fn user_participant_indices<'a>(
 9158        &self,
 9159        cx: &'a AppContext,
 9160    ) -> &'a HashMap<u64, ParticipantIndex> {
 9161        self.read(cx).user_store().read(cx).participant_indices()
 9162    }
 9163}
 9164
 9165fn inlay_hint_settings(
 9166    location: Anchor,
 9167    snapshot: &MultiBufferSnapshot,
 9168    cx: &mut ViewContext<'_, '_, Editor>,
 9169) -> InlayHintSettings {
 9170    let file = snapshot.file_at(location);
 9171    let language = snapshot.language_at(location);
 9172    let settings = all_language_settings(file, cx);
 9173    settings
 9174        .language(language.map(|l| l.name()).as_deref())
 9175        .inlay_hints
 9176}
 9177
 9178fn consume_contiguous_rows(
 9179    contiguous_row_selections: &mut Vec<Selection<Point>>,
 9180    selection: &Selection<Point>,
 9181    display_map: &DisplaySnapshot,
 9182    selections: &mut std::iter::Peekable<std::slice::Iter<Selection<Point>>>,
 9183) -> (u32, u32) {
 9184    contiguous_row_selections.push(selection.clone());
 9185    let start_row = selection.start.row;
 9186    let mut end_row = ending_row(selection, display_map);
 9187
 9188    while let Some(next_selection) = selections.peek() {
 9189        if next_selection.start.row <= end_row {
 9190            end_row = ending_row(next_selection, display_map);
 9191            contiguous_row_selections.push(selections.next().unwrap().clone());
 9192        } else {
 9193            break;
 9194        }
 9195    }
 9196    (start_row, end_row)
 9197}
 9198
 9199fn ending_row(next_selection: &Selection<Point>, display_map: &DisplaySnapshot) -> u32 {
 9200    if next_selection.end.column > 0 || next_selection.is_empty() {
 9201        display_map.next_line_boundary(next_selection.end).0.row + 1
 9202    } else {
 9203        next_selection.end.row
 9204    }
 9205}
 9206
 9207impl EditorSnapshot {
 9208    pub fn remote_selections_in_range<'a>(
 9209        &'a self,
 9210        range: &'a Range<Anchor>,
 9211        collaboration_hub: &dyn CollaborationHub,
 9212        cx: &'a AppContext,
 9213    ) -> impl 'a + Iterator<Item = RemoteSelection> {
 9214        let participant_indices = collaboration_hub.user_participant_indices(cx);
 9215        let collaborators_by_peer_id = collaboration_hub.collaborators(cx);
 9216        let collaborators_by_replica_id = collaborators_by_peer_id
 9217            .iter()
 9218            .map(|(_, collaborator)| (collaborator.replica_id, collaborator))
 9219            .collect::<HashMap<_, _>>();
 9220        self.buffer_snapshot
 9221            .remote_selections_in_range(range)
 9222            .filter_map(move |(replica_id, line_mode, cursor_shape, selection)| {
 9223                let collaborator = collaborators_by_replica_id.get(&replica_id)?;
 9224                let participant_index = participant_indices.get(&collaborator.user_id).copied();
 9225                Some(RemoteSelection {
 9226                    replica_id,
 9227                    selection,
 9228                    cursor_shape,
 9229                    line_mode,
 9230                    participant_index,
 9231                    peer_id: collaborator.peer_id,
 9232                })
 9233            })
 9234    }
 9235
 9236    pub fn language_at<T: ToOffset>(&self, position: T) -> Option<&Arc<Language>> {
 9237        self.display_snapshot.buffer_snapshot.language_at(position)
 9238    }
 9239
 9240    pub fn is_focused(&self) -> bool {
 9241        self.is_focused
 9242    }
 9243
 9244    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
 9245        self.placeholder_text.as_ref()
 9246    }
 9247
 9248    pub fn scroll_position(&self) -> Vector2F {
 9249        self.scroll_anchor.scroll_position(&self.display_snapshot)
 9250    }
 9251}
 9252
 9253impl Deref for EditorSnapshot {
 9254    type Target = DisplaySnapshot;
 9255
 9256    fn deref(&self) -> &Self::Target {
 9257        &self.display_snapshot
 9258    }
 9259}
 9260
 9261#[derive(Clone, Debug, PartialEq, Eq)]
 9262pub enum Event {
 9263    InputIgnored {
 9264        text: Arc<str>,
 9265    },
 9266    InputHandled {
 9267        utf16_range_to_replace: Option<Range<isize>>,
 9268        text: Arc<str>,
 9269    },
 9270    ExcerptsAdded {
 9271        buffer: ModelHandle<Buffer>,
 9272        predecessor: ExcerptId,
 9273        excerpts: Vec<(ExcerptId, ExcerptRange<language::Anchor>)>,
 9274    },
 9275    ExcerptsRemoved {
 9276        ids: Vec<ExcerptId>,
 9277    },
 9278    BufferEdited,
 9279    Edited,
 9280    Reparsed,
 9281    Focused,
 9282    Blurred,
 9283    DirtyChanged,
 9284    Saved,
 9285    TitleChanged,
 9286    DiffBaseChanged,
 9287    SelectionsChanged {
 9288        local: bool,
 9289    },
 9290    ScrollPositionChanged {
 9291        local: bool,
 9292        autoscroll: bool,
 9293    },
 9294    Closed,
 9295}
 9296
 9297pub struct EditorFocused(pub ViewHandle<Editor>);
 9298pub struct EditorBlurred(pub ViewHandle<Editor>);
 9299pub struct EditorReleased(pub WeakViewHandle<Editor>);
 9300
 9301impl Entity for Editor {
 9302    type Event = Event;
 9303
 9304    fn release(&mut self, cx: &mut AppContext) {
 9305        cx.emit_global(EditorReleased(self.handle.clone()));
 9306    }
 9307}
 9308
 9309impl View for Editor {
 9310    fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
 9311        let style = self.style(cx);
 9312        let font_changed = self.display_map.update(cx, |map, cx| {
 9313            map.set_fold_ellipses_color(style.folds.ellipses.text_color);
 9314            map.set_font(style.text.font_id, style.text.font_size, cx)
 9315        });
 9316
 9317        if font_changed {
 9318            cx.defer(move |editor, cx: &mut ViewContext<Editor>| {
 9319                hide_hover(editor, cx);
 9320                hide_link_definition(editor, cx);
 9321            });
 9322        }
 9323
 9324        Stack::new()
 9325            .with_child(EditorElement::new(style.clone()))
 9326            .with_child(ChildView::new(&self.mouse_context_menu, cx))
 9327            .into_any()
 9328    }
 9329
 9330    fn ui_name() -> &'static str {
 9331        "Editor"
 9332    }
 9333
 9334    fn focus_in(&mut self, focused: AnyViewHandle, cx: &mut ViewContext<Self>) {
 9335        if cx.is_self_focused() {
 9336            let focused_event = EditorFocused(cx.handle());
 9337            cx.emit(Event::Focused);
 9338            cx.emit_global(focused_event);
 9339        }
 9340        if let Some(rename) = self.pending_rename.as_ref() {
 9341            cx.focus(&rename.editor);
 9342        } else if cx.is_self_focused() || !focused.is::<Editor>() {
 9343            if !self.focused {
 9344                self.blink_manager.update(cx, BlinkManager::enable);
 9345            }
 9346            self.focused = true;
 9347            self.buffer.update(cx, |buffer, cx| {
 9348                buffer.finalize_last_transaction(cx);
 9349                if self.leader_peer_id.is_none() {
 9350                    buffer.set_active_selections(
 9351                        &self.selections.disjoint_anchors(),
 9352                        self.selections.line_mode,
 9353                        self.cursor_shape,
 9354                        cx,
 9355                    );
 9356                }
 9357            });
 9358        }
 9359    }
 9360
 9361    fn focus_out(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
 9362        let blurred_event = EditorBlurred(cx.handle());
 9363        cx.emit_global(blurred_event);
 9364        self.focused = false;
 9365        self.blink_manager.update(cx, BlinkManager::disable);
 9366        self.buffer
 9367            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
 9368        self.hide_context_menu(cx);
 9369        hide_hover(self, cx);
 9370        cx.emit(Event::Blurred);
 9371        cx.notify();
 9372    }
 9373
 9374    fn modifiers_changed(
 9375        &mut self,
 9376        event: &gpui::platform::ModifiersChangedEvent,
 9377        cx: &mut ViewContext<Self>,
 9378    ) -> bool {
 9379        let pending_selection = self.has_pending_selection();
 9380
 9381        if let Some(point) = &self.link_go_to_definition_state.last_trigger_point {
 9382            if event.cmd && !pending_selection {
 9383                let point = point.clone();
 9384                let snapshot = self.snapshot(cx);
 9385                let kind = point.definition_kind(event.shift);
 9386
 9387                show_link_definition(kind, self, point, snapshot, cx);
 9388                return false;
 9389            }
 9390        }
 9391
 9392        {
 9393            if self.link_go_to_definition_state.symbol_range.is_some()
 9394                || !self.link_go_to_definition_state.definitions.is_empty()
 9395            {
 9396                self.link_go_to_definition_state.symbol_range.take();
 9397                self.link_go_to_definition_state.definitions.clear();
 9398                cx.notify();
 9399            }
 9400
 9401            self.link_go_to_definition_state.task = None;
 9402
 9403            self.clear_highlights::<LinkGoToDefinitionState>(cx);
 9404        }
 9405
 9406        false
 9407    }
 9408
 9409    fn update_keymap_context(&self, keymap: &mut KeymapContext, cx: &AppContext) {
 9410        Self::reset_to_default_keymap_context(keymap);
 9411        let mode = match self.mode {
 9412            EditorMode::SingleLine => "single_line",
 9413            EditorMode::AutoHeight { .. } => "auto_height",
 9414            EditorMode::Full => "full",
 9415        };
 9416        keymap.add_key("mode", mode);
 9417        if self.pending_rename.is_some() {
 9418            keymap.add_identifier("renaming");
 9419        }
 9420        if self.context_menu_visible() {
 9421            match self.context_menu.read().as_ref() {
 9422                Some(ContextMenu::Completions(_)) => {
 9423                    keymap.add_identifier("menu");
 9424                    keymap.add_identifier("showing_completions")
 9425                }
 9426                Some(ContextMenu::CodeActions(_)) => {
 9427                    keymap.add_identifier("menu");
 9428                    keymap.add_identifier("showing_code_actions")
 9429                }
 9430                None => {}
 9431            }
 9432        }
 9433
 9434        for layer in self.keymap_context_layers.values() {
 9435            keymap.extend(layer);
 9436        }
 9437
 9438        if let Some(extension) = self
 9439            .buffer
 9440            .read(cx)
 9441            .as_singleton()
 9442            .and_then(|buffer| buffer.read(cx).file()?.path().extension()?.to_str())
 9443        {
 9444            keymap.add_key("extension", extension.to_string());
 9445        }
 9446    }
 9447
 9448    fn text_for_range(&self, range_utf16: Range<usize>, cx: &AppContext) -> Option<String> {
 9449        Some(
 9450            self.buffer
 9451                .read(cx)
 9452                .read(cx)
 9453                .text_for_range(OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end))
 9454                .collect(),
 9455        )
 9456    }
 9457
 9458    fn selected_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
 9459        // Prevent the IME menu from appearing when holding down an alphabetic key
 9460        // while input is disabled.
 9461        if !self.input_enabled {
 9462            return None;
 9463        }
 9464
 9465        let range = self.selections.newest::<OffsetUtf16>(cx).range();
 9466        Some(range.start.0..range.end.0)
 9467    }
 9468
 9469    fn marked_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
 9470        let snapshot = self.buffer.read(cx).read(cx);
 9471        let range = self.text_highlights::<InputComposition>(cx)?.1.get(0)?;
 9472        Some(range.start.to_offset_utf16(&snapshot).0..range.end.to_offset_utf16(&snapshot).0)
 9473    }
 9474
 9475    fn unmark_text(&mut self, cx: &mut ViewContext<Self>) {
 9476        self.clear_highlights::<InputComposition>(cx);
 9477        self.ime_transaction.take();
 9478    }
 9479
 9480    fn replace_text_in_range(
 9481        &mut self,
 9482        range_utf16: Option<Range<usize>>,
 9483        text: &str,
 9484        cx: &mut ViewContext<Self>,
 9485    ) {
 9486        if !self.input_enabled {
 9487            cx.emit(Event::InputIgnored { text: text.into() });
 9488            return;
 9489        }
 9490
 9491        self.transact(cx, |this, cx| {
 9492            let new_selected_ranges = if let Some(range_utf16) = range_utf16 {
 9493                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
 9494                Some(this.selection_replacement_ranges(range_utf16, cx))
 9495            } else {
 9496                this.marked_text_ranges(cx)
 9497            };
 9498
 9499            let range_to_replace = new_selected_ranges.as_ref().and_then(|ranges_to_replace| {
 9500                let newest_selection_id = this.selections.newest_anchor().id;
 9501                this.selections
 9502                    .all::<OffsetUtf16>(cx)
 9503                    .iter()
 9504                    .zip(ranges_to_replace.iter())
 9505                    .find_map(|(selection, range)| {
 9506                        if selection.id == newest_selection_id {
 9507                            Some(
 9508                                (range.start.0 as isize - selection.head().0 as isize)
 9509                                    ..(range.end.0 as isize - selection.head().0 as isize),
 9510                            )
 9511                        } else {
 9512                            None
 9513                        }
 9514                    })
 9515            });
 9516
 9517            cx.emit(Event::InputHandled {
 9518                utf16_range_to_replace: range_to_replace,
 9519                text: text.into(),
 9520            });
 9521
 9522            if let Some(new_selected_ranges) = new_selected_ranges {
 9523                this.change_selections(None, cx, |selections| {
 9524                    selections.select_ranges(new_selected_ranges)
 9525                });
 9526            }
 9527
 9528            this.handle_input(text, cx);
 9529        });
 9530
 9531        if let Some(transaction) = self.ime_transaction {
 9532            self.buffer.update(cx, |buffer, cx| {
 9533                buffer.group_until_transaction(transaction, cx);
 9534            });
 9535        }
 9536
 9537        self.unmark_text(cx);
 9538    }
 9539
 9540    fn replace_and_mark_text_in_range(
 9541        &mut self,
 9542        range_utf16: Option<Range<usize>>,
 9543        text: &str,
 9544        new_selected_range_utf16: Option<Range<usize>>,
 9545        cx: &mut ViewContext<Self>,
 9546    ) {
 9547        if !self.input_enabled {
 9548            cx.emit(Event::InputIgnored { text: text.into() });
 9549            return;
 9550        }
 9551
 9552        let transaction = self.transact(cx, |this, cx| {
 9553            let ranges_to_replace = if let Some(mut marked_ranges) = this.marked_text_ranges(cx) {
 9554                let snapshot = this.buffer.read(cx).read(cx);
 9555                if let Some(relative_range_utf16) = range_utf16.as_ref() {
 9556                    for marked_range in &mut marked_ranges {
 9557                        marked_range.end.0 = marked_range.start.0 + relative_range_utf16.end;
 9558                        marked_range.start.0 += relative_range_utf16.start;
 9559                        marked_range.start =
 9560                            snapshot.clip_offset_utf16(marked_range.start, Bias::Left);
 9561                        marked_range.end =
 9562                            snapshot.clip_offset_utf16(marked_range.end, Bias::Right);
 9563                    }
 9564                }
 9565                Some(marked_ranges)
 9566            } else if let Some(range_utf16) = range_utf16 {
 9567                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
 9568                Some(this.selection_replacement_ranges(range_utf16, cx))
 9569            } else {
 9570                None
 9571            };
 9572
 9573            let range_to_replace = ranges_to_replace.as_ref().and_then(|ranges_to_replace| {
 9574                let newest_selection_id = this.selections.newest_anchor().id;
 9575                this.selections
 9576                    .all::<OffsetUtf16>(cx)
 9577                    .iter()
 9578                    .zip(ranges_to_replace.iter())
 9579                    .find_map(|(selection, range)| {
 9580                        if selection.id == newest_selection_id {
 9581                            Some(
 9582                                (range.start.0 as isize - selection.head().0 as isize)
 9583                                    ..(range.end.0 as isize - selection.head().0 as isize),
 9584                            )
 9585                        } else {
 9586                            None
 9587                        }
 9588                    })
 9589            });
 9590
 9591            cx.emit(Event::InputHandled {
 9592                utf16_range_to_replace: range_to_replace,
 9593                text: text.into(),
 9594            });
 9595
 9596            if let Some(ranges) = ranges_to_replace {
 9597                this.change_selections(None, cx, |s| s.select_ranges(ranges));
 9598            }
 9599
 9600            let marked_ranges = {
 9601                let snapshot = this.buffer.read(cx).read(cx);
 9602                this.selections
 9603                    .disjoint_anchors()
 9604                    .iter()
 9605                    .map(|selection| {
 9606                        selection.start.bias_left(&*snapshot)..selection.end.bias_right(&*snapshot)
 9607                    })
 9608                    .collect::<Vec<_>>()
 9609            };
 9610
 9611            if text.is_empty() {
 9612                this.unmark_text(cx);
 9613            } else {
 9614                this.highlight_text::<InputComposition>(
 9615                    marked_ranges.clone(),
 9616                    this.style(cx).composition_mark,
 9617                    cx,
 9618                );
 9619            }
 9620
 9621            this.handle_input(text, cx);
 9622
 9623            if let Some(new_selected_range) = new_selected_range_utf16 {
 9624                let snapshot = this.buffer.read(cx).read(cx);
 9625                let new_selected_ranges = marked_ranges
 9626                    .into_iter()
 9627                    .map(|marked_range| {
 9628                        let insertion_start = marked_range.start.to_offset_utf16(&snapshot).0;
 9629                        let new_start = OffsetUtf16(new_selected_range.start + insertion_start);
 9630                        let new_end = OffsetUtf16(new_selected_range.end + insertion_start);
 9631                        snapshot.clip_offset_utf16(new_start, Bias::Left)
 9632                            ..snapshot.clip_offset_utf16(new_end, Bias::Right)
 9633                    })
 9634                    .collect::<Vec<_>>();
 9635
 9636                drop(snapshot);
 9637                this.change_selections(None, cx, |selections| {
 9638                    selections.select_ranges(new_selected_ranges)
 9639                });
 9640            }
 9641        });
 9642
 9643        self.ime_transaction = self.ime_transaction.or(transaction);
 9644        if let Some(transaction) = self.ime_transaction {
 9645            self.buffer.update(cx, |buffer, cx| {
 9646                buffer.group_until_transaction(transaction, cx);
 9647            });
 9648        }
 9649
 9650        if self.text_highlights::<InputComposition>(cx).is_none() {
 9651            self.ime_transaction.take();
 9652        }
 9653    }
 9654}
 9655
 9656fn build_style(
 9657    settings: &ThemeSettings,
 9658    get_field_editor_theme: Option<&GetFieldEditorTheme>,
 9659    override_text_style: Option<&OverrideTextStyle>,
 9660    cx: &AppContext,
 9661) -> EditorStyle {
 9662    let font_cache = cx.font_cache();
 9663    let line_height_scalar = settings.line_height();
 9664    let theme_id = settings.theme.meta.id;
 9665    let mut theme = settings.theme.editor.clone();
 9666    let mut style = if let Some(get_field_editor_theme) = get_field_editor_theme {
 9667        let field_editor_theme = get_field_editor_theme(&settings.theme);
 9668        theme.text_color = field_editor_theme.text.color;
 9669        theme.selection = field_editor_theme.selection;
 9670        theme.background = field_editor_theme
 9671            .container
 9672            .background_color
 9673            .unwrap_or_default();
 9674        EditorStyle {
 9675            text: field_editor_theme.text,
 9676            placeholder_text: field_editor_theme.placeholder_text,
 9677            line_height_scalar,
 9678            theme,
 9679            theme_id,
 9680        }
 9681    } else {
 9682        let font_family_id = settings.buffer_font_family;
 9683        let font_family_name = cx.font_cache().family_name(font_family_id).unwrap();
 9684        let font_properties = Default::default();
 9685        let font_id = font_cache
 9686            .select_font(font_family_id, &font_properties)
 9687            .unwrap();
 9688        let font_size = settings.buffer_font_size(cx);
 9689        EditorStyle {
 9690            text: TextStyle {
 9691                color: settings.theme.editor.text_color,
 9692                font_family_name,
 9693                font_family_id,
 9694                font_id,
 9695                font_size,
 9696                font_properties,
 9697                underline: Default::default(),
 9698                soft_wrap: false,
 9699            },
 9700            placeholder_text: None,
 9701            line_height_scalar,
 9702            theme,
 9703            theme_id,
 9704        }
 9705    };
 9706
 9707    if let Some(highlight_style) = override_text_style.and_then(|build_style| build_style(&style)) {
 9708        if let Some(highlighted) = style
 9709            .text
 9710            .clone()
 9711            .highlight(highlight_style, font_cache)
 9712            .log_err()
 9713        {
 9714            style.text = highlighted;
 9715        }
 9716    }
 9717
 9718    style
 9719}
 9720
 9721trait SelectionExt {
 9722    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize>;
 9723    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point>;
 9724    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
 9725    fn spanned_rows(&self, include_end_if_at_line_start: bool, map: &DisplaySnapshot)
 9726        -> Range<u32>;
 9727}
 9728
 9729impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
 9730    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
 9731        let start = self.start.to_point(buffer);
 9732        let end = self.end.to_point(buffer);
 9733        if self.reversed {
 9734            end..start
 9735        } else {
 9736            start..end
 9737        }
 9738    }
 9739
 9740    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
 9741        let start = self.start.to_offset(buffer);
 9742        let end = self.end.to_offset(buffer);
 9743        if self.reversed {
 9744            end..start
 9745        } else {
 9746            start..end
 9747        }
 9748    }
 9749
 9750    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
 9751        let start = self
 9752            .start
 9753            .to_point(&map.buffer_snapshot)
 9754            .to_display_point(map);
 9755        let end = self
 9756            .end
 9757            .to_point(&map.buffer_snapshot)
 9758            .to_display_point(map);
 9759        if self.reversed {
 9760            end..start
 9761        } else {
 9762            start..end
 9763        }
 9764    }
 9765
 9766    fn spanned_rows(
 9767        &self,
 9768        include_end_if_at_line_start: bool,
 9769        map: &DisplaySnapshot,
 9770    ) -> Range<u32> {
 9771        let start = self.start.to_point(&map.buffer_snapshot);
 9772        let mut end = self.end.to_point(&map.buffer_snapshot);
 9773        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
 9774            end.row -= 1;
 9775        }
 9776
 9777        let buffer_start = map.prev_line_boundary(start).0;
 9778        let buffer_end = map.next_line_boundary(end).0;
 9779        buffer_start.row..buffer_end.row + 1
 9780    }
 9781}
 9782
 9783impl<T: InvalidationRegion> InvalidationStack<T> {
 9784    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
 9785    where
 9786        S: Clone + ToOffset,
 9787    {
 9788        while let Some(region) = self.last() {
 9789            let all_selections_inside_invalidation_ranges =
 9790                if selections.len() == region.ranges().len() {
 9791                    selections
 9792                        .iter()
 9793                        .zip(region.ranges().iter().map(|r| r.to_offset(buffer)))
 9794                        .all(|(selection, invalidation_range)| {
 9795                            let head = selection.head().to_offset(buffer);
 9796                            invalidation_range.start <= head && invalidation_range.end >= head
 9797                        })
 9798                } else {
 9799                    false
 9800                };
 9801
 9802            if all_selections_inside_invalidation_ranges {
 9803                break;
 9804            } else {
 9805                self.pop();
 9806            }
 9807        }
 9808    }
 9809}
 9810
 9811impl<T> Default for InvalidationStack<T> {
 9812    fn default() -> Self {
 9813        Self(Default::default())
 9814    }
 9815}
 9816
 9817impl<T> Deref for InvalidationStack<T> {
 9818    type Target = Vec<T>;
 9819
 9820    fn deref(&self) -> &Self::Target {
 9821        &self.0
 9822    }
 9823}
 9824
 9825impl<T> DerefMut for InvalidationStack<T> {
 9826    fn deref_mut(&mut self) -> &mut Self::Target {
 9827        &mut self.0
 9828    }
 9829}
 9830
 9831impl InvalidationRegion for SnippetState {
 9832    fn ranges(&self) -> &[Range<Anchor>] {
 9833        &self.ranges[self.active_index]
 9834    }
 9835}
 9836
 9837impl Deref for EditorStyle {
 9838    type Target = theme::Editor;
 9839
 9840    fn deref(&self) -> &Self::Target {
 9841        &self.theme
 9842    }
 9843}
 9844
 9845pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> RenderBlock {
 9846    let mut highlighted_lines = Vec::new();
 9847
 9848    for (index, line) in diagnostic.message.lines().enumerate() {
 9849        let line = match &diagnostic.source {
 9850            Some(source) if index == 0 => {
 9851                let source_highlight = Vec::from_iter(0..source.len());
 9852                highlight_diagnostic_message(source_highlight, &format!("{source}: {line}"))
 9853            }
 9854
 9855            _ => highlight_diagnostic_message(Vec::new(), line),
 9856        };
 9857        highlighted_lines.push(line);
 9858    }
 9859    let message = diagnostic.message;
 9860    Arc::new(move |cx: &mut BlockContext| {
 9861        let message = message.clone();
 9862        let settings = settings::get::<ThemeSettings>(cx);
 9863        let tooltip_style = settings.theme.tooltip.clone();
 9864        let theme = &settings.theme.editor;
 9865        let style = diagnostic_style(diagnostic.severity, is_valid, theme);
 9866        let font_size = (style.text_scale_factor * settings.buffer_font_size(cx)).round();
 9867        let anchor_x = cx.anchor_x;
 9868        enum BlockContextToolip {}
 9869        MouseEventHandler::new::<BlockContext, _>(cx.block_id, cx, |_, _| {
 9870            Flex::column()
 9871                .with_children(highlighted_lines.iter().map(|(line, highlights)| {
 9872                    Label::new(
 9873                        line.clone(),
 9874                        style.message.clone().with_font_size(font_size),
 9875                    )
 9876                    .with_highlights(highlights.clone())
 9877                    .contained()
 9878                    .with_margin_left(anchor_x)
 9879                }))
 9880                .aligned()
 9881                .left()
 9882                .into_any()
 9883        })
 9884        .with_cursor_style(CursorStyle::PointingHand)
 9885        .on_click(MouseButton::Left, move |_, _, cx| {
 9886            cx.write_to_clipboard(ClipboardItem::new(message.clone()));
 9887        })
 9888        // We really need to rethink this ID system...
 9889        .with_tooltip::<BlockContextToolip>(
 9890            cx.block_id,
 9891            "Copy diagnostic message",
 9892            None,
 9893            tooltip_style,
 9894            cx,
 9895        )
 9896        .into_any()
 9897    })
 9898}
 9899
 9900pub fn highlight_diagnostic_message(
 9901    initial_highlights: Vec<usize>,
 9902    message: &str,
 9903) -> (String, Vec<usize>) {
 9904    let mut message_without_backticks = String::new();
 9905    let mut prev_offset = 0;
 9906    let mut inside_block = false;
 9907    let mut highlights = initial_highlights;
 9908    for (match_ix, (offset, _)) in message
 9909        .match_indices('`')
 9910        .chain([(message.len(), "")])
 9911        .enumerate()
 9912    {
 9913        message_without_backticks.push_str(&message[prev_offset..offset]);
 9914        if inside_block {
 9915            highlights.extend(prev_offset - match_ix..offset - match_ix);
 9916        }
 9917
 9918        inside_block = !inside_block;
 9919        prev_offset = offset + 1;
 9920    }
 9921
 9922    (message_without_backticks, highlights)
 9923}
 9924
 9925pub fn diagnostic_style(
 9926    severity: DiagnosticSeverity,
 9927    valid: bool,
 9928    theme: &theme::Editor,
 9929) -> DiagnosticStyle {
 9930    match (severity, valid) {
 9931        (DiagnosticSeverity::ERROR, true) => theme.error_diagnostic.clone(),
 9932        (DiagnosticSeverity::ERROR, false) => theme.invalid_error_diagnostic.clone(),
 9933        (DiagnosticSeverity::WARNING, true) => theme.warning_diagnostic.clone(),
 9934        (DiagnosticSeverity::WARNING, false) => theme.invalid_warning_diagnostic.clone(),
 9935        (DiagnosticSeverity::INFORMATION, true) => theme.information_diagnostic.clone(),
 9936        (DiagnosticSeverity::INFORMATION, false) => theme.invalid_information_diagnostic.clone(),
 9937        (DiagnosticSeverity::HINT, true) => theme.hint_diagnostic.clone(),
 9938        (DiagnosticSeverity::HINT, false) => theme.invalid_hint_diagnostic.clone(),
 9939        _ => theme.invalid_hint_diagnostic.clone(),
 9940    }
 9941}
 9942
 9943pub fn combine_syntax_and_fuzzy_match_highlights(
 9944    text: &str,
 9945    default_style: HighlightStyle,
 9946    syntax_ranges: impl Iterator<Item = (Range<usize>, HighlightStyle)>,
 9947    match_indices: &[usize],
 9948) -> Vec<(Range<usize>, HighlightStyle)> {
 9949    let mut result = Vec::new();
 9950    let mut match_indices = match_indices.iter().copied().peekable();
 9951
 9952    for (range, mut syntax_highlight) in syntax_ranges.chain([(usize::MAX..0, Default::default())])
 9953    {
 9954        syntax_highlight.weight = None;
 9955
 9956        // Add highlights for any fuzzy match characters before the next
 9957        // syntax highlight range.
 9958        while let Some(&match_index) = match_indices.peek() {
 9959            if match_index >= range.start {
 9960                break;
 9961            }
 9962            match_indices.next();
 9963            let end_index = char_ix_after(match_index, text);
 9964            let mut match_style = default_style;
 9965            match_style.weight = Some(fonts::Weight::BOLD);
 9966            result.push((match_index..end_index, match_style));
 9967        }
 9968
 9969        if range.start == usize::MAX {
 9970            break;
 9971        }
 9972
 9973        // Add highlights for any fuzzy match characters within the
 9974        // syntax highlight range.
 9975        let mut offset = range.start;
 9976        while let Some(&match_index) = match_indices.peek() {
 9977            if match_index >= range.end {
 9978                break;
 9979            }
 9980
 9981            match_indices.next();
 9982            if match_index > offset {
 9983                result.push((offset..match_index, syntax_highlight));
 9984            }
 9985
 9986            let mut end_index = char_ix_after(match_index, text);
 9987            while let Some(&next_match_index) = match_indices.peek() {
 9988                if next_match_index == end_index && next_match_index < range.end {
 9989                    end_index = char_ix_after(next_match_index, text);
 9990                    match_indices.next();
 9991                } else {
 9992                    break;
 9993                }
 9994            }
 9995
 9996            let mut match_style = syntax_highlight;
 9997            match_style.weight = Some(fonts::Weight::BOLD);
 9998            result.push((match_index..end_index, match_style));
 9999            offset = end_index;
10000        }
10001
10002        if offset < range.end {
10003            result.push((offset..range.end, syntax_highlight));
10004        }
10005    }
10006
10007    fn char_ix_after(ix: usize, text: &str) -> usize {
10008        ix + text[ix..].chars().next().unwrap().len_utf8()
10009    }
10010
10011    result
10012}
10013
10014pub fn styled_runs_for_code_label<'a>(
10015    label: &'a CodeLabel,
10016    syntax_theme: &'a theme::SyntaxTheme,
10017) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
10018    let fade_out = HighlightStyle {
10019        fade_out: Some(0.35),
10020        ..Default::default()
10021    };
10022
10023    let mut prev_end = label.filter_range.end;
10024    label
10025        .runs
10026        .iter()
10027        .enumerate()
10028        .flat_map(move |(ix, (range, highlight_id))| {
10029            let style = if let Some(style) = highlight_id.style(syntax_theme) {
10030                style
10031            } else {
10032                return Default::default();
10033            };
10034            let mut muted_style = style;
10035            muted_style.highlight(fade_out);
10036
10037            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
10038            if range.start >= label.filter_range.end {
10039                if range.start > prev_end {
10040                    runs.push((prev_end..range.start, fade_out));
10041                }
10042                runs.push((range.clone(), muted_style));
10043            } else if range.end <= label.filter_range.end {
10044                runs.push((range.clone(), style));
10045            } else {
10046                runs.push((range.start..label.filter_range.end, style));
10047                runs.push((label.filter_range.end..range.end, muted_style));
10048            }
10049            prev_end = cmp::max(prev_end, range.end);
10050
10051            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
10052                runs.push((prev_end..label.text.len(), fade_out));
10053            }
10054
10055            runs
10056        })
10057}
10058
10059pub fn split_words<'a>(text: &'a str) -> impl std::iter::Iterator<Item = &'a str> + 'a {
10060    let mut index = 0;
10061    let mut codepoints = text.char_indices().peekable();
10062
10063    std::iter::from_fn(move || {
10064        let start_index = index;
10065        while let Some((new_index, codepoint)) = codepoints.next() {
10066            index = new_index + codepoint.len_utf8();
10067            let current_upper = codepoint.is_uppercase();
10068            let next_upper = codepoints
10069                .peek()
10070                .map(|(_, c)| c.is_uppercase())
10071                .unwrap_or(false);
10072
10073            if !current_upper && next_upper {
10074                return Some(&text[start_index..index]);
10075            }
10076        }
10077
10078        index = text.len();
10079        if start_index < text.len() {
10080            return Some(&text[start_index..]);
10081        }
10082        None
10083    })
10084    .flat_map(|word| word.split_inclusive('_'))
10085    .flat_map(|word| word.split_inclusive('-'))
10086}
10087
10088trait RangeToAnchorExt {
10089    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor>;
10090}
10091
10092impl<T: ToOffset> RangeToAnchorExt for Range<T> {
10093    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor> {
10094        snapshot.anchor_after(self.start)..snapshot.anchor_before(self.end)
10095    }
10096}