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