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.copilot_state.completions.is_empty() {
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
2844        self.update_visible_copilot_suggestion(cx);
2845    }
2846
2847    fn previous_copilot_suggestion(
2848        &mut self,
2849        _: &copilot::PreviousSuggestion,
2850        cx: &mut ViewContext<Self>,
2851    ) {
2852        if self.copilot_state.completions.is_empty() {
2853            self.refresh_copilot_suggestions(cx);
2854            return;
2855        }
2856
2857        self.copilot_state.active_completion_index =
2858            if self.copilot_state.active_completion_index == 0 {
2859                self.copilot_state.completions.len() - 1
2860            } else {
2861                self.copilot_state.active_completion_index - 1
2862            };
2863
2864        self.update_visible_copilot_suggestion(cx);
2865    }
2866
2867    fn accept_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) -> bool {
2868        if let Some(text) = self.hide_copilot_suggestion(cx) {
2869            self.insert_with_autoindent_mode(&text.to_string(), None, cx);
2870            true
2871        } else {
2872            false
2873        }
2874    }
2875
2876    fn has_active_copilot_suggestion(&self, cx: &AppContext) -> bool {
2877        self.display_map.read(cx).has_suggestion()
2878    }
2879
2880    fn hide_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) -> Option<Rope> {
2881        if self.has_active_copilot_suggestion(cx) {
2882            let old_suggestion = self
2883                .display_map
2884                .update(cx, |map, cx| map.replace_suggestion::<usize>(None, cx));
2885            cx.notify();
2886            old_suggestion.map(|suggestion| suggestion.text)
2887        } else {
2888            None
2889        }
2890    }
2891
2892    fn update_visible_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) {
2893        let snapshot = self.buffer.read(cx).snapshot(cx);
2894        let selection = self.selections.newest_anchor();
2895        let cursor = selection.head();
2896
2897        if self.context_menu.is_some()
2898            || !self.completion_tasks.is_empty()
2899            || selection.start != selection.end
2900        {
2901            self.hide_copilot_suggestion(cx);
2902        } else if let Some(text) = self
2903            .copilot_state
2904            .text_for_active_completion(cursor, &snapshot)
2905        {
2906            self.display_map.update(cx, |map, cx| {
2907                map.replace_suggestion(
2908                    Some(Suggestion {
2909                        position: cursor,
2910                        text: text.into(),
2911                    }),
2912                    cx,
2913                )
2914            });
2915            cx.notify();
2916        } else {
2917            self.hide_copilot_suggestion(cx);
2918        }
2919    }
2920
2921    pub fn render_code_actions_indicator(
2922        &self,
2923        style: &EditorStyle,
2924        active: bool,
2925        cx: &mut RenderContext<Self>,
2926    ) -> Option<ElementBox> {
2927        if self.available_code_actions.is_some() {
2928            enum CodeActions {}
2929            Some(
2930                MouseEventHandler::<CodeActions>::new(0, cx, |state, _| {
2931                    Svg::new("icons/bolt_8.svg")
2932                        .with_color(style.code_actions.indicator.style_for(state, active).color)
2933                        .boxed()
2934                })
2935                .with_cursor_style(CursorStyle::PointingHand)
2936                .with_padding(Padding::uniform(3.))
2937                .on_down(MouseButton::Left, |_, cx| {
2938                    cx.dispatch_action(ToggleCodeActions {
2939                        deployed_from_indicator: true,
2940                    });
2941                })
2942                .boxed(),
2943            )
2944        } else {
2945            None
2946        }
2947    }
2948
2949    pub fn render_fold_indicators(
2950        &self,
2951        fold_data: Vec<Option<(FoldStatus, u32, bool)>>,
2952        style: &EditorStyle,
2953        gutter_hovered: bool,
2954        line_height: f32,
2955        gutter_margin: f32,
2956        cx: &mut RenderContext<Self>,
2957    ) -> Vec<Option<ElementBox>> {
2958        enum FoldIndicators {}
2959
2960        let style = style.folds.clone();
2961
2962        fold_data
2963            .iter()
2964            .enumerate()
2965            .map(|(ix, fold_data)| {
2966                fold_data
2967                    .map(|(fold_status, buffer_row, active)| {
2968                        (active || gutter_hovered || fold_status == FoldStatus::Folded).then(|| {
2969                            MouseEventHandler::<FoldIndicators>::new(
2970                                ix as usize,
2971                                cx,
2972                                |mouse_state, _| -> ElementBox {
2973                                    Svg::new(match fold_status {
2974                                        FoldStatus::Folded => style.folded_icon.clone(),
2975                                        FoldStatus::Foldable => style.foldable_icon.clone(),
2976                                    })
2977                                    .with_color(
2978                                        style
2979                                            .indicator
2980                                            .style_for(
2981                                                mouse_state,
2982                                                fold_status == FoldStatus::Folded,
2983                                            )
2984                                            .color,
2985                                    )
2986                                    .constrained()
2987                                    .with_width(gutter_margin * style.icon_margin_scale)
2988                                    .aligned()
2989                                    .constrained()
2990                                    .with_height(line_height)
2991                                    .with_width(gutter_margin)
2992                                    .aligned()
2993                                    .boxed()
2994                                },
2995                            )
2996                            .with_cursor_style(CursorStyle::PointingHand)
2997                            .with_padding(Padding::uniform(3.))
2998                            .on_click(MouseButton::Left, {
2999                                move |_, cx| {
3000                                    cx.dispatch_any_action(match fold_status {
3001                                        FoldStatus::Folded => Box::new(UnfoldAt { buffer_row }),
3002                                        FoldStatus::Foldable => Box::new(FoldAt { buffer_row }),
3003                                    });
3004                                }
3005                            })
3006                            .boxed()
3007                        })
3008                    })
3009                    .flatten()
3010            })
3011            .collect()
3012    }
3013
3014    pub fn context_menu_visible(&self) -> bool {
3015        self.context_menu
3016            .as_ref()
3017            .map_or(false, |menu| menu.visible())
3018    }
3019
3020    pub fn render_context_menu(
3021        &self,
3022        cursor_position: DisplayPoint,
3023        style: EditorStyle,
3024        cx: &mut RenderContext<Editor>,
3025    ) -> Option<(DisplayPoint, ElementBox)> {
3026        self.context_menu
3027            .as_ref()
3028            .map(|menu| menu.render(cursor_position, style, cx))
3029    }
3030
3031    fn show_context_menu(&mut self, menu: ContextMenu, cx: &mut ViewContext<Self>) {
3032        if !matches!(menu, ContextMenu::Completions(_)) {
3033            self.completion_tasks.clear();
3034        }
3035        self.context_menu = Some(menu);
3036        self.hide_copilot_suggestion(cx);
3037        cx.notify();
3038    }
3039
3040    fn hide_context_menu(&mut self, cx: &mut ViewContext<Self>) -> Option<ContextMenu> {
3041        cx.notify();
3042        self.completion_tasks.clear();
3043        let context_menu = self.context_menu.take();
3044        if context_menu.is_some() {
3045            self.update_visible_copilot_suggestion(cx);
3046        }
3047        context_menu
3048    }
3049
3050    pub fn insert_snippet(
3051        &mut self,
3052        insertion_ranges: &[Range<usize>],
3053        snippet: Snippet,
3054        cx: &mut ViewContext<Self>,
3055    ) -> Result<()> {
3056        let tabstops = self.buffer.update(cx, |buffer, cx| {
3057            let snippet_text: Arc<str> = snippet.text.clone().into();
3058            buffer.edit(
3059                insertion_ranges
3060                    .iter()
3061                    .cloned()
3062                    .map(|range| (range, snippet_text.clone())),
3063                Some(AutoindentMode::EachLine),
3064                cx,
3065            );
3066
3067            let snapshot = &*buffer.read(cx);
3068            let snippet = &snippet;
3069            snippet
3070                .tabstops
3071                .iter()
3072                .map(|tabstop| {
3073                    let mut tabstop_ranges = tabstop
3074                        .iter()
3075                        .flat_map(|tabstop_range| {
3076                            let mut delta = 0_isize;
3077                            insertion_ranges.iter().map(move |insertion_range| {
3078                                let insertion_start = insertion_range.start as isize + delta;
3079                                delta +=
3080                                    snippet.text.len() as isize - insertion_range.len() as isize;
3081
3082                                let start = snapshot.anchor_before(
3083                                    (insertion_start + tabstop_range.start) as usize,
3084                                );
3085                                let end = snapshot
3086                                    .anchor_after((insertion_start + tabstop_range.end) as usize);
3087                                start..end
3088                            })
3089                        })
3090                        .collect::<Vec<_>>();
3091                    tabstop_ranges.sort_unstable_by(|a, b| a.start.cmp(&b.start, snapshot));
3092                    tabstop_ranges
3093                })
3094                .collect::<Vec<_>>()
3095        });
3096
3097        if let Some(tabstop) = tabstops.first() {
3098            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3099                s.select_ranges(tabstop.iter().cloned());
3100            });
3101            self.snippet_stack.push(SnippetState {
3102                active_index: 0,
3103                ranges: tabstops,
3104            });
3105        }
3106
3107        Ok(())
3108    }
3109
3110    pub fn move_to_next_snippet_tabstop(&mut self, cx: &mut ViewContext<Self>) -> bool {
3111        self.move_to_snippet_tabstop(Bias::Right, cx)
3112    }
3113
3114    pub fn move_to_prev_snippet_tabstop(&mut self, cx: &mut ViewContext<Self>) -> bool {
3115        self.move_to_snippet_tabstop(Bias::Left, cx)
3116    }
3117
3118    pub fn move_to_snippet_tabstop(&mut self, bias: Bias, cx: &mut ViewContext<Self>) -> bool {
3119        if let Some(mut snippet) = self.snippet_stack.pop() {
3120            match bias {
3121                Bias::Left => {
3122                    if snippet.active_index > 0 {
3123                        snippet.active_index -= 1;
3124                    } else {
3125                        self.snippet_stack.push(snippet);
3126                        return false;
3127                    }
3128                }
3129                Bias::Right => {
3130                    if snippet.active_index + 1 < snippet.ranges.len() {
3131                        snippet.active_index += 1;
3132                    } else {
3133                        self.snippet_stack.push(snippet);
3134                        return false;
3135                    }
3136                }
3137            }
3138            if let Some(current_ranges) = snippet.ranges.get(snippet.active_index) {
3139                self.change_selections(Some(Autoscroll::fit()), cx, |s| {
3140                    s.select_anchor_ranges(current_ranges.iter().cloned())
3141                });
3142                // If snippet state is not at the last tabstop, push it back on the stack
3143                if snippet.active_index + 1 < snippet.ranges.len() {
3144                    self.snippet_stack.push(snippet);
3145                }
3146                return true;
3147            }
3148        }
3149
3150        false
3151    }
3152
3153    pub fn clear(&mut self, cx: &mut ViewContext<Self>) {
3154        self.transact(cx, |this, cx| {
3155            this.select_all(&SelectAll, cx);
3156            this.insert("", cx);
3157        });
3158    }
3159
3160    pub fn backspace(&mut self, _: &Backspace, cx: &mut ViewContext<Self>) {
3161        self.transact(cx, |this, cx| {
3162            this.select_autoclose_pair(cx);
3163            let mut selections = this.selections.all::<Point>(cx);
3164            if !this.selections.line_mode {
3165                let display_map = this.display_map.update(cx, |map, cx| map.snapshot(cx));
3166                for selection in &mut selections {
3167                    if selection.is_empty() {
3168                        let old_head = selection.head();
3169                        let mut new_head =
3170                            movement::left(&display_map, old_head.to_display_point(&display_map))
3171                                .to_point(&display_map);
3172                        if let Some((buffer, line_buffer_range)) = display_map
3173                            .buffer_snapshot
3174                            .buffer_line_for_row(old_head.row)
3175                        {
3176                            let indent_size =
3177                                buffer.indent_size_for_line(line_buffer_range.start.row);
3178                            let language_name = buffer
3179                                .language_at(line_buffer_range.start)
3180                                .map(|language| language.name());
3181                            let indent_len = match indent_size.kind {
3182                                IndentKind::Space => {
3183                                    cx.global::<Settings>().tab_size(language_name.as_deref())
3184                                }
3185                                IndentKind::Tab => NonZeroU32::new(1).unwrap(),
3186                            };
3187                            if old_head.column <= indent_size.len && old_head.column > 0 {
3188                                let indent_len = indent_len.get();
3189                                new_head = cmp::min(
3190                                    new_head,
3191                                    Point::new(
3192                                        old_head.row,
3193                                        ((old_head.column - 1) / indent_len) * indent_len,
3194                                    ),
3195                                );
3196                            }
3197                        }
3198
3199                        selection.set_head(new_head, SelectionGoal::None);
3200                    }
3201                }
3202            }
3203
3204            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
3205            this.insert("", cx);
3206            this.refresh_copilot_suggestions(cx);
3207        });
3208    }
3209
3210    pub fn delete(&mut self, _: &Delete, cx: &mut ViewContext<Self>) {
3211        self.transact(cx, |this, cx| {
3212            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
3213                let line_mode = s.line_mode;
3214                s.move_with(|map, selection| {
3215                    if selection.is_empty() && !line_mode {
3216                        let cursor = movement::right(map, selection.head());
3217                        selection.set_head(cursor, SelectionGoal::None);
3218                    }
3219                })
3220            });
3221            this.insert("", cx);
3222            this.refresh_copilot_suggestions(cx);
3223        });
3224    }
3225
3226    pub fn tab_prev(&mut self, _: &TabPrev, cx: &mut ViewContext<Self>) {
3227        if self.move_to_prev_snippet_tabstop(cx) {
3228            return;
3229        }
3230
3231        self.outdent(&Outdent, cx);
3232    }
3233
3234    pub fn tab(&mut self, _: &Tab, cx: &mut ViewContext<Self>) {
3235        if self.accept_copilot_suggestion(cx) {
3236            return;
3237        }
3238
3239        if self.move_to_next_snippet_tabstop(cx) {
3240            return;
3241        }
3242
3243        let mut selections = self.selections.all_adjusted(cx);
3244        let buffer = self.buffer.read(cx);
3245        let snapshot = buffer.snapshot(cx);
3246        let rows_iter = selections.iter().map(|s| s.head().row);
3247        let suggested_indents = snapshot.suggested_indents(rows_iter, cx);
3248
3249        let mut edits = Vec::new();
3250        let mut prev_edited_row = 0;
3251        let mut row_delta = 0;
3252        for selection in &mut selections {
3253            if selection.start.row != prev_edited_row {
3254                row_delta = 0;
3255            }
3256            prev_edited_row = selection.end.row;
3257
3258            // If the selection is non-empty, then increase the indentation of the selected lines.
3259            if !selection.is_empty() {
3260                row_delta =
3261                    Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
3262                continue;
3263            }
3264
3265            // If the selection is empty and the cursor is in the leading whitespace before the
3266            // suggested indentation, then auto-indent the line.
3267            let cursor = selection.head();
3268            if let Some(suggested_indent) = suggested_indents.get(&cursor.row).copied() {
3269                let current_indent = snapshot.indent_size_for_line(cursor.row);
3270                if cursor.column < suggested_indent.len
3271                    && cursor.column <= current_indent.len
3272                    && current_indent.len <= suggested_indent.len
3273                {
3274                    selection.start = Point::new(cursor.row, suggested_indent.len);
3275                    selection.end = selection.start;
3276                    if row_delta == 0 {
3277                        edits.extend(Buffer::edit_for_indent_size_adjustment(
3278                            cursor.row,
3279                            current_indent,
3280                            suggested_indent,
3281                        ));
3282                        row_delta = suggested_indent.len - current_indent.len;
3283                    }
3284                    continue;
3285                }
3286            }
3287
3288            // Otherwise, insert a hard or soft tab.
3289            let settings = cx.global::<Settings>();
3290            let language_name = buffer.language_at(cursor, cx).map(|l| l.name());
3291            let tab_size = if settings.hard_tabs(language_name.as_deref()) {
3292                IndentSize::tab()
3293            } else {
3294                let tab_size = settings.tab_size(language_name.as_deref()).get();
3295                let char_column = snapshot
3296                    .text_for_range(Point::new(cursor.row, 0)..cursor)
3297                    .flat_map(str::chars)
3298                    .count()
3299                    + row_delta as usize;
3300                let chars_to_next_tab_stop = tab_size - (char_column as u32 % tab_size);
3301                IndentSize::spaces(chars_to_next_tab_stop)
3302            };
3303            selection.start = Point::new(cursor.row, cursor.column + row_delta + tab_size.len);
3304            selection.end = selection.start;
3305            edits.push((cursor..cursor, tab_size.chars().collect::<String>()));
3306            row_delta += tab_size.len;
3307        }
3308
3309        self.transact(cx, |this, cx| {
3310            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
3311            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections))
3312        });
3313    }
3314
3315    pub fn indent(&mut self, _: &Indent, cx: &mut ViewContext<Self>) {
3316        let mut selections = self.selections.all::<Point>(cx);
3317        let mut prev_edited_row = 0;
3318        let mut row_delta = 0;
3319        let mut edits = Vec::new();
3320        let buffer = self.buffer.read(cx);
3321        let snapshot = buffer.snapshot(cx);
3322        for selection in &mut selections {
3323            if selection.start.row != prev_edited_row {
3324                row_delta = 0;
3325            }
3326            prev_edited_row = selection.end.row;
3327
3328            row_delta =
3329                Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
3330        }
3331
3332        self.transact(cx, |this, cx| {
3333            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
3334            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
3335        });
3336    }
3337
3338    fn indent_selection(
3339        buffer: &MultiBuffer,
3340        snapshot: &MultiBufferSnapshot,
3341        selection: &mut Selection<Point>,
3342        edits: &mut Vec<(Range<Point>, String)>,
3343        delta_for_start_row: u32,
3344        cx: &AppContext,
3345    ) -> u32 {
3346        let language_name = buffer.language_at(selection.start, cx).map(|l| l.name());
3347        let settings = cx.global::<Settings>();
3348        let tab_size = settings.tab_size(language_name.as_deref()).get();
3349        let indent_kind = if settings.hard_tabs(language_name.as_deref()) {
3350            IndentKind::Tab
3351        } else {
3352            IndentKind::Space
3353        };
3354        let mut start_row = selection.start.row;
3355        let mut end_row = selection.end.row + 1;
3356
3357        // If a selection ends at the beginning of a line, don't indent
3358        // that last line.
3359        if selection.end.column == 0 {
3360            end_row -= 1;
3361        }
3362
3363        // Avoid re-indenting a row that has already been indented by a
3364        // previous selection, but still update this selection's column
3365        // to reflect that indentation.
3366        if delta_for_start_row > 0 {
3367            start_row += 1;
3368            selection.start.column += delta_for_start_row;
3369            if selection.end.row == selection.start.row {
3370                selection.end.column += delta_for_start_row;
3371            }
3372        }
3373
3374        let mut delta_for_end_row = 0;
3375        for row in start_row..end_row {
3376            let current_indent = snapshot.indent_size_for_line(row);
3377            let indent_delta = match (current_indent.kind, indent_kind) {
3378                (IndentKind::Space, IndentKind::Space) => {
3379                    let columns_to_next_tab_stop = tab_size - (current_indent.len % tab_size);
3380                    IndentSize::spaces(columns_to_next_tab_stop)
3381                }
3382                (IndentKind::Tab, IndentKind::Space) => IndentSize::spaces(tab_size),
3383                (_, IndentKind::Tab) => IndentSize::tab(),
3384            };
3385
3386            let row_start = Point::new(row, 0);
3387            edits.push((
3388                row_start..row_start,
3389                indent_delta.chars().collect::<String>(),
3390            ));
3391
3392            // Update this selection's endpoints to reflect the indentation.
3393            if row == selection.start.row {
3394                selection.start.column += indent_delta.len;
3395            }
3396            if row == selection.end.row {
3397                selection.end.column += indent_delta.len;
3398                delta_for_end_row = indent_delta.len;
3399            }
3400        }
3401
3402        if selection.start.row == selection.end.row {
3403            delta_for_start_row + delta_for_end_row
3404        } else {
3405            delta_for_end_row
3406        }
3407    }
3408
3409    pub fn outdent(&mut self, _: &Outdent, cx: &mut ViewContext<Self>) {
3410        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3411        let selections = self.selections.all::<Point>(cx);
3412        let mut deletion_ranges = Vec::new();
3413        let mut last_outdent = None;
3414        {
3415            let buffer = self.buffer.read(cx);
3416            let snapshot = buffer.snapshot(cx);
3417            for selection in &selections {
3418                let language_name = buffer.language_at(selection.start, cx).map(|l| l.name());
3419                let tab_size = cx
3420                    .global::<Settings>()
3421                    .tab_size(language_name.as_deref())
3422                    .get();
3423                let mut rows = selection.spanned_rows(false, &display_map);
3424
3425                // Avoid re-outdenting a row that has already been outdented by a
3426                // previous selection.
3427                if let Some(last_row) = last_outdent {
3428                    if last_row == rows.start {
3429                        rows.start += 1;
3430                    }
3431                }
3432
3433                for row in rows {
3434                    let indent_size = snapshot.indent_size_for_line(row);
3435                    if indent_size.len > 0 {
3436                        let deletion_len = match indent_size.kind {
3437                            IndentKind::Space => {
3438                                let columns_to_prev_tab_stop = indent_size.len % tab_size;
3439                                if columns_to_prev_tab_stop == 0 {
3440                                    tab_size
3441                                } else {
3442                                    columns_to_prev_tab_stop
3443                                }
3444                            }
3445                            IndentKind::Tab => 1,
3446                        };
3447                        deletion_ranges.push(Point::new(row, 0)..Point::new(row, deletion_len));
3448                        last_outdent = Some(row);
3449                    }
3450                }
3451            }
3452        }
3453
3454        self.transact(cx, |this, cx| {
3455            this.buffer.update(cx, |buffer, cx| {
3456                let empty_str: Arc<str> = "".into();
3457                buffer.edit(
3458                    deletion_ranges
3459                        .into_iter()
3460                        .map(|range| (range, empty_str.clone())),
3461                    None,
3462                    cx,
3463                );
3464            });
3465            let selections = this.selections.all::<usize>(cx);
3466            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
3467        });
3468    }
3469
3470    pub fn delete_line(&mut self, _: &DeleteLine, cx: &mut ViewContext<Self>) {
3471        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3472        let selections = self.selections.all::<Point>(cx);
3473
3474        let mut new_cursors = Vec::new();
3475        let mut edit_ranges = Vec::new();
3476        let mut selections = selections.iter().peekable();
3477        while let Some(selection) = selections.next() {
3478            let mut rows = selection.spanned_rows(false, &display_map);
3479            let goal_display_column = selection.head().to_display_point(&display_map).column();
3480
3481            // Accumulate contiguous regions of rows that we want to delete.
3482            while let Some(next_selection) = selections.peek() {
3483                let next_rows = next_selection.spanned_rows(false, &display_map);
3484                if next_rows.start <= rows.end {
3485                    rows.end = next_rows.end;
3486                    selections.next().unwrap();
3487                } else {
3488                    break;
3489                }
3490            }
3491
3492            let buffer = &display_map.buffer_snapshot;
3493            let mut edit_start = Point::new(rows.start, 0).to_offset(buffer);
3494            let edit_end;
3495            let cursor_buffer_row;
3496            if buffer.max_point().row >= rows.end {
3497                // If there's a line after the range, delete the \n from the end of the row range
3498                // and position the cursor on the next line.
3499                edit_end = Point::new(rows.end, 0).to_offset(buffer);
3500                cursor_buffer_row = rows.end;
3501            } else {
3502                // If there isn't a line after the range, delete the \n from the line before the
3503                // start of the row range and position the cursor there.
3504                edit_start = edit_start.saturating_sub(1);
3505                edit_end = buffer.len();
3506                cursor_buffer_row = rows.start.saturating_sub(1);
3507            }
3508
3509            let mut cursor = Point::new(cursor_buffer_row, 0).to_display_point(&display_map);
3510            *cursor.column_mut() =
3511                cmp::min(goal_display_column, display_map.line_len(cursor.row()));
3512
3513            new_cursors.push((
3514                selection.id,
3515                buffer.anchor_after(cursor.to_point(&display_map)),
3516            ));
3517            edit_ranges.push(edit_start..edit_end);
3518        }
3519
3520        self.transact(cx, |this, cx| {
3521            let buffer = this.buffer.update(cx, |buffer, cx| {
3522                let empty_str: Arc<str> = "".into();
3523                buffer.edit(
3524                    edit_ranges
3525                        .into_iter()
3526                        .map(|range| (range, empty_str.clone())),
3527                    None,
3528                    cx,
3529                );
3530                buffer.snapshot(cx)
3531            });
3532            let new_selections = new_cursors
3533                .into_iter()
3534                .map(|(id, cursor)| {
3535                    let cursor = cursor.to_point(&buffer);
3536                    Selection {
3537                        id,
3538                        start: cursor,
3539                        end: cursor,
3540                        reversed: false,
3541                        goal: SelectionGoal::None,
3542                    }
3543                })
3544                .collect();
3545
3546            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
3547                s.select(new_selections);
3548            });
3549        });
3550    }
3551
3552    pub fn duplicate_line(&mut self, _: &DuplicateLine, cx: &mut ViewContext<Self>) {
3553        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3554        let buffer = &display_map.buffer_snapshot;
3555        let selections = self.selections.all::<Point>(cx);
3556
3557        let mut edits = Vec::new();
3558        let mut selections_iter = selections.iter().peekable();
3559        while let Some(selection) = selections_iter.next() {
3560            // Avoid duplicating the same lines twice.
3561            let mut rows = selection.spanned_rows(false, &display_map);
3562
3563            while let Some(next_selection) = selections_iter.peek() {
3564                let next_rows = next_selection.spanned_rows(false, &display_map);
3565                if next_rows.start < rows.end {
3566                    rows.end = next_rows.end;
3567                    selections_iter.next().unwrap();
3568                } else {
3569                    break;
3570                }
3571            }
3572
3573            // Copy the text from the selected row region and splice it at the start of the region.
3574            let start = Point::new(rows.start, 0);
3575            let end = Point::new(rows.end - 1, buffer.line_len(rows.end - 1));
3576            let text = buffer
3577                .text_for_range(start..end)
3578                .chain(Some("\n"))
3579                .collect::<String>();
3580            edits.push((start..start, text));
3581        }
3582
3583        self.transact(cx, |this, cx| {
3584            this.buffer.update(cx, |buffer, cx| {
3585                buffer.edit(edits, None, cx);
3586            });
3587
3588            this.request_autoscroll(Autoscroll::fit(), cx);
3589        });
3590    }
3591
3592    pub fn move_line_up(&mut self, _: &MoveLineUp, cx: &mut ViewContext<Self>) {
3593        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3594        let buffer = self.buffer.read(cx).snapshot(cx);
3595
3596        let mut edits = Vec::new();
3597        let mut unfold_ranges = Vec::new();
3598        let mut refold_ranges = Vec::new();
3599
3600        let selections = self.selections.all::<Point>(cx);
3601        let mut selections = selections.iter().peekable();
3602        let mut contiguous_row_selections = Vec::new();
3603        let mut new_selections = Vec::new();
3604
3605        while let Some(selection) = selections.next() {
3606            // Find all the selections that span a contiguous row range
3607            let (start_row, end_row) = consume_contiguous_rows(
3608                &mut contiguous_row_selections,
3609                selection,
3610                &display_map,
3611                &mut selections,
3612            );
3613
3614            // Move the text spanned by the row range to be before the line preceding the row range
3615            if start_row > 0 {
3616                let range_to_move = Point::new(start_row - 1, buffer.line_len(start_row - 1))
3617                    ..Point::new(end_row - 1, buffer.line_len(end_row - 1));
3618                let insertion_point = display_map
3619                    .prev_line_boundary(Point::new(start_row - 1, 0))
3620                    .0;
3621
3622                // Don't move lines across excerpts
3623                if buffer
3624                    .excerpt_boundaries_in_range((
3625                        Bound::Excluded(insertion_point),
3626                        Bound::Included(range_to_move.end),
3627                    ))
3628                    .next()
3629                    .is_none()
3630                {
3631                    let text = buffer
3632                        .text_for_range(range_to_move.clone())
3633                        .flat_map(|s| s.chars())
3634                        .skip(1)
3635                        .chain(['\n'])
3636                        .collect::<String>();
3637
3638                    edits.push((
3639                        buffer.anchor_after(range_to_move.start)
3640                            ..buffer.anchor_before(range_to_move.end),
3641                        String::new(),
3642                    ));
3643                    let insertion_anchor = buffer.anchor_after(insertion_point);
3644                    edits.push((insertion_anchor..insertion_anchor, text));
3645
3646                    let row_delta = range_to_move.start.row - insertion_point.row + 1;
3647
3648                    // Move selections up
3649                    new_selections.extend(contiguous_row_selections.drain(..).map(
3650                        |mut selection| {
3651                            selection.start.row -= row_delta;
3652                            selection.end.row -= row_delta;
3653                            selection
3654                        },
3655                    ));
3656
3657                    // Move folds up
3658                    unfold_ranges.push(range_to_move.clone());
3659                    for fold in display_map.folds_in_range(
3660                        buffer.anchor_before(range_to_move.start)
3661                            ..buffer.anchor_after(range_to_move.end),
3662                    ) {
3663                        let mut start = fold.start.to_point(&buffer);
3664                        let mut end = fold.end.to_point(&buffer);
3665                        start.row -= row_delta;
3666                        end.row -= row_delta;
3667                        refold_ranges.push(start..end);
3668                    }
3669                }
3670            }
3671
3672            // If we didn't move line(s), preserve the existing selections
3673            new_selections.append(&mut contiguous_row_selections);
3674        }
3675
3676        self.transact(cx, |this, cx| {
3677            this.unfold_ranges(unfold_ranges, true, true, cx);
3678            this.buffer.update(cx, |buffer, cx| {
3679                for (range, text) in edits {
3680                    buffer.edit([(range, text)], None, cx);
3681                }
3682            });
3683            this.fold_ranges(refold_ranges, true, cx);
3684            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
3685                s.select(new_selections);
3686            })
3687        });
3688    }
3689
3690    pub fn move_line_down(&mut self, _: &MoveLineDown, cx: &mut ViewContext<Self>) {
3691        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
3692        let buffer = self.buffer.read(cx).snapshot(cx);
3693
3694        let mut edits = Vec::new();
3695        let mut unfold_ranges = Vec::new();
3696        let mut refold_ranges = Vec::new();
3697
3698        let selections = self.selections.all::<Point>(cx);
3699        let mut selections = selections.iter().peekable();
3700        let mut contiguous_row_selections = Vec::new();
3701        let mut new_selections = Vec::new();
3702
3703        while let Some(selection) = selections.next() {
3704            // Find all the selections that span a contiguous row range
3705            let (start_row, end_row) = consume_contiguous_rows(
3706                &mut contiguous_row_selections,
3707                selection,
3708                &display_map,
3709                &mut selections,
3710            );
3711
3712            // Move the text spanned by the row range to be after the last line of the row range
3713            if end_row <= buffer.max_point().row {
3714                let range_to_move = Point::new(start_row, 0)..Point::new(end_row, 0);
3715                let insertion_point = display_map.next_line_boundary(Point::new(end_row, 0)).0;
3716
3717                // Don't move lines across excerpt boundaries
3718                if buffer
3719                    .excerpt_boundaries_in_range((
3720                        Bound::Excluded(range_to_move.start),
3721                        Bound::Included(insertion_point),
3722                    ))
3723                    .next()
3724                    .is_none()
3725                {
3726                    let mut text = String::from("\n");
3727                    text.extend(buffer.text_for_range(range_to_move.clone()));
3728                    text.pop(); // Drop trailing newline
3729                    edits.push((
3730                        buffer.anchor_after(range_to_move.start)
3731                            ..buffer.anchor_before(range_to_move.end),
3732                        String::new(),
3733                    ));
3734                    let insertion_anchor = buffer.anchor_after(insertion_point);
3735                    edits.push((insertion_anchor..insertion_anchor, text));
3736
3737                    let row_delta = insertion_point.row - range_to_move.end.row + 1;
3738
3739                    // Move selections down
3740                    new_selections.extend(contiguous_row_selections.drain(..).map(
3741                        |mut selection| {
3742                            selection.start.row += row_delta;
3743                            selection.end.row += row_delta;
3744                            selection
3745                        },
3746                    ));
3747
3748                    // Move folds down
3749                    unfold_ranges.push(range_to_move.clone());
3750                    for fold in display_map.folds_in_range(
3751                        buffer.anchor_before(range_to_move.start)
3752                            ..buffer.anchor_after(range_to_move.end),
3753                    ) {
3754                        let mut start = fold.start.to_point(&buffer);
3755                        let mut end = fold.end.to_point(&buffer);
3756                        start.row += row_delta;
3757                        end.row += row_delta;
3758                        refold_ranges.push(start..end);
3759                    }
3760                }
3761            }
3762
3763            // If we didn't move line(s), preserve the existing selections
3764            new_selections.append(&mut contiguous_row_selections);
3765        }
3766
3767        self.transact(cx, |this, cx| {
3768            this.unfold_ranges(unfold_ranges, true, true, cx);
3769            this.buffer.update(cx, |buffer, cx| {
3770                for (range, text) in edits {
3771                    buffer.edit([(range, text)], None, cx);
3772                }
3773            });
3774            this.fold_ranges(refold_ranges, true, cx);
3775            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(new_selections));
3776        });
3777    }
3778
3779    pub fn transpose(&mut self, _: &Transpose, cx: &mut ViewContext<Self>) {
3780        self.transact(cx, |this, cx| {
3781            let edits = this.change_selections(Some(Autoscroll::fit()), cx, |s| {
3782                let mut edits: Vec<(Range<usize>, String)> = Default::default();
3783                let line_mode = s.line_mode;
3784                s.move_with(|display_map, selection| {
3785                    if !selection.is_empty() || line_mode {
3786                        return;
3787                    }
3788
3789                    let mut head = selection.head();
3790                    let mut transpose_offset = head.to_offset(display_map, Bias::Right);
3791                    if head.column() == display_map.line_len(head.row()) {
3792                        transpose_offset = display_map
3793                            .buffer_snapshot
3794                            .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
3795                    }
3796
3797                    if transpose_offset == 0 {
3798                        return;
3799                    }
3800
3801                    *head.column_mut() += 1;
3802                    head = display_map.clip_point(head, Bias::Right);
3803                    selection.collapse_to(head, SelectionGoal::Column(head.column()));
3804
3805                    let transpose_start = display_map
3806                        .buffer_snapshot
3807                        .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
3808                    if edits.last().map_or(true, |e| e.0.end <= transpose_start) {
3809                        let transpose_end = display_map
3810                            .buffer_snapshot
3811                            .clip_offset(transpose_offset + 1, Bias::Right);
3812                        if let Some(ch) =
3813                            display_map.buffer_snapshot.chars_at(transpose_start).next()
3814                        {
3815                            edits.push((transpose_start..transpose_offset, String::new()));
3816                            edits.push((transpose_end..transpose_end, ch.to_string()));
3817                        }
3818                    }
3819                });
3820                edits
3821            });
3822            this.buffer
3823                .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
3824            let selections = this.selections.all::<usize>(cx);
3825            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
3826                s.select(selections);
3827            });
3828        });
3829    }
3830
3831    pub fn cut(&mut self, _: &Cut, cx: &mut ViewContext<Self>) {
3832        let mut text = String::new();
3833        let buffer = self.buffer.read(cx).snapshot(cx);
3834        let mut selections = self.selections.all::<Point>(cx);
3835        let mut clipboard_selections = Vec::with_capacity(selections.len());
3836        {
3837            let max_point = buffer.max_point();
3838            for selection in &mut selections {
3839                let is_entire_line = selection.is_empty() || self.selections.line_mode;
3840                if is_entire_line {
3841                    selection.start = Point::new(selection.start.row, 0);
3842                    selection.end = cmp::min(max_point, Point::new(selection.end.row + 1, 0));
3843                    selection.goal = SelectionGoal::None;
3844                }
3845                let mut len = 0;
3846                for chunk in buffer.text_for_range(selection.start..selection.end) {
3847                    text.push_str(chunk);
3848                    len += chunk.len();
3849                }
3850                clipboard_selections.push(ClipboardSelection {
3851                    len,
3852                    is_entire_line,
3853                    first_line_indent: buffer.indent_size_for_line(selection.start.row).len,
3854                });
3855            }
3856        }
3857
3858        self.transact(cx, |this, cx| {
3859            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
3860                s.select(selections);
3861            });
3862            this.insert("", cx);
3863            cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
3864        });
3865    }
3866
3867    pub fn copy(&mut self, _: &Copy, cx: &mut ViewContext<Self>) {
3868        let selections = self.selections.all::<Point>(cx);
3869        let buffer = self.buffer.read(cx).read(cx);
3870        let mut text = String::new();
3871
3872        let mut clipboard_selections = Vec::with_capacity(selections.len());
3873        {
3874            let max_point = buffer.max_point();
3875            for selection in selections.iter() {
3876                let mut start = selection.start;
3877                let mut end = selection.end;
3878                let is_entire_line = selection.is_empty() || self.selections.line_mode;
3879                if is_entire_line {
3880                    start = Point::new(start.row, 0);
3881                    end = cmp::min(max_point, Point::new(end.row + 1, 0));
3882                }
3883                let mut len = 0;
3884                for chunk in buffer.text_for_range(start..end) {
3885                    text.push_str(chunk);
3886                    len += chunk.len();
3887                }
3888                clipboard_selections.push(ClipboardSelection {
3889                    len,
3890                    is_entire_line,
3891                    first_line_indent: buffer.indent_size_for_line(start.row).len,
3892                });
3893            }
3894        }
3895
3896        cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
3897    }
3898
3899    pub fn paste(&mut self, _: &Paste, cx: &mut ViewContext<Self>) {
3900        self.transact(cx, |this, cx| {
3901            if let Some(item) = cx.as_mut().read_from_clipboard() {
3902                let mut clipboard_text = Cow::Borrowed(item.text());
3903                if let Some(mut clipboard_selections) = item.metadata::<Vec<ClipboardSelection>>() {
3904                    let old_selections = this.selections.all::<usize>(cx);
3905                    let all_selections_were_entire_line =
3906                        clipboard_selections.iter().all(|s| s.is_entire_line);
3907                    let first_selection_indent_column =
3908                        clipboard_selections.first().map(|s| s.first_line_indent);
3909                    if clipboard_selections.len() != old_selections.len() {
3910                        let mut newline_separated_text = String::new();
3911                        let mut clipboard_selections = clipboard_selections.drain(..).peekable();
3912                        let mut ix = 0;
3913                        while let Some(clipboard_selection) = clipboard_selections.next() {
3914                            newline_separated_text
3915                                .push_str(&clipboard_text[ix..ix + clipboard_selection.len]);
3916                            ix += clipboard_selection.len;
3917                            if clipboard_selections.peek().is_some() {
3918                                newline_separated_text.push('\n');
3919                            }
3920                        }
3921                        clipboard_text = Cow::Owned(newline_separated_text);
3922                    }
3923
3924                    this.buffer.update(cx, |buffer, cx| {
3925                        let snapshot = buffer.read(cx);
3926                        let mut start_offset = 0;
3927                        let mut edits = Vec::new();
3928                        let mut original_indent_columns = Vec::new();
3929                        let line_mode = this.selections.line_mode;
3930                        for (ix, selection) in old_selections.iter().enumerate() {
3931                            let to_insert;
3932                            let entire_line;
3933                            let original_indent_column;
3934                            if let Some(clipboard_selection) = clipboard_selections.get(ix) {
3935                                let end_offset = start_offset + clipboard_selection.len;
3936                                to_insert = &clipboard_text[start_offset..end_offset];
3937                                entire_line = clipboard_selection.is_entire_line;
3938                                start_offset = end_offset;
3939                                original_indent_column =
3940                                    Some(clipboard_selection.first_line_indent);
3941                            } else {
3942                                to_insert = clipboard_text.as_str();
3943                                entire_line = all_selections_were_entire_line;
3944                                original_indent_column = first_selection_indent_column
3945                            }
3946
3947                            // If the corresponding selection was empty when this slice of the
3948                            // clipboard text was written, then the entire line containing the
3949                            // selection was copied. If this selection is also currently empty,
3950                            // then paste the line before the current line of the buffer.
3951                            let range = if selection.is_empty() && !line_mode && entire_line {
3952                                let column = selection.start.to_point(&snapshot).column as usize;
3953                                let line_start = selection.start - column;
3954                                line_start..line_start
3955                            } else {
3956                                selection.range()
3957                            };
3958
3959                            edits.push((range, to_insert));
3960                            original_indent_columns.extend(original_indent_column);
3961                        }
3962                        drop(snapshot);
3963
3964                        buffer.edit(
3965                            edits,
3966                            Some(AutoindentMode::Block {
3967                                original_indent_columns,
3968                            }),
3969                            cx,
3970                        );
3971                    });
3972
3973                    let selections = this.selections.all::<usize>(cx);
3974                    this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
3975                } else {
3976                    this.insert(&clipboard_text, cx);
3977                }
3978            }
3979        });
3980    }
3981
3982    pub fn undo(&mut self, _: &Undo, cx: &mut ViewContext<Self>) {
3983        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.undo(cx)) {
3984            if let Some((selections, _)) = self.selection_history.transaction(tx_id).cloned() {
3985                self.change_selections(None, cx, |s| {
3986                    s.select_anchors(selections.to_vec());
3987                });
3988            }
3989            self.request_autoscroll(Autoscroll::fit(), cx);
3990            self.unmark_text(cx);
3991            self.refresh_copilot_suggestions(cx);
3992            cx.emit(Event::Edited);
3993        }
3994    }
3995
3996    pub fn redo(&mut self, _: &Redo, cx: &mut ViewContext<Self>) {
3997        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.redo(cx)) {
3998            if let Some((_, Some(selections))) = self.selection_history.transaction(tx_id).cloned()
3999            {
4000                self.change_selections(None, cx, |s| {
4001                    s.select_anchors(selections.to_vec());
4002                });
4003            }
4004            self.request_autoscroll(Autoscroll::fit(), cx);
4005            self.unmark_text(cx);
4006            self.refresh_copilot_suggestions(cx);
4007            cx.emit(Event::Edited);
4008        }
4009    }
4010
4011    pub fn finalize_last_transaction(&mut self, cx: &mut ViewContext<Self>) {
4012        self.buffer
4013            .update(cx, |buffer, cx| buffer.finalize_last_transaction(cx));
4014    }
4015
4016    pub fn move_left(&mut self, _: &MoveLeft, cx: &mut ViewContext<Self>) {
4017        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4018            let line_mode = s.line_mode;
4019            s.move_with(|map, selection| {
4020                let cursor = if selection.is_empty() && !line_mode {
4021                    movement::left(map, selection.start)
4022                } else {
4023                    selection.start
4024                };
4025                selection.collapse_to(cursor, SelectionGoal::None);
4026            });
4027        })
4028    }
4029
4030    pub fn select_left(&mut self, _: &SelectLeft, cx: &mut ViewContext<Self>) {
4031        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4032            s.move_heads_with(|map, head, _| (movement::left(map, head), SelectionGoal::None));
4033        })
4034    }
4035
4036    pub fn move_right(&mut self, _: &MoveRight, cx: &mut ViewContext<Self>) {
4037        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4038            let line_mode = s.line_mode;
4039            s.move_with(|map, selection| {
4040                let cursor = if selection.is_empty() && !line_mode {
4041                    movement::right(map, selection.end)
4042                } else {
4043                    selection.end
4044                };
4045                selection.collapse_to(cursor, SelectionGoal::None)
4046            });
4047        })
4048    }
4049
4050    pub fn select_right(&mut self, _: &SelectRight, cx: &mut ViewContext<Self>) {
4051        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4052            s.move_heads_with(|map, head, _| (movement::right(map, head), SelectionGoal::None));
4053        })
4054    }
4055
4056    pub fn move_up(&mut self, _: &MoveUp, cx: &mut ViewContext<Self>) {
4057        if self.take_rename(true, cx).is_some() {
4058            return;
4059        }
4060
4061        if let Some(context_menu) = self.context_menu.as_mut() {
4062            if context_menu.select_prev(cx) {
4063                return;
4064            }
4065        }
4066
4067        if matches!(self.mode, EditorMode::SingleLine) {
4068            cx.propagate_action();
4069            return;
4070        }
4071
4072        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4073            let line_mode = s.line_mode;
4074            s.move_with(|map, selection| {
4075                if !selection.is_empty() && !line_mode {
4076                    selection.goal = SelectionGoal::None;
4077                }
4078                let (cursor, goal) = movement::up(map, selection.start, selection.goal, false);
4079                selection.collapse_to(cursor, goal);
4080            });
4081        })
4082    }
4083
4084    pub fn move_page_up(&mut self, action: &MovePageUp, cx: &mut ViewContext<Self>) {
4085        if self.take_rename(true, cx).is_some() {
4086            return;
4087        }
4088
4089        if self
4090            .context_menu
4091            .as_mut()
4092            .map(|menu| menu.select_first(cx))
4093            .unwrap_or(false)
4094        {
4095            return;
4096        }
4097
4098        if matches!(self.mode, EditorMode::SingleLine) {
4099            cx.propagate_action();
4100            return;
4101        }
4102
4103        let row_count = if let Some(row_count) = self.visible_line_count() {
4104            row_count as u32 - 1
4105        } else {
4106            return;
4107        };
4108
4109        let autoscroll = if action.center_cursor {
4110            Autoscroll::center()
4111        } else {
4112            Autoscroll::fit()
4113        };
4114
4115        self.change_selections(Some(autoscroll), cx, |s| {
4116            let line_mode = s.line_mode;
4117            s.move_with(|map, selection| {
4118                if !selection.is_empty() && !line_mode {
4119                    selection.goal = SelectionGoal::None;
4120                }
4121                let (cursor, goal) =
4122                    movement::up_by_rows(map, selection.end, row_count, selection.goal, false);
4123                selection.collapse_to(cursor, goal);
4124            });
4125        });
4126    }
4127
4128    pub fn select_up(&mut self, _: &SelectUp, cx: &mut ViewContext<Self>) {
4129        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4130            s.move_heads_with(|map, head, goal| movement::up(map, head, goal, false))
4131        })
4132    }
4133
4134    pub fn move_down(&mut self, _: &MoveDown, cx: &mut ViewContext<Self>) {
4135        self.take_rename(true, cx);
4136
4137        if let Some(context_menu) = self.context_menu.as_mut() {
4138            if context_menu.select_next(cx) {
4139                return;
4140            }
4141        }
4142
4143        if self.mode == EditorMode::SingleLine {
4144            cx.propagate_action();
4145            return;
4146        }
4147
4148        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4149            let line_mode = s.line_mode;
4150            s.move_with(|map, selection| {
4151                if !selection.is_empty() && !line_mode {
4152                    selection.goal = SelectionGoal::None;
4153                }
4154                let (cursor, goal) = movement::down(map, selection.end, selection.goal, false);
4155                selection.collapse_to(cursor, goal);
4156            });
4157        });
4158    }
4159
4160    pub fn move_page_down(&mut self, action: &MovePageDown, cx: &mut ViewContext<Self>) {
4161        if self.take_rename(true, cx).is_some() {
4162            return;
4163        }
4164
4165        if self
4166            .context_menu
4167            .as_mut()
4168            .map(|menu| menu.select_last(cx))
4169            .unwrap_or(false)
4170        {
4171            return;
4172        }
4173
4174        if matches!(self.mode, EditorMode::SingleLine) {
4175            cx.propagate_action();
4176            return;
4177        }
4178
4179        let row_count = if let Some(row_count) = self.visible_line_count() {
4180            row_count as u32 - 1
4181        } else {
4182            return;
4183        };
4184
4185        let autoscroll = if action.center_cursor {
4186            Autoscroll::center()
4187        } else {
4188            Autoscroll::fit()
4189        };
4190
4191        self.change_selections(Some(autoscroll), cx, |s| {
4192            let line_mode = s.line_mode;
4193            s.move_with(|map, selection| {
4194                if !selection.is_empty() && !line_mode {
4195                    selection.goal = SelectionGoal::None;
4196                }
4197                let (cursor, goal) =
4198                    movement::down_by_rows(map, selection.end, row_count, selection.goal, false);
4199                selection.collapse_to(cursor, goal);
4200            });
4201        });
4202    }
4203
4204    pub fn select_down(&mut self, _: &SelectDown, cx: &mut ViewContext<Self>) {
4205        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4206            s.move_heads_with(|map, head, goal| movement::down(map, head, goal, false))
4207        });
4208    }
4209
4210    pub fn move_to_previous_word_start(
4211        &mut self,
4212        _: &MoveToPreviousWordStart,
4213        cx: &mut ViewContext<Self>,
4214    ) {
4215        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4216            s.move_cursors_with(|map, head, _| {
4217                (
4218                    movement::previous_word_start(map, head),
4219                    SelectionGoal::None,
4220                )
4221            });
4222        })
4223    }
4224
4225    pub fn move_to_previous_subword_start(
4226        &mut self,
4227        _: &MoveToPreviousSubwordStart,
4228        cx: &mut ViewContext<Self>,
4229    ) {
4230        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4231            s.move_cursors_with(|map, head, _| {
4232                (
4233                    movement::previous_subword_start(map, head),
4234                    SelectionGoal::None,
4235                )
4236            });
4237        })
4238    }
4239
4240    pub fn select_to_previous_word_start(
4241        &mut self,
4242        _: &SelectToPreviousWordStart,
4243        cx: &mut ViewContext<Self>,
4244    ) {
4245        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4246            s.move_heads_with(|map, head, _| {
4247                (
4248                    movement::previous_word_start(map, head),
4249                    SelectionGoal::None,
4250                )
4251            });
4252        })
4253    }
4254
4255    pub fn select_to_previous_subword_start(
4256        &mut self,
4257        _: &SelectToPreviousSubwordStart,
4258        cx: &mut ViewContext<Self>,
4259    ) {
4260        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4261            s.move_heads_with(|map, head, _| {
4262                (
4263                    movement::previous_subword_start(map, head),
4264                    SelectionGoal::None,
4265                )
4266            });
4267        })
4268    }
4269
4270    pub fn delete_to_previous_word_start(
4271        &mut self,
4272        _: &DeleteToPreviousWordStart,
4273        cx: &mut ViewContext<Self>,
4274    ) {
4275        self.transact(cx, |this, cx| {
4276            this.select_autoclose_pair(cx);
4277            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4278                let line_mode = s.line_mode;
4279                s.move_with(|map, selection| {
4280                    if selection.is_empty() && !line_mode {
4281                        let cursor = movement::previous_word_start(map, selection.head());
4282                        selection.set_head(cursor, SelectionGoal::None);
4283                    }
4284                });
4285            });
4286            this.insert("", cx);
4287        });
4288    }
4289
4290    pub fn delete_to_previous_subword_start(
4291        &mut self,
4292        _: &DeleteToPreviousSubwordStart,
4293        cx: &mut ViewContext<Self>,
4294    ) {
4295        self.transact(cx, |this, cx| {
4296            this.select_autoclose_pair(cx);
4297            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4298                let line_mode = s.line_mode;
4299                s.move_with(|map, selection| {
4300                    if selection.is_empty() && !line_mode {
4301                        let cursor = movement::previous_subword_start(map, selection.head());
4302                        selection.set_head(cursor, SelectionGoal::None);
4303                    }
4304                });
4305            });
4306            this.insert("", cx);
4307        });
4308    }
4309
4310    pub fn move_to_next_word_end(&mut self, _: &MoveToNextWordEnd, cx: &mut ViewContext<Self>) {
4311        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4312            s.move_cursors_with(|map, head, _| {
4313                (movement::next_word_end(map, head), SelectionGoal::None)
4314            });
4315        })
4316    }
4317
4318    pub fn move_to_next_subword_end(
4319        &mut self,
4320        _: &MoveToNextSubwordEnd,
4321        cx: &mut ViewContext<Self>,
4322    ) {
4323        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4324            s.move_cursors_with(|map, head, _| {
4325                (movement::next_subword_end(map, head), SelectionGoal::None)
4326            });
4327        })
4328    }
4329
4330    pub fn select_to_next_word_end(&mut self, _: &SelectToNextWordEnd, cx: &mut ViewContext<Self>) {
4331        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4332            s.move_heads_with(|map, head, _| {
4333                (movement::next_word_end(map, head), SelectionGoal::None)
4334            });
4335        })
4336    }
4337
4338    pub fn select_to_next_subword_end(
4339        &mut self,
4340        _: &SelectToNextSubwordEnd,
4341        cx: &mut ViewContext<Self>,
4342    ) {
4343        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4344            s.move_heads_with(|map, head, _| {
4345                (movement::next_subword_end(map, head), SelectionGoal::None)
4346            });
4347        })
4348    }
4349
4350    pub fn delete_to_next_word_end(&mut self, _: &DeleteToNextWordEnd, cx: &mut ViewContext<Self>) {
4351        self.transact(cx, |this, cx| {
4352            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4353                let line_mode = s.line_mode;
4354                s.move_with(|map, selection| {
4355                    if selection.is_empty() && !line_mode {
4356                        let cursor = movement::next_word_end(map, selection.head());
4357                        selection.set_head(cursor, SelectionGoal::None);
4358                    }
4359                });
4360            });
4361            this.insert("", cx);
4362        });
4363    }
4364
4365    pub fn delete_to_next_subword_end(
4366        &mut self,
4367        _: &DeleteToNextSubwordEnd,
4368        cx: &mut ViewContext<Self>,
4369    ) {
4370        self.transact(cx, |this, cx| {
4371            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4372                s.move_with(|map, selection| {
4373                    if selection.is_empty() {
4374                        let cursor = movement::next_subword_end(map, selection.head());
4375                        selection.set_head(cursor, SelectionGoal::None);
4376                    }
4377                });
4378            });
4379            this.insert("", cx);
4380        });
4381    }
4382
4383    pub fn move_to_beginning_of_line(
4384        &mut self,
4385        _: &MoveToBeginningOfLine,
4386        cx: &mut ViewContext<Self>,
4387    ) {
4388        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4389            s.move_cursors_with(|map, head, _| {
4390                (
4391                    movement::indented_line_beginning(map, head, true),
4392                    SelectionGoal::None,
4393                )
4394            });
4395        })
4396    }
4397
4398    pub fn select_to_beginning_of_line(
4399        &mut self,
4400        action: &SelectToBeginningOfLine,
4401        cx: &mut ViewContext<Self>,
4402    ) {
4403        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4404            s.move_heads_with(|map, head, _| {
4405                (
4406                    movement::indented_line_beginning(map, head, action.stop_at_soft_wraps),
4407                    SelectionGoal::None,
4408                )
4409            });
4410        });
4411    }
4412
4413    pub fn delete_to_beginning_of_line(
4414        &mut self,
4415        _: &DeleteToBeginningOfLine,
4416        cx: &mut ViewContext<Self>,
4417    ) {
4418        self.transact(cx, |this, cx| {
4419            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4420                s.move_with(|_, selection| {
4421                    selection.reversed = true;
4422                });
4423            });
4424
4425            this.select_to_beginning_of_line(
4426                &SelectToBeginningOfLine {
4427                    stop_at_soft_wraps: false,
4428                },
4429                cx,
4430            );
4431            this.backspace(&Backspace, cx);
4432        });
4433    }
4434
4435    pub fn move_to_end_of_line(&mut self, _: &MoveToEndOfLine, cx: &mut ViewContext<Self>) {
4436        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4437            s.move_cursors_with(|map, head, _| {
4438                (movement::line_end(map, head, true), SelectionGoal::None)
4439            });
4440        })
4441    }
4442
4443    pub fn select_to_end_of_line(
4444        &mut self,
4445        action: &SelectToEndOfLine,
4446        cx: &mut ViewContext<Self>,
4447    ) {
4448        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4449            s.move_heads_with(|map, head, _| {
4450                (
4451                    movement::line_end(map, head, action.stop_at_soft_wraps),
4452                    SelectionGoal::None,
4453                )
4454            });
4455        })
4456    }
4457
4458    pub fn delete_to_end_of_line(&mut self, _: &DeleteToEndOfLine, cx: &mut ViewContext<Self>) {
4459        self.transact(cx, |this, cx| {
4460            this.select_to_end_of_line(
4461                &SelectToEndOfLine {
4462                    stop_at_soft_wraps: false,
4463                },
4464                cx,
4465            );
4466            this.delete(&Delete, cx);
4467        });
4468    }
4469
4470    pub fn cut_to_end_of_line(&mut self, _: &CutToEndOfLine, cx: &mut ViewContext<Self>) {
4471        self.transact(cx, |this, cx| {
4472            this.select_to_end_of_line(
4473                &SelectToEndOfLine {
4474                    stop_at_soft_wraps: false,
4475                },
4476                cx,
4477            );
4478            this.cut(&Cut, cx);
4479        });
4480    }
4481
4482    pub fn move_to_beginning(&mut self, _: &MoveToBeginning, cx: &mut ViewContext<Self>) {
4483        if matches!(self.mode, EditorMode::SingleLine) {
4484            cx.propagate_action();
4485            return;
4486        }
4487
4488        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4489            s.select_ranges(vec![0..0]);
4490        });
4491    }
4492
4493    pub fn select_to_beginning(&mut self, _: &SelectToBeginning, cx: &mut ViewContext<Self>) {
4494        let mut selection = self.selections.last::<Point>(cx);
4495        selection.set_head(Point::zero(), SelectionGoal::None);
4496
4497        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4498            s.select(vec![selection]);
4499        });
4500    }
4501
4502    pub fn move_to_end(&mut self, _: &MoveToEnd, cx: &mut ViewContext<Self>) {
4503        if matches!(self.mode, EditorMode::SingleLine) {
4504            cx.propagate_action();
4505            return;
4506        }
4507
4508        let cursor = self.buffer.read(cx).read(cx).len();
4509        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4510            s.select_ranges(vec![cursor..cursor])
4511        });
4512    }
4513
4514    pub fn set_nav_history(&mut self, nav_history: Option<ItemNavHistory>) {
4515        self.nav_history = nav_history;
4516    }
4517
4518    pub fn nav_history(&self) -> Option<&ItemNavHistory> {
4519        self.nav_history.as_ref()
4520    }
4521
4522    fn push_to_nav_history(
4523        &self,
4524        cursor_anchor: Anchor,
4525        new_position: Option<Point>,
4526        cx: &mut ViewContext<Self>,
4527    ) {
4528        if let Some(nav_history) = &self.nav_history {
4529            let buffer = self.buffer.read(cx).read(cx);
4530            let cursor_position = cursor_anchor.to_point(&buffer);
4531            let scroll_state = self.scroll_manager.anchor();
4532            let scroll_top_row = scroll_state.top_row(&buffer);
4533            drop(buffer);
4534
4535            if let Some(new_position) = new_position {
4536                let row_delta = (new_position.row as i64 - cursor_position.row as i64).abs();
4537                if row_delta < MIN_NAVIGATION_HISTORY_ROW_DELTA {
4538                    return;
4539                }
4540            }
4541
4542            nav_history.push(
4543                Some(NavigationData {
4544                    cursor_anchor,
4545                    cursor_position,
4546                    scroll_anchor: scroll_state,
4547                    scroll_top_row,
4548                }),
4549                cx,
4550            );
4551        }
4552    }
4553
4554    pub fn select_to_end(&mut self, _: &SelectToEnd, cx: &mut ViewContext<Self>) {
4555        let buffer = self.buffer.read(cx).snapshot(cx);
4556        let mut selection = self.selections.first::<usize>(cx);
4557        selection.set_head(buffer.len(), SelectionGoal::None);
4558        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4559            s.select(vec![selection]);
4560        });
4561    }
4562
4563    pub fn select_all(&mut self, _: &SelectAll, cx: &mut ViewContext<Self>) {
4564        let end = self.buffer.read(cx).read(cx).len();
4565        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4566            s.select_ranges(vec![0..end]);
4567        });
4568    }
4569
4570    pub fn select_line(&mut self, _: &SelectLine, cx: &mut ViewContext<Self>) {
4571        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4572        let mut selections = self.selections.all::<Point>(cx);
4573        let max_point = display_map.buffer_snapshot.max_point();
4574        for selection in &mut selections {
4575            let rows = selection.spanned_rows(true, &display_map);
4576            selection.start = Point::new(rows.start, 0);
4577            selection.end = cmp::min(max_point, Point::new(rows.end, 0));
4578            selection.reversed = false;
4579        }
4580        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4581            s.select(selections);
4582        });
4583    }
4584
4585    pub fn split_selection_into_lines(
4586        &mut self,
4587        _: &SplitSelectionIntoLines,
4588        cx: &mut ViewContext<Self>,
4589    ) {
4590        let mut to_unfold = Vec::new();
4591        let mut new_selection_ranges = Vec::new();
4592        {
4593            let selections = self.selections.all::<Point>(cx);
4594            let buffer = self.buffer.read(cx).read(cx);
4595            for selection in selections {
4596                for row in selection.start.row..selection.end.row {
4597                    let cursor = Point::new(row, buffer.line_len(row));
4598                    new_selection_ranges.push(cursor..cursor);
4599                }
4600                new_selection_ranges.push(selection.end..selection.end);
4601                to_unfold.push(selection.start..selection.end);
4602            }
4603        }
4604        self.unfold_ranges(to_unfold, true, true, cx);
4605        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4606            s.select_ranges(new_selection_ranges);
4607        });
4608    }
4609
4610    pub fn add_selection_above(&mut self, _: &AddSelectionAbove, cx: &mut ViewContext<Self>) {
4611        self.add_selection(true, cx);
4612    }
4613
4614    pub fn add_selection_below(&mut self, _: &AddSelectionBelow, cx: &mut ViewContext<Self>) {
4615        self.add_selection(false, cx);
4616    }
4617
4618    fn add_selection(&mut self, above: bool, cx: &mut ViewContext<Self>) {
4619        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4620        let mut selections = self.selections.all::<Point>(cx);
4621        let mut state = self.add_selections_state.take().unwrap_or_else(|| {
4622            let oldest_selection = selections.iter().min_by_key(|s| s.id).unwrap().clone();
4623            let range = oldest_selection.display_range(&display_map).sorted();
4624            let columns = cmp::min(range.start.column(), range.end.column())
4625                ..cmp::max(range.start.column(), range.end.column());
4626
4627            selections.clear();
4628            let mut stack = Vec::new();
4629            for row in range.start.row()..=range.end.row() {
4630                if let Some(selection) = self.selections.build_columnar_selection(
4631                    &display_map,
4632                    row,
4633                    &columns,
4634                    oldest_selection.reversed,
4635                ) {
4636                    stack.push(selection.id);
4637                    selections.push(selection);
4638                }
4639            }
4640
4641            if above {
4642                stack.reverse();
4643            }
4644
4645            AddSelectionsState { above, stack }
4646        });
4647
4648        let last_added_selection = *state.stack.last().unwrap();
4649        let mut new_selections = Vec::new();
4650        if above == state.above {
4651            let end_row = if above {
4652                0
4653            } else {
4654                display_map.max_point().row()
4655            };
4656
4657            'outer: for selection in selections {
4658                if selection.id == last_added_selection {
4659                    let range = selection.display_range(&display_map).sorted();
4660                    debug_assert_eq!(range.start.row(), range.end.row());
4661                    let mut row = range.start.row();
4662                    let columns = if let SelectionGoal::ColumnRange { start, end } = selection.goal
4663                    {
4664                        start..end
4665                    } else {
4666                        cmp::min(range.start.column(), range.end.column())
4667                            ..cmp::max(range.start.column(), range.end.column())
4668                    };
4669
4670                    while row != end_row {
4671                        if above {
4672                            row -= 1;
4673                        } else {
4674                            row += 1;
4675                        }
4676
4677                        if let Some(new_selection) = self.selections.build_columnar_selection(
4678                            &display_map,
4679                            row,
4680                            &columns,
4681                            selection.reversed,
4682                        ) {
4683                            state.stack.push(new_selection.id);
4684                            if above {
4685                                new_selections.push(new_selection);
4686                                new_selections.push(selection);
4687                            } else {
4688                                new_selections.push(selection);
4689                                new_selections.push(new_selection);
4690                            }
4691
4692                            continue 'outer;
4693                        }
4694                    }
4695                }
4696
4697                new_selections.push(selection);
4698            }
4699        } else {
4700            new_selections = selections;
4701            new_selections.retain(|s| s.id != last_added_selection);
4702            state.stack.pop();
4703        }
4704
4705        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4706            s.select(new_selections);
4707        });
4708        if state.stack.len() > 1 {
4709            self.add_selections_state = Some(state);
4710        }
4711    }
4712
4713    pub fn select_next(&mut self, action: &SelectNext, cx: &mut ViewContext<Self>) {
4714        self.push_to_selection_history();
4715        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4716        let buffer = &display_map.buffer_snapshot;
4717        let mut selections = self.selections.all::<usize>(cx);
4718        if let Some(mut select_next_state) = self.select_next_state.take() {
4719            let query = &select_next_state.query;
4720            if !select_next_state.done {
4721                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
4722                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
4723                let mut next_selected_range = None;
4724
4725                let bytes_after_last_selection =
4726                    buffer.bytes_in_range(last_selection.end..buffer.len());
4727                let bytes_before_first_selection = buffer.bytes_in_range(0..first_selection.start);
4728                let query_matches = query
4729                    .stream_find_iter(bytes_after_last_selection)
4730                    .map(|result| (last_selection.end, result))
4731                    .chain(
4732                        query
4733                            .stream_find_iter(bytes_before_first_selection)
4734                            .map(|result| (0, result)),
4735                    );
4736                for (start_offset, query_match) in query_matches {
4737                    let query_match = query_match.unwrap(); // can only fail due to I/O
4738                    let offset_range =
4739                        start_offset + query_match.start()..start_offset + query_match.end();
4740                    let display_range = offset_range.start.to_display_point(&display_map)
4741                        ..offset_range.end.to_display_point(&display_map);
4742
4743                    if !select_next_state.wordwise
4744                        || (!movement::is_inside_word(&display_map, display_range.start)
4745                            && !movement::is_inside_word(&display_map, display_range.end))
4746                    {
4747                        next_selected_range = Some(offset_range);
4748                        break;
4749                    }
4750                }
4751
4752                if let Some(next_selected_range) = next_selected_range {
4753                    self.unfold_ranges([next_selected_range.clone()], false, true, cx);
4754                    self.change_selections(Some(Autoscroll::newest()), cx, |s| {
4755                        if action.replace_newest {
4756                            s.delete(s.newest_anchor().id);
4757                        }
4758                        s.insert_range(next_selected_range);
4759                    });
4760                } else {
4761                    select_next_state.done = true;
4762                }
4763            }
4764
4765            self.select_next_state = Some(select_next_state);
4766        } else if selections.len() == 1 {
4767            let selection = selections.last_mut().unwrap();
4768            if selection.start == selection.end {
4769                let word_range = movement::surrounding_word(
4770                    &display_map,
4771                    selection.start.to_display_point(&display_map),
4772                );
4773                selection.start = word_range.start.to_offset(&display_map, Bias::Left);
4774                selection.end = word_range.end.to_offset(&display_map, Bias::Left);
4775                selection.goal = SelectionGoal::None;
4776                selection.reversed = false;
4777
4778                let query = buffer
4779                    .text_for_range(selection.start..selection.end)
4780                    .collect::<String>();
4781                let select_state = SelectNextState {
4782                    query: AhoCorasick::new_auto_configured(&[query]),
4783                    wordwise: true,
4784                    done: false,
4785                };
4786                self.unfold_ranges([selection.start..selection.end], false, true, cx);
4787                self.change_selections(Some(Autoscroll::newest()), cx, |s| {
4788                    s.select(selections);
4789                });
4790                self.select_next_state = Some(select_state);
4791            } else {
4792                let query = buffer
4793                    .text_for_range(selection.start..selection.end)
4794                    .collect::<String>();
4795                self.select_next_state = Some(SelectNextState {
4796                    query: AhoCorasick::new_auto_configured(&[query]),
4797                    wordwise: false,
4798                    done: false,
4799                });
4800                self.select_next(action, cx);
4801            }
4802        }
4803    }
4804
4805    pub fn toggle_comments(&mut self, action: &ToggleComments, cx: &mut ViewContext<Self>) {
4806        self.transact(cx, |this, cx| {
4807            let mut selections = this.selections.all::<Point>(cx);
4808            let mut edits = Vec::new();
4809            let mut selection_edit_ranges = Vec::new();
4810            let mut last_toggled_row = None;
4811            let snapshot = this.buffer.read(cx).read(cx);
4812            let empty_str: Arc<str> = "".into();
4813            let mut suffixes_inserted = Vec::new();
4814
4815            fn comment_prefix_range(
4816                snapshot: &MultiBufferSnapshot,
4817                row: u32,
4818                comment_prefix: &str,
4819                comment_prefix_whitespace: &str,
4820            ) -> Range<Point> {
4821                let start = Point::new(row, snapshot.indent_size_for_line(row).len);
4822
4823                let mut line_bytes = snapshot
4824                    .bytes_in_range(start..snapshot.max_point())
4825                    .flatten()
4826                    .copied();
4827
4828                // If this line currently begins with the line comment prefix, then record
4829                // the range containing the prefix.
4830                if line_bytes
4831                    .by_ref()
4832                    .take(comment_prefix.len())
4833                    .eq(comment_prefix.bytes())
4834                {
4835                    // Include any whitespace that matches the comment prefix.
4836                    let matching_whitespace_len = line_bytes
4837                        .zip(comment_prefix_whitespace.bytes())
4838                        .take_while(|(a, b)| a == b)
4839                        .count() as u32;
4840                    let end = Point::new(
4841                        start.row,
4842                        start.column + comment_prefix.len() as u32 + matching_whitespace_len,
4843                    );
4844                    start..end
4845                } else {
4846                    start..start
4847                }
4848            }
4849
4850            fn comment_suffix_range(
4851                snapshot: &MultiBufferSnapshot,
4852                row: u32,
4853                comment_suffix: &str,
4854                comment_suffix_has_leading_space: bool,
4855            ) -> Range<Point> {
4856                let end = Point::new(row, snapshot.line_len(row));
4857                let suffix_start_column = end.column.saturating_sub(comment_suffix.len() as u32);
4858
4859                let mut line_end_bytes = snapshot
4860                    .bytes_in_range(Point::new(end.row, suffix_start_column.saturating_sub(1))..end)
4861                    .flatten()
4862                    .copied();
4863
4864                let leading_space_len = if suffix_start_column > 0
4865                    && line_end_bytes.next() == Some(b' ')
4866                    && comment_suffix_has_leading_space
4867                {
4868                    1
4869                } else {
4870                    0
4871                };
4872
4873                // If this line currently begins with the line comment prefix, then record
4874                // the range containing the prefix.
4875                if line_end_bytes.by_ref().eq(comment_suffix.bytes()) {
4876                    let start = Point::new(end.row, suffix_start_column - leading_space_len);
4877                    start..end
4878                } else {
4879                    end..end
4880                }
4881            }
4882
4883            // TODO: Handle selections that cross excerpts
4884            for selection in &mut selections {
4885                let start_column = snapshot.indent_size_for_line(selection.start.row).len;
4886                let language = if let Some(language) =
4887                    snapshot.language_scope_at(Point::new(selection.start.row, start_column))
4888                {
4889                    language
4890                } else {
4891                    continue;
4892                };
4893
4894                selection_edit_ranges.clear();
4895
4896                // If multiple selections contain a given row, avoid processing that
4897                // row more than once.
4898                let mut start_row = selection.start.row;
4899                if last_toggled_row == Some(start_row) {
4900                    start_row += 1;
4901                }
4902                let end_row =
4903                    if selection.end.row > selection.start.row && selection.end.column == 0 {
4904                        selection.end.row - 1
4905                    } else {
4906                        selection.end.row
4907                    };
4908                last_toggled_row = Some(end_row);
4909
4910                if start_row > end_row {
4911                    continue;
4912                }
4913
4914                // If the language has line comments, toggle those.
4915                if let Some(full_comment_prefix) = language.line_comment_prefix() {
4916                    // Split the comment prefix's trailing whitespace into a separate string,
4917                    // as that portion won't be used for detecting if a line is a comment.
4918                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
4919                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
4920                    let mut all_selection_lines_are_comments = true;
4921
4922                    for row in start_row..=end_row {
4923                        if snapshot.is_line_blank(row) {
4924                            continue;
4925                        }
4926
4927                        let prefix_range = comment_prefix_range(
4928                            snapshot.deref(),
4929                            row,
4930                            comment_prefix,
4931                            comment_prefix_whitespace,
4932                        );
4933                        if prefix_range.is_empty() {
4934                            all_selection_lines_are_comments = false;
4935                        }
4936                        selection_edit_ranges.push(prefix_range);
4937                    }
4938
4939                    if all_selection_lines_are_comments {
4940                        edits.extend(
4941                            selection_edit_ranges
4942                                .iter()
4943                                .cloned()
4944                                .map(|range| (range, empty_str.clone())),
4945                        );
4946                    } else {
4947                        let min_column = selection_edit_ranges
4948                            .iter()
4949                            .map(|r| r.start.column)
4950                            .min()
4951                            .unwrap_or(0);
4952                        edits.extend(selection_edit_ranges.iter().map(|range| {
4953                            let position = Point::new(range.start.row, min_column);
4954                            (position..position, full_comment_prefix.clone())
4955                        }));
4956                    }
4957                } else if let Some((full_comment_prefix, comment_suffix)) =
4958                    language.block_comment_delimiters()
4959                {
4960                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
4961                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
4962                    let prefix_range = comment_prefix_range(
4963                        snapshot.deref(),
4964                        start_row,
4965                        comment_prefix,
4966                        comment_prefix_whitespace,
4967                    );
4968                    let suffix_range = comment_suffix_range(
4969                        snapshot.deref(),
4970                        end_row,
4971                        comment_suffix.trim_start_matches(' '),
4972                        comment_suffix.starts_with(' '),
4973                    );
4974
4975                    if prefix_range.is_empty() || suffix_range.is_empty() {
4976                        edits.push((
4977                            prefix_range.start..prefix_range.start,
4978                            full_comment_prefix.clone(),
4979                        ));
4980                        edits.push((suffix_range.end..suffix_range.end, comment_suffix.clone()));
4981                        suffixes_inserted.push((end_row, comment_suffix.len()));
4982                    } else {
4983                        edits.push((prefix_range, empty_str.clone()));
4984                        edits.push((suffix_range, empty_str.clone()));
4985                    }
4986                } else {
4987                    continue;
4988                }
4989            }
4990
4991            drop(snapshot);
4992            this.buffer.update(cx, |buffer, cx| {
4993                buffer.edit(edits, None, cx);
4994            });
4995
4996            // Adjust selections so that they end before any comment suffixes that
4997            // were inserted.
4998            let mut suffixes_inserted = suffixes_inserted.into_iter().peekable();
4999            let mut selections = this.selections.all::<Point>(cx);
5000            let snapshot = this.buffer.read(cx).read(cx);
5001            for selection in &mut selections {
5002                while let Some((row, suffix_len)) = suffixes_inserted.peek().copied() {
5003                    match row.cmp(&selection.end.row) {
5004                        Ordering::Less => {
5005                            suffixes_inserted.next();
5006                            continue;
5007                        }
5008                        Ordering::Greater => break,
5009                        Ordering::Equal => {
5010                            if selection.end.column == snapshot.line_len(row) {
5011                                if selection.is_empty() {
5012                                    selection.start.column -= suffix_len as u32;
5013                                }
5014                                selection.end.column -= suffix_len as u32;
5015                            }
5016                            break;
5017                        }
5018                    }
5019                }
5020            }
5021
5022            drop(snapshot);
5023            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
5024
5025            let selections = this.selections.all::<Point>(cx);
5026            let selections_on_single_row = selections.windows(2).all(|selections| {
5027                selections[0].start.row == selections[1].start.row
5028                    && selections[0].end.row == selections[1].end.row
5029                    && selections[0].start.row == selections[0].end.row
5030            });
5031            let selections_selecting = selections
5032                .iter()
5033                .any(|selection| selection.start != selection.end);
5034            let advance_downwards = action.advance_downwards
5035                && selections_on_single_row
5036                && !selections_selecting
5037                && this.mode != EditorMode::SingleLine;
5038
5039            if advance_downwards {
5040                let snapshot = this.buffer.read(cx).snapshot(cx);
5041
5042                this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5043                    s.move_cursors_with(|display_snapshot, display_point, _| {
5044                        let mut point = display_point.to_point(display_snapshot);
5045                        point.row += 1;
5046                        point = snapshot.clip_point(point, Bias::Left);
5047                        let display_point = point.to_display_point(display_snapshot);
5048                        (display_point, SelectionGoal::Column(display_point.column()))
5049                    })
5050                });
5051            }
5052        });
5053    }
5054
5055    pub fn select_larger_syntax_node(
5056        &mut self,
5057        _: &SelectLargerSyntaxNode,
5058        cx: &mut ViewContext<Self>,
5059    ) {
5060        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5061        let buffer = self.buffer.read(cx).snapshot(cx);
5062        let old_selections = self.selections.all::<usize>(cx).into_boxed_slice();
5063
5064        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
5065        let mut selected_larger_node = false;
5066        let new_selections = old_selections
5067            .iter()
5068            .map(|selection| {
5069                let old_range = selection.start..selection.end;
5070                let mut new_range = old_range.clone();
5071                while let Some(containing_range) =
5072                    buffer.range_for_syntax_ancestor(new_range.clone())
5073                {
5074                    new_range = containing_range;
5075                    if !display_map.intersects_fold(new_range.start)
5076                        && !display_map.intersects_fold(new_range.end)
5077                    {
5078                        break;
5079                    }
5080                }
5081
5082                selected_larger_node |= new_range != old_range;
5083                Selection {
5084                    id: selection.id,
5085                    start: new_range.start,
5086                    end: new_range.end,
5087                    goal: SelectionGoal::None,
5088                    reversed: selection.reversed,
5089                }
5090            })
5091            .collect::<Vec<_>>();
5092
5093        if selected_larger_node {
5094            stack.push(old_selections);
5095            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5096                s.select(new_selections);
5097            });
5098        }
5099        self.select_larger_syntax_node_stack = stack;
5100    }
5101
5102    pub fn select_smaller_syntax_node(
5103        &mut self,
5104        _: &SelectSmallerSyntaxNode,
5105        cx: &mut ViewContext<Self>,
5106    ) {
5107        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
5108        if let Some(selections) = stack.pop() {
5109            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5110                s.select(selections.to_vec());
5111            });
5112        }
5113        self.select_larger_syntax_node_stack = stack;
5114    }
5115
5116    pub fn move_to_enclosing_bracket(
5117        &mut self,
5118        _: &MoveToEnclosingBracket,
5119        cx: &mut ViewContext<Self>,
5120    ) {
5121        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5122            s.move_offsets_with(|snapshot, selection| {
5123                let Some(enclosing_bracket_ranges) = snapshot.enclosing_bracket_ranges(selection.start..selection.end) else {
5124                    return;
5125                };
5126
5127                let mut best_length = usize::MAX;
5128                let mut best_inside = false;
5129                let mut best_in_bracket_range = false;
5130                let mut best_destination = None;
5131                for (open, close) in enclosing_bracket_ranges {
5132                    let close = close.to_inclusive();
5133                    let length = close.end() - open.start;
5134                    let inside = selection.start >= open.end && selection.end <= *close.start();
5135                    let in_bracket_range = open.to_inclusive().contains(&selection.head()) || close.contains(&selection.head());
5136
5137                    // If best is next to a bracket and current isn't, skip
5138                    if !in_bracket_range && best_in_bracket_range {
5139                        continue;
5140                    }
5141
5142                    // Prefer smaller lengths unless best is inside and current isn't
5143                    if length > best_length && (best_inside || !inside) {
5144                        continue;
5145                    }
5146
5147                    best_length = length;
5148                    best_inside = inside;
5149                    best_in_bracket_range = in_bracket_range;
5150                    best_destination = Some(if close.contains(&selection.start) && close.contains(&selection.end) {
5151                        if inside {
5152                            open.end
5153                        } else {
5154                            open.start
5155                        }
5156                    } else {
5157                        if inside {
5158                            *close.start()
5159                        } else {
5160                            *close.end()
5161                        }
5162                    });
5163                }
5164
5165                if let Some(destination) = best_destination {
5166                    selection.collapse_to(destination, SelectionGoal::None);
5167                }
5168            })
5169        });
5170    }
5171
5172    pub fn undo_selection(&mut self, _: &UndoSelection, cx: &mut ViewContext<Self>) {
5173        self.end_selection(cx);
5174        self.selection_history.mode = SelectionHistoryMode::Undoing;
5175        if let Some(entry) = self.selection_history.undo_stack.pop_back() {
5176            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
5177            self.select_next_state = entry.select_next_state;
5178            self.add_selections_state = entry.add_selections_state;
5179            self.request_autoscroll(Autoscroll::newest(), cx);
5180        }
5181        self.selection_history.mode = SelectionHistoryMode::Normal;
5182    }
5183
5184    pub fn redo_selection(&mut self, _: &RedoSelection, cx: &mut ViewContext<Self>) {
5185        self.end_selection(cx);
5186        self.selection_history.mode = SelectionHistoryMode::Redoing;
5187        if let Some(entry) = self.selection_history.redo_stack.pop_back() {
5188            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
5189            self.select_next_state = entry.select_next_state;
5190            self.add_selections_state = entry.add_selections_state;
5191            self.request_autoscroll(Autoscroll::newest(), cx);
5192        }
5193        self.selection_history.mode = SelectionHistoryMode::Normal;
5194    }
5195
5196    fn go_to_diagnostic(&mut self, _: &GoToDiagnostic, cx: &mut ViewContext<Self>) {
5197        self.go_to_diagnostic_impl(Direction::Next, cx)
5198    }
5199
5200    fn go_to_prev_diagnostic(&mut self, _: &GoToPrevDiagnostic, cx: &mut ViewContext<Self>) {
5201        self.go_to_diagnostic_impl(Direction::Prev, cx)
5202    }
5203
5204    pub fn go_to_diagnostic_impl(&mut self, direction: Direction, cx: &mut ViewContext<Self>) {
5205        let buffer = self.buffer.read(cx).snapshot(cx);
5206        let selection = self.selections.newest::<usize>(cx);
5207
5208        // If there is an active Diagnostic Popover. Jump to it's diagnostic instead.
5209        if direction == Direction::Next {
5210            if let Some(popover) = self.hover_state.diagnostic_popover.as_ref() {
5211                let (group_id, jump_to) = popover.activation_info();
5212                if self.activate_diagnostics(group_id, cx) {
5213                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5214                        let mut new_selection = s.newest_anchor().clone();
5215                        new_selection.collapse_to(jump_to, SelectionGoal::None);
5216                        s.select_anchors(vec![new_selection.clone()]);
5217                    });
5218                }
5219                return;
5220            }
5221        }
5222
5223        let mut active_primary_range = self.active_diagnostics.as_ref().map(|active_diagnostics| {
5224            active_diagnostics
5225                .primary_range
5226                .to_offset(&buffer)
5227                .to_inclusive()
5228        });
5229        let mut search_start = if let Some(active_primary_range) = active_primary_range.as_ref() {
5230            if active_primary_range.contains(&selection.head()) {
5231                *active_primary_range.end()
5232            } else {
5233                selection.head()
5234            }
5235        } else {
5236            selection.head()
5237        };
5238
5239        loop {
5240            let mut diagnostics = if direction == Direction::Prev {
5241                buffer.diagnostics_in_range::<_, usize>(0..search_start, true)
5242            } else {
5243                buffer.diagnostics_in_range::<_, usize>(search_start..buffer.len(), false)
5244            };
5245            let group = diagnostics.find_map(|entry| {
5246                if entry.diagnostic.is_primary
5247                    && entry.diagnostic.severity <= DiagnosticSeverity::WARNING
5248                    && !entry.range.is_empty()
5249                    && Some(entry.range.end) != active_primary_range.as_ref().map(|r| *r.end())
5250                {
5251                    Some((entry.range, entry.diagnostic.group_id))
5252                } else {
5253                    None
5254                }
5255            });
5256
5257            if let Some((primary_range, group_id)) = group {
5258                if self.activate_diagnostics(group_id, cx) {
5259                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5260                        s.select(vec![Selection {
5261                            id: selection.id,
5262                            start: primary_range.start,
5263                            end: primary_range.start,
5264                            reversed: false,
5265                            goal: SelectionGoal::None,
5266                        }]);
5267                    });
5268                }
5269                break;
5270            } else {
5271                // Cycle around to the start of the buffer, potentially moving back to the start of
5272                // the currently active diagnostic.
5273                active_primary_range.take();
5274                if direction == Direction::Prev {
5275                    if search_start == buffer.len() {
5276                        break;
5277                    } else {
5278                        search_start = buffer.len();
5279                    }
5280                } else if search_start == 0 {
5281                    break;
5282                } else {
5283                    search_start = 0;
5284                }
5285            }
5286        }
5287    }
5288
5289    fn go_to_hunk(&mut self, _: &GoToHunk, cx: &mut ViewContext<Self>) {
5290        self.go_to_hunk_impl(Direction::Next, cx)
5291    }
5292
5293    fn go_to_prev_hunk(&mut self, _: &GoToPrevHunk, cx: &mut ViewContext<Self>) {
5294        self.go_to_hunk_impl(Direction::Prev, cx)
5295    }
5296
5297    pub fn go_to_hunk_impl(&mut self, direction: Direction, cx: &mut ViewContext<Self>) {
5298        let snapshot = self
5299            .display_map
5300            .update(cx, |display_map, cx| display_map.snapshot(cx));
5301        let selection = self.selections.newest::<Point>(cx);
5302
5303        fn seek_in_direction(
5304            this: &mut Editor,
5305            snapshot: &DisplaySnapshot,
5306            initial_point: Point,
5307            is_wrapped: bool,
5308            direction: Direction,
5309            cx: &mut ViewContext<Editor>,
5310        ) -> bool {
5311            let hunks = if direction == Direction::Next {
5312                snapshot
5313                    .buffer_snapshot
5314                    .git_diff_hunks_in_range(initial_point.row..u32::MAX, false)
5315            } else {
5316                snapshot
5317                    .buffer_snapshot
5318                    .git_diff_hunks_in_range(0..initial_point.row, true)
5319            };
5320
5321            let display_point = initial_point.to_display_point(snapshot);
5322            let mut hunks = hunks
5323                .map(|hunk| diff_hunk_to_display(hunk, &snapshot))
5324                .skip_while(|hunk| {
5325                    if is_wrapped {
5326                        false
5327                    } else {
5328                        hunk.contains_display_row(display_point.row())
5329                    }
5330                })
5331                .dedup();
5332
5333            if let Some(hunk) = hunks.next() {
5334                this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5335                    let row = hunk.start_display_row();
5336                    let point = DisplayPoint::new(row, 0);
5337                    s.select_display_ranges([point..point]);
5338                });
5339
5340                true
5341            } else {
5342                false
5343            }
5344        }
5345
5346        if !seek_in_direction(self, &snapshot, selection.head(), false, direction, cx) {
5347            let wrapped_point = match direction {
5348                Direction::Next => Point::zero(),
5349                Direction::Prev => snapshot.buffer_snapshot.max_point(),
5350            };
5351            seek_in_direction(self, &snapshot, wrapped_point, true, direction, cx);
5352        }
5353    }
5354
5355    pub fn go_to_definition(
5356        workspace: &mut Workspace,
5357        _: &GoToDefinition,
5358        cx: &mut ViewContext<Workspace>,
5359    ) {
5360        Self::go_to_definition_of_kind(GotoDefinitionKind::Symbol, workspace, cx);
5361    }
5362
5363    pub fn go_to_type_definition(
5364        workspace: &mut Workspace,
5365        _: &GoToTypeDefinition,
5366        cx: &mut ViewContext<Workspace>,
5367    ) {
5368        Self::go_to_definition_of_kind(GotoDefinitionKind::Type, workspace, cx);
5369    }
5370
5371    fn go_to_definition_of_kind(
5372        kind: GotoDefinitionKind,
5373        workspace: &mut Workspace,
5374        cx: &mut ViewContext<Workspace>,
5375    ) {
5376        let active_item = workspace.active_item(cx);
5377        let editor_handle = if let Some(editor) = active_item
5378            .as_ref()
5379            .and_then(|item| item.act_as::<Self>(cx))
5380        {
5381            editor
5382        } else {
5383            return;
5384        };
5385
5386        let editor = editor_handle.read(cx);
5387        let buffer = editor.buffer.read(cx);
5388        let head = editor.selections.newest::<usize>(cx).head();
5389        let (buffer, head) = if let Some(text_anchor) = buffer.text_anchor_for_position(head, cx) {
5390            text_anchor
5391        } else {
5392            return;
5393        };
5394
5395        let project = workspace.project().clone();
5396        let definitions = project.update(cx, |project, cx| match kind {
5397            GotoDefinitionKind::Symbol => project.definition(&buffer, head, cx),
5398            GotoDefinitionKind::Type => project.type_definition(&buffer, head, cx),
5399        });
5400
5401        cx.spawn_labeled("Fetching Definition...", |workspace, mut cx| async move {
5402            let definitions = definitions.await?;
5403            workspace.update(&mut cx, |workspace, cx| {
5404                Editor::navigate_to_definitions(workspace, editor_handle, definitions, cx);
5405            });
5406
5407            Ok::<(), anyhow::Error>(())
5408        })
5409        .detach_and_log_err(cx);
5410    }
5411
5412    pub fn navigate_to_definitions(
5413        workspace: &mut Workspace,
5414        editor_handle: ViewHandle<Editor>,
5415        definitions: Vec<LocationLink>,
5416        cx: &mut ViewContext<Workspace>,
5417    ) {
5418        let pane = workspace.active_pane().clone();
5419        // If there is one definition, just open it directly
5420        if let [definition] = definitions.as_slice() {
5421            let range = definition
5422                .target
5423                .range
5424                .to_offset(definition.target.buffer.read(cx));
5425
5426            let target_editor_handle =
5427                workspace.open_project_item(definition.target.buffer.clone(), cx);
5428            target_editor_handle.update(cx, |target_editor, cx| {
5429                // When selecting a definition in a different buffer, disable the nav history
5430                // to avoid creating a history entry at the previous cursor location.
5431                if editor_handle != target_editor_handle {
5432                    pane.update(cx, |pane, _| pane.disable_history());
5433                }
5434                target_editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
5435                    s.select_ranges([range]);
5436                });
5437
5438                pane.update(cx, |pane, _| pane.enable_history());
5439            });
5440        } else if !definitions.is_empty() {
5441            let replica_id = editor_handle.read(cx).replica_id(cx);
5442            let title = definitions
5443                .iter()
5444                .find(|definition| definition.origin.is_some())
5445                .and_then(|definition| {
5446                    definition.origin.as_ref().map(|origin| {
5447                        let buffer = origin.buffer.read(cx);
5448                        format!(
5449                            "Definitions for {}",
5450                            buffer
5451                                .text_for_range(origin.range.clone())
5452                                .collect::<String>()
5453                        )
5454                    })
5455                })
5456                .unwrap_or("Definitions".to_owned());
5457            let locations = definitions
5458                .into_iter()
5459                .map(|definition| definition.target)
5460                .collect();
5461            Self::open_locations_in_multibuffer(workspace, locations, replica_id, title, cx)
5462        }
5463    }
5464
5465    pub fn find_all_references(
5466        workspace: &mut Workspace,
5467        _: &FindAllReferences,
5468        cx: &mut ViewContext<Workspace>,
5469    ) -> Option<Task<Result<()>>> {
5470        let active_item = workspace.active_item(cx)?;
5471        let editor_handle = active_item.act_as::<Self>(cx)?;
5472
5473        let editor = editor_handle.read(cx);
5474        let buffer = editor.buffer.read(cx);
5475        let head = editor.selections.newest::<usize>(cx).head();
5476        let (buffer, head) = buffer.text_anchor_for_position(head, cx)?;
5477        let replica_id = editor.replica_id(cx);
5478
5479        let project = workspace.project().clone();
5480        let references = project.update(cx, |project, cx| project.references(&buffer, head, cx));
5481        Some(cx.spawn_labeled(
5482            "Finding All References...",
5483            |workspace, mut cx| async move {
5484                let locations = references.await?;
5485                if locations.is_empty() {
5486                    return Ok(());
5487                }
5488
5489                workspace.update(&mut cx, |workspace, cx| {
5490                    let title = locations
5491                        .first()
5492                        .as_ref()
5493                        .map(|location| {
5494                            let buffer = location.buffer.read(cx);
5495                            format!(
5496                                "References to `{}`",
5497                                buffer
5498                                    .text_for_range(location.range.clone())
5499                                    .collect::<String>()
5500                            )
5501                        })
5502                        .unwrap();
5503                    Self::open_locations_in_multibuffer(
5504                        workspace, locations, replica_id, title, cx,
5505                    );
5506                });
5507
5508                Ok(())
5509            },
5510        ))
5511    }
5512
5513    /// Opens a multibuffer with the given project locations in it
5514    pub fn open_locations_in_multibuffer(
5515        workspace: &mut Workspace,
5516        mut locations: Vec<Location>,
5517        replica_id: ReplicaId,
5518        title: String,
5519        cx: &mut ViewContext<Workspace>,
5520    ) {
5521        // If there are multiple definitions, open them in a multibuffer
5522        locations.sort_by_key(|location| location.buffer.id());
5523        let mut locations = locations.into_iter().peekable();
5524        let mut ranges_to_highlight = Vec::new();
5525
5526        let excerpt_buffer = cx.add_model(|cx| {
5527            let mut multibuffer = MultiBuffer::new(replica_id);
5528            while let Some(location) = locations.next() {
5529                let buffer = location.buffer.read(cx);
5530                let mut ranges_for_buffer = Vec::new();
5531                let range = location.range.to_offset(buffer);
5532                ranges_for_buffer.push(range.clone());
5533
5534                while let Some(next_location) = locations.peek() {
5535                    if next_location.buffer == location.buffer {
5536                        ranges_for_buffer.push(next_location.range.to_offset(buffer));
5537                        locations.next();
5538                    } else {
5539                        break;
5540                    }
5541                }
5542
5543                ranges_for_buffer.sort_by_key(|range| (range.start, Reverse(range.end)));
5544                ranges_to_highlight.extend(multibuffer.push_excerpts_with_context_lines(
5545                    location.buffer.clone(),
5546                    ranges_for_buffer,
5547                    1,
5548                    cx,
5549                ))
5550            }
5551
5552            multibuffer.with_title(title)
5553        });
5554
5555        let editor = cx.add_view(|cx| {
5556            Editor::for_multibuffer(excerpt_buffer, Some(workspace.project().clone()), cx)
5557        });
5558        editor.update(cx, |editor, cx| {
5559            editor.highlight_background::<Self>(
5560                ranges_to_highlight,
5561                |theme| theme.editor.highlighted_line_background,
5562                cx,
5563            );
5564        });
5565        workspace.add_item(Box::new(editor), cx);
5566    }
5567
5568    pub fn rename(&mut self, _: &Rename, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
5569        use language::ToOffset as _;
5570
5571        let project = self.project.clone()?;
5572        let selection = self.selections.newest_anchor().clone();
5573        let (cursor_buffer, cursor_buffer_position) = self
5574            .buffer
5575            .read(cx)
5576            .text_anchor_for_position(selection.head(), cx)?;
5577        let (tail_buffer, _) = self
5578            .buffer
5579            .read(cx)
5580            .text_anchor_for_position(selection.tail(), cx)?;
5581        if tail_buffer != cursor_buffer {
5582            return None;
5583        }
5584
5585        let snapshot = cursor_buffer.read(cx).snapshot();
5586        let cursor_buffer_offset = cursor_buffer_position.to_offset(&snapshot);
5587        let prepare_rename = project.update(cx, |project, cx| {
5588            project.prepare_rename(cursor_buffer, cursor_buffer_offset, cx)
5589        });
5590
5591        Some(cx.spawn(|this, mut cx| async move {
5592            let rename_range = if let Some(range) = prepare_rename.await? {
5593                Some(range)
5594            } else {
5595                this.read_with(&cx, |this, cx| {
5596                    let buffer = this.buffer.read(cx).snapshot(cx);
5597                    let mut buffer_highlights = this
5598                        .document_highlights_for_position(selection.head(), &buffer)
5599                        .filter(|highlight| {
5600                            highlight.start.excerpt_id() == selection.head().excerpt_id()
5601                                && highlight.end.excerpt_id() == selection.head().excerpt_id()
5602                        });
5603                    buffer_highlights
5604                        .next()
5605                        .map(|highlight| highlight.start.text_anchor..highlight.end.text_anchor)
5606                })
5607            };
5608            if let Some(rename_range) = rename_range {
5609                let rename_buffer_range = rename_range.to_offset(&snapshot);
5610                let cursor_offset_in_rename_range =
5611                    cursor_buffer_offset.saturating_sub(rename_buffer_range.start);
5612
5613                this.update(&mut cx, |this, cx| {
5614                    this.take_rename(false, cx);
5615                    let style = this.style(cx);
5616                    let buffer = this.buffer.read(cx).read(cx);
5617                    let cursor_offset = selection.head().to_offset(&buffer);
5618                    let rename_start = cursor_offset.saturating_sub(cursor_offset_in_rename_range);
5619                    let rename_end = rename_start + rename_buffer_range.len();
5620                    let range = buffer.anchor_before(rename_start)..buffer.anchor_after(rename_end);
5621                    let mut old_highlight_id = None;
5622                    let old_name: Arc<str> = buffer
5623                        .chunks(rename_start..rename_end, true)
5624                        .map(|chunk| {
5625                            if old_highlight_id.is_none() {
5626                                old_highlight_id = chunk.syntax_highlight_id;
5627                            }
5628                            chunk.text
5629                        })
5630                        .collect::<String>()
5631                        .into();
5632
5633                    drop(buffer);
5634
5635                    // Position the selection in the rename editor so that it matches the current selection.
5636                    this.show_local_selections = false;
5637                    let rename_editor = cx.add_view(|cx| {
5638                        let mut editor = Editor::single_line(None, cx);
5639                        if let Some(old_highlight_id) = old_highlight_id {
5640                            editor.override_text_style =
5641                                Some(Box::new(move |style| old_highlight_id.style(&style.syntax)));
5642                        }
5643                        editor.buffer.update(cx, |buffer, cx| {
5644                            buffer.edit([(0..0, old_name.clone())], None, cx)
5645                        });
5646                        editor.select_all(&SelectAll, cx);
5647                        editor
5648                    });
5649
5650                    let ranges = this
5651                        .clear_background_highlights::<DocumentHighlightWrite>(cx)
5652                        .into_iter()
5653                        .flat_map(|(_, ranges)| ranges)
5654                        .chain(
5655                            this.clear_background_highlights::<DocumentHighlightRead>(cx)
5656                                .into_iter()
5657                                .flat_map(|(_, ranges)| ranges),
5658                        )
5659                        .collect();
5660
5661                    this.highlight_text::<Rename>(
5662                        ranges,
5663                        HighlightStyle {
5664                            fade_out: Some(style.rename_fade),
5665                            ..Default::default()
5666                        },
5667                        cx,
5668                    );
5669                    cx.focus(&rename_editor);
5670                    let block_id = this.insert_blocks(
5671                        [BlockProperties {
5672                            style: BlockStyle::Flex,
5673                            position: range.start.clone(),
5674                            height: 1,
5675                            render: Arc::new({
5676                                let editor = rename_editor.clone();
5677                                move |cx: &mut BlockContext| {
5678                                    ChildView::new(&editor, cx)
5679                                        .contained()
5680                                        .with_padding_left(cx.anchor_x)
5681                                        .boxed()
5682                                }
5683                            }),
5684                            disposition: BlockDisposition::Below,
5685                        }],
5686                        cx,
5687                    )[0];
5688                    this.pending_rename = Some(RenameState {
5689                        range,
5690                        old_name,
5691                        editor: rename_editor,
5692                        block_id,
5693                    });
5694                });
5695            }
5696
5697            Ok(())
5698        }))
5699    }
5700
5701    pub fn confirm_rename(
5702        workspace: &mut Workspace,
5703        _: &ConfirmRename,
5704        cx: &mut ViewContext<Workspace>,
5705    ) -> Option<Task<Result<()>>> {
5706        let editor = workspace.active_item(cx)?.act_as::<Editor>(cx)?;
5707
5708        let (buffer, range, old_name, new_name) = editor.update(cx, |editor, cx| {
5709            let rename = editor.take_rename(false, cx)?;
5710            let buffer = editor.buffer.read(cx);
5711            let (start_buffer, start) =
5712                buffer.text_anchor_for_position(rename.range.start.clone(), cx)?;
5713            let (end_buffer, end) =
5714                buffer.text_anchor_for_position(rename.range.end.clone(), cx)?;
5715            if start_buffer == end_buffer {
5716                let new_name = rename.editor.read(cx).text(cx);
5717                Some((start_buffer, start..end, rename.old_name, new_name))
5718            } else {
5719                None
5720            }
5721        })?;
5722
5723        let rename = workspace.project().clone().update(cx, |project, cx| {
5724            project.perform_rename(buffer.clone(), range.start, new_name.clone(), true, cx)
5725        });
5726
5727        Some(cx.spawn(|workspace, mut cx| async move {
5728            let project_transaction = rename.await?;
5729            Self::open_project_transaction(
5730                editor.clone(),
5731                workspace,
5732                project_transaction,
5733                format!("Rename: {}{}", old_name, new_name),
5734                cx.clone(),
5735            )
5736            .await?;
5737
5738            editor.update(&mut cx, |editor, cx| {
5739                editor.refresh_document_highlights(cx);
5740            });
5741            Ok(())
5742        }))
5743    }
5744
5745    fn take_rename(
5746        &mut self,
5747        moving_cursor: bool,
5748        cx: &mut ViewContext<Self>,
5749    ) -> Option<RenameState> {
5750        let rename = self.pending_rename.take()?;
5751        self.remove_blocks([rename.block_id].into_iter().collect(), cx);
5752        self.clear_text_highlights::<Rename>(cx);
5753        self.show_local_selections = true;
5754
5755        if moving_cursor {
5756            let rename_editor = rename.editor.read(cx);
5757            let cursor_in_rename_editor = rename_editor.selections.newest::<usize>(cx).head();
5758
5759            // Update the selection to match the position of the selection inside
5760            // the rename editor.
5761            let snapshot = self.buffer.read(cx).read(cx);
5762            let rename_range = rename.range.to_offset(&snapshot);
5763            let cursor_in_editor = snapshot
5764                .clip_offset(rename_range.start + cursor_in_rename_editor, Bias::Left)
5765                .min(rename_range.end);
5766            drop(snapshot);
5767
5768            self.change_selections(None, cx, |s| {
5769                s.select_ranges(vec![cursor_in_editor..cursor_in_editor])
5770            });
5771        } else {
5772            self.refresh_document_highlights(cx);
5773        }
5774
5775        Some(rename)
5776    }
5777
5778    #[cfg(any(test, feature = "test-support"))]
5779    pub fn pending_rename(&self) -> Option<&RenameState> {
5780        self.pending_rename.as_ref()
5781    }
5782
5783    fn format(&mut self, _: &Format, cx: &mut ViewContext<'_, Self>) -> Option<Task<Result<()>>> {
5784        let project = match &self.project {
5785            Some(project) => project.clone(),
5786            None => return None,
5787        };
5788
5789        Some(self.perform_format(project, FormatTrigger::Manual, cx))
5790    }
5791
5792    fn perform_format(
5793        &mut self,
5794        project: ModelHandle<Project>,
5795        trigger: FormatTrigger,
5796        cx: &mut ViewContext<'_, Self>,
5797    ) -> Task<Result<()>> {
5798        let buffer = self.buffer().clone();
5799        let buffers = buffer.read(cx).all_buffers();
5800
5801        let mut timeout = cx.background().timer(FORMAT_TIMEOUT).fuse();
5802        let format = project.update(cx, |project, cx| project.format(buffers, true, trigger, cx));
5803
5804        cx.spawn(|_, mut cx| async move {
5805            let transaction = futures::select_biased! {
5806                _ = timeout => {
5807                    log::warn!("timed out waiting for formatting");
5808                    None
5809                }
5810                transaction = format.log_err().fuse() => transaction,
5811            };
5812
5813            buffer.update(&mut cx, |buffer, cx| {
5814                if let Some(transaction) = transaction {
5815                    if !buffer.is_singleton() {
5816                        buffer.push_transaction(&transaction.0);
5817                    }
5818                }
5819
5820                cx.notify();
5821            });
5822
5823            Ok(())
5824        })
5825    }
5826
5827    fn restart_language_server(&mut self, _: &RestartLanguageServer, cx: &mut ViewContext<Self>) {
5828        if let Some(project) = self.project.clone() {
5829            self.buffer.update(cx, |multi_buffer, cx| {
5830                project.update(cx, |project, cx| {
5831                    project.restart_language_servers_for_buffers(multi_buffer.all_buffers(), cx);
5832                });
5833            })
5834        }
5835    }
5836
5837    fn show_character_palette(&mut self, _: &ShowCharacterPalette, cx: &mut ViewContext<Self>) {
5838        cx.show_character_palette();
5839    }
5840
5841    fn refresh_active_diagnostics(&mut self, cx: &mut ViewContext<Editor>) {
5842        if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
5843            let buffer = self.buffer.read(cx).snapshot(cx);
5844            let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
5845            let is_valid = buffer
5846                .diagnostics_in_range::<_, usize>(active_diagnostics.primary_range.clone(), false)
5847                .any(|entry| {
5848                    entry.diagnostic.is_primary
5849                        && !entry.range.is_empty()
5850                        && entry.range.start == primary_range_start
5851                        && entry.diagnostic.message == active_diagnostics.primary_message
5852                });
5853
5854            if is_valid != active_diagnostics.is_valid {
5855                active_diagnostics.is_valid = is_valid;
5856                let mut new_styles = HashMap::default();
5857                for (block_id, diagnostic) in &active_diagnostics.blocks {
5858                    new_styles.insert(
5859                        *block_id,
5860                        diagnostic_block_renderer(diagnostic.clone(), is_valid),
5861                    );
5862                }
5863                self.display_map
5864                    .update(cx, |display_map, _| display_map.replace_blocks(new_styles));
5865            }
5866        }
5867    }
5868
5869    fn activate_diagnostics(&mut self, group_id: usize, cx: &mut ViewContext<Self>) -> bool {
5870        self.dismiss_diagnostics(cx);
5871        self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
5872            let buffer = self.buffer.read(cx).snapshot(cx);
5873
5874            let mut primary_range = None;
5875            let mut primary_message = None;
5876            let mut group_end = Point::zero();
5877            let diagnostic_group = buffer
5878                .diagnostic_group::<Point>(group_id)
5879                .map(|entry| {
5880                    if entry.range.end > group_end {
5881                        group_end = entry.range.end;
5882                    }
5883                    if entry.diagnostic.is_primary {
5884                        primary_range = Some(entry.range.clone());
5885                        primary_message = Some(entry.diagnostic.message.clone());
5886                    }
5887                    entry
5888                })
5889                .collect::<Vec<_>>();
5890            let primary_range = primary_range?;
5891            let primary_message = primary_message?;
5892            let primary_range =
5893                buffer.anchor_after(primary_range.start)..buffer.anchor_before(primary_range.end);
5894
5895            let blocks = display_map
5896                .insert_blocks(
5897                    diagnostic_group.iter().map(|entry| {
5898                        let diagnostic = entry.diagnostic.clone();
5899                        let message_height = diagnostic.message.lines().count() as u8;
5900                        BlockProperties {
5901                            style: BlockStyle::Fixed,
5902                            position: buffer.anchor_after(entry.range.start),
5903                            height: message_height,
5904                            render: diagnostic_block_renderer(diagnostic, true),
5905                            disposition: BlockDisposition::Below,
5906                        }
5907                    }),
5908                    cx,
5909                )
5910                .into_iter()
5911                .zip(diagnostic_group.into_iter().map(|entry| entry.diagnostic))
5912                .collect();
5913
5914            Some(ActiveDiagnosticGroup {
5915                primary_range,
5916                primary_message,
5917                blocks,
5918                is_valid: true,
5919            })
5920        });
5921        self.active_diagnostics.is_some()
5922    }
5923
5924    fn dismiss_diagnostics(&mut self, cx: &mut ViewContext<Self>) {
5925        if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
5926            self.display_map.update(cx, |display_map, cx| {
5927                display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx);
5928            });
5929            cx.notify();
5930        }
5931    }
5932
5933    pub fn set_selections_from_remote(
5934        &mut self,
5935        selections: Vec<Selection<Anchor>>,
5936        pending_selection: Option<Selection<Anchor>>,
5937        cx: &mut ViewContext<Self>,
5938    ) {
5939        let old_cursor_position = self.selections.newest_anchor().head();
5940        self.selections.change_with(cx, |s| {
5941            s.select_anchors(selections);
5942            if let Some(pending_selection) = pending_selection {
5943                s.set_pending(pending_selection, SelectMode::Character);
5944            } else {
5945                s.clear_pending();
5946            }
5947        });
5948        self.selections_did_change(false, &old_cursor_position, cx);
5949    }
5950
5951    fn push_to_selection_history(&mut self) {
5952        self.selection_history.push(SelectionHistoryEntry {
5953            selections: self.selections.disjoint_anchors(),
5954            select_next_state: self.select_next_state.clone(),
5955            add_selections_state: self.add_selections_state.clone(),
5956        });
5957    }
5958
5959    pub fn transact(
5960        &mut self,
5961        cx: &mut ViewContext<Self>,
5962        update: impl FnOnce(&mut Self, &mut ViewContext<Self>),
5963    ) -> Option<TransactionId> {
5964        self.start_transaction_at(Instant::now(), cx);
5965        update(self, cx);
5966        self.end_transaction_at(Instant::now(), cx)
5967    }
5968
5969    fn start_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
5970        self.end_selection(cx);
5971        if let Some(tx_id) = self
5972            .buffer
5973            .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx))
5974        {
5975            self.selection_history
5976                .insert_transaction(tx_id, self.selections.disjoint_anchors());
5977        }
5978    }
5979
5980    fn end_transaction_at(
5981        &mut self,
5982        now: Instant,
5983        cx: &mut ViewContext<Self>,
5984    ) -> Option<TransactionId> {
5985        if let Some(tx_id) = self
5986            .buffer
5987            .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
5988        {
5989            if let Some((_, end_selections)) = self.selection_history.transaction_mut(tx_id) {
5990                *end_selections = Some(self.selections.disjoint_anchors());
5991            } else {
5992                log::error!("unexpectedly ended a transaction that wasn't started by this editor");
5993            }
5994
5995            cx.emit(Event::Edited);
5996            Some(tx_id)
5997        } else {
5998            None
5999        }
6000    }
6001
6002    pub fn fold(&mut self, _: &Fold, cx: &mut ViewContext<Self>) {
6003        let mut fold_ranges = Vec::new();
6004
6005        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6006
6007        let selections = self.selections.all::<Point>(cx);
6008        for selection in selections {
6009            let range = selection.range().sorted();
6010            let buffer_start_row = range.start.row;
6011
6012            for row in (0..=range.end.row).rev() {
6013                let fold_range = display_map.foldable_range(row);
6014
6015                if let Some(fold_range) = fold_range {
6016                    if fold_range.end.row >= buffer_start_row {
6017                        fold_ranges.push(fold_range);
6018                        if row <= range.start.row {
6019                            break;
6020                        }
6021                    }
6022                }
6023            }
6024        }
6025
6026        self.fold_ranges(fold_ranges, true, cx);
6027    }
6028
6029    pub fn fold_at(&mut self, fold_at: &FoldAt, cx: &mut ViewContext<Self>) {
6030        let buffer_row = fold_at.buffer_row;
6031        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6032
6033        if let Some(fold_range) = display_map.foldable_range(buffer_row) {
6034            let autoscroll = self
6035                .selections
6036                .all::<Point>(cx)
6037                .iter()
6038                .any(|selection| fold_range.overlaps(&selection.range()));
6039
6040            self.fold_ranges(std::iter::once(fold_range), autoscroll, cx);
6041        }
6042    }
6043
6044    pub fn unfold_lines(&mut self, _: &UnfoldLines, cx: &mut ViewContext<Self>) {
6045        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6046        let buffer = &display_map.buffer_snapshot;
6047        let selections = self.selections.all::<Point>(cx);
6048        let ranges = selections
6049            .iter()
6050            .map(|s| {
6051                let range = s.display_range(&display_map).sorted();
6052                let mut start = range.start.to_point(&display_map);
6053                let mut end = range.end.to_point(&display_map);
6054                start.column = 0;
6055                end.column = buffer.line_len(end.row);
6056                start..end
6057            })
6058            .collect::<Vec<_>>();
6059
6060        self.unfold_ranges(ranges, true, true, cx);
6061    }
6062
6063    pub fn unfold_at(&mut self, unfold_at: &UnfoldAt, cx: &mut ViewContext<Self>) {
6064        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6065
6066        let intersection_range = Point::new(unfold_at.buffer_row, 0)
6067            ..Point::new(
6068                unfold_at.buffer_row,
6069                display_map.buffer_snapshot.line_len(unfold_at.buffer_row),
6070            );
6071
6072        let autoscroll = self
6073            .selections
6074            .all::<Point>(cx)
6075            .iter()
6076            .any(|selection| selection.range().overlaps(&intersection_range));
6077
6078        self.unfold_ranges(std::iter::once(intersection_range), true, autoscroll, cx)
6079    }
6080
6081    pub fn fold_selected_ranges(&mut self, _: &FoldSelectedRanges, cx: &mut ViewContext<Self>) {
6082        let selections = self.selections.all::<Point>(cx);
6083        let ranges = selections.into_iter().map(|s| s.start..s.end);
6084        self.fold_ranges(ranges, true, cx);
6085    }
6086
6087    pub fn fold_ranges<T: ToOffset + Clone>(
6088        &mut self,
6089        ranges: impl IntoIterator<Item = Range<T>>,
6090        auto_scroll: bool,
6091        cx: &mut ViewContext<Self>,
6092    ) {
6093        let mut ranges = ranges.into_iter().peekable();
6094        if ranges.peek().is_some() {
6095            self.display_map.update(cx, |map, cx| map.fold(ranges, cx));
6096
6097            if auto_scroll {
6098                self.request_autoscroll(Autoscroll::fit(), cx);
6099            }
6100
6101            cx.notify();
6102        }
6103    }
6104
6105    pub fn unfold_ranges<T: ToOffset + Clone>(
6106        &mut self,
6107        ranges: impl IntoIterator<Item = Range<T>>,
6108        inclusive: bool,
6109        auto_scroll: bool,
6110        cx: &mut ViewContext<Self>,
6111    ) {
6112        let mut ranges = ranges.into_iter().peekable();
6113        if ranges.peek().is_some() {
6114            self.display_map
6115                .update(cx, |map, cx| map.unfold(ranges, inclusive, cx));
6116            if auto_scroll {
6117                self.request_autoscroll(Autoscroll::fit(), cx);
6118            }
6119
6120            cx.notify();
6121        }
6122    }
6123
6124    pub fn gutter_hover(
6125        &mut self,
6126        GutterHover { hovered }: &GutterHover,
6127        cx: &mut ViewContext<Self>,
6128    ) {
6129        self.gutter_hovered = *hovered;
6130        cx.notify();
6131    }
6132
6133    pub fn insert_blocks(
6134        &mut self,
6135        blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
6136        cx: &mut ViewContext<Self>,
6137    ) -> Vec<BlockId> {
6138        let blocks = self
6139            .display_map
6140            .update(cx, |display_map, cx| display_map.insert_blocks(blocks, cx));
6141        self.request_autoscroll(Autoscroll::fit(), cx);
6142        blocks
6143    }
6144
6145    pub fn replace_blocks(
6146        &mut self,
6147        blocks: HashMap<BlockId, RenderBlock>,
6148        cx: &mut ViewContext<Self>,
6149    ) {
6150        self.display_map
6151            .update(cx, |display_map, _| display_map.replace_blocks(blocks));
6152        self.request_autoscroll(Autoscroll::fit(), cx);
6153    }
6154
6155    pub fn remove_blocks(&mut self, block_ids: HashSet<BlockId>, cx: &mut ViewContext<Self>) {
6156        self.display_map.update(cx, |display_map, cx| {
6157            display_map.remove_blocks(block_ids, cx)
6158        });
6159    }
6160
6161    pub fn longest_row(&self, cx: &mut MutableAppContext) -> u32 {
6162        self.display_map
6163            .update(cx, |map, cx| map.snapshot(cx))
6164            .longest_row()
6165    }
6166
6167    pub fn max_point(&self, cx: &mut MutableAppContext) -> DisplayPoint {
6168        self.display_map
6169            .update(cx, |map, cx| map.snapshot(cx))
6170            .max_point()
6171    }
6172
6173    pub fn text(&self, cx: &AppContext) -> String {
6174        self.buffer.read(cx).read(cx).text()
6175    }
6176
6177    pub fn set_text(&mut self, text: impl Into<Arc<str>>, cx: &mut ViewContext<Self>) {
6178        self.transact(cx, |this, cx| {
6179            this.buffer
6180                .read(cx)
6181                .as_singleton()
6182                .expect("you can only call set_text on editors for singleton buffers")
6183                .update(cx, |buffer, cx| buffer.set_text(text, cx));
6184        });
6185    }
6186
6187    pub fn display_text(&self, cx: &mut MutableAppContext) -> String {
6188        self.display_map
6189            .update(cx, |map, cx| map.snapshot(cx))
6190            .text()
6191    }
6192
6193    pub fn soft_wrap_mode(&self, cx: &AppContext) -> SoftWrap {
6194        let language_name = self
6195            .buffer
6196            .read(cx)
6197            .as_singleton()
6198            .and_then(|singleton_buffer| singleton_buffer.read(cx).language())
6199            .map(|l| l.name());
6200
6201        let settings = cx.global::<Settings>();
6202        let mode = self
6203            .soft_wrap_mode_override
6204            .unwrap_or_else(|| settings.soft_wrap(language_name.as_deref()));
6205        match mode {
6206            settings::SoftWrap::None => SoftWrap::None,
6207            settings::SoftWrap::EditorWidth => SoftWrap::EditorWidth,
6208            settings::SoftWrap::PreferredLineLength => {
6209                SoftWrap::Column(settings.preferred_line_length(language_name.as_deref()))
6210            }
6211        }
6212    }
6213
6214    pub fn set_soft_wrap_mode(&mut self, mode: settings::SoftWrap, cx: &mut ViewContext<Self>) {
6215        self.soft_wrap_mode_override = Some(mode);
6216        cx.notify();
6217    }
6218
6219    pub fn set_wrap_width(&self, width: Option<f32>, cx: &mut MutableAppContext) -> bool {
6220        self.display_map
6221            .update(cx, |map, cx| map.set_wrap_width(width, cx))
6222    }
6223
6224    pub fn toggle_soft_wrap(&mut self, _: &ToggleSoftWrap, cx: &mut ViewContext<Self>) {
6225        if self.soft_wrap_mode_override.is_some() {
6226            self.soft_wrap_mode_override.take();
6227        } else {
6228            let soft_wrap = match self.soft_wrap_mode(cx) {
6229                SoftWrap::None => settings::SoftWrap::EditorWidth,
6230                SoftWrap::EditorWidth | SoftWrap::Column(_) => settings::SoftWrap::None,
6231            };
6232            self.soft_wrap_mode_override = Some(soft_wrap);
6233        }
6234        cx.notify();
6235    }
6236
6237    pub fn reveal_in_finder(&mut self, _: &RevealInFinder, cx: &mut ViewContext<Self>) {
6238        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
6239            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
6240                cx.reveal_path(&file.abs_path(cx));
6241            }
6242        }
6243    }
6244
6245    pub fn highlight_rows(&mut self, rows: Option<Range<u32>>) {
6246        self.highlighted_rows = rows;
6247    }
6248
6249    pub fn highlighted_rows(&self) -> Option<Range<u32>> {
6250        self.highlighted_rows.clone()
6251    }
6252
6253    pub fn highlight_background<T: 'static>(
6254        &mut self,
6255        ranges: Vec<Range<Anchor>>,
6256        color_fetcher: fn(&Theme) -> Color,
6257        cx: &mut ViewContext<Self>,
6258    ) {
6259        self.background_highlights
6260            .insert(TypeId::of::<T>(), (color_fetcher, ranges));
6261        cx.notify();
6262    }
6263
6264    #[allow(clippy::type_complexity)]
6265    pub fn clear_background_highlights<T: 'static>(
6266        &mut self,
6267        cx: &mut ViewContext<Self>,
6268    ) -> Option<(fn(&Theme) -> Color, Vec<Range<Anchor>>)> {
6269        let highlights = self.background_highlights.remove(&TypeId::of::<T>());
6270        if highlights.is_some() {
6271            cx.notify();
6272        }
6273        highlights
6274    }
6275
6276    #[cfg(feature = "test-support")]
6277    pub fn all_background_highlights(
6278        &mut self,
6279        cx: &mut ViewContext<Self>,
6280    ) -> Vec<(Range<DisplayPoint>, Color)> {
6281        let snapshot = self.snapshot(cx);
6282        let buffer = &snapshot.buffer_snapshot;
6283        let start = buffer.anchor_before(0);
6284        let end = buffer.anchor_after(buffer.len());
6285        let theme = cx.global::<Settings>().theme.as_ref();
6286        self.background_highlights_in_range(start..end, &snapshot, theme)
6287    }
6288
6289    fn document_highlights_for_position<'a>(
6290        &'a self,
6291        position: Anchor,
6292        buffer: &'a MultiBufferSnapshot,
6293    ) -> impl 'a + Iterator<Item = &Range<Anchor>> {
6294        let read_highlights = self
6295            .background_highlights
6296            .get(&TypeId::of::<DocumentHighlightRead>())
6297            .map(|h| &h.1);
6298        let write_highlights = self
6299            .background_highlights
6300            .get(&TypeId::of::<DocumentHighlightWrite>())
6301            .map(|h| &h.1);
6302        let left_position = position.bias_left(buffer);
6303        let right_position = position.bias_right(buffer);
6304        read_highlights
6305            .into_iter()
6306            .chain(write_highlights)
6307            .flat_map(move |ranges| {
6308                let start_ix = match ranges.binary_search_by(|probe| {
6309                    let cmp = probe.end.cmp(&left_position, buffer);
6310                    if cmp.is_ge() {
6311                        Ordering::Greater
6312                    } else {
6313                        Ordering::Less
6314                    }
6315                }) {
6316                    Ok(i) | Err(i) => i,
6317                };
6318
6319                let right_position = right_position.clone();
6320                ranges[start_ix..]
6321                    .iter()
6322                    .take_while(move |range| range.start.cmp(&right_position, buffer).is_le())
6323            })
6324    }
6325
6326    pub fn background_highlights_in_range(
6327        &self,
6328        search_range: Range<Anchor>,
6329        display_snapshot: &DisplaySnapshot,
6330        theme: &Theme,
6331    ) -> Vec<(Range<DisplayPoint>, Color)> {
6332        let mut results = Vec::new();
6333        let buffer = &display_snapshot.buffer_snapshot;
6334        for (color_fetcher, ranges) in self.background_highlights.values() {
6335            let color = color_fetcher(theme);
6336            let start_ix = match ranges.binary_search_by(|probe| {
6337                let cmp = probe.end.cmp(&search_range.start, buffer);
6338                if cmp.is_gt() {
6339                    Ordering::Greater
6340                } else {
6341                    Ordering::Less
6342                }
6343            }) {
6344                Ok(i) | Err(i) => i,
6345            };
6346            for range in &ranges[start_ix..] {
6347                if range.start.cmp(&search_range.end, buffer).is_ge() {
6348                    break;
6349                }
6350                let start = range
6351                    .start
6352                    .to_point(buffer)
6353                    .to_display_point(display_snapshot);
6354                let end = range
6355                    .end
6356                    .to_point(buffer)
6357                    .to_display_point(display_snapshot);
6358                results.push((start..end, color))
6359            }
6360        }
6361        results
6362    }
6363
6364    pub fn highlight_text<T: 'static>(
6365        &mut self,
6366        ranges: Vec<Range<Anchor>>,
6367        style: HighlightStyle,
6368        cx: &mut ViewContext<Self>,
6369    ) {
6370        self.display_map.update(cx, |map, _| {
6371            map.highlight_text(TypeId::of::<T>(), ranges, style)
6372        });
6373        cx.notify();
6374    }
6375
6376    pub fn text_highlights<'a, T: 'static>(
6377        &'a self,
6378        cx: &'a AppContext,
6379    ) -> Option<(HighlightStyle, &'a [Range<Anchor>])> {
6380        self.display_map.read(cx).text_highlights(TypeId::of::<T>())
6381    }
6382
6383    pub fn clear_text_highlights<T: 'static>(
6384        &mut self,
6385        cx: &mut ViewContext<Self>,
6386    ) -> Option<Arc<(HighlightStyle, Vec<Range<Anchor>>)>> {
6387        let highlights = self
6388            .display_map
6389            .update(cx, |map, _| map.clear_text_highlights(TypeId::of::<T>()));
6390        if highlights.is_some() {
6391            cx.notify();
6392        }
6393        highlights
6394    }
6395
6396    pub fn show_local_cursors(&self, cx: &AppContext) -> bool {
6397        self.blink_manager.read(cx).visible() && self.focused
6398    }
6399
6400    fn on_buffer_changed(&mut self, _: ModelHandle<MultiBuffer>, cx: &mut ViewContext<Self>) {
6401        cx.notify();
6402    }
6403
6404    fn on_buffer_event(
6405        &mut self,
6406        _: ModelHandle<MultiBuffer>,
6407        event: &multi_buffer::Event,
6408        cx: &mut ViewContext<Self>,
6409    ) {
6410        match event {
6411            multi_buffer::Event::Edited => {
6412                self.refresh_active_diagnostics(cx);
6413                self.refresh_code_actions(cx);
6414                if self.has_active_copilot_suggestion(cx) {
6415                    self.update_visible_copilot_suggestion(cx);
6416                }
6417                cx.emit(Event::BufferEdited);
6418            }
6419            multi_buffer::Event::ExcerptsAdded {
6420                buffer,
6421                predecessor,
6422                excerpts,
6423            } => cx.emit(Event::ExcerptsAdded {
6424                buffer: buffer.clone(),
6425                predecessor: *predecessor,
6426                excerpts: excerpts.clone(),
6427            }),
6428            multi_buffer::Event::ExcerptsRemoved { ids } => {
6429                cx.emit(Event::ExcerptsRemoved { ids: ids.clone() })
6430            }
6431            multi_buffer::Event::Reparsed => cx.emit(Event::Reparsed),
6432            multi_buffer::Event::DirtyChanged => cx.emit(Event::DirtyChanged),
6433            multi_buffer::Event::Saved => cx.emit(Event::Saved),
6434            multi_buffer::Event::FileHandleChanged => cx.emit(Event::TitleChanged),
6435            multi_buffer::Event::Reloaded => cx.emit(Event::TitleChanged),
6436            multi_buffer::Event::Closed => cx.emit(Event::Closed),
6437            multi_buffer::Event::DiagnosticsUpdated => {
6438                self.refresh_active_diagnostics(cx);
6439            }
6440        }
6441    }
6442
6443    fn on_display_map_changed(&mut self, _: ModelHandle<DisplayMap>, cx: &mut ViewContext<Self>) {
6444        cx.notify();
6445    }
6446
6447    fn on_settings_changed(&mut self, cx: &mut ViewContext<Self>) {
6448        self.refresh_copilot_suggestions(cx);
6449    }
6450
6451    pub fn set_searchable(&mut self, searchable: bool) {
6452        self.searchable = searchable;
6453    }
6454
6455    pub fn searchable(&self) -> bool {
6456        self.searchable
6457    }
6458
6459    fn open_excerpts(workspace: &mut Workspace, _: &OpenExcerpts, cx: &mut ViewContext<Workspace>) {
6460        let active_item = workspace.active_item(cx);
6461        let editor_handle = if let Some(editor) = active_item
6462            .as_ref()
6463            .and_then(|item| item.act_as::<Self>(cx))
6464        {
6465            editor
6466        } else {
6467            cx.propagate_action();
6468            return;
6469        };
6470
6471        let editor = editor_handle.read(cx);
6472        let buffer = editor.buffer.read(cx);
6473        if buffer.is_singleton() {
6474            cx.propagate_action();
6475            return;
6476        }
6477
6478        let mut new_selections_by_buffer = HashMap::default();
6479        for selection in editor.selections.all::<usize>(cx) {
6480            for (buffer, mut range) in
6481                buffer.range_to_buffer_ranges(selection.start..selection.end, cx)
6482            {
6483                if selection.reversed {
6484                    mem::swap(&mut range.start, &mut range.end);
6485                }
6486                new_selections_by_buffer
6487                    .entry(buffer)
6488                    .or_insert(Vec::new())
6489                    .push(range)
6490            }
6491        }
6492
6493        editor_handle.update(cx, |editor, cx| {
6494            editor.push_to_nav_history(editor.selections.newest_anchor().head(), None, cx);
6495        });
6496        let pane = workspace.active_pane().clone();
6497        pane.update(cx, |pane, _| pane.disable_history());
6498
6499        // We defer the pane interaction because we ourselves are a workspace item
6500        // and activating a new item causes the pane to call a method on us reentrantly,
6501        // which panics if we're on the stack.
6502        cx.defer(move |workspace, cx| {
6503            for (buffer, ranges) in new_selections_by_buffer.into_iter() {
6504                let editor = workspace.open_project_item::<Self>(buffer, cx);
6505                editor.update(cx, |editor, cx| {
6506                    editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
6507                        s.select_ranges(ranges);
6508                    });
6509                });
6510            }
6511
6512            pane.update(cx, |pane, _| pane.enable_history());
6513        });
6514    }
6515
6516    fn jump(workspace: &mut Workspace, action: &Jump, cx: &mut ViewContext<Workspace>) {
6517        let editor = workspace.open_path(action.path.clone(), None, true, cx);
6518        let position = action.position;
6519        let anchor = action.anchor;
6520        cx.spawn_weak(|_, mut cx| async move {
6521            let editor = editor.await.log_err()?.downcast::<Editor>()?;
6522            editor.update(&mut cx, |editor, cx| {
6523                let buffer = editor.buffer().read(cx).as_singleton()?;
6524                let buffer = buffer.read(cx);
6525                let cursor = if buffer.can_resolve(&anchor) {
6526                    language::ToPoint::to_point(&anchor, buffer)
6527                } else {
6528                    buffer.clip_point(position, Bias::Left)
6529                };
6530
6531                let nav_history = editor.nav_history.take();
6532                editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
6533                    s.select_ranges([cursor..cursor]);
6534                });
6535                editor.nav_history = nav_history;
6536
6537                Some(())
6538            })?;
6539            Some(())
6540        })
6541        .detach()
6542    }
6543
6544    fn marked_text_ranges(&self, cx: &AppContext) -> Option<Vec<Range<OffsetUtf16>>> {
6545        let snapshot = self.buffer.read(cx).read(cx);
6546        let (_, ranges) = self.text_highlights::<InputComposition>(cx)?;
6547        Some(
6548            ranges
6549                .iter()
6550                .map(move |range| {
6551                    range.start.to_offset_utf16(&snapshot)..range.end.to_offset_utf16(&snapshot)
6552                })
6553                .collect(),
6554        )
6555    }
6556
6557    fn selection_replacement_ranges(
6558        &self,
6559        range: Range<OffsetUtf16>,
6560        cx: &AppContext,
6561    ) -> Vec<Range<OffsetUtf16>> {
6562        let selections = self.selections.all::<OffsetUtf16>(cx);
6563        let newest_selection = selections
6564            .iter()
6565            .max_by_key(|selection| selection.id)
6566            .unwrap();
6567        let start_delta = range.start.0 as isize - newest_selection.start.0 as isize;
6568        let end_delta = range.end.0 as isize - newest_selection.end.0 as isize;
6569        let snapshot = self.buffer.read(cx).read(cx);
6570        selections
6571            .into_iter()
6572            .map(|mut selection| {
6573                selection.start.0 =
6574                    (selection.start.0 as isize).saturating_add(start_delta) as usize;
6575                selection.end.0 = (selection.end.0 as isize).saturating_add(end_delta) as usize;
6576                snapshot.clip_offset_utf16(selection.start, Bias::Left)
6577                    ..snapshot.clip_offset_utf16(selection.end, Bias::Right)
6578            })
6579            .collect()
6580    }
6581
6582    fn report_event(&self, name: &str, cx: &AppContext) {
6583        if let Some((project, file)) = self.project.as_ref().zip(
6584            self.buffer
6585                .read(cx)
6586                .as_singleton()
6587                .and_then(|b| b.read(cx).file()),
6588        ) {
6589            let extension = Path::new(file.file_name(cx))
6590                .extension()
6591                .and_then(|e| e.to_str());
6592            project.read(cx).client().report_event(
6593                name,
6594                json!({ "File Extension": extension }),
6595                cx.global::<Settings>().telemetry(),
6596            );
6597        }
6598    }
6599
6600    /// Copy the highlighted chunks to the clipboard as JSON. The format is an array of lines,
6601    /// with each line being an array of {text, highlight} objects.
6602    fn copy_highlight_json(&mut self, _: &CopyHighlightJson, cx: &mut ViewContext<Self>) {
6603        let Some(buffer) = self.buffer.read(cx).as_singleton() else {
6604            return;
6605        };
6606
6607        #[derive(Serialize)]
6608        struct Chunk<'a> {
6609            text: String,
6610            highlight: Option<&'a str>,
6611        }
6612
6613        let snapshot = buffer.read(cx).snapshot();
6614        let range = self
6615            .selected_text_range(cx)
6616            .and_then(|selected_range| {
6617                if selected_range.is_empty() {
6618                    None
6619                } else {
6620                    Some(selected_range)
6621                }
6622            })
6623            .unwrap_or_else(|| 0..snapshot.len());
6624
6625        let chunks = snapshot.chunks(range, true);
6626        let mut lines = Vec::new();
6627        let mut line: VecDeque<Chunk> = VecDeque::new();
6628
6629        let theme = &cx.global::<Settings>().theme.editor.syntax;
6630
6631        for chunk in chunks {
6632            let highlight = chunk.syntax_highlight_id.and_then(|id| id.name(theme));
6633            let mut chunk_lines = chunk.text.split("\n").peekable();
6634            while let Some(text) = chunk_lines.next() {
6635                let mut merged_with_last_token = false;
6636                if let Some(last_token) = line.back_mut() {
6637                    if last_token.highlight == highlight {
6638                        last_token.text.push_str(text);
6639                        merged_with_last_token = true;
6640                    }
6641                }
6642
6643                if !merged_with_last_token {
6644                    line.push_back(Chunk {
6645                        text: text.into(),
6646                        highlight,
6647                    });
6648                }
6649
6650                if chunk_lines.peek().is_some() {
6651                    if line.len() > 1 && line.front().unwrap().text.is_empty() {
6652                        line.pop_front();
6653                    }
6654                    if line.len() > 1 && line.back().unwrap().text.is_empty() {
6655                        line.pop_back();
6656                    }
6657
6658                    lines.push(mem::take(&mut line));
6659                }
6660            }
6661        }
6662
6663        let Some(lines) = serde_json::to_string_pretty(&lines).log_err() else { return; };
6664        cx.write_to_clipboard(ClipboardItem::new(lines));
6665    }
6666}
6667
6668fn consume_contiguous_rows(
6669    contiguous_row_selections: &mut Vec<Selection<Point>>,
6670    selection: &Selection<Point>,
6671    display_map: &DisplaySnapshot,
6672    selections: &mut std::iter::Peekable<std::slice::Iter<Selection<Point>>>,
6673) -> (u32, u32) {
6674    contiguous_row_selections.push(selection.clone());
6675    let start_row = selection.start.row;
6676    let mut end_row = ending_row(selection, display_map);
6677
6678    while let Some(next_selection) = selections.peek() {
6679        if next_selection.start.row <= end_row {
6680            end_row = ending_row(next_selection, display_map);
6681            contiguous_row_selections.push(selections.next().unwrap().clone());
6682        } else {
6683            break;
6684        }
6685    }
6686    (start_row, end_row)
6687}
6688
6689fn ending_row(next_selection: &Selection<Point>, display_map: &DisplaySnapshot) -> u32 {
6690    if next_selection.end.column > 0 || next_selection.is_empty() {
6691        display_map.next_line_boundary(next_selection.end).0.row + 1
6692    } else {
6693        next_selection.end.row
6694    }
6695}
6696
6697impl EditorSnapshot {
6698    pub fn language_at<T: ToOffset>(&self, position: T) -> Option<&Arc<Language>> {
6699        self.display_snapshot.buffer_snapshot.language_at(position)
6700    }
6701
6702    pub fn is_focused(&self) -> bool {
6703        self.is_focused
6704    }
6705
6706    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
6707        self.placeholder_text.as_ref()
6708    }
6709
6710    pub fn scroll_position(&self) -> Vector2F {
6711        self.scroll_anchor.scroll_position(&self.display_snapshot)
6712    }
6713}
6714
6715impl Deref for EditorSnapshot {
6716    type Target = DisplaySnapshot;
6717
6718    fn deref(&self) -> &Self::Target {
6719        &self.display_snapshot
6720    }
6721}
6722
6723#[derive(Clone, Debug, PartialEq, Eq)]
6724pub enum Event {
6725    InputIgnored {
6726        text: Arc<str>,
6727    },
6728    ExcerptsAdded {
6729        buffer: ModelHandle<Buffer>,
6730        predecessor: ExcerptId,
6731        excerpts: Vec<(ExcerptId, ExcerptRange<language::Anchor>)>,
6732    },
6733    ExcerptsRemoved {
6734        ids: Vec<ExcerptId>,
6735    },
6736    BufferEdited,
6737    Edited,
6738    Reparsed,
6739    Blurred,
6740    DirtyChanged,
6741    Saved,
6742    TitleChanged,
6743    SelectionsChanged {
6744        local: bool,
6745    },
6746    ScrollPositionChanged {
6747        local: bool,
6748    },
6749    Closed,
6750}
6751
6752pub struct EditorFocused(pub ViewHandle<Editor>);
6753pub struct EditorBlurred(pub ViewHandle<Editor>);
6754pub struct EditorReleased(pub WeakViewHandle<Editor>);
6755
6756impl Entity for Editor {
6757    type Event = Event;
6758
6759    fn release(&mut self, cx: &mut MutableAppContext) {
6760        cx.emit_global(EditorReleased(self.handle.clone()));
6761    }
6762}
6763
6764impl View for Editor {
6765    fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
6766        let style = self.style(cx);
6767        let font_changed = self.display_map.update(cx, |map, cx| {
6768            map.set_fold_ellipses_color(style.folds.ellipses.text_color);
6769            map.set_font(style.text.font_id, style.text.font_size, cx)
6770        });
6771
6772        if font_changed {
6773            let handle = self.handle.clone();
6774            cx.defer(move |cx| {
6775                if let Some(editor) = handle.upgrade(cx) {
6776                    editor.update(cx, |editor, cx| {
6777                        hide_hover(editor, &HideHover, cx);
6778                        hide_link_definition(editor, cx);
6779                    })
6780                }
6781            });
6782        }
6783
6784        Stack::new()
6785            .with_child(EditorElement::new(self.handle.clone(), style.clone()).boxed())
6786            .with_child(ChildView::new(&self.mouse_context_menu, cx).boxed())
6787            .boxed()
6788    }
6789
6790    fn ui_name() -> &'static str {
6791        "Editor"
6792    }
6793
6794    fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
6795        if cx.is_self_focused() {
6796            let focused_event = EditorFocused(cx.handle());
6797            cx.emit_global(focused_event);
6798        }
6799        if let Some(rename) = self.pending_rename.as_ref() {
6800            cx.focus(&rename.editor);
6801        } else {
6802            if !self.focused {
6803                self.blink_manager.update(cx, BlinkManager::enable);
6804            }
6805            self.focused = true;
6806            self.buffer.update(cx, |buffer, cx| {
6807                buffer.finalize_last_transaction(cx);
6808                if self.leader_replica_id.is_none() {
6809                    buffer.set_active_selections(
6810                        &self.selections.disjoint_anchors(),
6811                        self.selections.line_mode,
6812                        self.cursor_shape,
6813                        cx,
6814                    );
6815                }
6816            });
6817        }
6818    }
6819
6820    fn focus_out(&mut self, _: AnyViewHandle, cx: &mut ViewContext<Self>) {
6821        let blurred_event = EditorBlurred(cx.handle());
6822        cx.emit_global(blurred_event);
6823        self.focused = false;
6824        self.blink_manager.update(cx, BlinkManager::disable);
6825        self.buffer
6826            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
6827        self.hide_context_menu(cx);
6828        hide_hover(self, &HideHover, cx);
6829        cx.emit(Event::Blurred);
6830        cx.notify();
6831    }
6832
6833    fn modifiers_changed(
6834        &mut self,
6835        event: &gpui::ModifiersChangedEvent,
6836        cx: &mut ViewContext<Self>,
6837    ) -> bool {
6838        let pending_selection = self.has_pending_selection();
6839
6840        if let Some(point) = self.link_go_to_definition_state.last_mouse_location.clone() {
6841            if event.cmd && !pending_selection {
6842                let snapshot = self.snapshot(cx);
6843                let kind = if event.shift {
6844                    LinkDefinitionKind::Type
6845                } else {
6846                    LinkDefinitionKind::Symbol
6847                };
6848
6849                show_link_definition(kind, self, point, snapshot, cx);
6850                return false;
6851            }
6852        }
6853
6854        {
6855            if self.link_go_to_definition_state.symbol_range.is_some()
6856                || !self.link_go_to_definition_state.definitions.is_empty()
6857            {
6858                self.link_go_to_definition_state.symbol_range.take();
6859                self.link_go_to_definition_state.definitions.clear();
6860                cx.notify();
6861            }
6862
6863            self.link_go_to_definition_state.task = None;
6864
6865            self.clear_text_highlights::<LinkGoToDefinitionState>(cx);
6866        }
6867
6868        false
6869    }
6870
6871    fn keymap_context(&self, _: &AppContext) -> KeymapContext {
6872        let mut context = Self::default_keymap_context();
6873        let mode = match self.mode {
6874            EditorMode::SingleLine => "single_line",
6875            EditorMode::AutoHeight { .. } => "auto_height",
6876            EditorMode::Full => "full",
6877        };
6878        context.add_key("mode", mode);
6879        if self.pending_rename.is_some() {
6880            context.add_identifier("renaming");
6881        }
6882        match self.context_menu.as_ref() {
6883            Some(ContextMenu::Completions(_)) => context.add_identifier("showing_completions"),
6884            Some(ContextMenu::CodeActions(_)) => context.add_identifier("showing_code_actions"),
6885            None => {}
6886        }
6887
6888        for layer in self.keymap_context_layers.values() {
6889            context.extend(layer);
6890        }
6891
6892        context
6893    }
6894
6895    fn text_for_range(&self, range_utf16: Range<usize>, cx: &AppContext) -> Option<String> {
6896        Some(
6897            self.buffer
6898                .read(cx)
6899                .read(cx)
6900                .text_for_range(OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end))
6901                .collect(),
6902        )
6903    }
6904
6905    fn selected_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
6906        // Prevent the IME menu from appearing when holding down an alphabetic key
6907        // while input is disabled.
6908        if !self.input_enabled {
6909            return None;
6910        }
6911
6912        let range = self.selections.newest::<OffsetUtf16>(cx).range();
6913        Some(range.start.0..range.end.0)
6914    }
6915
6916    fn marked_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
6917        let snapshot = self.buffer.read(cx).read(cx);
6918        let range = self.text_highlights::<InputComposition>(cx)?.1.get(0)?;
6919        Some(range.start.to_offset_utf16(&snapshot).0..range.end.to_offset_utf16(&snapshot).0)
6920    }
6921
6922    fn unmark_text(&mut self, cx: &mut ViewContext<Self>) {
6923        self.clear_text_highlights::<InputComposition>(cx);
6924        self.ime_transaction.take();
6925    }
6926
6927    fn replace_text_in_range(
6928        &mut self,
6929        range_utf16: Option<Range<usize>>,
6930        text: &str,
6931        cx: &mut ViewContext<Self>,
6932    ) {
6933        self.transact(cx, |this, cx| {
6934            if this.input_enabled {
6935                let new_selected_ranges = if let Some(range_utf16) = range_utf16 {
6936                    let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
6937                    Some(this.selection_replacement_ranges(range_utf16, cx))
6938                } else {
6939                    this.marked_text_ranges(cx)
6940                };
6941
6942                if let Some(new_selected_ranges) = new_selected_ranges {
6943                    this.change_selections(None, cx, |selections| {
6944                        selections.select_ranges(new_selected_ranges)
6945                    });
6946                }
6947            }
6948
6949            this.handle_input(text, cx);
6950        });
6951
6952        if !self.input_enabled {
6953            return;
6954        }
6955
6956        if let Some(transaction) = self.ime_transaction {
6957            self.buffer.update(cx, |buffer, cx| {
6958                buffer.group_until_transaction(transaction, cx);
6959            });
6960        }
6961
6962        self.unmark_text(cx);
6963    }
6964
6965    fn replace_and_mark_text_in_range(
6966        &mut self,
6967        range_utf16: Option<Range<usize>>,
6968        text: &str,
6969        new_selected_range_utf16: Option<Range<usize>>,
6970        cx: &mut ViewContext<Self>,
6971    ) {
6972        if !self.input_enabled {
6973            return;
6974        }
6975
6976        let transaction = self.transact(cx, |this, cx| {
6977            let ranges_to_replace = if let Some(mut marked_ranges) = this.marked_text_ranges(cx) {
6978                let snapshot = this.buffer.read(cx).read(cx);
6979                if let Some(relative_range_utf16) = range_utf16.as_ref() {
6980                    for marked_range in &mut marked_ranges {
6981                        marked_range.end.0 = marked_range.start.0 + relative_range_utf16.end;
6982                        marked_range.start.0 += relative_range_utf16.start;
6983                        marked_range.start =
6984                            snapshot.clip_offset_utf16(marked_range.start, Bias::Left);
6985                        marked_range.end =
6986                            snapshot.clip_offset_utf16(marked_range.end, Bias::Right);
6987                    }
6988                }
6989                Some(marked_ranges)
6990            } else if let Some(range_utf16) = range_utf16 {
6991                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
6992                Some(this.selection_replacement_ranges(range_utf16, cx))
6993            } else {
6994                None
6995            };
6996
6997            if let Some(ranges) = ranges_to_replace {
6998                this.change_selections(None, cx, |s| s.select_ranges(ranges));
6999            }
7000
7001            let marked_ranges = {
7002                let snapshot = this.buffer.read(cx).read(cx);
7003                this.selections
7004                    .disjoint_anchors()
7005                    .iter()
7006                    .map(|selection| {
7007                        selection.start.bias_left(&*snapshot)..selection.end.bias_right(&*snapshot)
7008                    })
7009                    .collect::<Vec<_>>()
7010            };
7011
7012            if text.is_empty() {
7013                this.unmark_text(cx);
7014            } else {
7015                this.highlight_text::<InputComposition>(
7016                    marked_ranges.clone(),
7017                    this.style(cx).composition_mark,
7018                    cx,
7019                );
7020            }
7021
7022            this.handle_input(text, cx);
7023
7024            if let Some(new_selected_range) = new_selected_range_utf16 {
7025                let snapshot = this.buffer.read(cx).read(cx);
7026                let new_selected_ranges = marked_ranges
7027                    .into_iter()
7028                    .map(|marked_range| {
7029                        let insertion_start = marked_range.start.to_offset_utf16(&snapshot).0;
7030                        let new_start = OffsetUtf16(new_selected_range.start + insertion_start);
7031                        let new_end = OffsetUtf16(new_selected_range.end + insertion_start);
7032                        snapshot.clip_offset_utf16(new_start, Bias::Left)
7033                            ..snapshot.clip_offset_utf16(new_end, Bias::Right)
7034                    })
7035                    .collect::<Vec<_>>();
7036
7037                drop(snapshot);
7038                this.change_selections(None, cx, |selections| {
7039                    selections.select_ranges(new_selected_ranges)
7040                });
7041            }
7042        });
7043
7044        self.ime_transaction = self.ime_transaction.or(transaction);
7045        if let Some(transaction) = self.ime_transaction {
7046            self.buffer.update(cx, |buffer, cx| {
7047                buffer.group_until_transaction(transaction, cx);
7048            });
7049        }
7050
7051        if self.text_highlights::<InputComposition>(cx).is_none() {
7052            self.ime_transaction.take();
7053        }
7054    }
7055}
7056
7057fn build_style(
7058    settings: &Settings,
7059    get_field_editor_theme: Option<&GetFieldEditorTheme>,
7060    override_text_style: Option<&OverrideTextStyle>,
7061    cx: &AppContext,
7062) -> EditorStyle {
7063    let font_cache = cx.font_cache();
7064
7065    let mut theme = settings.theme.editor.clone();
7066    let mut style = if let Some(get_field_editor_theme) = get_field_editor_theme {
7067        let field_editor_theme = get_field_editor_theme(&settings.theme);
7068        theme.text_color = field_editor_theme.text.color;
7069        theme.selection = field_editor_theme.selection;
7070        theme.background = field_editor_theme
7071            .container
7072            .background_color
7073            .unwrap_or_default();
7074        EditorStyle {
7075            text: field_editor_theme.text,
7076            placeholder_text: field_editor_theme.placeholder_text,
7077            theme,
7078        }
7079    } else {
7080        let font_family_id = settings.buffer_font_family;
7081        let font_family_name = cx.font_cache().family_name(font_family_id).unwrap();
7082        let font_properties = Default::default();
7083        let font_id = font_cache
7084            .select_font(font_family_id, &font_properties)
7085            .unwrap();
7086        let font_size = settings.buffer_font_size;
7087        EditorStyle {
7088            text: TextStyle {
7089                color: settings.theme.editor.text_color,
7090                font_family_name,
7091                font_family_id,
7092                font_id,
7093                font_size,
7094                font_properties,
7095                underline: Default::default(),
7096            },
7097            placeholder_text: None,
7098            theme,
7099        }
7100    };
7101
7102    if let Some(highlight_style) = override_text_style.and_then(|build_style| build_style(&style)) {
7103        if let Some(highlighted) = style
7104            .text
7105            .clone()
7106            .highlight(highlight_style, font_cache)
7107            .log_err()
7108        {
7109            style.text = highlighted;
7110        }
7111    }
7112
7113    style
7114}
7115
7116trait SelectionExt {
7117    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize>;
7118    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point>;
7119    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
7120    fn spanned_rows(&self, include_end_if_at_line_start: bool, map: &DisplaySnapshot)
7121        -> Range<u32>;
7122}
7123
7124impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
7125    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
7126        let start = self.start.to_point(buffer);
7127        let end = self.end.to_point(buffer);
7128        if self.reversed {
7129            end..start
7130        } else {
7131            start..end
7132        }
7133    }
7134
7135    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
7136        let start = self.start.to_offset(buffer);
7137        let end = self.end.to_offset(buffer);
7138        if self.reversed {
7139            end..start
7140        } else {
7141            start..end
7142        }
7143    }
7144
7145    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
7146        let start = self
7147            .start
7148            .to_point(&map.buffer_snapshot)
7149            .to_display_point(map);
7150        let end = self
7151            .end
7152            .to_point(&map.buffer_snapshot)
7153            .to_display_point(map);
7154        if self.reversed {
7155            end..start
7156        } else {
7157            start..end
7158        }
7159    }
7160
7161    fn spanned_rows(
7162        &self,
7163        include_end_if_at_line_start: bool,
7164        map: &DisplaySnapshot,
7165    ) -> Range<u32> {
7166        let start = self.start.to_point(&map.buffer_snapshot);
7167        let mut end = self.end.to_point(&map.buffer_snapshot);
7168        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
7169            end.row -= 1;
7170        }
7171
7172        let buffer_start = map.prev_line_boundary(start).0;
7173        let buffer_end = map.next_line_boundary(end).0;
7174        buffer_start.row..buffer_end.row + 1
7175    }
7176}
7177
7178impl<T: InvalidationRegion> InvalidationStack<T> {
7179    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
7180    where
7181        S: Clone + ToOffset,
7182    {
7183        while let Some(region) = self.last() {
7184            let all_selections_inside_invalidation_ranges =
7185                if selections.len() == region.ranges().len() {
7186                    selections
7187                        .iter()
7188                        .zip(region.ranges().iter().map(|r| r.to_offset(buffer)))
7189                        .all(|(selection, invalidation_range)| {
7190                            let head = selection.head().to_offset(buffer);
7191                            invalidation_range.start <= head && invalidation_range.end >= head
7192                        })
7193                } else {
7194                    false
7195                };
7196
7197            if all_selections_inside_invalidation_ranges {
7198                break;
7199            } else {
7200                self.pop();
7201            }
7202        }
7203    }
7204}
7205
7206impl<T> Default for InvalidationStack<T> {
7207    fn default() -> Self {
7208        Self(Default::default())
7209    }
7210}
7211
7212impl<T> Deref for InvalidationStack<T> {
7213    type Target = Vec<T>;
7214
7215    fn deref(&self) -> &Self::Target {
7216        &self.0
7217    }
7218}
7219
7220impl<T> DerefMut for InvalidationStack<T> {
7221    fn deref_mut(&mut self) -> &mut Self::Target {
7222        &mut self.0
7223    }
7224}
7225
7226impl InvalidationRegion for SnippetState {
7227    fn ranges(&self) -> &[Range<Anchor>] {
7228        &self.ranges[self.active_index]
7229    }
7230}
7231
7232impl Deref for EditorStyle {
7233    type Target = theme::Editor;
7234
7235    fn deref(&self) -> &Self::Target {
7236        &self.theme
7237    }
7238}
7239
7240pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> RenderBlock {
7241    let mut highlighted_lines = Vec::new();
7242    for line in diagnostic.message.lines() {
7243        highlighted_lines.push(highlight_diagnostic_message(line));
7244    }
7245
7246    Arc::new(move |cx: &mut BlockContext| {
7247        let settings = cx.global::<Settings>();
7248        let theme = &settings.theme.editor;
7249        let style = diagnostic_style(diagnostic.severity, is_valid, theme);
7250        let font_size = (style.text_scale_factor * settings.buffer_font_size).round();
7251        Flex::column()
7252            .with_children(highlighted_lines.iter().map(|(line, highlights)| {
7253                Label::new(
7254                    line.clone(),
7255                    style.message.clone().with_font_size(font_size),
7256                )
7257                .with_highlights(highlights.clone())
7258                .contained()
7259                .with_margin_left(cx.anchor_x)
7260                .boxed()
7261            }))
7262            .aligned()
7263            .left()
7264            .boxed()
7265    })
7266}
7267
7268pub fn highlight_diagnostic_message(message: &str) -> (String, Vec<usize>) {
7269    let mut message_without_backticks = String::new();
7270    let mut prev_offset = 0;
7271    let mut inside_block = false;
7272    let mut highlights = Vec::new();
7273    for (match_ix, (offset, _)) in message
7274        .match_indices('`')
7275        .chain([(message.len(), "")])
7276        .enumerate()
7277    {
7278        message_without_backticks.push_str(&message[prev_offset..offset]);
7279        if inside_block {
7280            highlights.extend(prev_offset - match_ix..offset - match_ix);
7281        }
7282
7283        inside_block = !inside_block;
7284        prev_offset = offset + 1;
7285    }
7286
7287    (message_without_backticks, highlights)
7288}
7289
7290pub fn diagnostic_style(
7291    severity: DiagnosticSeverity,
7292    valid: bool,
7293    theme: &theme::Editor,
7294) -> DiagnosticStyle {
7295    match (severity, valid) {
7296        (DiagnosticSeverity::ERROR, true) => theme.error_diagnostic.clone(),
7297        (DiagnosticSeverity::ERROR, false) => theme.invalid_error_diagnostic.clone(),
7298        (DiagnosticSeverity::WARNING, true) => theme.warning_diagnostic.clone(),
7299        (DiagnosticSeverity::WARNING, false) => theme.invalid_warning_diagnostic.clone(),
7300        (DiagnosticSeverity::INFORMATION, true) => theme.information_diagnostic.clone(),
7301        (DiagnosticSeverity::INFORMATION, false) => theme.invalid_information_diagnostic.clone(),
7302        (DiagnosticSeverity::HINT, true) => theme.hint_diagnostic.clone(),
7303        (DiagnosticSeverity::HINT, false) => theme.invalid_hint_diagnostic.clone(),
7304        _ => theme.invalid_hint_diagnostic.clone(),
7305    }
7306}
7307
7308pub fn combine_syntax_and_fuzzy_match_highlights(
7309    text: &str,
7310    default_style: HighlightStyle,
7311    syntax_ranges: impl Iterator<Item = (Range<usize>, HighlightStyle)>,
7312    match_indices: &[usize],
7313) -> Vec<(Range<usize>, HighlightStyle)> {
7314    let mut result = Vec::new();
7315    let mut match_indices = match_indices.iter().copied().peekable();
7316
7317    for (range, mut syntax_highlight) in syntax_ranges.chain([(usize::MAX..0, Default::default())])
7318    {
7319        syntax_highlight.weight = None;
7320
7321        // Add highlights for any fuzzy match characters before the next
7322        // syntax highlight range.
7323        while let Some(&match_index) = match_indices.peek() {
7324            if match_index >= range.start {
7325                break;
7326            }
7327            match_indices.next();
7328            let end_index = char_ix_after(match_index, text);
7329            let mut match_style = default_style;
7330            match_style.weight = Some(fonts::Weight::BOLD);
7331            result.push((match_index..end_index, match_style));
7332        }
7333
7334        if range.start == usize::MAX {
7335            break;
7336        }
7337
7338        // Add highlights for any fuzzy match characters within the
7339        // syntax highlight range.
7340        let mut offset = range.start;
7341        while let Some(&match_index) = match_indices.peek() {
7342            if match_index >= range.end {
7343                break;
7344            }
7345
7346            match_indices.next();
7347            if match_index > offset {
7348                result.push((offset..match_index, syntax_highlight));
7349            }
7350
7351            let mut end_index = char_ix_after(match_index, text);
7352            while let Some(&next_match_index) = match_indices.peek() {
7353                if next_match_index == end_index && next_match_index < range.end {
7354                    end_index = char_ix_after(next_match_index, text);
7355                    match_indices.next();
7356                } else {
7357                    break;
7358                }
7359            }
7360
7361            let mut match_style = syntax_highlight;
7362            match_style.weight = Some(fonts::Weight::BOLD);
7363            result.push((match_index..end_index, match_style));
7364            offset = end_index;
7365        }
7366
7367        if offset < range.end {
7368            result.push((offset..range.end, syntax_highlight));
7369        }
7370    }
7371
7372    fn char_ix_after(ix: usize, text: &str) -> usize {
7373        ix + text[ix..].chars().next().unwrap().len_utf8()
7374    }
7375
7376    result
7377}
7378
7379pub fn styled_runs_for_code_label<'a>(
7380    label: &'a CodeLabel,
7381    syntax_theme: &'a theme::SyntaxTheme,
7382) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
7383    let fade_out = HighlightStyle {
7384        fade_out: Some(0.35),
7385        ..Default::default()
7386    };
7387
7388    let mut prev_end = label.filter_range.end;
7389    label
7390        .runs
7391        .iter()
7392        .enumerate()
7393        .flat_map(move |(ix, (range, highlight_id))| {
7394            let style = if let Some(style) = highlight_id.style(syntax_theme) {
7395                style
7396            } else {
7397                return Default::default();
7398            };
7399            let mut muted_style = style;
7400            muted_style.highlight(fade_out);
7401
7402            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
7403            if range.start >= label.filter_range.end {
7404                if range.start > prev_end {
7405                    runs.push((prev_end..range.start, fade_out));
7406                }
7407                runs.push((range.clone(), muted_style));
7408            } else if range.end <= label.filter_range.end {
7409                runs.push((range.clone(), style));
7410            } else {
7411                runs.push((range.start..label.filter_range.end, style));
7412                runs.push((label.filter_range.end..range.end, muted_style));
7413            }
7414            prev_end = cmp::max(prev_end, range.end);
7415
7416            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
7417                runs.push((prev_end..label.text.len(), fade_out));
7418            }
7419
7420            runs
7421        })
7422}
7423
7424pub fn split_words<'a>(text: &'a str) -> impl std::iter::Iterator<Item = &'a str> + 'a {
7425    let mut index = 0;
7426    let mut codepoints = text.char_indices().peekable();
7427
7428    std::iter::from_fn(move || {
7429        let start_index = index;
7430        while let Some((new_index, codepoint)) = codepoints.next() {
7431            index = new_index + codepoint.len_utf8();
7432            let current_upper = codepoint.is_uppercase();
7433            let next_upper = codepoints
7434                .peek()
7435                .map(|(_, c)| c.is_uppercase())
7436                .unwrap_or(false);
7437
7438            if !current_upper && next_upper {
7439                return Some(&text[start_index..index]);
7440            }
7441        }
7442
7443        index = text.len();
7444        if start_index < text.len() {
7445            return Some(&text[start_index..]);
7446        }
7447        None
7448    })
7449    .flat_map(|word| word.split_inclusive('_'))
7450}
7451
7452trait RangeToAnchorExt {
7453    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor>;
7454}
7455
7456impl<T: ToOffset> RangeToAnchorExt for Range<T> {
7457    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor> {
7458        snapshot.anchor_after(self.start)..snapshot.anchor_before(self.end)
7459    }
7460}