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