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