editor.rs

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