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