editor.rs

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