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