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