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