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