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