editor.rs

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