editor.rs

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