editor.rs

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