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