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