editor.rs

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