editor.rs

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