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