editor.rs

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