editor.rs

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