editor.rs

   1#![allow(rustdoc::private_intra_doc_links)]
   2//! This is the place where everything editor-related is stored (data-wise) and displayed (ui-wise).
   3//! The main point of interest in this crate is [`Editor`] type, which is used in every other Zed part as a user input element.
   4//! It comes in different flavors: single line, multiline and a fixed height one.
   5//!
   6//! Editor contains of multiple large submodules:
   7//! * [`element`] — the place where all rendering happens
   8//! * [`display_map`] - chunks up text in the editor into the logical blocks, establishes coordinates and mapping between each of them.
   9//!   Contains all metadata related to text transformations (folds, fake inlay text insertions, soft wraps, tab markup, etc.).
  10//! * [`inlay_hint_cache`] - is a storage of inlay hints out of LSP requests, responsible for querying LSP and updating `display_map`'s state accordingly.
  11//!
  12//! All other submodules and structs are mostly concerned with holding editor data about the way it displays current buffer region(s).
  13//!
  14//! If you're looking to improve Vim mode, you should check out Vim crate that wraps Editor and overrides it's behaviour.
  15pub mod actions;
  16mod blink_manager;
  17pub mod display_map;
  18mod editor_settings;
  19mod element;
  20mod inlay_hint_cache;
  21
  22mod git;
  23mod highlight_matching_bracket;
  24mod hover_popover;
  25pub mod items;
  26mod link_go_to_definition;
  27mod mouse_context_menu;
  28pub mod movement;
  29mod persistence;
  30mod rust_analyzer_ext;
  31pub mod scroll;
  32mod selections_collection;
  33
  34#[cfg(test)]
  35mod editor_tests;
  36#[cfg(any(test, feature = "test-support"))]
  37pub mod test;
  38use ::git::diff::DiffHunk;
  39pub(crate) use actions::*;
  40use aho_corasick::AhoCorasick;
  41use anyhow::{anyhow, Context as _, Result};
  42use blink_manager::BlinkManager;
  43use client::{Collaborator, ParticipantIndex};
  44use clock::ReplicaId;
  45use collections::{BTreeMap, Bound, HashMap, HashSet, VecDeque};
  46use convert_case::{Case, Casing};
  47use copilot::Copilot;
  48pub use display_map::DisplayPoint;
  49use display_map::*;
  50pub use editor_settings::EditorSettings;
  51use element::LineWithInvisibles;
  52pub use element::{Cursor, EditorElement, HighlightedRange, HighlightedRangeLine};
  53use futures::FutureExt;
  54use fuzzy::{StringMatch, StringMatchCandidate};
  55use git::diff_hunk_to_display;
  56use gpui::{
  57    div, impl_actions, point, prelude::*, px, relative, rems, size, uniform_list, Action,
  58    AnyElement, AppContext, AsyncWindowContext, BackgroundExecutor, Bounds, ClipboardItem, Context,
  59    DispatchPhase, ElementId, EventEmitter, FocusHandle, FocusableView, FontId, FontStyle,
  60    FontWeight, HighlightStyle, Hsla, InteractiveText, KeyContext, Model, MouseButton,
  61    ParentElement, Pixels, Render, SharedString, Styled, StyledText, Subscription, Task, TextStyle,
  62    UniformListScrollHandle, View, ViewContext, ViewInputHandler, VisualContext, WeakView,
  63    WhiteSpace, WindowContext,
  64};
  65use highlight_matching_bracket::refresh_matching_bracket_highlights;
  66use hover_popover::{hide_hover, HoverState};
  67use inlay_hint_cache::{InlayHintCache, InlaySplice, InvalidationStrategy};
  68pub use items::MAX_TAB_TITLE_LEN;
  69use itertools::Itertools;
  70use language::{char_kind, CharKind};
  71use language::{
  72    language_settings::{self, all_language_settings, InlayHintSettings},
  73    markdown, point_from_lsp, AutoindentMode, BracketPair, Buffer, Capability, CodeAction,
  74    CodeLabel, Completion, CursorShape, Diagnostic, Documentation, IndentKind, IndentSize,
  75    Language, LanguageServerName, OffsetRangeExt, Point, Selection, SelectionGoal, TransactionId,
  76};
  77
  78use link_go_to_definition::{GoToDefinitionLink, InlayHighlight, LinkGoToDefinitionState};
  79use lsp::{DiagnosticSeverity, LanguageServerId};
  80use mouse_context_menu::MouseContextMenu;
  81use movement::TextLayoutDetails;
  82use multi_buffer::ToOffsetUtf16;
  83pub use multi_buffer::{
  84    Anchor, AnchorRangeExt, ExcerptId, ExcerptRange, MultiBuffer, MultiBufferSnapshot, ToOffset,
  85    ToPoint,
  86};
  87use ordered_float::OrderedFloat;
  88use parking_lot::RwLock;
  89use project::{FormatTrigger, Location, Project, ProjectPath, ProjectTransaction};
  90use rand::prelude::*;
  91use rpc::proto::*;
  92use scroll::{Autoscroll, OngoingScroll, ScrollAnchor, ScrollManager, ScrollbarAutoHide};
  93use selections_collection::{resolve_multiple, MutableSelectionsCollection, SelectionsCollection};
  94use serde::{Deserialize, Serialize};
  95use settings::{Settings, SettingsStore};
  96use smallvec::SmallVec;
  97use snippet::Snippet;
  98use std::{
  99    any::TypeId,
 100    borrow::Cow,
 101    cmp::{self, Ordering, Reverse},
 102    mem,
 103    num::NonZeroU32,
 104    ops::{ControlFlow, Deref, DerefMut, Range, RangeInclusive},
 105    path::Path,
 106    sync::Arc,
 107    sync::Weak,
 108    time::{Duration, Instant},
 109};
 110pub use sum_tree::Bias;
 111use sum_tree::TreeMap;
 112use text::{BufferId, OffsetUtf16, Rope};
 113use theme::{
 114    observe_buffer_font_size_adjustment, ActiveTheme, PlayerColor, StatusColors, SyntaxTheme,
 115    ThemeColors, ThemeSettings,
 116};
 117use ui::{
 118    h_flex, prelude::*, ButtonSize, ButtonStyle, IconButton, IconName, IconSize, ListItem, Popover,
 119    Tooltip,
 120};
 121use util::{post_inc, RangeExt, ResultExt, TryFutureExt};
 122use workspace::{searchable::SearchEvent, ItemNavHistory, Pane, SplitDirection, ViewId, Workspace};
 123
 124const CURSOR_BLINK_INTERVAL: Duration = Duration::from_millis(500);
 125const MAX_LINE_LEN: usize = 1024;
 126const MIN_NAVIGATION_HISTORY_ROW_DELTA: i64 = 10;
 127const MAX_SELECTION_HISTORY_LEN: usize = 1024;
 128const COPILOT_DEBOUNCE_TIMEOUT: Duration = Duration::from_millis(75);
 129pub(crate) const CURSORS_VISIBLE_FOR: Duration = Duration::from_millis(2000);
 130#[doc(hidden)]
 131pub const CODE_ACTIONS_DEBOUNCE_TIMEOUT: Duration = Duration::from_millis(250);
 132#[doc(hidden)]
 133pub const DOCUMENT_HIGHLIGHTS_DEBOUNCE_TIMEOUT: Duration = Duration::from_millis(75);
 134
 135pub(crate) const FORMAT_TIMEOUT: Duration = Duration::from_secs(2);
 136
 137pub fn render_parsed_markdown(
 138    element_id: impl Into<ElementId>,
 139    parsed: &language::ParsedMarkdown,
 140    editor_style: &EditorStyle,
 141    workspace: Option<WeakView<Workspace>>,
 142    cx: &mut ViewContext<Editor>,
 143) -> InteractiveText {
 144    let code_span_background_color = cx
 145        .theme()
 146        .colors()
 147        .editor_document_highlight_read_background;
 148
 149    let highlights = gpui::combine_highlights(
 150        parsed.highlights.iter().filter_map(|(range, highlight)| {
 151            let highlight = highlight.to_highlight_style(&editor_style.syntax)?;
 152            Some((range.clone(), highlight))
 153        }),
 154        parsed
 155            .regions
 156            .iter()
 157            .zip(&parsed.region_ranges)
 158            .filter_map(|(region, range)| {
 159                if region.code {
 160                    Some((
 161                        range.clone(),
 162                        HighlightStyle {
 163                            background_color: Some(code_span_background_color),
 164                            ..Default::default()
 165                        },
 166                    ))
 167                } else {
 168                    None
 169                }
 170            }),
 171    );
 172
 173    let mut links = Vec::new();
 174    let mut link_ranges = Vec::new();
 175    for (range, region) in parsed.region_ranges.iter().zip(&parsed.regions) {
 176        if let Some(link) = region.link.clone() {
 177            links.push(link);
 178            link_ranges.push(range.clone());
 179        }
 180    }
 181
 182    InteractiveText::new(
 183        element_id,
 184        StyledText::new(parsed.text.clone()).with_highlights(&editor_style.text, highlights),
 185    )
 186    .on_click(link_ranges, move |clicked_range_ix, cx| {
 187        match &links[clicked_range_ix] {
 188            markdown::Link::Web { url } => cx.open_url(url),
 189            markdown::Link::Path { path } => {
 190                if let Some(workspace) = &workspace {
 191                    _ = workspace.update(cx, |workspace, cx| {
 192                        workspace.open_abs_path(path.clone(), false, cx).detach();
 193                    });
 194                }
 195            }
 196        }
 197    })
 198}
 199
 200#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
 201pub(crate) enum InlayId {
 202    Suggestion(usize),
 203    Hint(usize),
 204}
 205
 206impl InlayId {
 207    fn id(&self) -> usize {
 208        match self {
 209            Self::Suggestion(id) => *id,
 210            Self::Hint(id) => *id,
 211        }
 212    }
 213}
 214
 215enum DocumentHighlightRead {}
 216enum DocumentHighlightWrite {}
 217enum InputComposition {}
 218
 219#[derive(Copy, Clone, PartialEq, Eq)]
 220pub enum Direction {
 221    Prev,
 222    Next,
 223}
 224
 225pub fn init_settings(cx: &mut AppContext) {
 226    EditorSettings::register(cx);
 227}
 228
 229pub fn init(cx: &mut AppContext) {
 230    init_settings(cx);
 231
 232    workspace::register_project_item::<Editor>(cx);
 233    workspace::register_followable_item::<Editor>(cx);
 234    workspace::register_deserializable_item::<Editor>(cx);
 235    cx.observe_new_views(
 236        |workspace: &mut Workspace, _cx: &mut ViewContext<Workspace>| {
 237            workspace.register_action(Editor::new_file);
 238            workspace.register_action(Editor::new_file_in_direction);
 239        },
 240    )
 241    .detach();
 242
 243    cx.on_action(move |_: &workspace::NewFile, cx| {
 244        let app_state = cx.global::<Weak<workspace::AppState>>();
 245        if let Some(app_state) = app_state.upgrade() {
 246            workspace::open_new(&app_state, cx, |workspace, cx| {
 247                Editor::new_file(workspace, &Default::default(), cx)
 248            })
 249            .detach();
 250        }
 251    });
 252    cx.on_action(move |_: &workspace::NewWindow, cx| {
 253        let app_state = cx.global::<Weak<workspace::AppState>>();
 254        if let Some(app_state) = app_state.upgrade() {
 255            workspace::open_new(&app_state, cx, |workspace, cx| {
 256                Editor::new_file(workspace, &Default::default(), cx)
 257            })
 258            .detach();
 259        }
 260    });
 261}
 262
 263trait InvalidationRegion {
 264    fn ranges(&self) -> &[Range<Anchor>];
 265}
 266
 267#[derive(Clone, Debug, PartialEq)]
 268pub enum SelectPhase {
 269    Begin {
 270        position: DisplayPoint,
 271        add: bool,
 272        click_count: usize,
 273    },
 274    BeginColumnar {
 275        position: DisplayPoint,
 276        goal_column: u32,
 277    },
 278    Extend {
 279        position: DisplayPoint,
 280        click_count: usize,
 281    },
 282    Update {
 283        position: DisplayPoint,
 284        goal_column: u32,
 285        scroll_delta: gpui::Point<f32>,
 286    },
 287    End,
 288}
 289
 290#[derive(Clone, Debug)]
 291pub(crate) enum SelectMode {
 292    Character,
 293    Word(Range<Anchor>),
 294    Line(Range<Anchor>),
 295    All,
 296}
 297
 298#[derive(Copy, Clone, PartialEq, Eq, Debug)]
 299pub enum EditorMode {
 300    SingleLine,
 301    AutoHeight { max_lines: usize },
 302    Full,
 303}
 304
 305#[derive(Clone, Debug)]
 306pub enum SoftWrap {
 307    None,
 308    EditorWidth,
 309    Column(u32),
 310}
 311
 312#[derive(Clone)]
 313pub struct EditorStyle {
 314    pub background: Hsla,
 315    pub local_player: PlayerColor,
 316    pub text: TextStyle,
 317    pub scrollbar_width: Pixels,
 318    pub syntax: Arc<SyntaxTheme>,
 319    pub status: StatusColors,
 320    pub inlays_style: HighlightStyle,
 321    pub suggestions_style: HighlightStyle,
 322}
 323
 324impl Default for EditorStyle {
 325    fn default() -> Self {
 326        Self {
 327            background: Hsla::default(),
 328            local_player: PlayerColor::default(),
 329            text: TextStyle::default(),
 330            scrollbar_width: Pixels::default(),
 331            syntax: Default::default(),
 332            // HACK: Status colors don't have a real default.
 333            // We should look into removing the status colors from the editor
 334            // style and retrieve them directly from the theme.
 335            status: StatusColors::dark(),
 336            inlays_style: HighlightStyle::default(),
 337            suggestions_style: HighlightStyle::default(),
 338        }
 339    }
 340}
 341
 342type CompletionId = usize;
 343
 344// type GetFieldEditorTheme = dyn Fn(&theme::Theme) -> theme::FieldEditor;
 345// type OverrideTextStyle = dyn Fn(&EditorStyle) -> Option<HighlightStyle>;
 346
 347type BackgroundHighlight = (fn(&ThemeColors) -> Hsla, Vec<Range<Anchor>>);
 348type InlayBackgroundHighlight = (fn(&ThemeColors) -> Hsla, Vec<InlayHighlight>);
 349
 350pub struct Editor {
 351    handle: WeakView<Self>,
 352    focus_handle: FocusHandle,
 353    buffer: Model<MultiBuffer>,
 354    display_map: Model<DisplayMap>,
 355    pub selections: SelectionsCollection,
 356    pub scroll_manager: ScrollManager,
 357    columnar_selection_tail: Option<Anchor>,
 358    add_selections_state: Option<AddSelectionsState>,
 359    select_next_state: Option<SelectNextState>,
 360    select_prev_state: Option<SelectNextState>,
 361    selection_history: SelectionHistory,
 362    autoclose_regions: Vec<AutocloseRegion>,
 363    snippet_stack: InvalidationStack<SnippetState>,
 364    select_larger_syntax_node_stack: Vec<Box<[Selection<usize>]>>,
 365    ime_transaction: Option<TransactionId>,
 366    active_diagnostics: Option<ActiveDiagnosticGroup>,
 367    soft_wrap_mode_override: Option<language_settings::SoftWrap>,
 368    project: Option<Model<Project>>,
 369    completion_provider: Option<Box<dyn CompletionProvider>>,
 370    collaboration_hub: Option<Box<dyn CollaborationHub>>,
 371    blink_manager: Model<BlinkManager>,
 372    show_cursor_names: bool,
 373    hovered_cursors: HashMap<HoveredCursor, Task<()>>,
 374    pub show_local_selections: bool,
 375    mode: EditorMode,
 376    show_gutter: bool,
 377    show_wrap_guides: Option<bool>,
 378    placeholder_text: Option<Arc<str>>,
 379    highlighted_rows: Option<Range<u32>>,
 380    background_highlights: BTreeMap<TypeId, BackgroundHighlight>,
 381    inlay_background_highlights: TreeMap<Option<TypeId>, InlayBackgroundHighlight>,
 382    nav_history: Option<ItemNavHistory>,
 383    context_menu: RwLock<Option<ContextMenu>>,
 384    mouse_context_menu: Option<MouseContextMenu>,
 385    completion_tasks: Vec<(CompletionId, Task<Option<()>>)>,
 386    next_completion_id: CompletionId,
 387    available_code_actions: Option<(Model<Buffer>, Arc<[CodeAction]>)>,
 388    code_actions_task: Option<Task<()>>,
 389    document_highlights_task: Option<Task<()>>,
 390    pending_rename: Option<RenameState>,
 391    searchable: bool,
 392    cursor_shape: CursorShape,
 393    collapse_matches: bool,
 394    autoindent_mode: Option<AutoindentMode>,
 395    workspace: Option<(WeakView<Workspace>, i64)>,
 396    keymap_context_layers: BTreeMap<TypeId, KeyContext>,
 397    input_enabled: bool,
 398    read_only: bool,
 399    leader_peer_id: Option<PeerId>,
 400    remote_id: Option<ViewId>,
 401    hover_state: HoverState,
 402    gutter_hovered: bool,
 403    link_go_to_definition_state: LinkGoToDefinitionState,
 404    copilot_state: CopilotState,
 405    inlay_hint_cache: InlayHintCache,
 406    next_inlay_id: usize,
 407    _subscriptions: Vec<Subscription>,
 408    pixel_position_of_newest_cursor: Option<gpui::Point<Pixels>>,
 409    gutter_width: Pixels,
 410    style: Option<EditorStyle>,
 411    editor_actions: Vec<Box<dyn Fn(&mut ViewContext<Self>)>>,
 412    show_copilot_suggestions: bool,
 413    use_autoclose: bool,
 414}
 415
 416pub struct EditorSnapshot {
 417    pub mode: EditorMode,
 418    show_gutter: bool,
 419    pub display_snapshot: DisplaySnapshot,
 420    pub placeholder_text: Option<Arc<str>>,
 421    is_focused: bool,
 422    scroll_anchor: ScrollAnchor,
 423    ongoing_scroll: OngoingScroll,
 424}
 425
 426pub struct GutterDimensions {
 427    pub padding: Pixels,
 428    pub width: Pixels,
 429    pub margin: Pixels,
 430}
 431
 432impl Default for GutterDimensions {
 433    fn default() -> Self {
 434        Self {
 435            padding: Pixels::ZERO,
 436            width: Pixels::ZERO,
 437            margin: Pixels::ZERO,
 438        }
 439    }
 440}
 441
 442#[derive(Debug)]
 443pub struct RemoteSelection {
 444    pub replica_id: ReplicaId,
 445    pub selection: Selection<Anchor>,
 446    pub cursor_shape: CursorShape,
 447    pub peer_id: PeerId,
 448    pub line_mode: bool,
 449    pub participant_index: Option<ParticipantIndex>,
 450    pub user_name: Option<SharedString>,
 451}
 452
 453#[derive(Clone, Debug)]
 454struct SelectionHistoryEntry {
 455    selections: Arc<[Selection<Anchor>]>,
 456    select_next_state: Option<SelectNextState>,
 457    select_prev_state: Option<SelectNextState>,
 458    add_selections_state: Option<AddSelectionsState>,
 459}
 460
 461enum SelectionHistoryMode {
 462    Normal,
 463    Undoing,
 464    Redoing,
 465}
 466
 467#[derive(Clone, PartialEq, Eq, Hash)]
 468struct HoveredCursor {
 469    replica_id: u16,
 470    selection_id: usize,
 471}
 472
 473impl Default for SelectionHistoryMode {
 474    fn default() -> Self {
 475        Self::Normal
 476    }
 477}
 478
 479#[derive(Default)]
 480struct SelectionHistory {
 481    #[allow(clippy::type_complexity)]
 482    selections_by_transaction:
 483        HashMap<TransactionId, (Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)>,
 484    mode: SelectionHistoryMode,
 485    undo_stack: VecDeque<SelectionHistoryEntry>,
 486    redo_stack: VecDeque<SelectionHistoryEntry>,
 487}
 488
 489impl SelectionHistory {
 490    fn insert_transaction(
 491        &mut self,
 492        transaction_id: TransactionId,
 493        selections: Arc<[Selection<Anchor>]>,
 494    ) {
 495        self.selections_by_transaction
 496            .insert(transaction_id, (selections, None));
 497    }
 498
 499    #[allow(clippy::type_complexity)]
 500    fn transaction(
 501        &self,
 502        transaction_id: TransactionId,
 503    ) -> Option<&(Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)> {
 504        self.selections_by_transaction.get(&transaction_id)
 505    }
 506
 507    #[allow(clippy::type_complexity)]
 508    fn transaction_mut(
 509        &mut self,
 510        transaction_id: TransactionId,
 511    ) -> Option<&mut (Arc<[Selection<Anchor>]>, Option<Arc<[Selection<Anchor>]>>)> {
 512        self.selections_by_transaction.get_mut(&transaction_id)
 513    }
 514
 515    fn push(&mut self, entry: SelectionHistoryEntry) {
 516        if !entry.selections.is_empty() {
 517            match self.mode {
 518                SelectionHistoryMode::Normal => {
 519                    self.push_undo(entry);
 520                    self.redo_stack.clear();
 521                }
 522                SelectionHistoryMode::Undoing => self.push_redo(entry),
 523                SelectionHistoryMode::Redoing => self.push_undo(entry),
 524            }
 525        }
 526    }
 527
 528    fn push_undo(&mut self, entry: SelectionHistoryEntry) {
 529        if self
 530            .undo_stack
 531            .back()
 532            .map_or(true, |e| e.selections != entry.selections)
 533        {
 534            self.undo_stack.push_back(entry);
 535            if self.undo_stack.len() > MAX_SELECTION_HISTORY_LEN {
 536                self.undo_stack.pop_front();
 537            }
 538        }
 539    }
 540
 541    fn push_redo(&mut self, entry: SelectionHistoryEntry) {
 542        if self
 543            .redo_stack
 544            .back()
 545            .map_or(true, |e| e.selections != entry.selections)
 546        {
 547            self.redo_stack.push_back(entry);
 548            if self.redo_stack.len() > MAX_SELECTION_HISTORY_LEN {
 549                self.redo_stack.pop_front();
 550            }
 551        }
 552    }
 553}
 554
 555#[derive(Clone, Debug)]
 556struct AddSelectionsState {
 557    above: bool,
 558    stack: Vec<usize>,
 559}
 560
 561#[derive(Clone)]
 562struct SelectNextState {
 563    query: AhoCorasick,
 564    wordwise: bool,
 565    done: bool,
 566}
 567
 568impl std::fmt::Debug for SelectNextState {
 569    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 570        f.debug_struct(std::any::type_name::<Self>())
 571            .field("wordwise", &self.wordwise)
 572            .field("done", &self.done)
 573            .finish()
 574    }
 575}
 576
 577#[derive(Debug)]
 578struct AutocloseRegion {
 579    selection_id: usize,
 580    range: Range<Anchor>,
 581    pair: BracketPair,
 582}
 583
 584#[derive(Debug)]
 585struct SnippetState {
 586    ranges: Vec<Vec<Range<Anchor>>>,
 587    active_index: usize,
 588}
 589
 590#[doc(hidden)]
 591pub struct RenameState {
 592    pub range: Range<Anchor>,
 593    pub old_name: Arc<str>,
 594    pub editor: View<Editor>,
 595    block_id: BlockId,
 596}
 597
 598struct InvalidationStack<T>(Vec<T>);
 599
 600enum ContextMenu {
 601    Completions(CompletionsMenu),
 602    CodeActions(CodeActionsMenu),
 603}
 604
 605impl ContextMenu {
 606    fn select_first(
 607        &mut self,
 608        project: Option<&Model<Project>>,
 609        cx: &mut ViewContext<Editor>,
 610    ) -> bool {
 611        if self.visible() {
 612            match self {
 613                ContextMenu::Completions(menu) => menu.select_first(project, cx),
 614                ContextMenu::CodeActions(menu) => menu.select_first(cx),
 615            }
 616            true
 617        } else {
 618            false
 619        }
 620    }
 621
 622    fn select_prev(
 623        &mut self,
 624        project: Option<&Model<Project>>,
 625        cx: &mut ViewContext<Editor>,
 626    ) -> bool {
 627        if self.visible() {
 628            match self {
 629                ContextMenu::Completions(menu) => menu.select_prev(project, cx),
 630                ContextMenu::CodeActions(menu) => menu.select_prev(cx),
 631            }
 632            true
 633        } else {
 634            false
 635        }
 636    }
 637
 638    fn select_next(
 639        &mut self,
 640        project: Option<&Model<Project>>,
 641        cx: &mut ViewContext<Editor>,
 642    ) -> bool {
 643        if self.visible() {
 644            match self {
 645                ContextMenu::Completions(menu) => menu.select_next(project, cx),
 646                ContextMenu::CodeActions(menu) => menu.select_next(cx),
 647            }
 648            true
 649        } else {
 650            false
 651        }
 652    }
 653
 654    fn select_last(
 655        &mut self,
 656        project: Option<&Model<Project>>,
 657        cx: &mut ViewContext<Editor>,
 658    ) -> bool {
 659        if self.visible() {
 660            match self {
 661                ContextMenu::Completions(menu) => menu.select_last(project, cx),
 662                ContextMenu::CodeActions(menu) => menu.select_last(cx),
 663            }
 664            true
 665        } else {
 666            false
 667        }
 668    }
 669
 670    fn visible(&self) -> bool {
 671        match self {
 672            ContextMenu::Completions(menu) => menu.visible(),
 673            ContextMenu::CodeActions(menu) => menu.visible(),
 674        }
 675    }
 676
 677    fn render(
 678        &self,
 679        cursor_position: DisplayPoint,
 680        style: &EditorStyle,
 681        max_height: Pixels,
 682        workspace: Option<WeakView<Workspace>>,
 683        cx: &mut ViewContext<Editor>,
 684    ) -> (DisplayPoint, AnyElement) {
 685        match self {
 686            ContextMenu::Completions(menu) => (
 687                cursor_position,
 688                menu.render(style, max_height, workspace, cx),
 689            ),
 690            ContextMenu::CodeActions(menu) => menu.render(cursor_position, style, max_height, cx),
 691        }
 692    }
 693}
 694
 695#[derive(Clone)]
 696struct CompletionsMenu {
 697    id: CompletionId,
 698    initial_position: Anchor,
 699    buffer: Model<Buffer>,
 700    completions: Arc<RwLock<Box<[Completion]>>>,
 701    match_candidates: Arc<[StringMatchCandidate]>,
 702    matches: Arc<[StringMatch]>,
 703    selected_item: usize,
 704    scroll_handle: UniformListScrollHandle,
 705}
 706
 707impl CompletionsMenu {
 708    fn select_first(&mut self, project: Option<&Model<Project>>, cx: &mut ViewContext<Editor>) {
 709        self.selected_item = 0;
 710        self.scroll_handle.scroll_to_item(self.selected_item);
 711        self.attempt_resolve_selected_completion_documentation(project, cx);
 712        cx.notify();
 713    }
 714
 715    fn select_prev(&mut self, project: Option<&Model<Project>>, cx: &mut ViewContext<Editor>) {
 716        if self.selected_item > 0 {
 717            self.selected_item -= 1;
 718        } else {
 719            self.selected_item = self.matches.len() - 1;
 720        }
 721        self.scroll_handle.scroll_to_item(self.selected_item);
 722        self.attempt_resolve_selected_completion_documentation(project, cx);
 723        cx.notify();
 724    }
 725
 726    fn select_next(&mut self, project: Option<&Model<Project>>, cx: &mut ViewContext<Editor>) {
 727        if self.selected_item + 1 < self.matches.len() {
 728            self.selected_item += 1;
 729        } else {
 730            self.selected_item = 0;
 731        }
 732        self.scroll_handle.scroll_to_item(self.selected_item);
 733        self.attempt_resolve_selected_completion_documentation(project, cx);
 734        cx.notify();
 735    }
 736
 737    fn select_last(&mut self, project: Option<&Model<Project>>, cx: &mut ViewContext<Editor>) {
 738        self.selected_item = self.matches.len() - 1;
 739        self.scroll_handle.scroll_to_item(self.selected_item);
 740        self.attempt_resolve_selected_completion_documentation(project, cx);
 741        cx.notify();
 742    }
 743
 744    fn pre_resolve_completion_documentation(
 745        &self,
 746        editor: &Editor,
 747        cx: &mut ViewContext<Editor>,
 748    ) -> Option<Task<()>> {
 749        let settings = EditorSettings::get_global(cx);
 750        if !settings.show_completion_documentation {
 751            return None;
 752        }
 753
 754        let Some(provider) = editor.completion_provider.as_ref() else {
 755            return None;
 756        };
 757
 758        let resolve_task = provider.resolve_completions(
 759            self.matches.iter().map(|m| m.candidate_id).collect(),
 760            self.completions.clone(),
 761            cx,
 762        );
 763
 764        return Some(cx.spawn(move |this, mut cx| async move {
 765            if let Some(true) = resolve_task.await.log_err() {
 766                this.update(&mut cx, |_, cx| cx.notify()).ok();
 767            }
 768        }));
 769    }
 770
 771    fn attempt_resolve_selected_completion_documentation(
 772        &mut self,
 773        project: Option<&Model<Project>>,
 774        cx: &mut ViewContext<Editor>,
 775    ) {
 776        let settings = EditorSettings::get_global(cx);
 777        if !settings.show_completion_documentation {
 778            return;
 779        }
 780
 781        let completion_index = self.matches[self.selected_item].candidate_id;
 782        let Some(project) = project else {
 783            return;
 784        };
 785
 786        let resolve_task = project.update(cx, |project, cx| {
 787            project.resolve_completions(vec![completion_index], self.completions.clone(), cx)
 788        });
 789        cx.spawn(move |this, mut cx| async move {
 790            if let Some(true) = resolve_task.await.log_err() {
 791                this.update(&mut cx, |_, cx| cx.notify()).ok();
 792            }
 793        })
 794        .detach();
 795    }
 796
 797    fn visible(&self) -> bool {
 798        !self.matches.is_empty()
 799    }
 800
 801    fn render(
 802        &self,
 803        style: &EditorStyle,
 804        max_height: Pixels,
 805        workspace: Option<WeakView<Workspace>>,
 806        cx: &mut ViewContext<Editor>,
 807    ) -> AnyElement {
 808        let settings = EditorSettings::get_global(cx);
 809        let show_completion_documentation = settings.show_completion_documentation;
 810
 811        let widest_completion_ix = self
 812            .matches
 813            .iter()
 814            .enumerate()
 815            .max_by_key(|(_, mat)| {
 816                let completions = self.completions.read();
 817                let completion = &completions[mat.candidate_id];
 818                let documentation = &completion.documentation;
 819
 820                let mut len = completion.label.text.chars().count();
 821                if let Some(Documentation::SingleLine(text)) = documentation {
 822                    if show_completion_documentation {
 823                        len += text.chars().count();
 824                    }
 825                }
 826
 827                len
 828            })
 829            .map(|(ix, _)| ix);
 830
 831        let completions = self.completions.clone();
 832        let matches = self.matches.clone();
 833        let selected_item = self.selected_item;
 834        let style = style.clone();
 835
 836        let multiline_docs = {
 837            let mat = &self.matches[selected_item];
 838            let multiline_docs = match &self.completions.read()[mat.candidate_id].documentation {
 839                Some(Documentation::MultiLinePlainText(text)) => {
 840                    Some(div().child(SharedString::from(text.clone())))
 841                }
 842                Some(Documentation::MultiLineMarkdown(parsed)) => Some(div().child(
 843                    render_parsed_markdown("completions_markdown", parsed, &style, workspace, cx),
 844                )),
 845                _ => None,
 846            };
 847            multiline_docs.map(|div| {
 848                div.id("multiline_docs")
 849                    .max_h(max_height)
 850                    .flex_1()
 851                    .px_1p5()
 852                    .py_1()
 853                    .min_w(px(260.))
 854                    .max_w(px(640.))
 855                    .w(px(500.))
 856                    .overflow_y_scroll()
 857                    // Prevent a mouse down on documentation from being propagated to the editor,
 858                    // because that would move the cursor.
 859                    .on_mouse_down(MouseButton::Left, |_, cx| cx.stop_propagation())
 860            })
 861        };
 862
 863        let list = uniform_list(
 864            cx.view().clone(),
 865            "completions",
 866            matches.len(),
 867            move |_editor, range, cx| {
 868                let start_ix = range.start;
 869                let completions_guard = completions.read();
 870
 871                matches[range]
 872                    .iter()
 873                    .enumerate()
 874                    .map(|(ix, mat)| {
 875                        let item_ix = start_ix + ix;
 876                        let candidate_id = mat.candidate_id;
 877                        let completion = &completions_guard[candidate_id];
 878
 879                        let documentation = if show_completion_documentation {
 880                            &completion.documentation
 881                        } else {
 882                            &None
 883                        };
 884
 885                        let highlights = gpui::combine_highlights(
 886                            mat.ranges().map(|range| (range, FontWeight::BOLD.into())),
 887                            styled_runs_for_code_label(&completion.label, &style.syntax).map(
 888                                |(range, mut highlight)| {
 889                                    // Ignore font weight for syntax highlighting, as we'll use it
 890                                    // for fuzzy matches.
 891                                    highlight.font_weight = None;
 892                                    (range, highlight)
 893                                },
 894                            ),
 895                        );
 896                        let completion_label = StyledText::new(completion.label.text.clone())
 897                            .with_highlights(&style.text, highlights);
 898                        let documentation_label =
 899                            if let Some(Documentation::SingleLine(text)) = documentation {
 900                                if text.trim().is_empty() {
 901                                    None
 902                                } else {
 903                                    Some(
 904                                        h_flex().ml_4().child(
 905                                            Label::new(text.clone())
 906                                                .size(LabelSize::Small)
 907                                                .color(Color::Muted),
 908                                        ),
 909                                    )
 910                                }
 911                            } else {
 912                                None
 913                            };
 914
 915                        div().min_w(px(220.)).max_w(px(540.)).child(
 916                            ListItem::new(mat.candidate_id)
 917                                .inset(true)
 918                                .selected(item_ix == selected_item)
 919                                .on_click(cx.listener(move |editor, _event, cx| {
 920                                    cx.stop_propagation();
 921                                    editor
 922                                        .confirm_completion(
 923                                            &ConfirmCompletion {
 924                                                item_ix: Some(item_ix),
 925                                            },
 926                                            cx,
 927                                        )
 928                                        .map(|task| task.detach_and_log_err(cx));
 929                                }))
 930                                .child(h_flex().overflow_hidden().child(completion_label))
 931                                .end_slot::<Div>(documentation_label),
 932                        )
 933                    })
 934                    .collect()
 935            },
 936        )
 937        .max_h(max_height)
 938        .track_scroll(self.scroll_handle.clone())
 939        .with_width_from_item(widest_completion_ix);
 940
 941        Popover::new()
 942            .child(list)
 943            .when_some(multiline_docs, |popover, multiline_docs| {
 944                popover.aside(multiline_docs)
 945            })
 946            .into_any_element()
 947    }
 948
 949    pub async fn filter(&mut self, query: Option<&str>, executor: BackgroundExecutor) {
 950        let mut matches = if let Some(query) = query {
 951            fuzzy::match_strings(
 952                &self.match_candidates,
 953                query,
 954                query.chars().any(|c| c.is_uppercase()),
 955                100,
 956                &Default::default(),
 957                executor,
 958            )
 959            .await
 960        } else {
 961            self.match_candidates
 962                .iter()
 963                .enumerate()
 964                .map(|(candidate_id, candidate)| StringMatch {
 965                    candidate_id,
 966                    score: Default::default(),
 967                    positions: Default::default(),
 968                    string: candidate.string.clone(),
 969                })
 970                .collect()
 971        };
 972
 973        // Remove all candidates where the query's start does not match the start of any word in the candidate
 974        if let Some(query) = query {
 975            if let Some(query_start) = query.chars().next() {
 976                matches.retain(|string_match| {
 977                    split_words(&string_match.string).any(|word| {
 978                        // Check that the first codepoint of the word as lowercase matches the first
 979                        // codepoint of the query as lowercase
 980                        word.chars()
 981                            .flat_map(|codepoint| codepoint.to_lowercase())
 982                            .zip(query_start.to_lowercase())
 983                            .all(|(word_cp, query_cp)| word_cp == query_cp)
 984                    })
 985                });
 986            }
 987        }
 988
 989        let completions = self.completions.read();
 990        matches.sort_unstable_by_key(|mat| {
 991            let completion = &completions[mat.candidate_id];
 992            (
 993                completion.lsp_completion.sort_text.as_ref(),
 994                Reverse(OrderedFloat(mat.score)),
 995                completion.sort_key(),
 996            )
 997        });
 998
 999        for mat in &mut matches {
1000            let completion = &completions[mat.candidate_id];
1001            mat.string = completion.label.text.clone();
1002            for position in &mut mat.positions {
1003                *position += completion.label.filter_range.start;
1004            }
1005        }
1006        drop(completions);
1007
1008        self.matches = matches.into();
1009        self.selected_item = 0;
1010    }
1011}
1012
1013#[derive(Clone)]
1014struct CodeActionsMenu {
1015    actions: Arc<[CodeAction]>,
1016    buffer: Model<Buffer>,
1017    selected_item: usize,
1018    scroll_handle: UniformListScrollHandle,
1019    deployed_from_indicator: bool,
1020}
1021
1022impl CodeActionsMenu {
1023    fn select_first(&mut self, cx: &mut ViewContext<Editor>) {
1024        self.selected_item = 0;
1025        self.scroll_handle.scroll_to_item(self.selected_item);
1026        cx.notify()
1027    }
1028
1029    fn select_prev(&mut self, cx: &mut ViewContext<Editor>) {
1030        if self.selected_item > 0 {
1031            self.selected_item -= 1;
1032        } else {
1033            self.selected_item = self.actions.len() - 1;
1034        }
1035        self.scroll_handle.scroll_to_item(self.selected_item);
1036        cx.notify();
1037    }
1038
1039    fn select_next(&mut self, cx: &mut ViewContext<Editor>) {
1040        if self.selected_item + 1 < self.actions.len() {
1041            self.selected_item += 1;
1042        } else {
1043            self.selected_item = 0;
1044        }
1045        self.scroll_handle.scroll_to_item(self.selected_item);
1046        cx.notify();
1047    }
1048
1049    fn select_last(&mut self, cx: &mut ViewContext<Editor>) {
1050        self.selected_item = self.actions.len() - 1;
1051        self.scroll_handle.scroll_to_item(self.selected_item);
1052        cx.notify()
1053    }
1054
1055    fn visible(&self) -> bool {
1056        !self.actions.is_empty()
1057    }
1058
1059    fn render(
1060        &self,
1061        mut cursor_position: DisplayPoint,
1062        _style: &EditorStyle,
1063        max_height: Pixels,
1064        cx: &mut ViewContext<Editor>,
1065    ) -> (DisplayPoint, AnyElement) {
1066        let actions = self.actions.clone();
1067        let selected_item = self.selected_item;
1068
1069        let element = uniform_list(
1070            cx.view().clone(),
1071            "code_actions_menu",
1072            self.actions.len(),
1073            move |_this, range, cx| {
1074                actions[range.clone()]
1075                    .iter()
1076                    .enumerate()
1077                    .map(|(ix, action)| {
1078                        let item_ix = range.start + ix;
1079                        let selected = selected_item == item_ix;
1080                        let colors = cx.theme().colors();
1081                        div()
1082                            .px_2()
1083                            .text_color(colors.text)
1084                            .when(selected, |style| {
1085                                style
1086                                    .bg(colors.element_active)
1087                                    .text_color(colors.text_accent)
1088                            })
1089                            .hover(|style| {
1090                                style
1091                                    .bg(colors.element_hover)
1092                                    .text_color(colors.text_accent)
1093                            })
1094                            .on_mouse_down(
1095                                MouseButton::Left,
1096                                cx.listener(move |editor, _, cx| {
1097                                    cx.stop_propagation();
1098                                    editor
1099                                        .confirm_code_action(
1100                                            &ConfirmCodeAction {
1101                                                item_ix: Some(item_ix),
1102                                            },
1103                                            cx,
1104                                        )
1105                                        .map(|task| task.detach_and_log_err(cx));
1106                                }),
1107                            )
1108                            // TASK: It would be good to make lsp_action.title a SharedString to avoid allocating here.
1109                            .child(SharedString::from(action.lsp_action.title.clone()))
1110                    })
1111                    .collect()
1112            },
1113        )
1114        .elevation_1(cx)
1115        .px_2()
1116        .py_1()
1117        .max_h(max_height)
1118        .track_scroll(self.scroll_handle.clone())
1119        .with_width_from_item(
1120            self.actions
1121                .iter()
1122                .enumerate()
1123                .max_by_key(|(_, action)| action.lsp_action.title.chars().count())
1124                .map(|(ix, _)| ix),
1125        )
1126        .into_any_element();
1127
1128        if self.deployed_from_indicator {
1129            *cursor_position.column_mut() = 0;
1130        }
1131
1132        (cursor_position, element)
1133    }
1134}
1135
1136pub(crate) struct CopilotState {
1137    excerpt_id: Option<ExcerptId>,
1138    pending_refresh: Task<Option<()>>,
1139    pending_cycling_refresh: Task<Option<()>>,
1140    cycled: bool,
1141    completions: Vec<copilot::Completion>,
1142    active_completion_index: usize,
1143    suggestion: Option<Inlay>,
1144}
1145
1146impl Default for CopilotState {
1147    fn default() -> Self {
1148        Self {
1149            excerpt_id: None,
1150            pending_cycling_refresh: Task::ready(Some(())),
1151            pending_refresh: Task::ready(Some(())),
1152            completions: Default::default(),
1153            active_completion_index: 0,
1154            cycled: false,
1155            suggestion: None,
1156        }
1157    }
1158}
1159
1160impl CopilotState {
1161    fn active_completion(&self) -> Option<&copilot::Completion> {
1162        self.completions.get(self.active_completion_index)
1163    }
1164
1165    fn text_for_active_completion(
1166        &self,
1167        cursor: Anchor,
1168        buffer: &MultiBufferSnapshot,
1169    ) -> Option<&str> {
1170        use language::ToOffset as _;
1171
1172        let completion = self.active_completion()?;
1173        let excerpt_id = self.excerpt_id?;
1174        let completion_buffer = buffer.buffer_for_excerpt(excerpt_id)?;
1175        if excerpt_id != cursor.excerpt_id
1176            || !completion.range.start.is_valid(completion_buffer)
1177            || !completion.range.end.is_valid(completion_buffer)
1178        {
1179            return None;
1180        }
1181
1182        let mut completion_range = completion.range.to_offset(&completion_buffer);
1183        let prefix_len = Self::common_prefix(
1184            completion_buffer.chars_for_range(completion_range.clone()),
1185            completion.text.chars(),
1186        );
1187        completion_range.start += prefix_len;
1188        let suffix_len = Self::common_prefix(
1189            completion_buffer.reversed_chars_for_range(completion_range.clone()),
1190            completion.text[prefix_len..].chars().rev(),
1191        );
1192        completion_range.end = completion_range.end.saturating_sub(suffix_len);
1193
1194        if completion_range.is_empty()
1195            && completion_range.start == cursor.text_anchor.to_offset(&completion_buffer)
1196        {
1197            Some(&completion.text[prefix_len..completion.text.len() - suffix_len])
1198        } else {
1199            None
1200        }
1201    }
1202
1203    fn cycle_completions(&mut self, direction: Direction) {
1204        match direction {
1205            Direction::Prev => {
1206                self.active_completion_index = if self.active_completion_index == 0 {
1207                    self.completions.len().saturating_sub(1)
1208                } else {
1209                    self.active_completion_index - 1
1210                };
1211            }
1212            Direction::Next => {
1213                if self.completions.len() == 0 {
1214                    self.active_completion_index = 0
1215                } else {
1216                    self.active_completion_index =
1217                        (self.active_completion_index + 1) % self.completions.len();
1218                }
1219            }
1220        }
1221    }
1222
1223    fn push_completion(&mut self, new_completion: copilot::Completion) {
1224        for completion in &self.completions {
1225            if completion.text == new_completion.text && completion.range == new_completion.range {
1226                return;
1227            }
1228        }
1229        self.completions.push(new_completion);
1230    }
1231
1232    fn common_prefix<T1: Iterator<Item = char>, T2: Iterator<Item = char>>(a: T1, b: T2) -> usize {
1233        a.zip(b)
1234            .take_while(|(a, b)| a == b)
1235            .map(|(a, _)| a.len_utf8())
1236            .sum()
1237    }
1238}
1239
1240#[derive(Debug)]
1241struct ActiveDiagnosticGroup {
1242    primary_range: Range<Anchor>,
1243    primary_message: String,
1244    blocks: HashMap<BlockId, Diagnostic>,
1245    is_valid: bool,
1246}
1247
1248#[derive(Serialize, Deserialize)]
1249pub struct ClipboardSelection {
1250    pub len: usize,
1251    pub is_entire_line: bool,
1252    pub first_line_indent: u32,
1253}
1254
1255#[derive(Debug)]
1256pub(crate) struct NavigationData {
1257    cursor_anchor: Anchor,
1258    cursor_position: Point,
1259    scroll_anchor: ScrollAnchor,
1260    scroll_top_row: u32,
1261}
1262
1263enum GotoDefinitionKind {
1264    Symbol,
1265    Type,
1266}
1267
1268#[derive(Debug, Clone)]
1269enum InlayHintRefreshReason {
1270    Toggle(bool),
1271    SettingsChange(InlayHintSettings),
1272    NewLinesShown,
1273    BufferEdited(HashSet<Arc<Language>>),
1274    RefreshRequested,
1275    ExcerptsRemoved(Vec<ExcerptId>),
1276}
1277impl InlayHintRefreshReason {
1278    fn description(&self) -> &'static str {
1279        match self {
1280            Self::Toggle(_) => "toggle",
1281            Self::SettingsChange(_) => "settings change",
1282            Self::NewLinesShown => "new lines shown",
1283            Self::BufferEdited(_) => "buffer edited",
1284            Self::RefreshRequested => "refresh requested",
1285            Self::ExcerptsRemoved(_) => "excerpts removed",
1286        }
1287    }
1288}
1289
1290impl Editor {
1291    pub fn single_line(cx: &mut ViewContext<Self>) -> Self {
1292        let buffer = cx.new_model(|cx| {
1293            Buffer::new(
1294                0,
1295                BufferId::new(cx.entity_id().as_u64()).unwrap(),
1296                String::new(),
1297            )
1298        });
1299        let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
1300        Self::new(EditorMode::SingleLine, buffer, None, cx)
1301    }
1302
1303    pub fn multi_line(cx: &mut ViewContext<Self>) -> Self {
1304        let buffer = cx.new_model(|cx| {
1305            Buffer::new(
1306                0,
1307                BufferId::new(cx.entity_id().as_u64()).unwrap(),
1308                String::new(),
1309            )
1310        });
1311        let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
1312        Self::new(EditorMode::Full, buffer, None, cx)
1313    }
1314
1315    pub fn auto_height(max_lines: usize, cx: &mut ViewContext<Self>) -> Self {
1316        let buffer = cx.new_model(|cx| {
1317            Buffer::new(
1318                0,
1319                BufferId::new(cx.entity_id().as_u64()).unwrap(),
1320                String::new(),
1321            )
1322        });
1323        let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
1324        Self::new(EditorMode::AutoHeight { max_lines }, buffer, None, cx)
1325    }
1326
1327    pub fn for_buffer(
1328        buffer: Model<Buffer>,
1329        project: Option<Model<Project>>,
1330        cx: &mut ViewContext<Self>,
1331    ) -> Self {
1332        let buffer = cx.new_model(|cx| MultiBuffer::singleton(buffer, cx));
1333        Self::new(EditorMode::Full, buffer, project, cx)
1334    }
1335
1336    pub fn for_multibuffer(
1337        buffer: Model<MultiBuffer>,
1338        project: Option<Model<Project>>,
1339        cx: &mut ViewContext<Self>,
1340    ) -> Self {
1341        Self::new(EditorMode::Full, buffer, project, cx)
1342    }
1343
1344    pub fn clone(&self, cx: &mut ViewContext<Self>) -> Self {
1345        let mut clone = Self::new(self.mode, self.buffer.clone(), self.project.clone(), cx);
1346        self.display_map.update(cx, |display_map, cx| {
1347            let snapshot = display_map.snapshot(cx);
1348            clone.display_map.update(cx, |display_map, cx| {
1349                display_map.set_state(&snapshot, cx);
1350            });
1351        });
1352        clone.selections.clone_state(&self.selections);
1353        clone.scroll_manager.clone_state(&self.scroll_manager);
1354        clone.searchable = self.searchable;
1355        clone
1356    }
1357
1358    fn new(
1359        mode: EditorMode,
1360        buffer: Model<MultiBuffer>,
1361        project: Option<Model<Project>>,
1362        cx: &mut ViewContext<Self>,
1363    ) -> Self {
1364        let style = cx.text_style();
1365        let font_size = style.font_size.to_pixels(cx.rem_size());
1366        let display_map = cx.new_model(|cx| {
1367            DisplayMap::new(buffer.clone(), style.font(), font_size, None, 2, 1, cx)
1368        });
1369
1370        let selections = SelectionsCollection::new(display_map.clone(), buffer.clone());
1371
1372        let blink_manager = cx.new_model(|cx| BlinkManager::new(CURSOR_BLINK_INTERVAL, cx));
1373
1374        let soft_wrap_mode_override =
1375            (mode == EditorMode::SingleLine).then(|| language_settings::SoftWrap::None);
1376
1377        let mut project_subscriptions = Vec::new();
1378        if mode == EditorMode::Full {
1379            if let Some(project) = project.as_ref() {
1380                if buffer.read(cx).is_singleton() {
1381                    project_subscriptions.push(cx.observe(project, |_, _, cx| {
1382                        cx.emit(EditorEvent::TitleChanged);
1383                    }));
1384                }
1385                project_subscriptions.push(cx.subscribe(project, |editor, _, event, cx| {
1386                    if let project::Event::RefreshInlayHints = event {
1387                        editor.refresh_inlay_hints(InlayHintRefreshReason::RefreshRequested, cx);
1388                    };
1389                }));
1390            }
1391        }
1392
1393        let inlay_hint_settings = inlay_hint_settings(
1394            selections.newest_anchor().head(),
1395            &buffer.read(cx).snapshot(cx),
1396            cx,
1397        );
1398
1399        let focus_handle = cx.focus_handle();
1400        cx.on_focus(&focus_handle, Self::handle_focus).detach();
1401        cx.on_blur(&focus_handle, Self::handle_blur).detach();
1402
1403        let mut this = Self {
1404            handle: cx.view().downgrade(),
1405            focus_handle,
1406            buffer: buffer.clone(),
1407            display_map: display_map.clone(),
1408            selections,
1409            scroll_manager: ScrollManager::new(),
1410            columnar_selection_tail: None,
1411            add_selections_state: None,
1412            select_next_state: None,
1413            select_prev_state: None,
1414            selection_history: Default::default(),
1415            autoclose_regions: Default::default(),
1416            snippet_stack: Default::default(),
1417            select_larger_syntax_node_stack: Vec::new(),
1418            ime_transaction: Default::default(),
1419            active_diagnostics: None,
1420            soft_wrap_mode_override,
1421            completion_provider: project.clone().map(|project| Box::new(project) as _),
1422            collaboration_hub: project.clone().map(|project| Box::new(project) as _),
1423            project,
1424            blink_manager: blink_manager.clone(),
1425            show_local_selections: true,
1426            mode,
1427            show_gutter: mode == EditorMode::Full,
1428            show_wrap_guides: None,
1429            placeholder_text: None,
1430            highlighted_rows: None,
1431            background_highlights: Default::default(),
1432            inlay_background_highlights: Default::default(),
1433            nav_history: None,
1434            context_menu: RwLock::new(None),
1435            mouse_context_menu: None,
1436            completion_tasks: Default::default(),
1437            next_completion_id: 0,
1438            next_inlay_id: 0,
1439            available_code_actions: Default::default(),
1440            code_actions_task: Default::default(),
1441            document_highlights_task: Default::default(),
1442            pending_rename: Default::default(),
1443            searchable: true,
1444            cursor_shape: Default::default(),
1445            autoindent_mode: Some(AutoindentMode::EachLine),
1446            collapse_matches: false,
1447            workspace: None,
1448            keymap_context_layers: Default::default(),
1449            input_enabled: true,
1450            read_only: false,
1451            use_autoclose: true,
1452            leader_peer_id: None,
1453            remote_id: None,
1454            hover_state: Default::default(),
1455            link_go_to_definition_state: Default::default(),
1456            copilot_state: Default::default(),
1457            inlay_hint_cache: InlayHintCache::new(inlay_hint_settings),
1458            gutter_hovered: false,
1459            pixel_position_of_newest_cursor: None,
1460            gutter_width: Default::default(),
1461            style: None,
1462            show_cursor_names: false,
1463            hovered_cursors: Default::default(),
1464            editor_actions: Default::default(),
1465            show_copilot_suggestions: mode == EditorMode::Full,
1466            _subscriptions: vec![
1467                cx.observe(&buffer, Self::on_buffer_changed),
1468                cx.subscribe(&buffer, Self::on_buffer_event),
1469                cx.observe(&display_map, Self::on_display_map_changed),
1470                cx.observe(&blink_manager, |_, _, cx| cx.notify()),
1471                cx.observe_global::<SettingsStore>(Self::settings_changed),
1472                observe_buffer_font_size_adjustment(cx, |_, cx| cx.notify()),
1473                cx.observe_window_activation(|editor, cx| {
1474                    let active = cx.is_window_active();
1475                    editor.blink_manager.update(cx, |blink_manager, cx| {
1476                        if active {
1477                            blink_manager.enable(cx);
1478                        } else {
1479                            blink_manager.show_cursor(cx);
1480                            blink_manager.disable(cx);
1481                        }
1482                    });
1483                }),
1484            ],
1485        };
1486
1487        this._subscriptions.extend(project_subscriptions);
1488
1489        this.end_selection(cx);
1490        this.scroll_manager.show_scrollbar(cx);
1491
1492        if mode == EditorMode::Full {
1493            let should_auto_hide_scrollbars = cx.should_auto_hide_scrollbars();
1494            cx.set_global(ScrollbarAutoHide(should_auto_hide_scrollbars));
1495        }
1496
1497        this.report_editor_event("open", None, cx);
1498        this
1499    }
1500
1501    fn key_context(&self, cx: &AppContext) -> KeyContext {
1502        let mut key_context = KeyContext::default();
1503        key_context.add("Editor");
1504        let mode = match self.mode {
1505            EditorMode::SingleLine => "single_line",
1506            EditorMode::AutoHeight { .. } => "auto_height",
1507            EditorMode::Full => "full",
1508        };
1509        key_context.set("mode", mode);
1510        if self.pending_rename.is_some() {
1511            key_context.add("renaming");
1512        }
1513        if self.context_menu_visible() {
1514            match self.context_menu.read().as_ref() {
1515                Some(ContextMenu::Completions(_)) => {
1516                    key_context.add("menu");
1517                    key_context.add("showing_completions")
1518                }
1519                Some(ContextMenu::CodeActions(_)) => {
1520                    key_context.add("menu");
1521                    key_context.add("showing_code_actions")
1522                }
1523                None => {}
1524            }
1525        }
1526
1527        for layer in self.keymap_context_layers.values() {
1528            key_context.extend(layer);
1529        }
1530
1531        if let Some(extension) = self
1532            .buffer
1533            .read(cx)
1534            .as_singleton()
1535            .and_then(|buffer| buffer.read(cx).file()?.path().extension()?.to_str())
1536        {
1537            key_context.set("extension", extension.to_string());
1538        }
1539
1540        key_context
1541    }
1542
1543    pub fn new_file(
1544        workspace: &mut Workspace,
1545        _: &workspace::NewFile,
1546        cx: &mut ViewContext<Workspace>,
1547    ) {
1548        let project = workspace.project().clone();
1549        if project.read(cx).is_remote() {
1550            cx.propagate();
1551        } else if let Some(buffer) = project
1552            .update(cx, |project, cx| project.create_buffer("", None, cx))
1553            .log_err()
1554        {
1555            workspace.add_item(
1556                Box::new(cx.new_view(|cx| Editor::for_buffer(buffer, Some(project.clone()), cx))),
1557                cx,
1558            );
1559        }
1560    }
1561
1562    pub fn new_file_in_direction(
1563        workspace: &mut Workspace,
1564        action: &workspace::NewFileInDirection,
1565        cx: &mut ViewContext<Workspace>,
1566    ) {
1567        let project = workspace.project().clone();
1568        if project.read(cx).is_remote() {
1569            cx.propagate();
1570        } else if let Some(buffer) = project
1571            .update(cx, |project, cx| project.create_buffer("", None, cx))
1572            .log_err()
1573        {
1574            workspace.split_item(
1575                action.0,
1576                Box::new(cx.new_view(|cx| Editor::for_buffer(buffer, Some(project.clone()), cx))),
1577                cx,
1578            );
1579        }
1580    }
1581
1582    pub fn replica_id(&self, cx: &AppContext) -> ReplicaId {
1583        self.buffer.read(cx).replica_id()
1584    }
1585
1586    pub fn leader_peer_id(&self) -> Option<PeerId> {
1587        self.leader_peer_id
1588    }
1589
1590    pub fn buffer(&self) -> &Model<MultiBuffer> {
1591        &self.buffer
1592    }
1593
1594    pub fn workspace(&self) -> Option<View<Workspace>> {
1595        self.workspace.as_ref()?.0.upgrade()
1596    }
1597
1598    pub fn pane(&self, cx: &AppContext) -> Option<View<Pane>> {
1599        self.workspace()?.read(cx).pane_for(&self.handle.upgrade()?)
1600    }
1601
1602    pub fn title<'a>(&self, cx: &'a AppContext) -> Cow<'a, str> {
1603        self.buffer().read(cx).title(cx)
1604    }
1605
1606    pub fn snapshot(&mut self, cx: &mut WindowContext) -> EditorSnapshot {
1607        EditorSnapshot {
1608            mode: self.mode,
1609            show_gutter: self.show_gutter,
1610            display_snapshot: self.display_map.update(cx, |map, cx| map.snapshot(cx)),
1611            scroll_anchor: self.scroll_manager.anchor(),
1612            ongoing_scroll: self.scroll_manager.ongoing_scroll(),
1613            placeholder_text: self.placeholder_text.clone(),
1614            is_focused: self.focus_handle.is_focused(cx),
1615        }
1616    }
1617
1618    pub fn language_at<'a, T: ToOffset>(
1619        &self,
1620        point: T,
1621        cx: &'a AppContext,
1622    ) -> Option<Arc<Language>> {
1623        self.buffer.read(cx).language_at(point, cx)
1624    }
1625
1626    pub fn file_at<'a, T: ToOffset>(
1627        &self,
1628        point: T,
1629        cx: &'a AppContext,
1630    ) -> Option<Arc<dyn language::File>> {
1631        self.buffer.read(cx).read(cx).file_at(point).cloned()
1632    }
1633
1634    pub fn active_excerpt(
1635        &self,
1636        cx: &AppContext,
1637    ) -> Option<(ExcerptId, Model<Buffer>, Range<text::Anchor>)> {
1638        self.buffer
1639            .read(cx)
1640            .excerpt_containing(self.selections.newest_anchor().head(), cx)
1641    }
1642
1643    pub fn mode(&self) -> EditorMode {
1644        self.mode
1645    }
1646
1647    pub fn collaboration_hub(&self) -> Option<&dyn CollaborationHub> {
1648        self.collaboration_hub.as_deref()
1649    }
1650
1651    pub fn set_collaboration_hub(&mut self, hub: Box<dyn CollaborationHub>) {
1652        self.collaboration_hub = Some(hub);
1653    }
1654
1655    pub fn set_completion_provider(&mut self, hub: Box<dyn CompletionProvider>) {
1656        self.completion_provider = Some(hub);
1657    }
1658
1659    pub fn placeholder_text(&self) -> Option<&str> {
1660        self.placeholder_text.as_deref()
1661    }
1662
1663    pub fn set_placeholder_text(
1664        &mut self,
1665        placeholder_text: impl Into<Arc<str>>,
1666        cx: &mut ViewContext<Self>,
1667    ) {
1668        let placeholder_text = Some(placeholder_text.into());
1669        if self.placeholder_text != placeholder_text {
1670            self.placeholder_text = placeholder_text;
1671            cx.notify();
1672        }
1673    }
1674
1675    pub fn set_cursor_shape(&mut self, cursor_shape: CursorShape, cx: &mut ViewContext<Self>) {
1676        self.cursor_shape = cursor_shape;
1677        cx.notify();
1678    }
1679
1680    pub fn set_collapse_matches(&mut self, collapse_matches: bool) {
1681        self.collapse_matches = collapse_matches;
1682    }
1683
1684    pub fn range_for_match<T: std::marker::Copy>(&self, range: &Range<T>) -> Range<T> {
1685        if self.collapse_matches {
1686            return range.start..range.start;
1687        }
1688        range.clone()
1689    }
1690
1691    pub fn set_clip_at_line_ends(&mut self, clip: bool, cx: &mut ViewContext<Self>) {
1692        if self.display_map.read(cx).clip_at_line_ends != clip {
1693            self.display_map
1694                .update(cx, |map, _| map.clip_at_line_ends = clip);
1695        }
1696    }
1697
1698    pub fn set_keymap_context_layer<Tag: 'static>(
1699        &mut self,
1700        context: KeyContext,
1701        cx: &mut ViewContext<Self>,
1702    ) {
1703        self.keymap_context_layers
1704            .insert(TypeId::of::<Tag>(), context);
1705        cx.notify();
1706    }
1707
1708    pub fn remove_keymap_context_layer<Tag: 'static>(&mut self, cx: &mut ViewContext<Self>) {
1709        self.keymap_context_layers.remove(&TypeId::of::<Tag>());
1710        cx.notify();
1711    }
1712
1713    pub fn set_input_enabled(&mut self, input_enabled: bool) {
1714        self.input_enabled = input_enabled;
1715    }
1716
1717    pub fn set_autoindent(&mut self, autoindent: bool) {
1718        if autoindent {
1719            self.autoindent_mode = Some(AutoindentMode::EachLine);
1720        } else {
1721            self.autoindent_mode = None;
1722        }
1723    }
1724
1725    pub fn read_only(&self, cx: &AppContext) -> bool {
1726        self.read_only || self.buffer.read(cx).read_only()
1727    }
1728
1729    pub fn set_read_only(&mut self, read_only: bool) {
1730        self.read_only = read_only;
1731    }
1732
1733    pub fn set_use_autoclose(&mut self, autoclose: bool) {
1734        self.use_autoclose = autoclose;
1735    }
1736
1737    pub fn set_show_copilot_suggestions(&mut self, show_copilot_suggestions: bool) {
1738        self.show_copilot_suggestions = show_copilot_suggestions;
1739    }
1740
1741    fn selections_did_change(
1742        &mut self,
1743        local: bool,
1744        old_cursor_position: &Anchor,
1745        cx: &mut ViewContext<Self>,
1746    ) {
1747        if self.focus_handle.is_focused(cx) && self.leader_peer_id.is_none() {
1748            self.buffer.update(cx, |buffer, cx| {
1749                buffer.set_active_selections(
1750                    &self.selections.disjoint_anchors(),
1751                    self.selections.line_mode,
1752                    self.cursor_shape,
1753                    cx,
1754                )
1755            });
1756        }
1757
1758        let display_map = self
1759            .display_map
1760            .update(cx, |display_map, cx| display_map.snapshot(cx));
1761        let buffer = &display_map.buffer_snapshot;
1762        self.add_selections_state = None;
1763        self.select_next_state = None;
1764        self.select_prev_state = None;
1765        self.select_larger_syntax_node_stack.clear();
1766        self.invalidate_autoclose_regions(&self.selections.disjoint_anchors(), buffer);
1767        self.snippet_stack
1768            .invalidate(&self.selections.disjoint_anchors(), buffer);
1769        self.take_rename(false, cx);
1770
1771        let new_cursor_position = self.selections.newest_anchor().head();
1772
1773        self.push_to_nav_history(
1774            old_cursor_position.clone(),
1775            Some(new_cursor_position.to_point(buffer)),
1776            cx,
1777        );
1778
1779        if local {
1780            let new_cursor_position = self.selections.newest_anchor().head();
1781            let mut context_menu = self.context_menu.write();
1782            let completion_menu = match context_menu.as_ref() {
1783                Some(ContextMenu::Completions(menu)) => Some(menu),
1784
1785                _ => {
1786                    *context_menu = None;
1787                    None
1788                }
1789            };
1790
1791            if let Some(completion_menu) = completion_menu {
1792                let cursor_position = new_cursor_position.to_offset(buffer);
1793                let (word_range, kind) =
1794                    buffer.surrounding_word(completion_menu.initial_position.clone());
1795                if kind == Some(CharKind::Word)
1796                    && word_range.to_inclusive().contains(&cursor_position)
1797                {
1798                    let mut completion_menu = completion_menu.clone();
1799                    drop(context_menu);
1800
1801                    let query = Self::completion_query(buffer, cursor_position);
1802                    cx.spawn(move |this, mut cx| async move {
1803                        completion_menu
1804                            .filter(query.as_deref(), cx.background_executor().clone())
1805                            .await;
1806
1807                        this.update(&mut cx, |this, cx| {
1808                            let mut context_menu = this.context_menu.write();
1809                            let Some(ContextMenu::Completions(menu)) = context_menu.as_ref() else {
1810                                return;
1811                            };
1812
1813                            if menu.id > completion_menu.id {
1814                                return;
1815                            }
1816
1817                            *context_menu = Some(ContextMenu::Completions(completion_menu));
1818                            drop(context_menu);
1819                            cx.notify();
1820                        })
1821                    })
1822                    .detach();
1823
1824                    self.show_completions(&ShowCompletions, cx);
1825                } else {
1826                    drop(context_menu);
1827                    self.hide_context_menu(cx);
1828                }
1829            } else {
1830                drop(context_menu);
1831            }
1832
1833            hide_hover(self, cx);
1834
1835            if old_cursor_position.to_display_point(&display_map).row()
1836                != new_cursor_position.to_display_point(&display_map).row()
1837            {
1838                self.available_code_actions.take();
1839            }
1840            self.refresh_code_actions(cx);
1841            self.refresh_document_highlights(cx);
1842            refresh_matching_bracket_highlights(self, cx);
1843            self.discard_copilot_suggestion(cx);
1844        }
1845
1846        self.blink_manager.update(cx, BlinkManager::pause_blinking);
1847        cx.emit(EditorEvent::SelectionsChanged { local });
1848
1849        if self.selections.disjoint_anchors().len() == 1 {
1850            cx.emit(SearchEvent::ActiveMatchChanged)
1851        }
1852
1853        cx.notify();
1854    }
1855
1856    pub fn change_selections<R>(
1857        &mut self,
1858        autoscroll: Option<Autoscroll>,
1859        cx: &mut ViewContext<Self>,
1860        change: impl FnOnce(&mut MutableSelectionsCollection<'_>) -> R,
1861    ) -> R {
1862        let old_cursor_position = self.selections.newest_anchor().head();
1863        self.push_to_selection_history();
1864
1865        let (changed, result) = self.selections.change_with(cx, change);
1866
1867        if changed {
1868            if let Some(autoscroll) = autoscroll {
1869                self.request_autoscroll(autoscroll, cx);
1870            }
1871            self.selections_did_change(true, &old_cursor_position, cx);
1872        }
1873
1874        result
1875    }
1876
1877    pub fn edit<I, S, T>(&mut self, edits: I, cx: &mut ViewContext<Self>)
1878    where
1879        I: IntoIterator<Item = (Range<S>, T)>,
1880        S: ToOffset,
1881        T: Into<Arc<str>>,
1882    {
1883        if self.read_only(cx) {
1884            return;
1885        }
1886
1887        self.buffer
1888            .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
1889    }
1890
1891    pub fn edit_with_autoindent<I, S, T>(&mut self, edits: I, cx: &mut ViewContext<Self>)
1892    where
1893        I: IntoIterator<Item = (Range<S>, T)>,
1894        S: ToOffset,
1895        T: Into<Arc<str>>,
1896    {
1897        if self.read_only(cx) {
1898            return;
1899        }
1900
1901        self.buffer.update(cx, |buffer, cx| {
1902            buffer.edit(edits, self.autoindent_mode.clone(), cx)
1903        });
1904    }
1905
1906    pub fn edit_with_block_indent<I, S, T>(
1907        &mut self,
1908        edits: I,
1909        original_indent_columns: Vec<u32>,
1910        cx: &mut ViewContext<Self>,
1911    ) where
1912        I: IntoIterator<Item = (Range<S>, T)>,
1913        S: ToOffset,
1914        T: Into<Arc<str>>,
1915    {
1916        if self.read_only(cx) {
1917            return;
1918        }
1919
1920        self.buffer.update(cx, |buffer, cx| {
1921            buffer.edit(
1922                edits,
1923                Some(AutoindentMode::Block {
1924                    original_indent_columns,
1925                }),
1926                cx,
1927            )
1928        });
1929    }
1930
1931    fn select(&mut self, phase: SelectPhase, cx: &mut ViewContext<Self>) {
1932        self.hide_context_menu(cx);
1933
1934        match phase {
1935            SelectPhase::Begin {
1936                position,
1937                add,
1938                click_count,
1939            } => self.begin_selection(position, add, click_count, cx),
1940            SelectPhase::BeginColumnar {
1941                position,
1942                goal_column,
1943            } => self.begin_columnar_selection(position, goal_column, cx),
1944            SelectPhase::Extend {
1945                position,
1946                click_count,
1947            } => self.extend_selection(position, click_count, cx),
1948            SelectPhase::Update {
1949                position,
1950                goal_column,
1951                scroll_delta,
1952            } => self.update_selection(position, goal_column, scroll_delta, cx),
1953            SelectPhase::End => self.end_selection(cx),
1954        }
1955    }
1956
1957    fn extend_selection(
1958        &mut self,
1959        position: DisplayPoint,
1960        click_count: usize,
1961        cx: &mut ViewContext<Self>,
1962    ) {
1963        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
1964        let tail = self.selections.newest::<usize>(cx).tail();
1965        self.begin_selection(position, false, click_count, cx);
1966
1967        let position = position.to_offset(&display_map, Bias::Left);
1968        let tail_anchor = display_map.buffer_snapshot.anchor_before(tail);
1969
1970        let mut pending_selection = self
1971            .selections
1972            .pending_anchor()
1973            .expect("extend_selection not called with pending selection");
1974        if position >= tail {
1975            pending_selection.start = tail_anchor;
1976        } else {
1977            pending_selection.end = tail_anchor;
1978            pending_selection.reversed = true;
1979        }
1980
1981        let mut pending_mode = self.selections.pending_mode().unwrap();
1982        match &mut pending_mode {
1983            SelectMode::Word(range) | SelectMode::Line(range) => *range = tail_anchor..tail_anchor,
1984            _ => {}
1985        }
1986
1987        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
1988            s.set_pending(pending_selection, pending_mode)
1989        });
1990    }
1991
1992    fn begin_selection(
1993        &mut self,
1994        position: DisplayPoint,
1995        add: bool,
1996        click_count: usize,
1997        cx: &mut ViewContext<Self>,
1998    ) {
1999        if !self.focus_handle.is_focused(cx) {
2000            cx.focus(&self.focus_handle);
2001        }
2002
2003        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
2004        let buffer = &display_map.buffer_snapshot;
2005        let newest_selection = self.selections.newest_anchor().clone();
2006        let position = display_map.clip_point(position, Bias::Left);
2007
2008        let start;
2009        let end;
2010        let mode;
2011        let auto_scroll;
2012        match click_count {
2013            1 => {
2014                start = buffer.anchor_before(position.to_point(&display_map));
2015                end = start.clone();
2016                mode = SelectMode::Character;
2017                auto_scroll = true;
2018            }
2019            2 => {
2020                let range = movement::surrounding_word(&display_map, position);
2021                start = buffer.anchor_before(range.start.to_point(&display_map));
2022                end = buffer.anchor_before(range.end.to_point(&display_map));
2023                mode = SelectMode::Word(start.clone()..end.clone());
2024                auto_scroll = true;
2025            }
2026            3 => {
2027                let position = display_map
2028                    .clip_point(position, Bias::Left)
2029                    .to_point(&display_map);
2030                let line_start = display_map.prev_line_boundary(position).0;
2031                let next_line_start = buffer.clip_point(
2032                    display_map.next_line_boundary(position).0 + Point::new(1, 0),
2033                    Bias::Left,
2034                );
2035                start = buffer.anchor_before(line_start);
2036                end = buffer.anchor_before(next_line_start);
2037                mode = SelectMode::Line(start.clone()..end.clone());
2038                auto_scroll = true;
2039            }
2040            _ => {
2041                start = buffer.anchor_before(0);
2042                end = buffer.anchor_before(buffer.len());
2043                mode = SelectMode::All;
2044                auto_scroll = false;
2045            }
2046        }
2047
2048        self.change_selections(auto_scroll.then(|| Autoscroll::newest()), cx, |s| {
2049            if !add {
2050                s.clear_disjoint();
2051            } else if click_count > 1 {
2052                s.delete(newest_selection.id)
2053            }
2054
2055            s.set_pending_anchor_range(start..end, mode);
2056        });
2057    }
2058
2059    fn begin_columnar_selection(
2060        &mut self,
2061        position: DisplayPoint,
2062        goal_column: u32,
2063        cx: &mut ViewContext<Self>,
2064    ) {
2065        if !self.focus_handle.is_focused(cx) {
2066            cx.focus(&self.focus_handle);
2067        }
2068
2069        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
2070        let tail = self.selections.newest::<Point>(cx).tail();
2071        self.columnar_selection_tail = Some(display_map.buffer_snapshot.anchor_before(tail));
2072
2073        self.select_columns(
2074            tail.to_display_point(&display_map),
2075            position,
2076            goal_column,
2077            &display_map,
2078            cx,
2079        );
2080    }
2081
2082    fn update_selection(
2083        &mut self,
2084        position: DisplayPoint,
2085        goal_column: u32,
2086        scroll_delta: gpui::Point<f32>,
2087        cx: &mut ViewContext<Self>,
2088    ) {
2089        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
2090
2091        if let Some(tail) = self.columnar_selection_tail.as_ref() {
2092            let tail = tail.to_display_point(&display_map);
2093            self.select_columns(tail, position, goal_column, &display_map, cx);
2094        } else if let Some(mut pending) = self.selections.pending_anchor() {
2095            let buffer = self.buffer.read(cx).snapshot(cx);
2096            let head;
2097            let tail;
2098            let mode = self.selections.pending_mode().unwrap();
2099            match &mode {
2100                SelectMode::Character => {
2101                    head = position.to_point(&display_map);
2102                    tail = pending.tail().to_point(&buffer);
2103                }
2104                SelectMode::Word(original_range) => {
2105                    let original_display_range = original_range.start.to_display_point(&display_map)
2106                        ..original_range.end.to_display_point(&display_map);
2107                    let original_buffer_range = original_display_range.start.to_point(&display_map)
2108                        ..original_display_range.end.to_point(&display_map);
2109                    if movement::is_inside_word(&display_map, position)
2110                        || original_display_range.contains(&position)
2111                    {
2112                        let word_range = movement::surrounding_word(&display_map, position);
2113                        if word_range.start < original_display_range.start {
2114                            head = word_range.start.to_point(&display_map);
2115                        } else {
2116                            head = word_range.end.to_point(&display_map);
2117                        }
2118                    } else {
2119                        head = position.to_point(&display_map);
2120                    }
2121
2122                    if head <= original_buffer_range.start {
2123                        tail = original_buffer_range.end;
2124                    } else {
2125                        tail = original_buffer_range.start;
2126                    }
2127                }
2128                SelectMode::Line(original_range) => {
2129                    let original_range = original_range.to_point(&display_map.buffer_snapshot);
2130
2131                    let position = display_map
2132                        .clip_point(position, Bias::Left)
2133                        .to_point(&display_map);
2134                    let line_start = display_map.prev_line_boundary(position).0;
2135                    let next_line_start = buffer.clip_point(
2136                        display_map.next_line_boundary(position).0 + Point::new(1, 0),
2137                        Bias::Left,
2138                    );
2139
2140                    if line_start < original_range.start {
2141                        head = line_start
2142                    } else {
2143                        head = next_line_start
2144                    }
2145
2146                    if head <= original_range.start {
2147                        tail = original_range.end;
2148                    } else {
2149                        tail = original_range.start;
2150                    }
2151                }
2152                SelectMode::All => {
2153                    return;
2154                }
2155            };
2156
2157            if head < tail {
2158                pending.start = buffer.anchor_before(head);
2159                pending.end = buffer.anchor_before(tail);
2160                pending.reversed = true;
2161            } else {
2162                pending.start = buffer.anchor_before(tail);
2163                pending.end = buffer.anchor_before(head);
2164                pending.reversed = false;
2165            }
2166
2167            self.change_selections(None, cx, |s| {
2168                s.set_pending(pending, mode);
2169            });
2170        } else {
2171            log::error!("update_selection dispatched with no pending selection");
2172            return;
2173        }
2174
2175        self.apply_scroll_delta(scroll_delta, cx);
2176        cx.notify();
2177    }
2178
2179    fn end_selection(&mut self, cx: &mut ViewContext<Self>) {
2180        self.columnar_selection_tail.take();
2181        if self.selections.pending_anchor().is_some() {
2182            let selections = self.selections.all::<usize>(cx);
2183            self.change_selections(None, cx, |s| {
2184                s.select(selections);
2185                s.clear_pending();
2186            });
2187        }
2188    }
2189
2190    fn select_columns(
2191        &mut self,
2192        tail: DisplayPoint,
2193        head: DisplayPoint,
2194        goal_column: u32,
2195        display_map: &DisplaySnapshot,
2196        cx: &mut ViewContext<Self>,
2197    ) {
2198        let start_row = cmp::min(tail.row(), head.row());
2199        let end_row = cmp::max(tail.row(), head.row());
2200        let start_column = cmp::min(tail.column(), goal_column);
2201        let end_column = cmp::max(tail.column(), goal_column);
2202        let reversed = start_column < tail.column();
2203
2204        let selection_ranges = (start_row..=end_row)
2205            .filter_map(|row| {
2206                if start_column <= display_map.line_len(row) && !display_map.is_block_line(row) {
2207                    let start = display_map
2208                        .clip_point(DisplayPoint::new(row, start_column), Bias::Left)
2209                        .to_point(display_map);
2210                    let end = display_map
2211                        .clip_point(DisplayPoint::new(row, end_column), Bias::Right)
2212                        .to_point(display_map);
2213                    if reversed {
2214                        Some(end..start)
2215                    } else {
2216                        Some(start..end)
2217                    }
2218                } else {
2219                    None
2220                }
2221            })
2222            .collect::<Vec<_>>();
2223
2224        self.change_selections(None, cx, |s| {
2225            s.select_ranges(selection_ranges);
2226        });
2227        cx.notify();
2228    }
2229
2230    pub fn has_pending_nonempty_selection(&self) -> bool {
2231        let pending_nonempty_selection = match self.selections.pending_anchor() {
2232            Some(Selection { start, end, .. }) => start != end,
2233            None => false,
2234        };
2235        pending_nonempty_selection || self.columnar_selection_tail.is_some()
2236    }
2237
2238    pub fn has_pending_selection(&self) -> bool {
2239        self.selections.pending_anchor().is_some() || self.columnar_selection_tail.is_some()
2240    }
2241
2242    pub fn cancel(&mut self, _: &Cancel, cx: &mut ViewContext<Self>) {
2243        if self.take_rename(false, cx).is_some() {
2244            return;
2245        }
2246
2247        if hide_hover(self, cx) {
2248            return;
2249        }
2250
2251        if self.hide_context_menu(cx).is_some() {
2252            return;
2253        }
2254
2255        if self.discard_copilot_suggestion(cx) {
2256            return;
2257        }
2258
2259        if self.snippet_stack.pop().is_some() {
2260            return;
2261        }
2262
2263        if self.mode == EditorMode::Full {
2264            if self.active_diagnostics.is_some() {
2265                self.dismiss_diagnostics(cx);
2266                return;
2267            }
2268
2269            if self.change_selections(Some(Autoscroll::fit()), cx, |s| s.try_cancel()) {
2270                return;
2271            }
2272        }
2273
2274        cx.propagate();
2275    }
2276
2277    pub fn handle_input(&mut self, text: &str, cx: &mut ViewContext<Self>) {
2278        let text: Arc<str> = text.into();
2279
2280        if self.read_only(cx) {
2281            return;
2282        }
2283
2284        let selections = self.selections.all_adjusted(cx);
2285        let mut brace_inserted = false;
2286        let mut edits = Vec::new();
2287        let mut new_selections = Vec::with_capacity(selections.len());
2288        let mut new_autoclose_regions = Vec::new();
2289        let snapshot = self.buffer.read(cx).read(cx);
2290
2291        for (selection, autoclose_region) in
2292            self.selections_with_autoclose_regions(selections, &snapshot)
2293        {
2294            if let Some(scope) = snapshot.language_scope_at(selection.head()) {
2295                // Determine if the inserted text matches the opening or closing
2296                // bracket of any of this language's bracket pairs.
2297                let mut bracket_pair = None;
2298                let mut is_bracket_pair_start = false;
2299                if !text.is_empty() {
2300                    // `text` can be empty when an user is using IME (e.g. Chinese Wubi Simplified)
2301                    //  and they are removing the character that triggered IME popup.
2302                    for (pair, enabled) in scope.brackets() {
2303                        if enabled && pair.close && pair.start.ends_with(text.as_ref()) {
2304                            bracket_pair = Some(pair.clone());
2305                            is_bracket_pair_start = true;
2306                            break;
2307                        } else if pair.end.as_str() == text.as_ref() {
2308                            bracket_pair = Some(pair.clone());
2309                            break;
2310                        }
2311                    }
2312                }
2313
2314                if let Some(bracket_pair) = bracket_pair {
2315                    if selection.is_empty() {
2316                        if is_bracket_pair_start {
2317                            let prefix_len = bracket_pair.start.len() - text.len();
2318
2319                            // If the inserted text is a suffix of an opening bracket and the
2320                            // selection is preceded by the rest of the opening bracket, then
2321                            // insert the closing bracket.
2322                            let following_text_allows_autoclose = snapshot
2323                                .chars_at(selection.start)
2324                                .next()
2325                                .map_or(true, |c| scope.should_autoclose_before(c));
2326                            let preceding_text_matches_prefix = prefix_len == 0
2327                                || (selection.start.column >= (prefix_len as u32)
2328                                    && snapshot.contains_str_at(
2329                                        Point::new(
2330                                            selection.start.row,
2331                                            selection.start.column - (prefix_len as u32),
2332                                        ),
2333                                        &bracket_pair.start[..prefix_len],
2334                                    ));
2335                            let autoclose = self.use_autoclose
2336                                && snapshot.settings_at(selection.start, cx).use_autoclose;
2337                            if autoclose
2338                                && following_text_allows_autoclose
2339                                && preceding_text_matches_prefix
2340                            {
2341                                let anchor = snapshot.anchor_before(selection.end);
2342                                new_selections.push((selection.map(|_| anchor), text.len()));
2343                                new_autoclose_regions.push((
2344                                    anchor,
2345                                    text.len(),
2346                                    selection.id,
2347                                    bracket_pair.clone(),
2348                                ));
2349                                edits.push((
2350                                    selection.range(),
2351                                    format!("{}{}", text, bracket_pair.end).into(),
2352                                ));
2353                                brace_inserted = true;
2354                                continue;
2355                            }
2356                        }
2357
2358                        if let Some(region) = autoclose_region {
2359                            // If the selection is followed by an auto-inserted closing bracket,
2360                            // then don't insert that closing bracket again; just move the selection
2361                            // past the closing bracket.
2362                            let should_skip = selection.end == region.range.end.to_point(&snapshot)
2363                                && text.as_ref() == region.pair.end.as_str();
2364                            if should_skip {
2365                                let anchor = snapshot.anchor_after(selection.end);
2366                                new_selections
2367                                    .push((selection.map(|_| anchor), region.pair.end.len()));
2368                                continue;
2369                            }
2370                        }
2371                    }
2372                    // If an opening bracket is 1 character long and is typed while
2373                    // text is selected, then surround that text with the bracket pair.
2374                    else if is_bracket_pair_start && bracket_pair.start.chars().count() == 1 {
2375                        edits.push((selection.start..selection.start, text.clone()));
2376                        edits.push((
2377                            selection.end..selection.end,
2378                            bracket_pair.end.as_str().into(),
2379                        ));
2380                        brace_inserted = true;
2381                        new_selections.push((
2382                            Selection {
2383                                id: selection.id,
2384                                start: snapshot.anchor_after(selection.start),
2385                                end: snapshot.anchor_before(selection.end),
2386                                reversed: selection.reversed,
2387                                goal: selection.goal,
2388                            },
2389                            0,
2390                        ));
2391                        continue;
2392                    }
2393                }
2394            }
2395
2396            // If not handling any auto-close operation, then just replace the selected
2397            // text with the given input and move the selection to the end of the
2398            // newly inserted text.
2399            let anchor = snapshot.anchor_after(selection.end);
2400            new_selections.push((selection.map(|_| anchor), 0));
2401            edits.push((selection.start..selection.end, text.clone()));
2402        }
2403
2404        drop(snapshot);
2405        self.transact(cx, |this, cx| {
2406            this.buffer.update(cx, |buffer, cx| {
2407                buffer.edit(edits, this.autoindent_mode.clone(), cx);
2408            });
2409
2410            let new_anchor_selections = new_selections.iter().map(|e| &e.0);
2411            let new_selection_deltas = new_selections.iter().map(|e| e.1);
2412            let snapshot = this.buffer.read(cx).read(cx);
2413            let new_selections = resolve_multiple::<usize, _>(new_anchor_selections, &snapshot)
2414                .zip(new_selection_deltas)
2415                .map(|(selection, delta)| Selection {
2416                    id: selection.id,
2417                    start: selection.start + delta,
2418                    end: selection.end + delta,
2419                    reversed: selection.reversed,
2420                    goal: SelectionGoal::None,
2421                })
2422                .collect::<Vec<_>>();
2423
2424            let mut i = 0;
2425            for (position, delta, selection_id, pair) in new_autoclose_regions {
2426                let position = position.to_offset(&snapshot) + delta;
2427                let start = snapshot.anchor_before(position);
2428                let end = snapshot.anchor_after(position);
2429                while let Some(existing_state) = this.autoclose_regions.get(i) {
2430                    match existing_state.range.start.cmp(&start, &snapshot) {
2431                        Ordering::Less => i += 1,
2432                        Ordering::Greater => break,
2433                        Ordering::Equal => match end.cmp(&existing_state.range.end, &snapshot) {
2434                            Ordering::Less => i += 1,
2435                            Ordering::Equal => break,
2436                            Ordering::Greater => break,
2437                        },
2438                    }
2439                }
2440                this.autoclose_regions.insert(
2441                    i,
2442                    AutocloseRegion {
2443                        selection_id,
2444                        range: start..end,
2445                        pair,
2446                    },
2447                );
2448            }
2449
2450            drop(snapshot);
2451            let had_active_copilot_suggestion = this.has_active_copilot_suggestion(cx);
2452            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(new_selections));
2453
2454            if !brace_inserted && EditorSettings::get_global(cx).use_on_type_format {
2455                if let Some(on_type_format_task) =
2456                    this.trigger_on_type_formatting(text.to_string(), cx)
2457                {
2458                    on_type_format_task.detach_and_log_err(cx);
2459                }
2460            }
2461
2462            if had_active_copilot_suggestion {
2463                this.refresh_copilot_suggestions(true, cx);
2464                if !this.has_active_copilot_suggestion(cx) {
2465                    this.trigger_completion_on_input(&text, cx);
2466                }
2467            } else {
2468                this.trigger_completion_on_input(&text, cx);
2469                this.refresh_copilot_suggestions(true, cx);
2470            }
2471        });
2472    }
2473
2474    pub fn newline(&mut self, _: &Newline, cx: &mut ViewContext<Self>) {
2475        self.transact(cx, |this, cx| {
2476            let (edits, selection_fixup_info): (Vec<_>, Vec<_>) = {
2477                let selections = this.selections.all::<usize>(cx);
2478                let multi_buffer = this.buffer.read(cx);
2479                let buffer = multi_buffer.snapshot(cx);
2480                selections
2481                    .iter()
2482                    .map(|selection| {
2483                        let start_point = selection.start.to_point(&buffer);
2484                        let mut indent = buffer.indent_size_for_line(start_point.row);
2485                        indent.len = cmp::min(indent.len, start_point.column);
2486                        let start = selection.start;
2487                        let end = selection.end;
2488                        let is_cursor = start == end;
2489                        let language_scope = buffer.language_scope_at(start);
2490                        let (comment_delimiter, insert_extra_newline) = if let Some(language) =
2491                            &language_scope
2492                        {
2493                            let leading_whitespace_len = buffer
2494                                .reversed_chars_at(start)
2495                                .take_while(|c| c.is_whitespace() && *c != '\n')
2496                                .map(|c| c.len_utf8())
2497                                .sum::<usize>();
2498
2499                            let trailing_whitespace_len = buffer
2500                                .chars_at(end)
2501                                .take_while(|c| c.is_whitespace() && *c != '\n')
2502                                .map(|c| c.len_utf8())
2503                                .sum::<usize>();
2504
2505                            let insert_extra_newline =
2506                                language.brackets().any(|(pair, enabled)| {
2507                                    let pair_start = pair.start.trim_end();
2508                                    let pair_end = pair.end.trim_start();
2509
2510                                    enabled
2511                                        && pair.newline
2512                                        && buffer.contains_str_at(
2513                                            end + trailing_whitespace_len,
2514                                            pair_end,
2515                                        )
2516                                        && buffer.contains_str_at(
2517                                            (start - leading_whitespace_len)
2518                                                .saturating_sub(pair_start.len()),
2519                                            pair_start,
2520                                        )
2521                                });
2522                            // Comment extension on newline is allowed only for cursor selections
2523                            let comment_delimiter = language.line_comment_prefixes().filter(|_| {
2524                                let is_comment_extension_enabled =
2525                                    multi_buffer.settings_at(0, cx).extend_comment_on_newline;
2526                                is_cursor && is_comment_extension_enabled
2527                            });
2528                            let get_comment_delimiter = |delimiters: &[Arc<str>]| {
2529                                let max_len_of_delimiter =
2530                                    delimiters.iter().map(|delimiter| delimiter.len()).max()?;
2531                                let (snapshot, range) =
2532                                    buffer.buffer_line_for_row(start_point.row)?;
2533
2534                                let mut index_of_first_non_whitespace = 0;
2535                                let comment_candidate = snapshot
2536                                    .chars_for_range(range)
2537                                    .skip_while(|c| {
2538                                        let should_skip = c.is_whitespace();
2539                                        if should_skip {
2540                                            index_of_first_non_whitespace += 1;
2541                                        }
2542                                        should_skip
2543                                    })
2544                                    .take(max_len_of_delimiter)
2545                                    .collect::<String>();
2546                                let comment_prefix = delimiters.iter().find(|comment_prefix| {
2547                                    comment_candidate.starts_with(comment_prefix.as_ref())
2548                                })?;
2549                                let cursor_is_placed_after_comment_marker =
2550                                    index_of_first_non_whitespace + comment_prefix.len()
2551                                        <= start_point.column as usize;
2552                                if cursor_is_placed_after_comment_marker {
2553                                    Some(comment_prefix.clone())
2554                                } else {
2555                                    None
2556                                }
2557                            };
2558                            let comment_delimiter = if let Some(delimiters) = comment_delimiter {
2559                                get_comment_delimiter(delimiters)
2560                            } else {
2561                                None
2562                            };
2563                            (comment_delimiter, insert_extra_newline)
2564                        } else {
2565                            (None, false)
2566                        };
2567
2568                        let capacity_for_delimiter = comment_delimiter
2569                            .as_deref()
2570                            .map(str::len)
2571                            .unwrap_or_default();
2572                        let mut new_text =
2573                            String::with_capacity(1 + capacity_for_delimiter + indent.len as usize);
2574                        new_text.push_str("\n");
2575                        new_text.extend(indent.chars());
2576                        if let Some(delimiter) = &comment_delimiter {
2577                            new_text.push_str(&delimiter);
2578                        }
2579                        if insert_extra_newline {
2580                            new_text = new_text.repeat(2);
2581                        }
2582
2583                        let anchor = buffer.anchor_after(end);
2584                        let new_selection = selection.map(|_| anchor);
2585                        (
2586                            (start..end, new_text),
2587                            (insert_extra_newline, new_selection),
2588                        )
2589                    })
2590                    .unzip()
2591            };
2592
2593            this.edit_with_autoindent(edits, cx);
2594            let buffer = this.buffer.read(cx).snapshot(cx);
2595            let new_selections = selection_fixup_info
2596                .into_iter()
2597                .map(|(extra_newline_inserted, new_selection)| {
2598                    let mut cursor = new_selection.end.to_point(&buffer);
2599                    if extra_newline_inserted {
2600                        cursor.row -= 1;
2601                        cursor.column = buffer.line_len(cursor.row);
2602                    }
2603                    new_selection.map(|_| cursor)
2604                })
2605                .collect();
2606
2607            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(new_selections));
2608            this.refresh_copilot_suggestions(true, cx);
2609        });
2610    }
2611
2612    pub fn newline_above(&mut self, _: &NewlineAbove, cx: &mut ViewContext<Self>) {
2613        let buffer = self.buffer.read(cx);
2614        let snapshot = buffer.snapshot(cx);
2615
2616        let mut edits = Vec::new();
2617        let mut rows = Vec::new();
2618        let mut rows_inserted = 0;
2619
2620        for selection in self.selections.all_adjusted(cx) {
2621            let cursor = selection.head();
2622            let row = cursor.row;
2623
2624            let start_of_line = snapshot.clip_point(Point::new(row, 0), Bias::Left);
2625
2626            let newline = "\n".to_string();
2627            edits.push((start_of_line..start_of_line, newline));
2628
2629            rows.push(row + rows_inserted);
2630            rows_inserted += 1;
2631        }
2632
2633        self.transact(cx, |editor, cx| {
2634            editor.edit(edits, cx);
2635
2636            editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
2637                let mut index = 0;
2638                s.move_cursors_with(|map, _, _| {
2639                    let row = rows[index];
2640                    index += 1;
2641
2642                    let point = Point::new(row, 0);
2643                    let boundary = map.next_line_boundary(point).1;
2644                    let clipped = map.clip_point(boundary, Bias::Left);
2645
2646                    (clipped, SelectionGoal::None)
2647                });
2648            });
2649
2650            let mut indent_edits = Vec::new();
2651            let multibuffer_snapshot = editor.buffer.read(cx).snapshot(cx);
2652            for row in rows {
2653                let indents = multibuffer_snapshot.suggested_indents(row..row + 1, cx);
2654                for (row, indent) in indents {
2655                    if indent.len == 0 {
2656                        continue;
2657                    }
2658
2659                    let text = match indent.kind {
2660                        IndentKind::Space => " ".repeat(indent.len as usize),
2661                        IndentKind::Tab => "\t".repeat(indent.len as usize),
2662                    };
2663                    let point = Point::new(row, 0);
2664                    indent_edits.push((point..point, text));
2665                }
2666            }
2667            editor.edit(indent_edits, cx);
2668        });
2669    }
2670
2671    pub fn newline_below(&mut self, _: &NewlineBelow, cx: &mut ViewContext<Self>) {
2672        let buffer = self.buffer.read(cx);
2673        let snapshot = buffer.snapshot(cx);
2674
2675        let mut edits = Vec::new();
2676        let mut rows = Vec::new();
2677        let mut rows_inserted = 0;
2678
2679        for selection in self.selections.all_adjusted(cx) {
2680            let cursor = selection.head();
2681            let row = cursor.row;
2682
2683            let point = Point::new(row + 1, 0);
2684            let start_of_line = snapshot.clip_point(point, Bias::Left);
2685
2686            let newline = "\n".to_string();
2687            edits.push((start_of_line..start_of_line, newline));
2688
2689            rows_inserted += 1;
2690            rows.push(row + rows_inserted);
2691        }
2692
2693        self.transact(cx, |editor, cx| {
2694            editor.edit(edits, cx);
2695
2696            editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
2697                let mut index = 0;
2698                s.move_cursors_with(|map, _, _| {
2699                    let row = rows[index];
2700                    index += 1;
2701
2702                    let point = Point::new(row, 0);
2703                    let boundary = map.next_line_boundary(point).1;
2704                    let clipped = map.clip_point(boundary, Bias::Left);
2705
2706                    (clipped, SelectionGoal::None)
2707                });
2708            });
2709
2710            let mut indent_edits = Vec::new();
2711            let multibuffer_snapshot = editor.buffer.read(cx).snapshot(cx);
2712            for row in rows {
2713                let indents = multibuffer_snapshot.suggested_indents(row..row + 1, cx);
2714                for (row, indent) in indents {
2715                    if indent.len == 0 {
2716                        continue;
2717                    }
2718
2719                    let text = match indent.kind {
2720                        IndentKind::Space => " ".repeat(indent.len as usize),
2721                        IndentKind::Tab => "\t".repeat(indent.len as usize),
2722                    };
2723                    let point = Point::new(row, 0);
2724                    indent_edits.push((point..point, text));
2725                }
2726            }
2727            editor.edit(indent_edits, cx);
2728        });
2729    }
2730
2731    pub fn insert(&mut self, text: &str, cx: &mut ViewContext<Self>) {
2732        self.insert_with_autoindent_mode(
2733            text,
2734            Some(AutoindentMode::Block {
2735                original_indent_columns: Vec::new(),
2736            }),
2737            cx,
2738        );
2739    }
2740
2741    fn insert_with_autoindent_mode(
2742        &mut self,
2743        text: &str,
2744        autoindent_mode: Option<AutoindentMode>,
2745        cx: &mut ViewContext<Self>,
2746    ) {
2747        if self.read_only(cx) {
2748            return;
2749        }
2750
2751        let text: Arc<str> = text.into();
2752        self.transact(cx, |this, cx| {
2753            let old_selections = this.selections.all_adjusted(cx);
2754            let selection_anchors = this.buffer.update(cx, |buffer, cx| {
2755                let anchors = {
2756                    let snapshot = buffer.read(cx);
2757                    old_selections
2758                        .iter()
2759                        .map(|s| {
2760                            let anchor = snapshot.anchor_after(s.head());
2761                            s.map(|_| anchor)
2762                        })
2763                        .collect::<Vec<_>>()
2764                };
2765                buffer.edit(
2766                    old_selections
2767                        .iter()
2768                        .map(|s| (s.start..s.end, text.clone())),
2769                    autoindent_mode,
2770                    cx,
2771                );
2772                anchors
2773            });
2774
2775            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
2776                s.select_anchors(selection_anchors);
2777            })
2778        });
2779    }
2780
2781    fn trigger_completion_on_input(&mut self, text: &str, cx: &mut ViewContext<Self>) {
2782        if !EditorSettings::get_global(cx).show_completions_on_input {
2783            return;
2784        }
2785
2786        let selection = self.selections.newest_anchor();
2787        if self
2788            .buffer
2789            .read(cx)
2790            .is_completion_trigger(selection.head(), text, cx)
2791        {
2792            self.show_completions(&ShowCompletions, cx);
2793        } else {
2794            self.hide_context_menu(cx);
2795        }
2796    }
2797
2798    /// If any empty selections is touching the start of its innermost containing autoclose
2799    /// region, expand it to select the brackets.
2800    fn select_autoclose_pair(&mut self, cx: &mut ViewContext<Self>) {
2801        let selections = self.selections.all::<usize>(cx);
2802        let buffer = self.buffer.read(cx).read(cx);
2803        let mut new_selections = Vec::new();
2804        for (mut selection, region) in self.selections_with_autoclose_regions(selections, &buffer) {
2805            if let (Some(region), true) = (region, selection.is_empty()) {
2806                let mut range = region.range.to_offset(&buffer);
2807                if selection.start == range.start {
2808                    if range.start >= region.pair.start.len() {
2809                        range.start -= region.pair.start.len();
2810                        if buffer.contains_str_at(range.start, &region.pair.start) {
2811                            if buffer.contains_str_at(range.end, &region.pair.end) {
2812                                range.end += region.pair.end.len();
2813                                selection.start = range.start;
2814                                selection.end = range.end;
2815                            }
2816                        }
2817                    }
2818                }
2819            }
2820            new_selections.push(selection);
2821        }
2822
2823        drop(buffer);
2824        self.change_selections(None, cx, |selections| selections.select(new_selections));
2825    }
2826
2827    /// Iterate the given selections, and for each one, find the smallest surrounding
2828    /// autoclose region. This uses the ordering of the selections and the autoclose
2829    /// regions to avoid repeated comparisons.
2830    fn selections_with_autoclose_regions<'a, D: ToOffset + Clone>(
2831        &'a self,
2832        selections: impl IntoIterator<Item = Selection<D>>,
2833        buffer: &'a MultiBufferSnapshot,
2834    ) -> impl Iterator<Item = (Selection<D>, Option<&'a AutocloseRegion>)> {
2835        let mut i = 0;
2836        let mut regions = self.autoclose_regions.as_slice();
2837        selections.into_iter().map(move |selection| {
2838            let range = selection.start.to_offset(buffer)..selection.end.to_offset(buffer);
2839
2840            let mut enclosing = None;
2841            while let Some(pair_state) = regions.get(i) {
2842                if pair_state.range.end.to_offset(buffer) < range.start {
2843                    regions = &regions[i + 1..];
2844                    i = 0;
2845                } else if pair_state.range.start.to_offset(buffer) > range.end {
2846                    break;
2847                } else {
2848                    if pair_state.selection_id == selection.id {
2849                        enclosing = Some(pair_state);
2850                    }
2851                    i += 1;
2852                }
2853            }
2854
2855            (selection.clone(), enclosing)
2856        })
2857    }
2858
2859    /// Remove any autoclose regions that no longer contain their selection.
2860    fn invalidate_autoclose_regions(
2861        &mut self,
2862        mut selections: &[Selection<Anchor>],
2863        buffer: &MultiBufferSnapshot,
2864    ) {
2865        self.autoclose_regions.retain(|state| {
2866            let mut i = 0;
2867            while let Some(selection) = selections.get(i) {
2868                if selection.end.cmp(&state.range.start, buffer).is_lt() {
2869                    selections = &selections[1..];
2870                    continue;
2871                }
2872                if selection.start.cmp(&state.range.end, buffer).is_gt() {
2873                    break;
2874                }
2875                if selection.id == state.selection_id {
2876                    return true;
2877                } else {
2878                    i += 1;
2879                }
2880            }
2881            false
2882        });
2883    }
2884
2885    fn completion_query(buffer: &MultiBufferSnapshot, position: impl ToOffset) -> Option<String> {
2886        let offset = position.to_offset(buffer);
2887        let (word_range, kind) = buffer.surrounding_word(offset);
2888        if offset > word_range.start && kind == Some(CharKind::Word) {
2889            Some(
2890                buffer
2891                    .text_for_range(word_range.start..offset)
2892                    .collect::<String>(),
2893            )
2894        } else {
2895            None
2896        }
2897    }
2898
2899    pub fn toggle_inlay_hints(&mut self, _: &ToggleInlayHints, cx: &mut ViewContext<Self>) {
2900        self.refresh_inlay_hints(
2901            InlayHintRefreshReason::Toggle(!self.inlay_hint_cache.enabled),
2902            cx,
2903        );
2904    }
2905
2906    pub fn inlay_hints_enabled(&self) -> bool {
2907        self.inlay_hint_cache.enabled
2908    }
2909
2910    fn refresh_inlay_hints(&mut self, reason: InlayHintRefreshReason, cx: &mut ViewContext<Self>) {
2911        if self.project.is_none() || self.mode != EditorMode::Full {
2912            return;
2913        }
2914
2915        let reason_description = reason.description();
2916        let (invalidate_cache, required_languages) = match reason {
2917            InlayHintRefreshReason::Toggle(enabled) => {
2918                self.inlay_hint_cache.enabled = enabled;
2919                if enabled {
2920                    (InvalidationStrategy::RefreshRequested, None)
2921                } else {
2922                    self.inlay_hint_cache.clear();
2923                    self.splice_inlay_hints(
2924                        self.visible_inlay_hints(cx)
2925                            .iter()
2926                            .map(|inlay| inlay.id)
2927                            .collect(),
2928                        Vec::new(),
2929                        cx,
2930                    );
2931                    return;
2932                }
2933            }
2934            InlayHintRefreshReason::SettingsChange(new_settings) => {
2935                match self.inlay_hint_cache.update_settings(
2936                    &self.buffer,
2937                    new_settings,
2938                    self.visible_inlay_hints(cx),
2939                    cx,
2940                ) {
2941                    ControlFlow::Break(Some(InlaySplice {
2942                        to_remove,
2943                        to_insert,
2944                    })) => {
2945                        self.splice_inlay_hints(to_remove, to_insert, cx);
2946                        return;
2947                    }
2948                    ControlFlow::Break(None) => return,
2949                    ControlFlow::Continue(()) => (InvalidationStrategy::RefreshRequested, None),
2950                }
2951            }
2952            InlayHintRefreshReason::ExcerptsRemoved(excerpts_removed) => {
2953                if let Some(InlaySplice {
2954                    to_remove,
2955                    to_insert,
2956                }) = self.inlay_hint_cache.remove_excerpts(excerpts_removed)
2957                {
2958                    self.splice_inlay_hints(to_remove, to_insert, cx);
2959                }
2960                return;
2961            }
2962            InlayHintRefreshReason::NewLinesShown => (InvalidationStrategy::None, None),
2963            InlayHintRefreshReason::BufferEdited(buffer_languages) => {
2964                (InvalidationStrategy::BufferEdited, Some(buffer_languages))
2965            }
2966            InlayHintRefreshReason::RefreshRequested => {
2967                (InvalidationStrategy::RefreshRequested, None)
2968            }
2969        };
2970
2971        if let Some(InlaySplice {
2972            to_remove,
2973            to_insert,
2974        }) = self.inlay_hint_cache.spawn_hint_refresh(
2975            reason_description,
2976            self.excerpts_for_inlay_hints_query(required_languages.as_ref(), cx),
2977            invalidate_cache,
2978            cx,
2979        ) {
2980            self.splice_inlay_hints(to_remove, to_insert, cx);
2981        }
2982    }
2983
2984    fn visible_inlay_hints(&self, cx: &ViewContext<'_, Editor>) -> Vec<Inlay> {
2985        self.display_map
2986            .read(cx)
2987            .current_inlays()
2988            .filter(move |inlay| {
2989                Some(inlay.id) != self.copilot_state.suggestion.as_ref().map(|h| h.id)
2990            })
2991            .cloned()
2992            .collect()
2993    }
2994
2995    pub fn excerpts_for_inlay_hints_query(
2996        &self,
2997        restrict_to_languages: Option<&HashSet<Arc<Language>>>,
2998        cx: &mut ViewContext<Editor>,
2999    ) -> HashMap<ExcerptId, (Model<Buffer>, clock::Global, Range<usize>)> {
3000        let Some(project) = self.project.as_ref() else {
3001            return HashMap::default();
3002        };
3003        let project = project.read(cx);
3004        let multi_buffer = self.buffer().read(cx);
3005        let multi_buffer_snapshot = multi_buffer.snapshot(cx);
3006        let multi_buffer_visible_start = self
3007            .scroll_manager
3008            .anchor()
3009            .anchor
3010            .to_point(&multi_buffer_snapshot);
3011        let multi_buffer_visible_end = multi_buffer_snapshot.clip_point(
3012            multi_buffer_visible_start
3013                + Point::new(self.visible_line_count().unwrap_or(0.).ceil() as u32, 0),
3014            Bias::Left,
3015        );
3016        let multi_buffer_visible_range = multi_buffer_visible_start..multi_buffer_visible_end;
3017        multi_buffer
3018            .range_to_buffer_ranges(multi_buffer_visible_range, cx)
3019            .into_iter()
3020            .filter(|(_, excerpt_visible_range, _)| !excerpt_visible_range.is_empty())
3021            .filter_map(|(buffer_handle, excerpt_visible_range, excerpt_id)| {
3022                let buffer = buffer_handle.read(cx);
3023                let buffer_file = project::worktree::File::from_dyn(buffer.file())?;
3024                let buffer_worktree = project.worktree_for_id(buffer_file.worktree_id(cx), cx)?;
3025                let worktree_entry = buffer_worktree
3026                    .read(cx)
3027                    .entry_for_id(buffer_file.project_entry_id(cx)?)?;
3028                if worktree_entry.is_ignored {
3029                    return None;
3030                }
3031
3032                let language = buffer.language()?;
3033                if let Some(restrict_to_languages) = restrict_to_languages {
3034                    if !restrict_to_languages.contains(language) {
3035                        return None;
3036                    }
3037                }
3038                Some((
3039                    excerpt_id,
3040                    (
3041                        buffer_handle,
3042                        buffer.version().clone(),
3043                        excerpt_visible_range,
3044                    ),
3045                ))
3046            })
3047            .collect()
3048    }
3049
3050    pub fn text_layout_details(&self, cx: &WindowContext) -> TextLayoutDetails {
3051        TextLayoutDetails {
3052            text_system: cx.text_system().clone(),
3053            editor_style: self.style.clone().unwrap(),
3054            rem_size: cx.rem_size(),
3055        }
3056    }
3057
3058    fn splice_inlay_hints(
3059        &self,
3060        to_remove: Vec<InlayId>,
3061        to_insert: Vec<Inlay>,
3062        cx: &mut ViewContext<Self>,
3063    ) {
3064        self.display_map.update(cx, |display_map, cx| {
3065            display_map.splice_inlays(to_remove, to_insert, cx);
3066        });
3067        cx.notify();
3068    }
3069
3070    fn trigger_on_type_formatting(
3071        &self,
3072        input: String,
3073        cx: &mut ViewContext<Self>,
3074    ) -> Option<Task<Result<()>>> {
3075        if input.len() != 1 {
3076            return None;
3077        }
3078
3079        let project = self.project.as_ref()?;
3080        let position = self.selections.newest_anchor().head();
3081        let (buffer, buffer_position) = self
3082            .buffer
3083            .read(cx)
3084            .text_anchor_for_position(position.clone(), cx)?;
3085
3086        // OnTypeFormatting returns a list of edits, no need to pass them between Zed instances,
3087        // hence we do LSP request & edit on host side only — add formats to host's history.
3088        let push_to_lsp_host_history = true;
3089        // If this is not the host, append its history with new edits.
3090        let push_to_client_history = project.read(cx).is_remote();
3091
3092        let on_type_formatting = project.update(cx, |project, cx| {
3093            project.on_type_format(
3094                buffer.clone(),
3095                buffer_position,
3096                input,
3097                push_to_lsp_host_history,
3098                cx,
3099            )
3100        });
3101        Some(cx.spawn(|editor, mut cx| async move {
3102            if let Some(transaction) = on_type_formatting.await? {
3103                if push_to_client_history {
3104                    buffer
3105                        .update(&mut cx, |buffer, _| {
3106                            buffer.push_transaction(transaction, Instant::now());
3107                        })
3108                        .ok();
3109                }
3110                editor.update(&mut cx, |editor, cx| {
3111                    editor.refresh_document_highlights(cx);
3112                })?;
3113            }
3114            Ok(())
3115        }))
3116    }
3117
3118    fn show_completions(&mut self, _: &ShowCompletions, cx: &mut ViewContext<Self>) {
3119        if self.pending_rename.is_some() {
3120            return;
3121        }
3122
3123        let Some(provider) = self.completion_provider.as_ref() else {
3124            return;
3125        };
3126
3127        let position = self.selections.newest_anchor().head();
3128        let (buffer, buffer_position) = if let Some(output) = self
3129            .buffer
3130            .read(cx)
3131            .text_anchor_for_position(position.clone(), cx)
3132        {
3133            output
3134        } else {
3135            return;
3136        };
3137
3138        let query = Self::completion_query(&self.buffer.read(cx).read(cx), position.clone());
3139        let completions = provider.completions(&buffer, buffer_position, cx);
3140
3141        let id = post_inc(&mut self.next_completion_id);
3142        let task = cx.spawn(|this, mut cx| {
3143            async move {
3144                let completions = completions.await.log_err();
3145                let (menu, pre_resolve_task) = if let Some(completions) = completions {
3146                    let mut menu = CompletionsMenu {
3147                        id,
3148                        initial_position: position,
3149                        match_candidates: completions
3150                            .iter()
3151                            .enumerate()
3152                            .map(|(id, completion)| {
3153                                StringMatchCandidate::new(
3154                                    id,
3155                                    completion.label.text[completion.label.filter_range.clone()]
3156                                        .into(),
3157                                )
3158                            })
3159                            .collect(),
3160                        buffer,
3161                        completions: Arc::new(RwLock::new(completions.into())),
3162                        matches: Vec::new().into(),
3163                        selected_item: 0,
3164                        scroll_handle: UniformListScrollHandle::new(),
3165                    };
3166                    menu.filter(query.as_deref(), cx.background_executor().clone())
3167                        .await;
3168
3169                    if menu.matches.is_empty() {
3170                        (None, None)
3171                    } else {
3172                        let pre_resolve_task = this
3173                            .update(&mut cx, |editor, cx| {
3174                                menu.pre_resolve_completion_documentation(editor, cx)
3175                            })
3176                            .ok()
3177                            .flatten();
3178                        (Some(menu), pre_resolve_task)
3179                    }
3180                } else {
3181                    (None, None)
3182                };
3183
3184                this.update(&mut cx, |this, cx| {
3185                    this.completion_tasks.retain(|(task_id, _)| *task_id >= id);
3186
3187                    let mut context_menu = this.context_menu.write();
3188                    match context_menu.as_ref() {
3189                        None => {}
3190
3191                        Some(ContextMenu::Completions(prev_menu)) => {
3192                            if prev_menu.id > id {
3193                                return;
3194                            }
3195                        }
3196
3197                        _ => return,
3198                    }
3199
3200                    if this.focus_handle.is_focused(cx) && menu.is_some() {
3201                        let menu = menu.unwrap();
3202                        *context_menu = Some(ContextMenu::Completions(menu));
3203                        drop(context_menu);
3204                        this.discard_copilot_suggestion(cx);
3205                        cx.notify();
3206                    } else if this.completion_tasks.len() <= 1 {
3207                        // If there are no more completion tasks and the last menu was
3208                        // empty, we should hide it. If it was already hidden, we should
3209                        // also show the copilot suggestion when available.
3210                        drop(context_menu);
3211                        if this.hide_context_menu(cx).is_none() {
3212                            this.update_visible_copilot_suggestion(cx);
3213                        }
3214                    }
3215                })?;
3216
3217                if let Some(pre_resolve_task) = pre_resolve_task {
3218                    pre_resolve_task.await;
3219                }
3220
3221                Ok::<_, anyhow::Error>(())
3222            }
3223            .log_err()
3224        });
3225
3226        self.completion_tasks.push((id, task));
3227    }
3228
3229    pub fn confirm_completion(
3230        &mut self,
3231        action: &ConfirmCompletion,
3232        cx: &mut ViewContext<Self>,
3233    ) -> Option<Task<Result<()>>> {
3234        use language::ToOffset as _;
3235
3236        let completions_menu = if let ContextMenu::Completions(menu) = self.hide_context_menu(cx)? {
3237            menu
3238        } else {
3239            return None;
3240        };
3241
3242        let mat = completions_menu
3243            .matches
3244            .get(action.item_ix.unwrap_or(completions_menu.selected_item))?;
3245        let buffer_handle = completions_menu.buffer;
3246        let completions = completions_menu.completions.read();
3247        let completion = completions.get(mat.candidate_id)?;
3248        cx.stop_propagation();
3249
3250        let snippet;
3251        let text;
3252        if completion.is_snippet() {
3253            snippet = Some(Snippet::parse(&completion.new_text).log_err()?);
3254            text = snippet.as_ref().unwrap().text.clone();
3255        } else {
3256            snippet = None;
3257            text = completion.new_text.clone();
3258        };
3259        let selections = self.selections.all::<usize>(cx);
3260        let buffer = buffer_handle.read(cx);
3261        let old_range = completion.old_range.to_offset(buffer);
3262        let old_text = buffer.text_for_range(old_range.clone()).collect::<String>();
3263
3264        let newest_selection = self.selections.newest_anchor();
3265        if newest_selection.start.buffer_id != Some(buffer_handle.read(cx).remote_id()) {
3266            return None;
3267        }
3268
3269        let lookbehind = newest_selection
3270            .start
3271            .text_anchor
3272            .to_offset(buffer)
3273            .saturating_sub(old_range.start);
3274        let lookahead = old_range
3275            .end
3276            .saturating_sub(newest_selection.end.text_anchor.to_offset(buffer));
3277        let mut common_prefix_len = old_text
3278            .bytes()
3279            .zip(text.bytes())
3280            .take_while(|(a, b)| a == b)
3281            .count();
3282
3283        let snapshot = self.buffer.read(cx).snapshot(cx);
3284        let mut range_to_replace: Option<Range<isize>> = None;
3285        let mut ranges = Vec::new();
3286        for selection in &selections {
3287            if snapshot.contains_str_at(selection.start.saturating_sub(lookbehind), &old_text) {
3288                let start = selection.start.saturating_sub(lookbehind);
3289                let end = selection.end + lookahead;
3290                if selection.id == newest_selection.id {
3291                    range_to_replace = Some(
3292                        ((start + common_prefix_len) as isize - selection.start as isize)
3293                            ..(end as isize - selection.start as isize),
3294                    );
3295                }
3296                ranges.push(start + common_prefix_len..end);
3297            } else {
3298                common_prefix_len = 0;
3299                ranges.clear();
3300                ranges.extend(selections.iter().map(|s| {
3301                    if s.id == newest_selection.id {
3302                        range_to_replace = Some(
3303                            old_range.start.to_offset_utf16(&snapshot).0 as isize
3304                                - selection.start as isize
3305                                ..old_range.end.to_offset_utf16(&snapshot).0 as isize
3306                                    - selection.start as isize,
3307                        );
3308                        old_range.clone()
3309                    } else {
3310                        s.start..s.end
3311                    }
3312                }));
3313                break;
3314            }
3315        }
3316        let text = &text[common_prefix_len..];
3317
3318        cx.emit(EditorEvent::InputHandled {
3319            utf16_range_to_replace: range_to_replace,
3320            text: text.into(),
3321        });
3322
3323        self.transact(cx, |this, cx| {
3324            if let Some(mut snippet) = snippet {
3325                snippet.text = text.to_string();
3326                for tabstop in snippet.tabstops.iter_mut().flatten() {
3327                    tabstop.start -= common_prefix_len as isize;
3328                    tabstop.end -= common_prefix_len as isize;
3329                }
3330
3331                this.insert_snippet(&ranges, snippet, cx).log_err();
3332            } else {
3333                this.buffer.update(cx, |buffer, cx| {
3334                    buffer.edit(
3335                        ranges.iter().map(|range| (range.clone(), text)),
3336                        this.autoindent_mode.clone(),
3337                        cx,
3338                    );
3339                });
3340            }
3341
3342            this.refresh_copilot_suggestions(true, cx);
3343        });
3344
3345        let provider = self.completion_provider.as_ref()?;
3346        let apply_edits = provider.apply_additional_edits_for_completion(
3347            buffer_handle,
3348            completion.clone(),
3349            true,
3350            cx,
3351        );
3352        Some(cx.foreground_executor().spawn(async move {
3353            apply_edits.await?;
3354            Ok(())
3355        }))
3356    }
3357
3358    pub fn toggle_code_actions(&mut self, action: &ToggleCodeActions, cx: &mut ViewContext<Self>) {
3359        let mut context_menu = self.context_menu.write();
3360        if matches!(context_menu.as_ref(), Some(ContextMenu::CodeActions(_))) {
3361            *context_menu = None;
3362            cx.notify();
3363            return;
3364        }
3365        drop(context_menu);
3366
3367        let deployed_from_indicator = action.deployed_from_indicator;
3368        let mut task = self.code_actions_task.take();
3369        cx.spawn(|this, mut cx| async move {
3370            while let Some(prev_task) = task {
3371                prev_task.await;
3372                task = this.update(&mut cx, |this, _| this.code_actions_task.take())?;
3373            }
3374
3375            this.update(&mut cx, |this, cx| {
3376                if this.focus_handle.is_focused(cx) {
3377                    if let Some((buffer, actions)) = this.available_code_actions.clone() {
3378                        this.completion_tasks.clear();
3379                        this.discard_copilot_suggestion(cx);
3380                        *this.context_menu.write() =
3381                            Some(ContextMenu::CodeActions(CodeActionsMenu {
3382                                buffer,
3383                                actions,
3384                                selected_item: Default::default(),
3385                                scroll_handle: UniformListScrollHandle::default(),
3386                                deployed_from_indicator,
3387                            }));
3388                        cx.notify();
3389                    }
3390                }
3391            })?;
3392
3393            Ok::<_, anyhow::Error>(())
3394        })
3395        .detach_and_log_err(cx);
3396    }
3397
3398    pub fn confirm_code_action(
3399        &mut self,
3400        action: &ConfirmCodeAction,
3401        cx: &mut ViewContext<Self>,
3402    ) -> Option<Task<Result<()>>> {
3403        let actions_menu = if let ContextMenu::CodeActions(menu) = self.hide_context_menu(cx)? {
3404            menu
3405        } else {
3406            return None;
3407        };
3408        let action_ix = action.item_ix.unwrap_or(actions_menu.selected_item);
3409        let action = actions_menu.actions.get(action_ix)?.clone();
3410        let title = action.lsp_action.title.clone();
3411        let buffer = actions_menu.buffer;
3412        let workspace = self.workspace()?;
3413
3414        let apply_code_actions = workspace
3415            .read(cx)
3416            .project()
3417            .clone()
3418            .update(cx, |project, cx| {
3419                project.apply_code_action(buffer, action, true, cx)
3420            });
3421        let workspace = workspace.downgrade();
3422        Some(cx.spawn(|editor, cx| async move {
3423            let project_transaction = apply_code_actions.await?;
3424            Self::open_project_transaction(&editor, workspace, project_transaction, title, cx).await
3425        }))
3426    }
3427
3428    async fn open_project_transaction(
3429        this: &WeakView<Editor>,
3430        workspace: WeakView<Workspace>,
3431        transaction: ProjectTransaction,
3432        title: String,
3433        mut cx: AsyncWindowContext,
3434    ) -> Result<()> {
3435        let replica_id = this.update(&mut cx, |this, cx| this.replica_id(cx))?;
3436
3437        let mut entries = transaction.0.into_iter().collect::<Vec<_>>();
3438        cx.update(|cx| {
3439            entries.sort_unstable_by_key(|(buffer, _)| {
3440                buffer.read(cx).file().map(|f| f.path().clone())
3441            });
3442        })?;
3443
3444        // If the project transaction's edits are all contained within this editor, then
3445        // avoid opening a new editor to display them.
3446
3447        if let Some((buffer, transaction)) = entries.first() {
3448            if entries.len() == 1 {
3449                let excerpt = this.update(&mut cx, |editor, cx| {
3450                    editor
3451                        .buffer()
3452                        .read(cx)
3453                        .excerpt_containing(editor.selections.newest_anchor().head(), cx)
3454                })?;
3455                if let Some((_, excerpted_buffer, excerpt_range)) = excerpt {
3456                    if excerpted_buffer == *buffer {
3457                        let all_edits_within_excerpt = buffer.read_with(&cx, |buffer, _| {
3458                            let excerpt_range = excerpt_range.to_offset(buffer);
3459                            buffer
3460                                .edited_ranges_for_transaction::<usize>(transaction)
3461                                .all(|range| {
3462                                    excerpt_range.start <= range.start
3463                                        && excerpt_range.end >= range.end
3464                                })
3465                        })?;
3466
3467                        if all_edits_within_excerpt {
3468                            return Ok(());
3469                        }
3470                    }
3471                }
3472            }
3473        } else {
3474            return Ok(());
3475        }
3476
3477        let mut ranges_to_highlight = Vec::new();
3478        let excerpt_buffer = cx.new_model(|cx| {
3479            let mut multibuffer =
3480                MultiBuffer::new(replica_id, Capability::ReadWrite).with_title(title);
3481            for (buffer_handle, transaction) in &entries {
3482                let buffer = buffer_handle.read(cx);
3483                ranges_to_highlight.extend(
3484                    multibuffer.push_excerpts_with_context_lines(
3485                        buffer_handle.clone(),
3486                        buffer
3487                            .edited_ranges_for_transaction::<usize>(transaction)
3488                            .collect(),
3489                        1,
3490                        cx,
3491                    ),
3492                );
3493            }
3494            multibuffer.push_transaction(entries.iter().map(|(b, t)| (b, t)), cx);
3495            multibuffer
3496        })?;
3497
3498        workspace.update(&mut cx, |workspace, cx| {
3499            let project = workspace.project().clone();
3500            let editor =
3501                cx.new_view(|cx| Editor::for_multibuffer(excerpt_buffer, Some(project), cx));
3502            workspace.add_item(Box::new(editor.clone()), cx);
3503            editor.update(cx, |editor, cx| {
3504                editor.highlight_background::<Self>(
3505                    ranges_to_highlight,
3506                    |theme| theme.editor_highlighted_line_background,
3507                    cx,
3508                );
3509            });
3510        })?;
3511
3512        Ok(())
3513    }
3514
3515    fn refresh_code_actions(&mut self, cx: &mut ViewContext<Self>) -> Option<()> {
3516        let project = self.project.clone()?;
3517        let buffer = self.buffer.read(cx);
3518        let newest_selection = self.selections.newest_anchor().clone();
3519        let (start_buffer, start) = buffer.text_anchor_for_position(newest_selection.start, cx)?;
3520        let (end_buffer, end) = buffer.text_anchor_for_position(newest_selection.end, cx)?;
3521        if start_buffer != end_buffer {
3522            return None;
3523        }
3524
3525        self.code_actions_task = Some(cx.spawn(|this, mut cx| async move {
3526            cx.background_executor()
3527                .timer(CODE_ACTIONS_DEBOUNCE_TIMEOUT)
3528                .await;
3529
3530            let actions = if let Ok(code_actions) = project.update(&mut cx, |project, cx| {
3531                project.code_actions(&start_buffer, start..end, cx)
3532            }) {
3533                code_actions.await.log_err()
3534            } else {
3535                None
3536            };
3537
3538            this.update(&mut cx, |this, cx| {
3539                this.available_code_actions = actions.and_then(|actions| {
3540                    if actions.is_empty() {
3541                        None
3542                    } else {
3543                        Some((start_buffer, actions.into()))
3544                    }
3545                });
3546                cx.notify();
3547            })
3548            .log_err();
3549        }));
3550        None
3551    }
3552
3553    fn refresh_document_highlights(&mut self, cx: &mut ViewContext<Self>) -> Option<()> {
3554        if self.pending_rename.is_some() {
3555            return None;
3556        }
3557
3558        let project = self.project.clone()?;
3559        let buffer = self.buffer.read(cx);
3560        let newest_selection = self.selections.newest_anchor().clone();
3561        let cursor_position = newest_selection.head();
3562        let (cursor_buffer, cursor_buffer_position) =
3563            buffer.text_anchor_for_position(cursor_position.clone(), cx)?;
3564        let (tail_buffer, _) = buffer.text_anchor_for_position(newest_selection.tail(), cx)?;
3565        if cursor_buffer != tail_buffer {
3566            return None;
3567        }
3568
3569        self.document_highlights_task = Some(cx.spawn(|this, mut cx| async move {
3570            cx.background_executor()
3571                .timer(DOCUMENT_HIGHLIGHTS_DEBOUNCE_TIMEOUT)
3572                .await;
3573
3574            let highlights = if let Some(highlights) = project
3575                .update(&mut cx, |project, cx| {
3576                    project.document_highlights(&cursor_buffer, cursor_buffer_position, cx)
3577                })
3578                .log_err()
3579            {
3580                highlights.await.log_err()
3581            } else {
3582                None
3583            };
3584
3585            if let Some(highlights) = highlights {
3586                this.update(&mut cx, |this, cx| {
3587                    if this.pending_rename.is_some() {
3588                        return;
3589                    }
3590
3591                    let buffer_id = cursor_position.buffer_id;
3592                    let buffer = this.buffer.read(cx);
3593                    if !buffer
3594                        .text_anchor_for_position(cursor_position, cx)
3595                        .map_or(false, |(buffer, _)| buffer == cursor_buffer)
3596                    {
3597                        return;
3598                    }
3599
3600                    let cursor_buffer_snapshot = cursor_buffer.read(cx);
3601                    let mut write_ranges = Vec::new();
3602                    let mut read_ranges = Vec::new();
3603                    for highlight in highlights {
3604                        for (excerpt_id, excerpt_range) in
3605                            buffer.excerpts_for_buffer(&cursor_buffer, cx)
3606                        {
3607                            let start = highlight
3608                                .range
3609                                .start
3610                                .max(&excerpt_range.context.start, cursor_buffer_snapshot);
3611                            let end = highlight
3612                                .range
3613                                .end
3614                                .min(&excerpt_range.context.end, cursor_buffer_snapshot);
3615                            if start.cmp(&end, cursor_buffer_snapshot).is_ge() {
3616                                continue;
3617                            }
3618
3619                            let range = Anchor {
3620                                buffer_id,
3621                                excerpt_id: excerpt_id.clone(),
3622                                text_anchor: start,
3623                            }..Anchor {
3624                                buffer_id,
3625                                excerpt_id,
3626                                text_anchor: end,
3627                            };
3628                            if highlight.kind == lsp::DocumentHighlightKind::WRITE {
3629                                write_ranges.push(range);
3630                            } else {
3631                                read_ranges.push(range);
3632                            }
3633                        }
3634                    }
3635
3636                    this.highlight_background::<DocumentHighlightRead>(
3637                        read_ranges,
3638                        |theme| theme.editor_document_highlight_read_background,
3639                        cx,
3640                    );
3641                    this.highlight_background::<DocumentHighlightWrite>(
3642                        write_ranges,
3643                        |theme| theme.editor_document_highlight_write_background,
3644                        cx,
3645                    );
3646                    cx.notify();
3647                })
3648                .log_err();
3649            }
3650        }));
3651        None
3652    }
3653
3654    fn refresh_copilot_suggestions(
3655        &mut self,
3656        debounce: bool,
3657        cx: &mut ViewContext<Self>,
3658    ) -> Option<()> {
3659        let copilot = Copilot::global(cx)?;
3660        if !self.show_copilot_suggestions || !copilot.read(cx).status().is_authorized() {
3661            self.clear_copilot_suggestions(cx);
3662            return None;
3663        }
3664        self.update_visible_copilot_suggestion(cx);
3665
3666        let snapshot = self.buffer.read(cx).snapshot(cx);
3667        let cursor = self.selections.newest_anchor().head();
3668        if !self.is_copilot_enabled_at(cursor, &snapshot, cx) {
3669            self.clear_copilot_suggestions(cx);
3670            return None;
3671        }
3672
3673        let (buffer, buffer_position) =
3674            self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
3675        self.copilot_state.pending_refresh = cx.spawn(|this, mut cx| async move {
3676            if debounce {
3677                cx.background_executor()
3678                    .timer(COPILOT_DEBOUNCE_TIMEOUT)
3679                    .await;
3680            }
3681
3682            let completions = copilot
3683                .update(&mut cx, |copilot, cx| {
3684                    copilot.completions(&buffer, buffer_position, cx)
3685                })
3686                .log_err()
3687                .unwrap_or(Task::ready(Ok(Vec::new())))
3688                .await
3689                .log_err()
3690                .into_iter()
3691                .flatten()
3692                .collect_vec();
3693
3694            this.update(&mut cx, |this, cx| {
3695                if !completions.is_empty() {
3696                    this.copilot_state.cycled = false;
3697                    this.copilot_state.pending_cycling_refresh = Task::ready(None);
3698                    this.copilot_state.completions.clear();
3699                    this.copilot_state.active_completion_index = 0;
3700                    this.copilot_state.excerpt_id = Some(cursor.excerpt_id);
3701                    for completion in completions {
3702                        this.copilot_state.push_completion(completion);
3703                    }
3704                    this.update_visible_copilot_suggestion(cx);
3705                }
3706            })
3707            .log_err()?;
3708            Some(())
3709        });
3710
3711        Some(())
3712    }
3713
3714    fn cycle_copilot_suggestions(
3715        &mut self,
3716        direction: Direction,
3717        cx: &mut ViewContext<Self>,
3718    ) -> Option<()> {
3719        let copilot = Copilot::global(cx)?;
3720        if !self.show_copilot_suggestions || !copilot.read(cx).status().is_authorized() {
3721            return None;
3722        }
3723
3724        if self.copilot_state.cycled {
3725            self.copilot_state.cycle_completions(direction);
3726            self.update_visible_copilot_suggestion(cx);
3727        } else {
3728            let cursor = self.selections.newest_anchor().head();
3729            let (buffer, buffer_position) =
3730                self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
3731            self.copilot_state.pending_cycling_refresh = cx.spawn(|this, mut cx| async move {
3732                let completions = copilot
3733                    .update(&mut cx, |copilot, cx| {
3734                        copilot.completions_cycling(&buffer, buffer_position, cx)
3735                    })
3736                    .log_err()?
3737                    .await;
3738
3739                this.update(&mut cx, |this, cx| {
3740                    this.copilot_state.cycled = true;
3741                    for completion in completions.log_err().into_iter().flatten() {
3742                        this.copilot_state.push_completion(completion);
3743                    }
3744                    this.copilot_state.cycle_completions(direction);
3745                    this.update_visible_copilot_suggestion(cx);
3746                })
3747                .log_err()?;
3748
3749                Some(())
3750            });
3751        }
3752
3753        Some(())
3754    }
3755
3756    fn copilot_suggest(&mut self, _: &copilot::Suggest, cx: &mut ViewContext<Self>) {
3757        if !self.has_active_copilot_suggestion(cx) {
3758            self.refresh_copilot_suggestions(false, cx);
3759            return;
3760        }
3761
3762        self.update_visible_copilot_suggestion(cx);
3763    }
3764
3765    pub fn display_cursor_names(&mut self, _: &DisplayCursorNames, cx: &mut ViewContext<Self>) {
3766        self.show_cursor_names(cx);
3767    }
3768
3769    fn show_cursor_names(&mut self, cx: &mut ViewContext<Self>) {
3770        self.show_cursor_names = true;
3771        cx.notify();
3772        cx.spawn(|this, mut cx| async move {
3773            cx.background_executor().timer(CURSORS_VISIBLE_FOR).await;
3774            this.update(&mut cx, |this, cx| {
3775                this.show_cursor_names = false;
3776                cx.notify()
3777            })
3778            .ok()
3779        })
3780        .detach();
3781    }
3782
3783    fn next_copilot_suggestion(&mut self, _: &copilot::NextSuggestion, cx: &mut ViewContext<Self>) {
3784        if self.has_active_copilot_suggestion(cx) {
3785            self.cycle_copilot_suggestions(Direction::Next, cx);
3786        } else {
3787            let is_copilot_disabled = self.refresh_copilot_suggestions(false, cx).is_none();
3788            if is_copilot_disabled {
3789                cx.propagate();
3790            }
3791        }
3792    }
3793
3794    fn previous_copilot_suggestion(
3795        &mut self,
3796        _: &copilot::PreviousSuggestion,
3797        cx: &mut ViewContext<Self>,
3798    ) {
3799        if self.has_active_copilot_suggestion(cx) {
3800            self.cycle_copilot_suggestions(Direction::Prev, cx);
3801        } else {
3802            let is_copilot_disabled = self.refresh_copilot_suggestions(false, cx).is_none();
3803            if is_copilot_disabled {
3804                cx.propagate();
3805            }
3806        }
3807    }
3808
3809    fn accept_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) -> bool {
3810        if let Some(suggestion) = self.take_active_copilot_suggestion(cx) {
3811            if let Some((copilot, completion)) =
3812                Copilot::global(cx).zip(self.copilot_state.active_completion())
3813            {
3814                copilot
3815                    .update(cx, |copilot, cx| copilot.accept_completion(completion, cx))
3816                    .detach_and_log_err(cx);
3817
3818                self.report_copilot_event(Some(completion.uuid.clone()), true, cx)
3819            }
3820            cx.emit(EditorEvent::InputHandled {
3821                utf16_range_to_replace: None,
3822                text: suggestion.text.to_string().into(),
3823            });
3824            self.insert_with_autoindent_mode(&suggestion.text.to_string(), None, cx);
3825            cx.notify();
3826            true
3827        } else {
3828            false
3829        }
3830    }
3831
3832    fn discard_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) -> bool {
3833        if let Some(suggestion) = self.take_active_copilot_suggestion(cx) {
3834            if let Some(copilot) = Copilot::global(cx) {
3835                copilot
3836                    .update(cx, |copilot, cx| {
3837                        copilot.discard_completions(&self.copilot_state.completions, cx)
3838                    })
3839                    .detach_and_log_err(cx);
3840
3841                self.report_copilot_event(None, false, cx)
3842            }
3843
3844            self.display_map.update(cx, |map, cx| {
3845                map.splice_inlays(vec![suggestion.id], Vec::new(), cx)
3846            });
3847            cx.notify();
3848            true
3849        } else {
3850            false
3851        }
3852    }
3853
3854    fn is_copilot_enabled_at(
3855        &self,
3856        location: Anchor,
3857        snapshot: &MultiBufferSnapshot,
3858        cx: &mut ViewContext<Self>,
3859    ) -> bool {
3860        let file = snapshot.file_at(location);
3861        let language = snapshot.language_at(location);
3862        let settings = all_language_settings(file, cx);
3863        self.show_copilot_suggestions
3864            && settings.copilot_enabled(language, file.map(|f| f.path().as_ref()))
3865    }
3866
3867    fn has_active_copilot_suggestion(&self, cx: &AppContext) -> bool {
3868        if let Some(suggestion) = self.copilot_state.suggestion.as_ref() {
3869            let buffer = self.buffer.read(cx).read(cx);
3870            suggestion.position.is_valid(&buffer)
3871        } else {
3872            false
3873        }
3874    }
3875
3876    fn take_active_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) -> Option<Inlay> {
3877        let suggestion = self.copilot_state.suggestion.take()?;
3878        self.display_map.update(cx, |map, cx| {
3879            map.splice_inlays(vec![suggestion.id], Default::default(), cx);
3880        });
3881        let buffer = self.buffer.read(cx).read(cx);
3882
3883        if suggestion.position.is_valid(&buffer) {
3884            Some(suggestion)
3885        } else {
3886            None
3887        }
3888    }
3889
3890    fn update_visible_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) {
3891        let snapshot = self.buffer.read(cx).snapshot(cx);
3892        let selection = self.selections.newest_anchor();
3893        let cursor = selection.head();
3894
3895        if self.context_menu.read().is_some()
3896            || !self.completion_tasks.is_empty()
3897            || selection.start != selection.end
3898        {
3899            self.discard_copilot_suggestion(cx);
3900        } else if let Some(text) = self
3901            .copilot_state
3902            .text_for_active_completion(cursor, &snapshot)
3903        {
3904            let text = Rope::from(text);
3905            let mut to_remove = Vec::new();
3906            if let Some(suggestion) = self.copilot_state.suggestion.take() {
3907                to_remove.push(suggestion.id);
3908            }
3909
3910            let suggestion_inlay =
3911                Inlay::suggestion(post_inc(&mut self.next_inlay_id), cursor, text);
3912            self.copilot_state.suggestion = Some(suggestion_inlay.clone());
3913            self.display_map.update(cx, move |map, cx| {
3914                map.splice_inlays(to_remove, vec![suggestion_inlay], cx)
3915            });
3916            cx.notify();
3917        } else {
3918            self.discard_copilot_suggestion(cx);
3919        }
3920    }
3921
3922    fn clear_copilot_suggestions(&mut self, cx: &mut ViewContext<Self>) {
3923        self.copilot_state = Default::default();
3924        self.discard_copilot_suggestion(cx);
3925    }
3926
3927    pub fn render_code_actions_indicator(
3928        &self,
3929        _style: &EditorStyle,
3930        is_active: bool,
3931        cx: &mut ViewContext<Self>,
3932    ) -> Option<IconButton> {
3933        if self.available_code_actions.is_some() {
3934            Some(
3935                IconButton::new("code_actions_indicator", ui::IconName::Bolt)
3936                    .icon_size(IconSize::Small)
3937                    .icon_color(Color::Muted)
3938                    .selected(is_active)
3939                    .on_click(cx.listener(|editor, _e, cx| {
3940                        editor.toggle_code_actions(
3941                            &ToggleCodeActions {
3942                                deployed_from_indicator: true,
3943                            },
3944                            cx,
3945                        );
3946                    })),
3947            )
3948        } else {
3949            None
3950        }
3951    }
3952
3953    pub fn render_fold_indicators(
3954        &self,
3955        fold_data: Vec<Option<(FoldStatus, u32, bool)>>,
3956        _style: &EditorStyle,
3957        gutter_hovered: bool,
3958        _line_height: Pixels,
3959        _gutter_margin: Pixels,
3960        editor_view: View<Editor>,
3961    ) -> Vec<Option<IconButton>> {
3962        fold_data
3963            .iter()
3964            .enumerate()
3965            .map(|(ix, fold_data)| {
3966                fold_data
3967                    .map(|(fold_status, buffer_row, active)| {
3968                        (active || gutter_hovered || fold_status == FoldStatus::Folded).then(|| {
3969                            IconButton::new(ix as usize, ui::IconName::ChevronDown)
3970                                .on_click({
3971                                    let view = editor_view.clone();
3972                                    move |_e, cx| {
3973                                        view.update(cx, |editor, cx| match fold_status {
3974                                            FoldStatus::Folded => {
3975                                                editor.unfold_at(&UnfoldAt { buffer_row }, cx);
3976                                            }
3977                                            FoldStatus::Foldable => {
3978                                                editor.fold_at(&FoldAt { buffer_row }, cx);
3979                                            }
3980                                        })
3981                                    }
3982                                })
3983                                .icon_color(ui::Color::Muted)
3984                                .icon_size(ui::IconSize::Small)
3985                                .selected(fold_status == FoldStatus::Folded)
3986                                .selected_icon(ui::IconName::ChevronRight)
3987                                .size(ui::ButtonSize::None)
3988                        })
3989                    })
3990                    .flatten()
3991            })
3992            .collect()
3993    }
3994
3995    pub fn context_menu_visible(&self) -> bool {
3996        self.context_menu
3997            .read()
3998            .as_ref()
3999            .map_or(false, |menu| menu.visible())
4000    }
4001
4002    pub fn render_context_menu(
4003        &self,
4004        cursor_position: DisplayPoint,
4005        style: &EditorStyle,
4006        max_height: Pixels,
4007        cx: &mut ViewContext<Editor>,
4008    ) -> Option<(DisplayPoint, AnyElement)> {
4009        self.context_menu.read().as_ref().map(|menu| {
4010            menu.render(
4011                cursor_position,
4012                style,
4013                max_height,
4014                self.workspace.as_ref().map(|(w, _)| w.clone()),
4015                cx,
4016            )
4017        })
4018    }
4019
4020    fn hide_context_menu(&mut self, cx: &mut ViewContext<Self>) -> Option<ContextMenu> {
4021        cx.notify();
4022        self.completion_tasks.clear();
4023        let context_menu = self.context_menu.write().take();
4024        if context_menu.is_some() {
4025            self.update_visible_copilot_suggestion(cx);
4026        }
4027        context_menu
4028    }
4029
4030    pub fn insert_snippet(
4031        &mut self,
4032        insertion_ranges: &[Range<usize>],
4033        snippet: Snippet,
4034        cx: &mut ViewContext<Self>,
4035    ) -> Result<()> {
4036        let tabstops = self.buffer.update(cx, |buffer, cx| {
4037            let snippet_text: Arc<str> = snippet.text.clone().into();
4038            buffer.edit(
4039                insertion_ranges
4040                    .iter()
4041                    .cloned()
4042                    .map(|range| (range, snippet_text.clone())),
4043                Some(AutoindentMode::EachLine),
4044                cx,
4045            );
4046
4047            let snapshot = &*buffer.read(cx);
4048            let snippet = &snippet;
4049            snippet
4050                .tabstops
4051                .iter()
4052                .map(|tabstop| {
4053                    let mut tabstop_ranges = tabstop
4054                        .iter()
4055                        .flat_map(|tabstop_range| {
4056                            let mut delta = 0_isize;
4057                            insertion_ranges.iter().map(move |insertion_range| {
4058                                let insertion_start = insertion_range.start as isize + delta;
4059                                delta +=
4060                                    snippet.text.len() as isize - insertion_range.len() as isize;
4061
4062                                let start = snapshot.anchor_before(
4063                                    (insertion_start + tabstop_range.start) as usize,
4064                                );
4065                                let end = snapshot
4066                                    .anchor_after((insertion_start + tabstop_range.end) as usize);
4067                                start..end
4068                            })
4069                        })
4070                        .collect::<Vec<_>>();
4071                    tabstop_ranges.sort_unstable_by(|a, b| a.start.cmp(&b.start, snapshot));
4072                    tabstop_ranges
4073                })
4074                .collect::<Vec<_>>()
4075        });
4076
4077        if let Some(tabstop) = tabstops.first() {
4078            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4079                s.select_ranges(tabstop.iter().cloned());
4080            });
4081            self.snippet_stack.push(SnippetState {
4082                active_index: 0,
4083                ranges: tabstops,
4084            });
4085        }
4086
4087        Ok(())
4088    }
4089
4090    pub fn move_to_next_snippet_tabstop(&mut self, cx: &mut ViewContext<Self>) -> bool {
4091        self.move_to_snippet_tabstop(Bias::Right, cx)
4092    }
4093
4094    pub fn move_to_prev_snippet_tabstop(&mut self, cx: &mut ViewContext<Self>) -> bool {
4095        self.move_to_snippet_tabstop(Bias::Left, cx)
4096    }
4097
4098    pub fn move_to_snippet_tabstop(&mut self, bias: Bias, cx: &mut ViewContext<Self>) -> bool {
4099        if let Some(mut snippet) = self.snippet_stack.pop() {
4100            match bias {
4101                Bias::Left => {
4102                    if snippet.active_index > 0 {
4103                        snippet.active_index -= 1;
4104                    } else {
4105                        self.snippet_stack.push(snippet);
4106                        return false;
4107                    }
4108                }
4109                Bias::Right => {
4110                    if snippet.active_index + 1 < snippet.ranges.len() {
4111                        snippet.active_index += 1;
4112                    } else {
4113                        self.snippet_stack.push(snippet);
4114                        return false;
4115                    }
4116                }
4117            }
4118            if let Some(current_ranges) = snippet.ranges.get(snippet.active_index) {
4119                self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4120                    s.select_anchor_ranges(current_ranges.iter().cloned())
4121                });
4122                // If snippet state is not at the last tabstop, push it back on the stack
4123                if snippet.active_index + 1 < snippet.ranges.len() {
4124                    self.snippet_stack.push(snippet);
4125                }
4126                return true;
4127            }
4128        }
4129
4130        false
4131    }
4132
4133    pub fn clear(&mut self, cx: &mut ViewContext<Self>) {
4134        self.transact(cx, |this, cx| {
4135            this.select_all(&SelectAll, cx);
4136            this.insert("", cx);
4137        });
4138    }
4139
4140    pub fn backspace(&mut self, _: &Backspace, cx: &mut ViewContext<Self>) {
4141        self.transact(cx, |this, cx| {
4142            this.select_autoclose_pair(cx);
4143            let mut selections = this.selections.all::<Point>(cx);
4144            if !this.selections.line_mode {
4145                let display_map = this.display_map.update(cx, |map, cx| map.snapshot(cx));
4146                for selection in &mut selections {
4147                    if selection.is_empty() {
4148                        let old_head = selection.head();
4149                        let mut new_head =
4150                            movement::left(&display_map, old_head.to_display_point(&display_map))
4151                                .to_point(&display_map);
4152                        if let Some((buffer, line_buffer_range)) = display_map
4153                            .buffer_snapshot
4154                            .buffer_line_for_row(old_head.row)
4155                        {
4156                            let indent_size =
4157                                buffer.indent_size_for_line(line_buffer_range.start.row);
4158                            let indent_len = match indent_size.kind {
4159                                IndentKind::Space => {
4160                                    buffer.settings_at(line_buffer_range.start, cx).tab_size
4161                                }
4162                                IndentKind::Tab => NonZeroU32::new(1).unwrap(),
4163                            };
4164                            if old_head.column <= indent_size.len && old_head.column > 0 {
4165                                let indent_len = indent_len.get();
4166                                new_head = cmp::min(
4167                                    new_head,
4168                                    Point::new(
4169                                        old_head.row,
4170                                        ((old_head.column - 1) / indent_len) * indent_len,
4171                                    ),
4172                                );
4173                            }
4174                        }
4175
4176                        selection.set_head(new_head, SelectionGoal::None);
4177                    }
4178                }
4179            }
4180
4181            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
4182            this.insert("", cx);
4183            this.refresh_copilot_suggestions(true, cx);
4184        });
4185    }
4186
4187    pub fn delete(&mut self, _: &Delete, cx: &mut ViewContext<Self>) {
4188        self.transact(cx, |this, cx| {
4189            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4190                let line_mode = s.line_mode;
4191                s.move_with(|map, selection| {
4192                    if selection.is_empty() && !line_mode {
4193                        let cursor = movement::right(map, selection.head());
4194                        selection.end = cursor;
4195                        selection.reversed = true;
4196                        selection.goal = SelectionGoal::None;
4197                    }
4198                })
4199            });
4200            this.insert("", cx);
4201            this.refresh_copilot_suggestions(true, cx);
4202        });
4203    }
4204
4205    pub fn tab_prev(&mut self, _: &TabPrev, cx: &mut ViewContext<Self>) {
4206        if self.move_to_prev_snippet_tabstop(cx) {
4207            return;
4208        }
4209
4210        self.outdent(&Outdent, cx);
4211    }
4212
4213    pub fn tab(&mut self, _: &Tab, cx: &mut ViewContext<Self>) {
4214        if self.move_to_next_snippet_tabstop(cx) || self.read_only(cx) {
4215            return;
4216        }
4217
4218        let mut selections = self.selections.all_adjusted(cx);
4219        let buffer = self.buffer.read(cx);
4220        let snapshot = buffer.snapshot(cx);
4221        let rows_iter = selections.iter().map(|s| s.head().row);
4222        let suggested_indents = snapshot.suggested_indents(rows_iter, cx);
4223
4224        let mut edits = Vec::new();
4225        let mut prev_edited_row = 0;
4226        let mut row_delta = 0;
4227        for selection in &mut selections {
4228            if selection.start.row != prev_edited_row {
4229                row_delta = 0;
4230            }
4231            prev_edited_row = selection.end.row;
4232
4233            // If the selection is non-empty, then increase the indentation of the selected lines.
4234            if !selection.is_empty() {
4235                row_delta =
4236                    Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
4237                continue;
4238            }
4239
4240            // If the selection is empty and the cursor is in the leading whitespace before the
4241            // suggested indentation, then auto-indent the line.
4242            let cursor = selection.head();
4243            let current_indent = snapshot.indent_size_for_line(cursor.row);
4244            if let Some(suggested_indent) = suggested_indents.get(&cursor.row).copied() {
4245                if cursor.column < suggested_indent.len
4246                    && cursor.column <= current_indent.len
4247                    && current_indent.len <= suggested_indent.len
4248                {
4249                    selection.start = Point::new(cursor.row, suggested_indent.len);
4250                    selection.end = selection.start;
4251                    if row_delta == 0 {
4252                        edits.extend(Buffer::edit_for_indent_size_adjustment(
4253                            cursor.row,
4254                            current_indent,
4255                            suggested_indent,
4256                        ));
4257                        row_delta = suggested_indent.len - current_indent.len;
4258                    }
4259                    continue;
4260                }
4261            }
4262
4263            // Accept copilot suggestion if there is only one selection and the cursor is not
4264            // in the leading whitespace.
4265            if self.selections.count() == 1
4266                && cursor.column >= current_indent.len
4267                && self.has_active_copilot_suggestion(cx)
4268            {
4269                self.accept_copilot_suggestion(cx);
4270                return;
4271            }
4272
4273            // Otherwise, insert a hard or soft tab.
4274            let settings = buffer.settings_at(cursor, cx);
4275            let tab_size = if settings.hard_tabs {
4276                IndentSize::tab()
4277            } else {
4278                let tab_size = settings.tab_size.get();
4279                let char_column = snapshot
4280                    .text_for_range(Point::new(cursor.row, 0)..cursor)
4281                    .flat_map(str::chars)
4282                    .count()
4283                    + row_delta as usize;
4284                let chars_to_next_tab_stop = tab_size - (char_column as u32 % tab_size);
4285                IndentSize::spaces(chars_to_next_tab_stop)
4286            };
4287            selection.start = Point::new(cursor.row, cursor.column + row_delta + tab_size.len);
4288            selection.end = selection.start;
4289            edits.push((cursor..cursor, tab_size.chars().collect::<String>()));
4290            row_delta += tab_size.len;
4291        }
4292
4293        self.transact(cx, |this, cx| {
4294            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
4295            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
4296            this.refresh_copilot_suggestions(true, cx);
4297        });
4298    }
4299
4300    pub fn indent(&mut self, _: &Indent, cx: &mut ViewContext<Self>) {
4301        let mut selections = self.selections.all::<Point>(cx);
4302        let mut prev_edited_row = 0;
4303        let mut row_delta = 0;
4304        let mut edits = Vec::new();
4305        let buffer = self.buffer.read(cx);
4306        let snapshot = buffer.snapshot(cx);
4307        for selection in &mut selections {
4308            if selection.start.row != prev_edited_row {
4309                row_delta = 0;
4310            }
4311            prev_edited_row = selection.end.row;
4312
4313            row_delta =
4314                Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
4315        }
4316
4317        self.transact(cx, |this, cx| {
4318            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
4319            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
4320        });
4321    }
4322
4323    fn indent_selection(
4324        buffer: &MultiBuffer,
4325        snapshot: &MultiBufferSnapshot,
4326        selection: &mut Selection<Point>,
4327        edits: &mut Vec<(Range<Point>, String)>,
4328        delta_for_start_row: u32,
4329        cx: &AppContext,
4330    ) -> u32 {
4331        let settings = buffer.settings_at(selection.start, cx);
4332        let tab_size = settings.tab_size.get();
4333        let indent_kind = if settings.hard_tabs {
4334            IndentKind::Tab
4335        } else {
4336            IndentKind::Space
4337        };
4338        let mut start_row = selection.start.row;
4339        let mut end_row = selection.end.row + 1;
4340
4341        // If a selection ends at the beginning of a line, don't indent
4342        // that last line.
4343        if selection.end.column == 0 {
4344            end_row -= 1;
4345        }
4346
4347        // Avoid re-indenting a row that has already been indented by a
4348        // previous selection, but still update this selection's column
4349        // to reflect that indentation.
4350        if delta_for_start_row > 0 {
4351            start_row += 1;
4352            selection.start.column += delta_for_start_row;
4353            if selection.end.row == selection.start.row {
4354                selection.end.column += delta_for_start_row;
4355            }
4356        }
4357
4358        let mut delta_for_end_row = 0;
4359        for row in start_row..end_row {
4360            let current_indent = snapshot.indent_size_for_line(row);
4361            let indent_delta = match (current_indent.kind, indent_kind) {
4362                (IndentKind::Space, IndentKind::Space) => {
4363                    let columns_to_next_tab_stop = tab_size - (current_indent.len % tab_size);
4364                    IndentSize::spaces(columns_to_next_tab_stop)
4365                }
4366                (IndentKind::Tab, IndentKind::Space) => IndentSize::spaces(tab_size),
4367                (_, IndentKind::Tab) => IndentSize::tab(),
4368            };
4369
4370            let row_start = Point::new(row, 0);
4371            edits.push((
4372                row_start..row_start,
4373                indent_delta.chars().collect::<String>(),
4374            ));
4375
4376            // Update this selection's endpoints to reflect the indentation.
4377            if row == selection.start.row {
4378                selection.start.column += indent_delta.len;
4379            }
4380            if row == selection.end.row {
4381                selection.end.column += indent_delta.len;
4382                delta_for_end_row = indent_delta.len;
4383            }
4384        }
4385
4386        if selection.start.row == selection.end.row {
4387            delta_for_start_row + delta_for_end_row
4388        } else {
4389            delta_for_end_row
4390        }
4391    }
4392
4393    pub fn outdent(&mut self, _: &Outdent, cx: &mut ViewContext<Self>) {
4394        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4395        let selections = self.selections.all::<Point>(cx);
4396        let mut deletion_ranges = Vec::new();
4397        let mut last_outdent = None;
4398        {
4399            let buffer = self.buffer.read(cx);
4400            let snapshot = buffer.snapshot(cx);
4401            for selection in &selections {
4402                let settings = buffer.settings_at(selection.start, cx);
4403                let tab_size = settings.tab_size.get();
4404                let mut rows = selection.spanned_rows(false, &display_map);
4405
4406                // Avoid re-outdenting a row that has already been outdented by a
4407                // previous selection.
4408                if let Some(last_row) = last_outdent {
4409                    if last_row == rows.start {
4410                        rows.start += 1;
4411                    }
4412                }
4413
4414                for row in rows {
4415                    let indent_size = snapshot.indent_size_for_line(row);
4416                    if indent_size.len > 0 {
4417                        let deletion_len = match indent_size.kind {
4418                            IndentKind::Space => {
4419                                let columns_to_prev_tab_stop = indent_size.len % tab_size;
4420                                if columns_to_prev_tab_stop == 0 {
4421                                    tab_size
4422                                } else {
4423                                    columns_to_prev_tab_stop
4424                                }
4425                            }
4426                            IndentKind::Tab => 1,
4427                        };
4428                        deletion_ranges.push(Point::new(row, 0)..Point::new(row, deletion_len));
4429                        last_outdent = Some(row);
4430                    }
4431                }
4432            }
4433        }
4434
4435        self.transact(cx, |this, cx| {
4436            this.buffer.update(cx, |buffer, cx| {
4437                let empty_str: Arc<str> = "".into();
4438                buffer.edit(
4439                    deletion_ranges
4440                        .into_iter()
4441                        .map(|range| (range, empty_str.clone())),
4442                    None,
4443                    cx,
4444                );
4445            });
4446            let selections = this.selections.all::<usize>(cx);
4447            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
4448        });
4449    }
4450
4451    pub fn delete_line(&mut self, _: &DeleteLine, cx: &mut ViewContext<Self>) {
4452        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4453        let selections = self.selections.all::<Point>(cx);
4454
4455        let mut new_cursors = Vec::new();
4456        let mut edit_ranges = Vec::new();
4457        let mut selections = selections.iter().peekable();
4458        while let Some(selection) = selections.next() {
4459            let mut rows = selection.spanned_rows(false, &display_map);
4460            let goal_display_column = selection.head().to_display_point(&display_map).column();
4461
4462            // Accumulate contiguous regions of rows that we want to delete.
4463            while let Some(next_selection) = selections.peek() {
4464                let next_rows = next_selection.spanned_rows(false, &display_map);
4465                if next_rows.start <= rows.end {
4466                    rows.end = next_rows.end;
4467                    selections.next().unwrap();
4468                } else {
4469                    break;
4470                }
4471            }
4472
4473            let buffer = &display_map.buffer_snapshot;
4474            let mut edit_start = Point::new(rows.start, 0).to_offset(buffer);
4475            let edit_end;
4476            let cursor_buffer_row;
4477            if buffer.max_point().row >= rows.end {
4478                // If there's a line after the range, delete the \n from the end of the row range
4479                // and position the cursor on the next line.
4480                edit_end = Point::new(rows.end, 0).to_offset(buffer);
4481                cursor_buffer_row = rows.end;
4482            } else {
4483                // If there isn't a line after the range, delete the \n from the line before the
4484                // start of the row range and position the cursor there.
4485                edit_start = edit_start.saturating_sub(1);
4486                edit_end = buffer.len();
4487                cursor_buffer_row = rows.start.saturating_sub(1);
4488            }
4489
4490            let mut cursor = Point::new(cursor_buffer_row, 0).to_display_point(&display_map);
4491            *cursor.column_mut() =
4492                cmp::min(goal_display_column, display_map.line_len(cursor.row()));
4493
4494            new_cursors.push((
4495                selection.id,
4496                buffer.anchor_after(cursor.to_point(&display_map)),
4497            ));
4498            edit_ranges.push(edit_start..edit_end);
4499        }
4500
4501        self.transact(cx, |this, cx| {
4502            let buffer = this.buffer.update(cx, |buffer, cx| {
4503                let empty_str: Arc<str> = "".into();
4504                buffer.edit(
4505                    edit_ranges
4506                        .into_iter()
4507                        .map(|range| (range, empty_str.clone())),
4508                    None,
4509                    cx,
4510                );
4511                buffer.snapshot(cx)
4512            });
4513            let new_selections = new_cursors
4514                .into_iter()
4515                .map(|(id, cursor)| {
4516                    let cursor = cursor.to_point(&buffer);
4517                    Selection {
4518                        id,
4519                        start: cursor,
4520                        end: cursor,
4521                        reversed: false,
4522                        goal: SelectionGoal::None,
4523                    }
4524                })
4525                .collect();
4526
4527            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4528                s.select(new_selections);
4529            });
4530        });
4531    }
4532
4533    pub fn join_lines(&mut self, _: &JoinLines, cx: &mut ViewContext<Self>) {
4534        let mut row_ranges = Vec::<Range<u32>>::new();
4535        for selection in self.selections.all::<Point>(cx) {
4536            let start = selection.start.row;
4537            let end = if selection.start.row == selection.end.row {
4538                selection.start.row + 1
4539            } else {
4540                selection.end.row
4541            };
4542
4543            if let Some(last_row_range) = row_ranges.last_mut() {
4544                if start <= last_row_range.end {
4545                    last_row_range.end = end;
4546                    continue;
4547                }
4548            }
4549            row_ranges.push(start..end);
4550        }
4551
4552        let snapshot = self.buffer.read(cx).snapshot(cx);
4553        let mut cursor_positions = Vec::new();
4554        for row_range in &row_ranges {
4555            let anchor = snapshot.anchor_before(Point::new(
4556                row_range.end - 1,
4557                snapshot.line_len(row_range.end - 1),
4558            ));
4559            cursor_positions.push(anchor.clone()..anchor);
4560        }
4561
4562        self.transact(cx, |this, cx| {
4563            for row_range in row_ranges.into_iter().rev() {
4564                for row in row_range.rev() {
4565                    let end_of_line = Point::new(row, snapshot.line_len(row));
4566                    let indent = snapshot.indent_size_for_line(row + 1);
4567                    let start_of_next_line = Point::new(row + 1, indent.len);
4568
4569                    let replace = if snapshot.line_len(row + 1) > indent.len {
4570                        " "
4571                    } else {
4572                        ""
4573                    };
4574
4575                    this.buffer.update(cx, |buffer, cx| {
4576                        buffer.edit([(end_of_line..start_of_next_line, replace)], None, cx)
4577                    });
4578                }
4579            }
4580
4581            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4582                s.select_anchor_ranges(cursor_positions)
4583            });
4584        });
4585    }
4586
4587    pub fn sort_lines_case_sensitive(
4588        &mut self,
4589        _: &SortLinesCaseSensitive,
4590        cx: &mut ViewContext<Self>,
4591    ) {
4592        self.manipulate_lines(cx, |lines| lines.sort())
4593    }
4594
4595    pub fn sort_lines_case_insensitive(
4596        &mut self,
4597        _: &SortLinesCaseInsensitive,
4598        cx: &mut ViewContext<Self>,
4599    ) {
4600        self.manipulate_lines(cx, |lines| lines.sort_by_key(|line| line.to_lowercase()))
4601    }
4602
4603    pub fn reverse_lines(&mut self, _: &ReverseLines, cx: &mut ViewContext<Self>) {
4604        self.manipulate_lines(cx, |lines| lines.reverse())
4605    }
4606
4607    pub fn shuffle_lines(&mut self, _: &ShuffleLines, cx: &mut ViewContext<Self>) {
4608        self.manipulate_lines(cx, |lines| lines.shuffle(&mut thread_rng()))
4609    }
4610
4611    fn manipulate_lines<Fn>(&mut self, cx: &mut ViewContext<Self>, mut callback: Fn)
4612    where
4613        Fn: FnMut(&mut [&str]),
4614    {
4615        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4616        let buffer = self.buffer.read(cx).snapshot(cx);
4617
4618        let mut edits = Vec::new();
4619
4620        let selections = self.selections.all::<Point>(cx);
4621        let mut selections = selections.iter().peekable();
4622        let mut contiguous_row_selections = Vec::new();
4623        let mut new_selections = Vec::new();
4624
4625        while let Some(selection) = selections.next() {
4626            let (start_row, end_row) = consume_contiguous_rows(
4627                &mut contiguous_row_selections,
4628                selection,
4629                &display_map,
4630                &mut selections,
4631            );
4632
4633            let start_point = Point::new(start_row, 0);
4634            let end_point = Point::new(end_row - 1, buffer.line_len(end_row - 1));
4635            let text = buffer
4636                .text_for_range(start_point..end_point)
4637                .collect::<String>();
4638            let mut lines = text.split("\n").collect_vec();
4639
4640            let lines_len = lines.len();
4641            callback(&mut lines);
4642
4643            // This is a current limitation with selections.
4644            // If we wanted to support removing or adding lines, we'd need to fix the logic associated with selections.
4645            debug_assert!(
4646                lines.len() == lines_len,
4647                "callback should not change the number of lines"
4648            );
4649
4650            edits.push((start_point..end_point, lines.join("\n")));
4651            let start_anchor = buffer.anchor_after(start_point);
4652            let end_anchor = buffer.anchor_before(end_point);
4653
4654            // Make selection and push
4655            new_selections.push(Selection {
4656                id: selection.id,
4657                start: start_anchor.to_offset(&buffer),
4658                end: end_anchor.to_offset(&buffer),
4659                goal: SelectionGoal::None,
4660                reversed: selection.reversed,
4661            });
4662        }
4663
4664        self.transact(cx, |this, cx| {
4665            this.buffer.update(cx, |buffer, cx| {
4666                buffer.edit(edits, None, cx);
4667            });
4668
4669            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4670                s.select(new_selections);
4671            });
4672
4673            this.request_autoscroll(Autoscroll::fit(), cx);
4674        });
4675    }
4676
4677    pub fn convert_to_upper_case(&mut self, _: &ConvertToUpperCase, cx: &mut ViewContext<Self>) {
4678        self.manipulate_text(cx, |text| text.to_uppercase())
4679    }
4680
4681    pub fn convert_to_lower_case(&mut self, _: &ConvertToLowerCase, cx: &mut ViewContext<Self>) {
4682        self.manipulate_text(cx, |text| text.to_lowercase())
4683    }
4684
4685    pub fn convert_to_title_case(&mut self, _: &ConvertToTitleCase, cx: &mut ViewContext<Self>) {
4686        self.manipulate_text(cx, |text| {
4687            // Hack to get around the fact that to_case crate doesn't support '\n' as a word boundary
4688            // https://github.com/rutrum/convert-case/issues/16
4689            text.split("\n")
4690                .map(|line| line.to_case(Case::Title))
4691                .join("\n")
4692        })
4693    }
4694
4695    pub fn convert_to_snake_case(&mut self, _: &ConvertToSnakeCase, cx: &mut ViewContext<Self>) {
4696        self.manipulate_text(cx, |text| text.to_case(Case::Snake))
4697    }
4698
4699    pub fn convert_to_kebab_case(&mut self, _: &ConvertToKebabCase, cx: &mut ViewContext<Self>) {
4700        self.manipulate_text(cx, |text| text.to_case(Case::Kebab))
4701    }
4702
4703    pub fn convert_to_upper_camel_case(
4704        &mut self,
4705        _: &ConvertToUpperCamelCase,
4706        cx: &mut ViewContext<Self>,
4707    ) {
4708        self.manipulate_text(cx, |text| {
4709            // Hack to get around the fact that to_case crate doesn't support '\n' as a word boundary
4710            // https://github.com/rutrum/convert-case/issues/16
4711            text.split("\n")
4712                .map(|line| line.to_case(Case::UpperCamel))
4713                .join("\n")
4714        })
4715    }
4716
4717    pub fn convert_to_lower_camel_case(
4718        &mut self,
4719        _: &ConvertToLowerCamelCase,
4720        cx: &mut ViewContext<Self>,
4721    ) {
4722        self.manipulate_text(cx, |text| text.to_case(Case::Camel))
4723    }
4724
4725    fn manipulate_text<Fn>(&mut self, cx: &mut ViewContext<Self>, mut callback: Fn)
4726    where
4727        Fn: FnMut(&str) -> String,
4728    {
4729        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4730        let buffer = self.buffer.read(cx).snapshot(cx);
4731
4732        let mut new_selections = Vec::new();
4733        let mut edits = Vec::new();
4734        let mut selection_adjustment = 0i32;
4735
4736        for selection in self.selections.all::<usize>(cx) {
4737            let selection_is_empty = selection.is_empty();
4738
4739            let (start, end) = if selection_is_empty {
4740                let word_range = movement::surrounding_word(
4741                    &display_map,
4742                    selection.start.to_display_point(&display_map),
4743                );
4744                let start = word_range.start.to_offset(&display_map, Bias::Left);
4745                let end = word_range.end.to_offset(&display_map, Bias::Left);
4746                (start, end)
4747            } else {
4748                (selection.start, selection.end)
4749            };
4750
4751            let text = buffer.text_for_range(start..end).collect::<String>();
4752            let old_length = text.len() as i32;
4753            let text = callback(&text);
4754
4755            new_selections.push(Selection {
4756                start: (start as i32 - selection_adjustment) as usize,
4757                end: ((start + text.len()) as i32 - selection_adjustment) as usize,
4758                goal: SelectionGoal::None,
4759                ..selection
4760            });
4761
4762            selection_adjustment += old_length - text.len() as i32;
4763
4764            edits.push((start..end, text));
4765        }
4766
4767        self.transact(cx, |this, cx| {
4768            this.buffer.update(cx, |buffer, cx| {
4769                buffer.edit(edits, None, cx);
4770            });
4771
4772            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4773                s.select(new_selections);
4774            });
4775
4776            this.request_autoscroll(Autoscroll::fit(), cx);
4777        });
4778    }
4779
4780    pub fn duplicate_line(&mut self, _: &DuplicateLine, cx: &mut ViewContext<Self>) {
4781        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4782        let buffer = &display_map.buffer_snapshot;
4783        let selections = self.selections.all::<Point>(cx);
4784
4785        let mut edits = Vec::new();
4786        let mut selections_iter = selections.iter().peekable();
4787        while let Some(selection) = selections_iter.next() {
4788            // Avoid duplicating the same lines twice.
4789            let mut rows = selection.spanned_rows(false, &display_map);
4790
4791            while let Some(next_selection) = selections_iter.peek() {
4792                let next_rows = next_selection.spanned_rows(false, &display_map);
4793                if next_rows.start < rows.end {
4794                    rows.end = next_rows.end;
4795                    selections_iter.next().unwrap();
4796                } else {
4797                    break;
4798                }
4799            }
4800
4801            // Copy the text from the selected row region and splice it at the start of the region.
4802            let start = Point::new(rows.start, 0);
4803            let end = Point::new(rows.end - 1, buffer.line_len(rows.end - 1));
4804            let text = buffer
4805                .text_for_range(start..end)
4806                .chain(Some("\n"))
4807                .collect::<String>();
4808            edits.push((start..start, text));
4809        }
4810
4811        self.transact(cx, |this, cx| {
4812            this.buffer.update(cx, |buffer, cx| {
4813                buffer.edit(edits, None, cx);
4814            });
4815
4816            this.request_autoscroll(Autoscroll::fit(), cx);
4817        });
4818    }
4819
4820    pub fn move_line_up(&mut self, _: &MoveLineUp, cx: &mut ViewContext<Self>) {
4821        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4822        let buffer = self.buffer.read(cx).snapshot(cx);
4823
4824        let mut edits = Vec::new();
4825        let mut unfold_ranges = Vec::new();
4826        let mut refold_ranges = Vec::new();
4827
4828        let selections = self.selections.all::<Point>(cx);
4829        let mut selections = selections.iter().peekable();
4830        let mut contiguous_row_selections = Vec::new();
4831        let mut new_selections = Vec::new();
4832
4833        while let Some(selection) = selections.next() {
4834            // Find all the selections that span a contiguous row range
4835            let (start_row, end_row) = consume_contiguous_rows(
4836                &mut contiguous_row_selections,
4837                selection,
4838                &display_map,
4839                &mut selections,
4840            );
4841
4842            // Move the text spanned by the row range to be before the line preceding the row range
4843            if start_row > 0 {
4844                let range_to_move = Point::new(start_row - 1, buffer.line_len(start_row - 1))
4845                    ..Point::new(end_row - 1, buffer.line_len(end_row - 1));
4846                let insertion_point = display_map
4847                    .prev_line_boundary(Point::new(start_row - 1, 0))
4848                    .0;
4849
4850                // Don't move lines across excerpts
4851                if buffer
4852                    .excerpt_boundaries_in_range((
4853                        Bound::Excluded(insertion_point),
4854                        Bound::Included(range_to_move.end),
4855                    ))
4856                    .next()
4857                    .is_none()
4858                {
4859                    let text = buffer
4860                        .text_for_range(range_to_move.clone())
4861                        .flat_map(|s| s.chars())
4862                        .skip(1)
4863                        .chain(['\n'])
4864                        .collect::<String>();
4865
4866                    edits.push((
4867                        buffer.anchor_after(range_to_move.start)
4868                            ..buffer.anchor_before(range_to_move.end),
4869                        String::new(),
4870                    ));
4871                    let insertion_anchor = buffer.anchor_after(insertion_point);
4872                    edits.push((insertion_anchor..insertion_anchor, text));
4873
4874                    let row_delta = range_to_move.start.row - insertion_point.row + 1;
4875
4876                    // Move selections up
4877                    new_selections.extend(contiguous_row_selections.drain(..).map(
4878                        |mut selection| {
4879                            selection.start.row -= row_delta;
4880                            selection.end.row -= row_delta;
4881                            selection
4882                        },
4883                    ));
4884
4885                    // Move folds up
4886                    unfold_ranges.push(range_to_move.clone());
4887                    for fold in display_map.folds_in_range(
4888                        buffer.anchor_before(range_to_move.start)
4889                            ..buffer.anchor_after(range_to_move.end),
4890                    ) {
4891                        let mut start = fold.range.start.to_point(&buffer);
4892                        let mut end = fold.range.end.to_point(&buffer);
4893                        start.row -= row_delta;
4894                        end.row -= row_delta;
4895                        refold_ranges.push(start..end);
4896                    }
4897                }
4898            }
4899
4900            // If we didn't move line(s), preserve the existing selections
4901            new_selections.append(&mut contiguous_row_selections);
4902        }
4903
4904        self.transact(cx, |this, cx| {
4905            this.unfold_ranges(unfold_ranges, true, true, cx);
4906            this.buffer.update(cx, |buffer, cx| {
4907                for (range, text) in edits {
4908                    buffer.edit([(range, text)], None, cx);
4909                }
4910            });
4911            this.fold_ranges(refold_ranges, true, cx);
4912            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4913                s.select(new_selections);
4914            })
4915        });
4916    }
4917
4918    pub fn move_line_down(&mut self, _: &MoveLineDown, cx: &mut ViewContext<Self>) {
4919        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4920        let buffer = self.buffer.read(cx).snapshot(cx);
4921
4922        let mut edits = Vec::new();
4923        let mut unfold_ranges = Vec::new();
4924        let mut refold_ranges = Vec::new();
4925
4926        let selections = self.selections.all::<Point>(cx);
4927        let mut selections = selections.iter().peekable();
4928        let mut contiguous_row_selections = Vec::new();
4929        let mut new_selections = Vec::new();
4930
4931        while let Some(selection) = selections.next() {
4932            // Find all the selections that span a contiguous row range
4933            let (start_row, end_row) = consume_contiguous_rows(
4934                &mut contiguous_row_selections,
4935                selection,
4936                &display_map,
4937                &mut selections,
4938            );
4939
4940            // Move the text spanned by the row range to be after the last line of the row range
4941            if end_row <= buffer.max_point().row {
4942                let range_to_move = Point::new(start_row, 0)..Point::new(end_row, 0);
4943                let insertion_point = display_map.next_line_boundary(Point::new(end_row, 0)).0;
4944
4945                // Don't move lines across excerpt boundaries
4946                if buffer
4947                    .excerpt_boundaries_in_range((
4948                        Bound::Excluded(range_to_move.start),
4949                        Bound::Included(insertion_point),
4950                    ))
4951                    .next()
4952                    .is_none()
4953                {
4954                    let mut text = String::from("\n");
4955                    text.extend(buffer.text_for_range(range_to_move.clone()));
4956                    text.pop(); // Drop trailing newline
4957                    edits.push((
4958                        buffer.anchor_after(range_to_move.start)
4959                            ..buffer.anchor_before(range_to_move.end),
4960                        String::new(),
4961                    ));
4962                    let insertion_anchor = buffer.anchor_after(insertion_point);
4963                    edits.push((insertion_anchor..insertion_anchor, text));
4964
4965                    let row_delta = insertion_point.row - range_to_move.end.row + 1;
4966
4967                    // Move selections down
4968                    new_selections.extend(contiguous_row_selections.drain(..).map(
4969                        |mut selection| {
4970                            selection.start.row += row_delta;
4971                            selection.end.row += row_delta;
4972                            selection
4973                        },
4974                    ));
4975
4976                    // Move folds down
4977                    unfold_ranges.push(range_to_move.clone());
4978                    for fold in display_map.folds_in_range(
4979                        buffer.anchor_before(range_to_move.start)
4980                            ..buffer.anchor_after(range_to_move.end),
4981                    ) {
4982                        let mut start = fold.range.start.to_point(&buffer);
4983                        let mut end = fold.range.end.to_point(&buffer);
4984                        start.row += row_delta;
4985                        end.row += row_delta;
4986                        refold_ranges.push(start..end);
4987                    }
4988                }
4989            }
4990
4991            // If we didn't move line(s), preserve the existing selections
4992            new_selections.append(&mut contiguous_row_selections);
4993        }
4994
4995        self.transact(cx, |this, cx| {
4996            this.unfold_ranges(unfold_ranges, true, true, cx);
4997            this.buffer.update(cx, |buffer, cx| {
4998                for (range, text) in edits {
4999                    buffer.edit([(range, text)], None, cx);
5000                }
5001            });
5002            this.fold_ranges(refold_ranges, true, cx);
5003            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(new_selections));
5004        });
5005    }
5006
5007    pub fn transpose(&mut self, _: &Transpose, cx: &mut ViewContext<Self>) {
5008        let text_layout_details = &self.text_layout_details(cx);
5009        self.transact(cx, |this, cx| {
5010            let edits = this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5011                let mut edits: Vec<(Range<usize>, String)> = Default::default();
5012                let line_mode = s.line_mode;
5013                s.move_with(|display_map, selection| {
5014                    if !selection.is_empty() || line_mode {
5015                        return;
5016                    }
5017
5018                    let mut head = selection.head();
5019                    let mut transpose_offset = head.to_offset(display_map, Bias::Right);
5020                    if head.column() == display_map.line_len(head.row()) {
5021                        transpose_offset = display_map
5022                            .buffer_snapshot
5023                            .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
5024                    }
5025
5026                    if transpose_offset == 0 {
5027                        return;
5028                    }
5029
5030                    *head.column_mut() += 1;
5031                    head = display_map.clip_point(head, Bias::Right);
5032                    let goal = SelectionGoal::HorizontalPosition(
5033                        display_map
5034                            .x_for_display_point(head, &text_layout_details)
5035                            .into(),
5036                    );
5037                    selection.collapse_to(head, goal);
5038
5039                    let transpose_start = display_map
5040                        .buffer_snapshot
5041                        .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
5042                    if edits.last().map_or(true, |e| e.0.end <= transpose_start) {
5043                        let transpose_end = display_map
5044                            .buffer_snapshot
5045                            .clip_offset(transpose_offset + 1, Bias::Right);
5046                        if let Some(ch) =
5047                            display_map.buffer_snapshot.chars_at(transpose_start).next()
5048                        {
5049                            edits.push((transpose_start..transpose_offset, String::new()));
5050                            edits.push((transpose_end..transpose_end, ch.to_string()));
5051                        }
5052                    }
5053                });
5054                edits
5055            });
5056            this.buffer
5057                .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
5058            let selections = this.selections.all::<usize>(cx);
5059            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5060                s.select(selections);
5061            });
5062        });
5063    }
5064
5065    pub fn cut(&mut self, _: &Cut, cx: &mut ViewContext<Self>) {
5066        let mut text = String::new();
5067        let buffer = self.buffer.read(cx).snapshot(cx);
5068        let mut selections = self.selections.all::<Point>(cx);
5069        let mut clipboard_selections = Vec::with_capacity(selections.len());
5070        {
5071            let max_point = buffer.max_point();
5072            let mut is_first = true;
5073            for selection in &mut selections {
5074                let is_entire_line = selection.is_empty() || self.selections.line_mode;
5075                if is_entire_line {
5076                    selection.start = Point::new(selection.start.row, 0);
5077                    selection.end = cmp::min(max_point, Point::new(selection.end.row + 1, 0));
5078                    selection.goal = SelectionGoal::None;
5079                }
5080                if is_first {
5081                    is_first = false;
5082                } else {
5083                    text += "\n";
5084                }
5085                let mut len = 0;
5086                for chunk in buffer.text_for_range(selection.start..selection.end) {
5087                    text.push_str(chunk);
5088                    len += chunk.len();
5089                }
5090                clipboard_selections.push(ClipboardSelection {
5091                    len,
5092                    is_entire_line,
5093                    first_line_indent: buffer.indent_size_for_line(selection.start.row).len,
5094                });
5095            }
5096        }
5097
5098        self.transact(cx, |this, cx| {
5099            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5100                s.select(selections);
5101            });
5102            this.insert("", cx);
5103            cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
5104        });
5105    }
5106
5107    pub fn copy(&mut self, _: &Copy, cx: &mut ViewContext<Self>) {
5108        let selections = self.selections.all::<Point>(cx);
5109        let buffer = self.buffer.read(cx).read(cx);
5110        let mut text = String::new();
5111
5112        let mut clipboard_selections = Vec::with_capacity(selections.len());
5113        {
5114            let max_point = buffer.max_point();
5115            let mut is_first = true;
5116            for selection in selections.iter() {
5117                let mut start = selection.start;
5118                let mut end = selection.end;
5119                let is_entire_line = selection.is_empty() || self.selections.line_mode;
5120                if is_entire_line {
5121                    start = Point::new(start.row, 0);
5122                    end = cmp::min(max_point, Point::new(end.row + 1, 0));
5123                }
5124                if is_first {
5125                    is_first = false;
5126                } else {
5127                    text += "\n";
5128                }
5129                let mut len = 0;
5130                for chunk in buffer.text_for_range(start..end) {
5131                    text.push_str(chunk);
5132                    len += chunk.len();
5133                }
5134                clipboard_selections.push(ClipboardSelection {
5135                    len,
5136                    is_entire_line,
5137                    first_line_indent: buffer.indent_size_for_line(start.row).len,
5138                });
5139            }
5140        }
5141
5142        cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
5143    }
5144
5145    pub fn paste(&mut self, _: &Paste, cx: &mut ViewContext<Self>) {
5146        if self.read_only(cx) {
5147            return;
5148        }
5149
5150        self.transact(cx, |this, cx| {
5151            if let Some(item) = cx.read_from_clipboard() {
5152                let clipboard_text = Cow::Borrowed(item.text());
5153                if let Some(mut clipboard_selections) = item.metadata::<Vec<ClipboardSelection>>() {
5154                    let old_selections = this.selections.all::<usize>(cx);
5155                    let all_selections_were_entire_line =
5156                        clipboard_selections.iter().all(|s| s.is_entire_line);
5157                    let first_selection_indent_column =
5158                        clipboard_selections.first().map(|s| s.first_line_indent);
5159                    if clipboard_selections.len() != old_selections.len() {
5160                        clipboard_selections.drain(..);
5161                    }
5162
5163                    this.buffer.update(cx, |buffer, cx| {
5164                        let snapshot = buffer.read(cx);
5165                        let mut start_offset = 0;
5166                        let mut edits = Vec::new();
5167                        let mut original_indent_columns = Vec::new();
5168                        let line_mode = this.selections.line_mode;
5169                        for (ix, selection) in old_selections.iter().enumerate() {
5170                            let to_insert;
5171                            let entire_line;
5172                            let original_indent_column;
5173                            if let Some(clipboard_selection) = clipboard_selections.get(ix) {
5174                                let end_offset = start_offset + clipboard_selection.len;
5175                                to_insert = &clipboard_text[start_offset..end_offset];
5176                                entire_line = clipboard_selection.is_entire_line;
5177                                start_offset = end_offset + 1;
5178                                original_indent_column =
5179                                    Some(clipboard_selection.first_line_indent);
5180                            } else {
5181                                to_insert = clipboard_text.as_str();
5182                                entire_line = all_selections_were_entire_line;
5183                                original_indent_column = first_selection_indent_column
5184                            }
5185
5186                            // If the corresponding selection was empty when this slice of the
5187                            // clipboard text was written, then the entire line containing the
5188                            // selection was copied. If this selection is also currently empty,
5189                            // then paste the line before the current line of the buffer.
5190                            let range = if selection.is_empty() && !line_mode && entire_line {
5191                                let column = selection.start.to_point(&snapshot).column as usize;
5192                                let line_start = selection.start - column;
5193                                line_start..line_start
5194                            } else {
5195                                selection.range()
5196                            };
5197
5198                            edits.push((range, to_insert));
5199                            original_indent_columns.extend(original_indent_column);
5200                        }
5201                        drop(snapshot);
5202
5203                        buffer.edit(
5204                            edits,
5205                            Some(AutoindentMode::Block {
5206                                original_indent_columns,
5207                            }),
5208                            cx,
5209                        );
5210                    });
5211
5212                    let selections = this.selections.all::<usize>(cx);
5213                    this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
5214                } else {
5215                    this.insert(&clipboard_text, cx);
5216                }
5217            }
5218        });
5219    }
5220
5221    pub fn undo(&mut self, _: &Undo, cx: &mut ViewContext<Self>) {
5222        if self.read_only(cx) {
5223            return;
5224        }
5225
5226        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.undo(cx)) {
5227            if let Some((selections, _)) = self.selection_history.transaction(tx_id).cloned() {
5228                self.change_selections(None, cx, |s| {
5229                    s.select_anchors(selections.to_vec());
5230                });
5231            }
5232            self.request_autoscroll(Autoscroll::fit(), cx);
5233            self.unmark_text(cx);
5234            self.refresh_copilot_suggestions(true, cx);
5235            cx.emit(EditorEvent::Edited);
5236        }
5237    }
5238
5239    pub fn redo(&mut self, _: &Redo, cx: &mut ViewContext<Self>) {
5240        if self.read_only(cx) {
5241            return;
5242        }
5243
5244        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.redo(cx)) {
5245            if let Some((_, Some(selections))) = self.selection_history.transaction(tx_id).cloned()
5246            {
5247                self.change_selections(None, cx, |s| {
5248                    s.select_anchors(selections.to_vec());
5249                });
5250            }
5251            self.request_autoscroll(Autoscroll::fit(), cx);
5252            self.unmark_text(cx);
5253            self.refresh_copilot_suggestions(true, cx);
5254            cx.emit(EditorEvent::Edited);
5255        }
5256    }
5257
5258    pub fn finalize_last_transaction(&mut self, cx: &mut ViewContext<Self>) {
5259        self.buffer
5260            .update(cx, |buffer, cx| buffer.finalize_last_transaction(cx));
5261    }
5262
5263    pub fn move_left(&mut self, _: &MoveLeft, cx: &mut ViewContext<Self>) {
5264        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5265            let line_mode = s.line_mode;
5266            s.move_with(|map, selection| {
5267                let cursor = if selection.is_empty() && !line_mode {
5268                    movement::left(map, selection.start)
5269                } else {
5270                    selection.start
5271                };
5272                selection.collapse_to(cursor, SelectionGoal::None);
5273            });
5274        })
5275    }
5276
5277    pub fn select_left(&mut self, _: &SelectLeft, cx: &mut ViewContext<Self>) {
5278        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5279            s.move_heads_with(|map, head, _| (movement::left(map, head), SelectionGoal::None));
5280        })
5281    }
5282
5283    pub fn move_right(&mut self, _: &MoveRight, cx: &mut ViewContext<Self>) {
5284        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5285            let line_mode = s.line_mode;
5286            s.move_with(|map, selection| {
5287                let cursor = if selection.is_empty() && !line_mode {
5288                    movement::right(map, selection.end)
5289                } else {
5290                    selection.end
5291                };
5292                selection.collapse_to(cursor, SelectionGoal::None)
5293            });
5294        })
5295    }
5296
5297    pub fn select_right(&mut self, _: &SelectRight, cx: &mut ViewContext<Self>) {
5298        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5299            s.move_heads_with(|map, head, _| (movement::right(map, head), SelectionGoal::None));
5300        })
5301    }
5302
5303    pub fn move_up(&mut self, _: &MoveUp, cx: &mut ViewContext<Self>) {
5304        if self.take_rename(true, cx).is_some() {
5305            return;
5306        }
5307
5308        if matches!(self.mode, EditorMode::SingleLine) {
5309            cx.propagate();
5310            return;
5311        }
5312
5313        let text_layout_details = &self.text_layout_details(cx);
5314
5315        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5316            let line_mode = s.line_mode;
5317            s.move_with(|map, selection| {
5318                if !selection.is_empty() && !line_mode {
5319                    selection.goal = SelectionGoal::None;
5320                }
5321                let (cursor, goal) = movement::up(
5322                    map,
5323                    selection.start,
5324                    selection.goal,
5325                    false,
5326                    &text_layout_details,
5327                );
5328                selection.collapse_to(cursor, goal);
5329            });
5330        })
5331    }
5332
5333    pub fn move_page_up(&mut self, action: &MovePageUp, cx: &mut ViewContext<Self>) {
5334        if self.take_rename(true, cx).is_some() {
5335            return;
5336        }
5337
5338        if matches!(self.mode, EditorMode::SingleLine) {
5339            cx.propagate();
5340            return;
5341        }
5342
5343        let row_count = if let Some(row_count) = self.visible_line_count() {
5344            row_count as u32 - 1
5345        } else {
5346            return;
5347        };
5348
5349        let autoscroll = if action.center_cursor {
5350            Autoscroll::center()
5351        } else {
5352            Autoscroll::fit()
5353        };
5354
5355        let text_layout_details = &self.text_layout_details(cx);
5356
5357        self.change_selections(Some(autoscroll), cx, |s| {
5358            let line_mode = s.line_mode;
5359            s.move_with(|map, selection| {
5360                if !selection.is_empty() && !line_mode {
5361                    selection.goal = SelectionGoal::None;
5362                }
5363                let (cursor, goal) = movement::up_by_rows(
5364                    map,
5365                    selection.end,
5366                    row_count,
5367                    selection.goal,
5368                    false,
5369                    &text_layout_details,
5370                );
5371                selection.collapse_to(cursor, goal);
5372            });
5373        });
5374    }
5375
5376    pub fn select_up(&mut self, _: &SelectUp, cx: &mut ViewContext<Self>) {
5377        let text_layout_details = &self.text_layout_details(cx);
5378        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5379            s.move_heads_with(|map, head, goal| {
5380                movement::up(map, head, goal, false, &text_layout_details)
5381            })
5382        })
5383    }
5384
5385    pub fn move_down(&mut self, _: &MoveDown, cx: &mut ViewContext<Self>) {
5386        self.take_rename(true, cx);
5387
5388        if self.mode == EditorMode::SingleLine {
5389            cx.propagate();
5390            return;
5391        }
5392
5393        let text_layout_details = &self.text_layout_details(cx);
5394        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5395            let line_mode = s.line_mode;
5396            s.move_with(|map, selection| {
5397                if !selection.is_empty() && !line_mode {
5398                    selection.goal = SelectionGoal::None;
5399                }
5400                let (cursor, goal) = movement::down(
5401                    map,
5402                    selection.end,
5403                    selection.goal,
5404                    false,
5405                    &text_layout_details,
5406                );
5407                selection.collapse_to(cursor, goal);
5408            });
5409        });
5410    }
5411
5412    pub fn move_page_down(&mut self, action: &MovePageDown, cx: &mut ViewContext<Self>) {
5413        if self.take_rename(true, cx).is_some() {
5414            return;
5415        }
5416
5417        if self
5418            .context_menu
5419            .write()
5420            .as_mut()
5421            .map(|menu| menu.select_last(self.project.as_ref(), cx))
5422            .unwrap_or(false)
5423        {
5424            return;
5425        }
5426
5427        if matches!(self.mode, EditorMode::SingleLine) {
5428            cx.propagate();
5429            return;
5430        }
5431
5432        let row_count = if let Some(row_count) = self.visible_line_count() {
5433            row_count as u32 - 1
5434        } else {
5435            return;
5436        };
5437
5438        let autoscroll = if action.center_cursor {
5439            Autoscroll::center()
5440        } else {
5441            Autoscroll::fit()
5442        };
5443
5444        let text_layout_details = &self.text_layout_details(cx);
5445        self.change_selections(Some(autoscroll), cx, |s| {
5446            let line_mode = s.line_mode;
5447            s.move_with(|map, selection| {
5448                if !selection.is_empty() && !line_mode {
5449                    selection.goal = SelectionGoal::None;
5450                }
5451                let (cursor, goal) = movement::down_by_rows(
5452                    map,
5453                    selection.end,
5454                    row_count,
5455                    selection.goal,
5456                    false,
5457                    &text_layout_details,
5458                );
5459                selection.collapse_to(cursor, goal);
5460            });
5461        });
5462    }
5463
5464    pub fn select_down(&mut self, _: &SelectDown, cx: &mut ViewContext<Self>) {
5465        let text_layout_details = &self.text_layout_details(cx);
5466        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5467            s.move_heads_with(|map, head, goal| {
5468                movement::down(map, head, goal, false, &text_layout_details)
5469            })
5470        });
5471    }
5472
5473    pub fn context_menu_first(&mut self, _: &ContextMenuFirst, cx: &mut ViewContext<Self>) {
5474        if let Some(context_menu) = self.context_menu.write().as_mut() {
5475            context_menu.select_first(self.project.as_ref(), cx);
5476        }
5477    }
5478
5479    pub fn context_menu_prev(&mut self, _: &ContextMenuPrev, cx: &mut ViewContext<Self>) {
5480        if let Some(context_menu) = self.context_menu.write().as_mut() {
5481            context_menu.select_prev(self.project.as_ref(), cx);
5482        }
5483    }
5484
5485    pub fn context_menu_next(&mut self, _: &ContextMenuNext, cx: &mut ViewContext<Self>) {
5486        if let Some(context_menu) = self.context_menu.write().as_mut() {
5487            context_menu.select_next(self.project.as_ref(), cx);
5488        }
5489    }
5490
5491    pub fn context_menu_last(&mut self, _: &ContextMenuLast, cx: &mut ViewContext<Self>) {
5492        if let Some(context_menu) = self.context_menu.write().as_mut() {
5493            context_menu.select_last(self.project.as_ref(), cx);
5494        }
5495    }
5496
5497    pub fn move_to_previous_word_start(
5498        &mut self,
5499        _: &MoveToPreviousWordStart,
5500        cx: &mut ViewContext<Self>,
5501    ) {
5502        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5503            s.move_cursors_with(|map, head, _| {
5504                (
5505                    movement::previous_word_start(map, head),
5506                    SelectionGoal::None,
5507                )
5508            });
5509        })
5510    }
5511
5512    pub fn move_to_previous_subword_start(
5513        &mut self,
5514        _: &MoveToPreviousSubwordStart,
5515        cx: &mut ViewContext<Self>,
5516    ) {
5517        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5518            s.move_cursors_with(|map, head, _| {
5519                (
5520                    movement::previous_subword_start(map, head),
5521                    SelectionGoal::None,
5522                )
5523            });
5524        })
5525    }
5526
5527    pub fn select_to_previous_word_start(
5528        &mut self,
5529        _: &SelectToPreviousWordStart,
5530        cx: &mut ViewContext<Self>,
5531    ) {
5532        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5533            s.move_heads_with(|map, head, _| {
5534                (
5535                    movement::previous_word_start(map, head),
5536                    SelectionGoal::None,
5537                )
5538            });
5539        })
5540    }
5541
5542    pub fn select_to_previous_subword_start(
5543        &mut self,
5544        _: &SelectToPreviousSubwordStart,
5545        cx: &mut ViewContext<Self>,
5546    ) {
5547        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5548            s.move_heads_with(|map, head, _| {
5549                (
5550                    movement::previous_subword_start(map, head),
5551                    SelectionGoal::None,
5552                )
5553            });
5554        })
5555    }
5556
5557    pub fn delete_to_previous_word_start(
5558        &mut self,
5559        _: &DeleteToPreviousWordStart,
5560        cx: &mut ViewContext<Self>,
5561    ) {
5562        self.transact(cx, |this, cx| {
5563            this.select_autoclose_pair(cx);
5564            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5565                let line_mode = s.line_mode;
5566                s.move_with(|map, selection| {
5567                    if selection.is_empty() && !line_mode {
5568                        let cursor = movement::previous_word_start(map, selection.head());
5569                        selection.set_head(cursor, SelectionGoal::None);
5570                    }
5571                });
5572            });
5573            this.insert("", cx);
5574        });
5575    }
5576
5577    pub fn delete_to_previous_subword_start(
5578        &mut self,
5579        _: &DeleteToPreviousSubwordStart,
5580        cx: &mut ViewContext<Self>,
5581    ) {
5582        self.transact(cx, |this, cx| {
5583            this.select_autoclose_pair(cx);
5584            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5585                let line_mode = s.line_mode;
5586                s.move_with(|map, selection| {
5587                    if selection.is_empty() && !line_mode {
5588                        let cursor = movement::previous_subword_start(map, selection.head());
5589                        selection.set_head(cursor, SelectionGoal::None);
5590                    }
5591                });
5592            });
5593            this.insert("", cx);
5594        });
5595    }
5596
5597    pub fn move_to_next_word_end(&mut self, _: &MoveToNextWordEnd, cx: &mut ViewContext<Self>) {
5598        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5599            s.move_cursors_with(|map, head, _| {
5600                (movement::next_word_end(map, head), SelectionGoal::None)
5601            });
5602        })
5603    }
5604
5605    pub fn move_to_next_subword_end(
5606        &mut self,
5607        _: &MoveToNextSubwordEnd,
5608        cx: &mut ViewContext<Self>,
5609    ) {
5610        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5611            s.move_cursors_with(|map, head, _| {
5612                (movement::next_subword_end(map, head), SelectionGoal::None)
5613            });
5614        })
5615    }
5616
5617    pub fn select_to_next_word_end(&mut self, _: &SelectToNextWordEnd, cx: &mut ViewContext<Self>) {
5618        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5619            s.move_heads_with(|map, head, _| {
5620                (movement::next_word_end(map, head), SelectionGoal::None)
5621            });
5622        })
5623    }
5624
5625    pub fn select_to_next_subword_end(
5626        &mut self,
5627        _: &SelectToNextSubwordEnd,
5628        cx: &mut ViewContext<Self>,
5629    ) {
5630        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5631            s.move_heads_with(|map, head, _| {
5632                (movement::next_subword_end(map, head), SelectionGoal::None)
5633            });
5634        })
5635    }
5636
5637    pub fn delete_to_next_word_end(&mut self, _: &DeleteToNextWordEnd, cx: &mut ViewContext<Self>) {
5638        self.transact(cx, |this, cx| {
5639            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5640                let line_mode = s.line_mode;
5641                s.move_with(|map, selection| {
5642                    if selection.is_empty() && !line_mode {
5643                        let cursor = movement::next_word_end(map, selection.head());
5644                        selection.set_head(cursor, SelectionGoal::None);
5645                    }
5646                });
5647            });
5648            this.insert("", cx);
5649        });
5650    }
5651
5652    pub fn delete_to_next_subword_end(
5653        &mut self,
5654        _: &DeleteToNextSubwordEnd,
5655        cx: &mut ViewContext<Self>,
5656    ) {
5657        self.transact(cx, |this, cx| {
5658            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5659                s.move_with(|map, selection| {
5660                    if selection.is_empty() {
5661                        let cursor = movement::next_subword_end(map, selection.head());
5662                        selection.set_head(cursor, SelectionGoal::None);
5663                    }
5664                });
5665            });
5666            this.insert("", cx);
5667        });
5668    }
5669
5670    pub fn move_to_beginning_of_line(
5671        &mut self,
5672        _: &MoveToBeginningOfLine,
5673        cx: &mut ViewContext<Self>,
5674    ) {
5675        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5676            s.move_cursors_with(|map, head, _| {
5677                (
5678                    movement::indented_line_beginning(map, head, true),
5679                    SelectionGoal::None,
5680                )
5681            });
5682        })
5683    }
5684
5685    pub fn select_to_beginning_of_line(
5686        &mut self,
5687        action: &SelectToBeginningOfLine,
5688        cx: &mut ViewContext<Self>,
5689    ) {
5690        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5691            s.move_heads_with(|map, head, _| {
5692                (
5693                    movement::indented_line_beginning(map, head, action.stop_at_soft_wraps),
5694                    SelectionGoal::None,
5695                )
5696            });
5697        });
5698    }
5699
5700    pub fn delete_to_beginning_of_line(
5701        &mut self,
5702        _: &DeleteToBeginningOfLine,
5703        cx: &mut ViewContext<Self>,
5704    ) {
5705        self.transact(cx, |this, cx| {
5706            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5707                s.move_with(|_, selection| {
5708                    selection.reversed = true;
5709                });
5710            });
5711
5712            this.select_to_beginning_of_line(
5713                &SelectToBeginningOfLine {
5714                    stop_at_soft_wraps: false,
5715                },
5716                cx,
5717            );
5718            this.backspace(&Backspace, cx);
5719        });
5720    }
5721
5722    pub fn move_to_end_of_line(&mut self, _: &MoveToEndOfLine, cx: &mut ViewContext<Self>) {
5723        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5724            s.move_cursors_with(|map, head, _| {
5725                (movement::line_end(map, head, true), SelectionGoal::None)
5726            });
5727        })
5728    }
5729
5730    pub fn select_to_end_of_line(
5731        &mut self,
5732        action: &SelectToEndOfLine,
5733        cx: &mut ViewContext<Self>,
5734    ) {
5735        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5736            s.move_heads_with(|map, head, _| {
5737                (
5738                    movement::line_end(map, head, action.stop_at_soft_wraps),
5739                    SelectionGoal::None,
5740                )
5741            });
5742        })
5743    }
5744
5745    pub fn delete_to_end_of_line(&mut self, _: &DeleteToEndOfLine, cx: &mut ViewContext<Self>) {
5746        self.transact(cx, |this, cx| {
5747            this.select_to_end_of_line(
5748                &SelectToEndOfLine {
5749                    stop_at_soft_wraps: false,
5750                },
5751                cx,
5752            );
5753            this.delete(&Delete, cx);
5754        });
5755    }
5756
5757    pub fn cut_to_end_of_line(&mut self, _: &CutToEndOfLine, cx: &mut ViewContext<Self>) {
5758        self.transact(cx, |this, cx| {
5759            this.select_to_end_of_line(
5760                &SelectToEndOfLine {
5761                    stop_at_soft_wraps: false,
5762                },
5763                cx,
5764            );
5765            this.cut(&Cut, cx);
5766        });
5767    }
5768
5769    pub fn move_to_start_of_paragraph(
5770        &mut self,
5771        _: &MoveToStartOfParagraph,
5772        cx: &mut ViewContext<Self>,
5773    ) {
5774        if matches!(self.mode, EditorMode::SingleLine) {
5775            cx.propagate();
5776            return;
5777        }
5778
5779        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5780            s.move_with(|map, selection| {
5781                selection.collapse_to(
5782                    movement::start_of_paragraph(map, selection.head(), 1),
5783                    SelectionGoal::None,
5784                )
5785            });
5786        })
5787    }
5788
5789    pub fn move_to_end_of_paragraph(
5790        &mut self,
5791        _: &MoveToEndOfParagraph,
5792        cx: &mut ViewContext<Self>,
5793    ) {
5794        if matches!(self.mode, EditorMode::SingleLine) {
5795            cx.propagate();
5796            return;
5797        }
5798
5799        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5800            s.move_with(|map, selection| {
5801                selection.collapse_to(
5802                    movement::end_of_paragraph(map, selection.head(), 1),
5803                    SelectionGoal::None,
5804                )
5805            });
5806        })
5807    }
5808
5809    pub fn select_to_start_of_paragraph(
5810        &mut self,
5811        _: &SelectToStartOfParagraph,
5812        cx: &mut ViewContext<Self>,
5813    ) {
5814        if matches!(self.mode, EditorMode::SingleLine) {
5815            cx.propagate();
5816            return;
5817        }
5818
5819        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5820            s.move_heads_with(|map, head, _| {
5821                (
5822                    movement::start_of_paragraph(map, head, 1),
5823                    SelectionGoal::None,
5824                )
5825            });
5826        })
5827    }
5828
5829    pub fn select_to_end_of_paragraph(
5830        &mut self,
5831        _: &SelectToEndOfParagraph,
5832        cx: &mut ViewContext<Self>,
5833    ) {
5834        if matches!(self.mode, EditorMode::SingleLine) {
5835            cx.propagate();
5836            return;
5837        }
5838
5839        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5840            s.move_heads_with(|map, head, _| {
5841                (
5842                    movement::end_of_paragraph(map, head, 1),
5843                    SelectionGoal::None,
5844                )
5845            });
5846        })
5847    }
5848
5849    pub fn move_to_beginning(&mut self, _: &MoveToBeginning, cx: &mut ViewContext<Self>) {
5850        if matches!(self.mode, EditorMode::SingleLine) {
5851            cx.propagate();
5852            return;
5853        }
5854
5855        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5856            s.select_ranges(vec![0..0]);
5857        });
5858    }
5859
5860    pub fn select_to_beginning(&mut self, _: &SelectToBeginning, cx: &mut ViewContext<Self>) {
5861        let mut selection = self.selections.last::<Point>(cx);
5862        selection.set_head(Point::zero(), SelectionGoal::None);
5863
5864        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5865            s.select(vec![selection]);
5866        });
5867    }
5868
5869    pub fn move_to_end(&mut self, _: &MoveToEnd, cx: &mut ViewContext<Self>) {
5870        if matches!(self.mode, EditorMode::SingleLine) {
5871            cx.propagate();
5872            return;
5873        }
5874
5875        let cursor = self.buffer.read(cx).read(cx).len();
5876        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5877            s.select_ranges(vec![cursor..cursor])
5878        });
5879    }
5880
5881    pub fn set_nav_history(&mut self, nav_history: Option<ItemNavHistory>) {
5882        self.nav_history = nav_history;
5883    }
5884
5885    pub fn nav_history(&self) -> Option<&ItemNavHistory> {
5886        self.nav_history.as_ref()
5887    }
5888
5889    fn push_to_nav_history(
5890        &mut self,
5891        cursor_anchor: Anchor,
5892        new_position: Option<Point>,
5893        cx: &mut ViewContext<Self>,
5894    ) {
5895        if let Some(nav_history) = self.nav_history.as_mut() {
5896            let buffer = self.buffer.read(cx).read(cx);
5897            let cursor_position = cursor_anchor.to_point(&buffer);
5898            let scroll_state = self.scroll_manager.anchor();
5899            let scroll_top_row = scroll_state.top_row(&buffer);
5900            drop(buffer);
5901
5902            if let Some(new_position) = new_position {
5903                let row_delta = (new_position.row as i64 - cursor_position.row as i64).abs();
5904                if row_delta < MIN_NAVIGATION_HISTORY_ROW_DELTA {
5905                    return;
5906                }
5907            }
5908
5909            nav_history.push(
5910                Some(NavigationData {
5911                    cursor_anchor,
5912                    cursor_position,
5913                    scroll_anchor: scroll_state,
5914                    scroll_top_row,
5915                }),
5916                cx,
5917            );
5918        }
5919    }
5920
5921    pub fn select_to_end(&mut self, _: &SelectToEnd, cx: &mut ViewContext<Self>) {
5922        let buffer = self.buffer.read(cx).snapshot(cx);
5923        let mut selection = self.selections.first::<usize>(cx);
5924        selection.set_head(buffer.len(), SelectionGoal::None);
5925        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5926            s.select(vec![selection]);
5927        });
5928    }
5929
5930    pub fn select_all(&mut self, _: &SelectAll, cx: &mut ViewContext<Self>) {
5931        let end = self.buffer.read(cx).read(cx).len();
5932        self.change_selections(None, cx, |s| {
5933            s.select_ranges(vec![0..end]);
5934        });
5935    }
5936
5937    pub fn select_line(&mut self, _: &SelectLine, cx: &mut ViewContext<Self>) {
5938        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5939        let mut selections = self.selections.all::<Point>(cx);
5940        let max_point = display_map.buffer_snapshot.max_point();
5941        for selection in &mut selections {
5942            let rows = selection.spanned_rows(true, &display_map);
5943            selection.start = Point::new(rows.start, 0);
5944            selection.end = cmp::min(max_point, Point::new(rows.end, 0));
5945            selection.reversed = false;
5946        }
5947        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5948            s.select(selections);
5949        });
5950    }
5951
5952    pub fn split_selection_into_lines(
5953        &mut self,
5954        _: &SplitSelectionIntoLines,
5955        cx: &mut ViewContext<Self>,
5956    ) {
5957        let mut to_unfold = Vec::new();
5958        let mut new_selection_ranges = Vec::new();
5959        {
5960            let selections = self.selections.all::<Point>(cx);
5961            let buffer = self.buffer.read(cx).read(cx);
5962            for selection in selections {
5963                for row in selection.start.row..selection.end.row {
5964                    let cursor = Point::new(row, buffer.line_len(row));
5965                    new_selection_ranges.push(cursor..cursor);
5966                }
5967                new_selection_ranges.push(selection.end..selection.end);
5968                to_unfold.push(selection.start..selection.end);
5969            }
5970        }
5971        self.unfold_ranges(to_unfold, true, true, cx);
5972        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5973            s.select_ranges(new_selection_ranges);
5974        });
5975    }
5976
5977    pub fn add_selection_above(&mut self, _: &AddSelectionAbove, cx: &mut ViewContext<Self>) {
5978        self.add_selection(true, cx);
5979    }
5980
5981    pub fn add_selection_below(&mut self, _: &AddSelectionBelow, cx: &mut ViewContext<Self>) {
5982        self.add_selection(false, cx);
5983    }
5984
5985    fn add_selection(&mut self, above: bool, cx: &mut ViewContext<Self>) {
5986        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5987        let mut selections = self.selections.all::<Point>(cx);
5988        let text_layout_details = self.text_layout_details(cx);
5989        let mut state = self.add_selections_state.take().unwrap_or_else(|| {
5990            let oldest_selection = selections.iter().min_by_key(|s| s.id).unwrap().clone();
5991            let range = oldest_selection.display_range(&display_map).sorted();
5992
5993            let start_x = display_map.x_for_display_point(range.start, &text_layout_details);
5994            let end_x = display_map.x_for_display_point(range.end, &text_layout_details);
5995            let positions = start_x.min(end_x)..start_x.max(end_x);
5996
5997            selections.clear();
5998            let mut stack = Vec::new();
5999            for row in range.start.row()..=range.end.row() {
6000                if let Some(selection) = self.selections.build_columnar_selection(
6001                    &display_map,
6002                    row,
6003                    &positions,
6004                    oldest_selection.reversed,
6005                    &text_layout_details,
6006                ) {
6007                    stack.push(selection.id);
6008                    selections.push(selection);
6009                }
6010            }
6011
6012            if above {
6013                stack.reverse();
6014            }
6015
6016            AddSelectionsState { above, stack }
6017        });
6018
6019        let last_added_selection = *state.stack.last().unwrap();
6020        let mut new_selections = Vec::new();
6021        if above == state.above {
6022            let end_row = if above {
6023                0
6024            } else {
6025                display_map.max_point().row()
6026            };
6027
6028            'outer: for selection in selections {
6029                if selection.id == last_added_selection {
6030                    let range = selection.display_range(&display_map).sorted();
6031                    debug_assert_eq!(range.start.row(), range.end.row());
6032                    let mut row = range.start.row();
6033                    let positions =
6034                        if let SelectionGoal::HorizontalRange { start, end } = selection.goal {
6035                            px(start)..px(end)
6036                        } else {
6037                            let start_x =
6038                                display_map.x_for_display_point(range.start, &text_layout_details);
6039                            let end_x =
6040                                display_map.x_for_display_point(range.end, &text_layout_details);
6041                            start_x.min(end_x)..start_x.max(end_x)
6042                        };
6043
6044                    while row != end_row {
6045                        if above {
6046                            row -= 1;
6047                        } else {
6048                            row += 1;
6049                        }
6050
6051                        if let Some(new_selection) = self.selections.build_columnar_selection(
6052                            &display_map,
6053                            row,
6054                            &positions,
6055                            selection.reversed,
6056                            &text_layout_details,
6057                        ) {
6058                            state.stack.push(new_selection.id);
6059                            if above {
6060                                new_selections.push(new_selection);
6061                                new_selections.push(selection);
6062                            } else {
6063                                new_selections.push(selection);
6064                                new_selections.push(new_selection);
6065                            }
6066
6067                            continue 'outer;
6068                        }
6069                    }
6070                }
6071
6072                new_selections.push(selection);
6073            }
6074        } else {
6075            new_selections = selections;
6076            new_selections.retain(|s| s.id != last_added_selection);
6077            state.stack.pop();
6078        }
6079
6080        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6081            s.select(new_selections);
6082        });
6083        if state.stack.len() > 1 {
6084            self.add_selections_state = Some(state);
6085        }
6086    }
6087
6088    pub fn select_next_match_internal(
6089        &mut self,
6090        display_map: &DisplaySnapshot,
6091        replace_newest: bool,
6092        autoscroll: Option<Autoscroll>,
6093        cx: &mut ViewContext<Self>,
6094    ) -> Result<()> {
6095        fn select_next_match_ranges(
6096            this: &mut Editor,
6097            range: Range<usize>,
6098            replace_newest: bool,
6099            auto_scroll: Option<Autoscroll>,
6100            cx: &mut ViewContext<Editor>,
6101        ) {
6102            this.unfold_ranges([range.clone()], false, true, cx);
6103            this.change_selections(auto_scroll, cx, |s| {
6104                if replace_newest {
6105                    s.delete(s.newest_anchor().id);
6106                }
6107                s.insert_range(range.clone());
6108            });
6109        }
6110
6111        let buffer = &display_map.buffer_snapshot;
6112        let mut selections = self.selections.all::<usize>(cx);
6113        if let Some(mut select_next_state) = self.select_next_state.take() {
6114            let query = &select_next_state.query;
6115            if !select_next_state.done {
6116                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
6117                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
6118                let mut next_selected_range = None;
6119
6120                let bytes_after_last_selection =
6121                    buffer.bytes_in_range(last_selection.end..buffer.len());
6122                let bytes_before_first_selection = buffer.bytes_in_range(0..first_selection.start);
6123                let query_matches = query
6124                    .stream_find_iter(bytes_after_last_selection)
6125                    .map(|result| (last_selection.end, result))
6126                    .chain(
6127                        query
6128                            .stream_find_iter(bytes_before_first_selection)
6129                            .map(|result| (0, result)),
6130                    );
6131
6132                for (start_offset, query_match) in query_matches {
6133                    let query_match = query_match.unwrap(); // can only fail due to I/O
6134                    let offset_range =
6135                        start_offset + query_match.start()..start_offset + query_match.end();
6136                    let display_range = offset_range.start.to_display_point(&display_map)
6137                        ..offset_range.end.to_display_point(&display_map);
6138
6139                    if !select_next_state.wordwise
6140                        || (!movement::is_inside_word(&display_map, display_range.start)
6141                            && !movement::is_inside_word(&display_map, display_range.end))
6142                    {
6143                        // TODO: This is n^2, because we might check all the selections
6144                        if selections
6145                            .iter()
6146                            .find(|selection| selection.range().overlaps(&offset_range))
6147                            .is_none()
6148                        {
6149                            next_selected_range = Some(offset_range);
6150                            break;
6151                        }
6152                    }
6153                }
6154
6155                if let Some(next_selected_range) = next_selected_range {
6156                    select_next_match_ranges(
6157                        self,
6158                        next_selected_range,
6159                        replace_newest,
6160                        autoscroll,
6161                        cx,
6162                    );
6163                } else {
6164                    select_next_state.done = true;
6165                }
6166            }
6167
6168            self.select_next_state = Some(select_next_state);
6169        } else {
6170            let mut only_carets = true;
6171            let mut same_text_selected = true;
6172            let mut selected_text = None;
6173
6174            let mut selections_iter = selections.iter().peekable();
6175            while let Some(selection) = selections_iter.next() {
6176                if selection.start != selection.end {
6177                    only_carets = false;
6178                }
6179
6180                if same_text_selected {
6181                    if selected_text.is_none() {
6182                        selected_text =
6183                            Some(buffer.text_for_range(selection.range()).collect::<String>());
6184                    }
6185
6186                    if let Some(next_selection) = selections_iter.peek() {
6187                        if next_selection.range().len() == selection.range().len() {
6188                            let next_selected_text = buffer
6189                                .text_for_range(next_selection.range())
6190                                .collect::<String>();
6191                            if Some(next_selected_text) != selected_text {
6192                                same_text_selected = false;
6193                                selected_text = None;
6194                            }
6195                        } else {
6196                            same_text_selected = false;
6197                            selected_text = None;
6198                        }
6199                    }
6200                }
6201            }
6202
6203            if only_carets {
6204                for selection in &mut selections {
6205                    let word_range = movement::surrounding_word(
6206                        &display_map,
6207                        selection.start.to_display_point(&display_map),
6208                    );
6209                    selection.start = word_range.start.to_offset(&display_map, Bias::Left);
6210                    selection.end = word_range.end.to_offset(&display_map, Bias::Left);
6211                    selection.goal = SelectionGoal::None;
6212                    selection.reversed = false;
6213                    select_next_match_ranges(
6214                        self,
6215                        selection.start..selection.end,
6216                        replace_newest,
6217                        autoscroll,
6218                        cx,
6219                    );
6220                }
6221
6222                if selections.len() == 1 {
6223                    let selection = selections
6224                        .last()
6225                        .expect("ensured that there's only one selection");
6226                    let query = buffer
6227                        .text_for_range(selection.start..selection.end)
6228                        .collect::<String>();
6229                    let is_empty = query.is_empty();
6230                    let select_state = SelectNextState {
6231                        query: AhoCorasick::new(&[query])?,
6232                        wordwise: true,
6233                        done: is_empty,
6234                    };
6235                    self.select_next_state = Some(select_state);
6236                } else {
6237                    self.select_next_state = None;
6238                }
6239            } else if let Some(selected_text) = selected_text {
6240                self.select_next_state = Some(SelectNextState {
6241                    query: AhoCorasick::new(&[selected_text])?,
6242                    wordwise: false,
6243                    done: false,
6244                });
6245                self.select_next_match_internal(display_map, replace_newest, autoscroll, cx)?;
6246            }
6247        }
6248        Ok(())
6249    }
6250
6251    pub fn select_all_matches(
6252        &mut self,
6253        _action: &SelectAllMatches,
6254        cx: &mut ViewContext<Self>,
6255    ) -> Result<()> {
6256        self.push_to_selection_history();
6257        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6258
6259        self.select_next_match_internal(&display_map, false, None, cx)?;
6260        let Some(select_next_state) = self.select_next_state.as_mut() else {
6261            return Ok(());
6262        };
6263        if select_next_state.done {
6264            return Ok(());
6265        }
6266
6267        let mut new_selections = self.selections.all::<usize>(cx);
6268
6269        let buffer = &display_map.buffer_snapshot;
6270        let query_matches = select_next_state
6271            .query
6272            .stream_find_iter(buffer.bytes_in_range(0..buffer.len()));
6273
6274        for query_match in query_matches {
6275            let query_match = query_match.unwrap(); // can only fail due to I/O
6276            let offset_range = query_match.start()..query_match.end();
6277            let display_range = offset_range.start.to_display_point(&display_map)
6278                ..offset_range.end.to_display_point(&display_map);
6279
6280            if !select_next_state.wordwise
6281                || (!movement::is_inside_word(&display_map, display_range.start)
6282                    && !movement::is_inside_word(&display_map, display_range.end))
6283            {
6284                self.selections.change_with(cx, |selections| {
6285                    new_selections.push(Selection {
6286                        id: selections.new_selection_id(),
6287                        start: offset_range.start,
6288                        end: offset_range.end,
6289                        reversed: false,
6290                        goal: SelectionGoal::None,
6291                    });
6292                });
6293            }
6294        }
6295
6296        new_selections.sort_by_key(|selection| selection.start);
6297        let mut ix = 0;
6298        while ix + 1 < new_selections.len() {
6299            let current_selection = &new_selections[ix];
6300            let next_selection = &new_selections[ix + 1];
6301            if current_selection.range().overlaps(&next_selection.range()) {
6302                if current_selection.id < next_selection.id {
6303                    new_selections.remove(ix + 1);
6304                } else {
6305                    new_selections.remove(ix);
6306                }
6307            } else {
6308                ix += 1;
6309            }
6310        }
6311
6312        select_next_state.done = true;
6313        self.unfold_ranges(
6314            new_selections.iter().map(|selection| selection.range()),
6315            false,
6316            false,
6317            cx,
6318        );
6319        self.change_selections(Some(Autoscroll::fit()), cx, |selections| {
6320            selections.select(new_selections)
6321        });
6322
6323        Ok(())
6324    }
6325
6326    pub fn select_next(&mut self, action: &SelectNext, cx: &mut ViewContext<Self>) -> Result<()> {
6327        self.push_to_selection_history();
6328        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6329        self.select_next_match_internal(
6330            &display_map,
6331            action.replace_newest,
6332            Some(Autoscroll::newest()),
6333            cx,
6334        )?;
6335        Ok(())
6336    }
6337
6338    pub fn select_previous(
6339        &mut self,
6340        action: &SelectPrevious,
6341        cx: &mut ViewContext<Self>,
6342    ) -> Result<()> {
6343        self.push_to_selection_history();
6344        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6345        let buffer = &display_map.buffer_snapshot;
6346        let mut selections = self.selections.all::<usize>(cx);
6347        if let Some(mut select_prev_state) = self.select_prev_state.take() {
6348            let query = &select_prev_state.query;
6349            if !select_prev_state.done {
6350                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
6351                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
6352                let mut next_selected_range = None;
6353                // When we're iterating matches backwards, the oldest match will actually be the furthest one in the buffer.
6354                let bytes_before_last_selection =
6355                    buffer.reversed_bytes_in_range(0..last_selection.start);
6356                let bytes_after_first_selection =
6357                    buffer.reversed_bytes_in_range(first_selection.end..buffer.len());
6358                let query_matches = query
6359                    .stream_find_iter(bytes_before_last_selection)
6360                    .map(|result| (last_selection.start, result))
6361                    .chain(
6362                        query
6363                            .stream_find_iter(bytes_after_first_selection)
6364                            .map(|result| (buffer.len(), result)),
6365                    );
6366                for (end_offset, query_match) in query_matches {
6367                    let query_match = query_match.unwrap(); // can only fail due to I/O
6368                    let offset_range =
6369                        end_offset - query_match.end()..end_offset - query_match.start();
6370                    let display_range = offset_range.start.to_display_point(&display_map)
6371                        ..offset_range.end.to_display_point(&display_map);
6372
6373                    if !select_prev_state.wordwise
6374                        || (!movement::is_inside_word(&display_map, display_range.start)
6375                            && !movement::is_inside_word(&display_map, display_range.end))
6376                    {
6377                        next_selected_range = Some(offset_range);
6378                        break;
6379                    }
6380                }
6381
6382                if let Some(next_selected_range) = next_selected_range {
6383                    self.unfold_ranges([next_selected_range.clone()], false, true, cx);
6384                    self.change_selections(Some(Autoscroll::newest()), cx, |s| {
6385                        if action.replace_newest {
6386                            s.delete(s.newest_anchor().id);
6387                        }
6388                        s.insert_range(next_selected_range);
6389                    });
6390                } else {
6391                    select_prev_state.done = true;
6392                }
6393            }
6394
6395            self.select_prev_state = Some(select_prev_state);
6396        } else {
6397            let mut only_carets = true;
6398            let mut same_text_selected = true;
6399            let mut selected_text = None;
6400
6401            let mut selections_iter = selections.iter().peekable();
6402            while let Some(selection) = selections_iter.next() {
6403                if selection.start != selection.end {
6404                    only_carets = false;
6405                }
6406
6407                if same_text_selected {
6408                    if selected_text.is_none() {
6409                        selected_text =
6410                            Some(buffer.text_for_range(selection.range()).collect::<String>());
6411                    }
6412
6413                    if let Some(next_selection) = selections_iter.peek() {
6414                        if next_selection.range().len() == selection.range().len() {
6415                            let next_selected_text = buffer
6416                                .text_for_range(next_selection.range())
6417                                .collect::<String>();
6418                            if Some(next_selected_text) != selected_text {
6419                                same_text_selected = false;
6420                                selected_text = None;
6421                            }
6422                        } else {
6423                            same_text_selected = false;
6424                            selected_text = None;
6425                        }
6426                    }
6427                }
6428            }
6429
6430            if only_carets {
6431                for selection in &mut selections {
6432                    let word_range = movement::surrounding_word(
6433                        &display_map,
6434                        selection.start.to_display_point(&display_map),
6435                    );
6436                    selection.start = word_range.start.to_offset(&display_map, Bias::Left);
6437                    selection.end = word_range.end.to_offset(&display_map, Bias::Left);
6438                    selection.goal = SelectionGoal::None;
6439                    selection.reversed = false;
6440                }
6441                if selections.len() == 1 {
6442                    let selection = selections
6443                        .last()
6444                        .expect("ensured that there's only one selection");
6445                    let query = buffer
6446                        .text_for_range(selection.start..selection.end)
6447                        .collect::<String>();
6448                    let is_empty = query.is_empty();
6449                    let select_state = SelectNextState {
6450                        query: AhoCorasick::new(&[query.chars().rev().collect::<String>()])?,
6451                        wordwise: true,
6452                        done: is_empty,
6453                    };
6454                    self.select_prev_state = Some(select_state);
6455                } else {
6456                    self.select_prev_state = None;
6457                }
6458
6459                self.unfold_ranges(
6460                    selections.iter().map(|s| s.range()).collect::<Vec<_>>(),
6461                    false,
6462                    true,
6463                    cx,
6464                );
6465                self.change_selections(Some(Autoscroll::newest()), cx, |s| {
6466                    s.select(selections);
6467                });
6468            } else if let Some(selected_text) = selected_text {
6469                self.select_prev_state = Some(SelectNextState {
6470                    query: AhoCorasick::new(&[selected_text.chars().rev().collect::<String>()])?,
6471                    wordwise: false,
6472                    done: false,
6473                });
6474                self.select_previous(action, cx)?;
6475            }
6476        }
6477        Ok(())
6478    }
6479
6480    pub fn toggle_comments(&mut self, action: &ToggleComments, cx: &mut ViewContext<Self>) {
6481        let text_layout_details = &self.text_layout_details(cx);
6482        self.transact(cx, |this, cx| {
6483            let mut selections = this.selections.all::<Point>(cx);
6484            let mut edits = Vec::new();
6485            let mut selection_edit_ranges = Vec::new();
6486            let mut last_toggled_row = None;
6487            let snapshot = this.buffer.read(cx).read(cx);
6488            let empty_str: Arc<str> = "".into();
6489            let mut suffixes_inserted = Vec::new();
6490
6491            fn comment_prefix_range(
6492                snapshot: &MultiBufferSnapshot,
6493                row: u32,
6494                comment_prefix: &str,
6495                comment_prefix_whitespace: &str,
6496            ) -> Range<Point> {
6497                let start = Point::new(row, snapshot.indent_size_for_line(row).len);
6498
6499                let mut line_bytes = snapshot
6500                    .bytes_in_range(start..snapshot.max_point())
6501                    .flatten()
6502                    .copied();
6503
6504                // If this line currently begins with the line comment prefix, then record
6505                // the range containing the prefix.
6506                if line_bytes
6507                    .by_ref()
6508                    .take(comment_prefix.len())
6509                    .eq(comment_prefix.bytes())
6510                {
6511                    // Include any whitespace that matches the comment prefix.
6512                    let matching_whitespace_len = line_bytes
6513                        .zip(comment_prefix_whitespace.bytes())
6514                        .take_while(|(a, b)| a == b)
6515                        .count() as u32;
6516                    let end = Point::new(
6517                        start.row,
6518                        start.column + comment_prefix.len() as u32 + matching_whitespace_len,
6519                    );
6520                    start..end
6521                } else {
6522                    start..start
6523                }
6524            }
6525
6526            fn comment_suffix_range(
6527                snapshot: &MultiBufferSnapshot,
6528                row: u32,
6529                comment_suffix: &str,
6530                comment_suffix_has_leading_space: bool,
6531            ) -> Range<Point> {
6532                let end = Point::new(row, snapshot.line_len(row));
6533                let suffix_start_column = end.column.saturating_sub(comment_suffix.len() as u32);
6534
6535                let mut line_end_bytes = snapshot
6536                    .bytes_in_range(Point::new(end.row, suffix_start_column.saturating_sub(1))..end)
6537                    .flatten()
6538                    .copied();
6539
6540                let leading_space_len = if suffix_start_column > 0
6541                    && line_end_bytes.next() == Some(b' ')
6542                    && comment_suffix_has_leading_space
6543                {
6544                    1
6545                } else {
6546                    0
6547                };
6548
6549                // If this line currently begins with the line comment prefix, then record
6550                // the range containing the prefix.
6551                if line_end_bytes.by_ref().eq(comment_suffix.bytes()) {
6552                    let start = Point::new(end.row, suffix_start_column - leading_space_len);
6553                    start..end
6554                } else {
6555                    end..end
6556                }
6557            }
6558
6559            // TODO: Handle selections that cross excerpts
6560            for selection in &mut selections {
6561                let start_column = snapshot.indent_size_for_line(selection.start.row).len;
6562                let language = if let Some(language) =
6563                    snapshot.language_scope_at(Point::new(selection.start.row, start_column))
6564                {
6565                    language
6566                } else {
6567                    continue;
6568                };
6569
6570                selection_edit_ranges.clear();
6571
6572                // If multiple selections contain a given row, avoid processing that
6573                // row more than once.
6574                let mut start_row = selection.start.row;
6575                if last_toggled_row == Some(start_row) {
6576                    start_row += 1;
6577                }
6578                let end_row =
6579                    if selection.end.row > selection.start.row && selection.end.column == 0 {
6580                        selection.end.row - 1
6581                    } else {
6582                        selection.end.row
6583                    };
6584                last_toggled_row = Some(end_row);
6585
6586                if start_row > end_row {
6587                    continue;
6588                }
6589
6590                // If the language has line comments, toggle those.
6591                if let Some(full_comment_prefix) = language
6592                    .line_comment_prefixes()
6593                    .and_then(|prefixes| prefixes.first())
6594                {
6595                    // Split the comment prefix's trailing whitespace into a separate string,
6596                    // as that portion won't be used for detecting if a line is a comment.
6597                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
6598                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
6599                    let mut all_selection_lines_are_comments = true;
6600
6601                    for row in start_row..=end_row {
6602                        if start_row < end_row && snapshot.is_line_blank(row) {
6603                            continue;
6604                        }
6605
6606                        let prefix_range = comment_prefix_range(
6607                            snapshot.deref(),
6608                            row,
6609                            comment_prefix,
6610                            comment_prefix_whitespace,
6611                        );
6612                        if prefix_range.is_empty() {
6613                            all_selection_lines_are_comments = false;
6614                        }
6615                        selection_edit_ranges.push(prefix_range);
6616                    }
6617
6618                    if all_selection_lines_are_comments {
6619                        edits.extend(
6620                            selection_edit_ranges
6621                                .iter()
6622                                .cloned()
6623                                .map(|range| (range, empty_str.clone())),
6624                        );
6625                    } else {
6626                        let min_column = selection_edit_ranges
6627                            .iter()
6628                            .map(|r| r.start.column)
6629                            .min()
6630                            .unwrap_or(0);
6631                        edits.extend(selection_edit_ranges.iter().map(|range| {
6632                            let position = Point::new(range.start.row, min_column);
6633                            (position..position, full_comment_prefix.clone())
6634                        }));
6635                    }
6636                } else if let Some((full_comment_prefix, comment_suffix)) =
6637                    language.block_comment_delimiters()
6638                {
6639                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
6640                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
6641                    let prefix_range = comment_prefix_range(
6642                        snapshot.deref(),
6643                        start_row,
6644                        comment_prefix,
6645                        comment_prefix_whitespace,
6646                    );
6647                    let suffix_range = comment_suffix_range(
6648                        snapshot.deref(),
6649                        end_row,
6650                        comment_suffix.trim_start_matches(' '),
6651                        comment_suffix.starts_with(' '),
6652                    );
6653
6654                    if prefix_range.is_empty() || suffix_range.is_empty() {
6655                        edits.push((
6656                            prefix_range.start..prefix_range.start,
6657                            full_comment_prefix.clone(),
6658                        ));
6659                        edits.push((suffix_range.end..suffix_range.end, comment_suffix.clone()));
6660                        suffixes_inserted.push((end_row, comment_suffix.len()));
6661                    } else {
6662                        edits.push((prefix_range, empty_str.clone()));
6663                        edits.push((suffix_range, empty_str.clone()));
6664                    }
6665                } else {
6666                    continue;
6667                }
6668            }
6669
6670            drop(snapshot);
6671            this.buffer.update(cx, |buffer, cx| {
6672                buffer.edit(edits, None, cx);
6673            });
6674
6675            // Adjust selections so that they end before any comment suffixes that
6676            // were inserted.
6677            let mut suffixes_inserted = suffixes_inserted.into_iter().peekable();
6678            let mut selections = this.selections.all::<Point>(cx);
6679            let snapshot = this.buffer.read(cx).read(cx);
6680            for selection in &mut selections {
6681                while let Some((row, suffix_len)) = suffixes_inserted.peek().copied() {
6682                    match row.cmp(&selection.end.row) {
6683                        Ordering::Less => {
6684                            suffixes_inserted.next();
6685                            continue;
6686                        }
6687                        Ordering::Greater => break,
6688                        Ordering::Equal => {
6689                            if selection.end.column == snapshot.line_len(row) {
6690                                if selection.is_empty() {
6691                                    selection.start.column -= suffix_len as u32;
6692                                }
6693                                selection.end.column -= suffix_len as u32;
6694                            }
6695                            break;
6696                        }
6697                    }
6698                }
6699            }
6700
6701            drop(snapshot);
6702            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
6703
6704            let selections = this.selections.all::<Point>(cx);
6705            let selections_on_single_row = selections.windows(2).all(|selections| {
6706                selections[0].start.row == selections[1].start.row
6707                    && selections[0].end.row == selections[1].end.row
6708                    && selections[0].start.row == selections[0].end.row
6709            });
6710            let selections_selecting = selections
6711                .iter()
6712                .any(|selection| selection.start != selection.end);
6713            let advance_downwards = action.advance_downwards
6714                && selections_on_single_row
6715                && !selections_selecting
6716                && this.mode != EditorMode::SingleLine;
6717
6718            if advance_downwards {
6719                let snapshot = this.buffer.read(cx).snapshot(cx);
6720
6721                this.change_selections(Some(Autoscroll::fit()), cx, |s| {
6722                    s.move_cursors_with(|display_snapshot, display_point, _| {
6723                        let mut point = display_point.to_point(display_snapshot);
6724                        point.row += 1;
6725                        point = snapshot.clip_point(point, Bias::Left);
6726                        let display_point = point.to_display_point(display_snapshot);
6727                        let goal = SelectionGoal::HorizontalPosition(
6728                            display_snapshot
6729                                .x_for_display_point(display_point, &text_layout_details)
6730                                .into(),
6731                        );
6732                        (display_point, goal)
6733                    })
6734                });
6735            }
6736        });
6737    }
6738
6739    pub fn select_larger_syntax_node(
6740        &mut self,
6741        _: &SelectLargerSyntaxNode,
6742        cx: &mut ViewContext<Self>,
6743    ) {
6744        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6745        let buffer = self.buffer.read(cx).snapshot(cx);
6746        let old_selections = self.selections.all::<usize>(cx).into_boxed_slice();
6747
6748        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
6749        let mut selected_larger_node = false;
6750        let new_selections = old_selections
6751            .iter()
6752            .map(|selection| {
6753                let old_range = selection.start..selection.end;
6754                let mut new_range = old_range.clone();
6755                while let Some(containing_range) =
6756                    buffer.range_for_syntax_ancestor(new_range.clone())
6757                {
6758                    new_range = containing_range;
6759                    if !display_map.intersects_fold(new_range.start)
6760                        && !display_map.intersects_fold(new_range.end)
6761                    {
6762                        break;
6763                    }
6764                }
6765
6766                selected_larger_node |= new_range != old_range;
6767                Selection {
6768                    id: selection.id,
6769                    start: new_range.start,
6770                    end: new_range.end,
6771                    goal: SelectionGoal::None,
6772                    reversed: selection.reversed,
6773                }
6774            })
6775            .collect::<Vec<_>>();
6776
6777        if selected_larger_node {
6778            stack.push(old_selections);
6779            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6780                s.select(new_selections);
6781            });
6782        }
6783        self.select_larger_syntax_node_stack = stack;
6784    }
6785
6786    pub fn select_smaller_syntax_node(
6787        &mut self,
6788        _: &SelectSmallerSyntaxNode,
6789        cx: &mut ViewContext<Self>,
6790    ) {
6791        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
6792        if let Some(selections) = stack.pop() {
6793            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6794                s.select(selections.to_vec());
6795            });
6796        }
6797        self.select_larger_syntax_node_stack = stack;
6798    }
6799
6800    pub fn move_to_enclosing_bracket(
6801        &mut self,
6802        _: &MoveToEnclosingBracket,
6803        cx: &mut ViewContext<Self>,
6804    ) {
6805        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6806            s.move_offsets_with(|snapshot, selection| {
6807                let Some(enclosing_bracket_ranges) =
6808                    snapshot.enclosing_bracket_ranges(selection.start..selection.end)
6809                else {
6810                    return;
6811                };
6812
6813                let mut best_length = usize::MAX;
6814                let mut best_inside = false;
6815                let mut best_in_bracket_range = false;
6816                let mut best_destination = None;
6817                for (open, close) in enclosing_bracket_ranges {
6818                    let close = close.to_inclusive();
6819                    let length = close.end() - open.start;
6820                    let inside = selection.start >= open.end && selection.end <= *close.start();
6821                    let in_bracket_range = open.to_inclusive().contains(&selection.head())
6822                        || close.contains(&selection.head());
6823
6824                    // If best is next to a bracket and current isn't, skip
6825                    if !in_bracket_range && best_in_bracket_range {
6826                        continue;
6827                    }
6828
6829                    // Prefer smaller lengths unless best is inside and current isn't
6830                    if length > best_length && (best_inside || !inside) {
6831                        continue;
6832                    }
6833
6834                    best_length = length;
6835                    best_inside = inside;
6836                    best_in_bracket_range = in_bracket_range;
6837                    best_destination = Some(
6838                        if close.contains(&selection.start) && close.contains(&selection.end) {
6839                            if inside {
6840                                open.end
6841                            } else {
6842                                open.start
6843                            }
6844                        } else {
6845                            if inside {
6846                                *close.start()
6847                            } else {
6848                                *close.end()
6849                            }
6850                        },
6851                    );
6852                }
6853
6854                if let Some(destination) = best_destination {
6855                    selection.collapse_to(destination, SelectionGoal::None);
6856                }
6857            })
6858        });
6859    }
6860
6861    pub fn undo_selection(&mut self, _: &UndoSelection, cx: &mut ViewContext<Self>) {
6862        self.end_selection(cx);
6863        self.selection_history.mode = SelectionHistoryMode::Undoing;
6864        if let Some(entry) = self.selection_history.undo_stack.pop_back() {
6865            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
6866            self.select_next_state = entry.select_next_state;
6867            self.select_prev_state = entry.select_prev_state;
6868            self.add_selections_state = entry.add_selections_state;
6869            self.request_autoscroll(Autoscroll::newest(), cx);
6870        }
6871        self.selection_history.mode = SelectionHistoryMode::Normal;
6872    }
6873
6874    pub fn redo_selection(&mut self, _: &RedoSelection, cx: &mut ViewContext<Self>) {
6875        self.end_selection(cx);
6876        self.selection_history.mode = SelectionHistoryMode::Redoing;
6877        if let Some(entry) = self.selection_history.redo_stack.pop_back() {
6878            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
6879            self.select_next_state = entry.select_next_state;
6880            self.select_prev_state = entry.select_prev_state;
6881            self.add_selections_state = entry.add_selections_state;
6882            self.request_autoscroll(Autoscroll::newest(), cx);
6883        }
6884        self.selection_history.mode = SelectionHistoryMode::Normal;
6885    }
6886
6887    fn go_to_diagnostic(&mut self, _: &GoToDiagnostic, cx: &mut ViewContext<Self>) {
6888        self.go_to_diagnostic_impl(Direction::Next, cx)
6889    }
6890
6891    fn go_to_prev_diagnostic(&mut self, _: &GoToPrevDiagnostic, cx: &mut ViewContext<Self>) {
6892        self.go_to_diagnostic_impl(Direction::Prev, cx)
6893    }
6894
6895    pub fn go_to_diagnostic_impl(&mut self, direction: Direction, cx: &mut ViewContext<Self>) {
6896        let buffer = self.buffer.read(cx).snapshot(cx);
6897        let selection = self.selections.newest::<usize>(cx);
6898
6899        // If there is an active Diagnostic Popover jump to its diagnostic instead.
6900        if direction == Direction::Next {
6901            if let Some(popover) = self.hover_state.diagnostic_popover.as_ref() {
6902                let (group_id, jump_to) = popover.activation_info();
6903                if self.activate_diagnostics(group_id, cx) {
6904                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6905                        let mut new_selection = s.newest_anchor().clone();
6906                        new_selection.collapse_to(jump_to, SelectionGoal::None);
6907                        s.select_anchors(vec![new_selection.clone()]);
6908                    });
6909                }
6910                return;
6911            }
6912        }
6913
6914        let mut active_primary_range = self.active_diagnostics.as_ref().map(|active_diagnostics| {
6915            active_diagnostics
6916                .primary_range
6917                .to_offset(&buffer)
6918                .to_inclusive()
6919        });
6920        let mut search_start = if let Some(active_primary_range) = active_primary_range.as_ref() {
6921            if active_primary_range.contains(&selection.head()) {
6922                *active_primary_range.end()
6923            } else {
6924                selection.head()
6925            }
6926        } else {
6927            selection.head()
6928        };
6929
6930        loop {
6931            let mut diagnostics = if direction == Direction::Prev {
6932                buffer.diagnostics_in_range::<_, usize>(0..search_start, true)
6933            } else {
6934                buffer.diagnostics_in_range::<_, usize>(search_start..buffer.len(), false)
6935            };
6936            let group = diagnostics.find_map(|entry| {
6937                if entry.diagnostic.is_primary
6938                    && entry.diagnostic.severity <= DiagnosticSeverity::WARNING
6939                    && !entry.range.is_empty()
6940                    && Some(entry.range.end) != active_primary_range.as_ref().map(|r| *r.end())
6941                    && !entry.range.contains(&search_start)
6942                {
6943                    Some((entry.range, entry.diagnostic.group_id))
6944                } else {
6945                    None
6946                }
6947            });
6948
6949            if let Some((primary_range, group_id)) = group {
6950                if self.activate_diagnostics(group_id, cx) {
6951                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6952                        s.select(vec![Selection {
6953                            id: selection.id,
6954                            start: primary_range.start,
6955                            end: primary_range.start,
6956                            reversed: false,
6957                            goal: SelectionGoal::None,
6958                        }]);
6959                    });
6960                }
6961                break;
6962            } else {
6963                // Cycle around to the start of the buffer, potentially moving back to the start of
6964                // the currently active diagnostic.
6965                active_primary_range.take();
6966                if direction == Direction::Prev {
6967                    if search_start == buffer.len() {
6968                        break;
6969                    } else {
6970                        search_start = buffer.len();
6971                    }
6972                } else if search_start == 0 {
6973                    break;
6974                } else {
6975                    search_start = 0;
6976                }
6977            }
6978        }
6979    }
6980
6981    fn go_to_hunk(&mut self, _: &GoToHunk, cx: &mut ViewContext<Self>) {
6982        let snapshot = self
6983            .display_map
6984            .update(cx, |display_map, cx| display_map.snapshot(cx));
6985        let selection = self.selections.newest::<Point>(cx);
6986
6987        if !self.seek_in_direction(
6988            &snapshot,
6989            selection.head(),
6990            false,
6991            snapshot
6992                .buffer_snapshot
6993                .git_diff_hunks_in_range((selection.head().row + 1)..u32::MAX),
6994            cx,
6995        ) {
6996            let wrapped_point = Point::zero();
6997            self.seek_in_direction(
6998                &snapshot,
6999                wrapped_point,
7000                true,
7001                snapshot
7002                    .buffer_snapshot
7003                    .git_diff_hunks_in_range((wrapped_point.row + 1)..u32::MAX),
7004                cx,
7005            );
7006        }
7007    }
7008
7009    fn go_to_prev_hunk(&mut self, _: &GoToPrevHunk, cx: &mut ViewContext<Self>) {
7010        let snapshot = self
7011            .display_map
7012            .update(cx, |display_map, cx| display_map.snapshot(cx));
7013        let selection = self.selections.newest::<Point>(cx);
7014
7015        if !self.seek_in_direction(
7016            &snapshot,
7017            selection.head(),
7018            false,
7019            snapshot
7020                .buffer_snapshot
7021                .git_diff_hunks_in_range_rev(0..selection.head().row),
7022            cx,
7023        ) {
7024            let wrapped_point = snapshot.buffer_snapshot.max_point();
7025            self.seek_in_direction(
7026                &snapshot,
7027                wrapped_point,
7028                true,
7029                snapshot
7030                    .buffer_snapshot
7031                    .git_diff_hunks_in_range_rev(0..wrapped_point.row),
7032                cx,
7033            );
7034        }
7035    }
7036
7037    fn seek_in_direction(
7038        &mut self,
7039        snapshot: &DisplaySnapshot,
7040        initial_point: Point,
7041        is_wrapped: bool,
7042        hunks: impl Iterator<Item = DiffHunk<u32>>,
7043        cx: &mut ViewContext<Editor>,
7044    ) -> bool {
7045        let display_point = initial_point.to_display_point(snapshot);
7046        let mut hunks = hunks
7047            .map(|hunk| diff_hunk_to_display(hunk, &snapshot))
7048            .filter(|hunk| {
7049                if is_wrapped {
7050                    true
7051                } else {
7052                    !hunk.contains_display_row(display_point.row())
7053                }
7054            })
7055            .dedup();
7056
7057        if let Some(hunk) = hunks.next() {
7058            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
7059                let row = hunk.start_display_row();
7060                let point = DisplayPoint::new(row, 0);
7061                s.select_display_ranges([point..point]);
7062            });
7063
7064            true
7065        } else {
7066            false
7067        }
7068    }
7069
7070    pub fn go_to_definition(&mut self, _: &GoToDefinition, cx: &mut ViewContext<Self>) {
7071        self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, false, cx);
7072    }
7073
7074    pub fn go_to_type_definition(&mut self, _: &GoToTypeDefinition, cx: &mut ViewContext<Self>) {
7075        self.go_to_definition_of_kind(GotoDefinitionKind::Type, false, cx);
7076    }
7077
7078    pub fn go_to_definition_split(&mut self, _: &GoToDefinitionSplit, cx: &mut ViewContext<Self>) {
7079        self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, true, cx);
7080    }
7081
7082    pub fn go_to_type_definition_split(
7083        &mut self,
7084        _: &GoToTypeDefinitionSplit,
7085        cx: &mut ViewContext<Self>,
7086    ) {
7087        self.go_to_definition_of_kind(GotoDefinitionKind::Type, true, cx);
7088    }
7089
7090    fn go_to_definition_of_kind(
7091        &mut self,
7092        kind: GotoDefinitionKind,
7093        split: bool,
7094        cx: &mut ViewContext<Self>,
7095    ) {
7096        let Some(workspace) = self.workspace() else {
7097            return;
7098        };
7099        let buffer = self.buffer.read(cx);
7100        let head = self.selections.newest::<usize>(cx).head();
7101        let (buffer, head) = if let Some(text_anchor) = buffer.text_anchor_for_position(head, cx) {
7102            text_anchor
7103        } else {
7104            return;
7105        };
7106
7107        let project = workspace.read(cx).project().clone();
7108        let definitions = project.update(cx, |project, cx| match kind {
7109            GotoDefinitionKind::Symbol => project.definition(&buffer, head, cx),
7110            GotoDefinitionKind::Type => project.type_definition(&buffer, head, cx),
7111        });
7112
7113        cx.spawn(|editor, mut cx| async move {
7114            let definitions = definitions.await?;
7115            editor.update(&mut cx, |editor, cx| {
7116                editor.navigate_to_definitions(
7117                    definitions
7118                        .into_iter()
7119                        .map(GoToDefinitionLink::Text)
7120                        .collect(),
7121                    split,
7122                    cx,
7123                );
7124            })?;
7125            Ok::<(), anyhow::Error>(())
7126        })
7127        .detach_and_log_err(cx);
7128    }
7129
7130    pub fn navigate_to_definitions(
7131        &mut self,
7132        mut definitions: Vec<GoToDefinitionLink>,
7133        split: bool,
7134        cx: &mut ViewContext<Editor>,
7135    ) {
7136        let Some(workspace) = self.workspace() else {
7137            return;
7138        };
7139        let pane = workspace.read(cx).active_pane().clone();
7140        // If there is one definition, just open it directly
7141        if definitions.len() == 1 {
7142            let definition = definitions.pop().unwrap();
7143            let target_task = match definition {
7144                GoToDefinitionLink::Text(link) => Task::Ready(Some(Ok(Some(link.target)))),
7145                GoToDefinitionLink::InlayHint(lsp_location, server_id) => {
7146                    self.compute_target_location(lsp_location, server_id, cx)
7147                }
7148            };
7149            cx.spawn(|editor, mut cx| async move {
7150                let target = target_task.await.context("target resolution task")?;
7151                if let Some(target) = target {
7152                    editor.update(&mut cx, |editor, cx| {
7153                        let range = target.range.to_offset(target.buffer.read(cx));
7154                        let range = editor.range_for_match(&range);
7155                        if Some(&target.buffer) == editor.buffer.read(cx).as_singleton().as_ref() {
7156                            editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
7157                                s.select_ranges([range]);
7158                            });
7159                        } else {
7160                            cx.window_context().defer(move |cx| {
7161                                let target_editor: View<Self> =
7162                                    workspace.update(cx, |workspace, cx| {
7163                                        if split {
7164                                            workspace.split_project_item(target.buffer.clone(), cx)
7165                                        } else {
7166                                            workspace.open_project_item(target.buffer.clone(), cx)
7167                                        }
7168                                    });
7169                                target_editor.update(cx, |target_editor, cx| {
7170                                    // When selecting a definition in a different buffer, disable the nav history
7171                                    // to avoid creating a history entry at the previous cursor location.
7172                                    pane.update(cx, |pane, _| pane.disable_history());
7173                                    target_editor.change_selections(
7174                                        Some(Autoscroll::fit()),
7175                                        cx,
7176                                        |s| {
7177                                            s.select_ranges([range]);
7178                                        },
7179                                    );
7180                                    pane.update(cx, |pane, _| pane.enable_history());
7181                                });
7182                            });
7183                        }
7184                    })
7185                } else {
7186                    Ok(())
7187                }
7188            })
7189            .detach_and_log_err(cx);
7190        } else if !definitions.is_empty() {
7191            let replica_id = self.replica_id(cx);
7192            cx.spawn(|editor, mut cx| async move {
7193                let (title, location_tasks) = editor
7194                    .update(&mut cx, |editor, cx| {
7195                        let title = definitions
7196                            .iter()
7197                            .find_map(|definition| match definition {
7198                                GoToDefinitionLink::Text(link) => {
7199                                    link.origin.as_ref().map(|origin| {
7200                                        let buffer = origin.buffer.read(cx);
7201                                        format!(
7202                                            "Definitions for {}",
7203                                            buffer
7204                                                .text_for_range(origin.range.clone())
7205                                                .collect::<String>()
7206                                        )
7207                                    })
7208                                }
7209                                GoToDefinitionLink::InlayHint(_, _) => None,
7210                            })
7211                            .unwrap_or("Definitions".to_string());
7212                        let location_tasks = definitions
7213                            .into_iter()
7214                            .map(|definition| match definition {
7215                                GoToDefinitionLink::Text(link) => {
7216                                    Task::Ready(Some(Ok(Some(link.target))))
7217                                }
7218                                GoToDefinitionLink::InlayHint(lsp_location, server_id) => {
7219                                    editor.compute_target_location(lsp_location, server_id, cx)
7220                                }
7221                            })
7222                            .collect::<Vec<_>>();
7223                        (title, location_tasks)
7224                    })
7225                    .context("location tasks preparation")?;
7226
7227                let locations = futures::future::join_all(location_tasks)
7228                    .await
7229                    .into_iter()
7230                    .filter_map(|location| location.transpose())
7231                    .collect::<Result<_>>()
7232                    .context("location tasks")?;
7233                workspace
7234                    .update(&mut cx, |workspace, cx| {
7235                        Self::open_locations_in_multibuffer(
7236                            workspace, locations, replica_id, title, split, cx,
7237                        )
7238                    })
7239                    .ok();
7240
7241                anyhow::Ok(())
7242            })
7243            .detach_and_log_err(cx);
7244        }
7245    }
7246
7247    fn compute_target_location(
7248        &self,
7249        lsp_location: lsp::Location,
7250        server_id: LanguageServerId,
7251        cx: &mut ViewContext<Editor>,
7252    ) -> Task<anyhow::Result<Option<Location>>> {
7253        let Some(project) = self.project.clone() else {
7254            return Task::Ready(Some(Ok(None)));
7255        };
7256
7257        cx.spawn(move |editor, mut cx| async move {
7258            let location_task = editor.update(&mut cx, |editor, cx| {
7259                project.update(cx, |project, cx| {
7260                    let language_server_name =
7261                        editor.buffer.read(cx).as_singleton().and_then(|buffer| {
7262                            project
7263                                .language_server_for_buffer(buffer.read(cx), server_id, cx)
7264                                .map(|(_, lsp_adapter)| {
7265                                    LanguageServerName(Arc::from(lsp_adapter.name()))
7266                                })
7267                        });
7268                    language_server_name.map(|language_server_name| {
7269                        project.open_local_buffer_via_lsp(
7270                            lsp_location.uri.clone(),
7271                            server_id,
7272                            language_server_name,
7273                            cx,
7274                        )
7275                    })
7276                })
7277            })?;
7278            let location = match location_task {
7279                Some(task) => Some({
7280                    let target_buffer_handle = task.await.context("open local buffer")?;
7281                    let range = target_buffer_handle.update(&mut cx, |target_buffer, _| {
7282                        let target_start = target_buffer
7283                            .clip_point_utf16(point_from_lsp(lsp_location.range.start), Bias::Left);
7284                        let target_end = target_buffer
7285                            .clip_point_utf16(point_from_lsp(lsp_location.range.end), Bias::Left);
7286                        target_buffer.anchor_after(target_start)
7287                            ..target_buffer.anchor_before(target_end)
7288                    })?;
7289                    Location {
7290                        buffer: target_buffer_handle,
7291                        range,
7292                    }
7293                }),
7294                None => None,
7295            };
7296            Ok(location)
7297        })
7298    }
7299
7300    pub fn find_all_references(
7301        &mut self,
7302        _: &FindAllReferences,
7303        cx: &mut ViewContext<Self>,
7304    ) -> Option<Task<Result<()>>> {
7305        let buffer = self.buffer.read(cx);
7306        let head = self.selections.newest::<usize>(cx).head();
7307        let (buffer, head) = buffer.text_anchor_for_position(head, cx)?;
7308        let replica_id = self.replica_id(cx);
7309
7310        let workspace = self.workspace()?;
7311        let project = workspace.read(cx).project().clone();
7312        let references = project.update(cx, |project, cx| project.references(&buffer, head, cx));
7313        Some(cx.spawn(|_, mut cx| async move {
7314            let locations = references.await?;
7315            if locations.is_empty() {
7316                return Ok(());
7317            }
7318
7319            workspace.update(&mut cx, |workspace, cx| {
7320                let title = locations
7321                    .first()
7322                    .as_ref()
7323                    .map(|location| {
7324                        let buffer = location.buffer.read(cx);
7325                        format!(
7326                            "References to `{}`",
7327                            buffer
7328                                .text_for_range(location.range.clone())
7329                                .collect::<String>()
7330                        )
7331                    })
7332                    .unwrap();
7333                Self::open_locations_in_multibuffer(
7334                    workspace, locations, replica_id, title, false, cx,
7335                );
7336            })?;
7337
7338            Ok(())
7339        }))
7340    }
7341
7342    /// Opens a multibuffer with the given project locations in it
7343    pub fn open_locations_in_multibuffer(
7344        workspace: &mut Workspace,
7345        mut locations: Vec<Location>,
7346        replica_id: ReplicaId,
7347        title: String,
7348        split: bool,
7349        cx: &mut ViewContext<Workspace>,
7350    ) {
7351        // If there are multiple definitions, open them in a multibuffer
7352        locations.sort_by_key(|location| location.buffer.read(cx).remote_id());
7353        let mut locations = locations.into_iter().peekable();
7354        let mut ranges_to_highlight = Vec::new();
7355        let capability = workspace.project().read(cx).capability();
7356
7357        let excerpt_buffer = cx.new_model(|cx| {
7358            let mut multibuffer = MultiBuffer::new(replica_id, capability);
7359            while let Some(location) = locations.next() {
7360                let buffer = location.buffer.read(cx);
7361                let mut ranges_for_buffer = Vec::new();
7362                let range = location.range.to_offset(buffer);
7363                ranges_for_buffer.push(range.clone());
7364
7365                while let Some(next_location) = locations.peek() {
7366                    if next_location.buffer == location.buffer {
7367                        ranges_for_buffer.push(next_location.range.to_offset(buffer));
7368                        locations.next();
7369                    } else {
7370                        break;
7371                    }
7372                }
7373
7374                ranges_for_buffer.sort_by_key(|range| (range.start, Reverse(range.end)));
7375                ranges_to_highlight.extend(multibuffer.push_excerpts_with_context_lines(
7376                    location.buffer.clone(),
7377                    ranges_for_buffer,
7378                    1,
7379                    cx,
7380                ))
7381            }
7382
7383            multibuffer.with_title(title)
7384        });
7385
7386        let editor = cx.new_view(|cx| {
7387            Editor::for_multibuffer(excerpt_buffer, Some(workspace.project().clone()), cx)
7388        });
7389        editor.update(cx, |editor, cx| {
7390            editor.highlight_background::<Self>(
7391                ranges_to_highlight,
7392                |theme| theme.editor_highlighted_line_background,
7393                cx,
7394            );
7395        });
7396        if split {
7397            workspace.split_item(SplitDirection::Right, Box::new(editor), cx);
7398        } else {
7399            workspace.add_item(Box::new(editor), cx);
7400        }
7401    }
7402
7403    pub fn rename(&mut self, _: &Rename, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
7404        use language::ToOffset as _;
7405
7406        let project = self.project.clone()?;
7407        let selection = self.selections.newest_anchor().clone();
7408        let (cursor_buffer, cursor_buffer_position) = self
7409            .buffer
7410            .read(cx)
7411            .text_anchor_for_position(selection.head(), cx)?;
7412        let (tail_buffer, _) = self
7413            .buffer
7414            .read(cx)
7415            .text_anchor_for_position(selection.tail(), cx)?;
7416        if tail_buffer != cursor_buffer {
7417            return None;
7418        }
7419
7420        let snapshot = cursor_buffer.read(cx).snapshot();
7421        let cursor_buffer_offset = cursor_buffer_position.to_offset(&snapshot);
7422        let prepare_rename = project.update(cx, |project, cx| {
7423            project.prepare_rename(cursor_buffer, cursor_buffer_offset, cx)
7424        });
7425
7426        Some(cx.spawn(|this, mut cx| async move {
7427            let rename_range = if let Some(range) = prepare_rename.await? {
7428                Some(range)
7429            } else {
7430                this.update(&mut cx, |this, cx| {
7431                    let buffer = this.buffer.read(cx).snapshot(cx);
7432                    let mut buffer_highlights = this
7433                        .document_highlights_for_position(selection.head(), &buffer)
7434                        .filter(|highlight| {
7435                            highlight.start.excerpt_id == selection.head().excerpt_id
7436                                && highlight.end.excerpt_id == selection.head().excerpt_id
7437                        });
7438                    buffer_highlights
7439                        .next()
7440                        .map(|highlight| highlight.start.text_anchor..highlight.end.text_anchor)
7441                })?
7442            };
7443            if let Some(rename_range) = rename_range {
7444                let rename_buffer_range = rename_range.to_offset(&snapshot);
7445                let cursor_offset_in_rename_range =
7446                    cursor_buffer_offset.saturating_sub(rename_buffer_range.start);
7447
7448                this.update(&mut cx, |this, cx| {
7449                    this.take_rename(false, cx);
7450                    let buffer = this.buffer.read(cx).read(cx);
7451                    let cursor_offset = selection.head().to_offset(&buffer);
7452                    let rename_start = cursor_offset.saturating_sub(cursor_offset_in_rename_range);
7453                    let rename_end = rename_start + rename_buffer_range.len();
7454                    let range = buffer.anchor_before(rename_start)..buffer.anchor_after(rename_end);
7455                    let mut old_highlight_id = None;
7456                    let old_name: Arc<str> = buffer
7457                        .chunks(rename_start..rename_end, true)
7458                        .map(|chunk| {
7459                            if old_highlight_id.is_none() {
7460                                old_highlight_id = chunk.syntax_highlight_id;
7461                            }
7462                            chunk.text
7463                        })
7464                        .collect::<String>()
7465                        .into();
7466
7467                    drop(buffer);
7468
7469                    // Position the selection in the rename editor so that it matches the current selection.
7470                    this.show_local_selections = false;
7471                    let rename_editor = cx.new_view(|cx| {
7472                        let mut editor = Editor::single_line(cx);
7473                        editor.buffer.update(cx, |buffer, cx| {
7474                            buffer.edit([(0..0, old_name.clone())], None, cx)
7475                        });
7476                        editor.select_all(&SelectAll, cx);
7477                        editor
7478                    });
7479
7480                    let ranges = this
7481                        .clear_background_highlights::<DocumentHighlightWrite>(cx)
7482                        .into_iter()
7483                        .flat_map(|(_, ranges)| ranges.into_iter())
7484                        .chain(
7485                            this.clear_background_highlights::<DocumentHighlightRead>(cx)
7486                                .into_iter()
7487                                .flat_map(|(_, ranges)| ranges.into_iter()),
7488                        )
7489                        .collect();
7490
7491                    this.highlight_text::<Rename>(
7492                        ranges,
7493                        HighlightStyle {
7494                            fade_out: Some(0.6),
7495                            ..Default::default()
7496                        },
7497                        cx,
7498                    );
7499                    let rename_focus_handle = rename_editor.focus_handle(cx);
7500                    cx.focus(&rename_focus_handle);
7501                    let block_id = this.insert_blocks(
7502                        [BlockProperties {
7503                            style: BlockStyle::Flex,
7504                            position: range.start.clone(),
7505                            height: 1,
7506                            render: Arc::new({
7507                                let rename_editor = rename_editor.clone();
7508                                move |cx: &mut BlockContext| {
7509                                    let mut text_style = cx.editor_style.text.clone();
7510                                    if let Some(highlight_style) = old_highlight_id
7511                                        .and_then(|h| h.style(&cx.editor_style.syntax))
7512                                    {
7513                                        text_style = text_style.highlight(highlight_style);
7514                                    }
7515                                    div()
7516                                        .pl(cx.anchor_x)
7517                                        .child(EditorElement::new(
7518                                            &rename_editor,
7519                                            EditorStyle {
7520                                                background: cx.theme().system().transparent,
7521                                                local_player: cx.editor_style.local_player,
7522                                                text: text_style,
7523                                                scrollbar_width: cx.editor_style.scrollbar_width,
7524                                                syntax: cx.editor_style.syntax.clone(),
7525                                                status: cx.editor_style.status.clone(),
7526                                                inlays_style: HighlightStyle {
7527                                                    color: Some(cx.theme().status().hint),
7528                                                    font_weight: Some(FontWeight::BOLD),
7529                                                    ..HighlightStyle::default()
7530                                                },
7531                                                suggestions_style: HighlightStyle {
7532                                                    color: Some(cx.theme().status().predictive),
7533                                                    ..HighlightStyle::default()
7534                                                },
7535                                            },
7536                                        ))
7537                                        .into_any_element()
7538                                }
7539                            }),
7540                            disposition: BlockDisposition::Below,
7541                        }],
7542                        Some(Autoscroll::fit()),
7543                        cx,
7544                    )[0];
7545                    this.pending_rename = Some(RenameState {
7546                        range,
7547                        old_name,
7548                        editor: rename_editor,
7549                        block_id,
7550                    });
7551                })?;
7552            }
7553
7554            Ok(())
7555        }))
7556    }
7557
7558    pub fn confirm_rename(
7559        &mut self,
7560        _: &ConfirmRename,
7561        cx: &mut ViewContext<Self>,
7562    ) -> Option<Task<Result<()>>> {
7563        let rename = self.take_rename(false, cx)?;
7564        let workspace = self.workspace()?;
7565        let (start_buffer, start) = self
7566            .buffer
7567            .read(cx)
7568            .text_anchor_for_position(rename.range.start.clone(), cx)?;
7569        let (end_buffer, end) = self
7570            .buffer
7571            .read(cx)
7572            .text_anchor_for_position(rename.range.end.clone(), cx)?;
7573        if start_buffer != end_buffer {
7574            return None;
7575        }
7576
7577        let buffer = start_buffer;
7578        let range = start..end;
7579        let old_name = rename.old_name;
7580        let new_name = rename.editor.read(cx).text(cx);
7581
7582        let rename = workspace
7583            .read(cx)
7584            .project()
7585            .clone()
7586            .update(cx, |project, cx| {
7587                project.perform_rename(buffer.clone(), range.start, new_name.clone(), true, cx)
7588            });
7589        let workspace = workspace.downgrade();
7590
7591        Some(cx.spawn(|editor, mut cx| async move {
7592            let project_transaction = rename.await?;
7593            Self::open_project_transaction(
7594                &editor,
7595                workspace,
7596                project_transaction,
7597                format!("Rename: {}{}", old_name, new_name),
7598                cx.clone(),
7599            )
7600            .await?;
7601
7602            editor.update(&mut cx, |editor, cx| {
7603                editor.refresh_document_highlights(cx);
7604            })?;
7605            Ok(())
7606        }))
7607    }
7608
7609    fn take_rename(
7610        &mut self,
7611        moving_cursor: bool,
7612        cx: &mut ViewContext<Self>,
7613    ) -> Option<RenameState> {
7614        let rename = self.pending_rename.take()?;
7615        if rename.editor.focus_handle(cx).is_focused(cx) {
7616            cx.focus(&self.focus_handle);
7617        }
7618
7619        self.remove_blocks(
7620            [rename.block_id].into_iter().collect(),
7621            Some(Autoscroll::fit()),
7622            cx,
7623        );
7624        self.clear_highlights::<Rename>(cx);
7625        self.show_local_selections = true;
7626
7627        if moving_cursor {
7628            let rename_editor = rename.editor.read(cx);
7629            let cursor_in_rename_editor = rename_editor.selections.newest::<usize>(cx).head();
7630
7631            // Update the selection to match the position of the selection inside
7632            // the rename editor.
7633            let snapshot = self.buffer.read(cx).read(cx);
7634            let rename_range = rename.range.to_offset(&snapshot);
7635            let cursor_in_editor = snapshot
7636                .clip_offset(rename_range.start + cursor_in_rename_editor, Bias::Left)
7637                .min(rename_range.end);
7638            drop(snapshot);
7639
7640            self.change_selections(None, cx, |s| {
7641                s.select_ranges(vec![cursor_in_editor..cursor_in_editor])
7642            });
7643        } else {
7644            self.refresh_document_highlights(cx);
7645        }
7646
7647        Some(rename)
7648    }
7649
7650    #[cfg(any(test, feature = "test-support"))]
7651    pub fn pending_rename(&self) -> Option<&RenameState> {
7652        self.pending_rename.as_ref()
7653    }
7654
7655    fn format(&mut self, _: &Format, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
7656        let project = match &self.project {
7657            Some(project) => project.clone(),
7658            None => return None,
7659        };
7660
7661        Some(self.perform_format(project, FormatTrigger::Manual, cx))
7662    }
7663
7664    fn perform_format(
7665        &mut self,
7666        project: Model<Project>,
7667        trigger: FormatTrigger,
7668        cx: &mut ViewContext<Self>,
7669    ) -> Task<Result<()>> {
7670        let buffer = self.buffer().clone();
7671        let buffers = buffer.read(cx).all_buffers();
7672
7673        let mut timeout = cx.background_executor().timer(FORMAT_TIMEOUT).fuse();
7674        let format = project.update(cx, |project, cx| project.format(buffers, true, trigger, cx));
7675
7676        cx.spawn(|_, mut cx| async move {
7677            let transaction = futures::select_biased! {
7678                _ = timeout => {
7679                    log::warn!("timed out waiting for formatting");
7680                    None
7681                }
7682                transaction = format.log_err().fuse() => transaction,
7683            };
7684
7685            buffer
7686                .update(&mut cx, |buffer, cx| {
7687                    if let Some(transaction) = transaction {
7688                        if !buffer.is_singleton() {
7689                            buffer.push_transaction(&transaction.0, cx);
7690                        }
7691                    }
7692
7693                    cx.notify();
7694                })
7695                .ok();
7696
7697            Ok(())
7698        })
7699    }
7700
7701    fn restart_language_server(&mut self, _: &RestartLanguageServer, cx: &mut ViewContext<Self>) {
7702        if let Some(project) = self.project.clone() {
7703            self.buffer.update(cx, |multi_buffer, cx| {
7704                project.update(cx, |project, cx| {
7705                    project.restart_language_servers_for_buffers(multi_buffer.all_buffers(), cx);
7706                });
7707            })
7708        }
7709    }
7710
7711    fn show_character_palette(&mut self, _: &ShowCharacterPalette, cx: &mut ViewContext<Self>) {
7712        cx.show_character_palette();
7713    }
7714
7715    fn refresh_active_diagnostics(&mut self, cx: &mut ViewContext<Editor>) {
7716        if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
7717            let buffer = self.buffer.read(cx).snapshot(cx);
7718            let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
7719            let is_valid = buffer
7720                .diagnostics_in_range::<_, usize>(active_diagnostics.primary_range.clone(), false)
7721                .any(|entry| {
7722                    entry.diagnostic.is_primary
7723                        && !entry.range.is_empty()
7724                        && entry.range.start == primary_range_start
7725                        && entry.diagnostic.message == active_diagnostics.primary_message
7726                });
7727
7728            if is_valid != active_diagnostics.is_valid {
7729                active_diagnostics.is_valid = is_valid;
7730                let mut new_styles = HashMap::default();
7731                for (block_id, diagnostic) in &active_diagnostics.blocks {
7732                    new_styles.insert(
7733                        *block_id,
7734                        diagnostic_block_renderer(diagnostic.clone(), is_valid),
7735                    );
7736                }
7737                self.display_map
7738                    .update(cx, |display_map, _| display_map.replace_blocks(new_styles));
7739            }
7740        }
7741    }
7742
7743    fn activate_diagnostics(&mut self, group_id: usize, cx: &mut ViewContext<Self>) -> bool {
7744        self.dismiss_diagnostics(cx);
7745        self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
7746            let buffer = self.buffer.read(cx).snapshot(cx);
7747
7748            let mut primary_range = None;
7749            let mut primary_message = None;
7750            let mut group_end = Point::zero();
7751            let diagnostic_group = buffer
7752                .diagnostic_group::<Point>(group_id)
7753                .map(|entry| {
7754                    if entry.range.end > group_end {
7755                        group_end = entry.range.end;
7756                    }
7757                    if entry.diagnostic.is_primary {
7758                        primary_range = Some(entry.range.clone());
7759                        primary_message = Some(entry.diagnostic.message.clone());
7760                    }
7761                    entry
7762                })
7763                .collect::<Vec<_>>();
7764            let primary_range = primary_range?;
7765            let primary_message = primary_message?;
7766            let primary_range =
7767                buffer.anchor_after(primary_range.start)..buffer.anchor_before(primary_range.end);
7768
7769            let blocks = display_map
7770                .insert_blocks(
7771                    diagnostic_group.iter().map(|entry| {
7772                        let diagnostic = entry.diagnostic.clone();
7773                        let message_height = diagnostic.message.lines().count() as u8;
7774                        BlockProperties {
7775                            style: BlockStyle::Fixed,
7776                            position: buffer.anchor_after(entry.range.start),
7777                            height: message_height,
7778                            render: diagnostic_block_renderer(diagnostic, true),
7779                            disposition: BlockDisposition::Below,
7780                        }
7781                    }),
7782                    cx,
7783                )
7784                .into_iter()
7785                .zip(diagnostic_group.into_iter().map(|entry| entry.diagnostic))
7786                .collect();
7787
7788            Some(ActiveDiagnosticGroup {
7789                primary_range,
7790                primary_message,
7791                blocks,
7792                is_valid: true,
7793            })
7794        });
7795        self.active_diagnostics.is_some()
7796    }
7797
7798    fn dismiss_diagnostics(&mut self, cx: &mut ViewContext<Self>) {
7799        if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
7800            self.display_map.update(cx, |display_map, cx| {
7801                display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx);
7802            });
7803            cx.notify();
7804        }
7805    }
7806
7807    pub fn set_selections_from_remote(
7808        &mut self,
7809        selections: Vec<Selection<Anchor>>,
7810        pending_selection: Option<Selection<Anchor>>,
7811        cx: &mut ViewContext<Self>,
7812    ) {
7813        let old_cursor_position = self.selections.newest_anchor().head();
7814        self.selections.change_with(cx, |s| {
7815            s.select_anchors(selections);
7816            if let Some(pending_selection) = pending_selection {
7817                s.set_pending(pending_selection, SelectMode::Character);
7818            } else {
7819                s.clear_pending();
7820            }
7821        });
7822        self.selections_did_change(false, &old_cursor_position, cx);
7823    }
7824
7825    fn push_to_selection_history(&mut self) {
7826        self.selection_history.push(SelectionHistoryEntry {
7827            selections: self.selections.disjoint_anchors(),
7828            select_next_state: self.select_next_state.clone(),
7829            select_prev_state: self.select_prev_state.clone(),
7830            add_selections_state: self.add_selections_state.clone(),
7831        });
7832    }
7833
7834    pub fn transact(
7835        &mut self,
7836        cx: &mut ViewContext<Self>,
7837        update: impl FnOnce(&mut Self, &mut ViewContext<Self>),
7838    ) -> Option<TransactionId> {
7839        self.start_transaction_at(Instant::now(), cx);
7840        update(self, cx);
7841        self.end_transaction_at(Instant::now(), cx)
7842    }
7843
7844    fn start_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
7845        self.end_selection(cx);
7846        if let Some(tx_id) = self
7847            .buffer
7848            .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx))
7849        {
7850            self.selection_history
7851                .insert_transaction(tx_id, self.selections.disjoint_anchors());
7852        }
7853    }
7854
7855    fn end_transaction_at(
7856        &mut self,
7857        now: Instant,
7858        cx: &mut ViewContext<Self>,
7859    ) -> Option<TransactionId> {
7860        if let Some(tx_id) = self
7861            .buffer
7862            .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
7863        {
7864            if let Some((_, end_selections)) = self.selection_history.transaction_mut(tx_id) {
7865                *end_selections = Some(self.selections.disjoint_anchors());
7866            } else {
7867                log::error!("unexpectedly ended a transaction that wasn't started by this editor");
7868            }
7869
7870            cx.emit(EditorEvent::Edited);
7871            Some(tx_id)
7872        } else {
7873            None
7874        }
7875    }
7876
7877    pub fn fold(&mut self, _: &actions::Fold, cx: &mut ViewContext<Self>) {
7878        let mut fold_ranges = Vec::new();
7879
7880        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
7881
7882        let selections = self.selections.all_adjusted(cx);
7883        for selection in selections {
7884            let range = selection.range().sorted();
7885            let buffer_start_row = range.start.row;
7886
7887            for row in (0..=range.end.row).rev() {
7888                let fold_range = display_map.foldable_range(row);
7889
7890                if let Some(fold_range) = fold_range {
7891                    if fold_range.end.row >= buffer_start_row {
7892                        fold_ranges.push(fold_range);
7893                        if row <= range.start.row {
7894                            break;
7895                        }
7896                    }
7897                }
7898            }
7899        }
7900
7901        self.fold_ranges(fold_ranges, true, cx);
7902    }
7903
7904    pub fn fold_at(&mut self, fold_at: &FoldAt, cx: &mut ViewContext<Self>) {
7905        let buffer_row = fold_at.buffer_row;
7906        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
7907
7908        if let Some(fold_range) = display_map.foldable_range(buffer_row) {
7909            let autoscroll = self
7910                .selections
7911                .all::<Point>(cx)
7912                .iter()
7913                .any(|selection| fold_range.overlaps(&selection.range()));
7914
7915            self.fold_ranges(std::iter::once(fold_range), autoscroll, cx);
7916        }
7917    }
7918
7919    pub fn unfold_lines(&mut self, _: &UnfoldLines, cx: &mut ViewContext<Self>) {
7920        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
7921        let buffer = &display_map.buffer_snapshot;
7922        let selections = self.selections.all::<Point>(cx);
7923        let ranges = selections
7924            .iter()
7925            .map(|s| {
7926                let range = s.display_range(&display_map).sorted();
7927                let mut start = range.start.to_point(&display_map);
7928                let mut end = range.end.to_point(&display_map);
7929                start.column = 0;
7930                end.column = buffer.line_len(end.row);
7931                start..end
7932            })
7933            .collect::<Vec<_>>();
7934
7935        self.unfold_ranges(ranges, true, true, cx);
7936    }
7937
7938    pub fn unfold_at(&mut self, unfold_at: &UnfoldAt, cx: &mut ViewContext<Self>) {
7939        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
7940
7941        let intersection_range = Point::new(unfold_at.buffer_row, 0)
7942            ..Point::new(
7943                unfold_at.buffer_row,
7944                display_map.buffer_snapshot.line_len(unfold_at.buffer_row),
7945            );
7946
7947        let autoscroll = self
7948            .selections
7949            .all::<Point>(cx)
7950            .iter()
7951            .any(|selection| selection.range().overlaps(&intersection_range));
7952
7953        self.unfold_ranges(std::iter::once(intersection_range), true, autoscroll, cx)
7954    }
7955
7956    pub fn fold_selected_ranges(&mut self, _: &FoldSelectedRanges, cx: &mut ViewContext<Self>) {
7957        let selections = self.selections.all::<Point>(cx);
7958        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
7959        let line_mode = self.selections.line_mode;
7960        let ranges = selections.into_iter().map(|s| {
7961            if line_mode {
7962                let start = Point::new(s.start.row, 0);
7963                let end = Point::new(s.end.row, display_map.buffer_snapshot.line_len(s.end.row));
7964                start..end
7965            } else {
7966                s.start..s.end
7967            }
7968        });
7969        self.fold_ranges(ranges, true, cx);
7970    }
7971
7972    pub fn fold_ranges<T: ToOffset + Clone>(
7973        &mut self,
7974        ranges: impl IntoIterator<Item = Range<T>>,
7975        auto_scroll: bool,
7976        cx: &mut ViewContext<Self>,
7977    ) {
7978        let mut ranges = ranges.into_iter().peekable();
7979        if ranges.peek().is_some() {
7980            self.display_map.update(cx, |map, cx| map.fold(ranges, cx));
7981
7982            if auto_scroll {
7983                self.request_autoscroll(Autoscroll::fit(), cx);
7984            }
7985
7986            cx.notify();
7987        }
7988    }
7989
7990    pub fn unfold_ranges<T: ToOffset + Clone>(
7991        &mut self,
7992        ranges: impl IntoIterator<Item = Range<T>>,
7993        inclusive: bool,
7994        auto_scroll: bool,
7995        cx: &mut ViewContext<Self>,
7996    ) {
7997        let mut ranges = ranges.into_iter().peekable();
7998        if ranges.peek().is_some() {
7999            self.display_map
8000                .update(cx, |map, cx| map.unfold(ranges, inclusive, cx));
8001            if auto_scroll {
8002                self.request_autoscroll(Autoscroll::fit(), cx);
8003            }
8004
8005            cx.notify();
8006        }
8007    }
8008
8009    pub fn set_gutter_hovered(&mut self, hovered: bool, cx: &mut ViewContext<Self>) {
8010        if hovered != self.gutter_hovered {
8011            self.gutter_hovered = hovered;
8012            cx.notify();
8013        }
8014    }
8015
8016    pub fn insert_blocks(
8017        &mut self,
8018        blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
8019        autoscroll: Option<Autoscroll>,
8020        cx: &mut ViewContext<Self>,
8021    ) -> Vec<BlockId> {
8022        let blocks = self
8023            .display_map
8024            .update(cx, |display_map, cx| display_map.insert_blocks(blocks, cx));
8025        if let Some(autoscroll) = autoscroll {
8026            self.request_autoscroll(autoscroll, cx);
8027        }
8028        blocks
8029    }
8030
8031    pub fn replace_blocks(
8032        &mut self,
8033        blocks: HashMap<BlockId, RenderBlock>,
8034        autoscroll: Option<Autoscroll>,
8035        cx: &mut ViewContext<Self>,
8036    ) {
8037        self.display_map
8038            .update(cx, |display_map, _| display_map.replace_blocks(blocks));
8039        if let Some(autoscroll) = autoscroll {
8040            self.request_autoscroll(autoscroll, cx);
8041        }
8042    }
8043
8044    pub fn remove_blocks(
8045        &mut self,
8046        block_ids: HashSet<BlockId>,
8047        autoscroll: Option<Autoscroll>,
8048        cx: &mut ViewContext<Self>,
8049    ) {
8050        self.display_map.update(cx, |display_map, cx| {
8051            display_map.remove_blocks(block_ids, cx)
8052        });
8053        if let Some(autoscroll) = autoscroll {
8054            self.request_autoscroll(autoscroll, cx);
8055        }
8056    }
8057
8058    pub fn longest_row(&self, cx: &mut AppContext) -> u32 {
8059        self.display_map
8060            .update(cx, |map, cx| map.snapshot(cx))
8061            .longest_row()
8062    }
8063
8064    pub fn max_point(&self, cx: &mut AppContext) -> DisplayPoint {
8065        self.display_map
8066            .update(cx, |map, cx| map.snapshot(cx))
8067            .max_point()
8068    }
8069
8070    pub fn text(&self, cx: &AppContext) -> String {
8071        self.buffer.read(cx).read(cx).text()
8072    }
8073
8074    pub fn text_option(&self, cx: &AppContext) -> Option<String> {
8075        let text = self.text(cx);
8076        let text = text.trim();
8077
8078        if text.is_empty() {
8079            return None;
8080        }
8081
8082        Some(text.to_string())
8083    }
8084
8085    pub fn set_text(&mut self, text: impl Into<Arc<str>>, cx: &mut ViewContext<Self>) {
8086        self.transact(cx, |this, cx| {
8087            this.buffer
8088                .read(cx)
8089                .as_singleton()
8090                .expect("you can only call set_text on editors for singleton buffers")
8091                .update(cx, |buffer, cx| buffer.set_text(text, cx));
8092        });
8093    }
8094
8095    pub fn display_text(&self, cx: &mut AppContext) -> String {
8096        self.display_map
8097            .update(cx, |map, cx| map.snapshot(cx))
8098            .text()
8099    }
8100
8101    pub fn wrap_guides(&self, cx: &AppContext) -> SmallVec<[(usize, bool); 2]> {
8102        let mut wrap_guides = smallvec::smallvec![];
8103
8104        if self.show_wrap_guides == Some(false) {
8105            return wrap_guides;
8106        }
8107
8108        let settings = self.buffer.read(cx).settings_at(0, cx);
8109        if settings.show_wrap_guides {
8110            if let SoftWrap::Column(soft_wrap) = self.soft_wrap_mode(cx) {
8111                wrap_guides.push((soft_wrap as usize, true));
8112            }
8113            wrap_guides.extend(settings.wrap_guides.iter().map(|guide| (*guide, false)))
8114        }
8115
8116        wrap_guides
8117    }
8118
8119    pub fn soft_wrap_mode(&self, cx: &AppContext) -> SoftWrap {
8120        let settings = self.buffer.read(cx).settings_at(0, cx);
8121        let mode = self
8122            .soft_wrap_mode_override
8123            .unwrap_or_else(|| settings.soft_wrap);
8124        match mode {
8125            language_settings::SoftWrap::None => SoftWrap::None,
8126            language_settings::SoftWrap::EditorWidth => SoftWrap::EditorWidth,
8127            language_settings::SoftWrap::PreferredLineLength => {
8128                SoftWrap::Column(settings.preferred_line_length)
8129            }
8130        }
8131    }
8132
8133    pub fn set_soft_wrap_mode(
8134        &mut self,
8135        mode: language_settings::SoftWrap,
8136        cx: &mut ViewContext<Self>,
8137    ) {
8138        self.soft_wrap_mode_override = Some(mode);
8139        cx.notify();
8140    }
8141
8142    pub fn set_style(&mut self, style: EditorStyle, cx: &mut ViewContext<Self>) {
8143        let rem_size = cx.rem_size();
8144        self.display_map.update(cx, |map, cx| {
8145            map.set_font(
8146                style.text.font(),
8147                style.text.font_size.to_pixels(rem_size),
8148                cx,
8149            )
8150        });
8151        self.style = Some(style);
8152    }
8153
8154    #[cfg(any(test, feature = "test-support"))]
8155    pub fn style(&self) -> Option<&EditorStyle> {
8156        self.style.as_ref()
8157    }
8158
8159    // Called by the element. This method is not designed to be called outside of the editor
8160    // element's layout code because it does not notify when rewrapping is computed synchronously.
8161    pub(crate) fn set_wrap_width(&self, width: Option<Pixels>, cx: &mut AppContext) -> bool {
8162        self.display_map
8163            .update(cx, |map, cx| map.set_wrap_width(width, cx))
8164    }
8165
8166    pub fn toggle_soft_wrap(&mut self, _: &ToggleSoftWrap, cx: &mut ViewContext<Self>) {
8167        if self.soft_wrap_mode_override.is_some() {
8168            self.soft_wrap_mode_override.take();
8169        } else {
8170            let soft_wrap = match self.soft_wrap_mode(cx) {
8171                SoftWrap::None => language_settings::SoftWrap::EditorWidth,
8172                SoftWrap::EditorWidth | SoftWrap::Column(_) => language_settings::SoftWrap::None,
8173            };
8174            self.soft_wrap_mode_override = Some(soft_wrap);
8175        }
8176        cx.notify();
8177    }
8178
8179    pub fn set_show_gutter(&mut self, show_gutter: bool, cx: &mut ViewContext<Self>) {
8180        self.show_gutter = show_gutter;
8181        cx.notify();
8182    }
8183
8184    pub fn set_show_wrap_guides(&mut self, show_gutter: bool, cx: &mut ViewContext<Self>) {
8185        self.show_wrap_guides = Some(show_gutter);
8186        cx.notify();
8187    }
8188
8189    pub fn reveal_in_finder(&mut self, _: &RevealInFinder, cx: &mut ViewContext<Self>) {
8190        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
8191            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
8192                cx.reveal_path(&file.abs_path(cx));
8193            }
8194        }
8195    }
8196
8197    pub fn copy_path(&mut self, _: &CopyPath, cx: &mut ViewContext<Self>) {
8198        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
8199            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
8200                if let Some(path) = file.abs_path(cx).to_str() {
8201                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
8202                }
8203            }
8204        }
8205    }
8206
8207    pub fn copy_relative_path(&mut self, _: &CopyRelativePath, cx: &mut ViewContext<Self>) {
8208        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
8209            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
8210                if let Some(path) = file.path().to_str() {
8211                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
8212                }
8213            }
8214        }
8215    }
8216
8217    pub fn highlight_rows(&mut self, rows: Option<Range<u32>>) {
8218        self.highlighted_rows = rows;
8219    }
8220
8221    pub fn highlighted_rows(&self) -> Option<Range<u32>> {
8222        self.highlighted_rows.clone()
8223    }
8224
8225    pub fn highlight_background<T: 'static>(
8226        &mut self,
8227        ranges: Vec<Range<Anchor>>,
8228        color_fetcher: fn(&ThemeColors) -> Hsla,
8229        cx: &mut ViewContext<Self>,
8230    ) {
8231        self.background_highlights
8232            .insert(TypeId::of::<T>(), (color_fetcher, ranges));
8233        cx.notify();
8234    }
8235
8236    pub(crate) fn highlight_inlay_background<T: 'static>(
8237        &mut self,
8238        ranges: Vec<InlayHighlight>,
8239        color_fetcher: fn(&ThemeColors) -> Hsla,
8240        cx: &mut ViewContext<Self>,
8241    ) {
8242        // TODO: no actual highlights happen for inlays currently, find a way to do that
8243        self.inlay_background_highlights
8244            .insert(Some(TypeId::of::<T>()), (color_fetcher, ranges));
8245        cx.notify();
8246    }
8247
8248    pub fn clear_background_highlights<T: 'static>(
8249        &mut self,
8250        cx: &mut ViewContext<Self>,
8251    ) -> Option<BackgroundHighlight> {
8252        let text_highlights = self.background_highlights.remove(&TypeId::of::<T>());
8253        let inlay_highlights = self
8254            .inlay_background_highlights
8255            .remove(&Some(TypeId::of::<T>()));
8256        if text_highlights.is_some() || inlay_highlights.is_some() {
8257            cx.notify();
8258        }
8259        text_highlights
8260    }
8261
8262    #[cfg(feature = "test-support")]
8263    pub fn all_text_background_highlights(
8264        &mut self,
8265        cx: &mut ViewContext<Self>,
8266    ) -> Vec<(Range<DisplayPoint>, Hsla)> {
8267        let snapshot = self.snapshot(cx);
8268        let buffer = &snapshot.buffer_snapshot;
8269        let start = buffer.anchor_before(0);
8270        let end = buffer.anchor_after(buffer.len());
8271        let theme = cx.theme().colors();
8272        self.background_highlights_in_range(start..end, &snapshot, theme)
8273    }
8274
8275    fn document_highlights_for_position<'a>(
8276        &'a self,
8277        position: Anchor,
8278        buffer: &'a MultiBufferSnapshot,
8279    ) -> impl 'a + Iterator<Item = &Range<Anchor>> {
8280        let read_highlights = self
8281            .background_highlights
8282            .get(&TypeId::of::<DocumentHighlightRead>())
8283            .map(|h| &h.1);
8284        let write_highlights = self
8285            .background_highlights
8286            .get(&TypeId::of::<DocumentHighlightWrite>())
8287            .map(|h| &h.1);
8288        let left_position = position.bias_left(buffer);
8289        let right_position = position.bias_right(buffer);
8290        read_highlights
8291            .into_iter()
8292            .chain(write_highlights)
8293            .flat_map(move |ranges| {
8294                let start_ix = match ranges.binary_search_by(|probe| {
8295                    let cmp = probe.end.cmp(&left_position, buffer);
8296                    if cmp.is_ge() {
8297                        Ordering::Greater
8298                    } else {
8299                        Ordering::Less
8300                    }
8301                }) {
8302                    Ok(i) | Err(i) => i,
8303                };
8304
8305                let right_position = right_position.clone();
8306                ranges[start_ix..]
8307                    .iter()
8308                    .take_while(move |range| range.start.cmp(&right_position, buffer).is_le())
8309            })
8310    }
8311
8312    pub fn has_background_highlights<T: 'static>(&self) -> bool {
8313        self.background_highlights
8314            .get(&TypeId::of::<T>())
8315            .map_or(false, |(_, highlights)| !highlights.is_empty())
8316    }
8317
8318    pub fn background_highlights_in_range(
8319        &self,
8320        search_range: Range<Anchor>,
8321        display_snapshot: &DisplaySnapshot,
8322        theme: &ThemeColors,
8323    ) -> Vec<(Range<DisplayPoint>, Hsla)> {
8324        let mut results = Vec::new();
8325        for (color_fetcher, ranges) in self.background_highlights.values() {
8326            let color = color_fetcher(theme);
8327            let start_ix = match ranges.binary_search_by(|probe| {
8328                let cmp = probe
8329                    .end
8330                    .cmp(&search_range.start, &display_snapshot.buffer_snapshot);
8331                if cmp.is_gt() {
8332                    Ordering::Greater
8333                } else {
8334                    Ordering::Less
8335                }
8336            }) {
8337                Ok(i) | Err(i) => i,
8338            };
8339            for range in &ranges[start_ix..] {
8340                if range
8341                    .start
8342                    .cmp(&search_range.end, &display_snapshot.buffer_snapshot)
8343                    .is_ge()
8344                {
8345                    break;
8346                }
8347
8348                let start = range.start.to_display_point(&display_snapshot);
8349                let end = range.end.to_display_point(&display_snapshot);
8350                results.push((start..end, color))
8351            }
8352        }
8353        results
8354    }
8355
8356    pub fn background_highlight_row_ranges<T: 'static>(
8357        &self,
8358        search_range: Range<Anchor>,
8359        display_snapshot: &DisplaySnapshot,
8360        count: usize,
8361    ) -> Vec<RangeInclusive<DisplayPoint>> {
8362        let mut results = Vec::new();
8363        let Some((_, ranges)) = self.background_highlights.get(&TypeId::of::<T>()) else {
8364            return vec![];
8365        };
8366
8367        let start_ix = match ranges.binary_search_by(|probe| {
8368            let cmp = probe
8369                .end
8370                .cmp(&search_range.start, &display_snapshot.buffer_snapshot);
8371            if cmp.is_gt() {
8372                Ordering::Greater
8373            } else {
8374                Ordering::Less
8375            }
8376        }) {
8377            Ok(i) | Err(i) => i,
8378        };
8379        let mut push_region = |start: Option<Point>, end: Option<Point>| {
8380            if let (Some(start_display), Some(end_display)) = (start, end) {
8381                results.push(
8382                    start_display.to_display_point(display_snapshot)
8383                        ..=end_display.to_display_point(display_snapshot),
8384                );
8385            }
8386        };
8387        let mut start_row: Option<Point> = None;
8388        let mut end_row: Option<Point> = None;
8389        if ranges.len() > count {
8390            return Vec::new();
8391        }
8392        for range in &ranges[start_ix..] {
8393            if range
8394                .start
8395                .cmp(&search_range.end, &display_snapshot.buffer_snapshot)
8396                .is_ge()
8397            {
8398                break;
8399            }
8400            let end = range.end.to_point(&display_snapshot.buffer_snapshot);
8401            if let Some(current_row) = &end_row {
8402                if end.row == current_row.row {
8403                    continue;
8404                }
8405            }
8406            let start = range.start.to_point(&display_snapshot.buffer_snapshot);
8407            if start_row.is_none() {
8408                assert_eq!(end_row, None);
8409                start_row = Some(start);
8410                end_row = Some(end);
8411                continue;
8412            }
8413            if let Some(current_end) = end_row.as_mut() {
8414                if start.row > current_end.row + 1 {
8415                    push_region(start_row, end_row);
8416                    start_row = Some(start);
8417                    end_row = Some(end);
8418                } else {
8419                    // Merge two hunks.
8420                    *current_end = end;
8421                }
8422            } else {
8423                unreachable!();
8424            }
8425        }
8426        // We might still have a hunk that was not rendered (if there was a search hit on the last line)
8427        push_region(start_row, end_row);
8428        results
8429    }
8430
8431    pub fn highlight_text<T: 'static>(
8432        &mut self,
8433        ranges: Vec<Range<Anchor>>,
8434        style: HighlightStyle,
8435        cx: &mut ViewContext<Self>,
8436    ) {
8437        self.display_map.update(cx, |map, _| {
8438            map.highlight_text(TypeId::of::<T>(), ranges, style)
8439        });
8440        cx.notify();
8441    }
8442
8443    pub(crate) fn highlight_inlays<T: 'static>(
8444        &mut self,
8445        highlights: Vec<InlayHighlight>,
8446        style: HighlightStyle,
8447        cx: &mut ViewContext<Self>,
8448    ) {
8449        self.display_map.update(cx, |map, _| {
8450            map.highlight_inlays(TypeId::of::<T>(), highlights, style)
8451        });
8452        cx.notify();
8453    }
8454
8455    pub fn text_highlights<'a, T: 'static>(
8456        &'a self,
8457        cx: &'a AppContext,
8458    ) -> Option<(HighlightStyle, &'a [Range<Anchor>])> {
8459        self.display_map.read(cx).text_highlights(TypeId::of::<T>())
8460    }
8461
8462    pub fn clear_highlights<T: 'static>(&mut self, cx: &mut ViewContext<Self>) {
8463        let cleared = self
8464            .display_map
8465            .update(cx, |map, _| map.clear_highlights(TypeId::of::<T>()));
8466        if cleared {
8467            cx.notify();
8468        }
8469    }
8470
8471    pub fn show_local_cursors(&self, cx: &WindowContext) -> bool {
8472        (self.read_only(cx) || self.blink_manager.read(cx).visible())
8473            && self.focus_handle.is_focused(cx)
8474    }
8475
8476    fn on_buffer_changed(&mut self, _: Model<MultiBuffer>, cx: &mut ViewContext<Self>) {
8477        cx.notify();
8478    }
8479
8480    fn on_buffer_event(
8481        &mut self,
8482        multibuffer: Model<MultiBuffer>,
8483        event: &multi_buffer::Event,
8484        cx: &mut ViewContext<Self>,
8485    ) {
8486        match event {
8487            multi_buffer::Event::Edited {
8488                singleton_buffer_edited,
8489            } => {
8490                self.refresh_active_diagnostics(cx);
8491                self.refresh_code_actions(cx);
8492                if self.has_active_copilot_suggestion(cx) {
8493                    self.update_visible_copilot_suggestion(cx);
8494                }
8495                cx.emit(EditorEvent::BufferEdited);
8496                cx.emit(SearchEvent::MatchesInvalidated);
8497
8498                if *singleton_buffer_edited {
8499                    if let Some(project) = &self.project {
8500                        let project = project.read(cx);
8501                        let languages_affected = multibuffer
8502                            .read(cx)
8503                            .all_buffers()
8504                            .into_iter()
8505                            .filter_map(|buffer| {
8506                                let buffer = buffer.read(cx);
8507                                let language = buffer.language()?;
8508                                if project.is_local()
8509                                    && project.language_servers_for_buffer(buffer, cx).count() == 0
8510                                {
8511                                    None
8512                                } else {
8513                                    Some(language)
8514                                }
8515                            })
8516                            .cloned()
8517                            .collect::<HashSet<_>>();
8518                        if !languages_affected.is_empty() {
8519                            self.refresh_inlay_hints(
8520                                InlayHintRefreshReason::BufferEdited(languages_affected),
8521                                cx,
8522                            );
8523                        }
8524                    }
8525                }
8526
8527                let Some(project) = &self.project else { return };
8528                let telemetry = project.read(cx).client().telemetry().clone();
8529                telemetry.log_edit_event("editor");
8530            }
8531            multi_buffer::Event::ExcerptsAdded {
8532                buffer,
8533                predecessor,
8534                excerpts,
8535            } => {
8536                cx.emit(EditorEvent::ExcerptsAdded {
8537                    buffer: buffer.clone(),
8538                    predecessor: *predecessor,
8539                    excerpts: excerpts.clone(),
8540                });
8541                self.refresh_inlay_hints(InlayHintRefreshReason::NewLinesShown, cx);
8542            }
8543            multi_buffer::Event::ExcerptsRemoved { ids } => {
8544                self.refresh_inlay_hints(InlayHintRefreshReason::ExcerptsRemoved(ids.clone()), cx);
8545                cx.emit(EditorEvent::ExcerptsRemoved { ids: ids.clone() })
8546            }
8547            multi_buffer::Event::Reparsed => cx.emit(EditorEvent::Reparsed),
8548            multi_buffer::Event::DirtyChanged => cx.emit(EditorEvent::DirtyChanged),
8549            multi_buffer::Event::Saved => cx.emit(EditorEvent::Saved),
8550            multi_buffer::Event::FileHandleChanged | multi_buffer::Event::Reloaded => {
8551                cx.emit(EditorEvent::TitleChanged)
8552            }
8553            multi_buffer::Event::DiffBaseChanged => cx.emit(EditorEvent::DiffBaseChanged),
8554            multi_buffer::Event::Closed => cx.emit(EditorEvent::Closed),
8555            multi_buffer::Event::DiagnosticsUpdated => {
8556                self.refresh_active_diagnostics(cx);
8557            }
8558            _ => {}
8559        };
8560    }
8561
8562    fn on_display_map_changed(&mut self, _: Model<DisplayMap>, cx: &mut ViewContext<Self>) {
8563        cx.notify();
8564    }
8565
8566    fn settings_changed(&mut self, cx: &mut ViewContext<Self>) {
8567        self.refresh_copilot_suggestions(true, cx);
8568        self.refresh_inlay_hints(
8569            InlayHintRefreshReason::SettingsChange(inlay_hint_settings(
8570                self.selections.newest_anchor().head(),
8571                &self.buffer.read(cx).snapshot(cx),
8572                cx,
8573            )),
8574            cx,
8575        );
8576        cx.notify();
8577    }
8578
8579    pub fn set_searchable(&mut self, searchable: bool) {
8580        self.searchable = searchable;
8581    }
8582
8583    pub fn searchable(&self) -> bool {
8584        self.searchable
8585    }
8586
8587    fn open_excerpts(&mut self, _: &OpenExcerpts, cx: &mut ViewContext<Self>) {
8588        let buffer = self.buffer.read(cx);
8589        if buffer.is_singleton() {
8590            cx.propagate();
8591            return;
8592        }
8593
8594        let Some(workspace) = self.workspace() else {
8595            cx.propagate();
8596            return;
8597        };
8598
8599        let mut new_selections_by_buffer = HashMap::default();
8600        for selection in self.selections.all::<usize>(cx) {
8601            for (buffer, mut range, _) in
8602                buffer.range_to_buffer_ranges(selection.start..selection.end, cx)
8603            {
8604                if selection.reversed {
8605                    mem::swap(&mut range.start, &mut range.end);
8606                }
8607                new_selections_by_buffer
8608                    .entry(buffer)
8609                    .or_insert(Vec::new())
8610                    .push(range)
8611            }
8612        }
8613
8614        self.push_to_nav_history(self.selections.newest_anchor().head(), None, cx);
8615
8616        // We defer the pane interaction because we ourselves are a workspace item
8617        // and activating a new item causes the pane to call a method on us reentrantly,
8618        // which panics if we're on the stack.
8619        cx.window_context().defer(move |cx| {
8620            workspace.update(cx, |workspace, cx| {
8621                let pane = workspace.active_pane().clone();
8622                pane.update(cx, |pane, _| pane.disable_history());
8623
8624                for (buffer, ranges) in new_selections_by_buffer.into_iter() {
8625                    let editor = workspace.open_project_item::<Self>(buffer, cx);
8626                    editor.update(cx, |editor, cx| {
8627                        editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
8628                            s.select_ranges(ranges);
8629                        });
8630                    });
8631                }
8632
8633                pane.update(cx, |pane, _| pane.enable_history());
8634            })
8635        });
8636    }
8637
8638    fn jump(
8639        &mut self,
8640        path: ProjectPath,
8641        position: Point,
8642        anchor: language::Anchor,
8643        cx: &mut ViewContext<Self>,
8644    ) {
8645        let workspace = self.workspace();
8646        cx.spawn(|_, mut cx| async move {
8647            let workspace = workspace.ok_or_else(|| anyhow!("cannot jump without workspace"))?;
8648            let editor = workspace.update(&mut cx, |workspace, cx| {
8649                workspace.open_path(path, None, true, cx)
8650            })?;
8651            let editor = editor
8652                .await?
8653                .downcast::<Editor>()
8654                .ok_or_else(|| anyhow!("opened item was not an editor"))?
8655                .downgrade();
8656            editor.update(&mut cx, |editor, cx| {
8657                let buffer = editor
8658                    .buffer()
8659                    .read(cx)
8660                    .as_singleton()
8661                    .ok_or_else(|| anyhow!("cannot jump in a multi-buffer"))?;
8662                let buffer = buffer.read(cx);
8663                let cursor = if buffer.can_resolve(&anchor) {
8664                    language::ToPoint::to_point(&anchor, buffer)
8665                } else {
8666                    buffer.clip_point(position, Bias::Left)
8667                };
8668
8669                let nav_history = editor.nav_history.take();
8670                editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
8671                    s.select_ranges([cursor..cursor]);
8672                });
8673                editor.nav_history = nav_history;
8674
8675                anyhow::Ok(())
8676            })??;
8677
8678            anyhow::Ok(())
8679        })
8680        .detach_and_log_err(cx);
8681    }
8682
8683    fn marked_text_ranges(&self, cx: &AppContext) -> Option<Vec<Range<OffsetUtf16>>> {
8684        let snapshot = self.buffer.read(cx).read(cx);
8685        let (_, ranges) = self.text_highlights::<InputComposition>(cx)?;
8686        Some(
8687            ranges
8688                .iter()
8689                .map(move |range| {
8690                    range.start.to_offset_utf16(&snapshot)..range.end.to_offset_utf16(&snapshot)
8691                })
8692                .collect(),
8693        )
8694    }
8695
8696    fn selection_replacement_ranges(
8697        &self,
8698        range: Range<OffsetUtf16>,
8699        cx: &AppContext,
8700    ) -> Vec<Range<OffsetUtf16>> {
8701        let selections = self.selections.all::<OffsetUtf16>(cx);
8702        let newest_selection = selections
8703            .iter()
8704            .max_by_key(|selection| selection.id)
8705            .unwrap();
8706        let start_delta = range.start.0 as isize - newest_selection.start.0 as isize;
8707        let end_delta = range.end.0 as isize - newest_selection.end.0 as isize;
8708        let snapshot = self.buffer.read(cx).read(cx);
8709        selections
8710            .into_iter()
8711            .map(|mut selection| {
8712                selection.start.0 =
8713                    (selection.start.0 as isize).saturating_add(start_delta) as usize;
8714                selection.end.0 = (selection.end.0 as isize).saturating_add(end_delta) as usize;
8715                snapshot.clip_offset_utf16(selection.start, Bias::Left)
8716                    ..snapshot.clip_offset_utf16(selection.end, Bias::Right)
8717            })
8718            .collect()
8719    }
8720
8721    fn report_copilot_event(
8722        &self,
8723        suggestion_id: Option<String>,
8724        suggestion_accepted: bool,
8725        cx: &AppContext,
8726    ) {
8727        let Some(project) = &self.project else { return };
8728
8729        // If None, we are either getting suggestions in a new, unsaved file, or in a file without an extension
8730        let file_extension = self
8731            .buffer
8732            .read(cx)
8733            .as_singleton()
8734            .and_then(|b| b.read(cx).file())
8735            .and_then(|file| Path::new(file.file_name(cx)).extension())
8736            .and_then(|e| e.to_str())
8737            .map(|a| a.to_string());
8738
8739        let telemetry = project.read(cx).client().telemetry().clone();
8740
8741        telemetry.report_copilot_event(suggestion_id, suggestion_accepted, file_extension)
8742    }
8743
8744    #[cfg(any(test, feature = "test-support"))]
8745    fn report_editor_event(
8746        &self,
8747        _operation: &'static str,
8748        _file_extension: Option<String>,
8749        _cx: &AppContext,
8750    ) {
8751    }
8752
8753    #[cfg(not(any(test, feature = "test-support")))]
8754    fn report_editor_event(
8755        &self,
8756        operation: &'static str,
8757        file_extension: Option<String>,
8758        cx: &AppContext,
8759    ) {
8760        let Some(project) = &self.project else { return };
8761
8762        // If None, we are in a file without an extension
8763        let file = self
8764            .buffer
8765            .read(cx)
8766            .as_singleton()
8767            .and_then(|b| b.read(cx).file());
8768        let file_extension = file_extension.or(file
8769            .as_ref()
8770            .and_then(|file| Path::new(file.file_name(cx)).extension())
8771            .and_then(|e| e.to_str())
8772            .map(|a| a.to_string()));
8773
8774        let vim_mode = cx
8775            .global::<SettingsStore>()
8776            .raw_user_settings()
8777            .get("vim_mode")
8778            == Some(&serde_json::Value::Bool(true));
8779        let copilot_enabled = all_language_settings(file, cx).copilot_enabled(None, None);
8780        let copilot_enabled_for_language = self
8781            .buffer
8782            .read(cx)
8783            .settings_at(0, cx)
8784            .show_copilot_suggestions;
8785
8786        let telemetry = project.read(cx).client().telemetry().clone();
8787        telemetry.report_editor_event(
8788            file_extension,
8789            vim_mode,
8790            operation,
8791            copilot_enabled,
8792            copilot_enabled_for_language,
8793        )
8794    }
8795
8796    /// Copy the highlighted chunks to the clipboard as JSON. The format is an array of lines,
8797    /// with each line being an array of {text, highlight} objects.
8798    fn copy_highlight_json(&mut self, _: &CopyHighlightJson, cx: &mut ViewContext<Self>) {
8799        let Some(buffer) = self.buffer.read(cx).as_singleton() else {
8800            return;
8801        };
8802
8803        #[derive(Serialize)]
8804        struct Chunk<'a> {
8805            text: String,
8806            highlight: Option<&'a str>,
8807        }
8808
8809        let snapshot = buffer.read(cx).snapshot();
8810        let range = self
8811            .selected_text_range(cx)
8812            .and_then(|selected_range| {
8813                if selected_range.is_empty() {
8814                    None
8815                } else {
8816                    Some(selected_range)
8817                }
8818            })
8819            .unwrap_or_else(|| 0..snapshot.len());
8820
8821        let chunks = snapshot.chunks(range, true);
8822        let mut lines = Vec::new();
8823        let mut line: VecDeque<Chunk> = VecDeque::new();
8824
8825        let Some(style) = self.style.as_ref() else {
8826            return;
8827        };
8828
8829        for chunk in chunks {
8830            let highlight = chunk
8831                .syntax_highlight_id
8832                .and_then(|id| id.name(&style.syntax));
8833            let mut chunk_lines = chunk.text.split("\n").peekable();
8834            while let Some(text) = chunk_lines.next() {
8835                let mut merged_with_last_token = false;
8836                if let Some(last_token) = line.back_mut() {
8837                    if last_token.highlight == highlight {
8838                        last_token.text.push_str(text);
8839                        merged_with_last_token = true;
8840                    }
8841                }
8842
8843                if !merged_with_last_token {
8844                    line.push_back(Chunk {
8845                        text: text.into(),
8846                        highlight,
8847                    });
8848                }
8849
8850                if chunk_lines.peek().is_some() {
8851                    if line.len() > 1 && line.front().unwrap().text.is_empty() {
8852                        line.pop_front();
8853                    }
8854                    if line.len() > 1 && line.back().unwrap().text.is_empty() {
8855                        line.pop_back();
8856                    }
8857
8858                    lines.push(mem::take(&mut line));
8859                }
8860            }
8861        }
8862
8863        let Some(lines) = serde_json::to_string_pretty(&lines).log_err() else {
8864            return;
8865        };
8866        cx.write_to_clipboard(ClipboardItem::new(lines));
8867    }
8868
8869    pub fn inlay_hint_cache(&self) -> &InlayHintCache {
8870        &self.inlay_hint_cache
8871    }
8872
8873    pub fn replay_insert_event(
8874        &mut self,
8875        text: &str,
8876        relative_utf16_range: Option<Range<isize>>,
8877        cx: &mut ViewContext<Self>,
8878    ) {
8879        if !self.input_enabled {
8880            cx.emit(EditorEvent::InputIgnored { text: text.into() });
8881            return;
8882        }
8883        if let Some(relative_utf16_range) = relative_utf16_range {
8884            let selections = self.selections.all::<OffsetUtf16>(cx);
8885            self.change_selections(None, cx, |s| {
8886                let new_ranges = selections.into_iter().map(|range| {
8887                    let start = OffsetUtf16(
8888                        range
8889                            .head()
8890                            .0
8891                            .saturating_add_signed(relative_utf16_range.start),
8892                    );
8893                    let end = OffsetUtf16(
8894                        range
8895                            .head()
8896                            .0
8897                            .saturating_add_signed(relative_utf16_range.end),
8898                    );
8899                    start..end
8900                });
8901                s.select_ranges(new_ranges);
8902            });
8903        }
8904
8905        self.handle_input(text, cx);
8906    }
8907
8908    pub fn supports_inlay_hints(&self, cx: &AppContext) -> bool {
8909        let Some(project) = self.project.as_ref() else {
8910            return false;
8911        };
8912        let project = project.read(cx);
8913
8914        let mut supports = false;
8915        self.buffer().read(cx).for_each_buffer(|buffer| {
8916            if !supports {
8917                supports = project
8918                    .language_servers_for_buffer(buffer.read(cx), cx)
8919                    .any(
8920                        |(_, server)| match server.capabilities().inlay_hint_provider {
8921                            Some(lsp::OneOf::Left(enabled)) => enabled,
8922                            Some(lsp::OneOf::Right(_)) => true,
8923                            None => false,
8924                        },
8925                    )
8926            }
8927        });
8928        supports
8929    }
8930
8931    pub fn focus(&self, cx: &mut WindowContext) {
8932        cx.focus(&self.focus_handle)
8933    }
8934
8935    pub fn is_focused(&self, cx: &WindowContext) -> bool {
8936        self.focus_handle.is_focused(cx)
8937    }
8938
8939    fn handle_focus(&mut self, cx: &mut ViewContext<Self>) {
8940        cx.emit(EditorEvent::Focused);
8941
8942        if let Some(rename) = self.pending_rename.as_ref() {
8943            let rename_editor_focus_handle = rename.editor.read(cx).focus_handle.clone();
8944            cx.focus(&rename_editor_focus_handle);
8945        } else {
8946            self.blink_manager.update(cx, BlinkManager::enable);
8947            self.show_cursor_names(cx);
8948            self.buffer.update(cx, |buffer, cx| {
8949                buffer.finalize_last_transaction(cx);
8950                if self.leader_peer_id.is_none() {
8951                    buffer.set_active_selections(
8952                        &self.selections.disjoint_anchors(),
8953                        self.selections.line_mode,
8954                        self.cursor_shape,
8955                        cx,
8956                    );
8957                }
8958            });
8959        }
8960    }
8961
8962    pub fn handle_blur(&mut self, cx: &mut ViewContext<Self>) {
8963        self.blink_manager.update(cx, BlinkManager::disable);
8964        self.buffer
8965            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
8966        self.hide_context_menu(cx);
8967        hide_hover(self, cx);
8968        cx.emit(EditorEvent::Blurred);
8969        cx.notify();
8970    }
8971
8972    pub fn register_action<A: Action>(
8973        &mut self,
8974        listener: impl Fn(&A, &mut WindowContext) + 'static,
8975    ) -> &mut Self {
8976        let listener = Arc::new(listener);
8977
8978        self.editor_actions.push(Box::new(move |cx| {
8979            let _view = cx.view().clone();
8980            let cx = cx.window_context();
8981            let listener = listener.clone();
8982            cx.on_action(TypeId::of::<A>(), move |action, phase, cx| {
8983                let action = action.downcast_ref().unwrap();
8984                if phase == DispatchPhase::Bubble {
8985                    listener(action, cx)
8986                }
8987            })
8988        }));
8989        self
8990    }
8991}
8992
8993pub trait CollaborationHub {
8994    fn collaborators<'a>(&self, cx: &'a AppContext) -> &'a HashMap<PeerId, Collaborator>;
8995    fn user_participant_indices<'a>(
8996        &self,
8997        cx: &'a AppContext,
8998    ) -> &'a HashMap<u64, ParticipantIndex>;
8999    fn user_names(&self, cx: &AppContext) -> HashMap<u64, SharedString>;
9000}
9001
9002impl CollaborationHub for Model<Project> {
9003    fn collaborators<'a>(&self, cx: &'a AppContext) -> &'a HashMap<PeerId, Collaborator> {
9004        self.read(cx).collaborators()
9005    }
9006
9007    fn user_participant_indices<'a>(
9008        &self,
9009        cx: &'a AppContext,
9010    ) -> &'a HashMap<u64, ParticipantIndex> {
9011        self.read(cx).user_store().read(cx).participant_indices()
9012    }
9013
9014    fn user_names(&self, cx: &AppContext) -> HashMap<u64, SharedString> {
9015        let this = self.read(cx);
9016        let user_ids = this.collaborators().values().map(|c| c.user_id);
9017        this.user_store().read_with(cx, |user_store, cx| {
9018            user_store.participant_names(user_ids, cx)
9019        })
9020    }
9021}
9022
9023pub trait CompletionProvider {
9024    fn completions(
9025        &self,
9026        buffer: &Model<Buffer>,
9027        buffer_position: text::Anchor,
9028        cx: &mut ViewContext<Editor>,
9029    ) -> Task<Result<Vec<Completion>>>;
9030
9031    fn resolve_completions(
9032        &self,
9033        completion_indices: Vec<usize>,
9034        completions: Arc<RwLock<Box<[Completion]>>>,
9035        cx: &mut ViewContext<Editor>,
9036    ) -> Task<Result<bool>>;
9037
9038    fn apply_additional_edits_for_completion(
9039        &self,
9040        buffer: Model<Buffer>,
9041        completion: Completion,
9042        push_to_history: bool,
9043        cx: &mut ViewContext<Editor>,
9044    ) -> Task<Result<Option<language::Transaction>>>;
9045}
9046
9047impl CompletionProvider for Model<Project> {
9048    fn completions(
9049        &self,
9050        buffer: &Model<Buffer>,
9051        buffer_position: text::Anchor,
9052        cx: &mut ViewContext<Editor>,
9053    ) -> Task<Result<Vec<Completion>>> {
9054        self.update(cx, |project, cx| {
9055            project.completions(&buffer, buffer_position, cx)
9056        })
9057    }
9058
9059    fn resolve_completions(
9060        &self,
9061        completion_indices: Vec<usize>,
9062        completions: Arc<RwLock<Box<[Completion]>>>,
9063        cx: &mut ViewContext<Editor>,
9064    ) -> Task<Result<bool>> {
9065        self.update(cx, |project, cx| {
9066            project.resolve_completions(completion_indices, completions, cx)
9067        })
9068    }
9069
9070    fn apply_additional_edits_for_completion(
9071        &self,
9072        buffer: Model<Buffer>,
9073        completion: Completion,
9074        push_to_history: bool,
9075        cx: &mut ViewContext<Editor>,
9076    ) -> Task<Result<Option<language::Transaction>>> {
9077        self.update(cx, |project, cx| {
9078            project.apply_additional_edits_for_completion(buffer, completion, push_to_history, cx)
9079        })
9080    }
9081}
9082
9083fn inlay_hint_settings(
9084    location: Anchor,
9085    snapshot: &MultiBufferSnapshot,
9086    cx: &mut ViewContext<'_, Editor>,
9087) -> InlayHintSettings {
9088    let file = snapshot.file_at(location);
9089    let language = snapshot.language_at(location);
9090    let settings = all_language_settings(file, cx);
9091    settings
9092        .language(language.map(|l| l.name()).as_deref())
9093        .inlay_hints
9094}
9095
9096fn consume_contiguous_rows(
9097    contiguous_row_selections: &mut Vec<Selection<Point>>,
9098    selection: &Selection<Point>,
9099    display_map: &DisplaySnapshot,
9100    selections: &mut std::iter::Peekable<std::slice::Iter<Selection<Point>>>,
9101) -> (u32, u32) {
9102    contiguous_row_selections.push(selection.clone());
9103    let start_row = selection.start.row;
9104    let mut end_row = ending_row(selection, display_map);
9105
9106    while let Some(next_selection) = selections.peek() {
9107        if next_selection.start.row <= end_row {
9108            end_row = ending_row(next_selection, display_map);
9109            contiguous_row_selections.push(selections.next().unwrap().clone());
9110        } else {
9111            break;
9112        }
9113    }
9114    (start_row, end_row)
9115}
9116
9117fn ending_row(next_selection: &Selection<Point>, display_map: &DisplaySnapshot) -> u32 {
9118    if next_selection.end.column > 0 || next_selection.is_empty() {
9119        display_map.next_line_boundary(next_selection.end).0.row + 1
9120    } else {
9121        next_selection.end.row
9122    }
9123}
9124
9125impl EditorSnapshot {
9126    pub fn remote_selections_in_range<'a>(
9127        &'a self,
9128        range: &'a Range<Anchor>,
9129        collaboration_hub: &dyn CollaborationHub,
9130        cx: &'a AppContext,
9131    ) -> impl 'a + Iterator<Item = RemoteSelection> {
9132        let participant_names = collaboration_hub.user_names(cx);
9133        let participant_indices = collaboration_hub.user_participant_indices(cx);
9134        let collaborators_by_peer_id = collaboration_hub.collaborators(cx);
9135        let collaborators_by_replica_id = collaborators_by_peer_id
9136            .iter()
9137            .map(|(_, collaborator)| (collaborator.replica_id, collaborator))
9138            .collect::<HashMap<_, _>>();
9139        self.buffer_snapshot
9140            .remote_selections_in_range(range)
9141            .filter_map(move |(replica_id, line_mode, cursor_shape, selection)| {
9142                let collaborator = collaborators_by_replica_id.get(&replica_id)?;
9143                let participant_index = participant_indices.get(&collaborator.user_id).copied();
9144                let user_name = participant_names.get(&collaborator.user_id).cloned();
9145                Some(RemoteSelection {
9146                    replica_id,
9147                    selection,
9148                    cursor_shape,
9149                    line_mode,
9150                    participant_index,
9151                    peer_id: collaborator.peer_id,
9152                    user_name,
9153                })
9154            })
9155    }
9156
9157    pub fn language_at<T: ToOffset>(&self, position: T) -> Option<&Arc<Language>> {
9158        self.display_snapshot.buffer_snapshot.language_at(position)
9159    }
9160
9161    pub fn is_focused(&self) -> bool {
9162        self.is_focused
9163    }
9164
9165    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
9166        self.placeholder_text.as_ref()
9167    }
9168
9169    pub fn scroll_position(&self) -> gpui::Point<f32> {
9170        self.scroll_anchor.scroll_position(&self.display_snapshot)
9171    }
9172
9173    pub fn gutter_dimensions(
9174        &self,
9175        font_id: FontId,
9176        font_size: Pixels,
9177        em_width: Pixels,
9178        max_line_number_width: Pixels,
9179        cx: &AppContext,
9180    ) -> GutterDimensions {
9181        if self.show_gutter {
9182            let descent = cx.text_system().descent(font_id, font_size);
9183            let gutter_padding_factor = 4.0;
9184            let gutter_padding = (em_width * gutter_padding_factor).round();
9185            // Avoid flicker-like gutter resizes when the line number gains another digit and only resize the gutter on files with N*10^5 lines.
9186            let min_width_for_number_on_gutter = em_width * 4.0;
9187            let gutter_width =
9188                max_line_number_width.max(min_width_for_number_on_gutter) + gutter_padding * 2.0;
9189            let gutter_margin = -descent;
9190
9191            GutterDimensions {
9192                padding: gutter_padding,
9193                width: gutter_width,
9194                margin: gutter_margin,
9195            }
9196        } else {
9197            GutterDimensions::default()
9198        }
9199    }
9200}
9201
9202impl Deref for EditorSnapshot {
9203    type Target = DisplaySnapshot;
9204
9205    fn deref(&self) -> &Self::Target {
9206        &self.display_snapshot
9207    }
9208}
9209
9210#[derive(Clone, Debug, PartialEq, Eq)]
9211pub enum EditorEvent {
9212    InputIgnored {
9213        text: Arc<str>,
9214    },
9215    InputHandled {
9216        utf16_range_to_replace: Option<Range<isize>>,
9217        text: Arc<str>,
9218    },
9219    ExcerptsAdded {
9220        buffer: Model<Buffer>,
9221        predecessor: ExcerptId,
9222        excerpts: Vec<(ExcerptId, ExcerptRange<language::Anchor>)>,
9223    },
9224    ExcerptsRemoved {
9225        ids: Vec<ExcerptId>,
9226    },
9227    BufferEdited,
9228    Edited,
9229    Reparsed,
9230    Focused,
9231    Blurred,
9232    DirtyChanged,
9233    Saved,
9234    TitleChanged,
9235    DiffBaseChanged,
9236    SelectionsChanged {
9237        local: bool,
9238    },
9239    ScrollPositionChanged {
9240        local: bool,
9241        autoscroll: bool,
9242    },
9243    Closed,
9244}
9245
9246impl EventEmitter<EditorEvent> for Editor {}
9247
9248impl FocusableView for Editor {
9249    fn focus_handle(&self, _cx: &AppContext) -> FocusHandle {
9250        self.focus_handle.clone()
9251    }
9252}
9253
9254impl Render for Editor {
9255    fn render<'a>(&mut self, cx: &mut ViewContext<'a, Self>) -> impl IntoElement {
9256        let settings = ThemeSettings::get_global(cx);
9257        let text_style = match self.mode {
9258            EditorMode::SingleLine | EditorMode::AutoHeight { .. } => TextStyle {
9259                color: cx.theme().colors().editor_foreground,
9260                font_family: settings.ui_font.family.clone(),
9261                font_features: settings.ui_font.features,
9262                font_size: rems(0.875).into(),
9263                font_weight: FontWeight::NORMAL,
9264                font_style: FontStyle::Normal,
9265                line_height: relative(settings.buffer_line_height.value()),
9266                background_color: None,
9267                underline: None,
9268                white_space: WhiteSpace::Normal,
9269            },
9270
9271            EditorMode::Full => TextStyle {
9272                color: cx.theme().colors().editor_foreground,
9273                font_family: settings.buffer_font.family.clone(),
9274                font_features: settings.buffer_font.features,
9275                font_size: settings.buffer_font_size(cx).into(),
9276                font_weight: FontWeight::NORMAL,
9277                font_style: FontStyle::Normal,
9278                line_height: relative(settings.buffer_line_height.value()),
9279                background_color: None,
9280                underline: None,
9281                white_space: WhiteSpace::Normal,
9282            },
9283        };
9284
9285        let background = match self.mode {
9286            EditorMode::SingleLine => cx.theme().system().transparent,
9287            EditorMode::AutoHeight { max_lines: _ } => cx.theme().system().transparent,
9288            EditorMode::Full => cx.theme().colors().editor_background,
9289        };
9290
9291        EditorElement::new(
9292            cx.view(),
9293            EditorStyle {
9294                background,
9295                local_player: cx.theme().players().local(),
9296                text: text_style,
9297                scrollbar_width: px(12.),
9298                syntax: cx.theme().syntax().clone(),
9299                status: cx.theme().status().clone(),
9300                inlays_style: HighlightStyle {
9301                    color: Some(cx.theme().status().hint),
9302                    font_weight: Some(FontWeight::BOLD),
9303                    ..HighlightStyle::default()
9304                },
9305                suggestions_style: HighlightStyle {
9306                    color: Some(cx.theme().status().predictive),
9307                    ..HighlightStyle::default()
9308                },
9309            },
9310        )
9311    }
9312}
9313
9314impl ViewInputHandler for Editor {
9315    fn text_for_range(
9316        &mut self,
9317        range_utf16: Range<usize>,
9318        cx: &mut ViewContext<Self>,
9319    ) -> Option<String> {
9320        Some(
9321            self.buffer
9322                .read(cx)
9323                .read(cx)
9324                .text_for_range(OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end))
9325                .collect(),
9326        )
9327    }
9328
9329    fn selected_text_range(&mut self, cx: &mut ViewContext<Self>) -> Option<Range<usize>> {
9330        // Prevent the IME menu from appearing when holding down an alphabetic key
9331        // while input is disabled.
9332        if !self.input_enabled {
9333            return None;
9334        }
9335
9336        let range = self.selections.newest::<OffsetUtf16>(cx).range();
9337        Some(range.start.0..range.end.0)
9338    }
9339
9340    fn marked_text_range(&self, cx: &mut ViewContext<Self>) -> Option<Range<usize>> {
9341        let snapshot = self.buffer.read(cx).read(cx);
9342        let range = self.text_highlights::<InputComposition>(cx)?.1.get(0)?;
9343        Some(range.start.to_offset_utf16(&snapshot).0..range.end.to_offset_utf16(&snapshot).0)
9344    }
9345
9346    fn unmark_text(&mut self, cx: &mut ViewContext<Self>) {
9347        self.clear_highlights::<InputComposition>(cx);
9348        self.ime_transaction.take();
9349    }
9350
9351    fn replace_text_in_range(
9352        &mut self,
9353        range_utf16: Option<Range<usize>>,
9354        text: &str,
9355        cx: &mut ViewContext<Self>,
9356    ) {
9357        if !self.input_enabled {
9358            cx.emit(EditorEvent::InputIgnored { text: text.into() });
9359            return;
9360        }
9361
9362        self.transact(cx, |this, cx| {
9363            let new_selected_ranges = if let Some(range_utf16) = range_utf16 {
9364                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
9365                Some(this.selection_replacement_ranges(range_utf16, cx))
9366            } else {
9367                this.marked_text_ranges(cx)
9368            };
9369
9370            let range_to_replace = new_selected_ranges.as_ref().and_then(|ranges_to_replace| {
9371                let newest_selection_id = this.selections.newest_anchor().id;
9372                this.selections
9373                    .all::<OffsetUtf16>(cx)
9374                    .iter()
9375                    .zip(ranges_to_replace.iter())
9376                    .find_map(|(selection, range)| {
9377                        if selection.id == newest_selection_id {
9378                            Some(
9379                                (range.start.0 as isize - selection.head().0 as isize)
9380                                    ..(range.end.0 as isize - selection.head().0 as isize),
9381                            )
9382                        } else {
9383                            None
9384                        }
9385                    })
9386            });
9387
9388            cx.emit(EditorEvent::InputHandled {
9389                utf16_range_to_replace: range_to_replace,
9390                text: text.into(),
9391            });
9392
9393            if let Some(new_selected_ranges) = new_selected_ranges {
9394                this.change_selections(None, cx, |selections| {
9395                    selections.select_ranges(new_selected_ranges)
9396                });
9397            }
9398
9399            this.handle_input(text, cx);
9400        });
9401
9402        if let Some(transaction) = self.ime_transaction {
9403            self.buffer.update(cx, |buffer, cx| {
9404                buffer.group_until_transaction(transaction, cx);
9405            });
9406        }
9407
9408        self.unmark_text(cx);
9409    }
9410
9411    fn replace_and_mark_text_in_range(
9412        &mut self,
9413        range_utf16: Option<Range<usize>>,
9414        text: &str,
9415        new_selected_range_utf16: Option<Range<usize>>,
9416        cx: &mut ViewContext<Self>,
9417    ) {
9418        if !self.input_enabled {
9419            cx.emit(EditorEvent::InputIgnored { text: text.into() });
9420            return;
9421        }
9422
9423        let transaction = self.transact(cx, |this, cx| {
9424            let ranges_to_replace = if let Some(mut marked_ranges) = this.marked_text_ranges(cx) {
9425                let snapshot = this.buffer.read(cx).read(cx);
9426                if let Some(relative_range_utf16) = range_utf16.as_ref() {
9427                    for marked_range in &mut marked_ranges {
9428                        marked_range.end.0 = marked_range.start.0 + relative_range_utf16.end;
9429                        marked_range.start.0 += relative_range_utf16.start;
9430                        marked_range.start =
9431                            snapshot.clip_offset_utf16(marked_range.start, Bias::Left);
9432                        marked_range.end =
9433                            snapshot.clip_offset_utf16(marked_range.end, Bias::Right);
9434                    }
9435                }
9436                Some(marked_ranges)
9437            } else if let Some(range_utf16) = range_utf16 {
9438                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
9439                Some(this.selection_replacement_ranges(range_utf16, cx))
9440            } else {
9441                None
9442            };
9443
9444            let range_to_replace = ranges_to_replace.as_ref().and_then(|ranges_to_replace| {
9445                let newest_selection_id = this.selections.newest_anchor().id;
9446                this.selections
9447                    .all::<OffsetUtf16>(cx)
9448                    .iter()
9449                    .zip(ranges_to_replace.iter())
9450                    .find_map(|(selection, range)| {
9451                        if selection.id == newest_selection_id {
9452                            Some(
9453                                (range.start.0 as isize - selection.head().0 as isize)
9454                                    ..(range.end.0 as isize - selection.head().0 as isize),
9455                            )
9456                        } else {
9457                            None
9458                        }
9459                    })
9460            });
9461
9462            cx.emit(EditorEvent::InputHandled {
9463                utf16_range_to_replace: range_to_replace,
9464                text: text.into(),
9465            });
9466
9467            if let Some(ranges) = ranges_to_replace {
9468                this.change_selections(None, cx, |s| s.select_ranges(ranges));
9469            }
9470
9471            let marked_ranges = {
9472                let snapshot = this.buffer.read(cx).read(cx);
9473                this.selections
9474                    .disjoint_anchors()
9475                    .iter()
9476                    .map(|selection| {
9477                        selection.start.bias_left(&*snapshot)..selection.end.bias_right(&*snapshot)
9478                    })
9479                    .collect::<Vec<_>>()
9480            };
9481
9482            if text.is_empty() {
9483                this.unmark_text(cx);
9484            } else {
9485                this.highlight_text::<InputComposition>(
9486                    marked_ranges.clone(),
9487                    HighlightStyle::default(), // todo!() this.style(cx).composition_mark,
9488                    cx,
9489                );
9490            }
9491
9492            this.handle_input(text, cx);
9493
9494            if let Some(new_selected_range) = new_selected_range_utf16 {
9495                let snapshot = this.buffer.read(cx).read(cx);
9496                let new_selected_ranges = marked_ranges
9497                    .into_iter()
9498                    .map(|marked_range| {
9499                        let insertion_start = marked_range.start.to_offset_utf16(&snapshot).0;
9500                        let new_start = OffsetUtf16(new_selected_range.start + insertion_start);
9501                        let new_end = OffsetUtf16(new_selected_range.end + insertion_start);
9502                        snapshot.clip_offset_utf16(new_start, Bias::Left)
9503                            ..snapshot.clip_offset_utf16(new_end, Bias::Right)
9504                    })
9505                    .collect::<Vec<_>>();
9506
9507                drop(snapshot);
9508                this.change_selections(None, cx, |selections| {
9509                    selections.select_ranges(new_selected_ranges)
9510                });
9511            }
9512        });
9513
9514        self.ime_transaction = self.ime_transaction.or(transaction);
9515        if let Some(transaction) = self.ime_transaction {
9516            self.buffer.update(cx, |buffer, cx| {
9517                buffer.group_until_transaction(transaction, cx);
9518            });
9519        }
9520
9521        if self.text_highlights::<InputComposition>(cx).is_none() {
9522            self.ime_transaction.take();
9523        }
9524    }
9525
9526    fn bounds_for_range(
9527        &mut self,
9528        range_utf16: Range<usize>,
9529        element_bounds: gpui::Bounds<Pixels>,
9530        cx: &mut ViewContext<Self>,
9531    ) -> Option<gpui::Bounds<Pixels>> {
9532        let text_layout_details = self.text_layout_details(cx);
9533        let style = &text_layout_details.editor_style;
9534        let font_id = cx.text_system().resolve_font(&style.text.font());
9535        let font_size = style.text.font_size.to_pixels(cx.rem_size());
9536        let line_height = style.text.line_height_in_pixels(cx.rem_size());
9537        let em_width = cx
9538            .text_system()
9539            .typographic_bounds(font_id, font_size, 'm')
9540            .unwrap()
9541            .size
9542            .width;
9543
9544        let snapshot = self.snapshot(cx);
9545        let scroll_position = snapshot.scroll_position();
9546        let scroll_left = scroll_position.x * em_width;
9547
9548        let start = OffsetUtf16(range_utf16.start).to_display_point(&snapshot);
9549        let x = snapshot.x_for_display_point(start, &text_layout_details) - scroll_left
9550            + self.gutter_width;
9551        let y = line_height * (start.row() as f32 - scroll_position.y);
9552
9553        Some(Bounds {
9554            origin: element_bounds.origin + point(x, y),
9555            size: size(em_width, line_height),
9556        })
9557    }
9558}
9559
9560trait SelectionExt {
9561    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize>;
9562    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point>;
9563    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
9564    fn spanned_rows(&self, include_end_if_at_line_start: bool, map: &DisplaySnapshot)
9565        -> Range<u32>;
9566}
9567
9568impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
9569    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
9570        let start = self.start.to_point(buffer);
9571        let end = self.end.to_point(buffer);
9572        if self.reversed {
9573            end..start
9574        } else {
9575            start..end
9576        }
9577    }
9578
9579    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
9580        let start = self.start.to_offset(buffer);
9581        let end = self.end.to_offset(buffer);
9582        if self.reversed {
9583            end..start
9584        } else {
9585            start..end
9586        }
9587    }
9588
9589    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
9590        let start = self
9591            .start
9592            .to_point(&map.buffer_snapshot)
9593            .to_display_point(map);
9594        let end = self
9595            .end
9596            .to_point(&map.buffer_snapshot)
9597            .to_display_point(map);
9598        if self.reversed {
9599            end..start
9600        } else {
9601            start..end
9602        }
9603    }
9604
9605    fn spanned_rows(
9606        &self,
9607        include_end_if_at_line_start: bool,
9608        map: &DisplaySnapshot,
9609    ) -> Range<u32> {
9610        let start = self.start.to_point(&map.buffer_snapshot);
9611        let mut end = self.end.to_point(&map.buffer_snapshot);
9612        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
9613            end.row -= 1;
9614        }
9615
9616        let buffer_start = map.prev_line_boundary(start).0;
9617        let buffer_end = map.next_line_boundary(end).0;
9618        buffer_start.row..buffer_end.row + 1
9619    }
9620}
9621
9622impl<T: InvalidationRegion> InvalidationStack<T> {
9623    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
9624    where
9625        S: Clone + ToOffset,
9626    {
9627        while let Some(region) = self.last() {
9628            let all_selections_inside_invalidation_ranges =
9629                if selections.len() == region.ranges().len() {
9630                    selections
9631                        .iter()
9632                        .zip(region.ranges().iter().map(|r| r.to_offset(buffer)))
9633                        .all(|(selection, invalidation_range)| {
9634                            let head = selection.head().to_offset(buffer);
9635                            invalidation_range.start <= head && invalidation_range.end >= head
9636                        })
9637                } else {
9638                    false
9639                };
9640
9641            if all_selections_inside_invalidation_ranges {
9642                break;
9643            } else {
9644                self.pop();
9645            }
9646        }
9647    }
9648}
9649
9650impl<T> Default for InvalidationStack<T> {
9651    fn default() -> Self {
9652        Self(Default::default())
9653    }
9654}
9655
9656impl<T> Deref for InvalidationStack<T> {
9657    type Target = Vec<T>;
9658
9659    fn deref(&self) -> &Self::Target {
9660        &self.0
9661    }
9662}
9663
9664impl<T> DerefMut for InvalidationStack<T> {
9665    fn deref_mut(&mut self) -> &mut Self::Target {
9666        &mut self.0
9667    }
9668}
9669
9670impl InvalidationRegion for SnippetState {
9671    fn ranges(&self) -> &[Range<Anchor>] {
9672        &self.ranges[self.active_index]
9673    }
9674}
9675
9676pub fn diagnostic_block_renderer(diagnostic: Diagnostic, _is_valid: bool) -> RenderBlock {
9677    let (text_without_backticks, code_ranges) = highlight_diagnostic_message(&diagnostic);
9678
9679    Arc::new(move |cx: &mut BlockContext| {
9680        let group_id: SharedString = cx.block_id.to_string().into();
9681
9682        let mut text_style = cx.text_style().clone();
9683        text_style.color = diagnostic_style(diagnostic.severity, true, cx.theme().status());
9684
9685        h_flex()
9686            .id(cx.block_id)
9687            .group(group_id.clone())
9688            .relative()
9689            .size_full()
9690            .pl(cx.gutter_width)
9691            .w(cx.max_width + cx.gutter_width)
9692            .child(div().flex().w(cx.anchor_x - cx.gutter_width).flex_shrink())
9693            .child(div().flex().flex_shrink_0().child(
9694                StyledText::new(text_without_backticks.clone()).with_highlights(
9695                    &text_style,
9696                    code_ranges.iter().map(|range| {
9697                        (
9698                            range.clone(),
9699                            HighlightStyle {
9700                                font_weight: Some(FontWeight::BOLD),
9701                                ..Default::default()
9702                            },
9703                        )
9704                    }),
9705                ),
9706            ))
9707            .child(
9708                IconButton::new(("copy-block", cx.block_id), IconName::Copy)
9709                    .icon_color(Color::Muted)
9710                    .size(ButtonSize::Compact)
9711                    .style(ButtonStyle::Transparent)
9712                    .visible_on_hover(group_id)
9713                    .on_click({
9714                        let message = diagnostic.message.clone();
9715                        move |_click, cx| cx.write_to_clipboard(ClipboardItem::new(message.clone()))
9716                    })
9717                    .tooltip(|cx| Tooltip::text("Copy diagnostic message", cx)),
9718            )
9719            .into_any_element()
9720    })
9721}
9722
9723pub fn highlight_diagnostic_message(diagnostic: &Diagnostic) -> (SharedString, Vec<Range<usize>>) {
9724    let mut text_without_backticks = String::new();
9725    let mut code_ranges = Vec::new();
9726
9727    if let Some(source) = &diagnostic.source {
9728        text_without_backticks.push_str(&source);
9729        code_ranges.push(0..source.len());
9730        text_without_backticks.push_str(": ");
9731    }
9732
9733    let mut prev_offset = 0;
9734    let mut in_code_block = false;
9735    for (ix, _) in diagnostic
9736        .message
9737        .match_indices('`')
9738        .chain([(diagnostic.message.len(), "")])
9739    {
9740        let prev_len = text_without_backticks.len();
9741        text_without_backticks.push_str(&diagnostic.message[prev_offset..ix]);
9742        prev_offset = ix + 1;
9743        if in_code_block {
9744            code_ranges.push(prev_len..text_without_backticks.len());
9745            in_code_block = false;
9746        } else {
9747            in_code_block = true;
9748        }
9749    }
9750
9751    (text_without_backticks.into(), code_ranges)
9752}
9753
9754fn diagnostic_style(severity: DiagnosticSeverity, valid: bool, colors: &StatusColors) -> Hsla {
9755    match (severity, valid) {
9756        (DiagnosticSeverity::ERROR, true) => colors.error,
9757        (DiagnosticSeverity::ERROR, false) => colors.error,
9758        (DiagnosticSeverity::WARNING, true) => colors.warning,
9759        (DiagnosticSeverity::WARNING, false) => colors.warning,
9760        (DiagnosticSeverity::INFORMATION, true) => colors.info,
9761        (DiagnosticSeverity::INFORMATION, false) => colors.info,
9762        (DiagnosticSeverity::HINT, true) => colors.info,
9763        (DiagnosticSeverity::HINT, false) => colors.info,
9764        _ => colors.ignored,
9765    }
9766}
9767
9768pub fn styled_runs_for_code_label<'a>(
9769    label: &'a CodeLabel,
9770    syntax_theme: &'a theme::SyntaxTheme,
9771) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
9772    let fade_out = HighlightStyle {
9773        fade_out: Some(0.35),
9774        ..Default::default()
9775    };
9776
9777    let mut prev_end = label.filter_range.end;
9778    label
9779        .runs
9780        .iter()
9781        .enumerate()
9782        .flat_map(move |(ix, (range, highlight_id))| {
9783            let style = if let Some(style) = highlight_id.style(syntax_theme) {
9784                style
9785            } else {
9786                return Default::default();
9787            };
9788            let mut muted_style = style;
9789            muted_style.highlight(fade_out);
9790
9791            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
9792            if range.start >= label.filter_range.end {
9793                if range.start > prev_end {
9794                    runs.push((prev_end..range.start, fade_out));
9795                }
9796                runs.push((range.clone(), muted_style));
9797            } else if range.end <= label.filter_range.end {
9798                runs.push((range.clone(), style));
9799            } else {
9800                runs.push((range.start..label.filter_range.end, style));
9801                runs.push((label.filter_range.end..range.end, muted_style));
9802            }
9803            prev_end = cmp::max(prev_end, range.end);
9804
9805            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
9806                runs.push((prev_end..label.text.len(), fade_out));
9807            }
9808
9809            runs
9810        })
9811}
9812
9813pub(crate) fn split_words<'a>(text: &'a str) -> impl std::iter::Iterator<Item = &'a str> + 'a {
9814    let mut index = 0;
9815    let mut codepoints = text.char_indices().peekable();
9816
9817    std::iter::from_fn(move || {
9818        let start_index = index;
9819        while let Some((new_index, codepoint)) = codepoints.next() {
9820            index = new_index + codepoint.len_utf8();
9821            let current_upper = codepoint.is_uppercase();
9822            let next_upper = codepoints
9823                .peek()
9824                .map(|(_, c)| c.is_uppercase())
9825                .unwrap_or(false);
9826
9827            if !current_upper && next_upper {
9828                return Some(&text[start_index..index]);
9829            }
9830        }
9831
9832        index = text.len();
9833        if start_index < text.len() {
9834            return Some(&text[start_index..]);
9835        }
9836        None
9837    })
9838    .flat_map(|word| word.split_inclusive('_'))
9839    .flat_map(|word| word.split_inclusive('-'))
9840}
9841
9842trait RangeToAnchorExt {
9843    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor>;
9844}
9845
9846impl<T: ToOffset> RangeToAnchorExt for Range<T> {
9847    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor> {
9848        snapshot.anchor_after(self.start)..snapshot.anchor_before(self.end)
9849    }
9850}