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