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