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