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