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