editor.rs

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