editor.rs

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