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