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