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