editor.rs

   1mod blink_manager;
   2pub mod display_map;
   3mod editor_settings;
   4mod element;
   5
   6mod git;
   7mod highlight_matching_bracket;
   8mod hover_popover;
   9pub mod items;
  10mod link_go_to_definition;
  11mod mouse_context_menu;
  12pub mod movement;
  13mod multi_buffer;
  14mod persistence;
  15pub mod scroll;
  16pub mod selections_collection;
  17
  18#[cfg(test)]
  19mod editor_tests;
  20#[cfg(any(test, feature = "test-support"))]
  21pub mod test;
  22
  23use ::git::diff::DiffHunk;
  24use aho_corasick::AhoCorasick;
  25use anyhow::{anyhow, Result};
  26use blink_manager::BlinkManager;
  27use client::{ClickhouseEvent, TelemetrySettings};
  28use clock::ReplicaId;
  29use collections::{BTreeMap, Bound, HashMap, HashSet, VecDeque};
  30use copilot::Copilot;
  31pub use display_map::DisplayPoint;
  32use display_map::*;
  33pub use editor_settings::EditorSettings;
  34pub use element::*;
  35use futures::FutureExt;
  36use fuzzy::{StringMatch, StringMatchCandidate};
  37use gpui::{
  38    actions,
  39    color::Color,
  40    elements::*,
  41    executor,
  42    fonts::{self, HighlightStyle, TextStyle},
  43    geometry::vector::Vector2F,
  44    impl_actions,
  45    keymap_matcher::KeymapContext,
  46    platform::{CursorStyle, MouseButton},
  47    serde_json::{self, json},
  48    AnyElement, AnyViewHandle, AppContext, AsyncAppContext, ClipboardItem, Element, Entity,
  49    ModelHandle, Subscription, Task, View, ViewContext, ViewHandle, WeakViewHandle, WindowContext,
  50};
  51use highlight_matching_bracket::refresh_matching_bracket_highlights;
  52use hover_popover::{hide_hover, HoverState};
  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},
  58    AutoindentMode, BracketPair, Buffer, CodeAction, CodeLabel, Completion, CursorShape,
  59    Diagnostic, DiagnosticSeverity, File, IndentKind, IndentSize, Language, OffsetRangeExt,
  60    OffsetUtf16, Point, Selection, SelectionGoal, TransactionId,
  61};
  62use link_go_to_definition::{
  63    hide_link_definition, show_link_definition, LinkDefinitionKind, LinkGoToDefinitionState,
  64};
  65pub use multi_buffer::{
  66    Anchor, AnchorRangeExt, ExcerptId, ExcerptRange, MultiBuffer, MultiBufferSnapshot, ToOffset,
  67    ToPoint,
  68};
  69use multi_buffer::{MultiBufferChunks, ToOffsetUtf16};
  70use ordered_float::OrderedFloat;
  71use project::{FormatTrigger, Location, LocationLink, Project, ProjectPath, ProjectTransaction};
  72use scroll::{
  73    autoscroll::Autoscroll, OngoingScroll, ScrollAnchor, ScrollManager, ScrollbarAutoHide,
  74};
  75use selections_collection::{resolve_multiple, MutableSelectionsCollection, SelectionsCollection};
  76use serde::{Deserialize, Serialize};
  77use settings::SettingsStore;
  78use smallvec::SmallVec;
  79use snippet::Snippet;
  80use std::{
  81    any::TypeId,
  82    borrow::Cow,
  83    cmp::{self, Ordering, Reverse},
  84    mem,
  85    num::NonZeroU32,
  86    ops::{Deref, DerefMut, Range},
  87    path::Path,
  88    sync::Arc,
  89    time::{Duration, Instant},
  90};
  91pub use sum_tree::Bias;
  92use theme::{DiagnosticStyle, Theme, ThemeSettings};
  93use util::{post_inc, RangeExt, ResultExt, TryFutureExt};
  94use workspace::{ItemNavHistory, ViewId, Workspace};
  95
  96use crate::git::diff_hunk_to_display;
  97
  98const CURSOR_BLINK_INTERVAL: Duration = Duration::from_millis(500);
  99const MAX_LINE_LEN: usize = 1024;
 100const MIN_NAVIGATION_HISTORY_ROW_DELTA: i64 = 10;
 101const MAX_SELECTION_HISTORY_LEN: usize = 1024;
 102const COPILOT_DEBOUNCE_TIMEOUT: Duration = Duration::from_millis(75);
 103
 104pub const FORMAT_TIMEOUT: Duration = Duration::from_secs(2);
 105
 106#[derive(Clone, Deserialize, PartialEq, Default)]
 107pub struct SelectNext {
 108    #[serde(default)]
 109    pub replace_newest: bool,
 110}
 111
 112#[derive(Clone, Deserialize, PartialEq)]
 113pub struct SelectToBeginningOfLine {
 114    #[serde(default)]
 115    stop_at_soft_wraps: bool,
 116}
 117
 118#[derive(Clone, Default, Deserialize, PartialEq)]
 119pub struct MovePageUp {
 120    #[serde(default)]
 121    center_cursor: bool,
 122}
 123
 124#[derive(Clone, Default, Deserialize, PartialEq)]
 125pub struct MovePageDown {
 126    #[serde(default)]
 127    center_cursor: bool,
 128}
 129
 130#[derive(Clone, Deserialize, PartialEq)]
 131pub struct SelectToEndOfLine {
 132    #[serde(default)]
 133    stop_at_soft_wraps: bool,
 134}
 135
 136#[derive(Clone, Deserialize, PartialEq)]
 137pub struct ToggleCodeActions {
 138    #[serde(default)]
 139    pub deployed_from_indicator: bool,
 140}
 141
 142#[derive(Clone, Default, Deserialize, PartialEq)]
 143pub struct ConfirmCompletion {
 144    #[serde(default)]
 145    pub item_ix: Option<usize>,
 146}
 147
 148#[derive(Clone, Default, Deserialize, PartialEq)]
 149pub struct ConfirmCodeAction {
 150    #[serde(default)]
 151    pub item_ix: Option<usize>,
 152}
 153
 154#[derive(Clone, Default, Deserialize, PartialEq)]
 155pub struct ToggleComments {
 156    #[serde(default)]
 157    pub advance_downwards: bool,
 158}
 159
 160#[derive(Clone, Default, Deserialize, PartialEq)]
 161pub struct FoldAt {
 162    pub buffer_row: u32,
 163}
 164
 165#[derive(Clone, Default, Deserialize, PartialEq)]
 166pub struct UnfoldAt {
 167    pub buffer_row: u32,
 168}
 169
 170#[derive(Clone, Default, Deserialize, PartialEq)]
 171pub struct GutterHover {
 172    pub hovered: bool,
 173}
 174
 175actions!(
 176    editor,
 177    [
 178        Cancel,
 179        Backspace,
 180        Delete,
 181        Newline,
 182        NewlineAbove,
 183        NewlineBelow,
 184        GoToDiagnostic,
 185        GoToPrevDiagnostic,
 186        GoToHunk,
 187        GoToPrevHunk,
 188        Indent,
 189        Outdent,
 190        DeleteLine,
 191        DeleteToPreviousWordStart,
 192        DeleteToPreviousSubwordStart,
 193        DeleteToNextWordEnd,
 194        DeleteToNextSubwordEnd,
 195        DeleteToBeginningOfLine,
 196        DeleteToEndOfLine,
 197        CutToEndOfLine,
 198        DuplicateLine,
 199        MoveLineUp,
 200        MoveLineDown,
 201        Transpose,
 202        Cut,
 203        Copy,
 204        Paste,
 205        Undo,
 206        Redo,
 207        MoveUp,
 208        PageUp,
 209        MoveDown,
 210        PageDown,
 211        MoveLeft,
 212        MoveRight,
 213        MoveToPreviousWordStart,
 214        MoveToPreviousSubwordStart,
 215        MoveToNextWordEnd,
 216        MoveToNextSubwordEnd,
 217        MoveToBeginningOfLine,
 218        MoveToEndOfLine,
 219        MoveToStartOfParagraph,
 220        MoveToEndOfParagraph,
 221        MoveToBeginning,
 222        MoveToEnd,
 223        SelectUp,
 224        SelectDown,
 225        SelectLeft,
 226        SelectRight,
 227        SelectToPreviousWordStart,
 228        SelectToPreviousSubwordStart,
 229        SelectToNextWordEnd,
 230        SelectToNextSubwordEnd,
 231        SelectToStartOfParagraph,
 232        SelectToEndOfParagraph,
 233        SelectToBeginning,
 234        SelectToEnd,
 235        SelectAll,
 236        SelectLine,
 237        SplitSelectionIntoLines,
 238        AddSelectionAbove,
 239        AddSelectionBelow,
 240        Tab,
 241        TabPrev,
 242        ShowCharacterPalette,
 243        SelectLargerSyntaxNode,
 244        SelectSmallerSyntaxNode,
 245        GoToDefinition,
 246        GoToTypeDefinition,
 247        MoveToEnclosingBracket,
 248        UndoSelection,
 249        RedoSelection,
 250        FindAllReferences,
 251        Rename,
 252        ConfirmRename,
 253        Fold,
 254        UnfoldLines,
 255        FoldSelectedRanges,
 256        ShowCompletions,
 257        OpenExcerpts,
 258        RestartLanguageServer,
 259        Hover,
 260        Format,
 261        ToggleSoftWrap,
 262        RevealInFinder,
 263        CopyPath,
 264        CopyRelativePath,
 265        CopyHighlightJson
 266    ]
 267);
 268
 269impl_actions!(
 270    editor,
 271    [
 272        SelectNext,
 273        SelectToBeginningOfLine,
 274        SelectToEndOfLine,
 275        ToggleCodeActions,
 276        MovePageUp,
 277        MovePageDown,
 278        ConfirmCompletion,
 279        ConfirmCodeAction,
 280        ToggleComments,
 281        FoldAt,
 282        UnfoldAt,
 283        GutterHover
 284    ]
 285);
 286
 287enum DocumentHighlightRead {}
 288enum DocumentHighlightWrite {}
 289enum InputComposition {}
 290
 291#[derive(Copy, Clone, PartialEq, Eq)]
 292pub enum Direction {
 293    Prev,
 294    Next,
 295}
 296
 297pub fn init_settings(cx: &mut AppContext) {
 298    settings::register::<EditorSettings>(cx);
 299}
 300
 301pub fn init(cx: &mut AppContext) {
 302    init_settings(cx);
 303    cx.add_action(Editor::new_file);
 304    cx.add_action(Editor::cancel);
 305    cx.add_action(Editor::newline);
 306    cx.add_action(Editor::newline_above);
 307    cx.add_action(Editor::newline_below);
 308    cx.add_action(Editor::backspace);
 309    cx.add_action(Editor::delete);
 310    cx.add_action(Editor::tab);
 311    cx.add_action(Editor::tab_prev);
 312    cx.add_action(Editor::indent);
 313    cx.add_action(Editor::outdent);
 314    cx.add_action(Editor::delete_line);
 315    cx.add_action(Editor::delete_to_previous_word_start);
 316    cx.add_action(Editor::delete_to_previous_subword_start);
 317    cx.add_action(Editor::delete_to_next_word_end);
 318    cx.add_action(Editor::delete_to_next_subword_end);
 319    cx.add_action(Editor::delete_to_beginning_of_line);
 320    cx.add_action(Editor::delete_to_end_of_line);
 321    cx.add_action(Editor::cut_to_end_of_line);
 322    cx.add_action(Editor::duplicate_line);
 323    cx.add_action(Editor::move_line_up);
 324    cx.add_action(Editor::move_line_down);
 325    cx.add_action(Editor::transpose);
 326    cx.add_action(Editor::cut);
 327    cx.add_action(Editor::copy);
 328    cx.add_action(Editor::paste);
 329    cx.add_action(Editor::undo);
 330    cx.add_action(Editor::redo);
 331    cx.add_action(Editor::move_up);
 332    cx.add_action(Editor::move_page_up);
 333    cx.add_action(Editor::move_down);
 334    cx.add_action(Editor::move_page_down);
 335    cx.add_action(Editor::next_screen);
 336    cx.add_action(Editor::move_left);
 337    cx.add_action(Editor::move_right);
 338    cx.add_action(Editor::move_to_previous_word_start);
 339    cx.add_action(Editor::move_to_previous_subword_start);
 340    cx.add_action(Editor::move_to_next_word_end);
 341    cx.add_action(Editor::move_to_next_subword_end);
 342    cx.add_action(Editor::move_to_beginning_of_line);
 343    cx.add_action(Editor::move_to_end_of_line);
 344    cx.add_action(Editor::move_to_start_of_paragraph);
 345    cx.add_action(Editor::move_to_end_of_paragraph);
 346    cx.add_action(Editor::move_to_beginning);
 347    cx.add_action(Editor::move_to_end);
 348    cx.add_action(Editor::select_up);
 349    cx.add_action(Editor::select_down);
 350    cx.add_action(Editor::select_left);
 351    cx.add_action(Editor::select_right);
 352    cx.add_action(Editor::select_to_previous_word_start);
 353    cx.add_action(Editor::select_to_previous_subword_start);
 354    cx.add_action(Editor::select_to_next_word_end);
 355    cx.add_action(Editor::select_to_next_subword_end);
 356    cx.add_action(Editor::select_to_beginning_of_line);
 357    cx.add_action(Editor::select_to_end_of_line);
 358    cx.add_action(Editor::select_to_start_of_paragraph);
 359    cx.add_action(Editor::select_to_end_of_paragraph);
 360    cx.add_action(Editor::select_to_beginning);
 361    cx.add_action(Editor::select_to_end);
 362    cx.add_action(Editor::select_all);
 363    cx.add_action(Editor::select_line);
 364    cx.add_action(Editor::split_selection_into_lines);
 365    cx.add_action(Editor::add_selection_above);
 366    cx.add_action(Editor::add_selection_below);
 367    cx.add_action(Editor::select_next);
 368    cx.add_action(Editor::toggle_comments);
 369    cx.add_action(Editor::select_larger_syntax_node);
 370    cx.add_action(Editor::select_smaller_syntax_node);
 371    cx.add_action(Editor::move_to_enclosing_bracket);
 372    cx.add_action(Editor::undo_selection);
 373    cx.add_action(Editor::redo_selection);
 374    cx.add_action(Editor::go_to_diagnostic);
 375    cx.add_action(Editor::go_to_prev_diagnostic);
 376    cx.add_action(Editor::go_to_hunk);
 377    cx.add_action(Editor::go_to_prev_hunk);
 378    cx.add_action(Editor::go_to_definition);
 379    cx.add_action(Editor::go_to_type_definition);
 380    cx.add_action(Editor::fold);
 381    cx.add_action(Editor::fold_at);
 382    cx.add_action(Editor::unfold_lines);
 383    cx.add_action(Editor::unfold_at);
 384    cx.add_action(Editor::gutter_hover);
 385    cx.add_action(Editor::fold_selected_ranges);
 386    cx.add_action(Editor::show_completions);
 387    cx.add_action(Editor::toggle_code_actions);
 388    cx.add_action(Editor::open_excerpts);
 389    cx.add_action(Editor::toggle_soft_wrap);
 390    cx.add_action(Editor::reveal_in_finder);
 391    cx.add_action(Editor::copy_path);
 392    cx.add_action(Editor::copy_relative_path);
 393    cx.add_action(Editor::copy_highlight_json);
 394    cx.add_async_action(Editor::format);
 395    cx.add_action(Editor::restart_language_server);
 396    cx.add_action(Editor::show_character_palette);
 397    cx.add_async_action(Editor::confirm_completion);
 398    cx.add_async_action(Editor::confirm_code_action);
 399    cx.add_async_action(Editor::rename);
 400    cx.add_async_action(Editor::confirm_rename);
 401    cx.add_async_action(Editor::find_all_references);
 402    cx.add_action(Editor::next_copilot_suggestion);
 403    cx.add_action(Editor::previous_copilot_suggestion);
 404    cx.add_action(Editor::copilot_suggest);
 405
 406    hover_popover::init(cx);
 407    scroll::actions::init(cx);
 408
 409    workspace::register_project_item::<Editor>(cx);
 410    workspace::register_followable_item::<Editor>(cx);
 411    workspace::register_deserializable_item::<Editor>(cx);
 412}
 413
 414trait InvalidationRegion {
 415    fn ranges(&self) -> &[Range<Anchor>];
 416}
 417
 418#[derive(Clone, Debug, PartialEq)]
 419pub enum SelectPhase {
 420    Begin {
 421        position: DisplayPoint,
 422        add: bool,
 423        click_count: usize,
 424    },
 425    BeginColumnar {
 426        position: DisplayPoint,
 427        goal_column: u32,
 428    },
 429    Extend {
 430        position: DisplayPoint,
 431        click_count: usize,
 432    },
 433    Update {
 434        position: DisplayPoint,
 435        goal_column: u32,
 436        scroll_position: Vector2F,
 437    },
 438    End,
 439}
 440
 441#[derive(Clone, Debug)]
 442pub enum SelectMode {
 443    Character,
 444    Word(Range<Anchor>),
 445    Line(Range<Anchor>),
 446    All,
 447}
 448
 449#[derive(Copy, Clone, PartialEq, Eq, Debug)]
 450pub enum EditorMode {
 451    SingleLine,
 452    AutoHeight { max_lines: usize },
 453    Full,
 454}
 455
 456#[derive(Clone, Debug)]
 457pub enum SoftWrap {
 458    None,
 459    EditorWidth,
 460    Column(u32),
 461}
 462
 463#[derive(Clone)]
 464pub struct EditorStyle {
 465    pub text: TextStyle,
 466    pub placeholder_text: Option<TextStyle>,
 467    pub theme: theme::Editor,
 468    pub theme_id: usize,
 469}
 470
 471type CompletionId = usize;
 472
 473type GetFieldEditorTheme = dyn Fn(&theme::Theme) -> theme::FieldEditor;
 474type OverrideTextStyle = dyn Fn(&EditorStyle) -> Option<HighlightStyle>;
 475
 476pub struct Editor {
 477    handle: WeakViewHandle<Self>,
 478    buffer: ModelHandle<MultiBuffer>,
 479    display_map: ModelHandle<DisplayMap>,
 480    pub selections: SelectionsCollection,
 481    pub scroll_manager: ScrollManager,
 482    columnar_selection_tail: Option<Anchor>,
 483    add_selections_state: Option<AddSelectionsState>,
 484    select_next_state: Option<SelectNextState>,
 485    selection_history: SelectionHistory,
 486    autoclose_regions: Vec<AutocloseRegion>,
 487    snippet_stack: InvalidationStack<SnippetState>,
 488    select_larger_syntax_node_stack: Vec<Box<[Selection<usize>]>>,
 489    ime_transaction: Option<TransactionId>,
 490    active_diagnostics: Option<ActiveDiagnosticGroup>,
 491    soft_wrap_mode_override: Option<language_settings::SoftWrap>,
 492    get_field_editor_theme: Option<Arc<GetFieldEditorTheme>>,
 493    override_text_style: Option<Box<OverrideTextStyle>>,
 494    project: Option<ModelHandle<Project>>,
 495    focused: bool,
 496    blink_manager: ModelHandle<BlinkManager>,
 497    show_local_selections: bool,
 498    mode: EditorMode,
 499    placeholder_text: Option<Arc<str>>,
 500    highlighted_rows: Option<Range<u32>>,
 501    #[allow(clippy::type_complexity)]
 502    background_highlights: BTreeMap<TypeId, (fn(&Theme) -> Color, Vec<Range<Anchor>>)>,
 503    nav_history: Option<ItemNavHistory>,
 504    context_menu: Option<ContextMenu>,
 505    mouse_context_menu: ViewHandle<context_menu::ContextMenu>,
 506    completion_tasks: Vec<(CompletionId, Task<Option<()>>)>,
 507    next_completion_id: CompletionId,
 508    available_code_actions: Option<(ModelHandle<Buffer>, Arc<[CodeAction]>)>,
 509    code_actions_task: Option<Task<()>>,
 510    document_highlights_task: Option<Task<()>>,
 511    pending_rename: Option<RenameState>,
 512    searchable: bool,
 513    cursor_shape: CursorShape,
 514    workspace: Option<(WeakViewHandle<Workspace>, i64)>,
 515    keymap_context_layers: BTreeMap<TypeId, KeymapContext>,
 516    input_enabled: bool,
 517    read_only: bool,
 518    leader_replica_id: Option<u16>,
 519    remote_id: Option<ViewId>,
 520    hover_state: HoverState,
 521    gutter_hovered: bool,
 522    link_go_to_definition_state: LinkGoToDefinitionState,
 523    copilot_state: CopilotState,
 524    _subscriptions: Vec<Subscription>,
 525}
 526
 527pub struct EditorSnapshot {
 528    pub mode: EditorMode,
 529    pub display_snapshot: DisplaySnapshot,
 530    pub placeholder_text: Option<Arc<str>>,
 531    is_focused: bool,
 532    scroll_anchor: ScrollAnchor,
 533    ongoing_scroll: OngoingScroll,
 534}
 535
 536impl EditorSnapshot {
 537    fn has_scrollbar_info(&self) -> bool {
 538        self.buffer_snapshot
 539            .git_diff_hunks_in_range(0..self.max_point().row())
 540            .next()
 541            .is_some()
 542    }
 543}
 544
 545#[derive(Clone, Debug)]
 546struct SelectionHistoryEntry {
 547    selections: Arc<[Selection<Anchor>]>,
 548    select_next_state: Option<SelectNextState>,
 549    add_selections_state: Option<AddSelectionsState>,
 550}
 551
 552enum SelectionHistoryMode {
 553    Normal,
 554    Undoing,
 555    Redoing,
 556}
 557
 558impl Default for SelectionHistoryMode {
 559    fn default() -> Self {
 560        Self::Normal
 561    }
 562}
 563
 564#[derive(Default)]
 565struct SelectionHistory {
 566    #[allow(clippy::type_complexity)]
 567    selections_by_transaction:
 568        HashMap<TransactionId, (Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)>,
 569    mode: SelectionHistoryMode,
 570    undo_stack: VecDeque<SelectionHistoryEntry>,
 571    redo_stack: VecDeque<SelectionHistoryEntry>,
 572}
 573
 574impl SelectionHistory {
 575    fn insert_transaction(
 576        &mut self,
 577        transaction_id: TransactionId,
 578        selections: Arc<[Selection<Anchor>]>,
 579    ) {
 580        self.selections_by_transaction
 581            .insert(transaction_id, (selections, None));
 582    }
 583
 584    #[allow(clippy::type_complexity)]
 585    fn transaction(
 586        &self,
 587        transaction_id: TransactionId,
 588    ) -> Option<&(Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)> {
 589        self.selections_by_transaction.get(&transaction_id)
 590    }
 591
 592    #[allow(clippy::type_complexity)]
 593    fn transaction_mut(
 594        &mut self,
 595        transaction_id: TransactionId,
 596    ) -> Option<&mut (Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)> {
 597        self.selections_by_transaction.get_mut(&transaction_id)
 598    }
 599
 600    fn push(&mut self, entry: SelectionHistoryEntry) {
 601        if !entry.selections.is_empty() {
 602            match self.mode {
 603                SelectionHistoryMode::Normal => {
 604                    self.push_undo(entry);
 605                    self.redo_stack.clear();
 606                }
 607                SelectionHistoryMode::Undoing => self.push_redo(entry),
 608                SelectionHistoryMode::Redoing => self.push_undo(entry),
 609            }
 610        }
 611    }
 612
 613    fn push_undo(&mut self, entry: SelectionHistoryEntry) {
 614        if self
 615            .undo_stack
 616            .back()
 617            .map_or(true, |e| e.selections != entry.selections)
 618        {
 619            self.undo_stack.push_back(entry);
 620            if self.undo_stack.len() > MAX_SELECTION_HISTORY_LEN {
 621                self.undo_stack.pop_front();
 622            }
 623        }
 624    }
 625
 626    fn push_redo(&mut self, entry: SelectionHistoryEntry) {
 627        if self
 628            .redo_stack
 629            .back()
 630            .map_or(true, |e| e.selections != entry.selections)
 631        {
 632            self.redo_stack.push_back(entry);
 633            if self.redo_stack.len() > MAX_SELECTION_HISTORY_LEN {
 634                self.redo_stack.pop_front();
 635            }
 636        }
 637    }
 638}
 639
 640#[derive(Clone, Debug)]
 641struct AddSelectionsState {
 642    above: bool,
 643    stack: Vec<usize>,
 644}
 645
 646#[derive(Clone, Debug)]
 647struct SelectNextState {
 648    query: AhoCorasick,
 649    wordwise: bool,
 650    done: bool,
 651}
 652
 653#[derive(Debug)]
 654struct AutocloseRegion {
 655    selection_id: usize,
 656    range: Range<Anchor>,
 657    pair: BracketPair,
 658}
 659
 660#[derive(Debug)]
 661struct SnippetState {
 662    ranges: Vec<Vec<Range<Anchor>>>,
 663    active_index: usize,
 664}
 665
 666pub struct RenameState {
 667    pub range: Range<Anchor>,
 668    pub old_name: Arc<str>,
 669    pub editor: ViewHandle<Editor>,
 670    block_id: BlockId,
 671}
 672
 673struct InvalidationStack<T>(Vec<T>);
 674
 675enum ContextMenu {
 676    Completions(CompletionsMenu),
 677    CodeActions(CodeActionsMenu),
 678}
 679
 680impl ContextMenu {
 681    fn select_first(&mut self, cx: &mut ViewContext<Editor>) -> bool {
 682        if self.visible() {
 683            match self {
 684                ContextMenu::Completions(menu) => menu.select_first(cx),
 685                ContextMenu::CodeActions(menu) => menu.select_first(cx),
 686            }
 687            true
 688        } else {
 689            false
 690        }
 691    }
 692
 693    fn select_prev(&mut self, cx: &mut ViewContext<Editor>) -> bool {
 694        if self.visible() {
 695            match self {
 696                ContextMenu::Completions(menu) => menu.select_prev(cx),
 697                ContextMenu::CodeActions(menu) => menu.select_prev(cx),
 698            }
 699            true
 700        } else {
 701            false
 702        }
 703    }
 704
 705    fn select_next(&mut self, cx: &mut ViewContext<Editor>) -> bool {
 706        if self.visible() {
 707            match self {
 708                ContextMenu::Completions(menu) => menu.select_next(cx),
 709                ContextMenu::CodeActions(menu) => menu.select_next(cx),
 710            }
 711            true
 712        } else {
 713            false
 714        }
 715    }
 716
 717    fn select_last(&mut self, cx: &mut ViewContext<Editor>) -> bool {
 718        if self.visible() {
 719            match self {
 720                ContextMenu::Completions(menu) => menu.select_last(cx),
 721                ContextMenu::CodeActions(menu) => menu.select_last(cx),
 722            }
 723            true
 724        } else {
 725            false
 726        }
 727    }
 728
 729    fn visible(&self) -> bool {
 730        match self {
 731            ContextMenu::Completions(menu) => menu.visible(),
 732            ContextMenu::CodeActions(menu) => menu.visible(),
 733        }
 734    }
 735
 736    fn render(
 737        &self,
 738        cursor_position: DisplayPoint,
 739        style: EditorStyle,
 740        cx: &mut ViewContext<Editor>,
 741    ) -> (DisplayPoint, AnyElement<Editor>) {
 742        match self {
 743            ContextMenu::Completions(menu) => (cursor_position, menu.render(style, cx)),
 744            ContextMenu::CodeActions(menu) => menu.render(cursor_position, style, cx),
 745        }
 746    }
 747}
 748
 749struct CompletionsMenu {
 750    id: CompletionId,
 751    initial_position: Anchor,
 752    buffer: ModelHandle<Buffer>,
 753    completions: Arc<[Completion]>,
 754    match_candidates: Vec<StringMatchCandidate>,
 755    matches: Arc<[StringMatch]>,
 756    selected_item: usize,
 757    list: UniformListState,
 758}
 759
 760impl CompletionsMenu {
 761    fn select_first(&mut self, cx: &mut ViewContext<Editor>) {
 762        self.selected_item = 0;
 763        self.list.scroll_to(ScrollTarget::Show(self.selected_item));
 764        cx.notify();
 765    }
 766
 767    fn select_prev(&mut self, cx: &mut ViewContext<Editor>) {
 768        if self.selected_item > 0 {
 769            self.selected_item -= 1;
 770            self.list.scroll_to(ScrollTarget::Show(self.selected_item));
 771        }
 772        cx.notify();
 773    }
 774
 775    fn select_next(&mut self, cx: &mut ViewContext<Editor>) {
 776        if self.selected_item + 1 < self.matches.len() {
 777            self.selected_item += 1;
 778            self.list.scroll_to(ScrollTarget::Show(self.selected_item));
 779        }
 780        cx.notify();
 781    }
 782
 783    fn select_last(&mut self, cx: &mut ViewContext<Editor>) {
 784        self.selected_item = self.matches.len() - 1;
 785        self.list.scroll_to(ScrollTarget::Show(self.selected_item));
 786        cx.notify();
 787    }
 788
 789    fn visible(&self) -> bool {
 790        !self.matches.is_empty()
 791    }
 792
 793    fn render(&self, style: EditorStyle, cx: &mut ViewContext<Editor>) -> AnyElement<Editor> {
 794        enum CompletionTag {}
 795
 796        let completions = self.completions.clone();
 797        let matches = self.matches.clone();
 798        let selected_item = self.selected_item;
 799        let container_style = style.autocomplete.container;
 800        UniformList::new(
 801            self.list.clone(),
 802            matches.len(),
 803            cx,
 804            move |_, range, items, cx| {
 805                let start_ix = range.start;
 806                for (ix, mat) in matches[range].iter().enumerate() {
 807                    let completion = &completions[mat.candidate_id];
 808                    let item_ix = start_ix + ix;
 809                    items.push(
 810                        MouseEventHandler::<CompletionTag, _>::new(
 811                            mat.candidate_id,
 812                            cx,
 813                            |state, _| {
 814                                let item_style = if item_ix == selected_item {
 815                                    style.autocomplete.selected_item
 816                                } else if state.hovered() {
 817                                    style.autocomplete.hovered_item
 818                                } else {
 819                                    style.autocomplete.item
 820                                };
 821
 822                                Text::new(completion.label.text.clone(), style.text.clone())
 823                                    .with_soft_wrap(false)
 824                                    .with_highlights(combine_syntax_and_fuzzy_match_highlights(
 825                                        &completion.label.text,
 826                                        style.text.color.into(),
 827                                        styled_runs_for_code_label(
 828                                            &completion.label,
 829                                            &style.syntax,
 830                                        ),
 831                                        &mat.positions,
 832                                    ))
 833                                    .contained()
 834                                    .with_style(item_style)
 835                            },
 836                        )
 837                        .with_cursor_style(CursorStyle::PointingHand)
 838                        .on_down(MouseButton::Left, move |_, this, cx| {
 839                            this.confirm_completion(
 840                                &ConfirmCompletion {
 841                                    item_ix: Some(item_ix),
 842                                },
 843                                cx,
 844                            );
 845                        })
 846                        .into_any(),
 847                    );
 848                }
 849            },
 850        )
 851        .with_width_from_item(
 852            self.matches
 853                .iter()
 854                .enumerate()
 855                .max_by_key(|(_, mat)| {
 856                    self.completions[mat.candidate_id]
 857                        .label
 858                        .text
 859                        .chars()
 860                        .count()
 861                })
 862                .map(|(ix, _)| ix),
 863        )
 864        .contained()
 865        .with_style(container_style)
 866        .into_any()
 867    }
 868
 869    pub async fn filter(&mut self, query: Option<&str>, executor: Arc<executor::Background>) {
 870        let mut matches = if let Some(query) = query {
 871            fuzzy::match_strings(
 872                &self.match_candidates,
 873                query,
 874                query.chars().any(|c| c.is_uppercase()),
 875                100,
 876                &Default::default(),
 877                executor,
 878            )
 879            .await
 880        } else {
 881            self.match_candidates
 882                .iter()
 883                .enumerate()
 884                .map(|(candidate_id, candidate)| StringMatch {
 885                    candidate_id,
 886                    score: Default::default(),
 887                    positions: Default::default(),
 888                    string: candidate.string.clone(),
 889                })
 890                .collect()
 891        };
 892
 893        //Remove all candidates where the query's start does not match the start of any word in the candidate
 894        if let Some(query) = query {
 895            if let Some(query_start) = query.chars().next() {
 896                matches.retain(|string_match| {
 897                    split_words(&string_match.string).any(|word| {
 898                        //Check that the first codepoint of the word as lowercase matches the first
 899                        //codepoint of the query as lowercase
 900                        word.chars()
 901                            .flat_map(|codepoint| codepoint.to_lowercase())
 902                            .zip(query_start.to_lowercase())
 903                            .all(|(word_cp, query_cp)| word_cp == query_cp)
 904                    })
 905                });
 906            }
 907        }
 908
 909        matches.sort_unstable_by_key(|mat| {
 910            let completion = &self.completions[mat.candidate_id];
 911            (
 912                completion.lsp_completion.sort_text.as_ref(),
 913                Reverse(OrderedFloat(mat.score)),
 914                completion.sort_key(),
 915            )
 916        });
 917
 918        for mat in &mut matches {
 919            let filter_start = self.completions[mat.candidate_id].label.filter_range.start;
 920            for position in &mut mat.positions {
 921                *position += filter_start;
 922            }
 923        }
 924
 925        self.matches = matches.into();
 926    }
 927}
 928
 929#[derive(Clone)]
 930struct CodeActionsMenu {
 931    actions: Arc<[CodeAction]>,
 932    buffer: ModelHandle<Buffer>,
 933    selected_item: usize,
 934    list: UniformListState,
 935    deployed_from_indicator: bool,
 936}
 937
 938impl CodeActionsMenu {
 939    fn select_first(&mut self, cx: &mut ViewContext<Editor>) {
 940        self.selected_item = 0;
 941        cx.notify()
 942    }
 943
 944    fn select_prev(&mut self, cx: &mut ViewContext<Editor>) {
 945        if self.selected_item > 0 {
 946            self.selected_item -= 1;
 947            cx.notify()
 948        }
 949    }
 950
 951    fn select_next(&mut self, cx: &mut ViewContext<Editor>) {
 952        if self.selected_item + 1 < self.actions.len() {
 953            self.selected_item += 1;
 954            cx.notify()
 955        }
 956    }
 957
 958    fn select_last(&mut self, cx: &mut ViewContext<Editor>) {
 959        self.selected_item = self.actions.len() - 1;
 960        cx.notify()
 961    }
 962
 963    fn visible(&self) -> bool {
 964        !self.actions.is_empty()
 965    }
 966
 967    fn render(
 968        &self,
 969        mut cursor_position: DisplayPoint,
 970        style: EditorStyle,
 971        cx: &mut ViewContext<Editor>,
 972    ) -> (DisplayPoint, AnyElement<Editor>) {
 973        enum ActionTag {}
 974
 975        let container_style = style.autocomplete.container;
 976        let actions = self.actions.clone();
 977        let selected_item = self.selected_item;
 978        let element = UniformList::new(
 979            self.list.clone(),
 980            actions.len(),
 981            cx,
 982            move |_, range, items, cx| {
 983                let start_ix = range.start;
 984                for (ix, action) in actions[range].iter().enumerate() {
 985                    let item_ix = start_ix + ix;
 986                    items.push(
 987                        MouseEventHandler::<ActionTag, _>::new(item_ix, cx, |state, _| {
 988                            let item_style = if item_ix == selected_item {
 989                                style.autocomplete.selected_item
 990                            } else if state.hovered() {
 991                                style.autocomplete.hovered_item
 992                            } else {
 993                                style.autocomplete.item
 994                            };
 995
 996                            Text::new(action.lsp_action.title.clone(), style.text.clone())
 997                                .with_soft_wrap(false)
 998                                .contained()
 999                                .with_style(item_style)
1000                        })
1001                        .with_cursor_style(CursorStyle::PointingHand)
1002                        .on_down(MouseButton::Left, move |_, this, cx| {
1003                            let workspace = this
1004                                .workspace
1005                                .as_ref()
1006                                .and_then(|(workspace, _)| workspace.upgrade(cx));
1007                            cx.window_context().defer(move |cx| {
1008                                if let Some(workspace) = workspace {
1009                                    workspace.update(cx, |workspace, cx| {
1010                                        if let Some(task) = Editor::confirm_code_action(
1011                                            workspace,
1012                                            &Default::default(),
1013                                            cx,
1014                                        ) {
1015                                            task.detach_and_log_err(cx);
1016                                        }
1017                                    });
1018                                }
1019                            });
1020                        })
1021                        .into_any(),
1022                    );
1023                }
1024            },
1025        )
1026        .with_width_from_item(
1027            self.actions
1028                .iter()
1029                .enumerate()
1030                .max_by_key(|(_, action)| action.lsp_action.title.chars().count())
1031                .map(|(ix, _)| ix),
1032        )
1033        .contained()
1034        .with_style(container_style)
1035        .into_any();
1036
1037        if self.deployed_from_indicator {
1038            *cursor_position.column_mut() = 0;
1039        }
1040
1041        (cursor_position, element)
1042    }
1043}
1044
1045pub struct CopilotState {
1046    excerpt_id: Option<ExcerptId>,
1047    pending_refresh: Task<Option<()>>,
1048    pending_cycling_refresh: Task<Option<()>>,
1049    cycled: bool,
1050    completions: Vec<copilot::Completion>,
1051    active_completion_index: usize,
1052}
1053
1054impl Default for CopilotState {
1055    fn default() -> Self {
1056        Self {
1057            excerpt_id: None,
1058            pending_cycling_refresh: Task::ready(Some(())),
1059            pending_refresh: Task::ready(Some(())),
1060            completions: Default::default(),
1061            active_completion_index: 0,
1062            cycled: false,
1063        }
1064    }
1065}
1066
1067impl CopilotState {
1068    fn active_completion(&self) -> Option<&copilot::Completion> {
1069        self.completions.get(self.active_completion_index)
1070    }
1071
1072    fn text_for_active_completion(
1073        &self,
1074        cursor: Anchor,
1075        buffer: &MultiBufferSnapshot,
1076    ) -> Option<&str> {
1077        use language::ToOffset as _;
1078
1079        let completion = self.active_completion()?;
1080        let excerpt_id = self.excerpt_id?;
1081        let completion_buffer = buffer.buffer_for_excerpt(excerpt_id)?;
1082        if excerpt_id != cursor.excerpt_id
1083            || !completion.range.start.is_valid(completion_buffer)
1084            || !completion.range.end.is_valid(completion_buffer)
1085        {
1086            return None;
1087        }
1088
1089        let mut completion_range = completion.range.to_offset(&completion_buffer);
1090        let prefix_len = Self::common_prefix(
1091            completion_buffer.chars_for_range(completion_range.clone()),
1092            completion.text.chars(),
1093        );
1094        completion_range.start += prefix_len;
1095        let suffix_len = Self::common_prefix(
1096            completion_buffer.reversed_chars_for_range(completion_range.clone()),
1097            completion.text[prefix_len..].chars().rev(),
1098        );
1099        completion_range.end = completion_range.end.saturating_sub(suffix_len);
1100
1101        if completion_range.is_empty()
1102            && completion_range.start == cursor.text_anchor.to_offset(&completion_buffer)
1103        {
1104            Some(&completion.text[prefix_len..completion.text.len() - suffix_len])
1105        } else {
1106            None
1107        }
1108    }
1109
1110    fn cycle_completions(&mut self, direction: Direction) {
1111        match direction {
1112            Direction::Prev => {
1113                self.active_completion_index = if self.active_completion_index == 0 {
1114                    self.completions.len().saturating_sub(1)
1115                } else {
1116                    self.active_completion_index - 1
1117                };
1118            }
1119            Direction::Next => {
1120                if self.completions.len() == 0 {
1121                    self.active_completion_index = 0
1122                } else {
1123                    self.active_completion_index =
1124                        (self.active_completion_index + 1) % self.completions.len();
1125                }
1126            }
1127        }
1128    }
1129
1130    fn push_completion(&mut self, new_completion: copilot::Completion) {
1131        for completion in &self.completions {
1132            if completion.text == new_completion.text && completion.range == new_completion.range {
1133                return;
1134            }
1135        }
1136        self.completions.push(new_completion);
1137    }
1138
1139    fn common_prefix<T1: Iterator<Item = char>, T2: Iterator<Item = char>>(a: T1, b: T2) -> usize {
1140        a.zip(b)
1141            .take_while(|(a, b)| a == b)
1142            .map(|(a, _)| a.len_utf8())
1143            .sum()
1144    }
1145}
1146
1147#[derive(Debug)]
1148struct ActiveDiagnosticGroup {
1149    primary_range: Range<Anchor>,
1150    primary_message: String,
1151    blocks: HashMap<BlockId, Diagnostic>,
1152    is_valid: bool,
1153}
1154
1155#[derive(Serialize, Deserialize)]
1156pub struct ClipboardSelection {
1157    pub len: usize,
1158    pub is_entire_line: bool,
1159    pub first_line_indent: u32,
1160}
1161
1162#[derive(Debug)]
1163pub struct NavigationData {
1164    cursor_anchor: Anchor,
1165    cursor_position: Point,
1166    scroll_anchor: ScrollAnchor,
1167    scroll_top_row: u32,
1168}
1169
1170pub struct EditorCreated(pub ViewHandle<Editor>);
1171
1172enum GotoDefinitionKind {
1173    Symbol,
1174    Type,
1175}
1176
1177impl Editor {
1178    pub fn single_line(
1179        field_editor_style: Option<Arc<GetFieldEditorTheme>>,
1180        cx: &mut ViewContext<Self>,
1181    ) -> Self {
1182        let buffer = cx.add_model(|cx| Buffer::new(0, String::new(), cx));
1183        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
1184        Self::new(EditorMode::SingleLine, buffer, None, field_editor_style, cx)
1185    }
1186
1187    pub fn multi_line(
1188        field_editor_style: Option<Arc<GetFieldEditorTheme>>,
1189        cx: &mut ViewContext<Self>,
1190    ) -> Self {
1191        let buffer = cx.add_model(|cx| Buffer::new(0, String::new(), cx));
1192        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
1193        Self::new(EditorMode::Full, buffer, None, field_editor_style, cx)
1194    }
1195
1196    pub fn auto_height(
1197        max_lines: usize,
1198        field_editor_style: Option<Arc<GetFieldEditorTheme>>,
1199        cx: &mut ViewContext<Self>,
1200    ) -> Self {
1201        let buffer = cx.add_model(|cx| Buffer::new(0, String::new(), cx));
1202        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
1203        Self::new(
1204            EditorMode::AutoHeight { max_lines },
1205            buffer,
1206            None,
1207            field_editor_style,
1208            cx,
1209        )
1210    }
1211
1212    pub fn for_buffer(
1213        buffer: ModelHandle<Buffer>,
1214        project: Option<ModelHandle<Project>>,
1215        cx: &mut ViewContext<Self>,
1216    ) -> Self {
1217        let buffer = cx.add_model(|cx| MultiBuffer::singleton(buffer, cx));
1218        Self::new(EditorMode::Full, buffer, project, None, cx)
1219    }
1220
1221    pub fn for_multibuffer(
1222        buffer: ModelHandle<MultiBuffer>,
1223        project: Option<ModelHandle<Project>>,
1224        cx: &mut ViewContext<Self>,
1225    ) -> Self {
1226        Self::new(EditorMode::Full, buffer, project, None, cx)
1227    }
1228
1229    pub fn clone(&self, cx: &mut ViewContext<Self>) -> Self {
1230        let mut clone = Self::new(
1231            self.mode,
1232            self.buffer.clone(),
1233            self.project.clone(),
1234            self.get_field_editor_theme.clone(),
1235            cx,
1236        );
1237        self.display_map.update(cx, |display_map, cx| {
1238            let snapshot = display_map.snapshot(cx);
1239            clone.display_map.update(cx, |display_map, cx| {
1240                display_map.set_state(&snapshot, cx);
1241            });
1242        });
1243        clone.selections.clone_state(&self.selections);
1244        clone.scroll_manager.clone_state(&self.scroll_manager);
1245        clone.searchable = self.searchable;
1246        clone
1247    }
1248
1249    fn new(
1250        mode: EditorMode,
1251        buffer: ModelHandle<MultiBuffer>,
1252        project: Option<ModelHandle<Project>>,
1253        get_field_editor_theme: Option<Arc<GetFieldEditorTheme>>,
1254        cx: &mut ViewContext<Self>,
1255    ) -> Self {
1256        let editor_view_id = cx.view_id();
1257        let display_map = cx.add_model(|cx| {
1258            let settings = settings::get::<ThemeSettings>(cx);
1259            let style = build_style(settings, get_field_editor_theme.as_deref(), None, cx);
1260            DisplayMap::new(
1261                buffer.clone(),
1262                style.text.font_id,
1263                style.text.font_size,
1264                None,
1265                2,
1266                1,
1267                cx,
1268            )
1269        });
1270
1271        let selections = SelectionsCollection::new(display_map.clone(), buffer.clone());
1272
1273        let blink_manager = cx.add_model(|cx| BlinkManager::new(CURSOR_BLINK_INTERVAL, cx));
1274
1275        let soft_wrap_mode_override =
1276            (mode == EditorMode::SingleLine).then(|| language_settings::SoftWrap::None);
1277
1278        let mut project_subscription = None;
1279        if mode == EditorMode::Full && buffer.read(cx).is_singleton() {
1280            if let Some(project) = project.as_ref() {
1281                project_subscription = Some(cx.observe(project, |_, _, cx| {
1282                    cx.emit(Event::TitleChanged);
1283                }))
1284            }
1285        }
1286
1287        let mut this = Self {
1288            handle: cx.weak_handle(),
1289            buffer: buffer.clone(),
1290            display_map: display_map.clone(),
1291            selections,
1292            scroll_manager: ScrollManager::new(),
1293            columnar_selection_tail: None,
1294            add_selections_state: None,
1295            select_next_state: None,
1296            selection_history: Default::default(),
1297            autoclose_regions: Default::default(),
1298            snippet_stack: Default::default(),
1299            select_larger_syntax_node_stack: Vec::new(),
1300            ime_transaction: Default::default(),
1301            active_diagnostics: None,
1302            soft_wrap_mode_override,
1303            get_field_editor_theme,
1304            project,
1305            focused: false,
1306            blink_manager: blink_manager.clone(),
1307            show_local_selections: true,
1308            mode,
1309            placeholder_text: None,
1310            highlighted_rows: None,
1311            background_highlights: Default::default(),
1312            nav_history: None,
1313            context_menu: None,
1314            mouse_context_menu: cx
1315                .add_view(|cx| context_menu::ContextMenu::new(editor_view_id, cx)),
1316            completion_tasks: Default::default(),
1317            next_completion_id: 0,
1318            available_code_actions: Default::default(),
1319            code_actions_task: Default::default(),
1320            document_highlights_task: Default::default(),
1321            pending_rename: Default::default(),
1322            searchable: true,
1323            override_text_style: None,
1324            cursor_shape: Default::default(),
1325            workspace: None,
1326            keymap_context_layers: Default::default(),
1327            input_enabled: true,
1328            read_only: false,
1329            leader_replica_id: None,
1330            remote_id: None,
1331            hover_state: Default::default(),
1332            link_go_to_definition_state: Default::default(),
1333            copilot_state: Default::default(),
1334            gutter_hovered: false,
1335            _subscriptions: vec![
1336                cx.observe(&buffer, Self::on_buffer_changed),
1337                cx.subscribe(&buffer, Self::on_buffer_event),
1338                cx.observe(&display_map, Self::on_display_map_changed),
1339                cx.observe(&blink_manager, |_, _, cx| cx.notify()),
1340                cx.observe_global::<SettingsStore, _>(Self::settings_changed),
1341            ],
1342        };
1343
1344        if let Some(project_subscription) = project_subscription {
1345            this._subscriptions.push(project_subscription);
1346        }
1347
1348        this.end_selection(cx);
1349        this.scroll_manager.show_scrollbar(cx);
1350
1351        let editor_created_event = EditorCreated(cx.handle());
1352        cx.emit_global(editor_created_event);
1353
1354        if mode == EditorMode::Full {
1355            let should_auto_hide_scrollbars = cx.platform().should_auto_hide_scrollbars();
1356            cx.set_global(ScrollbarAutoHide(should_auto_hide_scrollbars));
1357        }
1358
1359        this.report_editor_event("open", None, cx);
1360        this
1361    }
1362
1363    pub fn new_file(
1364        workspace: &mut Workspace,
1365        _: &workspace::NewFile,
1366        cx: &mut ViewContext<Workspace>,
1367    ) {
1368        let project = workspace.project().clone();
1369        if project.read(cx).is_remote() {
1370            cx.propagate_action();
1371        } else if let Some(buffer) = project
1372            .update(cx, |project, cx| project.create_buffer("", None, cx))
1373            .log_err()
1374        {
1375            workspace.add_item(
1376                Box::new(cx.add_view(|cx| Editor::for_buffer(buffer, Some(project.clone()), cx))),
1377                cx,
1378            );
1379        }
1380    }
1381
1382    pub fn replica_id(&self, cx: &AppContext) -> ReplicaId {
1383        self.buffer.read(cx).replica_id()
1384    }
1385
1386    pub fn leader_replica_id(&self) -> Option<ReplicaId> {
1387        self.leader_replica_id
1388    }
1389
1390    pub fn buffer(&self) -> &ModelHandle<MultiBuffer> {
1391        &self.buffer
1392    }
1393
1394    fn workspace(&self, cx: &AppContext) -> Option<ViewHandle<Workspace>> {
1395        self.workspace.as_ref()?.0.upgrade(cx)
1396    }
1397
1398    pub fn title<'a>(&self, cx: &'a AppContext) -> Cow<'a, str> {
1399        self.buffer().read(cx).title(cx)
1400    }
1401
1402    pub fn snapshot(&mut self, cx: &mut WindowContext) -> EditorSnapshot {
1403        EditorSnapshot {
1404            mode: self.mode,
1405            display_snapshot: self.display_map.update(cx, |map, cx| map.snapshot(cx)),
1406            scroll_anchor: self.scroll_manager.anchor(),
1407            ongoing_scroll: self.scroll_manager.ongoing_scroll(),
1408            placeholder_text: self.placeholder_text.clone(),
1409            is_focused: self
1410                .handle
1411                .upgrade(cx)
1412                .map_or(false, |handle| handle.is_focused(cx)),
1413        }
1414    }
1415
1416    pub fn language_at<'a, T: ToOffset>(
1417        &self,
1418        point: T,
1419        cx: &'a AppContext,
1420    ) -> Option<Arc<Language>> {
1421        self.buffer.read(cx).language_at(point, cx)
1422    }
1423
1424    pub fn file_at<'a, T: ToOffset>(&self, point: T, cx: &'a AppContext) -> Option<Arc<dyn File>> {
1425        self.buffer.read(cx).read(cx).file_at(point).cloned()
1426    }
1427
1428    pub fn active_excerpt(
1429        &self,
1430        cx: &AppContext,
1431    ) -> Option<(ExcerptId, ModelHandle<Buffer>, Range<text::Anchor>)> {
1432        self.buffer
1433            .read(cx)
1434            .excerpt_containing(self.selections.newest_anchor().head(), cx)
1435    }
1436
1437    fn style(&self, cx: &AppContext) -> EditorStyle {
1438        build_style(
1439            settings::get::<ThemeSettings>(cx),
1440            self.get_field_editor_theme.as_deref(),
1441            self.override_text_style.as_deref(),
1442            cx,
1443        )
1444    }
1445
1446    pub fn mode(&self) -> EditorMode {
1447        self.mode
1448    }
1449
1450    pub fn set_placeholder_text(
1451        &mut self,
1452        placeholder_text: impl Into<Arc<str>>,
1453        cx: &mut ViewContext<Self>,
1454    ) {
1455        self.placeholder_text = Some(placeholder_text.into());
1456        cx.notify();
1457    }
1458
1459    pub fn set_cursor_shape(&mut self, cursor_shape: CursorShape, cx: &mut ViewContext<Self>) {
1460        self.cursor_shape = cursor_shape;
1461        cx.notify();
1462    }
1463
1464    pub fn set_clip_at_line_ends(&mut self, clip: bool, cx: &mut ViewContext<Self>) {
1465        if self.display_map.read(cx).clip_at_line_ends != clip {
1466            self.display_map
1467                .update(cx, |map, _| map.clip_at_line_ends = clip);
1468        }
1469    }
1470
1471    pub fn set_keymap_context_layer<Tag: 'static>(
1472        &mut self,
1473        context: KeymapContext,
1474        cx: &mut ViewContext<Self>,
1475    ) {
1476        self.keymap_context_layers
1477            .insert(TypeId::of::<Tag>(), context);
1478        cx.notify();
1479    }
1480
1481    pub fn remove_keymap_context_layer<Tag: 'static>(&mut self, cx: &mut ViewContext<Self>) {
1482        self.keymap_context_layers.remove(&TypeId::of::<Tag>());
1483        cx.notify();
1484    }
1485
1486    pub fn set_input_enabled(&mut self, input_enabled: bool) {
1487        self.input_enabled = input_enabled;
1488    }
1489
1490    pub fn set_read_only(&mut self, read_only: bool) {
1491        self.read_only = read_only;
1492    }
1493
1494    fn selections_did_change(
1495        &mut self,
1496        local: bool,
1497        old_cursor_position: &Anchor,
1498        cx: &mut ViewContext<Self>,
1499    ) {
1500        if self.focused && self.leader_replica_id.is_none() {
1501            self.buffer.update(cx, |buffer, cx| {
1502                buffer.set_active_selections(
1503                    &self.selections.disjoint_anchors(),
1504                    self.selections.line_mode,
1505                    self.cursor_shape,
1506                    cx,
1507                )
1508            });
1509        }
1510
1511        let display_map = self
1512            .display_map
1513            .update(cx, |display_map, cx| display_map.snapshot(cx));
1514        let buffer = &display_map.buffer_snapshot;
1515        self.add_selections_state = None;
1516        self.select_next_state = None;
1517        self.select_larger_syntax_node_stack.clear();
1518        self.invalidate_autoclose_regions(&self.selections.disjoint_anchors(), buffer);
1519        self.snippet_stack
1520            .invalidate(&self.selections.disjoint_anchors(), buffer);
1521        self.take_rename(false, cx);
1522
1523        let new_cursor_position = self.selections.newest_anchor().head();
1524
1525        self.push_to_nav_history(
1526            old_cursor_position.clone(),
1527            Some(new_cursor_position.to_point(buffer)),
1528            cx,
1529        );
1530
1531        if local {
1532            let new_cursor_position = self.selections.newest_anchor().head();
1533            let completion_menu = match self.context_menu.as_mut() {
1534                Some(ContextMenu::Completions(menu)) => Some(menu),
1535                _ => {
1536                    self.context_menu.take();
1537                    None
1538                }
1539            };
1540
1541            if let Some(completion_menu) = completion_menu {
1542                let cursor_position = new_cursor_position.to_offset(buffer);
1543                let (word_range, kind) =
1544                    buffer.surrounding_word(completion_menu.initial_position.clone());
1545                if kind == Some(CharKind::Word)
1546                    && word_range.to_inclusive().contains(&cursor_position)
1547                {
1548                    let query = Self::completion_query(buffer, cursor_position);
1549                    cx.background()
1550                        .block(completion_menu.filter(query.as_deref(), cx.background().clone()));
1551                    self.show_completions(&ShowCompletions, cx);
1552                } else {
1553                    self.hide_context_menu(cx);
1554                }
1555            }
1556
1557            hide_hover(self, cx);
1558
1559            if old_cursor_position.to_display_point(&display_map).row()
1560                != new_cursor_position.to_display_point(&display_map).row()
1561            {
1562                self.available_code_actions.take();
1563            }
1564            self.refresh_code_actions(cx);
1565            self.refresh_document_highlights(cx);
1566            refresh_matching_bracket_highlights(self, cx);
1567            self.discard_copilot_suggestion(cx);
1568        }
1569
1570        self.blink_manager.update(cx, BlinkManager::pause_blinking);
1571        cx.emit(Event::SelectionsChanged { local });
1572        cx.notify();
1573    }
1574
1575    pub fn change_selections<R>(
1576        &mut self,
1577        autoscroll: Option<Autoscroll>,
1578        cx: &mut ViewContext<Self>,
1579        change: impl FnOnce(&mut MutableSelectionsCollection<'_>) -> R,
1580    ) -> R {
1581        let old_cursor_position = self.selections.newest_anchor().head();
1582        self.push_to_selection_history();
1583
1584        let (changed, result) = self.selections.change_with(cx, change);
1585
1586        if changed {
1587            if let Some(autoscroll) = autoscroll {
1588                self.request_autoscroll(autoscroll, cx);
1589            }
1590            self.selections_did_change(true, &old_cursor_position, cx);
1591        }
1592
1593        result
1594    }
1595
1596    pub fn edit<I, S, T>(&mut self, edits: I, cx: &mut ViewContext<Self>)
1597    where
1598        I: IntoIterator<Item = (Range<S>, T)>,
1599        S: ToOffset,
1600        T: Into<Arc<str>>,
1601    {
1602        if self.read_only {
1603            return;
1604        }
1605
1606        self.buffer
1607            .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
1608    }
1609
1610    pub fn edit_with_autoindent<I, S, T>(&mut self, edits: I, cx: &mut ViewContext<Self>)
1611    where
1612        I: IntoIterator<Item = (Range<S>, T)>,
1613        S: ToOffset,
1614        T: Into<Arc<str>>,
1615    {
1616        if self.read_only {
1617            return;
1618        }
1619
1620        self.buffer.update(cx, |buffer, cx| {
1621            buffer.edit(edits, Some(AutoindentMode::EachLine), cx)
1622        });
1623    }
1624
1625    fn select(&mut self, phase: SelectPhase, cx: &mut ViewContext<Self>) {
1626        self.hide_context_menu(cx);
1627
1628        match phase {
1629            SelectPhase::Begin {
1630                position,
1631                add,
1632                click_count,
1633            } => self.begin_selection(position, add, click_count, cx),
1634            SelectPhase::BeginColumnar {
1635                position,
1636                goal_column,
1637            } => self.begin_columnar_selection(position, goal_column, cx),
1638            SelectPhase::Extend {
1639                position,
1640                click_count,
1641            } => self.extend_selection(position, click_count, cx),
1642            SelectPhase::Update {
1643                position,
1644                goal_column,
1645                scroll_position,
1646            } => self.update_selection(position, goal_column, scroll_position, cx),
1647            SelectPhase::End => self.end_selection(cx),
1648        }
1649    }
1650
1651    fn extend_selection(
1652        &mut self,
1653        position: DisplayPoint,
1654        click_count: usize,
1655        cx: &mut ViewContext<Self>,
1656    ) {
1657        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1658        let tail = self.selections.newest::<usize>(cx).tail();
1659        self.begin_selection(position, false, click_count, cx);
1660
1661        let position = position.to_offset(&display_map, Bias::Left);
1662        let tail_anchor = display_map.buffer_snapshot.anchor_before(tail);
1663
1664        let mut pending_selection = self
1665            .selections
1666            .pending_anchor()
1667            .expect("extend_selection not called with pending selection");
1668        if position >= tail {
1669            pending_selection.start = tail_anchor;
1670        } else {
1671            pending_selection.end = tail_anchor;
1672            pending_selection.reversed = true;
1673        }
1674
1675        let mut pending_mode = self.selections.pending_mode().unwrap();
1676        match &mut pending_mode {
1677            SelectMode::Word(range) | SelectMode::Line(range) => *range = tail_anchor..tail_anchor,
1678            _ => {}
1679        }
1680
1681        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
1682            s.set_pending(pending_selection, pending_mode)
1683        });
1684    }
1685
1686    fn begin_selection(
1687        &mut self,
1688        position: DisplayPoint,
1689        add: bool,
1690        click_count: usize,
1691        cx: &mut ViewContext<Self>,
1692    ) {
1693        if !self.focused {
1694            cx.focus_self();
1695        }
1696
1697        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1698        let buffer = &display_map.buffer_snapshot;
1699        let newest_selection = self.selections.newest_anchor().clone();
1700        let position = display_map.clip_point(position, Bias::Left);
1701
1702        let start;
1703        let end;
1704        let mode;
1705        let auto_scroll;
1706        match click_count {
1707            1 => {
1708                start = buffer.anchor_before(position.to_point(&display_map));
1709                end = start.clone();
1710                mode = SelectMode::Character;
1711                auto_scroll = true;
1712            }
1713            2 => {
1714                let range = movement::surrounding_word(&display_map, position);
1715                start = buffer.anchor_before(range.start.to_point(&display_map));
1716                end = buffer.anchor_before(range.end.to_point(&display_map));
1717                mode = SelectMode::Word(start.clone()..end.clone());
1718                auto_scroll = true;
1719            }
1720            3 => {
1721                let position = display_map
1722                    .clip_point(position, Bias::Left)
1723                    .to_point(&display_map);
1724                let line_start = display_map.prev_line_boundary(position).0;
1725                let next_line_start = buffer.clip_point(
1726                    display_map.next_line_boundary(position).0 + Point::new(1, 0),
1727                    Bias::Left,
1728                );
1729                start = buffer.anchor_before(line_start);
1730                end = buffer.anchor_before(next_line_start);
1731                mode = SelectMode::Line(start.clone()..end.clone());
1732                auto_scroll = true;
1733            }
1734            _ => {
1735                start = buffer.anchor_before(0);
1736                end = buffer.anchor_before(buffer.len());
1737                mode = SelectMode::All;
1738                auto_scroll = false;
1739            }
1740        }
1741
1742        self.change_selections(auto_scroll.then(|| Autoscroll::newest()), cx, |s| {
1743            if !add {
1744                s.clear_disjoint();
1745            } else if click_count > 1 {
1746                s.delete(newest_selection.id)
1747            }
1748
1749            s.set_pending_anchor_range(start..end, mode);
1750        });
1751    }
1752
1753    fn begin_columnar_selection(
1754        &mut self,
1755        position: DisplayPoint,
1756        goal_column: u32,
1757        cx: &mut ViewContext<Self>,
1758    ) {
1759        if !self.focused {
1760            cx.focus_self();
1761        }
1762
1763        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1764        let tail = self.selections.newest::<Point>(cx).tail();
1765        self.columnar_selection_tail = Some(display_map.buffer_snapshot.anchor_before(tail));
1766
1767        self.select_columns(
1768            tail.to_display_point(&display_map),
1769            position,
1770            goal_column,
1771            &display_map,
1772            cx,
1773        );
1774    }
1775
1776    fn update_selection(
1777        &mut self,
1778        position: DisplayPoint,
1779        goal_column: u32,
1780        scroll_position: Vector2F,
1781        cx: &mut ViewContext<Self>,
1782    ) {
1783        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1784
1785        if let Some(tail) = self.columnar_selection_tail.as_ref() {
1786            let tail = tail.to_display_point(&display_map);
1787            self.select_columns(tail, position, goal_column, &display_map, cx);
1788        } else if let Some(mut pending) = self.selections.pending_anchor() {
1789            let buffer = self.buffer.read(cx).snapshot(cx);
1790            let head;
1791            let tail;
1792            let mode = self.selections.pending_mode().unwrap();
1793            match &mode {
1794                SelectMode::Character => {
1795                    head = position.to_point(&display_map);
1796                    tail = pending.tail().to_point(&buffer);
1797                }
1798                SelectMode::Word(original_range) => {
1799                    let original_display_range = original_range.start.to_display_point(&display_map)
1800                        ..original_range.end.to_display_point(&display_map);
1801                    let original_buffer_range = original_display_range.start.to_point(&display_map)
1802                        ..original_display_range.end.to_point(&display_map);
1803                    if movement::is_inside_word(&display_map, position)
1804                        || original_display_range.contains(&position)
1805                    {
1806                        let word_range = movement::surrounding_word(&display_map, position);
1807                        if word_range.start < original_display_range.start {
1808                            head = word_range.start.to_point(&display_map);
1809                        } else {
1810                            head = word_range.end.to_point(&display_map);
1811                        }
1812                    } else {
1813                        head = position.to_point(&display_map);
1814                    }
1815
1816                    if head <= original_buffer_range.start {
1817                        tail = original_buffer_range.end;
1818                    } else {
1819                        tail = original_buffer_range.start;
1820                    }
1821                }
1822                SelectMode::Line(original_range) => {
1823                    let original_range = original_range.to_point(&display_map.buffer_snapshot);
1824
1825                    let position = display_map
1826                        .clip_point(position, Bias::Left)
1827                        .to_point(&display_map);
1828                    let line_start = display_map.prev_line_boundary(position).0;
1829                    let next_line_start = buffer.clip_point(
1830                        display_map.next_line_boundary(position).0 + Point::new(1, 0),
1831                        Bias::Left,
1832                    );
1833
1834                    if line_start < original_range.start {
1835                        head = line_start
1836                    } else {
1837                        head = next_line_start
1838                    }
1839
1840                    if head <= original_range.start {
1841                        tail = original_range.end;
1842                    } else {
1843                        tail = original_range.start;
1844                    }
1845                }
1846                SelectMode::All => {
1847                    return;
1848                }
1849            };
1850
1851            if head < tail {
1852                pending.start = buffer.anchor_before(head);
1853                pending.end = buffer.anchor_before(tail);
1854                pending.reversed = true;
1855            } else {
1856                pending.start = buffer.anchor_before(tail);
1857                pending.end = buffer.anchor_before(head);
1858                pending.reversed = false;
1859            }
1860
1861            self.change_selections(None, cx, |s| {
1862                s.set_pending(pending, mode);
1863            });
1864        } else {
1865            log::error!("update_selection dispatched with no pending selection");
1866            return;
1867        }
1868
1869        self.set_scroll_position(scroll_position, cx);
1870        cx.notify();
1871    }
1872
1873    fn end_selection(&mut self, cx: &mut ViewContext<Self>) {
1874        self.columnar_selection_tail.take();
1875        if self.selections.pending_anchor().is_some() {
1876            let selections = self.selections.all::<usize>(cx);
1877            self.change_selections(None, cx, |s| {
1878                s.select(selections);
1879                s.clear_pending();
1880            });
1881        }
1882    }
1883
1884    fn select_columns(
1885        &mut self,
1886        tail: DisplayPoint,
1887        head: DisplayPoint,
1888        goal_column: u32,
1889        display_map: &DisplaySnapshot,
1890        cx: &mut ViewContext<Self>,
1891    ) {
1892        let start_row = cmp::min(tail.row(), head.row());
1893        let end_row = cmp::max(tail.row(), head.row());
1894        let start_column = cmp::min(tail.column(), goal_column);
1895        let end_column = cmp::max(tail.column(), goal_column);
1896        let reversed = start_column < tail.column();
1897
1898        let selection_ranges = (start_row..=end_row)
1899            .filter_map(|row| {
1900                if start_column <= display_map.line_len(row) && !display_map.is_block_line(row) {
1901                    let start = display_map
1902                        .clip_point(DisplayPoint::new(row, start_column), Bias::Left)
1903                        .to_point(display_map);
1904                    let end = display_map
1905                        .clip_point(DisplayPoint::new(row, end_column), Bias::Right)
1906                        .to_point(display_map);
1907                    if reversed {
1908                        Some(end..start)
1909                    } else {
1910                        Some(start..end)
1911                    }
1912                } else {
1913                    None
1914                }
1915            })
1916            .collect::<Vec<_>>();
1917
1918        self.change_selections(None, cx, |s| {
1919            s.select_ranges(selection_ranges);
1920        });
1921        cx.notify();
1922    }
1923
1924    pub fn has_pending_nonempty_selection(&self) -> bool {
1925        let pending_nonempty_selection = match self.selections.pending_anchor() {
1926            Some(Selection { start, end, .. }) => start != end,
1927            None => false,
1928        };
1929        pending_nonempty_selection || self.columnar_selection_tail.is_some()
1930    }
1931
1932    pub fn has_pending_selection(&self) -> bool {
1933        self.selections.pending_anchor().is_some() || self.columnar_selection_tail.is_some()
1934    }
1935
1936    pub fn cancel(&mut self, _: &Cancel, cx: &mut ViewContext<Self>) {
1937        if self.take_rename(false, cx).is_some() {
1938            return;
1939        }
1940
1941        if hide_hover(self, cx) {
1942            return;
1943        }
1944
1945        if self.hide_context_menu(cx).is_some() {
1946            return;
1947        }
1948
1949        if self.discard_copilot_suggestion(cx) {
1950            return;
1951        }
1952
1953        if self.snippet_stack.pop().is_some() {
1954            return;
1955        }
1956
1957        if self.mode == EditorMode::Full {
1958            if self.active_diagnostics.is_some() {
1959                self.dismiss_diagnostics(cx);
1960                return;
1961            }
1962
1963            if self.change_selections(Some(Autoscroll::fit()), cx, |s| s.try_cancel()) {
1964                return;
1965            }
1966        }
1967
1968        cx.propagate_action();
1969    }
1970
1971    pub fn handle_input(&mut self, text: &str, cx: &mut ViewContext<Self>) {
1972        let text: Arc<str> = text.into();
1973
1974        if self.read_only {
1975            return;
1976        }
1977        if !self.input_enabled {
1978            cx.emit(Event::InputIgnored { text });
1979            return;
1980        }
1981
1982        let selections = self.selections.all_adjusted(cx);
1983        let mut edits = Vec::new();
1984        let mut new_selections = Vec::with_capacity(selections.len());
1985        let mut new_autoclose_regions = Vec::new();
1986        let snapshot = self.buffer.read(cx).read(cx);
1987
1988        for (selection, autoclose_region) in
1989            self.selections_with_autoclose_regions(selections, &snapshot)
1990        {
1991            if let Some(language) = snapshot.language_scope_at(selection.head()) {
1992                // Determine if the inserted text matches the opening or closing
1993                // bracket of any of this language's bracket pairs.
1994                let mut bracket_pair = None;
1995                let mut is_bracket_pair_start = false;
1996                for (pair, enabled) in language.brackets() {
1997                    if enabled && pair.close && pair.start.ends_with(text.as_ref()) {
1998                        bracket_pair = Some(pair.clone());
1999                        is_bracket_pair_start = true;
2000                        break;
2001                    } else if pair.end.as_str() == text.as_ref() {
2002                        bracket_pair = Some(pair.clone());
2003                        break;
2004                    }
2005                }
2006
2007                if let Some(bracket_pair) = bracket_pair {
2008                    if selection.is_empty() {
2009                        if is_bracket_pair_start {
2010                            let prefix_len = bracket_pair.start.len() - text.len();
2011
2012                            // If the inserted text is a suffix of an opening bracket and the
2013                            // selection is preceded by the rest of the opening bracket, then
2014                            // insert the closing bracket.
2015                            let following_text_allows_autoclose = snapshot
2016                                .chars_at(selection.start)
2017                                .next()
2018                                .map_or(true, |c| language.should_autoclose_before(c));
2019                            let preceding_text_matches_prefix = prefix_len == 0
2020                                || (selection.start.column >= (prefix_len as u32)
2021                                    && snapshot.contains_str_at(
2022                                        Point::new(
2023                                            selection.start.row,
2024                                            selection.start.column - (prefix_len as u32),
2025                                        ),
2026                                        &bracket_pair.start[..prefix_len],
2027                                    ));
2028                            if following_text_allows_autoclose && preceding_text_matches_prefix {
2029                                let anchor = snapshot.anchor_before(selection.end);
2030                                new_selections.push((selection.map(|_| anchor), text.len()));
2031                                new_autoclose_regions.push((
2032                                    anchor,
2033                                    text.len(),
2034                                    selection.id,
2035                                    bracket_pair.clone(),
2036                                ));
2037                                edits.push((
2038                                    selection.range(),
2039                                    format!("{}{}", text, bracket_pair.end).into(),
2040                                ));
2041                                continue;
2042                            }
2043                        }
2044
2045                        if let Some(region) = autoclose_region {
2046                            // If the selection is followed by an auto-inserted closing bracket,
2047                            // then don't insert that closing bracket again; just move the selection
2048                            // past the closing bracket.
2049                            let should_skip = selection.end == region.range.end.to_point(&snapshot)
2050                                && text.as_ref() == region.pair.end.as_str();
2051                            if should_skip {
2052                                let anchor = snapshot.anchor_after(selection.end);
2053                                new_selections
2054                                    .push((selection.map(|_| anchor), region.pair.end.len()));
2055                                continue;
2056                            }
2057                        }
2058                    }
2059                    // If an opening bracket is 1 character long and is typed while
2060                    // text is selected, then surround that text with the bracket pair.
2061                    else if is_bracket_pair_start && bracket_pair.start.chars().count() == 1 {
2062                        edits.push((selection.start..selection.start, text.clone()));
2063                        edits.push((
2064                            selection.end..selection.end,
2065                            bracket_pair.end.as_str().into(),
2066                        ));
2067                        new_selections.push((
2068                            Selection {
2069                                id: selection.id,
2070                                start: snapshot.anchor_after(selection.start),
2071                                end: snapshot.anchor_before(selection.end),
2072                                reversed: selection.reversed,
2073                                goal: selection.goal,
2074                            },
2075                            0,
2076                        ));
2077                        continue;
2078                    }
2079                }
2080            }
2081
2082            // If not handling any auto-close operation, then just replace the selected
2083            // text with the given input and move the selection to the end of the
2084            // newly inserted text.
2085            let anchor = snapshot.anchor_after(selection.end);
2086            new_selections.push((selection.map(|_| anchor), 0));
2087            edits.push((selection.start..selection.end, text.clone()));
2088        }
2089
2090        drop(snapshot);
2091        self.transact(cx, |this, cx| {
2092            this.buffer.update(cx, |buffer, cx| {
2093                buffer.edit(edits, Some(AutoindentMode::EachLine), cx);
2094            });
2095
2096            let new_anchor_selections = new_selections.iter().map(|e| &e.0);
2097            let new_selection_deltas = new_selections.iter().map(|e| e.1);
2098            let snapshot = this.buffer.read(cx).read(cx);
2099            let new_selections = resolve_multiple::<usize, _>(new_anchor_selections, &snapshot)
2100                .zip(new_selection_deltas)
2101                .map(|(selection, delta)| selection.map(|e| e + delta))
2102                .collect::<Vec<_>>();
2103
2104            let mut i = 0;
2105            for (position, delta, selection_id, pair) in new_autoclose_regions {
2106                let position = position.to_offset(&snapshot) + delta;
2107                let start = snapshot.anchor_before(position);
2108                let end = snapshot.anchor_after(position);
2109                while let Some(existing_state) = this.autoclose_regions.get(i) {
2110                    match existing_state.range.start.cmp(&start, &snapshot) {
2111                        Ordering::Less => i += 1,
2112                        Ordering::Greater => break,
2113                        Ordering::Equal => match end.cmp(&existing_state.range.end, &snapshot) {
2114                            Ordering::Less => i += 1,
2115                            Ordering::Equal => break,
2116                            Ordering::Greater => break,
2117                        },
2118                    }
2119                }
2120                this.autoclose_regions.insert(
2121                    i,
2122                    AutocloseRegion {
2123                        selection_id,
2124                        range: start..end,
2125                        pair,
2126                    },
2127                );
2128            }
2129
2130            drop(snapshot);
2131            let had_active_copilot_suggestion = this.has_active_copilot_suggestion(cx);
2132            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(new_selections));
2133
2134            if had_active_copilot_suggestion {
2135                this.refresh_copilot_suggestions(true, cx);
2136                if !this.has_active_copilot_suggestion(cx) {
2137                    this.trigger_completion_on_input(&text, cx);
2138                }
2139            } else {
2140                this.trigger_completion_on_input(&text, cx);
2141                this.refresh_copilot_suggestions(true, cx);
2142            }
2143        });
2144    }
2145
2146    pub fn newline(&mut self, _: &Newline, cx: &mut ViewContext<Self>) {
2147        self.transact(cx, |this, cx| {
2148            let (edits, selection_fixup_info): (Vec<_>, Vec<_>) = {
2149                let selections = this.selections.all::<usize>(cx);
2150
2151                let buffer = this.buffer.read(cx).snapshot(cx);
2152                selections
2153                    .iter()
2154                    .map(|selection| {
2155                        let start_point = selection.start.to_point(&buffer);
2156                        let mut indent = buffer.indent_size_for_line(start_point.row);
2157                        indent.len = cmp::min(indent.len, start_point.column);
2158                        let start = selection.start;
2159                        let end = selection.end;
2160
2161                        let mut insert_extra_newline = false;
2162                        if let Some(language) = buffer.language_scope_at(start) {
2163                            let leading_whitespace_len = buffer
2164                                .reversed_chars_at(start)
2165                                .take_while(|c| c.is_whitespace() && *c != '\n')
2166                                .map(|c| c.len_utf8())
2167                                .sum::<usize>();
2168
2169                            let trailing_whitespace_len = buffer
2170                                .chars_at(end)
2171                                .take_while(|c| c.is_whitespace() && *c != '\n')
2172                                .map(|c| c.len_utf8())
2173                                .sum::<usize>();
2174
2175                            insert_extra_newline = language.brackets().any(|(pair, enabled)| {
2176                                let pair_start = pair.start.trim_end();
2177                                let pair_end = pair.end.trim_start();
2178
2179                                enabled
2180                                    && pair.newline
2181                                    && buffer
2182                                        .contains_str_at(end + trailing_whitespace_len, pair_end)
2183                                    && buffer.contains_str_at(
2184                                        (start - leading_whitespace_len)
2185                                            .saturating_sub(pair_start.len()),
2186                                        pair_start,
2187                                    )
2188                            });
2189                        }
2190
2191                        let mut new_text = String::with_capacity(1 + indent.len as usize);
2192                        new_text.push('\n');
2193                        new_text.extend(indent.chars());
2194                        if insert_extra_newline {
2195                            new_text = new_text.repeat(2);
2196                        }
2197
2198                        let anchor = buffer.anchor_after(end);
2199                        let new_selection = selection.map(|_| anchor);
2200                        (
2201                            (start..end, new_text),
2202                            (insert_extra_newline, new_selection),
2203                        )
2204                    })
2205                    .unzip()
2206            };
2207
2208            this.edit_with_autoindent(edits, cx);
2209            let buffer = this.buffer.read(cx).snapshot(cx);
2210            let new_selections = selection_fixup_info
2211                .into_iter()
2212                .map(|(extra_newline_inserted, new_selection)| {
2213                    let mut cursor = new_selection.end.to_point(&buffer);
2214                    if extra_newline_inserted {
2215                        cursor.row -= 1;
2216                        cursor.column = buffer.line_len(cursor.row);
2217                    }
2218                    new_selection.map(|_| cursor)
2219                })
2220                .collect();
2221
2222            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(new_selections));
2223            this.refresh_copilot_suggestions(true, cx);
2224        });
2225    }
2226
2227    pub fn newline_above(&mut self, _: &NewlineAbove, cx: &mut ViewContext<Self>) {
2228        let buffer = self.buffer.read(cx);
2229        let snapshot = buffer.snapshot(cx);
2230
2231        let mut edits = Vec::new();
2232        let mut rows = Vec::new();
2233        let mut rows_inserted = 0;
2234
2235        for selection in self.selections.all_adjusted(cx) {
2236            let cursor = selection.head();
2237            let row = cursor.row;
2238
2239            let start_of_line = snapshot.clip_point(Point::new(row, 0), Bias::Left);
2240
2241            let newline = "\n".to_string();
2242            edits.push((start_of_line..start_of_line, newline));
2243
2244            rows.push(row + rows_inserted);
2245            rows_inserted += 1;
2246        }
2247
2248        self.transact(cx, |editor, cx| {
2249            editor.edit(edits, cx);
2250
2251            editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
2252                let mut index = 0;
2253                s.move_cursors_with(|map, _, _| {
2254                    let row = rows[index];
2255                    index += 1;
2256
2257                    let point = Point::new(row, 0);
2258                    let boundary = map.next_line_boundary(point).1;
2259                    let clipped = map.clip_point(boundary, Bias::Left);
2260
2261                    (clipped, SelectionGoal::None)
2262                });
2263            });
2264
2265            let mut indent_edits = Vec::new();
2266            let multibuffer_snapshot = editor.buffer.read(cx).snapshot(cx);
2267            for row in rows {
2268                let indents = multibuffer_snapshot.suggested_indents(row..row + 1, cx);
2269                for (row, indent) in indents {
2270                    if indent.len == 0 {
2271                        continue;
2272                    }
2273
2274                    let text = match indent.kind {
2275                        IndentKind::Space => " ".repeat(indent.len as usize),
2276                        IndentKind::Tab => "\t".repeat(indent.len as usize),
2277                    };
2278                    let point = Point::new(row, 0);
2279                    indent_edits.push((point..point, text));
2280                }
2281            }
2282            editor.edit(indent_edits, cx);
2283        });
2284    }
2285
2286    pub fn newline_below(&mut self, _: &NewlineBelow, cx: &mut ViewContext<Self>) {
2287        let buffer = self.buffer.read(cx);
2288        let snapshot = buffer.snapshot(cx);
2289
2290        let mut edits = Vec::new();
2291        let mut rows = Vec::new();
2292        let mut rows_inserted = 0;
2293
2294        for selection in self.selections.all_adjusted(cx) {
2295            let cursor = selection.head();
2296            let row = cursor.row;
2297
2298            let point = Point::new(row + 1, 0);
2299            let start_of_line = snapshot.clip_point(point, Bias::Left);
2300
2301            let newline = "\n".to_string();
2302            edits.push((start_of_line..start_of_line, newline));
2303
2304            rows_inserted += 1;
2305            rows.push(row + rows_inserted);
2306        }
2307
2308        self.transact(cx, |editor, cx| {
2309            editor.edit(edits, cx);
2310
2311            editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
2312                let mut index = 0;
2313                s.move_cursors_with(|map, _, _| {
2314                    let row = rows[index];
2315                    index += 1;
2316
2317                    let point = Point::new(row, 0);
2318                    let boundary = map.next_line_boundary(point).1;
2319                    let clipped = map.clip_point(boundary, Bias::Left);
2320
2321                    (clipped, SelectionGoal::None)
2322                });
2323            });
2324
2325            let mut indent_edits = Vec::new();
2326            let multibuffer_snapshot = editor.buffer.read(cx).snapshot(cx);
2327            for row in rows {
2328                let indents = multibuffer_snapshot.suggested_indents(row..row + 1, cx);
2329                for (row, indent) in indents {
2330                    if indent.len == 0 {
2331                        continue;
2332                    }
2333
2334                    let text = match indent.kind {
2335                        IndentKind::Space => " ".repeat(indent.len as usize),
2336                        IndentKind::Tab => "\t".repeat(indent.len as usize),
2337                    };
2338                    let point = Point::new(row, 0);
2339                    indent_edits.push((point..point, text));
2340                }
2341            }
2342            editor.edit(indent_edits, cx);
2343        });
2344    }
2345
2346    pub fn insert(&mut self, text: &str, cx: &mut ViewContext<Self>) {
2347        self.insert_with_autoindent_mode(
2348            text,
2349            Some(AutoindentMode::Block {
2350                original_indent_columns: Vec::new(),
2351            }),
2352            cx,
2353        );
2354    }
2355
2356    fn insert_with_autoindent_mode(
2357        &mut self,
2358        text: &str,
2359        autoindent_mode: Option<AutoindentMode>,
2360        cx: &mut ViewContext<Self>,
2361    ) {
2362        if self.read_only {
2363            return;
2364        }
2365
2366        let text: Arc<str> = text.into();
2367        self.transact(cx, |this, cx| {
2368            let old_selections = this.selections.all_adjusted(cx);
2369            let selection_anchors = this.buffer.update(cx, |buffer, cx| {
2370                let anchors = {
2371                    let snapshot = buffer.read(cx);
2372                    old_selections
2373                        .iter()
2374                        .map(|s| {
2375                            let anchor = snapshot.anchor_after(s.end);
2376                            s.map(|_| anchor)
2377                        })
2378                        .collect::<Vec<_>>()
2379                };
2380                buffer.edit(
2381                    old_selections
2382                        .iter()
2383                        .map(|s| (s.start..s.end, text.clone())),
2384                    autoindent_mode,
2385                    cx,
2386                );
2387                anchors
2388            });
2389
2390            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
2391                s.select_anchors(selection_anchors);
2392            })
2393        });
2394    }
2395
2396    fn trigger_completion_on_input(&mut self, text: &str, cx: &mut ViewContext<Self>) {
2397        if !settings::get::<EditorSettings>(cx).show_completions_on_input {
2398            return;
2399        }
2400
2401        let selection = self.selections.newest_anchor();
2402        if self
2403            .buffer
2404            .read(cx)
2405            .is_completion_trigger(selection.head(), text, cx)
2406        {
2407            self.show_completions(&ShowCompletions, cx);
2408        } else {
2409            self.hide_context_menu(cx);
2410        }
2411    }
2412
2413    /// If any empty selections is touching the start of its innermost containing autoclose
2414    /// region, expand it to select the brackets.
2415    fn select_autoclose_pair(&mut self, cx: &mut ViewContext<Self>) {
2416        let selections = self.selections.all::<usize>(cx);
2417        let buffer = self.buffer.read(cx).read(cx);
2418        let mut new_selections = Vec::new();
2419        for (mut selection, region) in self.selections_with_autoclose_regions(selections, &buffer) {
2420            if let (Some(region), true) = (region, selection.is_empty()) {
2421                let mut range = region.range.to_offset(&buffer);
2422                if selection.start == range.start {
2423                    if range.start >= region.pair.start.len() {
2424                        range.start -= region.pair.start.len();
2425                        if buffer.contains_str_at(range.start, &region.pair.start) {
2426                            if buffer.contains_str_at(range.end, &region.pair.end) {
2427                                range.end += region.pair.end.len();
2428                                selection.start = range.start;
2429                                selection.end = range.end;
2430                            }
2431                        }
2432                    }
2433                }
2434            }
2435            new_selections.push(selection);
2436        }
2437
2438        drop(buffer);
2439        self.change_selections(None, cx, |selections| selections.select(new_selections));
2440    }
2441
2442    /// Iterate the given selections, and for each one, find the smallest surrounding
2443    /// autoclose region. This uses the ordering of the selections and the autoclose
2444    /// regions to avoid repeated comparisons.
2445    fn selections_with_autoclose_regions<'a, D: ToOffset + Clone>(
2446        &'a self,
2447        selections: impl IntoIterator<Item = Selection<D>>,
2448        buffer: &'a MultiBufferSnapshot,
2449    ) -> impl Iterator<Item = (Selection<D>, Option<&'a AutocloseRegion>)> {
2450        let mut i = 0;
2451        let mut regions = self.autoclose_regions.as_slice();
2452        selections.into_iter().map(move |selection| {
2453            let range = selection.start.to_offset(buffer)..selection.end.to_offset(buffer);
2454
2455            let mut enclosing = None;
2456            while let Some(pair_state) = regions.get(i) {
2457                if pair_state.range.end.to_offset(buffer) < range.start {
2458                    regions = &regions[i + 1..];
2459                    i = 0;
2460                } else if pair_state.range.start.to_offset(buffer) > range.end {
2461                    break;
2462                } else if pair_state.selection_id == selection.id {
2463                    enclosing = Some(pair_state);
2464                    i += 1;
2465                }
2466            }
2467
2468            (selection.clone(), enclosing)
2469        })
2470    }
2471
2472    /// Remove any autoclose regions that no longer contain their selection.
2473    fn invalidate_autoclose_regions(
2474        &mut self,
2475        mut selections: &[Selection<Anchor>],
2476        buffer: &MultiBufferSnapshot,
2477    ) {
2478        self.autoclose_regions.retain(|state| {
2479            let mut i = 0;
2480            while let Some(selection) = selections.get(i) {
2481                if selection.end.cmp(&state.range.start, buffer).is_lt() {
2482                    selections = &selections[1..];
2483                    continue;
2484                }
2485                if selection.start.cmp(&state.range.end, buffer).is_gt() {
2486                    break;
2487                }
2488                if selection.id == state.selection_id {
2489                    return true;
2490                } else {
2491                    i += 1;
2492                }
2493            }
2494            false
2495        });
2496    }
2497
2498    fn completion_query(buffer: &MultiBufferSnapshot, position: impl ToOffset) -> Option<String> {
2499        let offset = position.to_offset(buffer);
2500        let (word_range, kind) = buffer.surrounding_word(offset);
2501        if offset > word_range.start && kind == Some(CharKind::Word) {
2502            Some(
2503                buffer
2504                    .text_for_range(word_range.start..offset)
2505                    .collect::<String>(),
2506            )
2507        } else {
2508            None
2509        }
2510    }
2511
2512    fn show_completions(&mut self, _: &ShowCompletions, cx: &mut ViewContext<Self>) {
2513        if self.pending_rename.is_some() {
2514            return;
2515        }
2516
2517        let project = if let Some(project) = self.project.clone() {
2518            project
2519        } else {
2520            return;
2521        };
2522
2523        let position = self.selections.newest_anchor().head();
2524        let (buffer, buffer_position) = if let Some(output) = self
2525            .buffer
2526            .read(cx)
2527            .text_anchor_for_position(position.clone(), cx)
2528        {
2529            output
2530        } else {
2531            return;
2532        };
2533
2534        let query = Self::completion_query(&self.buffer.read(cx).read(cx), position.clone());
2535        let completions = project.update(cx, |project, cx| {
2536            project.completions(&buffer, buffer_position, cx)
2537        });
2538
2539        let id = post_inc(&mut self.next_completion_id);
2540        let task = cx.spawn(|this, mut cx| {
2541            async move {
2542                let menu = if let Some(completions) = completions.await.log_err() {
2543                    let mut menu = CompletionsMenu {
2544                        id,
2545                        initial_position: position,
2546                        match_candidates: completions
2547                            .iter()
2548                            .enumerate()
2549                            .map(|(id, completion)| {
2550                                StringMatchCandidate::new(
2551                                    id,
2552                                    completion.label.text[completion.label.filter_range.clone()]
2553                                        .into(),
2554                                )
2555                            })
2556                            .collect(),
2557                        buffer,
2558                        completions: completions.into(),
2559                        matches: Vec::new().into(),
2560                        selected_item: 0,
2561                        list: Default::default(),
2562                    };
2563                    menu.filter(query.as_deref(), cx.background()).await;
2564                    if menu.matches.is_empty() {
2565                        None
2566                    } else {
2567                        Some(menu)
2568                    }
2569                } else {
2570                    None
2571                };
2572
2573                this.update(&mut cx, |this, cx| {
2574                    this.completion_tasks.retain(|(task_id, _)| *task_id > id);
2575
2576                    match this.context_menu.as_ref() {
2577                        None => {}
2578                        Some(ContextMenu::Completions(prev_menu)) => {
2579                            if prev_menu.id > id {
2580                                return;
2581                            }
2582                        }
2583                        _ => return,
2584                    }
2585
2586                    if this.focused && menu.is_some() {
2587                        let menu = menu.unwrap();
2588                        this.show_context_menu(ContextMenu::Completions(menu), cx);
2589                    } else if this.completion_tasks.is_empty() {
2590                        // If there are no more completion tasks and the last menu was
2591                        // empty, we should hide it. If it was already hidden, we should
2592                        // also show the copilot suggestion when available.
2593                        if this.hide_context_menu(cx).is_none() {
2594                            this.update_visible_copilot_suggestion(cx);
2595                        }
2596                    }
2597                })?;
2598
2599                Ok::<_, anyhow::Error>(())
2600            }
2601            .log_err()
2602        });
2603        self.completion_tasks.push((id, task));
2604    }
2605
2606    pub fn confirm_completion(
2607        &mut self,
2608        action: &ConfirmCompletion,
2609        cx: &mut ViewContext<Self>,
2610    ) -> Option<Task<Result<()>>> {
2611        use language::ToOffset as _;
2612
2613        let completions_menu = if let ContextMenu::Completions(menu) = self.hide_context_menu(cx)? {
2614            menu
2615        } else {
2616            return None;
2617        };
2618
2619        let mat = completions_menu
2620            .matches
2621            .get(action.item_ix.unwrap_or(completions_menu.selected_item))?;
2622        let buffer_handle = completions_menu.buffer;
2623        let completion = completions_menu.completions.get(mat.candidate_id)?;
2624
2625        let snippet;
2626        let text;
2627        if completion.is_snippet() {
2628            snippet = Some(Snippet::parse(&completion.new_text).log_err()?);
2629            text = snippet.as_ref().unwrap().text.clone();
2630        } else {
2631            snippet = None;
2632            text = completion.new_text.clone();
2633        };
2634        let selections = self.selections.all::<usize>(cx);
2635        let buffer = buffer_handle.read(cx);
2636        let old_range = completion.old_range.to_offset(buffer);
2637        let old_text = buffer.text_for_range(old_range.clone()).collect::<String>();
2638
2639        let newest_selection = self.selections.newest_anchor();
2640        if newest_selection.start.buffer_id != Some(buffer_handle.read(cx).remote_id()) {
2641            return None;
2642        }
2643
2644        let lookbehind = newest_selection
2645            .start
2646            .text_anchor
2647            .to_offset(buffer)
2648            .saturating_sub(old_range.start);
2649        let lookahead = old_range
2650            .end
2651            .saturating_sub(newest_selection.end.text_anchor.to_offset(buffer));
2652        let mut common_prefix_len = old_text
2653            .bytes()
2654            .zip(text.bytes())
2655            .take_while(|(a, b)| a == b)
2656            .count();
2657
2658        let snapshot = self.buffer.read(cx).snapshot(cx);
2659        let mut ranges = Vec::new();
2660        for selection in &selections {
2661            if snapshot.contains_str_at(selection.start.saturating_sub(lookbehind), &old_text) {
2662                let start = selection.start.saturating_sub(lookbehind);
2663                let end = selection.end + lookahead;
2664                ranges.push(start + common_prefix_len..end);
2665            } else {
2666                common_prefix_len = 0;
2667                ranges.clear();
2668                ranges.extend(selections.iter().map(|s| {
2669                    if s.id == newest_selection.id {
2670                        old_range.clone()
2671                    } else {
2672                        s.start..s.end
2673                    }
2674                }));
2675                break;
2676            }
2677        }
2678        let text = &text[common_prefix_len..];
2679
2680        self.transact(cx, |this, cx| {
2681            if let Some(mut snippet) = snippet {
2682                snippet.text = text.to_string();
2683                for tabstop in snippet.tabstops.iter_mut().flatten() {
2684                    tabstop.start -= common_prefix_len as isize;
2685                    tabstop.end -= common_prefix_len as isize;
2686                }
2687
2688                this.insert_snippet(&ranges, snippet, cx).log_err();
2689            } else {
2690                this.buffer.update(cx, |buffer, cx| {
2691                    buffer.edit(
2692                        ranges.iter().map(|range| (range.clone(), text)),
2693                        Some(AutoindentMode::EachLine),
2694                        cx,
2695                    );
2696                });
2697            }
2698
2699            this.refresh_copilot_suggestions(true, cx);
2700        });
2701
2702        let project = self.project.clone()?;
2703        let apply_edits = project.update(cx, |project, cx| {
2704            project.apply_additional_edits_for_completion(
2705                buffer_handle,
2706                completion.clone(),
2707                true,
2708                cx,
2709            )
2710        });
2711        Some(cx.foreground().spawn(async move {
2712            apply_edits.await?;
2713            Ok(())
2714        }))
2715    }
2716
2717    pub fn toggle_code_actions(&mut self, action: &ToggleCodeActions, cx: &mut ViewContext<Self>) {
2718        if matches!(
2719            self.context_menu.as_ref(),
2720            Some(ContextMenu::CodeActions(_))
2721        ) {
2722            self.context_menu.take();
2723            cx.notify();
2724            return;
2725        }
2726
2727        let deployed_from_indicator = action.deployed_from_indicator;
2728        let mut task = self.code_actions_task.take();
2729        cx.spawn(|this, mut cx| async move {
2730            while let Some(prev_task) = task {
2731                prev_task.await;
2732                task = this.update(&mut cx, |this, _| this.code_actions_task.take())?;
2733            }
2734
2735            this.update(&mut cx, |this, cx| {
2736                if this.focused {
2737                    if let Some((buffer, actions)) = this.available_code_actions.clone() {
2738                        this.show_context_menu(
2739                            ContextMenu::CodeActions(CodeActionsMenu {
2740                                buffer,
2741                                actions,
2742                                selected_item: Default::default(),
2743                                list: Default::default(),
2744                                deployed_from_indicator,
2745                            }),
2746                            cx,
2747                        );
2748                    }
2749                }
2750            })?;
2751
2752            Ok::<_, anyhow::Error>(())
2753        })
2754        .detach_and_log_err(cx);
2755    }
2756
2757    pub fn confirm_code_action(
2758        workspace: &mut Workspace,
2759        action: &ConfirmCodeAction,
2760        cx: &mut ViewContext<Workspace>,
2761    ) -> Option<Task<Result<()>>> {
2762        let editor = workspace.active_item(cx)?.act_as::<Editor>(cx)?;
2763        let actions_menu = if let ContextMenu::CodeActions(menu) =
2764            editor.update(cx, |editor, cx| editor.hide_context_menu(cx))?
2765        {
2766            menu
2767        } else {
2768            return None;
2769        };
2770        let action_ix = action.item_ix.unwrap_or(actions_menu.selected_item);
2771        let action = actions_menu.actions.get(action_ix)?.clone();
2772        let title = action.lsp_action.title.clone();
2773        let buffer = actions_menu.buffer;
2774
2775        let apply_code_actions = workspace.project().clone().update(cx, |project, cx| {
2776            project.apply_code_action(buffer, action, true, cx)
2777        });
2778        let editor = editor.downgrade();
2779        Some(cx.spawn(|workspace, cx| async move {
2780            let project_transaction = apply_code_actions.await?;
2781            Self::open_project_transaction(&editor, workspace, project_transaction, title, cx).await
2782        }))
2783    }
2784
2785    async fn open_project_transaction(
2786        this: &WeakViewHandle<Editor>,
2787        workspace: WeakViewHandle<Workspace>,
2788        transaction: ProjectTransaction,
2789        title: String,
2790        mut cx: AsyncAppContext,
2791    ) -> Result<()> {
2792        let replica_id = this.read_with(&cx, |this, cx| this.replica_id(cx))?;
2793
2794        let mut entries = transaction.0.into_iter().collect::<Vec<_>>();
2795        entries.sort_unstable_by_key(|(buffer, _)| {
2796            buffer.read_with(&cx, |buffer, _| buffer.file().map(|f| f.path().clone()))
2797        });
2798
2799        // If the project transaction's edits are all contained within this editor, then
2800        // avoid opening a new editor to display them.
2801
2802        if let Some((buffer, transaction)) = entries.first() {
2803            if entries.len() == 1 {
2804                let excerpt = this.read_with(&cx, |editor, cx| {
2805                    editor
2806                        .buffer()
2807                        .read(cx)
2808                        .excerpt_containing(editor.selections.newest_anchor().head(), cx)
2809                })?;
2810                if let Some((_, excerpted_buffer, excerpt_range)) = excerpt {
2811                    if excerpted_buffer == *buffer {
2812                        let all_edits_within_excerpt = buffer.read_with(&cx, |buffer, _| {
2813                            let excerpt_range = excerpt_range.to_offset(buffer);
2814                            buffer
2815                                .edited_ranges_for_transaction::<usize>(transaction)
2816                                .all(|range| {
2817                                    excerpt_range.start <= range.start
2818                                        && excerpt_range.end >= range.end
2819                                })
2820                        });
2821
2822                        if all_edits_within_excerpt {
2823                            return Ok(());
2824                        }
2825                    }
2826                }
2827            }
2828        } else {
2829            return Ok(());
2830        }
2831
2832        let mut ranges_to_highlight = Vec::new();
2833        let excerpt_buffer = cx.add_model(|cx| {
2834            let mut multibuffer = MultiBuffer::new(replica_id).with_title(title);
2835            for (buffer_handle, transaction) in &entries {
2836                let buffer = buffer_handle.read(cx);
2837                ranges_to_highlight.extend(
2838                    multibuffer.push_excerpts_with_context_lines(
2839                        buffer_handle.clone(),
2840                        buffer
2841                            .edited_ranges_for_transaction::<usize>(transaction)
2842                            .collect(),
2843                        1,
2844                        cx,
2845                    ),
2846                );
2847            }
2848            multibuffer.push_transaction(entries.iter().map(|(b, t)| (b, t)), cx);
2849            multibuffer
2850        });
2851
2852        workspace.update(&mut cx, |workspace, cx| {
2853            let project = workspace.project().clone();
2854            let editor =
2855                cx.add_view(|cx| Editor::for_multibuffer(excerpt_buffer, Some(project), cx));
2856            workspace.add_item(Box::new(editor.clone()), cx);
2857            editor.update(cx, |editor, cx| {
2858                editor.highlight_background::<Self>(
2859                    ranges_to_highlight,
2860                    |theme| theme.editor.highlighted_line_background,
2861                    cx,
2862                );
2863            });
2864        })?;
2865
2866        Ok(())
2867    }
2868
2869    fn refresh_code_actions(&mut self, cx: &mut ViewContext<Self>) -> Option<()> {
2870        let project = self.project.as_ref()?;
2871        let buffer = self.buffer.read(cx);
2872        let newest_selection = self.selections.newest_anchor().clone();
2873        let (start_buffer, start) = buffer.text_anchor_for_position(newest_selection.start, cx)?;
2874        let (end_buffer, end) = buffer.text_anchor_for_position(newest_selection.end, cx)?;
2875        if start_buffer != end_buffer {
2876            return None;
2877        }
2878
2879        let actions = project.update(cx, |project, cx| {
2880            project.code_actions(&start_buffer, start..end, cx)
2881        });
2882        self.code_actions_task = Some(cx.spawn(|this, mut cx| async move {
2883            let actions = actions.await;
2884            this.update(&mut cx, |this, cx| {
2885                this.available_code_actions = actions.log_err().and_then(|actions| {
2886                    if actions.is_empty() {
2887                        None
2888                    } else {
2889                        Some((start_buffer, actions.into()))
2890                    }
2891                });
2892                cx.notify();
2893            })
2894            .log_err();
2895        }));
2896        None
2897    }
2898
2899    fn refresh_document_highlights(&mut self, cx: &mut ViewContext<Self>) -> Option<()> {
2900        if self.pending_rename.is_some() {
2901            return None;
2902        }
2903
2904        let project = self.project.as_ref()?;
2905        let buffer = self.buffer.read(cx);
2906        let newest_selection = self.selections.newest_anchor().clone();
2907        let cursor_position = newest_selection.head();
2908        let (cursor_buffer, cursor_buffer_position) =
2909            buffer.text_anchor_for_position(cursor_position.clone(), cx)?;
2910        let (tail_buffer, _) = buffer.text_anchor_for_position(newest_selection.tail(), cx)?;
2911        if cursor_buffer != tail_buffer {
2912            return None;
2913        }
2914
2915        let highlights = project.update(cx, |project, cx| {
2916            project.document_highlights(&cursor_buffer, cursor_buffer_position, cx)
2917        });
2918
2919        self.document_highlights_task = Some(cx.spawn(|this, mut cx| async move {
2920            if let Some(highlights) = highlights.await.log_err() {
2921                this.update(&mut cx, |this, cx| {
2922                    if this.pending_rename.is_some() {
2923                        return;
2924                    }
2925
2926                    let buffer_id = cursor_position.buffer_id;
2927                    let buffer = this.buffer.read(cx);
2928                    if !buffer
2929                        .text_anchor_for_position(cursor_position, cx)
2930                        .map_or(false, |(buffer, _)| buffer == cursor_buffer)
2931                    {
2932                        return;
2933                    }
2934
2935                    let cursor_buffer_snapshot = cursor_buffer.read(cx);
2936                    let mut write_ranges = Vec::new();
2937                    let mut read_ranges = Vec::new();
2938                    for highlight in highlights {
2939                        for (excerpt_id, excerpt_range) in
2940                            buffer.excerpts_for_buffer(&cursor_buffer, cx)
2941                        {
2942                            let start = highlight
2943                                .range
2944                                .start
2945                                .max(&excerpt_range.context.start, cursor_buffer_snapshot);
2946                            let end = highlight
2947                                .range
2948                                .end
2949                                .min(&excerpt_range.context.end, cursor_buffer_snapshot);
2950                            if start.cmp(&end, cursor_buffer_snapshot).is_ge() {
2951                                continue;
2952                            }
2953
2954                            let range = Anchor {
2955                                buffer_id,
2956                                excerpt_id: excerpt_id.clone(),
2957                                text_anchor: start,
2958                            }..Anchor {
2959                                buffer_id,
2960                                excerpt_id,
2961                                text_anchor: end,
2962                            };
2963                            if highlight.kind == lsp::DocumentHighlightKind::WRITE {
2964                                write_ranges.push(range);
2965                            } else {
2966                                read_ranges.push(range);
2967                            }
2968                        }
2969                    }
2970
2971                    this.highlight_background::<DocumentHighlightRead>(
2972                        read_ranges,
2973                        |theme| theme.editor.document_highlight_read_background,
2974                        cx,
2975                    );
2976                    this.highlight_background::<DocumentHighlightWrite>(
2977                        write_ranges,
2978                        |theme| theme.editor.document_highlight_write_background,
2979                        cx,
2980                    );
2981                    cx.notify();
2982                })
2983                .log_err();
2984            }
2985        }));
2986        None
2987    }
2988
2989    fn refresh_copilot_suggestions(
2990        &mut self,
2991        debounce: bool,
2992        cx: &mut ViewContext<Self>,
2993    ) -> Option<()> {
2994        let copilot = Copilot::global(cx)?;
2995        if self.mode != EditorMode::Full || !copilot.read(cx).status().is_authorized() {
2996            self.clear_copilot_suggestions(cx);
2997            return None;
2998        }
2999        self.update_visible_copilot_suggestion(cx);
3000
3001        let snapshot = self.buffer.read(cx).snapshot(cx);
3002        let cursor = self.selections.newest_anchor().head();
3003        if !self.is_copilot_enabled_at(cursor, &snapshot, cx) {
3004            self.clear_copilot_suggestions(cx);
3005            return None;
3006        }
3007
3008        let (buffer, buffer_position) =
3009            self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
3010        self.copilot_state.pending_refresh = cx.spawn(|this, mut cx| async move {
3011            if debounce {
3012                cx.background().timer(COPILOT_DEBOUNCE_TIMEOUT).await;
3013            }
3014
3015            let completions = copilot
3016                .update(&mut cx, |copilot, cx| {
3017                    copilot.completions(&buffer, buffer_position, cx)
3018                })
3019                .await
3020                .log_err()
3021                .into_iter()
3022                .flatten()
3023                .collect_vec();
3024
3025            this.update(&mut cx, |this, cx| {
3026                if !completions.is_empty() {
3027                    this.copilot_state.cycled = false;
3028                    this.copilot_state.pending_cycling_refresh = Task::ready(None);
3029                    this.copilot_state.completions.clear();
3030                    this.copilot_state.active_completion_index = 0;
3031                    this.copilot_state.excerpt_id = Some(cursor.excerpt_id);
3032                    for completion in completions {
3033                        this.copilot_state.push_completion(completion);
3034                    }
3035                    this.update_visible_copilot_suggestion(cx);
3036                }
3037            })
3038            .log_err()?;
3039            Some(())
3040        });
3041
3042        Some(())
3043    }
3044
3045    fn cycle_copilot_suggestions(
3046        &mut self,
3047        direction: Direction,
3048        cx: &mut ViewContext<Self>,
3049    ) -> Option<()> {
3050        let copilot = Copilot::global(cx)?;
3051        if self.mode != EditorMode::Full || !copilot.read(cx).status().is_authorized() {
3052            return None;
3053        }
3054
3055        if self.copilot_state.cycled {
3056            self.copilot_state.cycle_completions(direction);
3057            self.update_visible_copilot_suggestion(cx);
3058        } else {
3059            let cursor = self.selections.newest_anchor().head();
3060            let (buffer, buffer_position) =
3061                self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
3062            self.copilot_state.pending_cycling_refresh = cx.spawn(|this, mut cx| async move {
3063                let completions = copilot
3064                    .update(&mut cx, |copilot, cx| {
3065                        copilot.completions_cycling(&buffer, buffer_position, cx)
3066                    })
3067                    .await;
3068
3069                this.update(&mut cx, |this, cx| {
3070                    this.copilot_state.cycled = true;
3071                    for completion in completions.log_err().into_iter().flatten() {
3072                        this.copilot_state.push_completion(completion);
3073                    }
3074                    this.copilot_state.cycle_completions(direction);
3075                    this.update_visible_copilot_suggestion(cx);
3076                })
3077                .log_err()?;
3078
3079                Some(())
3080            });
3081        }
3082
3083        Some(())
3084    }
3085
3086    fn copilot_suggest(&mut self, _: &copilot::Suggest, cx: &mut ViewContext<Self>) {
3087        if !self.has_active_copilot_suggestion(cx) {
3088            self.refresh_copilot_suggestions(false, cx);
3089            return;
3090        }
3091
3092        self.update_visible_copilot_suggestion(cx);
3093    }
3094
3095    fn next_copilot_suggestion(&mut self, _: &copilot::NextSuggestion, cx: &mut ViewContext<Self>) {
3096        if self.has_active_copilot_suggestion(cx) {
3097            self.cycle_copilot_suggestions(Direction::Next, cx);
3098        } else {
3099            self.refresh_copilot_suggestions(false, cx);
3100        }
3101    }
3102
3103    fn previous_copilot_suggestion(
3104        &mut self,
3105        _: &copilot::PreviousSuggestion,
3106        cx: &mut ViewContext<Self>,
3107    ) {
3108        if self.has_active_copilot_suggestion(cx) {
3109            self.cycle_copilot_suggestions(Direction::Prev, cx);
3110        } else {
3111            self.refresh_copilot_suggestions(false, cx);
3112        }
3113    }
3114
3115    fn accept_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) -> bool {
3116        if let Some(suggestion) = self
3117            .display_map
3118            .update(cx, |map, cx| map.replace_suggestion::<usize>(None, cx))
3119        {
3120            if let Some((copilot, completion)) =
3121                Copilot::global(cx).zip(self.copilot_state.active_completion())
3122            {
3123                copilot
3124                    .update(cx, |copilot, cx| copilot.accept_completion(completion, cx))
3125                    .detach_and_log_err(cx);
3126
3127                self.report_copilot_event(Some(completion.uuid.clone()), true, cx)
3128            }
3129            self.insert_with_autoindent_mode(&suggestion.text.to_string(), None, cx);
3130            cx.notify();
3131            true
3132        } else {
3133            false
3134        }
3135    }
3136
3137    fn discard_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) -> bool {
3138        if self.has_active_copilot_suggestion(cx) {
3139            if let Some(copilot) = Copilot::global(cx) {
3140                copilot
3141                    .update(cx, |copilot, cx| {
3142                        copilot.discard_completions(&self.copilot_state.completions, cx)
3143                    })
3144                    .detach_and_log_err(cx);
3145
3146                self.report_copilot_event(None, false, cx)
3147            }
3148
3149            self.display_map
3150                .update(cx, |map, cx| map.replace_suggestion::<usize>(None, cx));
3151            cx.notify();
3152            true
3153        } else {
3154            false
3155        }
3156    }
3157
3158    fn is_copilot_enabled_at(
3159        &self,
3160        location: Anchor,
3161        snapshot: &MultiBufferSnapshot,
3162        cx: &mut ViewContext<Self>,
3163    ) -> bool {
3164        let path = snapshot.file_at(location).map(|file| file.path().as_ref());
3165        let language_name = snapshot
3166            .language_at(location)
3167            .map(|language| language.name());
3168        let settings = all_language_settings(cx);
3169        settings.copilot_enabled(language_name.as_deref(), path)
3170    }
3171
3172    fn has_active_copilot_suggestion(&self, cx: &AppContext) -> bool {
3173        self.display_map.read(cx).has_suggestion()
3174    }
3175
3176    fn update_visible_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) {
3177        let snapshot = self.buffer.read(cx).snapshot(cx);
3178        let selection = self.selections.newest_anchor();
3179        let cursor = selection.head();
3180
3181        if self.context_menu.is_some()
3182            || !self.completion_tasks.is_empty()
3183            || selection.start != selection.end
3184        {
3185            self.discard_copilot_suggestion(cx);
3186        } else if let Some(text) = self
3187            .copilot_state
3188            .text_for_active_completion(cursor, &snapshot)
3189        {
3190            self.display_map.update(cx, move |map, cx| {
3191                map.replace_suggestion(
3192                    Some(Suggestion {
3193                        position: cursor,
3194                        text: text.trim_end().into(),
3195                    }),
3196                    cx,
3197                )
3198            });
3199            cx.notify();
3200        } else {
3201            self.discard_copilot_suggestion(cx);
3202        }
3203    }
3204
3205    fn clear_copilot_suggestions(&mut self, cx: &mut ViewContext<Self>) {
3206        self.copilot_state = Default::default();
3207        self.discard_copilot_suggestion(cx);
3208    }
3209
3210    pub fn render_code_actions_indicator(
3211        &self,
3212        style: &EditorStyle,
3213        active: bool,
3214        cx: &mut ViewContext<Self>,
3215    ) -> Option<AnyElement<Self>> {
3216        if self.available_code_actions.is_some() {
3217            enum CodeActions {}
3218            Some(
3219                MouseEventHandler::<CodeActions, _>::new(0, cx, |state, _| {
3220                    Svg::new("icons/bolt_8.svg")
3221                        .with_color(style.code_actions.indicator.style_for(state, active).color)
3222                })
3223                .with_cursor_style(CursorStyle::PointingHand)
3224                .with_padding(Padding::uniform(3.))
3225                .on_down(MouseButton::Left, |_, this, cx| {
3226                    this.toggle_code_actions(
3227                        &ToggleCodeActions {
3228                            deployed_from_indicator: true,
3229                        },
3230                        cx,
3231                    );
3232                })
3233                .into_any(),
3234            )
3235        } else {
3236            None
3237        }
3238    }
3239
3240    pub fn render_fold_indicators(
3241        &self,
3242        fold_data: Vec<Option<(FoldStatus, u32, bool)>>,
3243        style: &EditorStyle,
3244        gutter_hovered: bool,
3245        line_height: f32,
3246        gutter_margin: f32,
3247        cx: &mut ViewContext<Self>,
3248    ) -> Vec<Option<AnyElement<Self>>> {
3249        enum FoldIndicators {}
3250
3251        let style = style.folds.clone();
3252
3253        fold_data
3254            .iter()
3255            .enumerate()
3256            .map(|(ix, fold_data)| {
3257                fold_data
3258                    .map(|(fold_status, buffer_row, active)| {
3259                        (active || gutter_hovered || fold_status == FoldStatus::Folded).then(|| {
3260                            MouseEventHandler::<FoldIndicators, _>::new(
3261                                ix as usize,
3262                                cx,
3263                                |mouse_state, _| {
3264                                    Svg::new(match fold_status {
3265                                        FoldStatus::Folded => style.folded_icon.clone(),
3266                                        FoldStatus::Foldable => style.foldable_icon.clone(),
3267                                    })
3268                                    .with_color(
3269                                        style
3270                                            .indicator
3271                                            .style_for(
3272                                                mouse_state,
3273                                                fold_status == FoldStatus::Folded,
3274                                            )
3275                                            .color,
3276                                    )
3277                                    .constrained()
3278                                    .with_width(gutter_margin * style.icon_margin_scale)
3279                                    .aligned()
3280                                    .constrained()
3281                                    .with_height(line_height)
3282                                    .with_width(gutter_margin)
3283                                    .aligned()
3284                                },
3285                            )
3286                            .with_cursor_style(CursorStyle::PointingHand)
3287                            .with_padding(Padding::uniform(3.))
3288                            .on_click(MouseButton::Left, {
3289                                move |_, editor, cx| match fold_status {
3290                                    FoldStatus::Folded => {
3291                                        editor.unfold_at(&UnfoldAt { buffer_row }, cx);
3292                                    }
3293                                    FoldStatus::Foldable => {
3294                                        editor.fold_at(&FoldAt { buffer_row }, cx);
3295                                    }
3296                                }
3297                            })
3298                            .into_any()
3299                        })
3300                    })
3301                    .flatten()
3302            })
3303            .collect()
3304    }
3305
3306    pub fn context_menu_visible(&self) -> bool {
3307        self.context_menu
3308            .as_ref()
3309            .map_or(false, |menu| menu.visible())
3310    }
3311
3312    pub fn render_context_menu(
3313        &self,
3314        cursor_position: DisplayPoint,
3315        style: EditorStyle,
3316        cx: &mut ViewContext<Editor>,
3317    ) -> Option<(DisplayPoint, AnyElement<Editor>)> {
3318        self.context_menu
3319            .as_ref()
3320            .map(|menu| menu.render(cursor_position, style, cx))
3321    }
3322
3323    fn show_context_menu(&mut self, menu: ContextMenu, cx: &mut ViewContext<Self>) {
3324        if !matches!(menu, ContextMenu::Completions(_)) {
3325            self.completion_tasks.clear();
3326        }
3327        self.context_menu = Some(menu);
3328        self.discard_copilot_suggestion(cx);
3329        cx.notify();
3330    }
3331
3332    fn hide_context_menu(&mut self, cx: &mut ViewContext<Self>) -> Option<ContextMenu> {
3333        cx.notify();
3334        self.completion_tasks.clear();
3335        let context_menu = self.context_menu.take();
3336        if context_menu.is_some() {
3337            self.update_visible_copilot_suggestion(cx);
3338        }
3339        context_menu
3340    }
3341
3342    pub fn insert_snippet(
3343        &mut self,
3344        insertion_ranges: &[Range<usize>],
3345        snippet: Snippet,
3346        cx: &mut ViewContext<Self>,
3347    ) -> Result<()> {
3348        let tabstops = self.buffer.update(cx, |buffer, cx| {
3349            let snippet_text: Arc<str> = snippet.text.clone().into();
3350            buffer.edit(
3351                insertion_ranges
3352                    .iter()
3353                    .cloned()
3354                    .map(|range| (range, snippet_text.clone())),
3355                Some(AutoindentMode::EachLine),
3356                cx,
3357            );
3358
3359            let snapshot = &*buffer.read(cx);
3360            let snippet = &snippet;
3361            snippet
3362                .tabstops
3363                .iter()
3364                .map(|tabstop| {
3365                    let mut tabstop_ranges = tabstop
3366                        .iter()
3367                        .flat_map(|tabstop_range| {
3368                            let mut delta = 0_isize;
3369                            insertion_ranges.iter().map(move |insertion_range| {
3370                                let insertion_start = insertion_range.start as isize + delta;
3371                                delta +=
3372                                    snippet.text.len() as isize - insertion_range.len() as isize;
3373
3374                                let start = snapshot.anchor_before(
3375                                    (insertion_start + tabstop_range.start) as usize,
3376                                );
3377                                let end = snapshot
3378                                    .anchor_after((insertion_start + tabstop_range.end) as usize);
3379                                start..end
3380                            })
3381                        })
3382                        .collect::<Vec<_>>();
3383                    tabstop_ranges.sort_unstable_by(|a, b| a.start.cmp(&b.start, snapshot));
3384                    tabstop_ranges
3385                })
3386                .collect::<Vec<_>>()
3387        });
3388
3389        if let Some(tabstop) = tabstops.first() {
3390            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3391                s.select_ranges(tabstop.iter().cloned());
3392            });
3393            self.snippet_stack.push(SnippetState {
3394                active_index: 0,
3395                ranges: tabstops,
3396            });
3397        }
3398
3399        Ok(())
3400    }
3401
3402    pub fn move_to_next_snippet_tabstop(&mut self, cx: &mut ViewContext<Self>) -> bool {
3403        self.move_to_snippet_tabstop(Bias::Right, cx)
3404    }
3405
3406    pub fn move_to_prev_snippet_tabstop(&mut self, cx: &mut ViewContext<Self>) -> bool {
3407        self.move_to_snippet_tabstop(Bias::Left, cx)
3408    }
3409
3410    pub fn move_to_snippet_tabstop(&mut self, bias: Bias, cx: &mut ViewContext<Self>) -> bool {
3411        if let Some(mut snippet) = self.snippet_stack.pop() {
3412            match bias {
3413                Bias::Left => {
3414                    if snippet.active_index > 0 {
3415                        snippet.active_index -= 1;
3416                    } else {
3417                        self.snippet_stack.push(snippet);
3418                        return false;
3419                    }
3420                }
3421                Bias::Right => {
3422                    if snippet.active_index + 1 < snippet.ranges.len() {
3423                        snippet.active_index += 1;
3424                    } else {
3425                        self.snippet_stack.push(snippet);
3426                        return false;
3427                    }
3428                }
3429            }
3430            if let Some(current_ranges) = snippet.ranges.get(snippet.active_index) {
3431                self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3432                    s.select_anchor_ranges(current_ranges.iter().cloned())
3433                });
3434                // If snippet state is not at the last tabstop, push it back on the stack
3435                if snippet.active_index + 1 < snippet.ranges.len() {
3436                    self.snippet_stack.push(snippet);
3437                }
3438                return true;
3439            }
3440        }
3441
3442        false
3443    }
3444
3445    pub fn clear(&mut self, cx: &mut ViewContext<Self>) {
3446        self.transact(cx, |this, cx| {
3447            this.select_all(&SelectAll, cx);
3448            this.insert("", cx);
3449        });
3450    }
3451
3452    pub fn backspace(&mut self, _: &Backspace, cx: &mut ViewContext<Self>) {
3453        self.transact(cx, |this, cx| {
3454            this.select_autoclose_pair(cx);
3455            let mut selections = this.selections.all::<Point>(cx);
3456            if !this.selections.line_mode {
3457                let display_map = this.display_map.update(cx, |map, cx| map.snapshot(cx));
3458                for selection in &mut selections {
3459                    if selection.is_empty() {
3460                        let old_head = selection.head();
3461                        let mut new_head =
3462                            movement::left(&display_map, old_head.to_display_point(&display_map))
3463                                .to_point(&display_map);
3464                        if let Some((buffer, line_buffer_range)) = display_map
3465                            .buffer_snapshot
3466                            .buffer_line_for_row(old_head.row)
3467                        {
3468                            let indent_size =
3469                                buffer.indent_size_for_line(line_buffer_range.start.row);
3470                            let indent_len = match indent_size.kind {
3471                                IndentKind::Space => {
3472                                    buffer.settings_at(line_buffer_range.start, cx).tab_size
3473                                }
3474                                IndentKind::Tab => NonZeroU32::new(1).unwrap(),
3475                            };
3476                            if old_head.column <= indent_size.len && old_head.column > 0 {
3477                                let indent_len = indent_len.get();
3478                                new_head = cmp::min(
3479                                    new_head,
3480                                    Point::new(
3481                                        old_head.row,
3482                                        ((old_head.column - 1) / indent_len) * indent_len,
3483                                    ),
3484                                );
3485                            }
3486                        }
3487
3488                        selection.set_head(new_head, SelectionGoal::None);
3489                    }
3490                }
3491            }
3492
3493            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
3494            this.insert("", cx);
3495            this.refresh_copilot_suggestions(true, cx);
3496        });
3497    }
3498
3499    pub fn delete(&mut self, _: &Delete, cx: &mut ViewContext<Self>) {
3500        self.transact(cx, |this, cx| {
3501            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
3502                let line_mode = s.line_mode;
3503                s.move_with(|map, selection| {
3504                    if selection.is_empty() && !line_mode {
3505                        let cursor = movement::right(map, selection.head());
3506                        selection.set_head(cursor, SelectionGoal::None);
3507                    }
3508                })
3509            });
3510            this.insert("", cx);
3511            this.refresh_copilot_suggestions(true, cx);
3512        });
3513    }
3514
3515    pub fn tab_prev(&mut self, _: &TabPrev, cx: &mut ViewContext<Self>) {
3516        if self.move_to_prev_snippet_tabstop(cx) {
3517            return;
3518        }
3519
3520        self.outdent(&Outdent, cx);
3521    }
3522
3523    pub fn tab(&mut self, _: &Tab, cx: &mut ViewContext<Self>) {
3524        if self.move_to_next_snippet_tabstop(cx) {
3525            return;
3526        }
3527
3528        let mut selections = self.selections.all_adjusted(cx);
3529        let buffer = self.buffer.read(cx);
3530        let snapshot = buffer.snapshot(cx);
3531        let rows_iter = selections.iter().map(|s| s.head().row);
3532        let suggested_indents = snapshot.suggested_indents(rows_iter, cx);
3533
3534        let mut edits = Vec::new();
3535        let mut prev_edited_row = 0;
3536        let mut row_delta = 0;
3537        for selection in &mut selections {
3538            if selection.start.row != prev_edited_row {
3539                row_delta = 0;
3540            }
3541            prev_edited_row = selection.end.row;
3542
3543            // If the selection is non-empty, then increase the indentation of the selected lines.
3544            if !selection.is_empty() {
3545                row_delta =
3546                    Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
3547                continue;
3548            }
3549
3550            // If the selection is empty and the cursor is in the leading whitespace before the
3551            // suggested indentation, then auto-indent the line.
3552            let cursor = selection.head();
3553            let current_indent = snapshot.indent_size_for_line(cursor.row);
3554            if let Some(suggested_indent) = suggested_indents.get(&cursor.row).copied() {
3555                if cursor.column < suggested_indent.len
3556                    && cursor.column <= current_indent.len
3557                    && current_indent.len <= suggested_indent.len
3558                {
3559                    selection.start = Point::new(cursor.row, suggested_indent.len);
3560                    selection.end = selection.start;
3561                    if row_delta == 0 {
3562                        edits.extend(Buffer::edit_for_indent_size_adjustment(
3563                            cursor.row,
3564                            current_indent,
3565                            suggested_indent,
3566                        ));
3567                        row_delta = suggested_indent.len - current_indent.len;
3568                    }
3569                    continue;
3570                }
3571            }
3572
3573            // Accept copilot suggestion if there is only one selection and the cursor is not
3574            // in the leading whitespace.
3575            if self.selections.count() == 1
3576                && cursor.column >= current_indent.len
3577                && self.has_active_copilot_suggestion(cx)
3578            {
3579                self.accept_copilot_suggestion(cx);
3580                return;
3581            }
3582
3583            // Otherwise, insert a hard or soft tab.
3584            let settings = buffer.settings_at(cursor, cx);
3585            let tab_size = if settings.hard_tabs {
3586                IndentSize::tab()
3587            } else {
3588                let tab_size = settings.tab_size.get();
3589                let char_column = snapshot
3590                    .text_for_range(Point::new(cursor.row, 0)..cursor)
3591                    .flat_map(str::chars)
3592                    .count()
3593                    + row_delta as usize;
3594                let chars_to_next_tab_stop = tab_size - (char_column as u32 % tab_size);
3595                IndentSize::spaces(chars_to_next_tab_stop)
3596            };
3597            selection.start = Point::new(cursor.row, cursor.column + row_delta + tab_size.len);
3598            selection.end = selection.start;
3599            edits.push((cursor..cursor, tab_size.chars().collect::<String>()));
3600            row_delta += tab_size.len;
3601        }
3602
3603        self.transact(cx, |this, cx| {
3604            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
3605            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
3606            this.refresh_copilot_suggestions(true, cx);
3607        });
3608    }
3609
3610    pub fn indent(&mut self, _: &Indent, cx: &mut ViewContext<Self>) {
3611        let mut selections = self.selections.all::<Point>(cx);
3612        let mut prev_edited_row = 0;
3613        let mut row_delta = 0;
3614        let mut edits = Vec::new();
3615        let buffer = self.buffer.read(cx);
3616        let snapshot = buffer.snapshot(cx);
3617        for selection in &mut selections {
3618            if selection.start.row != prev_edited_row {
3619                row_delta = 0;
3620            }
3621            prev_edited_row = selection.end.row;
3622
3623            row_delta =
3624                Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
3625        }
3626
3627        self.transact(cx, |this, cx| {
3628            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
3629            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
3630        });
3631    }
3632
3633    fn indent_selection(
3634        buffer: &MultiBuffer,
3635        snapshot: &MultiBufferSnapshot,
3636        selection: &mut Selection<Point>,
3637        edits: &mut Vec<(Range<Point>, String)>,
3638        delta_for_start_row: u32,
3639        cx: &AppContext,
3640    ) -> u32 {
3641        let settings = buffer.settings_at(selection.start, cx);
3642        let tab_size = settings.tab_size.get();
3643        let indent_kind = if settings.hard_tabs {
3644            IndentKind::Tab
3645        } else {
3646            IndentKind::Space
3647        };
3648        let mut start_row = selection.start.row;
3649        let mut end_row = selection.end.row + 1;
3650
3651        // If a selection ends at the beginning of a line, don't indent
3652        // that last line.
3653        if selection.end.column == 0 {
3654            end_row -= 1;
3655        }
3656
3657        // Avoid re-indenting a row that has already been indented by a
3658        // previous selection, but still update this selection's column
3659        // to reflect that indentation.
3660        if delta_for_start_row > 0 {
3661            start_row += 1;
3662            selection.start.column += delta_for_start_row;
3663            if selection.end.row == selection.start.row {
3664                selection.end.column += delta_for_start_row;
3665            }
3666        }
3667
3668        let mut delta_for_end_row = 0;
3669        for row in start_row..end_row {
3670            let current_indent = snapshot.indent_size_for_line(row);
3671            let indent_delta = match (current_indent.kind, indent_kind) {
3672                (IndentKind::Space, IndentKind::Space) => {
3673                    let columns_to_next_tab_stop = tab_size - (current_indent.len % tab_size);
3674                    IndentSize::spaces(columns_to_next_tab_stop)
3675                }
3676                (IndentKind::Tab, IndentKind::Space) => IndentSize::spaces(tab_size),
3677                (_, IndentKind::Tab) => IndentSize::tab(),
3678            };
3679
3680            let row_start = Point::new(row, 0);
3681            edits.push((
3682                row_start..row_start,
3683                indent_delta.chars().collect::<String>(),
3684            ));
3685
3686            // Update this selection's endpoints to reflect the indentation.
3687            if row == selection.start.row {
3688                selection.start.column += indent_delta.len;
3689            }
3690            if row == selection.end.row {
3691                selection.end.column += indent_delta.len;
3692                delta_for_end_row = indent_delta.len;
3693            }
3694        }
3695
3696        if selection.start.row == selection.end.row {
3697            delta_for_start_row + delta_for_end_row
3698        } else {
3699            delta_for_end_row
3700        }
3701    }
3702
3703    pub fn outdent(&mut self, _: &Outdent, cx: &mut ViewContext<Self>) {
3704        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3705        let selections = self.selections.all::<Point>(cx);
3706        let mut deletion_ranges = Vec::new();
3707        let mut last_outdent = None;
3708        {
3709            let buffer = self.buffer.read(cx);
3710            let snapshot = buffer.snapshot(cx);
3711            for selection in &selections {
3712                let settings = buffer.settings_at(selection.start, cx);
3713                let tab_size = settings.tab_size.get();
3714                let mut rows = selection.spanned_rows(false, &display_map);
3715
3716                // Avoid re-outdenting a row that has already been outdented by a
3717                // previous selection.
3718                if let Some(last_row) = last_outdent {
3719                    if last_row == rows.start {
3720                        rows.start += 1;
3721                    }
3722                }
3723
3724                for row in rows {
3725                    let indent_size = snapshot.indent_size_for_line(row);
3726                    if indent_size.len > 0 {
3727                        let deletion_len = match indent_size.kind {
3728                            IndentKind::Space => {
3729                                let columns_to_prev_tab_stop = indent_size.len % tab_size;
3730                                if columns_to_prev_tab_stop == 0 {
3731                                    tab_size
3732                                } else {
3733                                    columns_to_prev_tab_stop
3734                                }
3735                            }
3736                            IndentKind::Tab => 1,
3737                        };
3738                        deletion_ranges.push(Point::new(row, 0)..Point::new(row, deletion_len));
3739                        last_outdent = Some(row);
3740                    }
3741                }
3742            }
3743        }
3744
3745        self.transact(cx, |this, cx| {
3746            this.buffer.update(cx, |buffer, cx| {
3747                let empty_str: Arc<str> = "".into();
3748                buffer.edit(
3749                    deletion_ranges
3750                        .into_iter()
3751                        .map(|range| (range, empty_str.clone())),
3752                    None,
3753                    cx,
3754                );
3755            });
3756            let selections = this.selections.all::<usize>(cx);
3757            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
3758        });
3759    }
3760
3761    pub fn delete_line(&mut self, _: &DeleteLine, cx: &mut ViewContext<Self>) {
3762        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3763        let selections = self.selections.all::<Point>(cx);
3764
3765        let mut new_cursors = Vec::new();
3766        let mut edit_ranges = Vec::new();
3767        let mut selections = selections.iter().peekable();
3768        while let Some(selection) = selections.next() {
3769            let mut rows = selection.spanned_rows(false, &display_map);
3770            let goal_display_column = selection.head().to_display_point(&display_map).column();
3771
3772            // Accumulate contiguous regions of rows that we want to delete.
3773            while let Some(next_selection) = selections.peek() {
3774                let next_rows = next_selection.spanned_rows(false, &display_map);
3775                if next_rows.start <= rows.end {
3776                    rows.end = next_rows.end;
3777                    selections.next().unwrap();
3778                } else {
3779                    break;
3780                }
3781            }
3782
3783            let buffer = &display_map.buffer_snapshot;
3784            let mut edit_start = Point::new(rows.start, 0).to_offset(buffer);
3785            let edit_end;
3786            let cursor_buffer_row;
3787            if buffer.max_point().row >= rows.end {
3788                // If there's a line after the range, delete the \n from the end of the row range
3789                // and position the cursor on the next line.
3790                edit_end = Point::new(rows.end, 0).to_offset(buffer);
3791                cursor_buffer_row = rows.end;
3792            } else {
3793                // If there isn't a line after the range, delete the \n from the line before the
3794                // start of the row range and position the cursor there.
3795                edit_start = edit_start.saturating_sub(1);
3796                edit_end = buffer.len();
3797                cursor_buffer_row = rows.start.saturating_sub(1);
3798            }
3799
3800            let mut cursor = Point::new(cursor_buffer_row, 0).to_display_point(&display_map);
3801            *cursor.column_mut() =
3802                cmp::min(goal_display_column, display_map.line_len(cursor.row()));
3803
3804            new_cursors.push((
3805                selection.id,
3806                buffer.anchor_after(cursor.to_point(&display_map)),
3807            ));
3808            edit_ranges.push(edit_start..edit_end);
3809        }
3810
3811        self.transact(cx, |this, cx| {
3812            let buffer = this.buffer.update(cx, |buffer, cx| {
3813                let empty_str: Arc<str> = "".into();
3814                buffer.edit(
3815                    edit_ranges
3816                        .into_iter()
3817                        .map(|range| (range, empty_str.clone())),
3818                    None,
3819                    cx,
3820                );
3821                buffer.snapshot(cx)
3822            });
3823            let new_selections = new_cursors
3824                .into_iter()
3825                .map(|(id, cursor)| {
3826                    let cursor = cursor.to_point(&buffer);
3827                    Selection {
3828                        id,
3829                        start: cursor,
3830                        end: cursor,
3831                        reversed: false,
3832                        goal: SelectionGoal::None,
3833                    }
3834                })
3835                .collect();
3836
3837            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
3838                s.select(new_selections);
3839            });
3840        });
3841    }
3842
3843    pub fn duplicate_line(&mut self, _: &DuplicateLine, cx: &mut ViewContext<Self>) {
3844        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3845        let buffer = &display_map.buffer_snapshot;
3846        let selections = self.selections.all::<Point>(cx);
3847
3848        let mut edits = Vec::new();
3849        let mut selections_iter = selections.iter().peekable();
3850        while let Some(selection) = selections_iter.next() {
3851            // Avoid duplicating the same lines twice.
3852            let mut rows = selection.spanned_rows(false, &display_map);
3853
3854            while let Some(next_selection) = selections_iter.peek() {
3855                let next_rows = next_selection.spanned_rows(false, &display_map);
3856                if next_rows.start < rows.end {
3857                    rows.end = next_rows.end;
3858                    selections_iter.next().unwrap();
3859                } else {
3860                    break;
3861                }
3862            }
3863
3864            // Copy the text from the selected row region and splice it at the start of the region.
3865            let start = Point::new(rows.start, 0);
3866            let end = Point::new(rows.end - 1, buffer.line_len(rows.end - 1));
3867            let text = buffer
3868                .text_for_range(start..end)
3869                .chain(Some("\n"))
3870                .collect::<String>();
3871            edits.push((start..start, text));
3872        }
3873
3874        self.transact(cx, |this, cx| {
3875            this.buffer.update(cx, |buffer, cx| {
3876                buffer.edit(edits, None, cx);
3877            });
3878
3879            this.request_autoscroll(Autoscroll::fit(), cx);
3880        });
3881    }
3882
3883    pub fn move_line_up(&mut self, _: &MoveLineUp, cx: &mut ViewContext<Self>) {
3884        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3885        let buffer = self.buffer.read(cx).snapshot(cx);
3886
3887        let mut edits = Vec::new();
3888        let mut unfold_ranges = Vec::new();
3889        let mut refold_ranges = Vec::new();
3890
3891        let selections = self.selections.all::<Point>(cx);
3892        let mut selections = selections.iter().peekable();
3893        let mut contiguous_row_selections = Vec::new();
3894        let mut new_selections = Vec::new();
3895
3896        while let Some(selection) = selections.next() {
3897            // Find all the selections that span a contiguous row range
3898            let (start_row, end_row) = consume_contiguous_rows(
3899                &mut contiguous_row_selections,
3900                selection,
3901                &display_map,
3902                &mut selections,
3903            );
3904
3905            // Move the text spanned by the row range to be before the line preceding the row range
3906            if start_row > 0 {
3907                let range_to_move = Point::new(start_row - 1, buffer.line_len(start_row - 1))
3908                    ..Point::new(end_row - 1, buffer.line_len(end_row - 1));
3909                let insertion_point = display_map
3910                    .prev_line_boundary(Point::new(start_row - 1, 0))
3911                    .0;
3912
3913                // Don't move lines across excerpts
3914                if buffer
3915                    .excerpt_boundaries_in_range((
3916                        Bound::Excluded(insertion_point),
3917                        Bound::Included(range_to_move.end),
3918                    ))
3919                    .next()
3920                    .is_none()
3921                {
3922                    let text = buffer
3923                        .text_for_range(range_to_move.clone())
3924                        .flat_map(|s| s.chars())
3925                        .skip(1)
3926                        .chain(['\n'])
3927                        .collect::<String>();
3928
3929                    edits.push((
3930                        buffer.anchor_after(range_to_move.start)
3931                            ..buffer.anchor_before(range_to_move.end),
3932                        String::new(),
3933                    ));
3934                    let insertion_anchor = buffer.anchor_after(insertion_point);
3935                    edits.push((insertion_anchor..insertion_anchor, text));
3936
3937                    let row_delta = range_to_move.start.row - insertion_point.row + 1;
3938
3939                    // Move selections up
3940                    new_selections.extend(contiguous_row_selections.drain(..).map(
3941                        |mut selection| {
3942                            selection.start.row -= row_delta;
3943                            selection.end.row -= row_delta;
3944                            selection
3945                        },
3946                    ));
3947
3948                    // Move folds up
3949                    unfold_ranges.push(range_to_move.clone());
3950                    for fold in display_map.folds_in_range(
3951                        buffer.anchor_before(range_to_move.start)
3952                            ..buffer.anchor_after(range_to_move.end),
3953                    ) {
3954                        let mut start = fold.start.to_point(&buffer);
3955                        let mut end = fold.end.to_point(&buffer);
3956                        start.row -= row_delta;
3957                        end.row -= row_delta;
3958                        refold_ranges.push(start..end);
3959                    }
3960                }
3961            }
3962
3963            // If we didn't move line(s), preserve the existing selections
3964            new_selections.append(&mut contiguous_row_selections);
3965        }
3966
3967        self.transact(cx, |this, cx| {
3968            this.unfold_ranges(unfold_ranges, true, true, cx);
3969            this.buffer.update(cx, |buffer, cx| {
3970                for (range, text) in edits {
3971                    buffer.edit([(range, text)], None, cx);
3972                }
3973            });
3974            this.fold_ranges(refold_ranges, true, cx);
3975            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
3976                s.select(new_selections);
3977            })
3978        });
3979    }
3980
3981    pub fn move_line_down(&mut self, _: &MoveLineDown, cx: &mut ViewContext<Self>) {
3982        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3983        let buffer = self.buffer.read(cx).snapshot(cx);
3984
3985        let mut edits = Vec::new();
3986        let mut unfold_ranges = Vec::new();
3987        let mut refold_ranges = Vec::new();
3988
3989        let selections = self.selections.all::<Point>(cx);
3990        let mut selections = selections.iter().peekable();
3991        let mut contiguous_row_selections = Vec::new();
3992        let mut new_selections = Vec::new();
3993
3994        while let Some(selection) = selections.next() {
3995            // Find all the selections that span a contiguous row range
3996            let (start_row, end_row) = consume_contiguous_rows(
3997                &mut contiguous_row_selections,
3998                selection,
3999                &display_map,
4000                &mut selections,
4001            );
4002
4003            // Move the text spanned by the row range to be after the last line of the row range
4004            if end_row <= buffer.max_point().row {
4005                let range_to_move = Point::new(start_row, 0)..Point::new(end_row, 0);
4006                let insertion_point = display_map.next_line_boundary(Point::new(end_row, 0)).0;
4007
4008                // Don't move lines across excerpt boundaries
4009                if buffer
4010                    .excerpt_boundaries_in_range((
4011                        Bound::Excluded(range_to_move.start),
4012                        Bound::Included(insertion_point),
4013                    ))
4014                    .next()
4015                    .is_none()
4016                {
4017                    let mut text = String::from("\n");
4018                    text.extend(buffer.text_for_range(range_to_move.clone()));
4019                    text.pop(); // Drop trailing newline
4020                    edits.push((
4021                        buffer.anchor_after(range_to_move.start)
4022                            ..buffer.anchor_before(range_to_move.end),
4023                        String::new(),
4024                    ));
4025                    let insertion_anchor = buffer.anchor_after(insertion_point);
4026                    edits.push((insertion_anchor..insertion_anchor, text));
4027
4028                    let row_delta = insertion_point.row - range_to_move.end.row + 1;
4029
4030                    // Move selections down
4031                    new_selections.extend(contiguous_row_selections.drain(..).map(
4032                        |mut selection| {
4033                            selection.start.row += row_delta;
4034                            selection.end.row += row_delta;
4035                            selection
4036                        },
4037                    ));
4038
4039                    // Move folds down
4040                    unfold_ranges.push(range_to_move.clone());
4041                    for fold in display_map.folds_in_range(
4042                        buffer.anchor_before(range_to_move.start)
4043                            ..buffer.anchor_after(range_to_move.end),
4044                    ) {
4045                        let mut start = fold.start.to_point(&buffer);
4046                        let mut end = fold.end.to_point(&buffer);
4047                        start.row += row_delta;
4048                        end.row += row_delta;
4049                        refold_ranges.push(start..end);
4050                    }
4051                }
4052            }
4053
4054            // If we didn't move line(s), preserve the existing selections
4055            new_selections.append(&mut contiguous_row_selections);
4056        }
4057
4058        self.transact(cx, |this, cx| {
4059            this.unfold_ranges(unfold_ranges, true, true, cx);
4060            this.buffer.update(cx, |buffer, cx| {
4061                for (range, text) in edits {
4062                    buffer.edit([(range, text)], None, cx);
4063                }
4064            });
4065            this.fold_ranges(refold_ranges, true, cx);
4066            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(new_selections));
4067        });
4068    }
4069
4070    pub fn transpose(&mut self, _: &Transpose, cx: &mut ViewContext<Self>) {
4071        self.transact(cx, |this, cx| {
4072            let edits = this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4073                let mut edits: Vec<(Range<usize>, String)> = Default::default();
4074                let line_mode = s.line_mode;
4075                s.move_with(|display_map, selection| {
4076                    if !selection.is_empty() || line_mode {
4077                        return;
4078                    }
4079
4080                    let mut head = selection.head();
4081                    let mut transpose_offset = head.to_offset(display_map, Bias::Right);
4082                    if head.column() == display_map.line_len(head.row()) {
4083                        transpose_offset = display_map
4084                            .buffer_snapshot
4085                            .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
4086                    }
4087
4088                    if transpose_offset == 0 {
4089                        return;
4090                    }
4091
4092                    *head.column_mut() += 1;
4093                    head = display_map.clip_point(head, Bias::Right);
4094                    selection.collapse_to(head, SelectionGoal::Column(head.column()));
4095
4096                    let transpose_start = display_map
4097                        .buffer_snapshot
4098                        .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
4099                    if edits.last().map_or(true, |e| e.0.end <= transpose_start) {
4100                        let transpose_end = display_map
4101                            .buffer_snapshot
4102                            .clip_offset(transpose_offset + 1, Bias::Right);
4103                        if let Some(ch) =
4104                            display_map.buffer_snapshot.chars_at(transpose_start).next()
4105                        {
4106                            edits.push((transpose_start..transpose_offset, String::new()));
4107                            edits.push((transpose_end..transpose_end, ch.to_string()));
4108                        }
4109                    }
4110                });
4111                edits
4112            });
4113            this.buffer
4114                .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
4115            let selections = this.selections.all::<usize>(cx);
4116            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4117                s.select(selections);
4118            });
4119        });
4120    }
4121
4122    pub fn cut(&mut self, _: &Cut, cx: &mut ViewContext<Self>) {
4123        let mut text = String::new();
4124        let buffer = self.buffer.read(cx).snapshot(cx);
4125        let mut selections = self.selections.all::<Point>(cx);
4126        let mut clipboard_selections = Vec::with_capacity(selections.len());
4127        {
4128            let max_point = buffer.max_point();
4129            for selection in &mut selections {
4130                let is_entire_line = selection.is_empty() || self.selections.line_mode;
4131                if is_entire_line {
4132                    selection.start = Point::new(selection.start.row, 0);
4133                    selection.end = cmp::min(max_point, Point::new(selection.end.row + 1, 0));
4134                    selection.goal = SelectionGoal::None;
4135                }
4136                let mut len = 0;
4137                for chunk in buffer.text_for_range(selection.start..selection.end) {
4138                    text.push_str(chunk);
4139                    len += chunk.len();
4140                }
4141                clipboard_selections.push(ClipboardSelection {
4142                    len,
4143                    is_entire_line,
4144                    first_line_indent: buffer.indent_size_for_line(selection.start.row).len,
4145                });
4146            }
4147        }
4148
4149        self.transact(cx, |this, cx| {
4150            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4151                s.select(selections);
4152            });
4153            this.insert("", cx);
4154            cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
4155        });
4156    }
4157
4158    pub fn copy(&mut self, _: &Copy, cx: &mut ViewContext<Self>) {
4159        let selections = self.selections.all::<Point>(cx);
4160        let buffer = self.buffer.read(cx).read(cx);
4161        let mut text = String::new();
4162
4163        let mut clipboard_selections = Vec::with_capacity(selections.len());
4164        {
4165            let max_point = buffer.max_point();
4166            for selection in selections.iter() {
4167                let mut start = selection.start;
4168                let mut end = selection.end;
4169                let is_entire_line = selection.is_empty() || self.selections.line_mode;
4170                if is_entire_line {
4171                    start = Point::new(start.row, 0);
4172                    end = cmp::min(max_point, Point::new(end.row + 1, 0));
4173                }
4174                let mut len = 0;
4175                for chunk in buffer.text_for_range(start..end) {
4176                    text.push_str(chunk);
4177                    len += chunk.len();
4178                }
4179                clipboard_selections.push(ClipboardSelection {
4180                    len,
4181                    is_entire_line,
4182                    first_line_indent: buffer.indent_size_for_line(start.row).len,
4183                });
4184            }
4185        }
4186
4187        cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
4188    }
4189
4190    pub fn paste(&mut self, _: &Paste, cx: &mut ViewContext<Self>) {
4191        self.transact(cx, |this, cx| {
4192            if let Some(item) = cx.read_from_clipboard() {
4193                let mut clipboard_text = Cow::Borrowed(item.text());
4194                if let Some(mut clipboard_selections) = item.metadata::<Vec<ClipboardSelection>>() {
4195                    let old_selections = this.selections.all::<usize>(cx);
4196                    let all_selections_were_entire_line =
4197                        clipboard_selections.iter().all(|s| s.is_entire_line);
4198                    let first_selection_indent_column =
4199                        clipboard_selections.first().map(|s| s.first_line_indent);
4200                    if clipboard_selections.len() != old_selections.len() {
4201                        let mut newline_separated_text = String::new();
4202                        let mut clipboard_selections = clipboard_selections.drain(..).peekable();
4203                        let mut ix = 0;
4204                        while let Some(clipboard_selection) = clipboard_selections.next() {
4205                            newline_separated_text
4206                                .push_str(&clipboard_text[ix..ix + clipboard_selection.len]);
4207                            ix += clipboard_selection.len;
4208                            if clipboard_selections.peek().is_some() {
4209                                newline_separated_text.push('\n');
4210                            }
4211                        }
4212                        clipboard_text = Cow::Owned(newline_separated_text);
4213                    }
4214
4215                    this.buffer.update(cx, |buffer, cx| {
4216                        let snapshot = buffer.read(cx);
4217                        let mut start_offset = 0;
4218                        let mut edits = Vec::new();
4219                        let mut original_indent_columns = Vec::new();
4220                        let line_mode = this.selections.line_mode;
4221                        for (ix, selection) in old_selections.iter().enumerate() {
4222                            let to_insert;
4223                            let entire_line;
4224                            let original_indent_column;
4225                            if let Some(clipboard_selection) = clipboard_selections.get(ix) {
4226                                let end_offset = start_offset + clipboard_selection.len;
4227                                to_insert = &clipboard_text[start_offset..end_offset];
4228                                entire_line = clipboard_selection.is_entire_line;
4229                                start_offset = end_offset;
4230                                original_indent_column =
4231                                    Some(clipboard_selection.first_line_indent);
4232                            } else {
4233                                to_insert = clipboard_text.as_str();
4234                                entire_line = all_selections_were_entire_line;
4235                                original_indent_column = first_selection_indent_column
4236                            }
4237
4238                            // If the corresponding selection was empty when this slice of the
4239                            // clipboard text was written, then the entire line containing the
4240                            // selection was copied. If this selection is also currently empty,
4241                            // then paste the line before the current line of the buffer.
4242                            let range = if selection.is_empty() && !line_mode && entire_line {
4243                                let column = selection.start.to_point(&snapshot).column as usize;
4244                                let line_start = selection.start - column;
4245                                line_start..line_start
4246                            } else {
4247                                selection.range()
4248                            };
4249
4250                            edits.push((range, to_insert));
4251                            original_indent_columns.extend(original_indent_column);
4252                        }
4253                        drop(snapshot);
4254
4255                        buffer.edit(
4256                            edits,
4257                            Some(AutoindentMode::Block {
4258                                original_indent_columns,
4259                            }),
4260                            cx,
4261                        );
4262                    });
4263
4264                    let selections = this.selections.all::<usize>(cx);
4265                    this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
4266                } else {
4267                    this.insert(&clipboard_text, cx);
4268                }
4269            }
4270        });
4271    }
4272
4273    pub fn undo(&mut self, _: &Undo, cx: &mut ViewContext<Self>) {
4274        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.undo(cx)) {
4275            if let Some((selections, _)) = self.selection_history.transaction(tx_id).cloned() {
4276                self.change_selections(None, cx, |s| {
4277                    s.select_anchors(selections.to_vec());
4278                });
4279            }
4280            self.request_autoscroll(Autoscroll::fit(), cx);
4281            self.unmark_text(cx);
4282            self.refresh_copilot_suggestions(true, cx);
4283            cx.emit(Event::Edited);
4284        }
4285    }
4286
4287    pub fn redo(&mut self, _: &Redo, cx: &mut ViewContext<Self>) {
4288        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.redo(cx)) {
4289            if let Some((_, Some(selections))) = self.selection_history.transaction(tx_id).cloned()
4290            {
4291                self.change_selections(None, cx, |s| {
4292                    s.select_anchors(selections.to_vec());
4293                });
4294            }
4295            self.request_autoscroll(Autoscroll::fit(), cx);
4296            self.unmark_text(cx);
4297            self.refresh_copilot_suggestions(true, cx);
4298            cx.emit(Event::Edited);
4299        }
4300    }
4301
4302    pub fn finalize_last_transaction(&mut self, cx: &mut ViewContext<Self>) {
4303        self.buffer
4304            .update(cx, |buffer, cx| buffer.finalize_last_transaction(cx));
4305    }
4306
4307    pub fn move_left(&mut self, _: &MoveLeft, cx: &mut ViewContext<Self>) {
4308        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4309            let line_mode = s.line_mode;
4310            s.move_with(|map, selection| {
4311                let cursor = if selection.is_empty() && !line_mode {
4312                    movement::left(map, selection.start)
4313                } else {
4314                    selection.start
4315                };
4316                selection.collapse_to(cursor, SelectionGoal::None);
4317            });
4318        })
4319    }
4320
4321    pub fn select_left(&mut self, _: &SelectLeft, cx: &mut ViewContext<Self>) {
4322        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4323            s.move_heads_with(|map, head, _| (movement::left(map, head), SelectionGoal::None));
4324        })
4325    }
4326
4327    pub fn move_right(&mut self, _: &MoveRight, cx: &mut ViewContext<Self>) {
4328        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4329            let line_mode = s.line_mode;
4330            s.move_with(|map, selection| {
4331                let cursor = if selection.is_empty() && !line_mode {
4332                    movement::right(map, selection.end)
4333                } else {
4334                    selection.end
4335                };
4336                selection.collapse_to(cursor, SelectionGoal::None)
4337            });
4338        })
4339    }
4340
4341    pub fn select_right(&mut self, _: &SelectRight, cx: &mut ViewContext<Self>) {
4342        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4343            s.move_heads_with(|map, head, _| (movement::right(map, head), SelectionGoal::None));
4344        })
4345    }
4346
4347    pub fn move_up(&mut self, _: &MoveUp, cx: &mut ViewContext<Self>) {
4348        if self.take_rename(true, cx).is_some() {
4349            return;
4350        }
4351
4352        if let Some(context_menu) = self.context_menu.as_mut() {
4353            if context_menu.select_prev(cx) {
4354                return;
4355            }
4356        }
4357
4358        if matches!(self.mode, EditorMode::SingleLine) {
4359            cx.propagate_action();
4360            return;
4361        }
4362
4363        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4364            let line_mode = s.line_mode;
4365            s.move_with(|map, selection| {
4366                if !selection.is_empty() && !line_mode {
4367                    selection.goal = SelectionGoal::None;
4368                }
4369                let (cursor, goal) = movement::up(map, selection.start, selection.goal, false);
4370                selection.collapse_to(cursor, goal);
4371            });
4372        })
4373    }
4374
4375    pub fn move_page_up(&mut self, action: &MovePageUp, cx: &mut ViewContext<Self>) {
4376        if self.take_rename(true, cx).is_some() {
4377            return;
4378        }
4379
4380        if self
4381            .context_menu
4382            .as_mut()
4383            .map(|menu| menu.select_first(cx))
4384            .unwrap_or(false)
4385        {
4386            return;
4387        }
4388
4389        if matches!(self.mode, EditorMode::SingleLine) {
4390            cx.propagate_action();
4391            return;
4392        }
4393
4394        let row_count = if let Some(row_count) = self.visible_line_count() {
4395            row_count as u32 - 1
4396        } else {
4397            return;
4398        };
4399
4400        let autoscroll = if action.center_cursor {
4401            Autoscroll::center()
4402        } else {
4403            Autoscroll::fit()
4404        };
4405
4406        self.change_selections(Some(autoscroll), cx, |s| {
4407            let line_mode = s.line_mode;
4408            s.move_with(|map, selection| {
4409                if !selection.is_empty() && !line_mode {
4410                    selection.goal = SelectionGoal::None;
4411                }
4412                let (cursor, goal) =
4413                    movement::up_by_rows(map, selection.end, row_count, selection.goal, false);
4414                selection.collapse_to(cursor, goal);
4415            });
4416        });
4417    }
4418
4419    pub fn select_up(&mut self, _: &SelectUp, cx: &mut ViewContext<Self>) {
4420        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4421            s.move_heads_with(|map, head, goal| movement::up(map, head, goal, false))
4422        })
4423    }
4424
4425    pub fn move_down(&mut self, _: &MoveDown, cx: &mut ViewContext<Self>) {
4426        self.take_rename(true, cx);
4427
4428        if let Some(context_menu) = self.context_menu.as_mut() {
4429            if context_menu.select_next(cx) {
4430                return;
4431            }
4432        }
4433
4434        if self.mode == EditorMode::SingleLine {
4435            cx.propagate_action();
4436            return;
4437        }
4438
4439        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4440            let line_mode = s.line_mode;
4441            s.move_with(|map, selection| {
4442                if !selection.is_empty() && !line_mode {
4443                    selection.goal = SelectionGoal::None;
4444                }
4445                let (cursor, goal) = movement::down(map, selection.end, selection.goal, false);
4446                selection.collapse_to(cursor, goal);
4447            });
4448        });
4449    }
4450
4451    pub fn move_page_down(&mut self, action: &MovePageDown, cx: &mut ViewContext<Self>) {
4452        if self.take_rename(true, cx).is_some() {
4453            return;
4454        }
4455
4456        if self
4457            .context_menu
4458            .as_mut()
4459            .map(|menu| menu.select_last(cx))
4460            .unwrap_or(false)
4461        {
4462            return;
4463        }
4464
4465        if matches!(self.mode, EditorMode::SingleLine) {
4466            cx.propagate_action();
4467            return;
4468        }
4469
4470        let row_count = if let Some(row_count) = self.visible_line_count() {
4471            row_count as u32 - 1
4472        } else {
4473            return;
4474        };
4475
4476        let autoscroll = if action.center_cursor {
4477            Autoscroll::center()
4478        } else {
4479            Autoscroll::fit()
4480        };
4481
4482        self.change_selections(Some(autoscroll), cx, |s| {
4483            let line_mode = s.line_mode;
4484            s.move_with(|map, selection| {
4485                if !selection.is_empty() && !line_mode {
4486                    selection.goal = SelectionGoal::None;
4487                }
4488                let (cursor, goal) =
4489                    movement::down_by_rows(map, selection.end, row_count, selection.goal, false);
4490                selection.collapse_to(cursor, goal);
4491            });
4492        });
4493    }
4494
4495    pub fn select_down(&mut self, _: &SelectDown, cx: &mut ViewContext<Self>) {
4496        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4497            s.move_heads_with(|map, head, goal| movement::down(map, head, goal, false))
4498        });
4499    }
4500
4501    pub fn move_to_previous_word_start(
4502        &mut self,
4503        _: &MoveToPreviousWordStart,
4504        cx: &mut ViewContext<Self>,
4505    ) {
4506        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4507            s.move_cursors_with(|map, head, _| {
4508                (
4509                    movement::previous_word_start(map, head),
4510                    SelectionGoal::None,
4511                )
4512            });
4513        })
4514    }
4515
4516    pub fn move_to_previous_subword_start(
4517        &mut self,
4518        _: &MoveToPreviousSubwordStart,
4519        cx: &mut ViewContext<Self>,
4520    ) {
4521        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4522            s.move_cursors_with(|map, head, _| {
4523                (
4524                    movement::previous_subword_start(map, head),
4525                    SelectionGoal::None,
4526                )
4527            });
4528        })
4529    }
4530
4531    pub fn select_to_previous_word_start(
4532        &mut self,
4533        _: &SelectToPreviousWordStart,
4534        cx: &mut ViewContext<Self>,
4535    ) {
4536        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4537            s.move_heads_with(|map, head, _| {
4538                (
4539                    movement::previous_word_start(map, head),
4540                    SelectionGoal::None,
4541                )
4542            });
4543        })
4544    }
4545
4546    pub fn select_to_previous_subword_start(
4547        &mut self,
4548        _: &SelectToPreviousSubwordStart,
4549        cx: &mut ViewContext<Self>,
4550    ) {
4551        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4552            s.move_heads_with(|map, head, _| {
4553                (
4554                    movement::previous_subword_start(map, head),
4555                    SelectionGoal::None,
4556                )
4557            });
4558        })
4559    }
4560
4561    pub fn delete_to_previous_word_start(
4562        &mut self,
4563        _: &DeleteToPreviousWordStart,
4564        cx: &mut ViewContext<Self>,
4565    ) {
4566        self.transact(cx, |this, cx| {
4567            this.select_autoclose_pair(cx);
4568            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4569                let line_mode = s.line_mode;
4570                s.move_with(|map, selection| {
4571                    if selection.is_empty() && !line_mode {
4572                        let cursor = movement::previous_word_start(map, selection.head());
4573                        selection.set_head(cursor, SelectionGoal::None);
4574                    }
4575                });
4576            });
4577            this.insert("", cx);
4578        });
4579    }
4580
4581    pub fn delete_to_previous_subword_start(
4582        &mut self,
4583        _: &DeleteToPreviousSubwordStart,
4584        cx: &mut ViewContext<Self>,
4585    ) {
4586        self.transact(cx, |this, cx| {
4587            this.select_autoclose_pair(cx);
4588            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4589                let line_mode = s.line_mode;
4590                s.move_with(|map, selection| {
4591                    if selection.is_empty() && !line_mode {
4592                        let cursor = movement::previous_subword_start(map, selection.head());
4593                        selection.set_head(cursor, SelectionGoal::None);
4594                    }
4595                });
4596            });
4597            this.insert("", cx);
4598        });
4599    }
4600
4601    pub fn move_to_next_word_end(&mut self, _: &MoveToNextWordEnd, cx: &mut ViewContext<Self>) {
4602        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4603            s.move_cursors_with(|map, head, _| {
4604                (movement::next_word_end(map, head), SelectionGoal::None)
4605            });
4606        })
4607    }
4608
4609    pub fn move_to_next_subword_end(
4610        &mut self,
4611        _: &MoveToNextSubwordEnd,
4612        cx: &mut ViewContext<Self>,
4613    ) {
4614        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4615            s.move_cursors_with(|map, head, _| {
4616                (movement::next_subword_end(map, head), SelectionGoal::None)
4617            });
4618        })
4619    }
4620
4621    pub fn select_to_next_word_end(&mut self, _: &SelectToNextWordEnd, cx: &mut ViewContext<Self>) {
4622        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4623            s.move_heads_with(|map, head, _| {
4624                (movement::next_word_end(map, head), SelectionGoal::None)
4625            });
4626        })
4627    }
4628
4629    pub fn select_to_next_subword_end(
4630        &mut self,
4631        _: &SelectToNextSubwordEnd,
4632        cx: &mut ViewContext<Self>,
4633    ) {
4634        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4635            s.move_heads_with(|map, head, _| {
4636                (movement::next_subword_end(map, head), SelectionGoal::None)
4637            });
4638        })
4639    }
4640
4641    pub fn delete_to_next_word_end(&mut self, _: &DeleteToNextWordEnd, cx: &mut ViewContext<Self>) {
4642        self.transact(cx, |this, cx| {
4643            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4644                let line_mode = s.line_mode;
4645                s.move_with(|map, selection| {
4646                    if selection.is_empty() && !line_mode {
4647                        let cursor = movement::next_word_end(map, selection.head());
4648                        selection.set_head(cursor, SelectionGoal::None);
4649                    }
4650                });
4651            });
4652            this.insert("", cx);
4653        });
4654    }
4655
4656    pub fn delete_to_next_subword_end(
4657        &mut self,
4658        _: &DeleteToNextSubwordEnd,
4659        cx: &mut ViewContext<Self>,
4660    ) {
4661        self.transact(cx, |this, cx| {
4662            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4663                s.move_with(|map, selection| {
4664                    if selection.is_empty() {
4665                        let cursor = movement::next_subword_end(map, selection.head());
4666                        selection.set_head(cursor, SelectionGoal::None);
4667                    }
4668                });
4669            });
4670            this.insert("", cx);
4671        });
4672    }
4673
4674    pub fn move_to_beginning_of_line(
4675        &mut self,
4676        _: &MoveToBeginningOfLine,
4677        cx: &mut ViewContext<Self>,
4678    ) {
4679        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4680            s.move_cursors_with(|map, head, _| {
4681                (
4682                    movement::indented_line_beginning(map, head, true),
4683                    SelectionGoal::None,
4684                )
4685            });
4686        })
4687    }
4688
4689    pub fn select_to_beginning_of_line(
4690        &mut self,
4691        action: &SelectToBeginningOfLine,
4692        cx: &mut ViewContext<Self>,
4693    ) {
4694        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4695            s.move_heads_with(|map, head, _| {
4696                (
4697                    movement::indented_line_beginning(map, head, action.stop_at_soft_wraps),
4698                    SelectionGoal::None,
4699                )
4700            });
4701        });
4702    }
4703
4704    pub fn delete_to_beginning_of_line(
4705        &mut self,
4706        _: &DeleteToBeginningOfLine,
4707        cx: &mut ViewContext<Self>,
4708    ) {
4709        self.transact(cx, |this, cx| {
4710            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4711                s.move_with(|_, selection| {
4712                    selection.reversed = true;
4713                });
4714            });
4715
4716            this.select_to_beginning_of_line(
4717                &SelectToBeginningOfLine {
4718                    stop_at_soft_wraps: false,
4719                },
4720                cx,
4721            );
4722            this.backspace(&Backspace, cx);
4723        });
4724    }
4725
4726    pub fn move_to_end_of_line(&mut self, _: &MoveToEndOfLine, cx: &mut ViewContext<Self>) {
4727        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4728            s.move_cursors_with(|map, head, _| {
4729                (movement::line_end(map, head, true), SelectionGoal::None)
4730            });
4731        })
4732    }
4733
4734    pub fn select_to_end_of_line(
4735        &mut self,
4736        action: &SelectToEndOfLine,
4737        cx: &mut ViewContext<Self>,
4738    ) {
4739        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4740            s.move_heads_with(|map, head, _| {
4741                (
4742                    movement::line_end(map, head, action.stop_at_soft_wraps),
4743                    SelectionGoal::None,
4744                )
4745            });
4746        })
4747    }
4748
4749    pub fn delete_to_end_of_line(&mut self, _: &DeleteToEndOfLine, cx: &mut ViewContext<Self>) {
4750        self.transact(cx, |this, cx| {
4751            this.select_to_end_of_line(
4752                &SelectToEndOfLine {
4753                    stop_at_soft_wraps: false,
4754                },
4755                cx,
4756            );
4757            this.delete(&Delete, cx);
4758        });
4759    }
4760
4761    pub fn cut_to_end_of_line(&mut self, _: &CutToEndOfLine, cx: &mut ViewContext<Self>) {
4762        self.transact(cx, |this, cx| {
4763            this.select_to_end_of_line(
4764                &SelectToEndOfLine {
4765                    stop_at_soft_wraps: false,
4766                },
4767                cx,
4768            );
4769            this.cut(&Cut, cx);
4770        });
4771    }
4772
4773    pub fn move_to_start_of_paragraph(
4774        &mut self,
4775        _: &MoveToStartOfParagraph,
4776        cx: &mut ViewContext<Self>,
4777    ) {
4778        if matches!(self.mode, EditorMode::SingleLine) {
4779            cx.propagate_action();
4780            return;
4781        }
4782
4783        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4784            s.move_with(|map, selection| {
4785                selection.collapse_to(
4786                    movement::start_of_paragraph(map, selection.head()),
4787                    SelectionGoal::None,
4788                )
4789            });
4790        })
4791    }
4792
4793    pub fn move_to_end_of_paragraph(
4794        &mut self,
4795        _: &MoveToEndOfParagraph,
4796        cx: &mut ViewContext<Self>,
4797    ) {
4798        if matches!(self.mode, EditorMode::SingleLine) {
4799            cx.propagate_action();
4800            return;
4801        }
4802
4803        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4804            s.move_with(|map, selection| {
4805                selection.collapse_to(
4806                    movement::end_of_paragraph(map, selection.head()),
4807                    SelectionGoal::None,
4808                )
4809            });
4810        })
4811    }
4812
4813    pub fn select_to_start_of_paragraph(
4814        &mut self,
4815        _: &SelectToStartOfParagraph,
4816        cx: &mut ViewContext<Self>,
4817    ) {
4818        if matches!(self.mode, EditorMode::SingleLine) {
4819            cx.propagate_action();
4820            return;
4821        }
4822
4823        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4824            s.move_heads_with(|map, head, _| {
4825                (movement::start_of_paragraph(map, head), SelectionGoal::None)
4826            });
4827        })
4828    }
4829
4830    pub fn select_to_end_of_paragraph(
4831        &mut self,
4832        _: &SelectToEndOfParagraph,
4833        cx: &mut ViewContext<Self>,
4834    ) {
4835        if matches!(self.mode, EditorMode::SingleLine) {
4836            cx.propagate_action();
4837            return;
4838        }
4839
4840        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4841            s.move_heads_with(|map, head, _| {
4842                (movement::end_of_paragraph(map, head), SelectionGoal::None)
4843            });
4844        })
4845    }
4846
4847    pub fn move_to_beginning(&mut self, _: &MoveToBeginning, cx: &mut ViewContext<Self>) {
4848        if matches!(self.mode, EditorMode::SingleLine) {
4849            cx.propagate_action();
4850            return;
4851        }
4852
4853        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4854            s.select_ranges(vec![0..0]);
4855        });
4856    }
4857
4858    pub fn select_to_beginning(&mut self, _: &SelectToBeginning, cx: &mut ViewContext<Self>) {
4859        let mut selection = self.selections.last::<Point>(cx);
4860        selection.set_head(Point::zero(), SelectionGoal::None);
4861
4862        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4863            s.select(vec![selection]);
4864        });
4865    }
4866
4867    pub fn move_to_end(&mut self, _: &MoveToEnd, cx: &mut ViewContext<Self>) {
4868        if matches!(self.mode, EditorMode::SingleLine) {
4869            cx.propagate_action();
4870            return;
4871        }
4872
4873        let cursor = self.buffer.read(cx).read(cx).len();
4874        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4875            s.select_ranges(vec![cursor..cursor])
4876        });
4877    }
4878
4879    pub fn set_nav_history(&mut self, nav_history: Option<ItemNavHistory>) {
4880        self.nav_history = nav_history;
4881    }
4882
4883    pub fn nav_history(&self) -> Option<&ItemNavHistory> {
4884        self.nav_history.as_ref()
4885    }
4886
4887    fn push_to_nav_history(
4888        &self,
4889        cursor_anchor: Anchor,
4890        new_position: Option<Point>,
4891        cx: &mut ViewContext<Self>,
4892    ) {
4893        if let Some(nav_history) = &self.nav_history {
4894            let buffer = self.buffer.read(cx).read(cx);
4895            let cursor_position = cursor_anchor.to_point(&buffer);
4896            let scroll_state = self.scroll_manager.anchor();
4897            let scroll_top_row = scroll_state.top_row(&buffer);
4898            drop(buffer);
4899
4900            if let Some(new_position) = new_position {
4901                let row_delta = (new_position.row as i64 - cursor_position.row as i64).abs();
4902                if row_delta < MIN_NAVIGATION_HISTORY_ROW_DELTA {
4903                    return;
4904                }
4905            }
4906
4907            nav_history.push(
4908                Some(NavigationData {
4909                    cursor_anchor,
4910                    cursor_position,
4911                    scroll_anchor: scroll_state,
4912                    scroll_top_row,
4913                }),
4914                cx,
4915            );
4916        }
4917    }
4918
4919    pub fn select_to_end(&mut self, _: &SelectToEnd, cx: &mut ViewContext<Self>) {
4920        let buffer = self.buffer.read(cx).snapshot(cx);
4921        let mut selection = self.selections.first::<usize>(cx);
4922        selection.set_head(buffer.len(), SelectionGoal::None);
4923        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4924            s.select(vec![selection]);
4925        });
4926    }
4927
4928    pub fn select_all(&mut self, _: &SelectAll, cx: &mut ViewContext<Self>) {
4929        let end = self.buffer.read(cx).read(cx).len();
4930        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4931            s.select_ranges(vec![0..end]);
4932        });
4933    }
4934
4935    pub fn select_line(&mut self, _: &SelectLine, cx: &mut ViewContext<Self>) {
4936        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4937        let mut selections = self.selections.all::<Point>(cx);
4938        let max_point = display_map.buffer_snapshot.max_point();
4939        for selection in &mut selections {
4940            let rows = selection.spanned_rows(true, &display_map);
4941            selection.start = Point::new(rows.start, 0);
4942            selection.end = cmp::min(max_point, Point::new(rows.end, 0));
4943            selection.reversed = false;
4944        }
4945        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4946            s.select(selections);
4947        });
4948    }
4949
4950    pub fn split_selection_into_lines(
4951        &mut self,
4952        _: &SplitSelectionIntoLines,
4953        cx: &mut ViewContext<Self>,
4954    ) {
4955        let mut to_unfold = Vec::new();
4956        let mut new_selection_ranges = Vec::new();
4957        {
4958            let selections = self.selections.all::<Point>(cx);
4959            let buffer = self.buffer.read(cx).read(cx);
4960            for selection in selections {
4961                for row in selection.start.row..selection.end.row {
4962                    let cursor = Point::new(row, buffer.line_len(row));
4963                    new_selection_ranges.push(cursor..cursor);
4964                }
4965                new_selection_ranges.push(selection.end..selection.end);
4966                to_unfold.push(selection.start..selection.end);
4967            }
4968        }
4969        self.unfold_ranges(to_unfold, true, true, cx);
4970        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4971            s.select_ranges(new_selection_ranges);
4972        });
4973    }
4974
4975    pub fn add_selection_above(&mut self, _: &AddSelectionAbove, cx: &mut ViewContext<Self>) {
4976        self.add_selection(true, cx);
4977    }
4978
4979    pub fn add_selection_below(&mut self, _: &AddSelectionBelow, cx: &mut ViewContext<Self>) {
4980        self.add_selection(false, cx);
4981    }
4982
4983    fn add_selection(&mut self, above: bool, cx: &mut ViewContext<Self>) {
4984        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4985        let mut selections = self.selections.all::<Point>(cx);
4986        let mut state = self.add_selections_state.take().unwrap_or_else(|| {
4987            let oldest_selection = selections.iter().min_by_key(|s| s.id).unwrap().clone();
4988            let range = oldest_selection.display_range(&display_map).sorted();
4989            let columns = cmp::min(range.start.column(), range.end.column())
4990                ..cmp::max(range.start.column(), range.end.column());
4991
4992            selections.clear();
4993            let mut stack = Vec::new();
4994            for row in range.start.row()..=range.end.row() {
4995                if let Some(selection) = self.selections.build_columnar_selection(
4996                    &display_map,
4997                    row,
4998                    &columns,
4999                    oldest_selection.reversed,
5000                ) {
5001                    stack.push(selection.id);
5002                    selections.push(selection);
5003                }
5004            }
5005
5006            if above {
5007                stack.reverse();
5008            }
5009
5010            AddSelectionsState { above, stack }
5011        });
5012
5013        let last_added_selection = *state.stack.last().unwrap();
5014        let mut new_selections = Vec::new();
5015        if above == state.above {
5016            let end_row = if above {
5017                0
5018            } else {
5019                display_map.max_point().row()
5020            };
5021
5022            'outer: for selection in selections {
5023                if selection.id == last_added_selection {
5024                    let range = selection.display_range(&display_map).sorted();
5025                    debug_assert_eq!(range.start.row(), range.end.row());
5026                    let mut row = range.start.row();
5027                    let columns = if let SelectionGoal::ColumnRange { start, end } = selection.goal
5028                    {
5029                        start..end
5030                    } else {
5031                        cmp::min(range.start.column(), range.end.column())
5032                            ..cmp::max(range.start.column(), range.end.column())
5033                    };
5034
5035                    while row != end_row {
5036                        if above {
5037                            row -= 1;
5038                        } else {
5039                            row += 1;
5040                        }
5041
5042                        if let Some(new_selection) = self.selections.build_columnar_selection(
5043                            &display_map,
5044                            row,
5045                            &columns,
5046                            selection.reversed,
5047                        ) {
5048                            state.stack.push(new_selection.id);
5049                            if above {
5050                                new_selections.push(new_selection);
5051                                new_selections.push(selection);
5052                            } else {
5053                                new_selections.push(selection);
5054                                new_selections.push(new_selection);
5055                            }
5056
5057                            continue 'outer;
5058                        }
5059                    }
5060                }
5061
5062                new_selections.push(selection);
5063            }
5064        } else {
5065            new_selections = selections;
5066            new_selections.retain(|s| s.id != last_added_selection);
5067            state.stack.pop();
5068        }
5069
5070        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5071            s.select(new_selections);
5072        });
5073        if state.stack.len() > 1 {
5074            self.add_selections_state = Some(state);
5075        }
5076    }
5077
5078    pub fn select_next(&mut self, action: &SelectNext, cx: &mut ViewContext<Self>) {
5079        self.push_to_selection_history();
5080        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5081        let buffer = &display_map.buffer_snapshot;
5082        let mut selections = self.selections.all::<usize>(cx);
5083        if let Some(mut select_next_state) = self.select_next_state.take() {
5084            let query = &select_next_state.query;
5085            if !select_next_state.done {
5086                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
5087                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
5088                let mut next_selected_range = None;
5089
5090                let bytes_after_last_selection =
5091                    buffer.bytes_in_range(last_selection.end..buffer.len());
5092                let bytes_before_first_selection = buffer.bytes_in_range(0..first_selection.start);
5093                let query_matches = query
5094                    .stream_find_iter(bytes_after_last_selection)
5095                    .map(|result| (last_selection.end, result))
5096                    .chain(
5097                        query
5098                            .stream_find_iter(bytes_before_first_selection)
5099                            .map(|result| (0, result)),
5100                    );
5101                for (start_offset, query_match) in query_matches {
5102                    let query_match = query_match.unwrap(); // can only fail due to I/O
5103                    let offset_range =
5104                        start_offset + query_match.start()..start_offset + query_match.end();
5105                    let display_range = offset_range.start.to_display_point(&display_map)
5106                        ..offset_range.end.to_display_point(&display_map);
5107
5108                    if !select_next_state.wordwise
5109                        || (!movement::is_inside_word(&display_map, display_range.start)
5110                            && !movement::is_inside_word(&display_map, display_range.end))
5111                    {
5112                        next_selected_range = Some(offset_range);
5113                        break;
5114                    }
5115                }
5116
5117                if let Some(next_selected_range) = next_selected_range {
5118                    self.unfold_ranges([next_selected_range.clone()], false, true, cx);
5119                    self.change_selections(Some(Autoscroll::newest()), cx, |s| {
5120                        if action.replace_newest {
5121                            s.delete(s.newest_anchor().id);
5122                        }
5123                        s.insert_range(next_selected_range);
5124                    });
5125                } else {
5126                    select_next_state.done = true;
5127                }
5128            }
5129
5130            self.select_next_state = Some(select_next_state);
5131        } else if selections.len() == 1 {
5132            let selection = selections.last_mut().unwrap();
5133            if selection.start == selection.end {
5134                let word_range = movement::surrounding_word(
5135                    &display_map,
5136                    selection.start.to_display_point(&display_map),
5137                );
5138                selection.start = word_range.start.to_offset(&display_map, Bias::Left);
5139                selection.end = word_range.end.to_offset(&display_map, Bias::Left);
5140                selection.goal = SelectionGoal::None;
5141                selection.reversed = false;
5142
5143                let query = buffer
5144                    .text_for_range(selection.start..selection.end)
5145                    .collect::<String>();
5146                let select_state = SelectNextState {
5147                    query: AhoCorasick::new_auto_configured(&[query]),
5148                    wordwise: true,
5149                    done: false,
5150                };
5151                self.unfold_ranges([selection.start..selection.end], false, true, cx);
5152                self.change_selections(Some(Autoscroll::newest()), cx, |s| {
5153                    s.select(selections);
5154                });
5155                self.select_next_state = Some(select_state);
5156            } else {
5157                let query = buffer
5158                    .text_for_range(selection.start..selection.end)
5159                    .collect::<String>();
5160                self.select_next_state = Some(SelectNextState {
5161                    query: AhoCorasick::new_auto_configured(&[query]),
5162                    wordwise: false,
5163                    done: false,
5164                });
5165                self.select_next(action, cx);
5166            }
5167        }
5168    }
5169
5170    pub fn toggle_comments(&mut self, action: &ToggleComments, cx: &mut ViewContext<Self>) {
5171        self.transact(cx, |this, cx| {
5172            let mut selections = this.selections.all::<Point>(cx);
5173            let mut edits = Vec::new();
5174            let mut selection_edit_ranges = Vec::new();
5175            let mut last_toggled_row = None;
5176            let snapshot = this.buffer.read(cx).read(cx);
5177            let empty_str: Arc<str> = "".into();
5178            let mut suffixes_inserted = Vec::new();
5179
5180            fn comment_prefix_range(
5181                snapshot: &MultiBufferSnapshot,
5182                row: u32,
5183                comment_prefix: &str,
5184                comment_prefix_whitespace: &str,
5185            ) -> Range<Point> {
5186                let start = Point::new(row, snapshot.indent_size_for_line(row).len);
5187
5188                let mut line_bytes = snapshot
5189                    .bytes_in_range(start..snapshot.max_point())
5190                    .flatten()
5191                    .copied();
5192
5193                // If this line currently begins with the line comment prefix, then record
5194                // the range containing the prefix.
5195                if line_bytes
5196                    .by_ref()
5197                    .take(comment_prefix.len())
5198                    .eq(comment_prefix.bytes())
5199                {
5200                    // Include any whitespace that matches the comment prefix.
5201                    let matching_whitespace_len = line_bytes
5202                        .zip(comment_prefix_whitespace.bytes())
5203                        .take_while(|(a, b)| a == b)
5204                        .count() as u32;
5205                    let end = Point::new(
5206                        start.row,
5207                        start.column + comment_prefix.len() as u32 + matching_whitespace_len,
5208                    );
5209                    start..end
5210                } else {
5211                    start..start
5212                }
5213            }
5214
5215            fn comment_suffix_range(
5216                snapshot: &MultiBufferSnapshot,
5217                row: u32,
5218                comment_suffix: &str,
5219                comment_suffix_has_leading_space: bool,
5220            ) -> Range<Point> {
5221                let end = Point::new(row, snapshot.line_len(row));
5222                let suffix_start_column = end.column.saturating_sub(comment_suffix.len() as u32);
5223
5224                let mut line_end_bytes = snapshot
5225                    .bytes_in_range(Point::new(end.row, suffix_start_column.saturating_sub(1))..end)
5226                    .flatten()
5227                    .copied();
5228
5229                let leading_space_len = if suffix_start_column > 0
5230                    && line_end_bytes.next() == Some(b' ')
5231                    && comment_suffix_has_leading_space
5232                {
5233                    1
5234                } else {
5235                    0
5236                };
5237
5238                // If this line currently begins with the line comment prefix, then record
5239                // the range containing the prefix.
5240                if line_end_bytes.by_ref().eq(comment_suffix.bytes()) {
5241                    let start = Point::new(end.row, suffix_start_column - leading_space_len);
5242                    start..end
5243                } else {
5244                    end..end
5245                }
5246            }
5247
5248            // TODO: Handle selections that cross excerpts
5249            for selection in &mut selections {
5250                let start_column = snapshot.indent_size_for_line(selection.start.row).len;
5251                let language = if let Some(language) =
5252                    snapshot.language_scope_at(Point::new(selection.start.row, start_column))
5253                {
5254                    language
5255                } else {
5256                    continue;
5257                };
5258
5259                selection_edit_ranges.clear();
5260
5261                // If multiple selections contain a given row, avoid processing that
5262                // row more than once.
5263                let mut start_row = selection.start.row;
5264                if last_toggled_row == Some(start_row) {
5265                    start_row += 1;
5266                }
5267                let end_row =
5268                    if selection.end.row > selection.start.row && selection.end.column == 0 {
5269                        selection.end.row - 1
5270                    } else {
5271                        selection.end.row
5272                    };
5273                last_toggled_row = Some(end_row);
5274
5275                if start_row > end_row {
5276                    continue;
5277                }
5278
5279                // If the language has line comments, toggle those.
5280                if let Some(full_comment_prefix) = language.line_comment_prefix() {
5281                    // Split the comment prefix's trailing whitespace into a separate string,
5282                    // as that portion won't be used for detecting if a line is a comment.
5283                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
5284                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
5285                    let mut all_selection_lines_are_comments = true;
5286
5287                    for row in start_row..=end_row {
5288                        if snapshot.is_line_blank(row) {
5289                            continue;
5290                        }
5291
5292                        let prefix_range = comment_prefix_range(
5293                            snapshot.deref(),
5294                            row,
5295                            comment_prefix,
5296                            comment_prefix_whitespace,
5297                        );
5298                        if prefix_range.is_empty() {
5299                            all_selection_lines_are_comments = false;
5300                        }
5301                        selection_edit_ranges.push(prefix_range);
5302                    }
5303
5304                    if all_selection_lines_are_comments {
5305                        edits.extend(
5306                            selection_edit_ranges
5307                                .iter()
5308                                .cloned()
5309                                .map(|range| (range, empty_str.clone())),
5310                        );
5311                    } else {
5312                        let min_column = selection_edit_ranges
5313                            .iter()
5314                            .map(|r| r.start.column)
5315                            .min()
5316                            .unwrap_or(0);
5317                        edits.extend(selection_edit_ranges.iter().map(|range| {
5318                            let position = Point::new(range.start.row, min_column);
5319                            (position..position, full_comment_prefix.clone())
5320                        }));
5321                    }
5322                } else if let Some((full_comment_prefix, comment_suffix)) =
5323                    language.block_comment_delimiters()
5324                {
5325                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
5326                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
5327                    let prefix_range = comment_prefix_range(
5328                        snapshot.deref(),
5329                        start_row,
5330                        comment_prefix,
5331                        comment_prefix_whitespace,
5332                    );
5333                    let suffix_range = comment_suffix_range(
5334                        snapshot.deref(),
5335                        end_row,
5336                        comment_suffix.trim_start_matches(' '),
5337                        comment_suffix.starts_with(' '),
5338                    );
5339
5340                    if prefix_range.is_empty() || suffix_range.is_empty() {
5341                        edits.push((
5342                            prefix_range.start..prefix_range.start,
5343                            full_comment_prefix.clone(),
5344                        ));
5345                        edits.push((suffix_range.end..suffix_range.end, comment_suffix.clone()));
5346                        suffixes_inserted.push((end_row, comment_suffix.len()));
5347                    } else {
5348                        edits.push((prefix_range, empty_str.clone()));
5349                        edits.push((suffix_range, empty_str.clone()));
5350                    }
5351                } else {
5352                    continue;
5353                }
5354            }
5355
5356            drop(snapshot);
5357            this.buffer.update(cx, |buffer, cx| {
5358                buffer.edit(edits, None, cx);
5359            });
5360
5361            // Adjust selections so that they end before any comment suffixes that
5362            // were inserted.
5363            let mut suffixes_inserted = suffixes_inserted.into_iter().peekable();
5364            let mut selections = this.selections.all::<Point>(cx);
5365            let snapshot = this.buffer.read(cx).read(cx);
5366            for selection in &mut selections {
5367                while let Some((row, suffix_len)) = suffixes_inserted.peek().copied() {
5368                    match row.cmp(&selection.end.row) {
5369                        Ordering::Less => {
5370                            suffixes_inserted.next();
5371                            continue;
5372                        }
5373                        Ordering::Greater => break,
5374                        Ordering::Equal => {
5375                            if selection.end.column == snapshot.line_len(row) {
5376                                if selection.is_empty() {
5377                                    selection.start.column -= suffix_len as u32;
5378                                }
5379                                selection.end.column -= suffix_len as u32;
5380                            }
5381                            break;
5382                        }
5383                    }
5384                }
5385            }
5386
5387            drop(snapshot);
5388            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
5389
5390            let selections = this.selections.all::<Point>(cx);
5391            let selections_on_single_row = selections.windows(2).all(|selections| {
5392                selections[0].start.row == selections[1].start.row
5393                    && selections[0].end.row == selections[1].end.row
5394                    && selections[0].start.row == selections[0].end.row
5395            });
5396            let selections_selecting = selections
5397                .iter()
5398                .any(|selection| selection.start != selection.end);
5399            let advance_downwards = action.advance_downwards
5400                && selections_on_single_row
5401                && !selections_selecting
5402                && this.mode != EditorMode::SingleLine;
5403
5404            if advance_downwards {
5405                let snapshot = this.buffer.read(cx).snapshot(cx);
5406
5407                this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5408                    s.move_cursors_with(|display_snapshot, display_point, _| {
5409                        let mut point = display_point.to_point(display_snapshot);
5410                        point.row += 1;
5411                        point = snapshot.clip_point(point, Bias::Left);
5412                        let display_point = point.to_display_point(display_snapshot);
5413                        (display_point, SelectionGoal::Column(display_point.column()))
5414                    })
5415                });
5416            }
5417        });
5418    }
5419
5420    pub fn select_larger_syntax_node(
5421        &mut self,
5422        _: &SelectLargerSyntaxNode,
5423        cx: &mut ViewContext<Self>,
5424    ) {
5425        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5426        let buffer = self.buffer.read(cx).snapshot(cx);
5427        let old_selections = self.selections.all::<usize>(cx).into_boxed_slice();
5428
5429        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
5430        let mut selected_larger_node = false;
5431        let new_selections = old_selections
5432            .iter()
5433            .map(|selection| {
5434                let old_range = selection.start..selection.end;
5435                let mut new_range = old_range.clone();
5436                while let Some(containing_range) =
5437                    buffer.range_for_syntax_ancestor(new_range.clone())
5438                {
5439                    new_range = containing_range;
5440                    if !display_map.intersects_fold(new_range.start)
5441                        && !display_map.intersects_fold(new_range.end)
5442                    {
5443                        break;
5444                    }
5445                }
5446
5447                selected_larger_node |= new_range != old_range;
5448                Selection {
5449                    id: selection.id,
5450                    start: new_range.start,
5451                    end: new_range.end,
5452                    goal: SelectionGoal::None,
5453                    reversed: selection.reversed,
5454                }
5455            })
5456            .collect::<Vec<_>>();
5457
5458        if selected_larger_node {
5459            stack.push(old_selections);
5460            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5461                s.select(new_selections);
5462            });
5463        }
5464        self.select_larger_syntax_node_stack = stack;
5465    }
5466
5467    pub fn select_smaller_syntax_node(
5468        &mut self,
5469        _: &SelectSmallerSyntaxNode,
5470        cx: &mut ViewContext<Self>,
5471    ) {
5472        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
5473        if let Some(selections) = stack.pop() {
5474            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5475                s.select(selections.to_vec());
5476            });
5477        }
5478        self.select_larger_syntax_node_stack = stack;
5479    }
5480
5481    pub fn move_to_enclosing_bracket(
5482        &mut self,
5483        _: &MoveToEnclosingBracket,
5484        cx: &mut ViewContext<Self>,
5485    ) {
5486        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5487            s.move_offsets_with(|snapshot, selection| {
5488                let Some(enclosing_bracket_ranges) = snapshot.enclosing_bracket_ranges(selection.start..selection.end) else {
5489                    return;
5490                };
5491
5492                let mut best_length = usize::MAX;
5493                let mut best_inside = false;
5494                let mut best_in_bracket_range = false;
5495                let mut best_destination = None;
5496                for (open, close) in enclosing_bracket_ranges {
5497                    let close = close.to_inclusive();
5498                    let length = close.end() - open.start;
5499                    let inside = selection.start >= open.end && selection.end <= *close.start();
5500                    let in_bracket_range = open.to_inclusive().contains(&selection.head()) || close.contains(&selection.head());
5501
5502                    // If best is next to a bracket and current isn't, skip
5503                    if !in_bracket_range && best_in_bracket_range {
5504                        continue;
5505                    }
5506
5507                    // Prefer smaller lengths unless best is inside and current isn't
5508                    if length > best_length && (best_inside || !inside) {
5509                        continue;
5510                    }
5511
5512                    best_length = length;
5513                    best_inside = inside;
5514                    best_in_bracket_range = in_bracket_range;
5515                    best_destination = Some(if close.contains(&selection.start) && close.contains(&selection.end) {
5516                        if inside {
5517                            open.end
5518                        } else {
5519                            open.start
5520                        }
5521                    } else {
5522                        if inside {
5523                            *close.start()
5524                        } else {
5525                            *close.end()
5526                        }
5527                    });
5528                }
5529
5530                if let Some(destination) = best_destination {
5531                    selection.collapse_to(destination, SelectionGoal::None);
5532                }
5533            })
5534        });
5535    }
5536
5537    pub fn undo_selection(&mut self, _: &UndoSelection, cx: &mut ViewContext<Self>) {
5538        self.end_selection(cx);
5539        self.selection_history.mode = SelectionHistoryMode::Undoing;
5540        if let Some(entry) = self.selection_history.undo_stack.pop_back() {
5541            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
5542            self.select_next_state = entry.select_next_state;
5543            self.add_selections_state = entry.add_selections_state;
5544            self.request_autoscroll(Autoscroll::newest(), cx);
5545        }
5546        self.selection_history.mode = SelectionHistoryMode::Normal;
5547    }
5548
5549    pub fn redo_selection(&mut self, _: &RedoSelection, cx: &mut ViewContext<Self>) {
5550        self.end_selection(cx);
5551        self.selection_history.mode = SelectionHistoryMode::Redoing;
5552        if let Some(entry) = self.selection_history.redo_stack.pop_back() {
5553            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
5554            self.select_next_state = entry.select_next_state;
5555            self.add_selections_state = entry.add_selections_state;
5556            self.request_autoscroll(Autoscroll::newest(), cx);
5557        }
5558        self.selection_history.mode = SelectionHistoryMode::Normal;
5559    }
5560
5561    fn go_to_diagnostic(&mut self, _: &GoToDiagnostic, cx: &mut ViewContext<Self>) {
5562        self.go_to_diagnostic_impl(Direction::Next, cx)
5563    }
5564
5565    fn go_to_prev_diagnostic(&mut self, _: &GoToPrevDiagnostic, cx: &mut ViewContext<Self>) {
5566        self.go_to_diagnostic_impl(Direction::Prev, cx)
5567    }
5568
5569    pub fn go_to_diagnostic_impl(&mut self, direction: Direction, cx: &mut ViewContext<Self>) {
5570        let buffer = self.buffer.read(cx).snapshot(cx);
5571        let selection = self.selections.newest::<usize>(cx);
5572
5573        // If there is an active Diagnostic Popover. Jump to it's diagnostic instead.
5574        if direction == Direction::Next {
5575            if let Some(popover) = self.hover_state.diagnostic_popover.as_ref() {
5576                let (group_id, jump_to) = popover.activation_info();
5577                if self.activate_diagnostics(group_id, cx) {
5578                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5579                        let mut new_selection = s.newest_anchor().clone();
5580                        new_selection.collapse_to(jump_to, SelectionGoal::None);
5581                        s.select_anchors(vec![new_selection.clone()]);
5582                    });
5583                }
5584                return;
5585            }
5586        }
5587
5588        let mut active_primary_range = self.active_diagnostics.as_ref().map(|active_diagnostics| {
5589            active_diagnostics
5590                .primary_range
5591                .to_offset(&buffer)
5592                .to_inclusive()
5593        });
5594        let mut search_start = if let Some(active_primary_range) = active_primary_range.as_ref() {
5595            if active_primary_range.contains(&selection.head()) {
5596                *active_primary_range.end()
5597            } else {
5598                selection.head()
5599            }
5600        } else {
5601            selection.head()
5602        };
5603
5604        loop {
5605            let mut diagnostics = if direction == Direction::Prev {
5606                buffer.diagnostics_in_range::<_, usize>(0..search_start, true)
5607            } else {
5608                buffer.diagnostics_in_range::<_, usize>(search_start..buffer.len(), false)
5609            };
5610            let group = diagnostics.find_map(|entry| {
5611                if entry.diagnostic.is_primary
5612                    && entry.diagnostic.severity <= DiagnosticSeverity::WARNING
5613                    && !entry.range.is_empty()
5614                    && Some(entry.range.end) != active_primary_range.as_ref().map(|r| *r.end())
5615                {
5616                    Some((entry.range, entry.diagnostic.group_id))
5617                } else {
5618                    None
5619                }
5620            });
5621
5622            if let Some((primary_range, group_id)) = group {
5623                if self.activate_diagnostics(group_id, cx) {
5624                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5625                        s.select(vec![Selection {
5626                            id: selection.id,
5627                            start: primary_range.start,
5628                            end: primary_range.start,
5629                            reversed: false,
5630                            goal: SelectionGoal::None,
5631                        }]);
5632                    });
5633                }
5634                break;
5635            } else {
5636                // Cycle around to the start of the buffer, potentially moving back to the start of
5637                // the currently active diagnostic.
5638                active_primary_range.take();
5639                if direction == Direction::Prev {
5640                    if search_start == buffer.len() {
5641                        break;
5642                    } else {
5643                        search_start = buffer.len();
5644                    }
5645                } else if search_start == 0 {
5646                    break;
5647                } else {
5648                    search_start = 0;
5649                }
5650            }
5651        }
5652    }
5653
5654    fn go_to_hunk(&mut self, _: &GoToHunk, cx: &mut ViewContext<Self>) {
5655        let snapshot = self
5656            .display_map
5657            .update(cx, |display_map, cx| display_map.snapshot(cx));
5658        let selection = self.selections.newest::<Point>(cx);
5659
5660        if !self.seek_in_direction(
5661            &snapshot,
5662            selection.head(),
5663            false,
5664            snapshot
5665                .buffer_snapshot
5666                .git_diff_hunks_in_range((selection.head().row + 1)..u32::MAX),
5667            cx,
5668        ) {
5669            let wrapped_point = Point::zero();
5670            self.seek_in_direction(
5671                &snapshot,
5672                wrapped_point,
5673                true,
5674                snapshot
5675                    .buffer_snapshot
5676                    .git_diff_hunks_in_range((wrapped_point.row + 1)..u32::MAX),
5677                cx,
5678            );
5679        }
5680    }
5681
5682    fn go_to_prev_hunk(&mut self, _: &GoToPrevHunk, cx: &mut ViewContext<Self>) {
5683        let snapshot = self
5684            .display_map
5685            .update(cx, |display_map, cx| display_map.snapshot(cx));
5686        let selection = self.selections.newest::<Point>(cx);
5687
5688        if !self.seek_in_direction(
5689            &snapshot,
5690            selection.head(),
5691            false,
5692            snapshot
5693                .buffer_snapshot
5694                .git_diff_hunks_in_range_rev(0..selection.head().row),
5695            cx,
5696        ) {
5697            let wrapped_point = snapshot.buffer_snapshot.max_point();
5698            self.seek_in_direction(
5699                &snapshot,
5700                wrapped_point,
5701                true,
5702                snapshot
5703                    .buffer_snapshot
5704                    .git_diff_hunks_in_range_rev(0..wrapped_point.row),
5705                cx,
5706            );
5707        }
5708    }
5709
5710    fn seek_in_direction(
5711        &mut self,
5712        snapshot: &DisplaySnapshot,
5713        initial_point: Point,
5714        is_wrapped: bool,
5715        hunks: impl Iterator<Item = DiffHunk<u32>>,
5716        cx: &mut ViewContext<Editor>,
5717    ) -> bool {
5718        let display_point = initial_point.to_display_point(snapshot);
5719        let mut hunks = hunks
5720            .map(|hunk| diff_hunk_to_display(hunk, &snapshot))
5721            .skip_while(|hunk| {
5722                if is_wrapped {
5723                    false
5724                } else {
5725                    hunk.contains_display_row(display_point.row())
5726                }
5727            })
5728            .dedup();
5729
5730        if let Some(hunk) = hunks.next() {
5731            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5732                let row = hunk.start_display_row();
5733                let point = DisplayPoint::new(row, 0);
5734                s.select_display_ranges([point..point]);
5735            });
5736
5737            true
5738        } else {
5739            false
5740        }
5741    }
5742
5743    pub fn go_to_definition(&mut self, _: &GoToDefinition, cx: &mut ViewContext<Self>) {
5744        self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, cx);
5745    }
5746
5747    pub fn go_to_type_definition(&mut self, _: &GoToTypeDefinition, cx: &mut ViewContext<Self>) {
5748        self.go_to_definition_of_kind(GotoDefinitionKind::Type, cx);
5749    }
5750
5751    fn go_to_definition_of_kind(&mut self, kind: GotoDefinitionKind, cx: &mut ViewContext<Self>) {
5752        let Some(workspace) = self.workspace(cx) else { return };
5753        let buffer = self.buffer.read(cx);
5754        let head = self.selections.newest::<usize>(cx).head();
5755        let (buffer, head) = if let Some(text_anchor) = buffer.text_anchor_for_position(head, cx) {
5756            text_anchor
5757        } else {
5758            return;
5759        };
5760
5761        let project = workspace.read(cx).project().clone();
5762        let definitions = project.update(cx, |project, cx| match kind {
5763            GotoDefinitionKind::Symbol => project.definition(&buffer, head, cx),
5764            GotoDefinitionKind::Type => project.type_definition(&buffer, head, cx),
5765        });
5766
5767        cx.spawn_labeled("Fetching Definition...", |editor, mut cx| async move {
5768            let definitions = definitions.await?;
5769            editor.update(&mut cx, |editor, cx| {
5770                editor.navigate_to_definitions(definitions, cx);
5771            })?;
5772            Ok::<(), anyhow::Error>(())
5773        })
5774        .detach_and_log_err(cx);
5775    }
5776
5777    pub fn navigate_to_definitions(
5778        &mut self,
5779        mut definitions: Vec<LocationLink>,
5780        cx: &mut ViewContext<Editor>,
5781    ) {
5782        let Some(workspace) = self.workspace(cx) else { return };
5783        let pane = workspace.read(cx).active_pane().clone();
5784        // If there is one definition, just open it directly
5785        if definitions.len() == 1 {
5786            let definition = definitions.pop().unwrap();
5787            let range = definition
5788                .target
5789                .range
5790                .to_offset(definition.target.buffer.read(cx));
5791
5792            if Some(&definition.target.buffer) == self.buffer.read(cx).as_singleton().as_ref() {
5793                self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5794                    s.select_ranges([range]);
5795                });
5796            } else {
5797                cx.window_context().defer(move |cx| {
5798                    let target_editor: ViewHandle<Self> = workspace.update(cx, |workspace, cx| {
5799                        workspace.open_project_item(definition.target.buffer.clone(), cx)
5800                    });
5801                    target_editor.update(cx, |target_editor, cx| {
5802                        // When selecting a definition in a different buffer, disable the nav history
5803                        // to avoid creating a history entry at the previous cursor location.
5804                        pane.update(cx, |pane, _| pane.disable_history());
5805                        target_editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
5806                            s.select_ranges([range]);
5807                        });
5808                        pane.update(cx, |pane, _| pane.enable_history());
5809                    });
5810                });
5811            }
5812        } else if !definitions.is_empty() {
5813            let replica_id = self.replica_id(cx);
5814            cx.window_context().defer(move |cx| {
5815                let title = definitions
5816                    .iter()
5817                    .find(|definition| definition.origin.is_some())
5818                    .and_then(|definition| {
5819                        definition.origin.as_ref().map(|origin| {
5820                            let buffer = origin.buffer.read(cx);
5821                            format!(
5822                                "Definitions for {}",
5823                                buffer
5824                                    .text_for_range(origin.range.clone())
5825                                    .collect::<String>()
5826                            )
5827                        })
5828                    })
5829                    .unwrap_or("Definitions".to_owned());
5830                let locations = definitions
5831                    .into_iter()
5832                    .map(|definition| definition.target)
5833                    .collect();
5834                workspace.update(cx, |workspace, cx| {
5835                    Self::open_locations_in_multibuffer(workspace, locations, replica_id, title, cx)
5836                });
5837            });
5838        }
5839    }
5840
5841    pub fn find_all_references(
5842        workspace: &mut Workspace,
5843        _: &FindAllReferences,
5844        cx: &mut ViewContext<Workspace>,
5845    ) -> Option<Task<Result<()>>> {
5846        let active_item = workspace.active_item(cx)?;
5847        let editor_handle = active_item.act_as::<Self>(cx)?;
5848
5849        let editor = editor_handle.read(cx);
5850        let buffer = editor.buffer.read(cx);
5851        let head = editor.selections.newest::<usize>(cx).head();
5852        let (buffer, head) = buffer.text_anchor_for_position(head, cx)?;
5853        let replica_id = editor.replica_id(cx);
5854
5855        let project = workspace.project().clone();
5856        let references = project.update(cx, |project, cx| project.references(&buffer, head, cx));
5857        Some(cx.spawn_labeled(
5858            "Finding All References...",
5859            |workspace, mut cx| async move {
5860                let locations = references.await?;
5861                if locations.is_empty() {
5862                    return Ok(());
5863                }
5864
5865                workspace.update(&mut cx, |workspace, cx| {
5866                    let title = locations
5867                        .first()
5868                        .as_ref()
5869                        .map(|location| {
5870                            let buffer = location.buffer.read(cx);
5871                            format!(
5872                                "References to `{}`",
5873                                buffer
5874                                    .text_for_range(location.range.clone())
5875                                    .collect::<String>()
5876                            )
5877                        })
5878                        .unwrap();
5879                    Self::open_locations_in_multibuffer(
5880                        workspace, locations, replica_id, title, cx,
5881                    );
5882                })?;
5883
5884                Ok(())
5885            },
5886        ))
5887    }
5888
5889    /// Opens a multibuffer with the given project locations in it
5890    pub fn open_locations_in_multibuffer(
5891        workspace: &mut Workspace,
5892        mut locations: Vec<Location>,
5893        replica_id: ReplicaId,
5894        title: String,
5895        cx: &mut ViewContext<Workspace>,
5896    ) {
5897        // If there are multiple definitions, open them in a multibuffer
5898        locations.sort_by_key(|location| location.buffer.read(cx).remote_id());
5899        let mut locations = locations.into_iter().peekable();
5900        let mut ranges_to_highlight = Vec::new();
5901
5902        let excerpt_buffer = cx.add_model(|cx| {
5903            let mut multibuffer = MultiBuffer::new(replica_id);
5904            while let Some(location) = locations.next() {
5905                let buffer = location.buffer.read(cx);
5906                let mut ranges_for_buffer = Vec::new();
5907                let range = location.range.to_offset(buffer);
5908                ranges_for_buffer.push(range.clone());
5909
5910                while let Some(next_location) = locations.peek() {
5911                    if next_location.buffer == location.buffer {
5912                        ranges_for_buffer.push(next_location.range.to_offset(buffer));
5913                        locations.next();
5914                    } else {
5915                        break;
5916                    }
5917                }
5918
5919                ranges_for_buffer.sort_by_key(|range| (range.start, Reverse(range.end)));
5920                ranges_to_highlight.extend(multibuffer.push_excerpts_with_context_lines(
5921                    location.buffer.clone(),
5922                    ranges_for_buffer,
5923                    1,
5924                    cx,
5925                ))
5926            }
5927
5928            multibuffer.with_title(title)
5929        });
5930
5931        let editor = cx.add_view(|cx| {
5932            Editor::for_multibuffer(excerpt_buffer, Some(workspace.project().clone()), cx)
5933        });
5934        editor.update(cx, |editor, cx| {
5935            editor.highlight_background::<Self>(
5936                ranges_to_highlight,
5937                |theme| theme.editor.highlighted_line_background,
5938                cx,
5939            );
5940        });
5941        workspace.add_item(Box::new(editor), cx);
5942    }
5943
5944    pub fn rename(&mut self, _: &Rename, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
5945        use language::ToOffset as _;
5946
5947        let project = self.project.clone()?;
5948        let selection = self.selections.newest_anchor().clone();
5949        let (cursor_buffer, cursor_buffer_position) = self
5950            .buffer
5951            .read(cx)
5952            .text_anchor_for_position(selection.head(), cx)?;
5953        let (tail_buffer, _) = self
5954            .buffer
5955            .read(cx)
5956            .text_anchor_for_position(selection.tail(), cx)?;
5957        if tail_buffer != cursor_buffer {
5958            return None;
5959        }
5960
5961        let snapshot = cursor_buffer.read(cx).snapshot();
5962        let cursor_buffer_offset = cursor_buffer_position.to_offset(&snapshot);
5963        let prepare_rename = project.update(cx, |project, cx| {
5964            project.prepare_rename(cursor_buffer, cursor_buffer_offset, cx)
5965        });
5966
5967        Some(cx.spawn(|this, mut cx| async move {
5968            let rename_range = if let Some(range) = prepare_rename.await? {
5969                Some(range)
5970            } else {
5971                this.read_with(&cx, |this, cx| {
5972                    let buffer = this.buffer.read(cx).snapshot(cx);
5973                    let mut buffer_highlights = this
5974                        .document_highlights_for_position(selection.head(), &buffer)
5975                        .filter(|highlight| {
5976                            highlight.start.excerpt_id() == selection.head().excerpt_id()
5977                                && highlight.end.excerpt_id() == selection.head().excerpt_id()
5978                        });
5979                    buffer_highlights
5980                        .next()
5981                        .map(|highlight| highlight.start.text_anchor..highlight.end.text_anchor)
5982                })?
5983            };
5984            if let Some(rename_range) = rename_range {
5985                let rename_buffer_range = rename_range.to_offset(&snapshot);
5986                let cursor_offset_in_rename_range =
5987                    cursor_buffer_offset.saturating_sub(rename_buffer_range.start);
5988
5989                this.update(&mut cx, |this, cx| {
5990                    this.take_rename(false, cx);
5991                    let style = this.style(cx);
5992                    let buffer = this.buffer.read(cx).read(cx);
5993                    let cursor_offset = selection.head().to_offset(&buffer);
5994                    let rename_start = cursor_offset.saturating_sub(cursor_offset_in_rename_range);
5995                    let rename_end = rename_start + rename_buffer_range.len();
5996                    let range = buffer.anchor_before(rename_start)..buffer.anchor_after(rename_end);
5997                    let mut old_highlight_id = None;
5998                    let old_name: Arc<str> = buffer
5999                        .chunks(rename_start..rename_end, true)
6000                        .map(|chunk| {
6001                            if old_highlight_id.is_none() {
6002                                old_highlight_id = chunk.syntax_highlight_id;
6003                            }
6004                            chunk.text
6005                        })
6006                        .collect::<String>()
6007                        .into();
6008
6009                    drop(buffer);
6010
6011                    // Position the selection in the rename editor so that it matches the current selection.
6012                    this.show_local_selections = false;
6013                    let rename_editor = cx.add_view(|cx| {
6014                        let mut editor = Editor::single_line(None, cx);
6015                        if let Some(old_highlight_id) = old_highlight_id {
6016                            editor.override_text_style =
6017                                Some(Box::new(move |style| old_highlight_id.style(&style.syntax)));
6018                        }
6019                        editor.buffer.update(cx, |buffer, cx| {
6020                            buffer.edit([(0..0, old_name.clone())], None, cx)
6021                        });
6022                        editor.select_all(&SelectAll, cx);
6023                        editor
6024                    });
6025
6026                    let ranges = this
6027                        .clear_background_highlights::<DocumentHighlightWrite>(cx)
6028                        .into_iter()
6029                        .flat_map(|(_, ranges)| ranges)
6030                        .chain(
6031                            this.clear_background_highlights::<DocumentHighlightRead>(cx)
6032                                .into_iter()
6033                                .flat_map(|(_, ranges)| ranges),
6034                        )
6035                        .collect();
6036
6037                    this.highlight_text::<Rename>(
6038                        ranges,
6039                        HighlightStyle {
6040                            fade_out: Some(style.rename_fade),
6041                            ..Default::default()
6042                        },
6043                        cx,
6044                    );
6045                    cx.focus(&rename_editor);
6046                    let block_id = this.insert_blocks(
6047                        [BlockProperties {
6048                            style: BlockStyle::Flex,
6049                            position: range.start.clone(),
6050                            height: 1,
6051                            render: Arc::new({
6052                                let editor = rename_editor.clone();
6053                                move |cx: &mut BlockContext| {
6054                                    ChildView::new(&editor, cx)
6055                                        .contained()
6056                                        .with_padding_left(cx.anchor_x)
6057                                        .into_any()
6058                                }
6059                            }),
6060                            disposition: BlockDisposition::Below,
6061                        }],
6062                        cx,
6063                    )[0];
6064                    this.pending_rename = Some(RenameState {
6065                        range,
6066                        old_name,
6067                        editor: rename_editor,
6068                        block_id,
6069                    });
6070                })?;
6071            }
6072
6073            Ok(())
6074        }))
6075    }
6076
6077    pub fn confirm_rename(
6078        workspace: &mut Workspace,
6079        _: &ConfirmRename,
6080        cx: &mut ViewContext<Workspace>,
6081    ) -> Option<Task<Result<()>>> {
6082        let editor = workspace.active_item(cx)?.act_as::<Editor>(cx)?;
6083
6084        let (buffer, range, old_name, new_name) = editor.update(cx, |editor, cx| {
6085            let rename = editor.take_rename(false, cx)?;
6086            let buffer = editor.buffer.read(cx);
6087            let (start_buffer, start) =
6088                buffer.text_anchor_for_position(rename.range.start.clone(), cx)?;
6089            let (end_buffer, end) =
6090                buffer.text_anchor_for_position(rename.range.end.clone(), cx)?;
6091            if start_buffer == end_buffer {
6092                let new_name = rename.editor.read(cx).text(cx);
6093                Some((start_buffer, start..end, rename.old_name, new_name))
6094            } else {
6095                None
6096            }
6097        })?;
6098
6099        let rename = workspace.project().clone().update(cx, |project, cx| {
6100            project.perform_rename(buffer.clone(), range.start, new_name.clone(), true, cx)
6101        });
6102
6103        let editor = editor.downgrade();
6104        Some(cx.spawn(|workspace, mut cx| async move {
6105            let project_transaction = rename.await?;
6106            Self::open_project_transaction(
6107                &editor,
6108                workspace,
6109                project_transaction,
6110                format!("Rename: {}{}", old_name, new_name),
6111                cx.clone(),
6112            )
6113            .await?;
6114
6115            editor.update(&mut cx, |editor, cx| {
6116                editor.refresh_document_highlights(cx);
6117            })?;
6118            Ok(())
6119        }))
6120    }
6121
6122    fn take_rename(
6123        &mut self,
6124        moving_cursor: bool,
6125        cx: &mut ViewContext<Self>,
6126    ) -> Option<RenameState> {
6127        let rename = self.pending_rename.take()?;
6128        self.remove_blocks([rename.block_id].into_iter().collect(), cx);
6129        self.clear_text_highlights::<Rename>(cx);
6130        self.show_local_selections = true;
6131
6132        if moving_cursor {
6133            let rename_editor = rename.editor.read(cx);
6134            let cursor_in_rename_editor = rename_editor.selections.newest::<usize>(cx).head();
6135
6136            // Update the selection to match the position of the selection inside
6137            // the rename editor.
6138            let snapshot = self.buffer.read(cx).read(cx);
6139            let rename_range = rename.range.to_offset(&snapshot);
6140            let cursor_in_editor = snapshot
6141                .clip_offset(rename_range.start + cursor_in_rename_editor, Bias::Left)
6142                .min(rename_range.end);
6143            drop(snapshot);
6144
6145            self.change_selections(None, cx, |s| {
6146                s.select_ranges(vec![cursor_in_editor..cursor_in_editor])
6147            });
6148        } else {
6149            self.refresh_document_highlights(cx);
6150        }
6151
6152        Some(rename)
6153    }
6154
6155    #[cfg(any(test, feature = "test-support"))]
6156    pub fn pending_rename(&self) -> Option<&RenameState> {
6157        self.pending_rename.as_ref()
6158    }
6159
6160    fn format(&mut self, _: &Format, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
6161        let project = match &self.project {
6162            Some(project) => project.clone(),
6163            None => return None,
6164        };
6165
6166        Some(self.perform_format(project, FormatTrigger::Manual, cx))
6167    }
6168
6169    fn perform_format(
6170        &mut self,
6171        project: ModelHandle<Project>,
6172        trigger: FormatTrigger,
6173        cx: &mut ViewContext<Self>,
6174    ) -> Task<Result<()>> {
6175        let buffer = self.buffer().clone();
6176        let buffers = buffer.read(cx).all_buffers();
6177
6178        let mut timeout = cx.background().timer(FORMAT_TIMEOUT).fuse();
6179        let format = project.update(cx, |project, cx| project.format(buffers, true, trigger, cx));
6180
6181        cx.spawn(|_, mut cx| async move {
6182            let transaction = futures::select_biased! {
6183                _ = timeout => {
6184                    log::warn!("timed out waiting for formatting");
6185                    None
6186                }
6187                transaction = format.log_err().fuse() => transaction,
6188            };
6189
6190            buffer.update(&mut cx, |buffer, cx| {
6191                if let Some(transaction) = transaction {
6192                    if !buffer.is_singleton() {
6193                        buffer.push_transaction(&transaction.0, cx);
6194                    }
6195                }
6196
6197                cx.notify();
6198            });
6199
6200            Ok(())
6201        })
6202    }
6203
6204    fn restart_language_server(&mut self, _: &RestartLanguageServer, cx: &mut ViewContext<Self>) {
6205        if let Some(project) = self.project.clone() {
6206            self.buffer.update(cx, |multi_buffer, cx| {
6207                project.update(cx, |project, cx| {
6208                    project.restart_language_servers_for_buffers(multi_buffer.all_buffers(), cx);
6209                });
6210            })
6211        }
6212    }
6213
6214    fn show_character_palette(&mut self, _: &ShowCharacterPalette, cx: &mut ViewContext<Self>) {
6215        cx.show_character_palette();
6216    }
6217
6218    fn refresh_active_diagnostics(&mut self, cx: &mut ViewContext<Editor>) {
6219        if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
6220            let buffer = self.buffer.read(cx).snapshot(cx);
6221            let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
6222            let is_valid = buffer
6223                .diagnostics_in_range::<_, usize>(active_diagnostics.primary_range.clone(), false)
6224                .any(|entry| {
6225                    entry.diagnostic.is_primary
6226                        && !entry.range.is_empty()
6227                        && entry.range.start == primary_range_start
6228                        && entry.diagnostic.message == active_diagnostics.primary_message
6229                });
6230
6231            if is_valid != active_diagnostics.is_valid {
6232                active_diagnostics.is_valid = is_valid;
6233                let mut new_styles = HashMap::default();
6234                for (block_id, diagnostic) in &active_diagnostics.blocks {
6235                    new_styles.insert(
6236                        *block_id,
6237                        diagnostic_block_renderer(diagnostic.clone(), is_valid),
6238                    );
6239                }
6240                self.display_map
6241                    .update(cx, |display_map, _| display_map.replace_blocks(new_styles));
6242            }
6243        }
6244    }
6245
6246    fn activate_diagnostics(&mut self, group_id: usize, cx: &mut ViewContext<Self>) -> bool {
6247        self.dismiss_diagnostics(cx);
6248        self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
6249            let buffer = self.buffer.read(cx).snapshot(cx);
6250
6251            let mut primary_range = None;
6252            let mut primary_message = None;
6253            let mut group_end = Point::zero();
6254            let diagnostic_group = buffer
6255                .diagnostic_group::<Point>(group_id)
6256                .map(|entry| {
6257                    if entry.range.end > group_end {
6258                        group_end = entry.range.end;
6259                    }
6260                    if entry.diagnostic.is_primary {
6261                        primary_range = Some(entry.range.clone());
6262                        primary_message = Some(entry.diagnostic.message.clone());
6263                    }
6264                    entry
6265                })
6266                .collect::<Vec<_>>();
6267            let primary_range = primary_range?;
6268            let primary_message = primary_message?;
6269            let primary_range =
6270                buffer.anchor_after(primary_range.start)..buffer.anchor_before(primary_range.end);
6271
6272            let blocks = display_map
6273                .insert_blocks(
6274                    diagnostic_group.iter().map(|entry| {
6275                        let diagnostic = entry.diagnostic.clone();
6276                        let message_height = diagnostic.message.lines().count() as u8;
6277                        BlockProperties {
6278                            style: BlockStyle::Fixed,
6279                            position: buffer.anchor_after(entry.range.start),
6280                            height: message_height,
6281                            render: diagnostic_block_renderer(diagnostic, true),
6282                            disposition: BlockDisposition::Below,
6283                        }
6284                    }),
6285                    cx,
6286                )
6287                .into_iter()
6288                .zip(diagnostic_group.into_iter().map(|entry| entry.diagnostic))
6289                .collect();
6290
6291            Some(ActiveDiagnosticGroup {
6292                primary_range,
6293                primary_message,
6294                blocks,
6295                is_valid: true,
6296            })
6297        });
6298        self.active_diagnostics.is_some()
6299    }
6300
6301    fn dismiss_diagnostics(&mut self, cx: &mut ViewContext<Self>) {
6302        if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
6303            self.display_map.update(cx, |display_map, cx| {
6304                display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx);
6305            });
6306            cx.notify();
6307        }
6308    }
6309
6310    pub fn set_selections_from_remote(
6311        &mut self,
6312        selections: Vec<Selection<Anchor>>,
6313        pending_selection: Option<Selection<Anchor>>,
6314        cx: &mut ViewContext<Self>,
6315    ) {
6316        let old_cursor_position = self.selections.newest_anchor().head();
6317        self.selections.change_with(cx, |s| {
6318            s.select_anchors(selections);
6319            if let Some(pending_selection) = pending_selection {
6320                s.set_pending(pending_selection, SelectMode::Character);
6321            } else {
6322                s.clear_pending();
6323            }
6324        });
6325        self.selections_did_change(false, &old_cursor_position, cx);
6326    }
6327
6328    fn push_to_selection_history(&mut self) {
6329        self.selection_history.push(SelectionHistoryEntry {
6330            selections: self.selections.disjoint_anchors(),
6331            select_next_state: self.select_next_state.clone(),
6332            add_selections_state: self.add_selections_state.clone(),
6333        });
6334    }
6335
6336    pub fn transact(
6337        &mut self,
6338        cx: &mut ViewContext<Self>,
6339        update: impl FnOnce(&mut Self, &mut ViewContext<Self>),
6340    ) -> Option<TransactionId> {
6341        self.start_transaction_at(Instant::now(), cx);
6342        update(self, cx);
6343        self.end_transaction_at(Instant::now(), cx)
6344    }
6345
6346    fn start_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
6347        self.end_selection(cx);
6348        if let Some(tx_id) = self
6349            .buffer
6350            .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx))
6351        {
6352            self.selection_history
6353                .insert_transaction(tx_id, self.selections.disjoint_anchors());
6354        }
6355    }
6356
6357    fn end_transaction_at(
6358        &mut self,
6359        now: Instant,
6360        cx: &mut ViewContext<Self>,
6361    ) -> Option<TransactionId> {
6362        if let Some(tx_id) = self
6363            .buffer
6364            .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
6365        {
6366            if let Some((_, end_selections)) = self.selection_history.transaction_mut(tx_id) {
6367                *end_selections = Some(self.selections.disjoint_anchors());
6368            } else {
6369                log::error!("unexpectedly ended a transaction that wasn't started by this editor");
6370            }
6371
6372            cx.emit(Event::Edited);
6373            Some(tx_id)
6374        } else {
6375            None
6376        }
6377    }
6378
6379    pub fn fold(&mut self, _: &Fold, cx: &mut ViewContext<Self>) {
6380        let mut fold_ranges = Vec::new();
6381
6382        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6383
6384        let selections = self.selections.all::<Point>(cx);
6385        for selection in selections {
6386            let range = selection.range().sorted();
6387            let buffer_start_row = range.start.row;
6388
6389            for row in (0..=range.end.row).rev() {
6390                let fold_range = display_map.foldable_range(row);
6391
6392                if let Some(fold_range) = fold_range {
6393                    if fold_range.end.row >= buffer_start_row {
6394                        fold_ranges.push(fold_range);
6395                        if row <= range.start.row {
6396                            break;
6397                        }
6398                    }
6399                }
6400            }
6401        }
6402
6403        self.fold_ranges(fold_ranges, true, cx);
6404    }
6405
6406    pub fn fold_at(&mut self, fold_at: &FoldAt, cx: &mut ViewContext<Self>) {
6407        let buffer_row = fold_at.buffer_row;
6408        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6409
6410        if let Some(fold_range) = display_map.foldable_range(buffer_row) {
6411            let autoscroll = self
6412                .selections
6413                .all::<Point>(cx)
6414                .iter()
6415                .any(|selection| fold_range.overlaps(&selection.range()));
6416
6417            self.fold_ranges(std::iter::once(fold_range), autoscroll, cx);
6418        }
6419    }
6420
6421    pub fn unfold_lines(&mut self, _: &UnfoldLines, cx: &mut ViewContext<Self>) {
6422        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6423        let buffer = &display_map.buffer_snapshot;
6424        let selections = self.selections.all::<Point>(cx);
6425        let ranges = selections
6426            .iter()
6427            .map(|s| {
6428                let range = s.display_range(&display_map).sorted();
6429                let mut start = range.start.to_point(&display_map);
6430                let mut end = range.end.to_point(&display_map);
6431                start.column = 0;
6432                end.column = buffer.line_len(end.row);
6433                start..end
6434            })
6435            .collect::<Vec<_>>();
6436
6437        self.unfold_ranges(ranges, true, true, cx);
6438    }
6439
6440    pub fn unfold_at(&mut self, unfold_at: &UnfoldAt, cx: &mut ViewContext<Self>) {
6441        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6442
6443        let intersection_range = Point::new(unfold_at.buffer_row, 0)
6444            ..Point::new(
6445                unfold_at.buffer_row,
6446                display_map.buffer_snapshot.line_len(unfold_at.buffer_row),
6447            );
6448
6449        let autoscroll = self
6450            .selections
6451            .all::<Point>(cx)
6452            .iter()
6453            .any(|selection| selection.range().overlaps(&intersection_range));
6454
6455        self.unfold_ranges(std::iter::once(intersection_range), true, autoscroll, cx)
6456    }
6457
6458    pub fn fold_selected_ranges(&mut self, _: &FoldSelectedRanges, cx: &mut ViewContext<Self>) {
6459        let selections = self.selections.all::<Point>(cx);
6460        let ranges = selections.into_iter().map(|s| s.start..s.end);
6461        self.fold_ranges(ranges, true, cx);
6462    }
6463
6464    pub fn fold_ranges<T: ToOffset + Clone>(
6465        &mut self,
6466        ranges: impl IntoIterator<Item = Range<T>>,
6467        auto_scroll: bool,
6468        cx: &mut ViewContext<Self>,
6469    ) {
6470        let mut ranges = ranges.into_iter().peekable();
6471        if ranges.peek().is_some() {
6472            self.display_map.update(cx, |map, cx| map.fold(ranges, cx));
6473
6474            if auto_scroll {
6475                self.request_autoscroll(Autoscroll::fit(), cx);
6476            }
6477
6478            cx.notify();
6479        }
6480    }
6481
6482    pub fn unfold_ranges<T: ToOffset + Clone>(
6483        &mut self,
6484        ranges: impl IntoIterator<Item = Range<T>>,
6485        inclusive: bool,
6486        auto_scroll: bool,
6487        cx: &mut ViewContext<Self>,
6488    ) {
6489        let mut ranges = ranges.into_iter().peekable();
6490        if ranges.peek().is_some() {
6491            self.display_map
6492                .update(cx, |map, cx| map.unfold(ranges, inclusive, cx));
6493            if auto_scroll {
6494                self.request_autoscroll(Autoscroll::fit(), cx);
6495            }
6496
6497            cx.notify();
6498        }
6499    }
6500
6501    pub fn gutter_hover(
6502        &mut self,
6503        GutterHover { hovered }: &GutterHover,
6504        cx: &mut ViewContext<Self>,
6505    ) {
6506        self.gutter_hovered = *hovered;
6507        cx.notify();
6508    }
6509
6510    pub fn insert_blocks(
6511        &mut self,
6512        blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
6513        cx: &mut ViewContext<Self>,
6514    ) -> Vec<BlockId> {
6515        let blocks = self
6516            .display_map
6517            .update(cx, |display_map, cx| display_map.insert_blocks(blocks, cx));
6518        self.request_autoscroll(Autoscroll::fit(), cx);
6519        blocks
6520    }
6521
6522    pub fn replace_blocks(
6523        &mut self,
6524        blocks: HashMap<BlockId, RenderBlock>,
6525        cx: &mut ViewContext<Self>,
6526    ) {
6527        self.display_map
6528            .update(cx, |display_map, _| display_map.replace_blocks(blocks));
6529        self.request_autoscroll(Autoscroll::fit(), cx);
6530    }
6531
6532    pub fn remove_blocks(&mut self, block_ids: HashSet<BlockId>, cx: &mut ViewContext<Self>) {
6533        self.display_map.update(cx, |display_map, cx| {
6534            display_map.remove_blocks(block_ids, cx)
6535        });
6536    }
6537
6538    pub fn longest_row(&self, cx: &mut AppContext) -> u32 {
6539        self.display_map
6540            .update(cx, |map, cx| map.snapshot(cx))
6541            .longest_row()
6542    }
6543
6544    pub fn max_point(&self, cx: &mut AppContext) -> DisplayPoint {
6545        self.display_map
6546            .update(cx, |map, cx| map.snapshot(cx))
6547            .max_point()
6548    }
6549
6550    pub fn text(&self, cx: &AppContext) -> String {
6551        self.buffer.read(cx).read(cx).text()
6552    }
6553
6554    pub fn set_text(&mut self, text: impl Into<Arc<str>>, cx: &mut ViewContext<Self>) {
6555        self.transact(cx, |this, cx| {
6556            this.buffer
6557                .read(cx)
6558                .as_singleton()
6559                .expect("you can only call set_text on editors for singleton buffers")
6560                .update(cx, |buffer, cx| buffer.set_text(text, cx));
6561        });
6562    }
6563
6564    pub fn display_text(&self, cx: &mut AppContext) -> String {
6565        self.display_map
6566            .update(cx, |map, cx| map.snapshot(cx))
6567            .text()
6568    }
6569
6570    pub fn soft_wrap_mode(&self, cx: &AppContext) -> SoftWrap {
6571        let settings = self.buffer.read(cx).settings_at(0, cx);
6572        let mode = self
6573            .soft_wrap_mode_override
6574            .unwrap_or_else(|| settings.soft_wrap);
6575        match mode {
6576            language_settings::SoftWrap::None => SoftWrap::None,
6577            language_settings::SoftWrap::EditorWidth => SoftWrap::EditorWidth,
6578            language_settings::SoftWrap::PreferredLineLength => {
6579                SoftWrap::Column(settings.preferred_line_length)
6580            }
6581        }
6582    }
6583
6584    pub fn set_soft_wrap_mode(
6585        &mut self,
6586        mode: language_settings::SoftWrap,
6587        cx: &mut ViewContext<Self>,
6588    ) {
6589        self.soft_wrap_mode_override = Some(mode);
6590        cx.notify();
6591    }
6592
6593    pub fn set_wrap_width(&self, width: Option<f32>, cx: &mut AppContext) -> bool {
6594        self.display_map
6595            .update(cx, |map, cx| map.set_wrap_width(width, cx))
6596    }
6597
6598    pub fn toggle_soft_wrap(&mut self, _: &ToggleSoftWrap, cx: &mut ViewContext<Self>) {
6599        if self.soft_wrap_mode_override.is_some() {
6600            self.soft_wrap_mode_override.take();
6601        } else {
6602            let soft_wrap = match self.soft_wrap_mode(cx) {
6603                SoftWrap::None => language_settings::SoftWrap::EditorWidth,
6604                SoftWrap::EditorWidth | SoftWrap::Column(_) => language_settings::SoftWrap::None,
6605            };
6606            self.soft_wrap_mode_override = Some(soft_wrap);
6607        }
6608        cx.notify();
6609    }
6610
6611    pub fn reveal_in_finder(&mut self, _: &RevealInFinder, cx: &mut ViewContext<Self>) {
6612        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
6613            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
6614                cx.reveal_path(&file.abs_path(cx));
6615            }
6616        }
6617    }
6618
6619    pub fn copy_path(&mut self, _: &CopyPath, cx: &mut ViewContext<Self>) {
6620        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
6621            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
6622                if let Some(path) = file.abs_path(cx).to_str() {
6623                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
6624                }
6625            }
6626        }
6627    }
6628
6629    pub fn copy_relative_path(&mut self, _: &CopyRelativePath, cx: &mut ViewContext<Self>) {
6630        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
6631            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
6632                if let Some(path) = file.path().to_str() {
6633                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
6634                }
6635            }
6636        }
6637    }
6638
6639    pub fn highlight_rows(&mut self, rows: Option<Range<u32>>) {
6640        self.highlighted_rows = rows;
6641    }
6642
6643    pub fn highlighted_rows(&self) -> Option<Range<u32>> {
6644        self.highlighted_rows.clone()
6645    }
6646
6647    pub fn highlight_background<T: 'static>(
6648        &mut self,
6649        ranges: Vec<Range<Anchor>>,
6650        color_fetcher: fn(&Theme) -> Color,
6651        cx: &mut ViewContext<Self>,
6652    ) {
6653        self.background_highlights
6654            .insert(TypeId::of::<T>(), (color_fetcher, ranges));
6655        cx.notify();
6656    }
6657
6658    #[allow(clippy::type_complexity)]
6659    pub fn clear_background_highlights<T: 'static>(
6660        &mut self,
6661        cx: &mut ViewContext<Self>,
6662    ) -> Option<(fn(&Theme) -> Color, Vec<Range<Anchor>>)> {
6663        let highlights = self.background_highlights.remove(&TypeId::of::<T>());
6664        if highlights.is_some() {
6665            cx.notify();
6666        }
6667        highlights
6668    }
6669
6670    #[cfg(feature = "test-support")]
6671    pub fn all_background_highlights(
6672        &mut self,
6673        cx: &mut ViewContext<Self>,
6674    ) -> Vec<(Range<DisplayPoint>, Color)> {
6675        let snapshot = self.snapshot(cx);
6676        let buffer = &snapshot.buffer_snapshot;
6677        let start = buffer.anchor_before(0);
6678        let end = buffer.anchor_after(buffer.len());
6679        let theme = theme::current(cx);
6680        self.background_highlights_in_range(start..end, &snapshot, theme.as_ref())
6681    }
6682
6683    fn document_highlights_for_position<'a>(
6684        &'a self,
6685        position: Anchor,
6686        buffer: &'a MultiBufferSnapshot,
6687    ) -> impl 'a + Iterator<Item = &Range<Anchor>> {
6688        let read_highlights = self
6689            .background_highlights
6690            .get(&TypeId::of::<DocumentHighlightRead>())
6691            .map(|h| &h.1);
6692        let write_highlights = self
6693            .background_highlights
6694            .get(&TypeId::of::<DocumentHighlightWrite>())
6695            .map(|h| &h.1);
6696        let left_position = position.bias_left(buffer);
6697        let right_position = position.bias_right(buffer);
6698        read_highlights
6699            .into_iter()
6700            .chain(write_highlights)
6701            .flat_map(move |ranges| {
6702                let start_ix = match ranges.binary_search_by(|probe| {
6703                    let cmp = probe.end.cmp(&left_position, buffer);
6704                    if cmp.is_ge() {
6705                        Ordering::Greater
6706                    } else {
6707                        Ordering::Less
6708                    }
6709                }) {
6710                    Ok(i) | Err(i) => i,
6711                };
6712
6713                let right_position = right_position.clone();
6714                ranges[start_ix..]
6715                    .iter()
6716                    .take_while(move |range| range.start.cmp(&right_position, buffer).is_le())
6717            })
6718    }
6719
6720    pub fn background_highlights_in_range(
6721        &self,
6722        search_range: Range<Anchor>,
6723        display_snapshot: &DisplaySnapshot,
6724        theme: &Theme,
6725    ) -> Vec<(Range<DisplayPoint>, Color)> {
6726        let mut results = Vec::new();
6727        let buffer = &display_snapshot.buffer_snapshot;
6728        for (color_fetcher, ranges) in self.background_highlights.values() {
6729            let color = color_fetcher(theme);
6730            let start_ix = match ranges.binary_search_by(|probe| {
6731                let cmp = probe.end.cmp(&search_range.start, buffer);
6732                if cmp.is_gt() {
6733                    Ordering::Greater
6734                } else {
6735                    Ordering::Less
6736                }
6737            }) {
6738                Ok(i) | Err(i) => i,
6739            };
6740            for range in &ranges[start_ix..] {
6741                if range.start.cmp(&search_range.end, buffer).is_ge() {
6742                    break;
6743                }
6744                let start = range
6745                    .start
6746                    .to_point(buffer)
6747                    .to_display_point(display_snapshot);
6748                let end = range
6749                    .end
6750                    .to_point(buffer)
6751                    .to_display_point(display_snapshot);
6752                results.push((start..end, color))
6753            }
6754        }
6755        results
6756    }
6757
6758    pub fn highlight_text<T: 'static>(
6759        &mut self,
6760        ranges: Vec<Range<Anchor>>,
6761        style: HighlightStyle,
6762        cx: &mut ViewContext<Self>,
6763    ) {
6764        self.display_map.update(cx, |map, _| {
6765            map.highlight_text(TypeId::of::<T>(), ranges, style)
6766        });
6767        cx.notify();
6768    }
6769
6770    pub fn text_highlights<'a, T: 'static>(
6771        &'a self,
6772        cx: &'a AppContext,
6773    ) -> Option<(HighlightStyle, &'a [Range<Anchor>])> {
6774        self.display_map.read(cx).text_highlights(TypeId::of::<T>())
6775    }
6776
6777    pub fn clear_text_highlights<T: 'static>(
6778        &mut self,
6779        cx: &mut ViewContext<Self>,
6780    ) -> Option<Arc<(HighlightStyle, Vec<Range<Anchor>>)>> {
6781        let highlights = self
6782            .display_map
6783            .update(cx, |map, _| map.clear_text_highlights(TypeId::of::<T>()));
6784        if highlights.is_some() {
6785            cx.notify();
6786        }
6787        highlights
6788    }
6789
6790    pub fn show_local_cursors(&self, cx: &AppContext) -> bool {
6791        self.blink_manager.read(cx).visible() && self.focused
6792    }
6793
6794    fn on_buffer_changed(&mut self, _: ModelHandle<MultiBuffer>, cx: &mut ViewContext<Self>) {
6795        cx.notify();
6796    }
6797
6798    fn on_buffer_event(
6799        &mut self,
6800        _: ModelHandle<MultiBuffer>,
6801        event: &multi_buffer::Event,
6802        cx: &mut ViewContext<Self>,
6803    ) {
6804        match event {
6805            multi_buffer::Event::Edited => {
6806                self.refresh_active_diagnostics(cx);
6807                self.refresh_code_actions(cx);
6808                if self.has_active_copilot_suggestion(cx) {
6809                    self.update_visible_copilot_suggestion(cx);
6810                }
6811                cx.emit(Event::BufferEdited);
6812            }
6813            multi_buffer::Event::ExcerptsAdded {
6814                buffer,
6815                predecessor,
6816                excerpts,
6817            } => cx.emit(Event::ExcerptsAdded {
6818                buffer: buffer.clone(),
6819                predecessor: *predecessor,
6820                excerpts: excerpts.clone(),
6821            }),
6822            multi_buffer::Event::ExcerptsRemoved { ids } => {
6823                cx.emit(Event::ExcerptsRemoved { ids: ids.clone() })
6824            }
6825            multi_buffer::Event::Reparsed => cx.emit(Event::Reparsed),
6826            multi_buffer::Event::DirtyChanged => cx.emit(Event::DirtyChanged),
6827            multi_buffer::Event::Saved => cx.emit(Event::Saved),
6828            multi_buffer::Event::FileHandleChanged => cx.emit(Event::TitleChanged),
6829            multi_buffer::Event::Reloaded => cx.emit(Event::TitleChanged),
6830            multi_buffer::Event::Closed => cx.emit(Event::Closed),
6831            multi_buffer::Event::DiagnosticsUpdated => {
6832                self.refresh_active_diagnostics(cx);
6833            }
6834            multi_buffer::Event::LanguageChanged => {}
6835        }
6836    }
6837
6838    fn on_display_map_changed(&mut self, _: ModelHandle<DisplayMap>, cx: &mut ViewContext<Self>) {
6839        cx.notify();
6840    }
6841
6842    fn settings_changed(&mut self, cx: &mut ViewContext<Self>) {
6843        self.refresh_copilot_suggestions(true, cx);
6844    }
6845
6846    pub fn set_searchable(&mut self, searchable: bool) {
6847        self.searchable = searchable;
6848    }
6849
6850    pub fn searchable(&self) -> bool {
6851        self.searchable
6852    }
6853
6854    fn open_excerpts(workspace: &mut Workspace, _: &OpenExcerpts, cx: &mut ViewContext<Workspace>) {
6855        let active_item = workspace.active_item(cx);
6856        let editor_handle = if let Some(editor) = active_item
6857            .as_ref()
6858            .and_then(|item| item.act_as::<Self>(cx))
6859        {
6860            editor
6861        } else {
6862            cx.propagate_action();
6863            return;
6864        };
6865
6866        let editor = editor_handle.read(cx);
6867        let buffer = editor.buffer.read(cx);
6868        if buffer.is_singleton() {
6869            cx.propagate_action();
6870            return;
6871        }
6872
6873        let mut new_selections_by_buffer = HashMap::default();
6874        for selection in editor.selections.all::<usize>(cx) {
6875            for (buffer, mut range) in
6876                buffer.range_to_buffer_ranges(selection.start..selection.end, cx)
6877            {
6878                if selection.reversed {
6879                    mem::swap(&mut range.start, &mut range.end);
6880                }
6881                new_selections_by_buffer
6882                    .entry(buffer)
6883                    .or_insert(Vec::new())
6884                    .push(range)
6885            }
6886        }
6887
6888        editor_handle.update(cx, |editor, cx| {
6889            editor.push_to_nav_history(editor.selections.newest_anchor().head(), None, cx);
6890        });
6891        let pane = workspace.active_pane().clone();
6892        pane.update(cx, |pane, _| pane.disable_history());
6893
6894        // We defer the pane interaction because we ourselves are a workspace item
6895        // and activating a new item causes the pane to call a method on us reentrantly,
6896        // which panics if we're on the stack.
6897        cx.defer(move |workspace, cx| {
6898            for (buffer, ranges) in new_selections_by_buffer.into_iter() {
6899                let editor = workspace.open_project_item::<Self>(buffer, cx);
6900                editor.update(cx, |editor, cx| {
6901                    editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
6902                        s.select_ranges(ranges);
6903                    });
6904                });
6905            }
6906
6907            pane.update(cx, |pane, _| pane.enable_history());
6908        });
6909    }
6910
6911    fn jump(
6912        workspace: &mut Workspace,
6913        path: ProjectPath,
6914        position: Point,
6915        anchor: language::Anchor,
6916        cx: &mut ViewContext<Workspace>,
6917    ) {
6918        let editor = workspace.open_path(path, None, true, cx);
6919        cx.spawn(|_, mut cx| async move {
6920            let editor = editor
6921                .await?
6922                .downcast::<Editor>()
6923                .ok_or_else(|| anyhow!("opened item was not an editor"))?
6924                .downgrade();
6925            editor.update(&mut cx, |editor, cx| {
6926                let buffer = editor
6927                    .buffer()
6928                    .read(cx)
6929                    .as_singleton()
6930                    .ok_or_else(|| anyhow!("cannot jump in a multi-buffer"))?;
6931                let buffer = buffer.read(cx);
6932                let cursor = if buffer.can_resolve(&anchor) {
6933                    language::ToPoint::to_point(&anchor, buffer)
6934                } else {
6935                    buffer.clip_point(position, Bias::Left)
6936                };
6937
6938                let nav_history = editor.nav_history.take();
6939                editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
6940                    s.select_ranges([cursor..cursor]);
6941                });
6942                editor.nav_history = nav_history;
6943
6944                anyhow::Ok(())
6945            })??;
6946
6947            anyhow::Ok(())
6948        })
6949        .detach_and_log_err(cx);
6950    }
6951
6952    fn marked_text_ranges(&self, cx: &AppContext) -> Option<Vec<Range<OffsetUtf16>>> {
6953        let snapshot = self.buffer.read(cx).read(cx);
6954        let (_, ranges) = self.text_highlights::<InputComposition>(cx)?;
6955        Some(
6956            ranges
6957                .iter()
6958                .map(move |range| {
6959                    range.start.to_offset_utf16(&snapshot)..range.end.to_offset_utf16(&snapshot)
6960                })
6961                .collect(),
6962        )
6963    }
6964
6965    fn selection_replacement_ranges(
6966        &self,
6967        range: Range<OffsetUtf16>,
6968        cx: &AppContext,
6969    ) -> Vec<Range<OffsetUtf16>> {
6970        let selections = self.selections.all::<OffsetUtf16>(cx);
6971        let newest_selection = selections
6972            .iter()
6973            .max_by_key(|selection| selection.id)
6974            .unwrap();
6975        let start_delta = range.start.0 as isize - newest_selection.start.0 as isize;
6976        let end_delta = range.end.0 as isize - newest_selection.end.0 as isize;
6977        let snapshot = self.buffer.read(cx).read(cx);
6978        selections
6979            .into_iter()
6980            .map(|mut selection| {
6981                selection.start.0 =
6982                    (selection.start.0 as isize).saturating_add(start_delta) as usize;
6983                selection.end.0 = (selection.end.0 as isize).saturating_add(end_delta) as usize;
6984                snapshot.clip_offset_utf16(selection.start, Bias::Left)
6985                    ..snapshot.clip_offset_utf16(selection.end, Bias::Right)
6986            })
6987            .collect()
6988    }
6989
6990    fn report_copilot_event(
6991        &self,
6992        suggestion_id: Option<String>,
6993        suggestion_accepted: bool,
6994        cx: &AppContext,
6995    ) {
6996        let Some(project) = &self.project else {
6997            return
6998        };
6999
7000        // If None, we are either getting suggestions in a new, unsaved file, or in a file without an extension
7001        let file_extension = self
7002            .buffer
7003            .read(cx)
7004            .as_singleton()
7005            .and_then(|b| b.read(cx).file())
7006            .and_then(|file| Path::new(file.file_name(cx)).extension())
7007            .and_then(|e| e.to_str())
7008            .map(|a| a.to_string());
7009
7010        let telemetry = project.read(cx).client().telemetry().clone();
7011        let telemetry_settings = *settings::get::<TelemetrySettings>(cx);
7012
7013        let event = ClickhouseEvent::Copilot {
7014            suggestion_id,
7015            suggestion_accepted,
7016            file_extension,
7017        };
7018        telemetry.report_clickhouse_event(event, telemetry_settings);
7019    }
7020
7021    fn report_editor_event(
7022        &self,
7023        name: &'static str,
7024        file_extension: Option<String>,
7025        cx: &AppContext,
7026    ) {
7027        let Some(project) = &self.project else {
7028            return
7029        };
7030
7031        // If None, we are in a file without an extension
7032        let file_extension = file_extension.or(self
7033            .buffer
7034            .read(cx)
7035            .as_singleton()
7036            .and_then(|b| b.read(cx).file())
7037            .and_then(|file| Path::new(file.file_name(cx)).extension())
7038            .and_then(|e| e.to_str())
7039            .map(|a| a.to_string()));
7040
7041        let vim_mode = cx
7042            .global::<SettingsStore>()
7043            .untyped_user_settings()
7044            .get("vim_mode")
7045            == Some(&serde_json::Value::Bool(true));
7046        let telemetry_settings = *settings::get::<TelemetrySettings>(cx);
7047        let copilot_enabled = all_language_settings(cx).copilot_enabled(None, None);
7048        let copilot_enabled_for_language = self
7049            .buffer
7050            .read(cx)
7051            .settings_at(0, cx)
7052            .show_copilot_suggestions;
7053
7054        let telemetry = project.read(cx).client().telemetry().clone();
7055        telemetry.report_mixpanel_event(
7056            match name {
7057                "open" => "open editor",
7058                "save" => "save editor",
7059                _ => name,
7060            },
7061            json!({ "File Extension": file_extension, "Vim Mode": vim_mode, "In Clickhouse": true  }),
7062            telemetry_settings,
7063        );
7064        let event = ClickhouseEvent::Editor {
7065            file_extension,
7066            vim_mode,
7067            operation: name,
7068            copilot_enabled,
7069            copilot_enabled_for_language,
7070        };
7071        telemetry.report_clickhouse_event(event, telemetry_settings)
7072    }
7073
7074    /// Copy the highlighted chunks to the clipboard as JSON. The format is an array of lines,
7075    /// with each line being an array of {text, highlight} objects.
7076    fn copy_highlight_json(&mut self, _: &CopyHighlightJson, cx: &mut ViewContext<Self>) {
7077        let Some(buffer) = self.buffer.read(cx).as_singleton() else {
7078            return;
7079        };
7080
7081        #[derive(Serialize)]
7082        struct Chunk<'a> {
7083            text: String,
7084            highlight: Option<&'a str>,
7085        }
7086
7087        let snapshot = buffer.read(cx).snapshot();
7088        let range = self
7089            .selected_text_range(cx)
7090            .and_then(|selected_range| {
7091                if selected_range.is_empty() {
7092                    None
7093                } else {
7094                    Some(selected_range)
7095                }
7096            })
7097            .unwrap_or_else(|| 0..snapshot.len());
7098
7099        let chunks = snapshot.chunks(range, true);
7100        let mut lines = Vec::new();
7101        let mut line: VecDeque<Chunk> = VecDeque::new();
7102
7103        let theme = &theme::current(cx).editor.syntax;
7104
7105        for chunk in chunks {
7106            let highlight = chunk.syntax_highlight_id.and_then(|id| id.name(theme));
7107            let mut chunk_lines = chunk.text.split("\n").peekable();
7108            while let Some(text) = chunk_lines.next() {
7109                let mut merged_with_last_token = false;
7110                if let Some(last_token) = line.back_mut() {
7111                    if last_token.highlight == highlight {
7112                        last_token.text.push_str(text);
7113                        merged_with_last_token = true;
7114                    }
7115                }
7116
7117                if !merged_with_last_token {
7118                    line.push_back(Chunk {
7119                        text: text.into(),
7120                        highlight,
7121                    });
7122                }
7123
7124                if chunk_lines.peek().is_some() {
7125                    if line.len() > 1 && line.front().unwrap().text.is_empty() {
7126                        line.pop_front();
7127                    }
7128                    if line.len() > 1 && line.back().unwrap().text.is_empty() {
7129                        line.pop_back();
7130                    }
7131
7132                    lines.push(mem::take(&mut line));
7133                }
7134            }
7135        }
7136
7137        let Some(lines) = serde_json::to_string_pretty(&lines).log_err() else { return; };
7138        cx.write_to_clipboard(ClipboardItem::new(lines));
7139    }
7140}
7141
7142fn consume_contiguous_rows(
7143    contiguous_row_selections: &mut Vec<Selection<Point>>,
7144    selection: &Selection<Point>,
7145    display_map: &DisplaySnapshot,
7146    selections: &mut std::iter::Peekable<std::slice::Iter<Selection<Point>>>,
7147) -> (u32, u32) {
7148    contiguous_row_selections.push(selection.clone());
7149    let start_row = selection.start.row;
7150    let mut end_row = ending_row(selection, display_map);
7151
7152    while let Some(next_selection) = selections.peek() {
7153        if next_selection.start.row <= end_row {
7154            end_row = ending_row(next_selection, display_map);
7155            contiguous_row_selections.push(selections.next().unwrap().clone());
7156        } else {
7157            break;
7158        }
7159    }
7160    (start_row, end_row)
7161}
7162
7163fn ending_row(next_selection: &Selection<Point>, display_map: &DisplaySnapshot) -> u32 {
7164    if next_selection.end.column > 0 || next_selection.is_empty() {
7165        display_map.next_line_boundary(next_selection.end).0.row + 1
7166    } else {
7167        next_selection.end.row
7168    }
7169}
7170
7171impl EditorSnapshot {
7172    pub fn language_at<T: ToOffset>(&self, position: T) -> Option<&Arc<Language>> {
7173        self.display_snapshot.buffer_snapshot.language_at(position)
7174    }
7175
7176    pub fn is_focused(&self) -> bool {
7177        self.is_focused
7178    }
7179
7180    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
7181        self.placeholder_text.as_ref()
7182    }
7183
7184    pub fn scroll_position(&self) -> Vector2F {
7185        self.scroll_anchor.scroll_position(&self.display_snapshot)
7186    }
7187}
7188
7189impl Deref for EditorSnapshot {
7190    type Target = DisplaySnapshot;
7191
7192    fn deref(&self) -> &Self::Target {
7193        &self.display_snapshot
7194    }
7195}
7196
7197#[derive(Clone, Debug, PartialEq, Eq)]
7198pub enum Event {
7199    InputIgnored {
7200        text: Arc<str>,
7201    },
7202    ExcerptsAdded {
7203        buffer: ModelHandle<Buffer>,
7204        predecessor: ExcerptId,
7205        excerpts: Vec<(ExcerptId, ExcerptRange<language::Anchor>)>,
7206    },
7207    ExcerptsRemoved {
7208        ids: Vec<ExcerptId>,
7209    },
7210    BufferEdited,
7211    Edited,
7212    Reparsed,
7213    Blurred,
7214    DirtyChanged,
7215    Saved,
7216    TitleChanged,
7217    SelectionsChanged {
7218        local: bool,
7219    },
7220    ScrollPositionChanged {
7221        local: bool,
7222    },
7223    Closed,
7224}
7225
7226pub struct EditorFocused(pub ViewHandle<Editor>);
7227pub struct EditorBlurred(pub ViewHandle<Editor>);
7228pub struct EditorReleased(pub WeakViewHandle<Editor>);
7229
7230impl Entity for Editor {
7231    type Event = Event;
7232
7233    fn release(&mut self, cx: &mut AppContext) {
7234        cx.emit_global(EditorReleased(self.handle.clone()));
7235    }
7236}
7237
7238impl View for Editor {
7239    fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
7240        let style = self.style(cx);
7241        let font_changed = self.display_map.update(cx, |map, cx| {
7242            map.set_fold_ellipses_color(style.folds.ellipses.text_color);
7243            map.set_font(style.text.font_id, style.text.font_size, cx)
7244        });
7245
7246        if font_changed {
7247            cx.defer(move |editor, cx: &mut ViewContext<Editor>| {
7248                hide_hover(editor, cx);
7249                hide_link_definition(editor, cx);
7250            });
7251        }
7252
7253        Stack::new()
7254            .with_child(EditorElement::new(style.clone()))
7255            .with_child(ChildView::new(&self.mouse_context_menu, cx))
7256            .into_any()
7257    }
7258
7259    fn ui_name() -> &'static str {
7260        "Editor"
7261    }
7262
7263    fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
7264        if cx.is_self_focused() {
7265            let focused_event = EditorFocused(cx.handle());
7266            cx.emit_global(focused_event);
7267        }
7268        if let Some(rename) = self.pending_rename.as_ref() {
7269            cx.focus(&rename.editor);
7270        } else {
7271            if !self.focused {
7272                self.blink_manager.update(cx, BlinkManager::enable);
7273            }
7274            self.focused = true;
7275            self.buffer.update(cx, |buffer, cx| {
7276                buffer.finalize_last_transaction(cx);
7277                if self.leader_replica_id.is_none() {
7278                    buffer.set_active_selections(
7279                        &self.selections.disjoint_anchors(),
7280                        self.selections.line_mode,
7281                        self.cursor_shape,
7282                        cx,
7283                    );
7284                }
7285            });
7286        }
7287    }
7288
7289    fn focus_out(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
7290        let blurred_event = EditorBlurred(cx.handle());
7291        cx.emit_global(blurred_event);
7292        self.focused = false;
7293        self.blink_manager.update(cx, BlinkManager::disable);
7294        self.buffer
7295            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
7296        self.hide_context_menu(cx);
7297        hide_hover(self, cx);
7298        cx.emit(Event::Blurred);
7299        cx.notify();
7300    }
7301
7302    fn modifiers_changed(
7303        &mut self,
7304        event: &gpui::platform::ModifiersChangedEvent,
7305        cx: &mut ViewContext<Self>,
7306    ) -> bool {
7307        let pending_selection = self.has_pending_selection();
7308
7309        if let Some(point) = self.link_go_to_definition_state.last_mouse_location.clone() {
7310            if event.cmd && !pending_selection {
7311                let snapshot = self.snapshot(cx);
7312                let kind = if event.shift {
7313                    LinkDefinitionKind::Type
7314                } else {
7315                    LinkDefinitionKind::Symbol
7316                };
7317
7318                show_link_definition(kind, self, point, snapshot, cx);
7319                return false;
7320            }
7321        }
7322
7323        {
7324            if self.link_go_to_definition_state.symbol_range.is_some()
7325                || !self.link_go_to_definition_state.definitions.is_empty()
7326            {
7327                self.link_go_to_definition_state.symbol_range.take();
7328                self.link_go_to_definition_state.definitions.clear();
7329                cx.notify();
7330            }
7331
7332            self.link_go_to_definition_state.task = None;
7333
7334            self.clear_text_highlights::<LinkGoToDefinitionState>(cx);
7335        }
7336
7337        false
7338    }
7339
7340    fn update_keymap_context(&self, keymap: &mut KeymapContext, _: &AppContext) {
7341        Self::reset_to_default_keymap_context(keymap);
7342        let mode = match self.mode {
7343            EditorMode::SingleLine => "single_line",
7344            EditorMode::AutoHeight { .. } => "auto_height",
7345            EditorMode::Full => "full",
7346        };
7347        keymap.add_key("mode", mode);
7348        if self.pending_rename.is_some() {
7349            keymap.add_identifier("renaming");
7350        }
7351        match self.context_menu.as_ref() {
7352            Some(ContextMenu::Completions(_)) => keymap.add_identifier("showing_completions"),
7353            Some(ContextMenu::CodeActions(_)) => keymap.add_identifier("showing_code_actions"),
7354            None => {}
7355        }
7356
7357        for layer in self.keymap_context_layers.values() {
7358            keymap.extend(layer);
7359        }
7360    }
7361
7362    fn text_for_range(&self, range_utf16: Range<usize>, cx: &AppContext) -> Option<String> {
7363        Some(
7364            self.buffer
7365                .read(cx)
7366                .read(cx)
7367                .text_for_range(OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end))
7368                .collect(),
7369        )
7370    }
7371
7372    fn selected_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
7373        // Prevent the IME menu from appearing when holding down an alphabetic key
7374        // while input is disabled.
7375        if !self.input_enabled {
7376            return None;
7377        }
7378
7379        let range = self.selections.newest::<OffsetUtf16>(cx).range();
7380        Some(range.start.0..range.end.0)
7381    }
7382
7383    fn marked_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
7384        let snapshot = self.buffer.read(cx).read(cx);
7385        let range = self.text_highlights::<InputComposition>(cx)?.1.get(0)?;
7386        Some(range.start.to_offset_utf16(&snapshot).0..range.end.to_offset_utf16(&snapshot).0)
7387    }
7388
7389    fn unmark_text(&mut self, cx: &mut ViewContext<Self>) {
7390        self.clear_text_highlights::<InputComposition>(cx);
7391        self.ime_transaction.take();
7392    }
7393
7394    fn replace_text_in_range(
7395        &mut self,
7396        range_utf16: Option<Range<usize>>,
7397        text: &str,
7398        cx: &mut ViewContext<Self>,
7399    ) {
7400        self.transact(cx, |this, cx| {
7401            if this.input_enabled {
7402                let new_selected_ranges = if let Some(range_utf16) = range_utf16 {
7403                    let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
7404                    Some(this.selection_replacement_ranges(range_utf16, cx))
7405                } else {
7406                    this.marked_text_ranges(cx)
7407                };
7408
7409                if let Some(new_selected_ranges) = new_selected_ranges {
7410                    this.change_selections(None, cx, |selections| {
7411                        selections.select_ranges(new_selected_ranges)
7412                    });
7413                }
7414            }
7415
7416            this.handle_input(text, cx);
7417        });
7418
7419        if !self.input_enabled {
7420            return;
7421        }
7422
7423        if let Some(transaction) = self.ime_transaction {
7424            self.buffer.update(cx, |buffer, cx| {
7425                buffer.group_until_transaction(transaction, cx);
7426            });
7427        }
7428
7429        self.unmark_text(cx);
7430    }
7431
7432    fn replace_and_mark_text_in_range(
7433        &mut self,
7434        range_utf16: Option<Range<usize>>,
7435        text: &str,
7436        new_selected_range_utf16: Option<Range<usize>>,
7437        cx: &mut ViewContext<Self>,
7438    ) {
7439        if !self.input_enabled {
7440            return;
7441        }
7442
7443        let transaction = self.transact(cx, |this, cx| {
7444            let ranges_to_replace = if let Some(mut marked_ranges) = this.marked_text_ranges(cx) {
7445                let snapshot = this.buffer.read(cx).read(cx);
7446                if let Some(relative_range_utf16) = range_utf16.as_ref() {
7447                    for marked_range in &mut marked_ranges {
7448                        marked_range.end.0 = marked_range.start.0 + relative_range_utf16.end;
7449                        marked_range.start.0 += relative_range_utf16.start;
7450                        marked_range.start =
7451                            snapshot.clip_offset_utf16(marked_range.start, Bias::Left);
7452                        marked_range.end =
7453                            snapshot.clip_offset_utf16(marked_range.end, Bias::Right);
7454                    }
7455                }
7456                Some(marked_ranges)
7457            } else if let Some(range_utf16) = range_utf16 {
7458                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
7459                Some(this.selection_replacement_ranges(range_utf16, cx))
7460            } else {
7461                None
7462            };
7463
7464            if let Some(ranges) = ranges_to_replace {
7465                this.change_selections(None, cx, |s| s.select_ranges(ranges));
7466            }
7467
7468            let marked_ranges = {
7469                let snapshot = this.buffer.read(cx).read(cx);
7470                this.selections
7471                    .disjoint_anchors()
7472                    .iter()
7473                    .map(|selection| {
7474                        selection.start.bias_left(&*snapshot)..selection.end.bias_right(&*snapshot)
7475                    })
7476                    .collect::<Vec<_>>()
7477            };
7478
7479            if text.is_empty() {
7480                this.unmark_text(cx);
7481            } else {
7482                this.highlight_text::<InputComposition>(
7483                    marked_ranges.clone(),
7484                    this.style(cx).composition_mark,
7485                    cx,
7486                );
7487            }
7488
7489            this.handle_input(text, cx);
7490
7491            if let Some(new_selected_range) = new_selected_range_utf16 {
7492                let snapshot = this.buffer.read(cx).read(cx);
7493                let new_selected_ranges = marked_ranges
7494                    .into_iter()
7495                    .map(|marked_range| {
7496                        let insertion_start = marked_range.start.to_offset_utf16(&snapshot).0;
7497                        let new_start = OffsetUtf16(new_selected_range.start + insertion_start);
7498                        let new_end = OffsetUtf16(new_selected_range.end + insertion_start);
7499                        snapshot.clip_offset_utf16(new_start, Bias::Left)
7500                            ..snapshot.clip_offset_utf16(new_end, Bias::Right)
7501                    })
7502                    .collect::<Vec<_>>();
7503
7504                drop(snapshot);
7505                this.change_selections(None, cx, |selections| {
7506                    selections.select_ranges(new_selected_ranges)
7507                });
7508            }
7509        });
7510
7511        self.ime_transaction = self.ime_transaction.or(transaction);
7512        if let Some(transaction) = self.ime_transaction {
7513            self.buffer.update(cx, |buffer, cx| {
7514                buffer.group_until_transaction(transaction, cx);
7515            });
7516        }
7517
7518        if self.text_highlights::<InputComposition>(cx).is_none() {
7519            self.ime_transaction.take();
7520        }
7521    }
7522}
7523
7524fn build_style(
7525    settings: &ThemeSettings,
7526    get_field_editor_theme: Option<&GetFieldEditorTheme>,
7527    override_text_style: Option<&OverrideTextStyle>,
7528    cx: &AppContext,
7529) -> EditorStyle {
7530    let font_cache = cx.font_cache();
7531
7532    let theme_id = settings.theme.meta.id;
7533    let mut theme = settings.theme.editor.clone();
7534    let mut style = if let Some(get_field_editor_theme) = get_field_editor_theme {
7535        let field_editor_theme = get_field_editor_theme(&settings.theme);
7536        theme.text_color = field_editor_theme.text.color;
7537        theme.selection = field_editor_theme.selection;
7538        theme.background = field_editor_theme
7539            .container
7540            .background_color
7541            .unwrap_or_default();
7542        EditorStyle {
7543            text: field_editor_theme.text,
7544            placeholder_text: field_editor_theme.placeholder_text,
7545            theme,
7546            theme_id,
7547        }
7548    } else {
7549        let font_family_id = settings.buffer_font_family;
7550        let font_family_name = cx.font_cache().family_name(font_family_id).unwrap();
7551        let font_properties = Default::default();
7552        let font_id = font_cache
7553            .select_font(font_family_id, &font_properties)
7554            .unwrap();
7555        let font_size = settings.buffer_font_size(cx);
7556        EditorStyle {
7557            text: TextStyle {
7558                color: settings.theme.editor.text_color,
7559                font_family_name,
7560                font_family_id,
7561                font_id,
7562                font_size,
7563                font_properties,
7564                underline: Default::default(),
7565            },
7566            placeholder_text: None,
7567            theme,
7568            theme_id,
7569        }
7570    };
7571
7572    if let Some(highlight_style) = override_text_style.and_then(|build_style| build_style(&style)) {
7573        if let Some(highlighted) = style
7574            .text
7575            .clone()
7576            .highlight(highlight_style, font_cache)
7577            .log_err()
7578        {
7579            style.text = highlighted;
7580        }
7581    }
7582
7583    style
7584}
7585
7586trait SelectionExt {
7587    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize>;
7588    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point>;
7589    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
7590    fn spanned_rows(&self, include_end_if_at_line_start: bool, map: &DisplaySnapshot)
7591        -> Range<u32>;
7592}
7593
7594impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
7595    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
7596        let start = self.start.to_point(buffer);
7597        let end = self.end.to_point(buffer);
7598        if self.reversed {
7599            end..start
7600        } else {
7601            start..end
7602        }
7603    }
7604
7605    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
7606        let start = self.start.to_offset(buffer);
7607        let end = self.end.to_offset(buffer);
7608        if self.reversed {
7609            end..start
7610        } else {
7611            start..end
7612        }
7613    }
7614
7615    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
7616        let start = self
7617            .start
7618            .to_point(&map.buffer_snapshot)
7619            .to_display_point(map);
7620        let end = self
7621            .end
7622            .to_point(&map.buffer_snapshot)
7623            .to_display_point(map);
7624        if self.reversed {
7625            end..start
7626        } else {
7627            start..end
7628        }
7629    }
7630
7631    fn spanned_rows(
7632        &self,
7633        include_end_if_at_line_start: bool,
7634        map: &DisplaySnapshot,
7635    ) -> Range<u32> {
7636        let start = self.start.to_point(&map.buffer_snapshot);
7637        let mut end = self.end.to_point(&map.buffer_snapshot);
7638        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
7639            end.row -= 1;
7640        }
7641
7642        let buffer_start = map.prev_line_boundary(start).0;
7643        let buffer_end = map.next_line_boundary(end).0;
7644        buffer_start.row..buffer_end.row + 1
7645    }
7646}
7647
7648impl<T: InvalidationRegion> InvalidationStack<T> {
7649    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
7650    where
7651        S: Clone + ToOffset,
7652    {
7653        while let Some(region) = self.last() {
7654            let all_selections_inside_invalidation_ranges =
7655                if selections.len() == region.ranges().len() {
7656                    selections
7657                        .iter()
7658                        .zip(region.ranges().iter().map(|r| r.to_offset(buffer)))
7659                        .all(|(selection, invalidation_range)| {
7660                            let head = selection.head().to_offset(buffer);
7661                            invalidation_range.start <= head && invalidation_range.end >= head
7662                        })
7663                } else {
7664                    false
7665                };
7666
7667            if all_selections_inside_invalidation_ranges {
7668                break;
7669            } else {
7670                self.pop();
7671            }
7672        }
7673    }
7674}
7675
7676impl<T> Default for InvalidationStack<T> {
7677    fn default() -> Self {
7678        Self(Default::default())
7679    }
7680}
7681
7682impl<T> Deref for InvalidationStack<T> {
7683    type Target = Vec<T>;
7684
7685    fn deref(&self) -> &Self::Target {
7686        &self.0
7687    }
7688}
7689
7690impl<T> DerefMut for InvalidationStack<T> {
7691    fn deref_mut(&mut self) -> &mut Self::Target {
7692        &mut self.0
7693    }
7694}
7695
7696impl InvalidationRegion for SnippetState {
7697    fn ranges(&self) -> &[Range<Anchor>] {
7698        &self.ranges[self.active_index]
7699    }
7700}
7701
7702impl Deref for EditorStyle {
7703    type Target = theme::Editor;
7704
7705    fn deref(&self) -> &Self::Target {
7706        &self.theme
7707    }
7708}
7709
7710pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> RenderBlock {
7711    let mut highlighted_lines = Vec::new();
7712    for (index, line) in diagnostic.message.lines().enumerate() {
7713        let line = match &diagnostic.source {
7714            Some(source) if index == 0 => {
7715                let source_highlight = Vec::from_iter(0..source.len());
7716                highlight_diagnostic_message(source_highlight, &format!("{source}: {line}"))
7717            }
7718
7719            _ => highlight_diagnostic_message(Vec::new(), line),
7720        };
7721        highlighted_lines.push(line);
7722    }
7723
7724    Arc::new(move |cx: &mut BlockContext| {
7725        let settings = settings::get::<ThemeSettings>(cx);
7726        let theme = &settings.theme.editor;
7727        let style = diagnostic_style(diagnostic.severity, is_valid, theme);
7728        let font_size = (style.text_scale_factor * settings.buffer_font_size(cx)).round();
7729        Flex::column()
7730            .with_children(highlighted_lines.iter().map(|(line, highlights)| {
7731                Label::new(
7732                    line.clone(),
7733                    style.message.clone().with_font_size(font_size),
7734                )
7735                .with_highlights(highlights.clone())
7736                .contained()
7737                .with_margin_left(cx.anchor_x)
7738            }))
7739            .aligned()
7740            .left()
7741            .into_any()
7742    })
7743}
7744
7745pub fn highlight_diagnostic_message(
7746    inital_highlights: Vec<usize>,
7747    message: &str,
7748) -> (String, Vec<usize>) {
7749    let mut message_without_backticks = String::new();
7750    let mut prev_offset = 0;
7751    let mut inside_block = false;
7752    let mut highlights = inital_highlights;
7753    for (match_ix, (offset, _)) in message
7754        .match_indices('`')
7755        .chain([(message.len(), "")])
7756        .enumerate()
7757    {
7758        message_without_backticks.push_str(&message[prev_offset..offset]);
7759        if inside_block {
7760            highlights.extend(prev_offset - match_ix..offset - match_ix);
7761        }
7762
7763        inside_block = !inside_block;
7764        prev_offset = offset + 1;
7765    }
7766
7767    (message_without_backticks, highlights)
7768}
7769
7770pub fn diagnostic_style(
7771    severity: DiagnosticSeverity,
7772    valid: bool,
7773    theme: &theme::Editor,
7774) -> DiagnosticStyle {
7775    match (severity, valid) {
7776        (DiagnosticSeverity::ERROR, true) => theme.error_diagnostic.clone(),
7777        (DiagnosticSeverity::ERROR, false) => theme.invalid_error_diagnostic.clone(),
7778        (DiagnosticSeverity::WARNING, true) => theme.warning_diagnostic.clone(),
7779        (DiagnosticSeverity::WARNING, false) => theme.invalid_warning_diagnostic.clone(),
7780        (DiagnosticSeverity::INFORMATION, true) => theme.information_diagnostic.clone(),
7781        (DiagnosticSeverity::INFORMATION, false) => theme.invalid_information_diagnostic.clone(),
7782        (DiagnosticSeverity::HINT, true) => theme.hint_diagnostic.clone(),
7783        (DiagnosticSeverity::HINT, false) => theme.invalid_hint_diagnostic.clone(),
7784        _ => theme.invalid_hint_diagnostic.clone(),
7785    }
7786}
7787
7788pub fn combine_syntax_and_fuzzy_match_highlights(
7789    text: &str,
7790    default_style: HighlightStyle,
7791    syntax_ranges: impl Iterator<Item = (Range<usize>, HighlightStyle)>,
7792    match_indices: &[usize],
7793) -> Vec<(Range<usize>, HighlightStyle)> {
7794    let mut result = Vec::new();
7795    let mut match_indices = match_indices.iter().copied().peekable();
7796
7797    for (range, mut syntax_highlight) in syntax_ranges.chain([(usize::MAX..0, Default::default())])
7798    {
7799        syntax_highlight.weight = None;
7800
7801        // Add highlights for any fuzzy match characters before the next
7802        // syntax highlight range.
7803        while let Some(&match_index) = match_indices.peek() {
7804            if match_index >= range.start {
7805                break;
7806            }
7807            match_indices.next();
7808            let end_index = char_ix_after(match_index, text);
7809            let mut match_style = default_style;
7810            match_style.weight = Some(fonts::Weight::BOLD);
7811            result.push((match_index..end_index, match_style));
7812        }
7813
7814        if range.start == usize::MAX {
7815            break;
7816        }
7817
7818        // Add highlights for any fuzzy match characters within the
7819        // syntax highlight range.
7820        let mut offset = range.start;
7821        while let Some(&match_index) = match_indices.peek() {
7822            if match_index >= range.end {
7823                break;
7824            }
7825
7826            match_indices.next();
7827            if match_index > offset {
7828                result.push((offset..match_index, syntax_highlight));
7829            }
7830
7831            let mut end_index = char_ix_after(match_index, text);
7832            while let Some(&next_match_index) = match_indices.peek() {
7833                if next_match_index == end_index && next_match_index < range.end {
7834                    end_index = char_ix_after(next_match_index, text);
7835                    match_indices.next();
7836                } else {
7837                    break;
7838                }
7839            }
7840
7841            let mut match_style = syntax_highlight;
7842            match_style.weight = Some(fonts::Weight::BOLD);
7843            result.push((match_index..end_index, match_style));
7844            offset = end_index;
7845        }
7846
7847        if offset < range.end {
7848            result.push((offset..range.end, syntax_highlight));
7849        }
7850    }
7851
7852    fn char_ix_after(ix: usize, text: &str) -> usize {
7853        ix + text[ix..].chars().next().unwrap().len_utf8()
7854    }
7855
7856    result
7857}
7858
7859pub fn styled_runs_for_code_label<'a>(
7860    label: &'a CodeLabel,
7861    syntax_theme: &'a theme::SyntaxTheme,
7862) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
7863    let fade_out = HighlightStyle {
7864        fade_out: Some(0.35),
7865        ..Default::default()
7866    };
7867
7868    let mut prev_end = label.filter_range.end;
7869    label
7870        .runs
7871        .iter()
7872        .enumerate()
7873        .flat_map(move |(ix, (range, highlight_id))| {
7874            let style = if let Some(style) = highlight_id.style(syntax_theme) {
7875                style
7876            } else {
7877                return Default::default();
7878            };
7879            let mut muted_style = style;
7880            muted_style.highlight(fade_out);
7881
7882            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
7883            if range.start >= label.filter_range.end {
7884                if range.start > prev_end {
7885                    runs.push((prev_end..range.start, fade_out));
7886                }
7887                runs.push((range.clone(), muted_style));
7888            } else if range.end <= label.filter_range.end {
7889                runs.push((range.clone(), style));
7890            } else {
7891                runs.push((range.start..label.filter_range.end, style));
7892                runs.push((label.filter_range.end..range.end, muted_style));
7893            }
7894            prev_end = cmp::max(prev_end, range.end);
7895
7896            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
7897                runs.push((prev_end..label.text.len(), fade_out));
7898            }
7899
7900            runs
7901        })
7902}
7903
7904pub fn split_words<'a>(text: &'a str) -> impl std::iter::Iterator<Item = &'a str> + 'a {
7905    let mut index = 0;
7906    let mut codepoints = text.char_indices().peekable();
7907
7908    std::iter::from_fn(move || {
7909        let start_index = index;
7910        while let Some((new_index, codepoint)) = codepoints.next() {
7911            index = new_index + codepoint.len_utf8();
7912            let current_upper = codepoint.is_uppercase();
7913            let next_upper = codepoints
7914                .peek()
7915                .map(|(_, c)| c.is_uppercase())
7916                .unwrap_or(false);
7917
7918            if !current_upper && next_upper {
7919                return Some(&text[start_index..index]);
7920            }
7921        }
7922
7923        index = text.len();
7924        if start_index < text.len() {
7925            return Some(&text[start_index..]);
7926        }
7927        None
7928    })
7929    .flat_map(|word| word.split_inclusive('_'))
7930}
7931
7932trait RangeToAnchorExt {
7933    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor>;
7934}
7935
7936impl<T: ToOffset> RangeToAnchorExt for Range<T> {
7937    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor> {
7938        snapshot.anchor_after(self.start)..snapshot.anchor_before(self.end)
7939    }
7940}