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