editor.rs

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