editor.rs

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