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.is_empty() {
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        dbg!("TOGGLE CODE ACTIONS");
3644        let mut context_menu = self.context_menu.write();
3645        if matches!(context_menu.as_ref(), Some(ContextMenu::CodeActions(_))) {
3646            *context_menu = None;
3647            cx.notify();
3648            return;
3649        }
3650        drop(context_menu);
3651
3652        let deployed_from_indicator = action.deployed_from_indicator;
3653        let mut task = self.code_actions_task.take();
3654        cx.spawn(|this, mut cx| async move {
3655            while let Some(prev_task) = task {
3656                prev_task.await;
3657                task = this.update(&mut cx, |this, _| this.code_actions_task.take())?;
3658            }
3659
3660            this.update(&mut cx, |this, cx| {
3661                if this.focus_handle.is_focused(cx) {
3662                    if let Some((buffer, actions)) = this.available_code_actions.clone() {
3663                        this.completion_tasks.clear();
3664                        this.discard_copilot_suggestion(cx);
3665                        *this.context_menu.write() =
3666                            Some(ContextMenu::CodeActions(CodeActionsMenu {
3667                                buffer,
3668                                actions,
3669                                selected_item: Default::default(),
3670                                scroll_handle: UniformListScrollHandle::default(),
3671                                deployed_from_indicator,
3672                            }));
3673                        cx.notify();
3674                    }
3675                }
3676            })?;
3677
3678            Ok::<_, anyhow::Error>(())
3679        })
3680        .detach_and_log_err(cx);
3681    }
3682
3683    pub fn confirm_code_action(
3684        &mut self,
3685        action: &ConfirmCodeAction,
3686        cx: &mut ViewContext<Self>,
3687    ) -> Option<Task<Result<()>>> {
3688        let actions_menu = if let ContextMenu::CodeActions(menu) = self.hide_context_menu(cx)? {
3689            menu
3690        } else {
3691            return None;
3692        };
3693        let action_ix = action.item_ix.unwrap_or(actions_menu.selected_item);
3694        let action = actions_menu.actions.get(action_ix)?.clone();
3695        let title = action.lsp_action.title.clone();
3696        let buffer = actions_menu.buffer;
3697        let workspace = self.workspace()?;
3698
3699        let apply_code_actions = workspace
3700            .read(cx)
3701            .project()
3702            .clone()
3703            .update(cx, |project, cx| {
3704                project.apply_code_action(buffer, action, true, cx)
3705            });
3706        let workspace = workspace.downgrade();
3707        Some(cx.spawn(|editor, cx| async move {
3708            let project_transaction = apply_code_actions.await?;
3709            Self::open_project_transaction(&editor, workspace, project_transaction, title, cx).await
3710        }))
3711    }
3712
3713    async fn open_project_transaction(
3714        this: &WeakView<Editor>,
3715        workspace: WeakView<Workspace>,
3716        transaction: ProjectTransaction,
3717        title: String,
3718        mut cx: AsyncWindowContext,
3719    ) -> Result<()> {
3720        let replica_id = this.update(&mut cx, |this, cx| this.replica_id(cx))?;
3721
3722        let mut entries = transaction.0.into_iter().collect::<Vec<_>>();
3723        cx.update(|_, cx| {
3724            entries.sort_unstable_by_key(|(buffer, _)| {
3725                buffer.read(cx).file().map(|f| f.path().clone())
3726            });
3727        })?;
3728
3729        // If the project transaction's edits are all contained within this editor, then
3730        // avoid opening a new editor to display them.
3731
3732        if let Some((buffer, transaction)) = entries.first() {
3733            if entries.len() == 1 {
3734                let excerpt = this.update(&mut cx, |editor, cx| {
3735                    editor
3736                        .buffer()
3737                        .read(cx)
3738                        .excerpt_containing(editor.selections.newest_anchor().head(), cx)
3739                })?;
3740                if let Some((_, excerpted_buffer, excerpt_range)) = excerpt {
3741                    if excerpted_buffer == *buffer {
3742                        let all_edits_within_excerpt = buffer.read_with(&cx, |buffer, _| {
3743                            let excerpt_range = excerpt_range.to_offset(buffer);
3744                            buffer
3745                                .edited_ranges_for_transaction::<usize>(transaction)
3746                                .all(|range| {
3747                                    excerpt_range.start <= range.start
3748                                        && excerpt_range.end >= range.end
3749                                })
3750                        })?;
3751
3752                        if all_edits_within_excerpt {
3753                            return Ok(());
3754                        }
3755                    }
3756                }
3757            }
3758        } else {
3759            return Ok(());
3760        }
3761
3762        let mut ranges_to_highlight = Vec::new();
3763        let excerpt_buffer = cx.build_model(|cx| {
3764            let mut multibuffer = MultiBuffer::new(replica_id).with_title(title);
3765            for (buffer_handle, transaction) in &entries {
3766                let buffer = buffer_handle.read(cx);
3767                ranges_to_highlight.extend(
3768                    multibuffer.push_excerpts_with_context_lines(
3769                        buffer_handle.clone(),
3770                        buffer
3771                            .edited_ranges_for_transaction::<usize>(transaction)
3772                            .collect(),
3773                        1,
3774                        cx,
3775                    ),
3776                );
3777            }
3778            multibuffer.push_transaction(entries.iter().map(|(b, t)| (b, t)), cx);
3779            multibuffer
3780        })?;
3781
3782        workspace.update(&mut cx, |workspace, cx| {
3783            let project = workspace.project().clone();
3784            let editor =
3785                cx.build_view(|cx| Editor::for_multibuffer(excerpt_buffer, Some(project), cx));
3786            workspace.add_item(Box::new(editor.clone()), cx);
3787            editor.update(cx, |editor, cx| {
3788                editor.highlight_background::<Self>(
3789                    ranges_to_highlight,
3790                    |theme| theme.editor_highlighted_line_background,
3791                    cx,
3792                );
3793            });
3794        })?;
3795
3796        Ok(())
3797    }
3798
3799    fn refresh_code_actions(&mut self, cx: &mut ViewContext<Self>) -> Option<()> {
3800        let project = self.project.clone()?;
3801        let buffer = self.buffer.read(cx);
3802        let newest_selection = self.selections.newest_anchor().clone();
3803        let (start_buffer, start) = buffer.text_anchor_for_position(newest_selection.start, cx)?;
3804        let (end_buffer, end) = buffer.text_anchor_for_position(newest_selection.end, cx)?;
3805        if start_buffer != end_buffer {
3806            return None;
3807        }
3808
3809        self.code_actions_task = Some(cx.spawn(|this, mut cx| async move {
3810            cx.background_executor()
3811                .timer(CODE_ACTIONS_DEBOUNCE_TIMEOUT)
3812                .await;
3813
3814            let actions = if let Ok(code_actions) = project.update(&mut cx, |project, cx| {
3815                project.code_actions(&start_buffer, start..end, cx)
3816            }) {
3817                code_actions.await.log_err()
3818            } else {
3819                None
3820            };
3821
3822            this.update(&mut cx, |this, cx| {
3823                this.available_code_actions = actions.and_then(|actions| {
3824                    if actions.is_empty() {
3825                        None
3826                    } else {
3827                        Some((start_buffer, actions.into()))
3828                    }
3829                });
3830                cx.notify();
3831            })
3832            .log_err();
3833        }));
3834        None
3835    }
3836
3837    fn refresh_document_highlights(&mut self, cx: &mut ViewContext<Self>) -> Option<()> {
3838        if self.pending_rename.is_some() {
3839            return None;
3840        }
3841
3842        let project = self.project.clone()?;
3843        let buffer = self.buffer.read(cx);
3844        let newest_selection = self.selections.newest_anchor().clone();
3845        let cursor_position = newest_selection.head();
3846        let (cursor_buffer, cursor_buffer_position) =
3847            buffer.text_anchor_for_position(cursor_position.clone(), cx)?;
3848        let (tail_buffer, _) = buffer.text_anchor_for_position(newest_selection.tail(), cx)?;
3849        if cursor_buffer != tail_buffer {
3850            return None;
3851        }
3852
3853        self.document_highlights_task = Some(cx.spawn(|this, mut cx| async move {
3854            cx.background_executor()
3855                .timer(DOCUMENT_HIGHLIGHTS_DEBOUNCE_TIMEOUT)
3856                .await;
3857
3858            let highlights = if let Some(highlights) = project
3859                .update(&mut cx, |project, cx| {
3860                    project.document_highlights(&cursor_buffer, cursor_buffer_position, cx)
3861                })
3862                .log_err()
3863            {
3864                highlights.await.log_err()
3865            } else {
3866                None
3867            };
3868
3869            if let Some(highlights) = highlights {
3870                this.update(&mut cx, |this, cx| {
3871                    if this.pending_rename.is_some() {
3872                        return;
3873                    }
3874
3875                    let buffer_id = cursor_position.buffer_id;
3876                    let buffer = this.buffer.read(cx);
3877                    if !buffer
3878                        .text_anchor_for_position(cursor_position, cx)
3879                        .map_or(false, |(buffer, _)| buffer == cursor_buffer)
3880                    {
3881                        return;
3882                    }
3883
3884                    let cursor_buffer_snapshot = cursor_buffer.read(cx);
3885                    let mut write_ranges = Vec::new();
3886                    let mut read_ranges = Vec::new();
3887                    for highlight in highlights {
3888                        for (excerpt_id, excerpt_range) in
3889                            buffer.excerpts_for_buffer(&cursor_buffer, cx)
3890                        {
3891                            let start = highlight
3892                                .range
3893                                .start
3894                                .max(&excerpt_range.context.start, cursor_buffer_snapshot);
3895                            let end = highlight
3896                                .range
3897                                .end
3898                                .min(&excerpt_range.context.end, cursor_buffer_snapshot);
3899                            if start.cmp(&end, cursor_buffer_snapshot).is_ge() {
3900                                continue;
3901                            }
3902
3903                            let range = Anchor {
3904                                buffer_id,
3905                                excerpt_id: excerpt_id.clone(),
3906                                text_anchor: start,
3907                            }..Anchor {
3908                                buffer_id,
3909                                excerpt_id,
3910                                text_anchor: end,
3911                            };
3912                            if highlight.kind == lsp::DocumentHighlightKind::WRITE {
3913                                write_ranges.push(range);
3914                            } else {
3915                                read_ranges.push(range);
3916                            }
3917                        }
3918                    }
3919
3920                    this.highlight_background::<DocumentHighlightRead>(
3921                        read_ranges,
3922                        |theme| theme.editor_document_highlight_read_background,
3923                        cx,
3924                    );
3925                    this.highlight_background::<DocumentHighlightWrite>(
3926                        write_ranges,
3927                        |theme| theme.editor_document_highlight_write_background,
3928                        cx,
3929                    );
3930                    cx.notify();
3931                })
3932                .log_err();
3933            }
3934        }));
3935        None
3936    }
3937
3938    fn refresh_copilot_suggestions(
3939        &mut self,
3940        debounce: bool,
3941        cx: &mut ViewContext<Self>,
3942    ) -> Option<()> {
3943        let copilot = Copilot::global(cx)?;
3944        if self.mode != EditorMode::Full || !copilot.read(cx).status().is_authorized() {
3945            self.clear_copilot_suggestions(cx);
3946            return None;
3947        }
3948        self.update_visible_copilot_suggestion(cx);
3949
3950        let snapshot = self.buffer.read(cx).snapshot(cx);
3951        let cursor = self.selections.newest_anchor().head();
3952        if !self.is_copilot_enabled_at(cursor, &snapshot, cx) {
3953            self.clear_copilot_suggestions(cx);
3954            return None;
3955        }
3956
3957        let (buffer, buffer_position) =
3958            self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
3959        self.copilot_state.pending_refresh = cx.spawn(|this, mut cx| async move {
3960            if debounce {
3961                cx.background_executor()
3962                    .timer(COPILOT_DEBOUNCE_TIMEOUT)
3963                    .await;
3964            }
3965
3966            let completions = copilot
3967                .update(&mut cx, |copilot, cx| {
3968                    copilot.completions(&buffer, buffer_position, cx)
3969                })
3970                .log_err()
3971                .unwrap_or(Task::ready(Ok(Vec::new())))
3972                .await
3973                .log_err()
3974                .into_iter()
3975                .flatten()
3976                .collect_vec();
3977
3978            this.update(&mut cx, |this, cx| {
3979                if !completions.is_empty() {
3980                    this.copilot_state.cycled = false;
3981                    this.copilot_state.pending_cycling_refresh = Task::ready(None);
3982                    this.copilot_state.completions.clear();
3983                    this.copilot_state.active_completion_index = 0;
3984                    this.copilot_state.excerpt_id = Some(cursor.excerpt_id);
3985                    for completion in completions {
3986                        this.copilot_state.push_completion(completion);
3987                    }
3988                    this.update_visible_copilot_suggestion(cx);
3989                }
3990            })
3991            .log_err()?;
3992            Some(())
3993        });
3994
3995        Some(())
3996    }
3997
3998    fn cycle_copilot_suggestions(
3999        &mut self,
4000        direction: Direction,
4001        cx: &mut ViewContext<Self>,
4002    ) -> Option<()> {
4003        let copilot = Copilot::global(cx)?;
4004        if self.mode != EditorMode::Full || !copilot.read(cx).status().is_authorized() {
4005            return None;
4006        }
4007
4008        if self.copilot_state.cycled {
4009            self.copilot_state.cycle_completions(direction);
4010            self.update_visible_copilot_suggestion(cx);
4011        } else {
4012            let cursor = self.selections.newest_anchor().head();
4013            let (buffer, buffer_position) =
4014                self.buffer.read(cx).text_anchor_for_position(cursor, cx)?;
4015            self.copilot_state.pending_cycling_refresh = cx.spawn(|this, mut cx| async move {
4016                let completions = copilot
4017                    .update(&mut cx, |copilot, cx| {
4018                        copilot.completions_cycling(&buffer, buffer_position, cx)
4019                    })
4020                    .log_err()?
4021                    .await;
4022
4023                this.update(&mut cx, |this, cx| {
4024                    this.copilot_state.cycled = true;
4025                    for completion in completions.log_err().into_iter().flatten() {
4026                        this.copilot_state.push_completion(completion);
4027                    }
4028                    this.copilot_state.cycle_completions(direction);
4029                    this.update_visible_copilot_suggestion(cx);
4030                })
4031                .log_err()?;
4032
4033                Some(())
4034            });
4035        }
4036
4037        Some(())
4038    }
4039
4040    fn copilot_suggest(&mut self, _: &copilot::Suggest, cx: &mut ViewContext<Self>) {
4041        if !self.has_active_copilot_suggestion(cx) {
4042            self.refresh_copilot_suggestions(false, cx);
4043            return;
4044        }
4045
4046        self.update_visible_copilot_suggestion(cx);
4047    }
4048
4049    fn next_copilot_suggestion(&mut self, _: &copilot::NextSuggestion, cx: &mut ViewContext<Self>) {
4050        if self.has_active_copilot_suggestion(cx) {
4051            self.cycle_copilot_suggestions(Direction::Next, cx);
4052        } else {
4053            let is_copilot_disabled = self.refresh_copilot_suggestions(false, cx).is_none();
4054            if is_copilot_disabled {
4055                cx.propagate();
4056            }
4057        }
4058    }
4059
4060    fn previous_copilot_suggestion(
4061        &mut self,
4062        _: &copilot::PreviousSuggestion,
4063        cx: &mut ViewContext<Self>,
4064    ) {
4065        if self.has_active_copilot_suggestion(cx) {
4066            self.cycle_copilot_suggestions(Direction::Prev, cx);
4067        } else {
4068            let is_copilot_disabled = self.refresh_copilot_suggestions(false, cx).is_none();
4069            if is_copilot_disabled {
4070                cx.propagate();
4071            }
4072        }
4073    }
4074
4075    fn accept_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) -> bool {
4076        if let Some(suggestion) = self.take_active_copilot_suggestion(cx) {
4077            if let Some((copilot, completion)) =
4078                Copilot::global(cx).zip(self.copilot_state.active_completion())
4079            {
4080                copilot
4081                    .update(cx, |copilot, cx| copilot.accept_completion(completion, cx))
4082                    .detach_and_log_err(cx);
4083
4084                self.report_copilot_event(Some(completion.uuid.clone()), true, cx)
4085            }
4086            cx.emit(EditorEvent::InputHandled {
4087                utf16_range_to_replace: None,
4088                text: suggestion.text.to_string().into(),
4089            });
4090            self.insert_with_autoindent_mode(&suggestion.text.to_string(), None, cx);
4091            cx.notify();
4092            true
4093        } else {
4094            false
4095        }
4096    }
4097
4098    fn discard_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) -> bool {
4099        if let Some(suggestion) = self.take_active_copilot_suggestion(cx) {
4100            if let Some(copilot) = Copilot::global(cx) {
4101                copilot
4102                    .update(cx, |copilot, cx| {
4103                        copilot.discard_completions(&self.copilot_state.completions, cx)
4104                    })
4105                    .detach_and_log_err(cx);
4106
4107                self.report_copilot_event(None, false, cx)
4108            }
4109
4110            self.display_map.update(cx, |map, cx| {
4111                map.splice_inlays(vec![suggestion.id], Vec::new(), cx)
4112            });
4113            cx.notify();
4114            true
4115        } else {
4116            false
4117        }
4118    }
4119
4120    fn is_copilot_enabled_at(
4121        &self,
4122        location: Anchor,
4123        snapshot: &MultiBufferSnapshot,
4124        cx: &mut ViewContext<Self>,
4125    ) -> bool {
4126        let file = snapshot.file_at(location);
4127        let language = snapshot.language_at(location);
4128        let settings = all_language_settings(file, cx);
4129        settings.copilot_enabled(language, file.map(|f| f.path().as_ref()))
4130    }
4131
4132    fn has_active_copilot_suggestion(&self, cx: &AppContext) -> bool {
4133        if let Some(suggestion) = self.copilot_state.suggestion.as_ref() {
4134            let buffer = self.buffer.read(cx).read(cx);
4135            suggestion.position.is_valid(&buffer)
4136        } else {
4137            false
4138        }
4139    }
4140
4141    fn take_active_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) -> Option<Inlay> {
4142        let suggestion = self.copilot_state.suggestion.take()?;
4143        self.display_map.update(cx, |map, cx| {
4144            map.splice_inlays(vec![suggestion.id], Default::default(), cx);
4145        });
4146        let buffer = self.buffer.read(cx).read(cx);
4147
4148        if suggestion.position.is_valid(&buffer) {
4149            Some(suggestion)
4150        } else {
4151            None
4152        }
4153    }
4154
4155    fn update_visible_copilot_suggestion(&mut self, cx: &mut ViewContext<Self>) {
4156        let snapshot = self.buffer.read(cx).snapshot(cx);
4157        let selection = self.selections.newest_anchor();
4158        let cursor = selection.head();
4159
4160        if self.context_menu.read().is_some()
4161            || !self.completion_tasks.is_empty()
4162            || selection.start != selection.end
4163        {
4164            self.discard_copilot_suggestion(cx);
4165        } else if let Some(text) = self
4166            .copilot_state
4167            .text_for_active_completion(cursor, &snapshot)
4168        {
4169            let text = Rope::from(text);
4170            let mut to_remove = Vec::new();
4171            if let Some(suggestion) = self.copilot_state.suggestion.take() {
4172                to_remove.push(suggestion.id);
4173            }
4174
4175            let suggestion_inlay =
4176                Inlay::suggestion(post_inc(&mut self.next_inlay_id), cursor, text);
4177            self.copilot_state.suggestion = Some(suggestion_inlay.clone());
4178            self.display_map.update(cx, move |map, cx| {
4179                map.splice_inlays(to_remove, vec![suggestion_inlay], cx)
4180            });
4181            cx.notify();
4182        } else {
4183            self.discard_copilot_suggestion(cx);
4184        }
4185    }
4186
4187    fn clear_copilot_suggestions(&mut self, cx: &mut ViewContext<Self>) {
4188        self.copilot_state = Default::default();
4189        self.discard_copilot_suggestion(cx);
4190    }
4191
4192    pub fn render_code_actions_indicator(
4193        &self,
4194        style: &EditorStyle,
4195        is_active: bool,
4196        cx: &mut ViewContext<Self>,
4197    ) -> Option<IconButton> {
4198        if self.available_code_actions.is_some() {
4199            Some(
4200                IconButton::new("code_actions_indicator", ui::Icon::Bolt).on_click(cx.listener(
4201                    |editor, e, cx| {
4202                        editor.toggle_code_actions(
4203                            &ToggleCodeActions {
4204                                deployed_from_indicator: true,
4205                            },
4206                            cx,
4207                        );
4208                    },
4209                )),
4210            )
4211        } else {
4212            None
4213        }
4214    }
4215
4216    pub fn render_fold_indicators(
4217        &self,
4218        fold_data: Vec<Option<(FoldStatus, u32, bool)>>,
4219        style: &EditorStyle,
4220        gutter_hovered: bool,
4221        line_height: Pixels,
4222        gutter_margin: Pixels,
4223        cx: &mut ViewContext<Self>,
4224    ) -> Vec<Option<IconButton>> {
4225        fold_data
4226            .iter()
4227            .enumerate()
4228            .map(|(ix, fold_data)| {
4229                fold_data
4230                    .map(|(fold_status, buffer_row, active)| {
4231                        (active || gutter_hovered || fold_status == FoldStatus::Folded).then(|| {
4232                            let icon = match fold_status {
4233                                FoldStatus::Folded => ui::Icon::ChevronRight,
4234                                FoldStatus::Foldable => ui::Icon::ChevronDown,
4235                            };
4236                            IconButton::new(ix as usize, icon)
4237                                .on_click(cx.listener(move |editor, e, cx| match fold_status {
4238                                    FoldStatus::Folded => {
4239                                        editor.unfold_at(&UnfoldAt { buffer_row }, cx);
4240                                    }
4241                                    FoldStatus::Foldable => {
4242                                        editor.fold_at(&FoldAt { buffer_row }, cx);
4243                                    }
4244                                }))
4245                                .icon_color(ui::Color::Muted)
4246                        })
4247                    })
4248                    .flatten()
4249            })
4250            .collect()
4251    }
4252
4253    pub fn context_menu_visible(&self) -> bool {
4254        self.context_menu
4255            .read()
4256            .as_ref()
4257            .map_or(false, |menu| menu.visible())
4258    }
4259
4260    pub fn render_context_menu(
4261        &self,
4262        cursor_position: DisplayPoint,
4263        style: &EditorStyle,
4264        max_height: Pixels,
4265        cx: &mut ViewContext<Editor>,
4266    ) -> Option<(DisplayPoint, AnyElement)> {
4267        self.context_menu.read().as_ref().map(|menu| {
4268            menu.render(
4269                cursor_position,
4270                style,
4271                max_height,
4272                self.workspace.as_ref().map(|(w, _)| w.clone()),
4273                cx,
4274            )
4275        })
4276    }
4277
4278    fn hide_context_menu(&mut self, cx: &mut ViewContext<Self>) -> Option<ContextMenu> {
4279        cx.notify();
4280        self.completion_tasks.clear();
4281        let context_menu = self.context_menu.write().take();
4282        if context_menu.is_some() {
4283            self.update_visible_copilot_suggestion(cx);
4284        }
4285        context_menu
4286    }
4287
4288    pub fn insert_snippet(
4289        &mut self,
4290        insertion_ranges: &[Range<usize>],
4291        snippet: Snippet,
4292        cx: &mut ViewContext<Self>,
4293    ) -> Result<()> {
4294        let tabstops = self.buffer.update(cx, |buffer, cx| {
4295            let snippet_text: Arc<str> = snippet.text.clone().into();
4296            buffer.edit(
4297                insertion_ranges
4298                    .iter()
4299                    .cloned()
4300                    .map(|range| (range, snippet_text.clone())),
4301                Some(AutoindentMode::EachLine),
4302                cx,
4303            );
4304
4305            let snapshot = &*buffer.read(cx);
4306            let snippet = &snippet;
4307            snippet
4308                .tabstops
4309                .iter()
4310                .map(|tabstop| {
4311                    let mut tabstop_ranges = tabstop
4312                        .iter()
4313                        .flat_map(|tabstop_range| {
4314                            let mut delta = 0_isize;
4315                            insertion_ranges.iter().map(move |insertion_range| {
4316                                let insertion_start = insertion_range.start as isize + delta;
4317                                delta +=
4318                                    snippet.text.len() as isize - insertion_range.len() as isize;
4319
4320                                let start = snapshot.anchor_before(
4321                                    (insertion_start + tabstop_range.start) as usize,
4322                                );
4323                                let end = snapshot
4324                                    .anchor_after((insertion_start + tabstop_range.end) as usize);
4325                                start..end
4326                            })
4327                        })
4328                        .collect::<Vec<_>>();
4329                    tabstop_ranges.sort_unstable_by(|a, b| a.start.cmp(&b.start, snapshot));
4330                    tabstop_ranges
4331                })
4332                .collect::<Vec<_>>()
4333        });
4334
4335        if let Some(tabstop) = tabstops.first() {
4336            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4337                s.select_ranges(tabstop.iter().cloned());
4338            });
4339            self.snippet_stack.push(SnippetState {
4340                active_index: 0,
4341                ranges: tabstops,
4342            });
4343        }
4344
4345        Ok(())
4346    }
4347
4348    pub fn move_to_next_snippet_tabstop(&mut self, cx: &mut ViewContext<Self>) -> bool {
4349        self.move_to_snippet_tabstop(Bias::Right, cx)
4350    }
4351
4352    pub fn move_to_prev_snippet_tabstop(&mut self, cx: &mut ViewContext<Self>) -> bool {
4353        self.move_to_snippet_tabstop(Bias::Left, cx)
4354    }
4355
4356    pub fn move_to_snippet_tabstop(&mut self, bias: Bias, cx: &mut ViewContext<Self>) -> bool {
4357        if let Some(mut snippet) = self.snippet_stack.pop() {
4358            match bias {
4359                Bias::Left => {
4360                    if snippet.active_index > 0 {
4361                        snippet.active_index -= 1;
4362                    } else {
4363                        self.snippet_stack.push(snippet);
4364                        return false;
4365                    }
4366                }
4367                Bias::Right => {
4368                    if snippet.active_index + 1 < snippet.ranges.len() {
4369                        snippet.active_index += 1;
4370                    } else {
4371                        self.snippet_stack.push(snippet);
4372                        return false;
4373                    }
4374                }
4375            }
4376            if let Some(current_ranges) = snippet.ranges.get(snippet.active_index) {
4377                self.change_selections(Some(Autoscroll::fit()), cx, |s| {
4378                    s.select_anchor_ranges(current_ranges.iter().cloned())
4379                });
4380                // If snippet state is not at the last tabstop, push it back on the stack
4381                if snippet.active_index + 1 < snippet.ranges.len() {
4382                    self.snippet_stack.push(snippet);
4383                }
4384                return true;
4385            }
4386        }
4387
4388        false
4389    }
4390
4391    pub fn clear(&mut self, cx: &mut ViewContext<Self>) {
4392        self.transact(cx, |this, cx| {
4393            this.select_all(&SelectAll, cx);
4394            this.insert("", cx);
4395        });
4396    }
4397
4398    pub fn backspace(&mut self, _: &Backspace, cx: &mut ViewContext<Self>) {
4399        self.transact(cx, |this, cx| {
4400            this.select_autoclose_pair(cx);
4401            let mut selections = this.selections.all::<Point>(cx);
4402            if !this.selections.line_mode {
4403                let display_map = this.display_map.update(cx, |map, cx| map.snapshot(cx));
4404                for selection in &mut selections {
4405                    if selection.is_empty() {
4406                        let old_head = selection.head();
4407                        let mut new_head =
4408                            movement::left(&display_map, old_head.to_display_point(&display_map))
4409                                .to_point(&display_map);
4410                        if let Some((buffer, line_buffer_range)) = display_map
4411                            .buffer_snapshot
4412                            .buffer_line_for_row(old_head.row)
4413                        {
4414                            let indent_size =
4415                                buffer.indent_size_for_line(line_buffer_range.start.row);
4416                            let indent_len = match indent_size.kind {
4417                                IndentKind::Space => {
4418                                    buffer.settings_at(line_buffer_range.start, cx).tab_size
4419                                }
4420                                IndentKind::Tab => NonZeroU32::new(1).unwrap(),
4421                            };
4422                            if old_head.column <= indent_size.len && old_head.column > 0 {
4423                                let indent_len = indent_len.get();
4424                                new_head = cmp::min(
4425                                    new_head,
4426                                    Point::new(
4427                                        old_head.row,
4428                                        ((old_head.column - 1) / indent_len) * indent_len,
4429                                    ),
4430                                );
4431                            }
4432                        }
4433
4434                        selection.set_head(new_head, SelectionGoal::None);
4435                    }
4436                }
4437            }
4438
4439            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
4440            this.insert("", cx);
4441            this.refresh_copilot_suggestions(true, cx);
4442        });
4443    }
4444
4445    pub fn delete(&mut self, _: &Delete, cx: &mut ViewContext<Self>) {
4446        self.transact(cx, |this, cx| {
4447            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4448                let line_mode = s.line_mode;
4449                s.move_with(|map, selection| {
4450                    if selection.is_empty() && !line_mode {
4451                        let cursor = movement::right(map, selection.head());
4452                        selection.end = cursor;
4453                        selection.reversed = true;
4454                        selection.goal = SelectionGoal::None;
4455                    }
4456                })
4457            });
4458            this.insert("", cx);
4459            this.refresh_copilot_suggestions(true, cx);
4460        });
4461    }
4462
4463    pub fn tab_prev(&mut self, _: &TabPrev, cx: &mut ViewContext<Self>) {
4464        if self.move_to_prev_snippet_tabstop(cx) {
4465            return;
4466        }
4467
4468        self.outdent(&Outdent, cx);
4469    }
4470
4471    pub fn tab(&mut self, _: &Tab, cx: &mut ViewContext<Self>) {
4472        if self.move_to_next_snippet_tabstop(cx) {
4473            return;
4474        }
4475
4476        let mut selections = self.selections.all_adjusted(cx);
4477        let buffer = self.buffer.read(cx);
4478        let snapshot = buffer.snapshot(cx);
4479        let rows_iter = selections.iter().map(|s| s.head().row);
4480        let suggested_indents = snapshot.suggested_indents(rows_iter, cx);
4481
4482        let mut edits = Vec::new();
4483        let mut prev_edited_row = 0;
4484        let mut row_delta = 0;
4485        for selection in &mut selections {
4486            if selection.start.row != prev_edited_row {
4487                row_delta = 0;
4488            }
4489            prev_edited_row = selection.end.row;
4490
4491            // If the selection is non-empty, then increase the indentation of the selected lines.
4492            if !selection.is_empty() {
4493                row_delta =
4494                    Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
4495                continue;
4496            }
4497
4498            // If the selection is empty and the cursor is in the leading whitespace before the
4499            // suggested indentation, then auto-indent the line.
4500            let cursor = selection.head();
4501            let current_indent = snapshot.indent_size_for_line(cursor.row);
4502            if let Some(suggested_indent) = suggested_indents.get(&cursor.row).copied() {
4503                if cursor.column < suggested_indent.len
4504                    && cursor.column <= current_indent.len
4505                    && current_indent.len <= suggested_indent.len
4506                {
4507                    selection.start = Point::new(cursor.row, suggested_indent.len);
4508                    selection.end = selection.start;
4509                    if row_delta == 0 {
4510                        edits.extend(Buffer::edit_for_indent_size_adjustment(
4511                            cursor.row,
4512                            current_indent,
4513                            suggested_indent,
4514                        ));
4515                        row_delta = suggested_indent.len - current_indent.len;
4516                    }
4517                    continue;
4518                }
4519            }
4520
4521            // Accept copilot suggestion if there is only one selection and the cursor is not
4522            // in the leading whitespace.
4523            if self.selections.count() == 1
4524                && cursor.column >= current_indent.len
4525                && self.has_active_copilot_suggestion(cx)
4526            {
4527                self.accept_copilot_suggestion(cx);
4528                return;
4529            }
4530
4531            // Otherwise, insert a hard or soft tab.
4532            let settings = buffer.settings_at(cursor, cx);
4533            let tab_size = if settings.hard_tabs {
4534                IndentSize::tab()
4535            } else {
4536                let tab_size = settings.tab_size.get();
4537                let char_column = snapshot
4538                    .text_for_range(Point::new(cursor.row, 0)..cursor)
4539                    .flat_map(str::chars)
4540                    .count()
4541                    + row_delta as usize;
4542                let chars_to_next_tab_stop = tab_size - (char_column as u32 % tab_size);
4543                IndentSize::spaces(chars_to_next_tab_stop)
4544            };
4545            selection.start = Point::new(cursor.row, cursor.column + row_delta + tab_size.len);
4546            selection.end = selection.start;
4547            edits.push((cursor..cursor, tab_size.chars().collect::<String>()));
4548            row_delta += tab_size.len;
4549        }
4550
4551        self.transact(cx, |this, cx| {
4552            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
4553            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
4554            this.refresh_copilot_suggestions(true, cx);
4555        });
4556    }
4557
4558    pub fn indent(&mut self, _: &Indent, cx: &mut ViewContext<Self>) {
4559        let mut selections = self.selections.all::<Point>(cx);
4560        let mut prev_edited_row = 0;
4561        let mut row_delta = 0;
4562        let mut edits = Vec::new();
4563        let buffer = self.buffer.read(cx);
4564        let snapshot = buffer.snapshot(cx);
4565        for selection in &mut selections {
4566            if selection.start.row != prev_edited_row {
4567                row_delta = 0;
4568            }
4569            prev_edited_row = selection.end.row;
4570
4571            row_delta =
4572                Self::indent_selection(buffer, &snapshot, selection, &mut edits, row_delta, cx);
4573        }
4574
4575        self.transact(cx, |this, cx| {
4576            this.buffer.update(cx, |b, cx| b.edit(edits, None, cx));
4577            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
4578        });
4579    }
4580
4581    fn indent_selection(
4582        buffer: &MultiBuffer,
4583        snapshot: &MultiBufferSnapshot,
4584        selection: &mut Selection<Point>,
4585        edits: &mut Vec<(Range<Point>, String)>,
4586        delta_for_start_row: u32,
4587        cx: &AppContext,
4588    ) -> u32 {
4589        let settings = buffer.settings_at(selection.start, cx);
4590        let tab_size = settings.tab_size.get();
4591        let indent_kind = if settings.hard_tabs {
4592            IndentKind::Tab
4593        } else {
4594            IndentKind::Space
4595        };
4596        let mut start_row = selection.start.row;
4597        let mut end_row = selection.end.row + 1;
4598
4599        // If a selection ends at the beginning of a line, don't indent
4600        // that last line.
4601        if selection.end.column == 0 {
4602            end_row -= 1;
4603        }
4604
4605        // Avoid re-indenting a row that has already been indented by a
4606        // previous selection, but still update this selection's column
4607        // to reflect that indentation.
4608        if delta_for_start_row > 0 {
4609            start_row += 1;
4610            selection.start.column += delta_for_start_row;
4611            if selection.end.row == selection.start.row {
4612                selection.end.column += delta_for_start_row;
4613            }
4614        }
4615
4616        let mut delta_for_end_row = 0;
4617        for row in start_row..end_row {
4618            let current_indent = snapshot.indent_size_for_line(row);
4619            let indent_delta = match (current_indent.kind, indent_kind) {
4620                (IndentKind::Space, IndentKind::Space) => {
4621                    let columns_to_next_tab_stop = tab_size - (current_indent.len % tab_size);
4622                    IndentSize::spaces(columns_to_next_tab_stop)
4623                }
4624                (IndentKind::Tab, IndentKind::Space) => IndentSize::spaces(tab_size),
4625                (_, IndentKind::Tab) => IndentSize::tab(),
4626            };
4627
4628            let row_start = Point::new(row, 0);
4629            edits.push((
4630                row_start..row_start,
4631                indent_delta.chars().collect::<String>(),
4632            ));
4633
4634            // Update this selection's endpoints to reflect the indentation.
4635            if row == selection.start.row {
4636                selection.start.column += indent_delta.len;
4637            }
4638            if row == selection.end.row {
4639                selection.end.column += indent_delta.len;
4640                delta_for_end_row = indent_delta.len;
4641            }
4642        }
4643
4644        if selection.start.row == selection.end.row {
4645            delta_for_start_row + delta_for_end_row
4646        } else {
4647            delta_for_end_row
4648        }
4649    }
4650
4651    pub fn outdent(&mut self, _: &Outdent, cx: &mut ViewContext<Self>) {
4652        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4653        let selections = self.selections.all::<Point>(cx);
4654        let mut deletion_ranges = Vec::new();
4655        let mut last_outdent = None;
4656        {
4657            let buffer = self.buffer.read(cx);
4658            let snapshot = buffer.snapshot(cx);
4659            for selection in &selections {
4660                let settings = buffer.settings_at(selection.start, cx);
4661                let tab_size = settings.tab_size.get();
4662                let mut rows = selection.spanned_rows(false, &display_map);
4663
4664                // Avoid re-outdenting a row that has already been outdented by a
4665                // previous selection.
4666                if let Some(last_row) = last_outdent {
4667                    if last_row == rows.start {
4668                        rows.start += 1;
4669                    }
4670                }
4671
4672                for row in rows {
4673                    let indent_size = snapshot.indent_size_for_line(row);
4674                    if indent_size.len > 0 {
4675                        let deletion_len = match indent_size.kind {
4676                            IndentKind::Space => {
4677                                let columns_to_prev_tab_stop = indent_size.len % tab_size;
4678                                if columns_to_prev_tab_stop == 0 {
4679                                    tab_size
4680                                } else {
4681                                    columns_to_prev_tab_stop
4682                                }
4683                            }
4684                            IndentKind::Tab => 1,
4685                        };
4686                        deletion_ranges.push(Point::new(row, 0)..Point::new(row, deletion_len));
4687                        last_outdent = Some(row);
4688                    }
4689                }
4690            }
4691        }
4692
4693        self.transact(cx, |this, cx| {
4694            this.buffer.update(cx, |buffer, cx| {
4695                let empty_str: Arc<str> = "".into();
4696                buffer.edit(
4697                    deletion_ranges
4698                        .into_iter()
4699                        .map(|range| (range, empty_str.clone())),
4700                    None,
4701                    cx,
4702                );
4703            });
4704            let selections = this.selections.all::<usize>(cx);
4705            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
4706        });
4707    }
4708
4709    pub fn delete_line(&mut self, _: &DeleteLine, cx: &mut ViewContext<Self>) {
4710        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4711        let selections = self.selections.all::<Point>(cx);
4712
4713        let mut new_cursors = Vec::new();
4714        let mut edit_ranges = Vec::new();
4715        let mut selections = selections.iter().peekable();
4716        while let Some(selection) = selections.next() {
4717            let mut rows = selection.spanned_rows(false, &display_map);
4718            let goal_display_column = selection.head().to_display_point(&display_map).column();
4719
4720            // Accumulate contiguous regions of rows that we want to delete.
4721            while let Some(next_selection) = selections.peek() {
4722                let next_rows = next_selection.spanned_rows(false, &display_map);
4723                if next_rows.start <= rows.end {
4724                    rows.end = next_rows.end;
4725                    selections.next().unwrap();
4726                } else {
4727                    break;
4728                }
4729            }
4730
4731            let buffer = &display_map.buffer_snapshot;
4732            let mut edit_start = Point::new(rows.start, 0).to_offset(buffer);
4733            let edit_end;
4734            let cursor_buffer_row;
4735            if buffer.max_point().row >= rows.end {
4736                // If there's a line after the range, delete the \n from the end of the row range
4737                // and position the cursor on the next line.
4738                edit_end = Point::new(rows.end, 0).to_offset(buffer);
4739                cursor_buffer_row = rows.end;
4740            } else {
4741                // If there isn't a line after the range, delete the \n from the line before the
4742                // start of the row range and position the cursor there.
4743                edit_start = edit_start.saturating_sub(1);
4744                edit_end = buffer.len();
4745                cursor_buffer_row = rows.start.saturating_sub(1);
4746            }
4747
4748            let mut cursor = Point::new(cursor_buffer_row, 0).to_display_point(&display_map);
4749            *cursor.column_mut() =
4750                cmp::min(goal_display_column, display_map.line_len(cursor.row()));
4751
4752            new_cursors.push((
4753                selection.id,
4754                buffer.anchor_after(cursor.to_point(&display_map)),
4755            ));
4756            edit_ranges.push(edit_start..edit_end);
4757        }
4758
4759        self.transact(cx, |this, cx| {
4760            let buffer = this.buffer.update(cx, |buffer, cx| {
4761                let empty_str: Arc<str> = "".into();
4762                buffer.edit(
4763                    edit_ranges
4764                        .into_iter()
4765                        .map(|range| (range, empty_str.clone())),
4766                    None,
4767                    cx,
4768                );
4769                buffer.snapshot(cx)
4770            });
4771            let new_selections = new_cursors
4772                .into_iter()
4773                .map(|(id, cursor)| {
4774                    let cursor = cursor.to_point(&buffer);
4775                    Selection {
4776                        id,
4777                        start: cursor,
4778                        end: cursor,
4779                        reversed: false,
4780                        goal: SelectionGoal::None,
4781                    }
4782                })
4783                .collect();
4784
4785            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4786                s.select(new_selections);
4787            });
4788        });
4789    }
4790
4791    pub fn join_lines(&mut self, _: &JoinLines, cx: &mut ViewContext<Self>) {
4792        let mut row_ranges = Vec::<Range<u32>>::new();
4793        for selection in self.selections.all::<Point>(cx) {
4794            let start = selection.start.row;
4795            let end = if selection.start.row == selection.end.row {
4796                selection.start.row + 1
4797            } else {
4798                selection.end.row
4799            };
4800
4801            if let Some(last_row_range) = row_ranges.last_mut() {
4802                if start <= last_row_range.end {
4803                    last_row_range.end = end;
4804                    continue;
4805                }
4806            }
4807            row_ranges.push(start..end);
4808        }
4809
4810        let snapshot = self.buffer.read(cx).snapshot(cx);
4811        let mut cursor_positions = Vec::new();
4812        for row_range in &row_ranges {
4813            let anchor = snapshot.anchor_before(Point::new(
4814                row_range.end - 1,
4815                snapshot.line_len(row_range.end - 1),
4816            ));
4817            cursor_positions.push(anchor.clone()..anchor);
4818        }
4819
4820        self.transact(cx, |this, cx| {
4821            for row_range in row_ranges.into_iter().rev() {
4822                for row in row_range.rev() {
4823                    let end_of_line = Point::new(row, snapshot.line_len(row));
4824                    let indent = snapshot.indent_size_for_line(row + 1);
4825                    let start_of_next_line = Point::new(row + 1, indent.len);
4826
4827                    let replace = if snapshot.line_len(row + 1) > indent.len {
4828                        " "
4829                    } else {
4830                        ""
4831                    };
4832
4833                    this.buffer.update(cx, |buffer, cx| {
4834                        buffer.edit([(end_of_line..start_of_next_line, replace)], None, cx)
4835                    });
4836                }
4837            }
4838
4839            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4840                s.select_anchor_ranges(cursor_positions)
4841            });
4842        });
4843    }
4844
4845    pub fn sort_lines_case_sensitive(
4846        &mut self,
4847        _: &SortLinesCaseSensitive,
4848        cx: &mut ViewContext<Self>,
4849    ) {
4850        self.manipulate_lines(cx, |lines| lines.sort())
4851    }
4852
4853    pub fn sort_lines_case_insensitive(
4854        &mut self,
4855        _: &SortLinesCaseInsensitive,
4856        cx: &mut ViewContext<Self>,
4857    ) {
4858        self.manipulate_lines(cx, |lines| lines.sort_by_key(|line| line.to_lowercase()))
4859    }
4860
4861    pub fn reverse_lines(&mut self, _: &ReverseLines, cx: &mut ViewContext<Self>) {
4862        self.manipulate_lines(cx, |lines| lines.reverse())
4863    }
4864
4865    pub fn shuffle_lines(&mut self, _: &ShuffleLines, cx: &mut ViewContext<Self>) {
4866        self.manipulate_lines(cx, |lines| lines.shuffle(&mut thread_rng()))
4867    }
4868
4869    fn manipulate_lines<Fn>(&mut self, cx: &mut ViewContext<Self>, mut callback: Fn)
4870    where
4871        Fn: FnMut(&mut [&str]),
4872    {
4873        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4874        let buffer = self.buffer.read(cx).snapshot(cx);
4875
4876        let mut edits = Vec::new();
4877
4878        let selections = self.selections.all::<Point>(cx);
4879        let mut selections = selections.iter().peekable();
4880        let mut contiguous_row_selections = Vec::new();
4881        let mut new_selections = Vec::new();
4882
4883        while let Some(selection) = selections.next() {
4884            let (start_row, end_row) = consume_contiguous_rows(
4885                &mut contiguous_row_selections,
4886                selection,
4887                &display_map,
4888                &mut selections,
4889            );
4890
4891            let start_point = Point::new(start_row, 0);
4892            let end_point = Point::new(end_row - 1, buffer.line_len(end_row - 1));
4893            let text = buffer
4894                .text_for_range(start_point..end_point)
4895                .collect::<String>();
4896            let mut lines = text.split("\n").collect_vec();
4897
4898            let lines_len = lines.len();
4899            callback(&mut lines);
4900
4901            // This is a current limitation with selections.
4902            // If we wanted to support removing or adding lines, we'd need to fix the logic associated with selections.
4903            debug_assert!(
4904                lines.len() == lines_len,
4905                "callback should not change the number of lines"
4906            );
4907
4908            edits.push((start_point..end_point, lines.join("\n")));
4909            let start_anchor = buffer.anchor_after(start_point);
4910            let end_anchor = buffer.anchor_before(end_point);
4911
4912            // Make selection and push
4913            new_selections.push(Selection {
4914                id: selection.id,
4915                start: start_anchor.to_offset(&buffer),
4916                end: end_anchor.to_offset(&buffer),
4917                goal: SelectionGoal::None,
4918                reversed: selection.reversed,
4919            });
4920        }
4921
4922        self.transact(cx, |this, cx| {
4923            this.buffer.update(cx, |buffer, cx| {
4924                buffer.edit(edits, None, cx);
4925            });
4926
4927            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
4928                s.select(new_selections);
4929            });
4930
4931            this.request_autoscroll(Autoscroll::fit(), cx);
4932        });
4933    }
4934
4935    pub fn convert_to_upper_case(&mut self, _: &ConvertToUpperCase, cx: &mut ViewContext<Self>) {
4936        self.manipulate_text(cx, |text| text.to_uppercase())
4937    }
4938
4939    pub fn convert_to_lower_case(&mut self, _: &ConvertToLowerCase, cx: &mut ViewContext<Self>) {
4940        self.manipulate_text(cx, |text| text.to_lowercase())
4941    }
4942
4943    pub fn convert_to_title_case(&mut self, _: &ConvertToTitleCase, cx: &mut ViewContext<Self>) {
4944        self.manipulate_text(cx, |text| {
4945            // Hack to get around the fact that to_case crate doesn't support '\n' as a word boundary
4946            // https://github.com/rutrum/convert-case/issues/16
4947            text.split("\n")
4948                .map(|line| line.to_case(Case::Title))
4949                .join("\n")
4950        })
4951    }
4952
4953    pub fn convert_to_snake_case(&mut self, _: &ConvertToSnakeCase, cx: &mut ViewContext<Self>) {
4954        self.manipulate_text(cx, |text| text.to_case(Case::Snake))
4955    }
4956
4957    pub fn convert_to_kebab_case(&mut self, _: &ConvertToKebabCase, cx: &mut ViewContext<Self>) {
4958        self.manipulate_text(cx, |text| text.to_case(Case::Kebab))
4959    }
4960
4961    pub fn convert_to_upper_camel_case(
4962        &mut self,
4963        _: &ConvertToUpperCamelCase,
4964        cx: &mut ViewContext<Self>,
4965    ) {
4966        self.manipulate_text(cx, |text| {
4967            // Hack to get around the fact that to_case crate doesn't support '\n' as a word boundary
4968            // https://github.com/rutrum/convert-case/issues/16
4969            text.split("\n")
4970                .map(|line| line.to_case(Case::UpperCamel))
4971                .join("\n")
4972        })
4973    }
4974
4975    pub fn convert_to_lower_camel_case(
4976        &mut self,
4977        _: &ConvertToLowerCamelCase,
4978        cx: &mut ViewContext<Self>,
4979    ) {
4980        self.manipulate_text(cx, |text| text.to_case(Case::Camel))
4981    }
4982
4983    fn manipulate_text<Fn>(&mut self, cx: &mut ViewContext<Self>, mut callback: Fn)
4984    where
4985        Fn: FnMut(&str) -> String,
4986    {
4987        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
4988        let buffer = self.buffer.read(cx).snapshot(cx);
4989
4990        let mut new_selections = Vec::new();
4991        let mut edits = Vec::new();
4992        let mut selection_adjustment = 0i32;
4993
4994        for selection in self.selections.all::<usize>(cx) {
4995            let selection_is_empty = selection.is_empty();
4996
4997            let (start, end) = if selection_is_empty {
4998                let word_range = movement::surrounding_word(
4999                    &display_map,
5000                    selection.start.to_display_point(&display_map),
5001                );
5002                let start = word_range.start.to_offset(&display_map, Bias::Left);
5003                let end = word_range.end.to_offset(&display_map, Bias::Left);
5004                (start, end)
5005            } else {
5006                (selection.start, selection.end)
5007            };
5008
5009            let text = buffer.text_for_range(start..end).collect::<String>();
5010            let old_length = text.len() as i32;
5011            let text = callback(&text);
5012
5013            new_selections.push(Selection {
5014                start: (start as i32 - selection_adjustment) as usize,
5015                end: ((start + text.len()) as i32 - selection_adjustment) as usize,
5016                goal: SelectionGoal::None,
5017                ..selection
5018            });
5019
5020            selection_adjustment += old_length - text.len() as i32;
5021
5022            edits.push((start..end, text));
5023        }
5024
5025        self.transact(cx, |this, cx| {
5026            this.buffer.update(cx, |buffer, cx| {
5027                buffer.edit(edits, None, cx);
5028            });
5029
5030            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5031                s.select(new_selections);
5032            });
5033
5034            this.request_autoscroll(Autoscroll::fit(), cx);
5035        });
5036    }
5037
5038    pub fn duplicate_line(&mut self, _: &DuplicateLine, cx: &mut ViewContext<Self>) {
5039        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5040        let buffer = &display_map.buffer_snapshot;
5041        let selections = self.selections.all::<Point>(cx);
5042
5043        let mut edits = Vec::new();
5044        let mut selections_iter = selections.iter().peekable();
5045        while let Some(selection) = selections_iter.next() {
5046            // Avoid duplicating the same lines twice.
5047            let mut rows = selection.spanned_rows(false, &display_map);
5048
5049            while let Some(next_selection) = selections_iter.peek() {
5050                let next_rows = next_selection.spanned_rows(false, &display_map);
5051                if next_rows.start < rows.end {
5052                    rows.end = next_rows.end;
5053                    selections_iter.next().unwrap();
5054                } else {
5055                    break;
5056                }
5057            }
5058
5059            // Copy the text from the selected row region and splice it at the start of the region.
5060            let start = Point::new(rows.start, 0);
5061            let end = Point::new(rows.end - 1, buffer.line_len(rows.end - 1));
5062            let text = buffer
5063                .text_for_range(start..end)
5064                .chain(Some("\n"))
5065                .collect::<String>();
5066            edits.push((start..start, text));
5067        }
5068
5069        self.transact(cx, |this, cx| {
5070            this.buffer.update(cx, |buffer, cx| {
5071                buffer.edit(edits, None, cx);
5072            });
5073
5074            this.request_autoscroll(Autoscroll::fit(), cx);
5075        });
5076    }
5077
5078    pub fn move_line_up(&mut self, _: &MoveLineUp, cx: &mut ViewContext<Self>) {
5079        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5080        let buffer = self.buffer.read(cx).snapshot(cx);
5081
5082        let mut edits = Vec::new();
5083        let mut unfold_ranges = Vec::new();
5084        let mut refold_ranges = Vec::new();
5085
5086        let selections = self.selections.all::<Point>(cx);
5087        let mut selections = selections.iter().peekable();
5088        let mut contiguous_row_selections = Vec::new();
5089        let mut new_selections = Vec::new();
5090
5091        while let Some(selection) = selections.next() {
5092            // Find all the selections that span a contiguous row range
5093            let (start_row, end_row) = consume_contiguous_rows(
5094                &mut contiguous_row_selections,
5095                selection,
5096                &display_map,
5097                &mut selections,
5098            );
5099
5100            // Move the text spanned by the row range to be before the line preceding the row range
5101            if start_row > 0 {
5102                let range_to_move = Point::new(start_row - 1, buffer.line_len(start_row - 1))
5103                    ..Point::new(end_row - 1, buffer.line_len(end_row - 1));
5104                let insertion_point = display_map
5105                    .prev_line_boundary(Point::new(start_row - 1, 0))
5106                    .0;
5107
5108                // Don't move lines across excerpts
5109                if buffer
5110                    .excerpt_boundaries_in_range((
5111                        Bound::Excluded(insertion_point),
5112                        Bound::Included(range_to_move.end),
5113                    ))
5114                    .next()
5115                    .is_none()
5116                {
5117                    let text = buffer
5118                        .text_for_range(range_to_move.clone())
5119                        .flat_map(|s| s.chars())
5120                        .skip(1)
5121                        .chain(['\n'])
5122                        .collect::<String>();
5123
5124                    edits.push((
5125                        buffer.anchor_after(range_to_move.start)
5126                            ..buffer.anchor_before(range_to_move.end),
5127                        String::new(),
5128                    ));
5129                    let insertion_anchor = buffer.anchor_after(insertion_point);
5130                    edits.push((insertion_anchor..insertion_anchor, text));
5131
5132                    let row_delta = range_to_move.start.row - insertion_point.row + 1;
5133
5134                    // Move selections up
5135                    new_selections.extend(contiguous_row_selections.drain(..).map(
5136                        |mut selection| {
5137                            selection.start.row -= row_delta;
5138                            selection.end.row -= row_delta;
5139                            selection
5140                        },
5141                    ));
5142
5143                    // Move folds up
5144                    unfold_ranges.push(range_to_move.clone());
5145                    for fold in display_map.folds_in_range(
5146                        buffer.anchor_before(range_to_move.start)
5147                            ..buffer.anchor_after(range_to_move.end),
5148                    ) {
5149                        let mut start = fold.range.start.to_point(&buffer);
5150                        let mut end = fold.range.end.to_point(&buffer);
5151                        start.row -= row_delta;
5152                        end.row -= row_delta;
5153                        refold_ranges.push(start..end);
5154                    }
5155                }
5156            }
5157
5158            // If we didn't move line(s), preserve the existing selections
5159            new_selections.append(&mut contiguous_row_selections);
5160        }
5161
5162        self.transact(cx, |this, cx| {
5163            this.unfold_ranges(unfold_ranges, true, true, cx);
5164            this.buffer.update(cx, |buffer, cx| {
5165                for (range, text) in edits {
5166                    buffer.edit([(range, text)], None, cx);
5167                }
5168            });
5169            this.fold_ranges(refold_ranges, true, cx);
5170            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5171                s.select(new_selections);
5172            })
5173        });
5174    }
5175
5176    pub fn move_line_down(&mut self, _: &MoveLineDown, cx: &mut ViewContext<Self>) {
5177        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
5178        let buffer = self.buffer.read(cx).snapshot(cx);
5179
5180        let mut edits = Vec::new();
5181        let mut unfold_ranges = Vec::new();
5182        let mut refold_ranges = Vec::new();
5183
5184        let selections = self.selections.all::<Point>(cx);
5185        let mut selections = selections.iter().peekable();
5186        let mut contiguous_row_selections = Vec::new();
5187        let mut new_selections = Vec::new();
5188
5189        while let Some(selection) = selections.next() {
5190            // Find all the selections that span a contiguous row range
5191            let (start_row, end_row) = consume_contiguous_rows(
5192                &mut contiguous_row_selections,
5193                selection,
5194                &display_map,
5195                &mut selections,
5196            );
5197
5198            // Move the text spanned by the row range to be after the last line of the row range
5199            if end_row <= buffer.max_point().row {
5200                let range_to_move = Point::new(start_row, 0)..Point::new(end_row, 0);
5201                let insertion_point = display_map.next_line_boundary(Point::new(end_row, 0)).0;
5202
5203                // Don't move lines across excerpt boundaries
5204                if buffer
5205                    .excerpt_boundaries_in_range((
5206                        Bound::Excluded(range_to_move.start),
5207                        Bound::Included(insertion_point),
5208                    ))
5209                    .next()
5210                    .is_none()
5211                {
5212                    let mut text = String::from("\n");
5213                    text.extend(buffer.text_for_range(range_to_move.clone()));
5214                    text.pop(); // Drop trailing newline
5215                    edits.push((
5216                        buffer.anchor_after(range_to_move.start)
5217                            ..buffer.anchor_before(range_to_move.end),
5218                        String::new(),
5219                    ));
5220                    let insertion_anchor = buffer.anchor_after(insertion_point);
5221                    edits.push((insertion_anchor..insertion_anchor, text));
5222
5223                    let row_delta = insertion_point.row - range_to_move.end.row + 1;
5224
5225                    // Move selections down
5226                    new_selections.extend(contiguous_row_selections.drain(..).map(
5227                        |mut selection| {
5228                            selection.start.row += row_delta;
5229                            selection.end.row += row_delta;
5230                            selection
5231                        },
5232                    ));
5233
5234                    // Move folds down
5235                    unfold_ranges.push(range_to_move.clone());
5236                    for fold in display_map.folds_in_range(
5237                        buffer.anchor_before(range_to_move.start)
5238                            ..buffer.anchor_after(range_to_move.end),
5239                    ) {
5240                        let mut start = fold.range.start.to_point(&buffer);
5241                        let mut end = fold.range.end.to_point(&buffer);
5242                        start.row += row_delta;
5243                        end.row += row_delta;
5244                        refold_ranges.push(start..end);
5245                    }
5246                }
5247            }
5248
5249            // If we didn't move line(s), preserve the existing selections
5250            new_selections.append(&mut contiguous_row_selections);
5251        }
5252
5253        self.transact(cx, |this, cx| {
5254            this.unfold_ranges(unfold_ranges, true, true, cx);
5255            this.buffer.update(cx, |buffer, cx| {
5256                for (range, text) in edits {
5257                    buffer.edit([(range, text)], None, cx);
5258                }
5259            });
5260            this.fold_ranges(refold_ranges, true, cx);
5261            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(new_selections));
5262        });
5263    }
5264
5265    pub fn transpose(&mut self, _: &Transpose, cx: &mut ViewContext<Self>) {
5266        let text_layout_details = &self.text_layout_details(cx);
5267        self.transact(cx, |this, cx| {
5268            let edits = this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5269                let mut edits: Vec<(Range<usize>, String)> = Default::default();
5270                let line_mode = s.line_mode;
5271                s.move_with(|display_map, selection| {
5272                    if !selection.is_empty() || line_mode {
5273                        return;
5274                    }
5275
5276                    let mut head = selection.head();
5277                    let mut transpose_offset = head.to_offset(display_map, Bias::Right);
5278                    if head.column() == display_map.line_len(head.row()) {
5279                        transpose_offset = display_map
5280                            .buffer_snapshot
5281                            .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
5282                    }
5283
5284                    if transpose_offset == 0 {
5285                        return;
5286                    }
5287
5288                    *head.column_mut() += 1;
5289                    head = display_map.clip_point(head, Bias::Right);
5290                    let goal = SelectionGoal::HorizontalPosition(
5291                        display_map
5292                            .x_for_display_point(head, &text_layout_details)
5293                            .into(),
5294                    );
5295                    selection.collapse_to(head, goal);
5296
5297                    let transpose_start = display_map
5298                        .buffer_snapshot
5299                        .clip_offset(transpose_offset.saturating_sub(1), Bias::Left);
5300                    if edits.last().map_or(true, |e| e.0.end <= transpose_start) {
5301                        let transpose_end = display_map
5302                            .buffer_snapshot
5303                            .clip_offset(transpose_offset + 1, Bias::Right);
5304                        if let Some(ch) =
5305                            display_map.buffer_snapshot.chars_at(transpose_start).next()
5306                        {
5307                            edits.push((transpose_start..transpose_offset, String::new()));
5308                            edits.push((transpose_end..transpose_end, ch.to_string()));
5309                        }
5310                    }
5311                });
5312                edits
5313            });
5314            this.buffer
5315                .update(cx, |buffer, cx| buffer.edit(edits, None, cx));
5316            let selections = this.selections.all::<usize>(cx);
5317            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5318                s.select(selections);
5319            });
5320        });
5321    }
5322
5323    pub fn cut(&mut self, _: &Cut, cx: &mut ViewContext<Self>) {
5324        let mut text = String::new();
5325        let buffer = self.buffer.read(cx).snapshot(cx);
5326        let mut selections = self.selections.all::<Point>(cx);
5327        let mut clipboard_selections = Vec::with_capacity(selections.len());
5328        {
5329            let max_point = buffer.max_point();
5330            let mut is_first = true;
5331            for selection in &mut selections {
5332                let is_entire_line = selection.is_empty() || self.selections.line_mode;
5333                if is_entire_line {
5334                    selection.start = Point::new(selection.start.row, 0);
5335                    selection.end = cmp::min(max_point, Point::new(selection.end.row + 1, 0));
5336                    selection.goal = SelectionGoal::None;
5337                }
5338                if is_first {
5339                    is_first = false;
5340                } else {
5341                    text += "\n";
5342                }
5343                let mut len = 0;
5344                for chunk in buffer.text_for_range(selection.start..selection.end) {
5345                    text.push_str(chunk);
5346                    len += chunk.len();
5347                }
5348                clipboard_selections.push(ClipboardSelection {
5349                    len,
5350                    is_entire_line,
5351                    first_line_indent: buffer.indent_size_for_line(selection.start.row).len,
5352                });
5353            }
5354        }
5355
5356        self.transact(cx, |this, cx| {
5357            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5358                s.select(selections);
5359            });
5360            this.insert("", cx);
5361            cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
5362        });
5363    }
5364
5365    pub fn copy(&mut self, _: &Copy, cx: &mut ViewContext<Self>) {
5366        let selections = self.selections.all::<Point>(cx);
5367        let buffer = self.buffer.read(cx).read(cx);
5368        let mut text = String::new();
5369
5370        let mut clipboard_selections = Vec::with_capacity(selections.len());
5371        {
5372            let max_point = buffer.max_point();
5373            let mut is_first = true;
5374            for selection in selections.iter() {
5375                let mut start = selection.start;
5376                let mut end = selection.end;
5377                let is_entire_line = selection.is_empty() || self.selections.line_mode;
5378                if is_entire_line {
5379                    start = Point::new(start.row, 0);
5380                    end = cmp::min(max_point, Point::new(end.row + 1, 0));
5381                }
5382                if is_first {
5383                    is_first = false;
5384                } else {
5385                    text += "\n";
5386                }
5387                let mut len = 0;
5388                for chunk in buffer.text_for_range(start..end) {
5389                    text.push_str(chunk);
5390                    len += chunk.len();
5391                }
5392                clipboard_selections.push(ClipboardSelection {
5393                    len,
5394                    is_entire_line,
5395                    first_line_indent: buffer.indent_size_for_line(start.row).len,
5396                });
5397            }
5398        }
5399
5400        cx.write_to_clipboard(ClipboardItem::new(text).with_metadata(clipboard_selections));
5401    }
5402
5403    pub fn paste(&mut self, _: &Paste, cx: &mut ViewContext<Self>) {
5404        self.transact(cx, |this, cx| {
5405            if let Some(item) = cx.read_from_clipboard() {
5406                let clipboard_text = Cow::Borrowed(item.text());
5407                if let Some(mut clipboard_selections) = item.metadata::<Vec<ClipboardSelection>>() {
5408                    let old_selections = this.selections.all::<usize>(cx);
5409                    let all_selections_were_entire_line =
5410                        clipboard_selections.iter().all(|s| s.is_entire_line);
5411                    let first_selection_indent_column =
5412                        clipboard_selections.first().map(|s| s.first_line_indent);
5413                    if clipboard_selections.len() != old_selections.len() {
5414                        clipboard_selections.drain(..);
5415                    }
5416
5417                    this.buffer.update(cx, |buffer, cx| {
5418                        let snapshot = buffer.read(cx);
5419                        let mut start_offset = 0;
5420                        let mut edits = Vec::new();
5421                        let mut original_indent_columns = Vec::new();
5422                        let line_mode = this.selections.line_mode;
5423                        for (ix, selection) in old_selections.iter().enumerate() {
5424                            let to_insert;
5425                            let entire_line;
5426                            let original_indent_column;
5427                            if let Some(clipboard_selection) = clipboard_selections.get(ix) {
5428                                let end_offset = start_offset + clipboard_selection.len;
5429                                to_insert = &clipboard_text[start_offset..end_offset];
5430                                entire_line = clipboard_selection.is_entire_line;
5431                                start_offset = end_offset + 1;
5432                                original_indent_column =
5433                                    Some(clipboard_selection.first_line_indent);
5434                            } else {
5435                                to_insert = clipboard_text.as_str();
5436                                entire_line = all_selections_were_entire_line;
5437                                original_indent_column = first_selection_indent_column
5438                            }
5439
5440                            // If the corresponding selection was empty when this slice of the
5441                            // clipboard text was written, then the entire line containing the
5442                            // selection was copied. If this selection is also currently empty,
5443                            // then paste the line before the current line of the buffer.
5444                            let range = if selection.is_empty() && !line_mode && entire_line {
5445                                let column = selection.start.to_point(&snapshot).column as usize;
5446                                let line_start = selection.start - column;
5447                                line_start..line_start
5448                            } else {
5449                                selection.range()
5450                            };
5451
5452                            edits.push((range, to_insert));
5453                            original_indent_columns.extend(original_indent_column);
5454                        }
5455                        drop(snapshot);
5456
5457                        buffer.edit(
5458                            edits,
5459                            Some(AutoindentMode::Block {
5460                                original_indent_columns,
5461                            }),
5462                            cx,
5463                        );
5464                    });
5465
5466                    let selections = this.selections.all::<usize>(cx);
5467                    this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
5468                } else {
5469                    this.insert(&clipboard_text, cx);
5470                }
5471            }
5472        });
5473    }
5474
5475    pub fn undo(&mut self, _: &Undo, cx: &mut ViewContext<Self>) {
5476        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.undo(cx)) {
5477            if let Some((selections, _)) = self.selection_history.transaction(tx_id).cloned() {
5478                self.change_selections(None, cx, |s| {
5479                    s.select_anchors(selections.to_vec());
5480                });
5481            }
5482            self.request_autoscroll(Autoscroll::fit(), cx);
5483            self.unmark_text(cx);
5484            self.refresh_copilot_suggestions(true, cx);
5485            cx.emit(EditorEvent::Edited);
5486        }
5487    }
5488
5489    pub fn redo(&mut self, _: &Redo, cx: &mut ViewContext<Self>) {
5490        if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.redo(cx)) {
5491            if let Some((_, Some(selections))) = self.selection_history.transaction(tx_id).cloned()
5492            {
5493                self.change_selections(None, cx, |s| {
5494                    s.select_anchors(selections.to_vec());
5495                });
5496            }
5497            self.request_autoscroll(Autoscroll::fit(), cx);
5498            self.unmark_text(cx);
5499            self.refresh_copilot_suggestions(true, cx);
5500            cx.emit(EditorEvent::Edited);
5501        }
5502    }
5503
5504    pub fn finalize_last_transaction(&mut self, cx: &mut ViewContext<Self>) {
5505        self.buffer
5506            .update(cx, |buffer, cx| buffer.finalize_last_transaction(cx));
5507    }
5508
5509    pub fn move_left(&mut self, _: &MoveLeft, cx: &mut ViewContext<Self>) {
5510        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5511            let line_mode = s.line_mode;
5512            s.move_with(|map, selection| {
5513                let cursor = if selection.is_empty() && !line_mode {
5514                    movement::left(map, selection.start)
5515                } else {
5516                    selection.start
5517                };
5518                selection.collapse_to(cursor, SelectionGoal::None);
5519            });
5520        })
5521    }
5522
5523    pub fn select_left(&mut self, _: &SelectLeft, cx: &mut ViewContext<Self>) {
5524        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5525            s.move_heads_with(|map, head, _| (movement::left(map, head), SelectionGoal::None));
5526        })
5527    }
5528
5529    pub fn move_right(&mut self, _: &MoveRight, cx: &mut ViewContext<Self>) {
5530        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5531            let line_mode = s.line_mode;
5532            s.move_with(|map, selection| {
5533                let cursor = if selection.is_empty() && !line_mode {
5534                    movement::right(map, selection.end)
5535                } else {
5536                    selection.end
5537                };
5538                selection.collapse_to(cursor, SelectionGoal::None)
5539            });
5540        })
5541    }
5542
5543    pub fn select_right(&mut self, _: &SelectRight, cx: &mut ViewContext<Self>) {
5544        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5545            s.move_heads_with(|map, head, _| (movement::right(map, head), SelectionGoal::None));
5546        })
5547    }
5548
5549    pub fn move_up(&mut self, _: &MoveUp, cx: &mut ViewContext<Self>) {
5550        if self.take_rename(true, cx).is_some() {
5551            return;
5552        }
5553
5554        if matches!(self.mode, EditorMode::SingleLine) {
5555            cx.propagate();
5556            return;
5557        }
5558
5559        let text_layout_details = &self.text_layout_details(cx);
5560
5561        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5562            let line_mode = s.line_mode;
5563            s.move_with(|map, selection| {
5564                if !selection.is_empty() && !line_mode {
5565                    selection.goal = SelectionGoal::None;
5566                }
5567                let (cursor, goal) = movement::up(
5568                    map,
5569                    selection.start,
5570                    selection.goal,
5571                    false,
5572                    &text_layout_details,
5573                );
5574                selection.collapse_to(cursor, goal);
5575            });
5576        })
5577    }
5578
5579    pub fn move_page_up(&mut self, action: &MovePageUp, cx: &mut ViewContext<Self>) {
5580        if self.take_rename(true, cx).is_some() {
5581            return;
5582        }
5583
5584        if matches!(self.mode, EditorMode::SingleLine) {
5585            cx.propagate();
5586            return;
5587        }
5588
5589        let row_count = if let Some(row_count) = self.visible_line_count() {
5590            row_count as u32 - 1
5591        } else {
5592            return;
5593        };
5594
5595        let autoscroll = if action.center_cursor {
5596            Autoscroll::center()
5597        } else {
5598            Autoscroll::fit()
5599        };
5600
5601        let text_layout_details = &self.text_layout_details(cx);
5602
5603        self.change_selections(Some(autoscroll), cx, |s| {
5604            let line_mode = s.line_mode;
5605            s.move_with(|map, selection| {
5606                if !selection.is_empty() && !line_mode {
5607                    selection.goal = SelectionGoal::None;
5608                }
5609                let (cursor, goal) = movement::up_by_rows(
5610                    map,
5611                    selection.end,
5612                    row_count,
5613                    selection.goal,
5614                    false,
5615                    &text_layout_details,
5616                );
5617                selection.collapse_to(cursor, goal);
5618            });
5619        });
5620    }
5621
5622    pub fn select_up(&mut self, _: &SelectUp, cx: &mut ViewContext<Self>) {
5623        let text_layout_details = &self.text_layout_details(cx);
5624        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5625            s.move_heads_with(|map, head, goal| {
5626                movement::up(map, head, goal, false, &text_layout_details)
5627            })
5628        })
5629    }
5630
5631    pub fn move_down(&mut self, _: &MoveDown, cx: &mut ViewContext<Self>) {
5632        self.take_rename(true, cx);
5633
5634        if self.mode == EditorMode::SingleLine {
5635            cx.propagate();
5636            return;
5637        }
5638
5639        let text_layout_details = &self.text_layout_details(cx);
5640        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5641            let line_mode = s.line_mode;
5642            s.move_with(|map, selection| {
5643                if !selection.is_empty() && !line_mode {
5644                    selection.goal = SelectionGoal::None;
5645                }
5646                let (cursor, goal) = movement::down(
5647                    map,
5648                    selection.end,
5649                    selection.goal,
5650                    false,
5651                    &text_layout_details,
5652                );
5653                selection.collapse_to(cursor, goal);
5654            });
5655        });
5656    }
5657
5658    pub fn move_page_down(&mut self, action: &MovePageDown, cx: &mut ViewContext<Self>) {
5659        if self.take_rename(true, cx).is_some() {
5660            return;
5661        }
5662
5663        if self
5664            .context_menu
5665            .write()
5666            .as_mut()
5667            .map(|menu| menu.select_last(self.project.as_ref(), cx))
5668            .unwrap_or(false)
5669        {
5670            return;
5671        }
5672
5673        if matches!(self.mode, EditorMode::SingleLine) {
5674            cx.propagate();
5675            return;
5676        }
5677
5678        let row_count = if let Some(row_count) = self.visible_line_count() {
5679            row_count as u32 - 1
5680        } else {
5681            return;
5682        };
5683
5684        let autoscroll = if action.center_cursor {
5685            Autoscroll::center()
5686        } else {
5687            Autoscroll::fit()
5688        };
5689
5690        let text_layout_details = &self.text_layout_details(cx);
5691        self.change_selections(Some(autoscroll), cx, |s| {
5692            let line_mode = s.line_mode;
5693            s.move_with(|map, selection| {
5694                if !selection.is_empty() && !line_mode {
5695                    selection.goal = SelectionGoal::None;
5696                }
5697                let (cursor, goal) = movement::down_by_rows(
5698                    map,
5699                    selection.end,
5700                    row_count,
5701                    selection.goal,
5702                    false,
5703                    &text_layout_details,
5704                );
5705                selection.collapse_to(cursor, goal);
5706            });
5707        });
5708    }
5709
5710    pub fn select_down(&mut self, _: &SelectDown, cx: &mut ViewContext<Self>) {
5711        let text_layout_details = &self.text_layout_details(cx);
5712        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5713            s.move_heads_with(|map, head, goal| {
5714                movement::down(map, head, goal, false, &text_layout_details)
5715            })
5716        });
5717    }
5718
5719    pub fn context_menu_first(&mut self, _: &ContextMenuFirst, cx: &mut ViewContext<Self>) {
5720        if let Some(context_menu) = self.context_menu.write().as_mut() {
5721            context_menu.select_first(self.project.as_ref(), cx);
5722        }
5723    }
5724
5725    pub fn context_menu_prev(&mut self, _: &ContextMenuPrev, cx: &mut ViewContext<Self>) {
5726        if let Some(context_menu) = self.context_menu.write().as_mut() {
5727            context_menu.select_prev(self.project.as_ref(), cx);
5728        }
5729    }
5730
5731    pub fn context_menu_next(&mut self, _: &ContextMenuNext, cx: &mut ViewContext<Self>) {
5732        if let Some(context_menu) = self.context_menu.write().as_mut() {
5733            context_menu.select_next(self.project.as_ref(), cx);
5734        }
5735    }
5736
5737    pub fn context_menu_last(&mut self, _: &ContextMenuLast, cx: &mut ViewContext<Self>) {
5738        if let Some(context_menu) = self.context_menu.write().as_mut() {
5739            context_menu.select_last(self.project.as_ref(), cx);
5740        }
5741    }
5742
5743    pub fn move_to_previous_word_start(
5744        &mut self,
5745        _: &MoveToPreviousWordStart,
5746        cx: &mut ViewContext<Self>,
5747    ) {
5748        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5749            s.move_cursors_with(|map, head, _| {
5750                (
5751                    movement::previous_word_start(map, head),
5752                    SelectionGoal::None,
5753                )
5754            });
5755        })
5756    }
5757
5758    pub fn move_to_previous_subword_start(
5759        &mut self,
5760        _: &MoveToPreviousSubwordStart,
5761        cx: &mut ViewContext<Self>,
5762    ) {
5763        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5764            s.move_cursors_with(|map, head, _| {
5765                (
5766                    movement::previous_subword_start(map, head),
5767                    SelectionGoal::None,
5768                )
5769            });
5770        })
5771    }
5772
5773    pub fn select_to_previous_word_start(
5774        &mut self,
5775        _: &SelectToPreviousWordStart,
5776        cx: &mut ViewContext<Self>,
5777    ) {
5778        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5779            s.move_heads_with(|map, head, _| {
5780                (
5781                    movement::previous_word_start(map, head),
5782                    SelectionGoal::None,
5783                )
5784            });
5785        })
5786    }
5787
5788    pub fn select_to_previous_subword_start(
5789        &mut self,
5790        _: &SelectToPreviousSubwordStart,
5791        cx: &mut ViewContext<Self>,
5792    ) {
5793        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5794            s.move_heads_with(|map, head, _| {
5795                (
5796                    movement::previous_subword_start(map, head),
5797                    SelectionGoal::None,
5798                )
5799            });
5800        })
5801    }
5802
5803    pub fn delete_to_previous_word_start(
5804        &mut self,
5805        _: &DeleteToPreviousWordStart,
5806        cx: &mut ViewContext<Self>,
5807    ) {
5808        self.transact(cx, |this, cx| {
5809            this.select_autoclose_pair(cx);
5810            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5811                let line_mode = s.line_mode;
5812                s.move_with(|map, selection| {
5813                    if selection.is_empty() && !line_mode {
5814                        let cursor = movement::previous_word_start(map, selection.head());
5815                        selection.set_head(cursor, SelectionGoal::None);
5816                    }
5817                });
5818            });
5819            this.insert("", cx);
5820        });
5821    }
5822
5823    pub fn delete_to_previous_subword_start(
5824        &mut self,
5825        _: &DeleteToPreviousSubwordStart,
5826        cx: &mut ViewContext<Self>,
5827    ) {
5828        self.transact(cx, |this, cx| {
5829            this.select_autoclose_pair(cx);
5830            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5831                let line_mode = s.line_mode;
5832                s.move_with(|map, selection| {
5833                    if selection.is_empty() && !line_mode {
5834                        let cursor = movement::previous_subword_start(map, selection.head());
5835                        selection.set_head(cursor, SelectionGoal::None);
5836                    }
5837                });
5838            });
5839            this.insert("", cx);
5840        });
5841    }
5842
5843    pub fn move_to_next_word_end(&mut self, _: &MoveToNextWordEnd, cx: &mut ViewContext<Self>) {
5844        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5845            s.move_cursors_with(|map, head, _| {
5846                (movement::next_word_end(map, head), SelectionGoal::None)
5847            });
5848        })
5849    }
5850
5851    pub fn move_to_next_subword_end(
5852        &mut self,
5853        _: &MoveToNextSubwordEnd,
5854        cx: &mut ViewContext<Self>,
5855    ) {
5856        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5857            s.move_cursors_with(|map, head, _| {
5858                (movement::next_subword_end(map, head), SelectionGoal::None)
5859            });
5860        })
5861    }
5862
5863    pub fn select_to_next_word_end(&mut self, _: &SelectToNextWordEnd, cx: &mut ViewContext<Self>) {
5864        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5865            s.move_heads_with(|map, head, _| {
5866                (movement::next_word_end(map, head), SelectionGoal::None)
5867            });
5868        })
5869    }
5870
5871    pub fn select_to_next_subword_end(
5872        &mut self,
5873        _: &SelectToNextSubwordEnd,
5874        cx: &mut ViewContext<Self>,
5875    ) {
5876        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5877            s.move_heads_with(|map, head, _| {
5878                (movement::next_subword_end(map, head), SelectionGoal::None)
5879            });
5880        })
5881    }
5882
5883    pub fn delete_to_next_word_end(&mut self, _: &DeleteToNextWordEnd, cx: &mut ViewContext<Self>) {
5884        self.transact(cx, |this, cx| {
5885            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5886                let line_mode = s.line_mode;
5887                s.move_with(|map, selection| {
5888                    if selection.is_empty() && !line_mode {
5889                        let cursor = movement::next_word_end(map, selection.head());
5890                        selection.set_head(cursor, SelectionGoal::None);
5891                    }
5892                });
5893            });
5894            this.insert("", cx);
5895        });
5896    }
5897
5898    pub fn delete_to_next_subword_end(
5899        &mut self,
5900        _: &DeleteToNextSubwordEnd,
5901        cx: &mut ViewContext<Self>,
5902    ) {
5903        self.transact(cx, |this, cx| {
5904            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5905                s.move_with(|map, selection| {
5906                    if selection.is_empty() {
5907                        let cursor = movement::next_subword_end(map, selection.head());
5908                        selection.set_head(cursor, SelectionGoal::None);
5909                    }
5910                });
5911            });
5912            this.insert("", cx);
5913        });
5914    }
5915
5916    pub fn move_to_beginning_of_line(
5917        &mut self,
5918        _: &MoveToBeginningOfLine,
5919        cx: &mut ViewContext<Self>,
5920    ) {
5921        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5922            s.move_cursors_with(|map, head, _| {
5923                (
5924                    movement::indented_line_beginning(map, head, true),
5925                    SelectionGoal::None,
5926                )
5927            });
5928        })
5929    }
5930
5931    pub fn select_to_beginning_of_line(
5932        &mut self,
5933        action: &SelectToBeginningOfLine,
5934        cx: &mut ViewContext<Self>,
5935    ) {
5936        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5937            s.move_heads_with(|map, head, _| {
5938                (
5939                    movement::indented_line_beginning(map, head, action.stop_at_soft_wraps),
5940                    SelectionGoal::None,
5941                )
5942            });
5943        });
5944    }
5945
5946    pub fn delete_to_beginning_of_line(
5947        &mut self,
5948        _: &DeleteToBeginningOfLine,
5949        cx: &mut ViewContext<Self>,
5950    ) {
5951        self.transact(cx, |this, cx| {
5952            this.change_selections(Some(Autoscroll::fit()), cx, |s| {
5953                s.move_with(|_, selection| {
5954                    selection.reversed = true;
5955                });
5956            });
5957
5958            this.select_to_beginning_of_line(
5959                &SelectToBeginningOfLine {
5960                    stop_at_soft_wraps: false,
5961                },
5962                cx,
5963            );
5964            this.backspace(&Backspace, cx);
5965        });
5966    }
5967
5968    pub fn move_to_end_of_line(&mut self, _: &MoveToEndOfLine, cx: &mut ViewContext<Self>) {
5969        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5970            s.move_cursors_with(|map, head, _| {
5971                (movement::line_end(map, head, true), SelectionGoal::None)
5972            });
5973        })
5974    }
5975
5976    pub fn select_to_end_of_line(
5977        &mut self,
5978        action: &SelectToEndOfLine,
5979        cx: &mut ViewContext<Self>,
5980    ) {
5981        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
5982            s.move_heads_with(|map, head, _| {
5983                (
5984                    movement::line_end(map, head, action.stop_at_soft_wraps),
5985                    SelectionGoal::None,
5986                )
5987            });
5988        })
5989    }
5990
5991    pub fn delete_to_end_of_line(&mut self, _: &DeleteToEndOfLine, cx: &mut ViewContext<Self>) {
5992        self.transact(cx, |this, cx| {
5993            this.select_to_end_of_line(
5994                &SelectToEndOfLine {
5995                    stop_at_soft_wraps: false,
5996                },
5997                cx,
5998            );
5999            this.delete(&Delete, cx);
6000        });
6001    }
6002
6003    pub fn cut_to_end_of_line(&mut self, _: &CutToEndOfLine, cx: &mut ViewContext<Self>) {
6004        self.transact(cx, |this, cx| {
6005            this.select_to_end_of_line(
6006                &SelectToEndOfLine {
6007                    stop_at_soft_wraps: false,
6008                },
6009                cx,
6010            );
6011            this.cut(&Cut, cx);
6012        });
6013    }
6014
6015    pub fn move_to_start_of_paragraph(
6016        &mut self,
6017        _: &MoveToStartOfParagraph,
6018        cx: &mut ViewContext<Self>,
6019    ) {
6020        if matches!(self.mode, EditorMode::SingleLine) {
6021            cx.propagate();
6022            return;
6023        }
6024
6025        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6026            s.move_with(|map, selection| {
6027                selection.collapse_to(
6028                    movement::start_of_paragraph(map, selection.head(), 1),
6029                    SelectionGoal::None,
6030                )
6031            });
6032        })
6033    }
6034
6035    pub fn move_to_end_of_paragraph(
6036        &mut self,
6037        _: &MoveToEndOfParagraph,
6038        cx: &mut ViewContext<Self>,
6039    ) {
6040        if matches!(self.mode, EditorMode::SingleLine) {
6041            cx.propagate();
6042            return;
6043        }
6044
6045        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6046            s.move_with(|map, selection| {
6047                selection.collapse_to(
6048                    movement::end_of_paragraph(map, selection.head(), 1),
6049                    SelectionGoal::None,
6050                )
6051            });
6052        })
6053    }
6054
6055    pub fn select_to_start_of_paragraph(
6056        &mut self,
6057        _: &SelectToStartOfParagraph,
6058        cx: &mut ViewContext<Self>,
6059    ) {
6060        if matches!(self.mode, EditorMode::SingleLine) {
6061            cx.propagate();
6062            return;
6063        }
6064
6065        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6066            s.move_heads_with(|map, head, _| {
6067                (
6068                    movement::start_of_paragraph(map, head, 1),
6069                    SelectionGoal::None,
6070                )
6071            });
6072        })
6073    }
6074
6075    pub fn select_to_end_of_paragraph(
6076        &mut self,
6077        _: &SelectToEndOfParagraph,
6078        cx: &mut ViewContext<Self>,
6079    ) {
6080        if matches!(self.mode, EditorMode::SingleLine) {
6081            cx.propagate();
6082            return;
6083        }
6084
6085        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6086            s.move_heads_with(|map, head, _| {
6087                (
6088                    movement::end_of_paragraph(map, head, 1),
6089                    SelectionGoal::None,
6090                )
6091            });
6092        })
6093    }
6094
6095    pub fn move_to_beginning(&mut self, _: &MoveToBeginning, cx: &mut ViewContext<Self>) {
6096        if matches!(self.mode, EditorMode::SingleLine) {
6097            cx.propagate();
6098            return;
6099        }
6100
6101        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6102            s.select_ranges(vec![0..0]);
6103        });
6104    }
6105
6106    pub fn select_to_beginning(&mut self, _: &SelectToBeginning, cx: &mut ViewContext<Self>) {
6107        let mut selection = self.selections.last::<Point>(cx);
6108        selection.set_head(Point::zero(), SelectionGoal::None);
6109
6110        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6111            s.select(vec![selection]);
6112        });
6113    }
6114
6115    pub fn move_to_end(&mut self, _: &MoveToEnd, cx: &mut ViewContext<Self>) {
6116        if matches!(self.mode, EditorMode::SingleLine) {
6117            cx.propagate();
6118            return;
6119        }
6120
6121        let cursor = self.buffer.read(cx).read(cx).len();
6122        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6123            s.select_ranges(vec![cursor..cursor])
6124        });
6125    }
6126
6127    pub fn set_nav_history(&mut self, nav_history: Option<ItemNavHistory>) {
6128        self.nav_history = nav_history;
6129    }
6130
6131    pub fn nav_history(&self) -> Option<&ItemNavHistory> {
6132        self.nav_history.as_ref()
6133    }
6134
6135    fn push_to_nav_history(
6136        &mut self,
6137        cursor_anchor: Anchor,
6138        new_position: Option<Point>,
6139        cx: &mut ViewContext<Self>,
6140    ) {
6141        if let Some(nav_history) = self.nav_history.as_mut() {
6142            let buffer = self.buffer.read(cx).read(cx);
6143            let cursor_position = cursor_anchor.to_point(&buffer);
6144            let scroll_state = self.scroll_manager.anchor();
6145            let scroll_top_row = scroll_state.top_row(&buffer);
6146            drop(buffer);
6147
6148            if let Some(new_position) = new_position {
6149                let row_delta = (new_position.row as i64 - cursor_position.row as i64).abs();
6150                if row_delta < MIN_NAVIGATION_HISTORY_ROW_DELTA {
6151                    return;
6152                }
6153            }
6154
6155            nav_history.push(
6156                Some(NavigationData {
6157                    cursor_anchor,
6158                    cursor_position,
6159                    scroll_anchor: scroll_state,
6160                    scroll_top_row,
6161                }),
6162                cx,
6163            );
6164        }
6165    }
6166
6167    pub fn select_to_end(&mut self, _: &SelectToEnd, cx: &mut ViewContext<Self>) {
6168        let buffer = self.buffer.read(cx).snapshot(cx);
6169        let mut selection = self.selections.first::<usize>(cx);
6170        selection.set_head(buffer.len(), SelectionGoal::None);
6171        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6172            s.select(vec![selection]);
6173        });
6174    }
6175
6176    pub fn select_all(&mut self, _: &SelectAll, cx: &mut ViewContext<Self>) {
6177        let end = self.buffer.read(cx).read(cx).len();
6178        self.change_selections(None, cx, |s| {
6179            s.select_ranges(vec![0..end]);
6180        });
6181    }
6182
6183    pub fn select_line(&mut self, _: &SelectLine, cx: &mut ViewContext<Self>) {
6184        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6185        let mut selections = self.selections.all::<Point>(cx);
6186        let max_point = display_map.buffer_snapshot.max_point();
6187        for selection in &mut selections {
6188            let rows = selection.spanned_rows(true, &display_map);
6189            selection.start = Point::new(rows.start, 0);
6190            selection.end = cmp::min(max_point, Point::new(rows.end, 0));
6191            selection.reversed = false;
6192        }
6193        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6194            s.select(selections);
6195        });
6196    }
6197
6198    pub fn split_selection_into_lines(
6199        &mut self,
6200        _: &SplitSelectionIntoLines,
6201        cx: &mut ViewContext<Self>,
6202    ) {
6203        let mut to_unfold = Vec::new();
6204        let mut new_selection_ranges = Vec::new();
6205        {
6206            let selections = self.selections.all::<Point>(cx);
6207            let buffer = self.buffer.read(cx).read(cx);
6208            for selection in selections {
6209                for row in selection.start.row..selection.end.row {
6210                    let cursor = Point::new(row, buffer.line_len(row));
6211                    new_selection_ranges.push(cursor..cursor);
6212                }
6213                new_selection_ranges.push(selection.end..selection.end);
6214                to_unfold.push(selection.start..selection.end);
6215            }
6216        }
6217        self.unfold_ranges(to_unfold, true, true, cx);
6218        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6219            s.select_ranges(new_selection_ranges);
6220        });
6221    }
6222
6223    pub fn add_selection_above(&mut self, _: &AddSelectionAbove, cx: &mut ViewContext<Self>) {
6224        self.add_selection(true, cx);
6225    }
6226
6227    pub fn add_selection_below(&mut self, _: &AddSelectionBelow, cx: &mut ViewContext<Self>) {
6228        self.add_selection(false, cx);
6229    }
6230
6231    fn add_selection(&mut self, above: bool, cx: &mut ViewContext<Self>) {
6232        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6233        let mut selections = self.selections.all::<Point>(cx);
6234        let text_layout_details = self.text_layout_details(cx);
6235        let mut state = self.add_selections_state.take().unwrap_or_else(|| {
6236            let oldest_selection = selections.iter().min_by_key(|s| s.id).unwrap().clone();
6237            let range = oldest_selection.display_range(&display_map).sorted();
6238
6239            let start_x = display_map.x_for_display_point(range.start, &text_layout_details);
6240            let end_x = display_map.x_for_display_point(range.end, &text_layout_details);
6241            let positions = start_x.min(end_x)..start_x.max(end_x);
6242
6243            selections.clear();
6244            let mut stack = Vec::new();
6245            for row in range.start.row()..=range.end.row() {
6246                if let Some(selection) = self.selections.build_columnar_selection(
6247                    &display_map,
6248                    row,
6249                    &positions,
6250                    oldest_selection.reversed,
6251                    &text_layout_details,
6252                ) {
6253                    stack.push(selection.id);
6254                    selections.push(selection);
6255                }
6256            }
6257
6258            if above {
6259                stack.reverse();
6260            }
6261
6262            AddSelectionsState { above, stack }
6263        });
6264
6265        let last_added_selection = *state.stack.last().unwrap();
6266        let mut new_selections = Vec::new();
6267        if above == state.above {
6268            let end_row = if above {
6269                0
6270            } else {
6271                display_map.max_point().row()
6272            };
6273
6274            'outer: for selection in selections {
6275                if selection.id == last_added_selection {
6276                    let range = selection.display_range(&display_map).sorted();
6277                    debug_assert_eq!(range.start.row(), range.end.row());
6278                    let mut row = range.start.row();
6279                    let positions =
6280                        if let SelectionGoal::HorizontalRange { start, end } = selection.goal {
6281                            px(start)..px(end)
6282                        } else {
6283                            let start_x =
6284                                display_map.x_for_display_point(range.start, &text_layout_details);
6285                            let end_x =
6286                                display_map.x_for_display_point(range.end, &text_layout_details);
6287                            start_x.min(end_x)..start_x.max(end_x)
6288                        };
6289
6290                    while row != end_row {
6291                        if above {
6292                            row -= 1;
6293                        } else {
6294                            row += 1;
6295                        }
6296
6297                        if let Some(new_selection) = self.selections.build_columnar_selection(
6298                            &display_map,
6299                            row,
6300                            &positions,
6301                            selection.reversed,
6302                            &text_layout_details,
6303                        ) {
6304                            state.stack.push(new_selection.id);
6305                            if above {
6306                                new_selections.push(new_selection);
6307                                new_selections.push(selection);
6308                            } else {
6309                                new_selections.push(selection);
6310                                new_selections.push(new_selection);
6311                            }
6312
6313                            continue 'outer;
6314                        }
6315                    }
6316                }
6317
6318                new_selections.push(selection);
6319            }
6320        } else {
6321            new_selections = selections;
6322            new_selections.retain(|s| s.id != last_added_selection);
6323            state.stack.pop();
6324        }
6325
6326        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6327            s.select(new_selections);
6328        });
6329        if state.stack.len() > 1 {
6330            self.add_selections_state = Some(state);
6331        }
6332    }
6333
6334    pub fn select_next_match_internal(
6335        &mut self,
6336        display_map: &DisplaySnapshot,
6337        replace_newest: bool,
6338        autoscroll: Option<Autoscroll>,
6339        cx: &mut ViewContext<Self>,
6340    ) -> Result<()> {
6341        fn select_next_match_ranges(
6342            this: &mut Editor,
6343            range: Range<usize>,
6344            replace_newest: bool,
6345            auto_scroll: Option<Autoscroll>,
6346            cx: &mut ViewContext<Editor>,
6347        ) {
6348            this.unfold_ranges([range.clone()], false, true, cx);
6349            this.change_selections(auto_scroll, cx, |s| {
6350                if replace_newest {
6351                    s.delete(s.newest_anchor().id);
6352                }
6353                s.insert_range(range.clone());
6354            });
6355        }
6356
6357        let buffer = &display_map.buffer_snapshot;
6358        let mut selections = self.selections.all::<usize>(cx);
6359        if let Some(mut select_next_state) = self.select_next_state.take() {
6360            let query = &select_next_state.query;
6361            if !select_next_state.done {
6362                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
6363                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
6364                let mut next_selected_range = None;
6365
6366                let bytes_after_last_selection =
6367                    buffer.bytes_in_range(last_selection.end..buffer.len());
6368                let bytes_before_first_selection = buffer.bytes_in_range(0..first_selection.start);
6369                let query_matches = query
6370                    .stream_find_iter(bytes_after_last_selection)
6371                    .map(|result| (last_selection.end, result))
6372                    .chain(
6373                        query
6374                            .stream_find_iter(bytes_before_first_selection)
6375                            .map(|result| (0, result)),
6376                    );
6377
6378                for (start_offset, query_match) in query_matches {
6379                    let query_match = query_match.unwrap(); // can only fail due to I/O
6380                    let offset_range =
6381                        start_offset + query_match.start()..start_offset + query_match.end();
6382                    let display_range = offset_range.start.to_display_point(&display_map)
6383                        ..offset_range.end.to_display_point(&display_map);
6384
6385                    if !select_next_state.wordwise
6386                        || (!movement::is_inside_word(&display_map, display_range.start)
6387                            && !movement::is_inside_word(&display_map, display_range.end))
6388                    {
6389                        if selections
6390                            .iter()
6391                            .find(|selection| selection.range().overlaps(&offset_range))
6392                            .is_none()
6393                        {
6394                            next_selected_range = Some(offset_range);
6395                            break;
6396                        }
6397                    }
6398                }
6399
6400                if let Some(next_selected_range) = next_selected_range {
6401                    select_next_match_ranges(
6402                        self,
6403                        next_selected_range,
6404                        replace_newest,
6405                        autoscroll,
6406                        cx,
6407                    );
6408                } else {
6409                    select_next_state.done = true;
6410                }
6411            }
6412
6413            self.select_next_state = Some(select_next_state);
6414        } else if selections.len() == 1 {
6415            let selection = selections.last_mut().unwrap();
6416            if selection.start == selection.end {
6417                let word_range = movement::surrounding_word(
6418                    &display_map,
6419                    selection.start.to_display_point(&display_map),
6420                );
6421                selection.start = word_range.start.to_offset(&display_map, Bias::Left);
6422                selection.end = word_range.end.to_offset(&display_map, Bias::Left);
6423                selection.goal = SelectionGoal::None;
6424                selection.reversed = false;
6425
6426                let query = buffer
6427                    .text_for_range(selection.start..selection.end)
6428                    .collect::<String>();
6429
6430                let is_empty = query.is_empty();
6431                let select_state = SelectNextState {
6432                    query: AhoCorasick::new(&[query])?,
6433                    wordwise: true,
6434                    done: is_empty,
6435                };
6436                select_next_match_ranges(
6437                    self,
6438                    selection.start..selection.end,
6439                    replace_newest,
6440                    autoscroll,
6441                    cx,
6442                );
6443                self.select_next_state = Some(select_state);
6444            } else {
6445                let query = buffer
6446                    .text_for_range(selection.start..selection.end)
6447                    .collect::<String>();
6448                self.select_next_state = Some(SelectNextState {
6449                    query: AhoCorasick::new(&[query])?,
6450                    wordwise: false,
6451                    done: false,
6452                });
6453                self.select_next_match_internal(display_map, replace_newest, autoscroll, cx)?;
6454            }
6455        }
6456        Ok(())
6457    }
6458
6459    pub fn select_all_matches(
6460        &mut self,
6461        action: &SelectAllMatches,
6462        cx: &mut ViewContext<Self>,
6463    ) -> Result<()> {
6464        self.push_to_selection_history();
6465        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6466
6467        loop {
6468            self.select_next_match_internal(&display_map, action.replace_newest, None, cx)?;
6469
6470            if self
6471                .select_next_state
6472                .as_ref()
6473                .map(|selection_state| selection_state.done)
6474                .unwrap_or(true)
6475            {
6476                break;
6477            }
6478        }
6479
6480        Ok(())
6481    }
6482
6483    pub fn select_next(&mut self, action: &SelectNext, cx: &mut ViewContext<Self>) -> Result<()> {
6484        self.push_to_selection_history();
6485        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6486        self.select_next_match_internal(
6487            &display_map,
6488            action.replace_newest,
6489            Some(Autoscroll::newest()),
6490            cx,
6491        )?;
6492        Ok(())
6493    }
6494
6495    pub fn select_previous(
6496        &mut self,
6497        action: &SelectPrevious,
6498        cx: &mut ViewContext<Self>,
6499    ) -> Result<()> {
6500        self.push_to_selection_history();
6501        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6502        let buffer = &display_map.buffer_snapshot;
6503        let mut selections = self.selections.all::<usize>(cx);
6504        if let Some(mut select_prev_state) = self.select_prev_state.take() {
6505            let query = &select_prev_state.query;
6506            if !select_prev_state.done {
6507                let first_selection = selections.iter().min_by_key(|s| s.id).unwrap();
6508                let last_selection = selections.iter().max_by_key(|s| s.id).unwrap();
6509                let mut next_selected_range = None;
6510                // When we're iterating matches backwards, the oldest match will actually be the furthest one in the buffer.
6511                let bytes_before_last_selection =
6512                    buffer.reversed_bytes_in_range(0..last_selection.start);
6513                let bytes_after_first_selection =
6514                    buffer.reversed_bytes_in_range(first_selection.end..buffer.len());
6515                let query_matches = query
6516                    .stream_find_iter(bytes_before_last_selection)
6517                    .map(|result| (last_selection.start, result))
6518                    .chain(
6519                        query
6520                            .stream_find_iter(bytes_after_first_selection)
6521                            .map(|result| (buffer.len(), result)),
6522                    );
6523                for (end_offset, query_match) in query_matches {
6524                    let query_match = query_match.unwrap(); // can only fail due to I/O
6525                    let offset_range =
6526                        end_offset - query_match.end()..end_offset - query_match.start();
6527                    let display_range = offset_range.start.to_display_point(&display_map)
6528                        ..offset_range.end.to_display_point(&display_map);
6529
6530                    if !select_prev_state.wordwise
6531                        || (!movement::is_inside_word(&display_map, display_range.start)
6532                            && !movement::is_inside_word(&display_map, display_range.end))
6533                    {
6534                        next_selected_range = Some(offset_range);
6535                        break;
6536                    }
6537                }
6538
6539                if let Some(next_selected_range) = next_selected_range {
6540                    self.unfold_ranges([next_selected_range.clone()], false, true, cx);
6541                    self.change_selections(Some(Autoscroll::newest()), cx, |s| {
6542                        if action.replace_newest {
6543                            s.delete(s.newest_anchor().id);
6544                        }
6545                        s.insert_range(next_selected_range);
6546                    });
6547                } else {
6548                    select_prev_state.done = true;
6549                }
6550            }
6551
6552            self.select_prev_state = Some(select_prev_state);
6553        } else if selections.len() == 1 {
6554            let selection = selections.last_mut().unwrap();
6555            if selection.start == selection.end {
6556                let word_range = movement::surrounding_word(
6557                    &display_map,
6558                    selection.start.to_display_point(&display_map),
6559                );
6560                selection.start = word_range.start.to_offset(&display_map, Bias::Left);
6561                selection.end = word_range.end.to_offset(&display_map, Bias::Left);
6562                selection.goal = SelectionGoal::None;
6563                selection.reversed = false;
6564
6565                let query = buffer
6566                    .text_for_range(selection.start..selection.end)
6567                    .collect::<String>();
6568                let query = query.chars().rev().collect::<String>();
6569                let select_state = SelectNextState {
6570                    query: AhoCorasick::new(&[query])?,
6571                    wordwise: true,
6572                    done: false,
6573                };
6574                self.unfold_ranges([selection.start..selection.end], false, true, cx);
6575                self.change_selections(Some(Autoscroll::newest()), cx, |s| {
6576                    s.select(selections);
6577                });
6578                self.select_prev_state = Some(select_state);
6579            } else {
6580                let query = buffer
6581                    .text_for_range(selection.start..selection.end)
6582                    .collect::<String>();
6583                let query = query.chars().rev().collect::<String>();
6584                self.select_prev_state = Some(SelectNextState {
6585                    query: AhoCorasick::new(&[query])?,
6586                    wordwise: false,
6587                    done: false,
6588                });
6589                self.select_previous(action, cx)?;
6590            }
6591        }
6592        Ok(())
6593    }
6594
6595    pub fn toggle_comments(&mut self, action: &ToggleComments, cx: &mut ViewContext<Self>) {
6596        let text_layout_details = &self.text_layout_details(cx);
6597        self.transact(cx, |this, cx| {
6598            let mut selections = this.selections.all::<Point>(cx);
6599            let mut edits = Vec::new();
6600            let mut selection_edit_ranges = Vec::new();
6601            let mut last_toggled_row = None;
6602            let snapshot = this.buffer.read(cx).read(cx);
6603            let empty_str: Arc<str> = "".into();
6604            let mut suffixes_inserted = Vec::new();
6605
6606            fn comment_prefix_range(
6607                snapshot: &MultiBufferSnapshot,
6608                row: u32,
6609                comment_prefix: &str,
6610                comment_prefix_whitespace: &str,
6611            ) -> Range<Point> {
6612                let start = Point::new(row, snapshot.indent_size_for_line(row).len);
6613
6614                let mut line_bytes = snapshot
6615                    .bytes_in_range(start..snapshot.max_point())
6616                    .flatten()
6617                    .copied();
6618
6619                // If this line currently begins with the line comment prefix, then record
6620                // the range containing the prefix.
6621                if line_bytes
6622                    .by_ref()
6623                    .take(comment_prefix.len())
6624                    .eq(comment_prefix.bytes())
6625                {
6626                    // Include any whitespace that matches the comment prefix.
6627                    let matching_whitespace_len = line_bytes
6628                        .zip(comment_prefix_whitespace.bytes())
6629                        .take_while(|(a, b)| a == b)
6630                        .count() as u32;
6631                    let end = Point::new(
6632                        start.row,
6633                        start.column + comment_prefix.len() as u32 + matching_whitespace_len,
6634                    );
6635                    start..end
6636                } else {
6637                    start..start
6638                }
6639            }
6640
6641            fn comment_suffix_range(
6642                snapshot: &MultiBufferSnapshot,
6643                row: u32,
6644                comment_suffix: &str,
6645                comment_suffix_has_leading_space: bool,
6646            ) -> Range<Point> {
6647                let end = Point::new(row, snapshot.line_len(row));
6648                let suffix_start_column = end.column.saturating_sub(comment_suffix.len() as u32);
6649
6650                let mut line_end_bytes = snapshot
6651                    .bytes_in_range(Point::new(end.row, suffix_start_column.saturating_sub(1))..end)
6652                    .flatten()
6653                    .copied();
6654
6655                let leading_space_len = if suffix_start_column > 0
6656                    && line_end_bytes.next() == Some(b' ')
6657                    && comment_suffix_has_leading_space
6658                {
6659                    1
6660                } else {
6661                    0
6662                };
6663
6664                // If this line currently begins with the line comment prefix, then record
6665                // the range containing the prefix.
6666                if line_end_bytes.by_ref().eq(comment_suffix.bytes()) {
6667                    let start = Point::new(end.row, suffix_start_column - leading_space_len);
6668                    start..end
6669                } else {
6670                    end..end
6671                }
6672            }
6673
6674            // TODO: Handle selections that cross excerpts
6675            for selection in &mut selections {
6676                let start_column = snapshot.indent_size_for_line(selection.start.row).len;
6677                let language = if let Some(language) =
6678                    snapshot.language_scope_at(Point::new(selection.start.row, start_column))
6679                {
6680                    language
6681                } else {
6682                    continue;
6683                };
6684
6685                selection_edit_ranges.clear();
6686
6687                // If multiple selections contain a given row, avoid processing that
6688                // row more than once.
6689                let mut start_row = selection.start.row;
6690                if last_toggled_row == Some(start_row) {
6691                    start_row += 1;
6692                }
6693                let end_row =
6694                    if selection.end.row > selection.start.row && selection.end.column == 0 {
6695                        selection.end.row - 1
6696                    } else {
6697                        selection.end.row
6698                    };
6699                last_toggled_row = Some(end_row);
6700
6701                if start_row > end_row {
6702                    continue;
6703                }
6704
6705                // If the language has line comments, toggle those.
6706                if let Some(full_comment_prefix) = language.line_comment_prefix() {
6707                    // Split the comment prefix's trailing whitespace into a separate string,
6708                    // as that portion won't be used for detecting if a line is a comment.
6709                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
6710                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
6711                    let mut all_selection_lines_are_comments = true;
6712
6713                    for row in start_row..=end_row {
6714                        if snapshot.is_line_blank(row) && start_row < end_row {
6715                            continue;
6716                        }
6717
6718                        let prefix_range = comment_prefix_range(
6719                            snapshot.deref(),
6720                            row,
6721                            comment_prefix,
6722                            comment_prefix_whitespace,
6723                        );
6724                        if prefix_range.is_empty() {
6725                            all_selection_lines_are_comments = false;
6726                        }
6727                        selection_edit_ranges.push(prefix_range);
6728                    }
6729
6730                    if all_selection_lines_are_comments {
6731                        edits.extend(
6732                            selection_edit_ranges
6733                                .iter()
6734                                .cloned()
6735                                .map(|range| (range, empty_str.clone())),
6736                        );
6737                    } else {
6738                        let min_column = selection_edit_ranges
6739                            .iter()
6740                            .map(|r| r.start.column)
6741                            .min()
6742                            .unwrap_or(0);
6743                        edits.extend(selection_edit_ranges.iter().map(|range| {
6744                            let position = Point::new(range.start.row, min_column);
6745                            (position..position, full_comment_prefix.clone())
6746                        }));
6747                    }
6748                } else if let Some((full_comment_prefix, comment_suffix)) =
6749                    language.block_comment_delimiters()
6750                {
6751                    let comment_prefix = full_comment_prefix.trim_end_matches(' ');
6752                    let comment_prefix_whitespace = &full_comment_prefix[comment_prefix.len()..];
6753                    let prefix_range = comment_prefix_range(
6754                        snapshot.deref(),
6755                        start_row,
6756                        comment_prefix,
6757                        comment_prefix_whitespace,
6758                    );
6759                    let suffix_range = comment_suffix_range(
6760                        snapshot.deref(),
6761                        end_row,
6762                        comment_suffix.trim_start_matches(' '),
6763                        comment_suffix.starts_with(' '),
6764                    );
6765
6766                    if prefix_range.is_empty() || suffix_range.is_empty() {
6767                        edits.push((
6768                            prefix_range.start..prefix_range.start,
6769                            full_comment_prefix.clone(),
6770                        ));
6771                        edits.push((suffix_range.end..suffix_range.end, comment_suffix.clone()));
6772                        suffixes_inserted.push((end_row, comment_suffix.len()));
6773                    } else {
6774                        edits.push((prefix_range, empty_str.clone()));
6775                        edits.push((suffix_range, empty_str.clone()));
6776                    }
6777                } else {
6778                    continue;
6779                }
6780            }
6781
6782            drop(snapshot);
6783            this.buffer.update(cx, |buffer, cx| {
6784                buffer.edit(edits, None, cx);
6785            });
6786
6787            // Adjust selections so that they end before any comment suffixes that
6788            // were inserted.
6789            let mut suffixes_inserted = suffixes_inserted.into_iter().peekable();
6790            let mut selections = this.selections.all::<Point>(cx);
6791            let snapshot = this.buffer.read(cx).read(cx);
6792            for selection in &mut selections {
6793                while let Some((row, suffix_len)) = suffixes_inserted.peek().copied() {
6794                    match row.cmp(&selection.end.row) {
6795                        Ordering::Less => {
6796                            suffixes_inserted.next();
6797                            continue;
6798                        }
6799                        Ordering::Greater => break,
6800                        Ordering::Equal => {
6801                            if selection.end.column == snapshot.line_len(row) {
6802                                if selection.is_empty() {
6803                                    selection.start.column -= suffix_len as u32;
6804                                }
6805                                selection.end.column -= suffix_len as u32;
6806                            }
6807                            break;
6808                        }
6809                    }
6810                }
6811            }
6812
6813            drop(snapshot);
6814            this.change_selections(Some(Autoscroll::fit()), cx, |s| s.select(selections));
6815
6816            let selections = this.selections.all::<Point>(cx);
6817            let selections_on_single_row = selections.windows(2).all(|selections| {
6818                selections[0].start.row == selections[1].start.row
6819                    && selections[0].end.row == selections[1].end.row
6820                    && selections[0].start.row == selections[0].end.row
6821            });
6822            let selections_selecting = selections
6823                .iter()
6824                .any(|selection| selection.start != selection.end);
6825            let advance_downwards = action.advance_downwards
6826                && selections_on_single_row
6827                && !selections_selecting
6828                && this.mode != EditorMode::SingleLine;
6829
6830            if advance_downwards {
6831                let snapshot = this.buffer.read(cx).snapshot(cx);
6832
6833                this.change_selections(Some(Autoscroll::fit()), cx, |s| {
6834                    s.move_cursors_with(|display_snapshot, display_point, _| {
6835                        let mut point = display_point.to_point(display_snapshot);
6836                        point.row += 1;
6837                        point = snapshot.clip_point(point, Bias::Left);
6838                        let display_point = point.to_display_point(display_snapshot);
6839                        let goal = SelectionGoal::HorizontalPosition(
6840                            display_snapshot
6841                                .x_for_display_point(display_point, &text_layout_details)
6842                                .into(),
6843                        );
6844                        (display_point, goal)
6845                    })
6846                });
6847            }
6848        });
6849    }
6850
6851    pub fn select_larger_syntax_node(
6852        &mut self,
6853        _: &SelectLargerSyntaxNode,
6854        cx: &mut ViewContext<Self>,
6855    ) {
6856        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
6857        let buffer = self.buffer.read(cx).snapshot(cx);
6858        let old_selections = self.selections.all::<usize>(cx).into_boxed_slice();
6859
6860        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
6861        let mut selected_larger_node = false;
6862        let new_selections = old_selections
6863            .iter()
6864            .map(|selection| {
6865                let old_range = selection.start..selection.end;
6866                let mut new_range = old_range.clone();
6867                while let Some(containing_range) =
6868                    buffer.range_for_syntax_ancestor(new_range.clone())
6869                {
6870                    new_range = containing_range;
6871                    if !display_map.intersects_fold(new_range.start)
6872                        && !display_map.intersects_fold(new_range.end)
6873                    {
6874                        break;
6875                    }
6876                }
6877
6878                selected_larger_node |= new_range != old_range;
6879                Selection {
6880                    id: selection.id,
6881                    start: new_range.start,
6882                    end: new_range.end,
6883                    goal: SelectionGoal::None,
6884                    reversed: selection.reversed,
6885                }
6886            })
6887            .collect::<Vec<_>>();
6888
6889        if selected_larger_node {
6890            stack.push(old_selections);
6891            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6892                s.select(new_selections);
6893            });
6894        }
6895        self.select_larger_syntax_node_stack = stack;
6896    }
6897
6898    pub fn select_smaller_syntax_node(
6899        &mut self,
6900        _: &SelectSmallerSyntaxNode,
6901        cx: &mut ViewContext<Self>,
6902    ) {
6903        let mut stack = mem::take(&mut self.select_larger_syntax_node_stack);
6904        if let Some(selections) = stack.pop() {
6905            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6906                s.select(selections.to_vec());
6907            });
6908        }
6909        self.select_larger_syntax_node_stack = stack;
6910    }
6911
6912    pub fn move_to_enclosing_bracket(
6913        &mut self,
6914        _: &MoveToEnclosingBracket,
6915        cx: &mut ViewContext<Self>,
6916    ) {
6917        self.change_selections(Some(Autoscroll::fit()), cx, |s| {
6918            s.move_offsets_with(|snapshot, selection| {
6919                let Some(enclosing_bracket_ranges) =
6920                    snapshot.enclosing_bracket_ranges(selection.start..selection.end)
6921                else {
6922                    return;
6923                };
6924
6925                let mut best_length = usize::MAX;
6926                let mut best_inside = false;
6927                let mut best_in_bracket_range = false;
6928                let mut best_destination = None;
6929                for (open, close) in enclosing_bracket_ranges {
6930                    let close = close.to_inclusive();
6931                    let length = close.end() - open.start;
6932                    let inside = selection.start >= open.end && selection.end <= *close.start();
6933                    let in_bracket_range = open.to_inclusive().contains(&selection.head())
6934                        || close.contains(&selection.head());
6935
6936                    // If best is next to a bracket and current isn't, skip
6937                    if !in_bracket_range && best_in_bracket_range {
6938                        continue;
6939                    }
6940
6941                    // Prefer smaller lengths unless best is inside and current isn't
6942                    if length > best_length && (best_inside || !inside) {
6943                        continue;
6944                    }
6945
6946                    best_length = length;
6947                    best_inside = inside;
6948                    best_in_bracket_range = in_bracket_range;
6949                    best_destination = Some(
6950                        if close.contains(&selection.start) && close.contains(&selection.end) {
6951                            if inside {
6952                                open.end
6953                            } else {
6954                                open.start
6955                            }
6956                        } else {
6957                            if inside {
6958                                *close.start()
6959                            } else {
6960                                *close.end()
6961                            }
6962                        },
6963                    );
6964                }
6965
6966                if let Some(destination) = best_destination {
6967                    selection.collapse_to(destination, SelectionGoal::None);
6968                }
6969            })
6970        });
6971    }
6972
6973    pub fn undo_selection(&mut self, _: &UndoSelection, cx: &mut ViewContext<Self>) {
6974        self.end_selection(cx);
6975        self.selection_history.mode = SelectionHistoryMode::Undoing;
6976        if let Some(entry) = self.selection_history.undo_stack.pop_back() {
6977            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
6978            self.select_next_state = entry.select_next_state;
6979            self.select_prev_state = entry.select_prev_state;
6980            self.add_selections_state = entry.add_selections_state;
6981            self.request_autoscroll(Autoscroll::newest(), cx);
6982        }
6983        self.selection_history.mode = SelectionHistoryMode::Normal;
6984    }
6985
6986    pub fn redo_selection(&mut self, _: &RedoSelection, cx: &mut ViewContext<Self>) {
6987        self.end_selection(cx);
6988        self.selection_history.mode = SelectionHistoryMode::Redoing;
6989        if let Some(entry) = self.selection_history.redo_stack.pop_back() {
6990            self.change_selections(None, cx, |s| s.select_anchors(entry.selections.to_vec()));
6991            self.select_next_state = entry.select_next_state;
6992            self.select_prev_state = entry.select_prev_state;
6993            self.add_selections_state = entry.add_selections_state;
6994            self.request_autoscroll(Autoscroll::newest(), cx);
6995        }
6996        self.selection_history.mode = SelectionHistoryMode::Normal;
6997    }
6998
6999    fn go_to_diagnostic(&mut self, _: &GoToDiagnostic, cx: &mut ViewContext<Self>) {
7000        self.go_to_diagnostic_impl(Direction::Next, cx)
7001    }
7002
7003    fn go_to_prev_diagnostic(&mut self, _: &GoToPrevDiagnostic, cx: &mut ViewContext<Self>) {
7004        self.go_to_diagnostic_impl(Direction::Prev, cx)
7005    }
7006
7007    pub fn go_to_diagnostic_impl(&mut self, direction: Direction, cx: &mut ViewContext<Self>) {
7008        let buffer = self.buffer.read(cx).snapshot(cx);
7009        let selection = self.selections.newest::<usize>(cx);
7010
7011        // If there is an active Diagnostic Popover. Jump to it's diagnostic instead.
7012        if direction == Direction::Next {
7013            if let Some(popover) = self.hover_state.diagnostic_popover.as_ref() {
7014                let (group_id, jump_to) = popover.activation_info();
7015                if self.activate_diagnostics(group_id, cx) {
7016                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
7017                        let mut new_selection = s.newest_anchor().clone();
7018                        new_selection.collapse_to(jump_to, SelectionGoal::None);
7019                        s.select_anchors(vec![new_selection.clone()]);
7020                    });
7021                }
7022                return;
7023            }
7024        }
7025
7026        let mut active_primary_range = self.active_diagnostics.as_ref().map(|active_diagnostics| {
7027            active_diagnostics
7028                .primary_range
7029                .to_offset(&buffer)
7030                .to_inclusive()
7031        });
7032        let mut search_start = if let Some(active_primary_range) = active_primary_range.as_ref() {
7033            if active_primary_range.contains(&selection.head()) {
7034                *active_primary_range.end()
7035            } else {
7036                selection.head()
7037            }
7038        } else {
7039            selection.head()
7040        };
7041
7042        loop {
7043            let mut diagnostics = if direction == Direction::Prev {
7044                buffer.diagnostics_in_range::<_, usize>(0..search_start, true)
7045            } else {
7046                buffer.diagnostics_in_range::<_, usize>(search_start..buffer.len(), false)
7047            };
7048            let group = diagnostics.find_map(|entry| {
7049                if entry.diagnostic.is_primary
7050                    && entry.diagnostic.severity <= DiagnosticSeverity::WARNING
7051                    && !entry.range.is_empty()
7052                    && Some(entry.range.end) != active_primary_range.as_ref().map(|r| *r.end())
7053                    && !entry.range.contains(&search_start)
7054                {
7055                    Some((entry.range, entry.diagnostic.group_id))
7056                } else {
7057                    None
7058                }
7059            });
7060
7061            if let Some((primary_range, group_id)) = group {
7062                if self.activate_diagnostics(group_id, cx) {
7063                    self.change_selections(Some(Autoscroll::fit()), cx, |s| {
7064                        s.select(vec![Selection {
7065                            id: selection.id,
7066                            start: primary_range.start,
7067                            end: primary_range.start,
7068                            reversed: false,
7069                            goal: SelectionGoal::None,
7070                        }]);
7071                    });
7072                }
7073                break;
7074            } else {
7075                // Cycle around to the start of the buffer, potentially moving back to the start of
7076                // the currently active diagnostic.
7077                active_primary_range.take();
7078                if direction == Direction::Prev {
7079                    if search_start == buffer.len() {
7080                        break;
7081                    } else {
7082                        search_start = buffer.len();
7083                    }
7084                } else if search_start == 0 {
7085                    break;
7086                } else {
7087                    search_start = 0;
7088                }
7089            }
7090        }
7091    }
7092
7093    fn go_to_hunk(&mut self, _: &GoToHunk, cx: &mut ViewContext<Self>) {
7094        let snapshot = self
7095            .display_map
7096            .update(cx, |display_map, cx| display_map.snapshot(cx));
7097        let selection = self.selections.newest::<Point>(cx);
7098
7099        if !self.seek_in_direction(
7100            &snapshot,
7101            selection.head(),
7102            false,
7103            snapshot
7104                .buffer_snapshot
7105                .git_diff_hunks_in_range((selection.head().row + 1)..u32::MAX),
7106            cx,
7107        ) {
7108            let wrapped_point = Point::zero();
7109            self.seek_in_direction(
7110                &snapshot,
7111                wrapped_point,
7112                true,
7113                snapshot
7114                    .buffer_snapshot
7115                    .git_diff_hunks_in_range((wrapped_point.row + 1)..u32::MAX),
7116                cx,
7117            );
7118        }
7119    }
7120
7121    fn go_to_prev_hunk(&mut self, _: &GoToPrevHunk, cx: &mut ViewContext<Self>) {
7122        let snapshot = self
7123            .display_map
7124            .update(cx, |display_map, cx| display_map.snapshot(cx));
7125        let selection = self.selections.newest::<Point>(cx);
7126
7127        if !self.seek_in_direction(
7128            &snapshot,
7129            selection.head(),
7130            false,
7131            snapshot
7132                .buffer_snapshot
7133                .git_diff_hunks_in_range_rev(0..selection.head().row),
7134            cx,
7135        ) {
7136            let wrapped_point = snapshot.buffer_snapshot.max_point();
7137            self.seek_in_direction(
7138                &snapshot,
7139                wrapped_point,
7140                true,
7141                snapshot
7142                    .buffer_snapshot
7143                    .git_diff_hunks_in_range_rev(0..wrapped_point.row),
7144                cx,
7145            );
7146        }
7147    }
7148
7149    fn seek_in_direction(
7150        &mut self,
7151        snapshot: &DisplaySnapshot,
7152        initial_point: Point,
7153        is_wrapped: bool,
7154        hunks: impl Iterator<Item = DiffHunk<u32>>,
7155        cx: &mut ViewContext<Editor>,
7156    ) -> bool {
7157        let display_point = initial_point.to_display_point(snapshot);
7158        let mut hunks = hunks
7159            .map(|hunk| diff_hunk_to_display(hunk, &snapshot))
7160            .filter(|hunk| {
7161                if is_wrapped {
7162                    true
7163                } else {
7164                    !hunk.contains_display_row(display_point.row())
7165                }
7166            })
7167            .dedup();
7168
7169        if let Some(hunk) = hunks.next() {
7170            self.change_selections(Some(Autoscroll::fit()), cx, |s| {
7171                let row = hunk.start_display_row();
7172                let point = DisplayPoint::new(row, 0);
7173                s.select_display_ranges([point..point]);
7174            });
7175
7176            true
7177        } else {
7178            false
7179        }
7180    }
7181
7182    pub fn go_to_definition(&mut self, _: &GoToDefinition, cx: &mut ViewContext<Self>) {
7183        self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, false, cx);
7184    }
7185
7186    pub fn go_to_type_definition(&mut self, _: &GoToTypeDefinition, cx: &mut ViewContext<Self>) {
7187        self.go_to_definition_of_kind(GotoDefinitionKind::Type, false, cx);
7188    }
7189
7190    pub fn go_to_definition_split(&mut self, _: &GoToDefinitionSplit, cx: &mut ViewContext<Self>) {
7191        self.go_to_definition_of_kind(GotoDefinitionKind::Symbol, true, cx);
7192    }
7193
7194    pub fn go_to_type_definition_split(
7195        &mut self,
7196        _: &GoToTypeDefinitionSplit,
7197        cx: &mut ViewContext<Self>,
7198    ) {
7199        self.go_to_definition_of_kind(GotoDefinitionKind::Type, true, cx);
7200    }
7201
7202    fn go_to_definition_of_kind(
7203        &mut self,
7204        kind: GotoDefinitionKind,
7205        split: bool,
7206        cx: &mut ViewContext<Self>,
7207    ) {
7208        let Some(workspace) = self.workspace() else {
7209            return;
7210        };
7211        let buffer = self.buffer.read(cx);
7212        let head = self.selections.newest::<usize>(cx).head();
7213        let (buffer, head) = if let Some(text_anchor) = buffer.text_anchor_for_position(head, cx) {
7214            text_anchor
7215        } else {
7216            return;
7217        };
7218
7219        let project = workspace.read(cx).project().clone();
7220        let definitions = project.update(cx, |project, cx| match kind {
7221            GotoDefinitionKind::Symbol => project.definition(&buffer, head, cx),
7222            GotoDefinitionKind::Type => project.type_definition(&buffer, head, cx),
7223        });
7224
7225        cx.spawn(|editor, mut cx| async move {
7226            let definitions = definitions.await?;
7227            editor.update(&mut cx, |editor, cx| {
7228                editor.navigate_to_definitions(
7229                    definitions
7230                        .into_iter()
7231                        .map(GoToDefinitionLink::Text)
7232                        .collect(),
7233                    split,
7234                    cx,
7235                );
7236            })?;
7237            Ok::<(), anyhow::Error>(())
7238        })
7239        .detach_and_log_err(cx);
7240    }
7241
7242    pub fn navigate_to_definitions(
7243        &mut self,
7244        mut definitions: Vec<GoToDefinitionLink>,
7245        split: bool,
7246        cx: &mut ViewContext<Editor>,
7247    ) {
7248        let Some(workspace) = self.workspace() else {
7249            return;
7250        };
7251        let pane = workspace.read(cx).active_pane().clone();
7252        // If there is one definition, just open it directly
7253        if definitions.len() == 1 {
7254            let definition = definitions.pop().unwrap();
7255            let target_task = match definition {
7256                GoToDefinitionLink::Text(link) => Task::Ready(Some(Ok(Some(link.target)))),
7257                GoToDefinitionLink::InlayHint(lsp_location, server_id) => {
7258                    self.compute_target_location(lsp_location, server_id, cx)
7259                }
7260            };
7261            cx.spawn(|editor, mut cx| async move {
7262                let target = target_task.await.context("target resolution task")?;
7263                if let Some(target) = target {
7264                    editor.update(&mut cx, |editor, cx| {
7265                        let range = target.range.to_offset(target.buffer.read(cx));
7266                        let range = editor.range_for_match(&range);
7267                        if Some(&target.buffer) == editor.buffer.read(cx).as_singleton().as_ref() {
7268                            editor.change_selections(Some(Autoscroll::fit()), cx, |s| {
7269                                s.select_ranges([range]);
7270                            });
7271                        } else {
7272                            cx.window_context().defer(move |cx| {
7273                                let target_editor: View<Self> =
7274                                    workspace.update(cx, |workspace, cx| {
7275                                        if split {
7276                                            workspace.split_project_item(target.buffer.clone(), cx)
7277                                        } else {
7278                                            workspace.open_project_item(target.buffer.clone(), cx)
7279                                        }
7280                                    });
7281                                target_editor.update(cx, |target_editor, cx| {
7282                                    // When selecting a definition in a different buffer, disable the nav history
7283                                    // to avoid creating a history entry at the previous cursor location.
7284                                    pane.update(cx, |pane, _| pane.disable_history());
7285                                    target_editor.change_selections(
7286                                        Some(Autoscroll::fit()),
7287                                        cx,
7288                                        |s| {
7289                                            s.select_ranges([range]);
7290                                        },
7291                                    );
7292                                    pane.update(cx, |pane, _| pane.enable_history());
7293                                });
7294                            });
7295                        }
7296                    })
7297                } else {
7298                    Ok(())
7299                }
7300            })
7301            .detach_and_log_err(cx);
7302        } else if !definitions.is_empty() {
7303            let replica_id = self.replica_id(cx);
7304            cx.spawn(|editor, mut cx| async move {
7305                let (title, location_tasks) = editor
7306                    .update(&mut cx, |editor, cx| {
7307                        let title = definitions
7308                            .iter()
7309                            .find_map(|definition| match definition {
7310                                GoToDefinitionLink::Text(link) => {
7311                                    link.origin.as_ref().map(|origin| {
7312                                        let buffer = origin.buffer.read(cx);
7313                                        format!(
7314                                            "Definitions for {}",
7315                                            buffer
7316                                                .text_for_range(origin.range.clone())
7317                                                .collect::<String>()
7318                                        )
7319                                    })
7320                                }
7321                                GoToDefinitionLink::InlayHint(_, _) => None,
7322                            })
7323                            .unwrap_or("Definitions".to_string());
7324                        let location_tasks = definitions
7325                            .into_iter()
7326                            .map(|definition| match definition {
7327                                GoToDefinitionLink::Text(link) => {
7328                                    Task::Ready(Some(Ok(Some(link.target))))
7329                                }
7330                                GoToDefinitionLink::InlayHint(lsp_location, server_id) => {
7331                                    editor.compute_target_location(lsp_location, server_id, cx)
7332                                }
7333                            })
7334                            .collect::<Vec<_>>();
7335                        (title, location_tasks)
7336                    })
7337                    .context("location tasks preparation")?;
7338
7339                let locations = futures::future::join_all(location_tasks)
7340                    .await
7341                    .into_iter()
7342                    .filter_map(|location| location.transpose())
7343                    .collect::<Result<_>>()
7344                    .context("location tasks")?;
7345                workspace.update(&mut cx, |workspace, cx| {
7346                    Self::open_locations_in_multibuffer(
7347                        workspace, locations, replica_id, title, split, cx,
7348                    )
7349                });
7350
7351                anyhow::Ok(())
7352            })
7353            .detach_and_log_err(cx);
7354        }
7355    }
7356
7357    fn compute_target_location(
7358        &self,
7359        lsp_location: lsp::Location,
7360        server_id: LanguageServerId,
7361        cx: &mut ViewContext<Editor>,
7362    ) -> Task<anyhow::Result<Option<Location>>> {
7363        let Some(project) = self.project.clone() else {
7364            return Task::Ready(Some(Ok(None)));
7365        };
7366
7367        cx.spawn(move |editor, mut cx| async move {
7368            let location_task = editor.update(&mut cx, |editor, cx| {
7369                project.update(cx, |project, cx| {
7370                    let language_server_name =
7371                        editor.buffer.read(cx).as_singleton().and_then(|buffer| {
7372                            project
7373                                .language_server_for_buffer(buffer.read(cx), server_id, cx)
7374                                .map(|(_, lsp_adapter)| {
7375                                    LanguageServerName(Arc::from(lsp_adapter.name()))
7376                                })
7377                        });
7378                    language_server_name.map(|language_server_name| {
7379                        project.open_local_buffer_via_lsp(
7380                            lsp_location.uri.clone(),
7381                            server_id,
7382                            language_server_name,
7383                            cx,
7384                        )
7385                    })
7386                })
7387            })?;
7388            let location = match location_task {
7389                Some(task) => Some({
7390                    let target_buffer_handle = task.await.context("open local buffer")?;
7391                    let range = target_buffer_handle.update(&mut cx, |target_buffer, _| {
7392                        let target_start = target_buffer
7393                            .clip_point_utf16(point_from_lsp(lsp_location.range.start), Bias::Left);
7394                        let target_end = target_buffer
7395                            .clip_point_utf16(point_from_lsp(lsp_location.range.end), Bias::Left);
7396                        target_buffer.anchor_after(target_start)
7397                            ..target_buffer.anchor_before(target_end)
7398                    })?;
7399                    Location {
7400                        buffer: target_buffer_handle,
7401                        range,
7402                    }
7403                }),
7404                None => None,
7405            };
7406            Ok(location)
7407        })
7408    }
7409
7410    pub fn find_all_references(
7411        &mut self,
7412        _: &FindAllReferences,
7413        cx: &mut ViewContext<Self>,
7414    ) -> Option<Task<Result<()>>> {
7415        let buffer = self.buffer.read(cx);
7416        let head = self.selections.newest::<usize>(cx).head();
7417        let (buffer, head) = buffer.text_anchor_for_position(head, cx)?;
7418        let replica_id = self.replica_id(cx);
7419
7420        let workspace = self.workspace()?;
7421        let project = workspace.read(cx).project().clone();
7422        let references = project.update(cx, |project, cx| project.references(&buffer, head, cx));
7423        Some(cx.spawn(|_, mut cx| async move {
7424            let locations = references.await?;
7425            if locations.is_empty() {
7426                return Ok(());
7427            }
7428
7429            workspace.update(&mut cx, |workspace, cx| {
7430                let title = locations
7431                    .first()
7432                    .as_ref()
7433                    .map(|location| {
7434                        let buffer = location.buffer.read(cx);
7435                        format!(
7436                            "References to `{}`",
7437                            buffer
7438                                .text_for_range(location.range.clone())
7439                                .collect::<String>()
7440                        )
7441                    })
7442                    .unwrap();
7443                Self::open_locations_in_multibuffer(
7444                    workspace, locations, replica_id, title, false, cx,
7445                );
7446            })?;
7447
7448            Ok(())
7449        }))
7450    }
7451
7452    /// Opens a multibuffer with the given project locations in it
7453    pub fn open_locations_in_multibuffer(
7454        workspace: &mut Workspace,
7455        mut locations: Vec<Location>,
7456        replica_id: ReplicaId,
7457        title: String,
7458        split: bool,
7459        cx: &mut ViewContext<Workspace>,
7460    ) {
7461        // If there are multiple definitions, open them in a multibuffer
7462        locations.sort_by_key(|location| location.buffer.read(cx).remote_id());
7463        let mut locations = locations.into_iter().peekable();
7464        let mut ranges_to_highlight = Vec::new();
7465
7466        let excerpt_buffer = cx.build_model(|cx| {
7467            let mut multibuffer = MultiBuffer::new(replica_id);
7468            while let Some(location) = locations.next() {
7469                let buffer = location.buffer.read(cx);
7470                let mut ranges_for_buffer = Vec::new();
7471                let range = location.range.to_offset(buffer);
7472                ranges_for_buffer.push(range.clone());
7473
7474                while let Some(next_location) = locations.peek() {
7475                    if next_location.buffer == location.buffer {
7476                        ranges_for_buffer.push(next_location.range.to_offset(buffer));
7477                        locations.next();
7478                    } else {
7479                        break;
7480                    }
7481                }
7482
7483                ranges_for_buffer.sort_by_key(|range| (range.start, Reverse(range.end)));
7484                ranges_to_highlight.extend(multibuffer.push_excerpts_with_context_lines(
7485                    location.buffer.clone(),
7486                    ranges_for_buffer,
7487                    1,
7488                    cx,
7489                ))
7490            }
7491
7492            multibuffer.with_title(title)
7493        });
7494
7495        let editor = cx.build_view(|cx| {
7496            Editor::for_multibuffer(excerpt_buffer, Some(workspace.project().clone()), cx)
7497        });
7498        editor.update(cx, |editor, cx| {
7499            editor.highlight_background::<Self>(
7500                ranges_to_highlight,
7501                |theme| theme.editor_highlighted_line_background,
7502                cx,
7503            );
7504        });
7505        if split {
7506            workspace.split_item(SplitDirection::Right, Box::new(editor), cx);
7507        } else {
7508            workspace.add_item(Box::new(editor), cx);
7509        }
7510    }
7511
7512    pub fn rename(&mut self, _: &Rename, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
7513        use language::ToOffset as _;
7514
7515        let project = self.project.clone()?;
7516        let selection = self.selections.newest_anchor().clone();
7517        let (cursor_buffer, cursor_buffer_position) = self
7518            .buffer
7519            .read(cx)
7520            .text_anchor_for_position(selection.head(), cx)?;
7521        let (tail_buffer, _) = self
7522            .buffer
7523            .read(cx)
7524            .text_anchor_for_position(selection.tail(), cx)?;
7525        if tail_buffer != cursor_buffer {
7526            return None;
7527        }
7528
7529        let snapshot = cursor_buffer.read(cx).snapshot();
7530        let cursor_buffer_offset = cursor_buffer_position.to_offset(&snapshot);
7531        let prepare_rename = project.update(cx, |project, cx| {
7532            project.prepare_rename(cursor_buffer, cursor_buffer_offset, cx)
7533        });
7534
7535        Some(cx.spawn(|this, mut cx| async move {
7536            let rename_range = if let Some(range) = prepare_rename.await? {
7537                Some(range)
7538            } else {
7539                this.update(&mut cx, |this, cx| {
7540                    let buffer = this.buffer.read(cx).snapshot(cx);
7541                    let mut buffer_highlights = this
7542                        .document_highlights_for_position(selection.head(), &buffer)
7543                        .filter(|highlight| {
7544                            highlight.start.excerpt_id == selection.head().excerpt_id
7545                                && highlight.end.excerpt_id == selection.head().excerpt_id
7546                        });
7547                    buffer_highlights
7548                        .next()
7549                        .map(|highlight| highlight.start.text_anchor..highlight.end.text_anchor)
7550                })?
7551            };
7552            if let Some(rename_range) = rename_range {
7553                let rename_buffer_range = rename_range.to_offset(&snapshot);
7554                let cursor_offset_in_rename_range =
7555                    cursor_buffer_offset.saturating_sub(rename_buffer_range.start);
7556
7557                this.update(&mut cx, |this, cx| {
7558                    this.take_rename(false, cx);
7559                    let buffer = this.buffer.read(cx).read(cx);
7560                    let cursor_offset = selection.head().to_offset(&buffer);
7561                    let rename_start = cursor_offset.saturating_sub(cursor_offset_in_rename_range);
7562                    let rename_end = rename_start + rename_buffer_range.len();
7563                    let range = buffer.anchor_before(rename_start)..buffer.anchor_after(rename_end);
7564                    let mut old_highlight_id = None;
7565                    let old_name: Arc<str> = buffer
7566                        .chunks(rename_start..rename_end, true)
7567                        .map(|chunk| {
7568                            if old_highlight_id.is_none() {
7569                                old_highlight_id = chunk.syntax_highlight_id;
7570                            }
7571                            chunk.text
7572                        })
7573                        .collect::<String>()
7574                        .into();
7575
7576                    drop(buffer);
7577
7578                    // Position the selection in the rename editor so that it matches the current selection.
7579                    this.show_local_selections = false;
7580                    let rename_editor = cx.build_view(|cx| {
7581                        let mut editor = Editor::single_line(cx);
7582                        editor.buffer.update(cx, |buffer, cx| {
7583                            buffer.edit([(0..0, old_name.clone())], None, cx)
7584                        });
7585                        editor.select_all(&SelectAll, cx);
7586                        editor
7587                    });
7588
7589                    let ranges = this
7590                        .clear_background_highlights::<DocumentHighlightWrite>(cx)
7591                        .into_iter()
7592                        .flat_map(|(_, ranges)| ranges.into_iter())
7593                        .chain(
7594                            this.clear_background_highlights::<DocumentHighlightRead>(cx)
7595                                .into_iter()
7596                                .flat_map(|(_, ranges)| ranges.into_iter()),
7597                        )
7598                        .collect();
7599
7600                    this.highlight_text::<Rename>(
7601                        ranges,
7602                        HighlightStyle {
7603                            fade_out: Some(0.6),
7604                            ..Default::default()
7605                        },
7606                        cx,
7607                    );
7608                    let rename_focus_handle = rename_editor.focus_handle(cx);
7609                    cx.focus(&rename_focus_handle);
7610                    let block_id = this.insert_blocks(
7611                        [BlockProperties {
7612                            style: BlockStyle::Flex,
7613                            position: range.start.clone(),
7614                            height: 1,
7615                            render: Arc::new({
7616                                let rename_editor = rename_editor.clone();
7617                                move |cx: &mut BlockContext| {
7618                                    let mut text_style = cx.editor_style.text.clone();
7619                                    if let Some(highlight_style) = old_highlight_id
7620                                        .and_then(|h| h.style(&cx.editor_style.syntax))
7621                                    {
7622                                        text_style = text_style.highlight(highlight_style);
7623                                    }
7624                                    div()
7625                                        .pl(cx.anchor_x)
7626                                        .child(EditorElement::new(
7627                                            &rename_editor,
7628                                            EditorStyle {
7629                                                background: cx.theme().system().transparent,
7630                                                local_player: cx.editor_style.local_player,
7631                                                text: text_style,
7632                                                scrollbar_width: cx.editor_style.scrollbar_width,
7633                                                syntax: cx.editor_style.syntax.clone(),
7634                                                diagnostic_style: cx
7635                                                    .editor_style
7636                                                    .diagnostic_style
7637                                                    .clone(),
7638                                            },
7639                                        ))
7640                                        .into_any_element()
7641                                }
7642                            }),
7643                            disposition: BlockDisposition::Below,
7644                        }],
7645                        Some(Autoscroll::fit()),
7646                        cx,
7647                    )[0];
7648                    this.pending_rename = Some(RenameState {
7649                        range,
7650                        old_name,
7651                        editor: rename_editor,
7652                        block_id,
7653                    });
7654                })?;
7655            }
7656
7657            Ok(())
7658        }))
7659    }
7660
7661    pub fn confirm_rename(
7662        &mut self,
7663        _: &ConfirmRename,
7664        cx: &mut ViewContext<Self>,
7665    ) -> Option<Task<Result<()>>> {
7666        let rename = self.take_rename(false, cx)?;
7667        let workspace = self.workspace()?;
7668        let (start_buffer, start) = self
7669            .buffer
7670            .read(cx)
7671            .text_anchor_for_position(rename.range.start.clone(), cx)?;
7672        let (end_buffer, end) = self
7673            .buffer
7674            .read(cx)
7675            .text_anchor_for_position(rename.range.end.clone(), cx)?;
7676        if start_buffer != end_buffer {
7677            return None;
7678        }
7679
7680        let buffer = start_buffer;
7681        let range = start..end;
7682        let old_name = rename.old_name;
7683        let new_name = rename.editor.read(cx).text(cx);
7684
7685        let rename = workspace
7686            .read(cx)
7687            .project()
7688            .clone()
7689            .update(cx, |project, cx| {
7690                project.perform_rename(buffer.clone(), range.start, new_name.clone(), true, cx)
7691            });
7692        let workspace = workspace.downgrade();
7693
7694        Some(cx.spawn(|editor, mut cx| async move {
7695            let project_transaction = rename.await?;
7696            Self::open_project_transaction(
7697                &editor,
7698                workspace,
7699                project_transaction,
7700                format!("Rename: {}{}", old_name, new_name),
7701                cx.clone(),
7702            )
7703            .await?;
7704
7705            editor.update(&mut cx, |editor, cx| {
7706                editor.refresh_document_highlights(cx);
7707            })?;
7708            Ok(())
7709        }))
7710    }
7711
7712    fn take_rename(
7713        &mut self,
7714        moving_cursor: bool,
7715        cx: &mut ViewContext<Self>,
7716    ) -> Option<RenameState> {
7717        let rename = self.pending_rename.take()?;
7718        if rename.editor.focus_handle(cx).is_focused(cx) {
7719            cx.focus(&self.focus_handle);
7720        }
7721
7722        self.remove_blocks(
7723            [rename.block_id].into_iter().collect(),
7724            Some(Autoscroll::fit()),
7725            cx,
7726        );
7727        self.clear_highlights::<Rename>(cx);
7728        self.show_local_selections = true;
7729
7730        if moving_cursor {
7731            let rename_editor = rename.editor.read(cx);
7732            let cursor_in_rename_editor = rename_editor.selections.newest::<usize>(cx).head();
7733
7734            // Update the selection to match the position of the selection inside
7735            // the rename editor.
7736            let snapshot = self.buffer.read(cx).read(cx);
7737            let rename_range = rename.range.to_offset(&snapshot);
7738            let cursor_in_editor = snapshot
7739                .clip_offset(rename_range.start + cursor_in_rename_editor, Bias::Left)
7740                .min(rename_range.end);
7741            drop(snapshot);
7742
7743            self.change_selections(None, cx, |s| {
7744                s.select_ranges(vec![cursor_in_editor..cursor_in_editor])
7745            });
7746        } else {
7747            self.refresh_document_highlights(cx);
7748        }
7749
7750        Some(rename)
7751    }
7752
7753    #[cfg(any(test, feature = "test-support"))]
7754    pub fn pending_rename(&self) -> Option<&RenameState> {
7755        self.pending_rename.as_ref()
7756    }
7757
7758    fn format(&mut self, _: &Format, cx: &mut ViewContext<Self>) -> Option<Task<Result<()>>> {
7759        let project = match &self.project {
7760            Some(project) => project.clone(),
7761            None => return None,
7762        };
7763
7764        Some(self.perform_format(project, FormatTrigger::Manual, cx))
7765    }
7766
7767    fn perform_format(
7768        &mut self,
7769        project: Model<Project>,
7770        trigger: FormatTrigger,
7771        cx: &mut ViewContext<Self>,
7772    ) -> Task<Result<()>> {
7773        let buffer = self.buffer().clone();
7774        let buffers = buffer.read(cx).all_buffers();
7775
7776        let mut timeout = cx.background_executor().timer(FORMAT_TIMEOUT).fuse();
7777        let format = project.update(cx, |project, cx| project.format(buffers, true, trigger, cx));
7778
7779        cx.spawn(|_, mut cx| async move {
7780            let transaction = futures::select_biased! {
7781                _ = timeout => {
7782                    log::warn!("timed out waiting for formatting");
7783                    None
7784                }
7785                transaction = format.log_err().fuse() => transaction,
7786            };
7787
7788            buffer.update(&mut cx, |buffer, cx| {
7789                if let Some(transaction) = transaction {
7790                    if !buffer.is_singleton() {
7791                        buffer.push_transaction(&transaction.0, cx);
7792                    }
7793                }
7794
7795                cx.notify();
7796            });
7797
7798            Ok(())
7799        })
7800    }
7801
7802    fn restart_language_server(&mut self, _: &RestartLanguageServer, cx: &mut ViewContext<Self>) {
7803        if let Some(project) = self.project.clone() {
7804            self.buffer.update(cx, |multi_buffer, cx| {
7805                project.update(cx, |project, cx| {
7806                    project.restart_language_servers_for_buffers(multi_buffer.all_buffers(), cx);
7807                });
7808            })
7809        }
7810    }
7811
7812    fn show_character_palette(&mut self, _: &ShowCharacterPalette, cx: &mut ViewContext<Self>) {
7813        cx.show_character_palette();
7814    }
7815
7816    fn refresh_active_diagnostics(&mut self, cx: &mut ViewContext<Editor>) {
7817        if let Some(active_diagnostics) = self.active_diagnostics.as_mut() {
7818            let buffer = self.buffer.read(cx).snapshot(cx);
7819            let primary_range_start = active_diagnostics.primary_range.start.to_offset(&buffer);
7820            let is_valid = buffer
7821                .diagnostics_in_range::<_, usize>(active_diagnostics.primary_range.clone(), false)
7822                .any(|entry| {
7823                    entry.diagnostic.is_primary
7824                        && !entry.range.is_empty()
7825                        && entry.range.start == primary_range_start
7826                        && entry.diagnostic.message == active_diagnostics.primary_message
7827                });
7828
7829            if is_valid != active_diagnostics.is_valid {
7830                active_diagnostics.is_valid = is_valid;
7831                let mut new_styles = HashMap::default();
7832                for (block_id, diagnostic) in &active_diagnostics.blocks {
7833                    new_styles.insert(
7834                        *block_id,
7835                        diagnostic_block_renderer(diagnostic.clone(), is_valid),
7836                    );
7837                }
7838                self.display_map
7839                    .update(cx, |display_map, _| display_map.replace_blocks(new_styles));
7840            }
7841        }
7842    }
7843
7844    fn activate_diagnostics(&mut self, group_id: usize, cx: &mut ViewContext<Self>) -> bool {
7845        self.dismiss_diagnostics(cx);
7846        self.active_diagnostics = self.display_map.update(cx, |display_map, cx| {
7847            let buffer = self.buffer.read(cx).snapshot(cx);
7848
7849            let mut primary_range = None;
7850            let mut primary_message = None;
7851            let mut group_end = Point::zero();
7852            let diagnostic_group = buffer
7853                .diagnostic_group::<Point>(group_id)
7854                .map(|entry| {
7855                    if entry.range.end > group_end {
7856                        group_end = entry.range.end;
7857                    }
7858                    if entry.diagnostic.is_primary {
7859                        primary_range = Some(entry.range.clone());
7860                        primary_message = Some(entry.diagnostic.message.clone());
7861                    }
7862                    entry
7863                })
7864                .collect::<Vec<_>>();
7865            let primary_range = primary_range?;
7866            let primary_message = primary_message?;
7867            let primary_range =
7868                buffer.anchor_after(primary_range.start)..buffer.anchor_before(primary_range.end);
7869
7870            let blocks = display_map
7871                .insert_blocks(
7872                    diagnostic_group.iter().map(|entry| {
7873                        let diagnostic = entry.diagnostic.clone();
7874                        let message_height = diagnostic.message.lines().count() as u8;
7875                        BlockProperties {
7876                            style: BlockStyle::Fixed,
7877                            position: buffer.anchor_after(entry.range.start),
7878                            height: message_height,
7879                            render: diagnostic_block_renderer(diagnostic, true),
7880                            disposition: BlockDisposition::Below,
7881                        }
7882                    }),
7883                    cx,
7884                )
7885                .into_iter()
7886                .zip(diagnostic_group.into_iter().map(|entry| entry.diagnostic))
7887                .collect();
7888
7889            Some(ActiveDiagnosticGroup {
7890                primary_range,
7891                primary_message,
7892                blocks,
7893                is_valid: true,
7894            })
7895        });
7896        self.active_diagnostics.is_some()
7897    }
7898
7899    fn dismiss_diagnostics(&mut self, cx: &mut ViewContext<Self>) {
7900        if let Some(active_diagnostic_group) = self.active_diagnostics.take() {
7901            self.display_map.update(cx, |display_map, cx| {
7902                display_map.remove_blocks(active_diagnostic_group.blocks.into_keys().collect(), cx);
7903            });
7904            cx.notify();
7905        }
7906    }
7907
7908    pub fn set_selections_from_remote(
7909        &mut self,
7910        selections: Vec<Selection<Anchor>>,
7911        pending_selection: Option<Selection<Anchor>>,
7912        cx: &mut ViewContext<Self>,
7913    ) {
7914        let old_cursor_position = self.selections.newest_anchor().head();
7915        self.selections.change_with(cx, |s| {
7916            s.select_anchors(selections);
7917            if let Some(pending_selection) = pending_selection {
7918                s.set_pending(pending_selection, SelectMode::Character);
7919            } else {
7920                s.clear_pending();
7921            }
7922        });
7923        self.selections_did_change(false, &old_cursor_position, cx);
7924    }
7925
7926    fn push_to_selection_history(&mut self) {
7927        self.selection_history.push(SelectionHistoryEntry {
7928            selections: self.selections.disjoint_anchors(),
7929            select_next_state: self.select_next_state.clone(),
7930            select_prev_state: self.select_prev_state.clone(),
7931            add_selections_state: self.add_selections_state.clone(),
7932        });
7933    }
7934
7935    pub fn transact(
7936        &mut self,
7937        cx: &mut ViewContext<Self>,
7938        update: impl FnOnce(&mut Self, &mut ViewContext<Self>),
7939    ) -> Option<TransactionId> {
7940        self.start_transaction_at(Instant::now(), cx);
7941        update(self, cx);
7942        self.end_transaction_at(Instant::now(), cx)
7943    }
7944
7945    fn start_transaction_at(&mut self, now: Instant, cx: &mut ViewContext<Self>) {
7946        self.end_selection(cx);
7947        if let Some(tx_id) = self
7948            .buffer
7949            .update(cx, |buffer, cx| buffer.start_transaction_at(now, cx))
7950        {
7951            self.selection_history
7952                .insert_transaction(tx_id, self.selections.disjoint_anchors());
7953        }
7954    }
7955
7956    fn end_transaction_at(
7957        &mut self,
7958        now: Instant,
7959        cx: &mut ViewContext<Self>,
7960    ) -> Option<TransactionId> {
7961        if let Some(tx_id) = self
7962            .buffer
7963            .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
7964        {
7965            if let Some((_, end_selections)) = self.selection_history.transaction_mut(tx_id) {
7966                *end_selections = Some(self.selections.disjoint_anchors());
7967            } else {
7968                log::error!("unexpectedly ended a transaction that wasn't started by this editor");
7969            }
7970
7971            cx.emit(EditorEvent::Edited);
7972            Some(tx_id)
7973        } else {
7974            None
7975        }
7976    }
7977
7978    pub fn fold(&mut self, _: &Fold, cx: &mut ViewContext<Self>) {
7979        let mut fold_ranges = Vec::new();
7980
7981        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
7982
7983        let selections = self.selections.all_adjusted(cx);
7984        for selection in selections {
7985            let range = selection.range().sorted();
7986            let buffer_start_row = range.start.row;
7987
7988            for row in (0..=range.end.row).rev() {
7989                let fold_range = display_map.foldable_range(row);
7990
7991                if let Some(fold_range) = fold_range {
7992                    if fold_range.end.row >= buffer_start_row {
7993                        fold_ranges.push(fold_range);
7994                        if row <= range.start.row {
7995                            break;
7996                        }
7997                    }
7998                }
7999            }
8000        }
8001
8002        self.fold_ranges(fold_ranges, true, cx);
8003    }
8004
8005    pub fn fold_at(&mut self, fold_at: &FoldAt, cx: &mut ViewContext<Self>) {
8006        let buffer_row = fold_at.buffer_row;
8007        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
8008
8009        if let Some(fold_range) = display_map.foldable_range(buffer_row) {
8010            let autoscroll = self
8011                .selections
8012                .all::<Point>(cx)
8013                .iter()
8014                .any(|selection| fold_range.overlaps(&selection.range()));
8015
8016            self.fold_ranges(std::iter::once(fold_range), autoscroll, cx);
8017        }
8018    }
8019
8020    pub fn unfold_lines(&mut self, _: &UnfoldLines, cx: &mut ViewContext<Self>) {
8021        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
8022        let buffer = &display_map.buffer_snapshot;
8023        let selections = self.selections.all::<Point>(cx);
8024        let ranges = selections
8025            .iter()
8026            .map(|s| {
8027                let range = s.display_range(&display_map).sorted();
8028                let mut start = range.start.to_point(&display_map);
8029                let mut end = range.end.to_point(&display_map);
8030                start.column = 0;
8031                end.column = buffer.line_len(end.row);
8032                start..end
8033            })
8034            .collect::<Vec<_>>();
8035
8036        self.unfold_ranges(ranges, true, true, cx);
8037    }
8038
8039    pub fn unfold_at(&mut self, unfold_at: &UnfoldAt, cx: &mut ViewContext<Self>) {
8040        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
8041
8042        let intersection_range = Point::new(unfold_at.buffer_row, 0)
8043            ..Point::new(
8044                unfold_at.buffer_row,
8045                display_map.buffer_snapshot.line_len(unfold_at.buffer_row),
8046            );
8047
8048        let autoscroll = self
8049            .selections
8050            .all::<Point>(cx)
8051            .iter()
8052            .any(|selection| selection.range().overlaps(&intersection_range));
8053
8054        self.unfold_ranges(std::iter::once(intersection_range), true, autoscroll, cx)
8055    }
8056
8057    pub fn fold_selected_ranges(&mut self, _: &FoldSelectedRanges, cx: &mut ViewContext<Self>) {
8058        let selections = self.selections.all::<Point>(cx);
8059        let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
8060        let line_mode = self.selections.line_mode;
8061        let ranges = selections.into_iter().map(|s| {
8062            if line_mode {
8063                let start = Point::new(s.start.row, 0);
8064                let end = Point::new(s.end.row, display_map.buffer_snapshot.line_len(s.end.row));
8065                start..end
8066            } else {
8067                s.start..s.end
8068            }
8069        });
8070        self.fold_ranges(ranges, true, cx);
8071    }
8072
8073    pub fn fold_ranges<T: ToOffset + Clone>(
8074        &mut self,
8075        ranges: impl IntoIterator<Item = Range<T>>,
8076        auto_scroll: bool,
8077        cx: &mut ViewContext<Self>,
8078    ) {
8079        let mut ranges = ranges.into_iter().peekable();
8080        if ranges.peek().is_some() {
8081            self.display_map.update(cx, |map, cx| map.fold(ranges, cx));
8082
8083            if auto_scroll {
8084                self.request_autoscroll(Autoscroll::fit(), cx);
8085            }
8086
8087            cx.notify();
8088        }
8089    }
8090
8091    pub fn unfold_ranges<T: ToOffset + Clone>(
8092        &mut self,
8093        ranges: impl IntoIterator<Item = Range<T>>,
8094        inclusive: bool,
8095        auto_scroll: bool,
8096        cx: &mut ViewContext<Self>,
8097    ) {
8098        let mut ranges = ranges.into_iter().peekable();
8099        if ranges.peek().is_some() {
8100            self.display_map
8101                .update(cx, |map, cx| map.unfold(ranges, inclusive, cx));
8102            if auto_scroll {
8103                self.request_autoscroll(Autoscroll::fit(), cx);
8104            }
8105
8106            cx.notify();
8107        }
8108    }
8109
8110    pub fn set_gutter_hovered(&mut self, hovered: bool, cx: &mut ViewContext<Self>) {
8111        if hovered != self.gutter_hovered {
8112            self.gutter_hovered = hovered;
8113            cx.notify();
8114        }
8115    }
8116
8117    pub fn insert_blocks(
8118        &mut self,
8119        blocks: impl IntoIterator<Item = BlockProperties<Anchor>>,
8120        autoscroll: Option<Autoscroll>,
8121        cx: &mut ViewContext<Self>,
8122    ) -> Vec<BlockId> {
8123        let blocks = self
8124            .display_map
8125            .update(cx, |display_map, cx| display_map.insert_blocks(blocks, cx));
8126        if let Some(autoscroll) = autoscroll {
8127            self.request_autoscroll(autoscroll, cx);
8128        }
8129        blocks
8130    }
8131
8132    pub fn replace_blocks(
8133        &mut self,
8134        blocks: HashMap<BlockId, RenderBlock>,
8135        autoscroll: Option<Autoscroll>,
8136        cx: &mut ViewContext<Self>,
8137    ) {
8138        self.display_map
8139            .update(cx, |display_map, _| display_map.replace_blocks(blocks));
8140        if let Some(autoscroll) = autoscroll {
8141            self.request_autoscroll(autoscroll, cx);
8142        }
8143    }
8144
8145    pub fn remove_blocks(
8146        &mut self,
8147        block_ids: HashSet<BlockId>,
8148        autoscroll: Option<Autoscroll>,
8149        cx: &mut ViewContext<Self>,
8150    ) {
8151        self.display_map.update(cx, |display_map, cx| {
8152            display_map.remove_blocks(block_ids, cx)
8153        });
8154        if let Some(autoscroll) = autoscroll {
8155            self.request_autoscroll(autoscroll, cx);
8156        }
8157    }
8158
8159    pub fn longest_row(&self, cx: &mut AppContext) -> u32 {
8160        self.display_map
8161            .update(cx, |map, cx| map.snapshot(cx))
8162            .longest_row()
8163    }
8164
8165    pub fn max_point(&self, cx: &mut AppContext) -> DisplayPoint {
8166        self.display_map
8167            .update(cx, |map, cx| map.snapshot(cx))
8168            .max_point()
8169    }
8170
8171    pub fn text(&self, cx: &AppContext) -> String {
8172        self.buffer.read(cx).read(cx).text()
8173    }
8174
8175    pub fn set_text(&mut self, text: impl Into<Arc<str>>, cx: &mut ViewContext<Self>) {
8176        self.transact(cx, |this, cx| {
8177            this.buffer
8178                .read(cx)
8179                .as_singleton()
8180                .expect("you can only call set_text on editors for singleton buffers")
8181                .update(cx, |buffer, cx| buffer.set_text(text, cx));
8182        });
8183    }
8184
8185    pub fn display_text(&self, cx: &mut AppContext) -> String {
8186        self.display_map
8187            .update(cx, |map, cx| map.snapshot(cx))
8188            .text()
8189    }
8190
8191    pub fn wrap_guides(&self, cx: &AppContext) -> SmallVec<[(usize, bool); 2]> {
8192        let mut wrap_guides = smallvec::smallvec![];
8193
8194        if self.show_wrap_guides == Some(false) {
8195            return wrap_guides;
8196        }
8197
8198        let settings = self.buffer.read(cx).settings_at(0, cx);
8199        if settings.show_wrap_guides {
8200            if let SoftWrap::Column(soft_wrap) = self.soft_wrap_mode(cx) {
8201                wrap_guides.push((soft_wrap as usize, true));
8202            }
8203            wrap_guides.extend(settings.wrap_guides.iter().map(|guide| (*guide, false)))
8204        }
8205
8206        wrap_guides
8207    }
8208
8209    pub fn soft_wrap_mode(&self, cx: &AppContext) -> SoftWrap {
8210        let settings = self.buffer.read(cx).settings_at(0, cx);
8211        let mode = self
8212            .soft_wrap_mode_override
8213            .unwrap_or_else(|| settings.soft_wrap);
8214        match mode {
8215            language_settings::SoftWrap::None => SoftWrap::None,
8216            language_settings::SoftWrap::EditorWidth => SoftWrap::EditorWidth,
8217            language_settings::SoftWrap::PreferredLineLength => {
8218                SoftWrap::Column(settings.preferred_line_length)
8219            }
8220        }
8221    }
8222
8223    pub fn set_soft_wrap_mode(
8224        &mut self,
8225        mode: language_settings::SoftWrap,
8226        cx: &mut ViewContext<Self>,
8227    ) {
8228        self.soft_wrap_mode_override = Some(mode);
8229        cx.notify();
8230    }
8231
8232    pub fn set_style(&mut self, style: EditorStyle, cx: &mut ViewContext<Self>) {
8233        let rem_size = cx.rem_size();
8234        self.display_map.update(cx, |map, cx| {
8235            map.set_font(
8236                style.text.font(),
8237                style.text.font_size.to_pixels(rem_size),
8238                cx,
8239            )
8240        });
8241        self.style = Some(style);
8242    }
8243
8244    pub fn set_wrap_width(&self, width: Option<Pixels>, cx: &mut AppContext) -> bool {
8245        self.display_map
8246            .update(cx, |map, cx| map.set_wrap_width(width, cx))
8247    }
8248
8249    pub fn toggle_soft_wrap(&mut self, _: &ToggleSoftWrap, cx: &mut ViewContext<Self>) {
8250        if self.soft_wrap_mode_override.is_some() {
8251            self.soft_wrap_mode_override.take();
8252        } else {
8253            let soft_wrap = match self.soft_wrap_mode(cx) {
8254                SoftWrap::None => language_settings::SoftWrap::EditorWidth,
8255                SoftWrap::EditorWidth | SoftWrap::Column(_) => language_settings::SoftWrap::None,
8256            };
8257            self.soft_wrap_mode_override = Some(soft_wrap);
8258        }
8259        cx.notify();
8260    }
8261
8262    pub fn set_show_gutter(&mut self, show_gutter: bool, cx: &mut ViewContext<Self>) {
8263        self.show_gutter = show_gutter;
8264        cx.notify();
8265    }
8266
8267    pub fn set_show_wrap_guides(&mut self, show_gutter: bool, cx: &mut ViewContext<Self>) {
8268        self.show_wrap_guides = Some(show_gutter);
8269        cx.notify();
8270    }
8271
8272    pub fn reveal_in_finder(&mut self, _: &RevealInFinder, cx: &mut ViewContext<Self>) {
8273        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
8274            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
8275                cx.reveal_path(&file.abs_path(cx));
8276            }
8277        }
8278    }
8279
8280    pub fn copy_path(&mut self, _: &CopyPath, cx: &mut ViewContext<Self>) {
8281        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
8282            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
8283                if let Some(path) = file.abs_path(cx).to_str() {
8284                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
8285                }
8286            }
8287        }
8288    }
8289
8290    pub fn copy_relative_path(&mut self, _: &CopyRelativePath, cx: &mut ViewContext<Self>) {
8291        if let Some(buffer) = self.buffer().read(cx).as_singleton() {
8292            if let Some(file) = buffer.read(cx).file().and_then(|f| f.as_local()) {
8293                if let Some(path) = file.path().to_str() {
8294                    cx.write_to_clipboard(ClipboardItem::new(path.to_string()));
8295                }
8296            }
8297        }
8298    }
8299
8300    pub fn highlight_rows(&mut self, rows: Option<Range<u32>>) {
8301        self.highlighted_rows = rows;
8302    }
8303
8304    pub fn highlighted_rows(&self) -> Option<Range<u32>> {
8305        self.highlighted_rows.clone()
8306    }
8307
8308    pub fn highlight_background<T: 'static>(
8309        &mut self,
8310        ranges: Vec<Range<Anchor>>,
8311        color_fetcher: fn(&ThemeColors) -> Hsla,
8312        cx: &mut ViewContext<Self>,
8313    ) {
8314        self.background_highlights
8315            .insert(TypeId::of::<T>(), (color_fetcher, ranges));
8316        cx.notify();
8317    }
8318
8319    pub fn highlight_inlay_background<T: 'static>(
8320        &mut self,
8321        ranges: Vec<InlayHighlight>,
8322        color_fetcher: fn(&ThemeColors) -> Hsla,
8323        cx: &mut ViewContext<Self>,
8324    ) {
8325        // TODO: no actual highlights happen for inlays currently, find a way to do that
8326        self.inlay_background_highlights
8327            .insert(Some(TypeId::of::<T>()), (color_fetcher, ranges));
8328        cx.notify();
8329    }
8330
8331    pub fn clear_background_highlights<T: 'static>(
8332        &mut self,
8333        cx: &mut ViewContext<Self>,
8334    ) -> Option<BackgroundHighlight> {
8335        let text_highlights = self.background_highlights.remove(&TypeId::of::<T>());
8336        let inlay_highlights = self
8337            .inlay_background_highlights
8338            .remove(&Some(TypeId::of::<T>()));
8339        if text_highlights.is_some() || inlay_highlights.is_some() {
8340            cx.notify();
8341        }
8342        text_highlights
8343    }
8344
8345    #[cfg(feature = "test-support")]
8346    pub fn all_text_background_highlights(
8347        &mut self,
8348        cx: &mut ViewContext<Self>,
8349    ) -> Vec<(Range<DisplayPoint>, Hsla)> {
8350        let snapshot = self.snapshot(cx);
8351        let buffer = &snapshot.buffer_snapshot;
8352        let start = buffer.anchor_before(0);
8353        let end = buffer.anchor_after(buffer.len());
8354        let theme = cx.theme().colors();
8355        self.background_highlights_in_range(start..end, &snapshot, theme)
8356    }
8357
8358    fn document_highlights_for_position<'a>(
8359        &'a self,
8360        position: Anchor,
8361        buffer: &'a MultiBufferSnapshot,
8362    ) -> impl 'a + Iterator<Item = &Range<Anchor>> {
8363        let read_highlights = self
8364            .background_highlights
8365            .get(&TypeId::of::<DocumentHighlightRead>())
8366            .map(|h| &h.1);
8367        let write_highlights = self
8368            .background_highlights
8369            .get(&TypeId::of::<DocumentHighlightWrite>())
8370            .map(|h| &h.1);
8371        let left_position = position.bias_left(buffer);
8372        let right_position = position.bias_right(buffer);
8373        read_highlights
8374            .into_iter()
8375            .chain(write_highlights)
8376            .flat_map(move |ranges| {
8377                let start_ix = match ranges.binary_search_by(|probe| {
8378                    let cmp = probe.end.cmp(&left_position, buffer);
8379                    if cmp.is_ge() {
8380                        Ordering::Greater
8381                    } else {
8382                        Ordering::Less
8383                    }
8384                }) {
8385                    Ok(i) | Err(i) => i,
8386                };
8387
8388                let right_position = right_position.clone();
8389                ranges[start_ix..]
8390                    .iter()
8391                    .take_while(move |range| range.start.cmp(&right_position, buffer).is_le())
8392            })
8393    }
8394
8395    pub fn background_highlights_in_range(
8396        &self,
8397        search_range: Range<Anchor>,
8398        display_snapshot: &DisplaySnapshot,
8399        theme: &ThemeColors,
8400    ) -> Vec<(Range<DisplayPoint>, Hsla)> {
8401        let mut results = Vec::new();
8402        for (color_fetcher, ranges) in self.background_highlights.values() {
8403            let color = color_fetcher(theme);
8404            let start_ix = match ranges.binary_search_by(|probe| {
8405                let cmp = probe
8406                    .end
8407                    .cmp(&search_range.start, &display_snapshot.buffer_snapshot);
8408                if cmp.is_gt() {
8409                    Ordering::Greater
8410                } else {
8411                    Ordering::Less
8412                }
8413            }) {
8414                Ok(i) | Err(i) => i,
8415            };
8416            for range in &ranges[start_ix..] {
8417                if range
8418                    .start
8419                    .cmp(&search_range.end, &display_snapshot.buffer_snapshot)
8420                    .is_ge()
8421                {
8422                    break;
8423                }
8424
8425                let start = range.start.to_display_point(&display_snapshot);
8426                let end = range.end.to_display_point(&display_snapshot);
8427                results.push((start..end, color))
8428            }
8429        }
8430        results
8431    }
8432
8433    pub fn background_highlight_row_ranges<T: 'static>(
8434        &self,
8435        search_range: Range<Anchor>,
8436        display_snapshot: &DisplaySnapshot,
8437        count: usize,
8438    ) -> Vec<RangeInclusive<DisplayPoint>> {
8439        let mut results = Vec::new();
8440        let Some((_, ranges)) = self.background_highlights.get(&TypeId::of::<T>()) else {
8441            return vec![];
8442        };
8443
8444        let start_ix = match ranges.binary_search_by(|probe| {
8445            let cmp = probe
8446                .end
8447                .cmp(&search_range.start, &display_snapshot.buffer_snapshot);
8448            if cmp.is_gt() {
8449                Ordering::Greater
8450            } else {
8451                Ordering::Less
8452            }
8453        }) {
8454            Ok(i) | Err(i) => i,
8455        };
8456        let mut push_region = |start: Option<Point>, end: Option<Point>| {
8457            if let (Some(start_display), Some(end_display)) = (start, end) {
8458                results.push(
8459                    start_display.to_display_point(display_snapshot)
8460                        ..=end_display.to_display_point(display_snapshot),
8461                );
8462            }
8463        };
8464        let mut start_row: Option<Point> = None;
8465        let mut end_row: Option<Point> = None;
8466        if ranges.len() > count {
8467            return Vec::new();
8468        }
8469        for range in &ranges[start_ix..] {
8470            if range
8471                .start
8472                .cmp(&search_range.end, &display_snapshot.buffer_snapshot)
8473                .is_ge()
8474            {
8475                break;
8476            }
8477            let end = range.end.to_point(&display_snapshot.buffer_snapshot);
8478            if let Some(current_row) = &end_row {
8479                if end.row == current_row.row {
8480                    continue;
8481                }
8482            }
8483            let start = range.start.to_point(&display_snapshot.buffer_snapshot);
8484            if start_row.is_none() {
8485                assert_eq!(end_row, None);
8486                start_row = Some(start);
8487                end_row = Some(end);
8488                continue;
8489            }
8490            if let Some(current_end) = end_row.as_mut() {
8491                if start.row > current_end.row + 1 {
8492                    push_region(start_row, end_row);
8493                    start_row = Some(start);
8494                    end_row = Some(end);
8495                } else {
8496                    // Merge two hunks.
8497                    *current_end = end;
8498                }
8499            } else {
8500                unreachable!();
8501            }
8502        }
8503        // We might still have a hunk that was not rendered (if there was a search hit on the last line)
8504        push_region(start_row, end_row);
8505        results
8506    }
8507
8508    pub fn highlight_text<T: 'static>(
8509        &mut self,
8510        ranges: Vec<Range<Anchor>>,
8511        style: HighlightStyle,
8512        cx: &mut ViewContext<Self>,
8513    ) {
8514        self.display_map.update(cx, |map, _| {
8515            map.highlight_text(TypeId::of::<T>(), ranges, style)
8516        });
8517        cx.notify();
8518    }
8519
8520    pub fn highlight_inlays<T: 'static>(
8521        &mut self,
8522        highlights: Vec<InlayHighlight>,
8523        style: HighlightStyle,
8524        cx: &mut ViewContext<Self>,
8525    ) {
8526        self.display_map.update(cx, |map, _| {
8527            map.highlight_inlays(TypeId::of::<T>(), highlights, style)
8528        });
8529        cx.notify();
8530    }
8531
8532    pub fn text_highlights<'a, T: 'static>(
8533        &'a self,
8534        cx: &'a AppContext,
8535    ) -> Option<(HighlightStyle, &'a [Range<Anchor>])> {
8536        self.display_map.read(cx).text_highlights(TypeId::of::<T>())
8537    }
8538
8539    pub fn clear_highlights<T: 'static>(&mut self, cx: &mut ViewContext<Self>) {
8540        let cleared = self
8541            .display_map
8542            .update(cx, |map, _| map.clear_highlights(TypeId::of::<T>()));
8543        if cleared {
8544            cx.notify();
8545        }
8546    }
8547
8548    pub fn show_local_cursors(&self, cx: &WindowContext) -> bool {
8549        self.blink_manager.read(cx).visible() && self.focus_handle.is_focused(cx)
8550    }
8551
8552    fn on_buffer_changed(&mut self, _: Model<MultiBuffer>, cx: &mut ViewContext<Self>) {
8553        cx.notify();
8554    }
8555
8556    fn on_buffer_event(
8557        &mut self,
8558        multibuffer: Model<MultiBuffer>,
8559        event: &multi_buffer::Event,
8560        cx: &mut ViewContext<Self>,
8561    ) {
8562        match event {
8563            multi_buffer::Event::Edited {
8564                sigleton_buffer_edited,
8565            } => {
8566                self.refresh_active_diagnostics(cx);
8567                self.refresh_code_actions(cx);
8568                if self.has_active_copilot_suggestion(cx) {
8569                    self.update_visible_copilot_suggestion(cx);
8570                }
8571                cx.emit(EditorEvent::BufferEdited);
8572                cx.emit(ItemEvent::Edit);
8573                cx.emit(ItemEvent::UpdateBreadcrumbs);
8574                cx.emit(SearchEvent::MatchesInvalidated);
8575
8576                if *sigleton_buffer_edited {
8577                    if let Some(project) = &self.project {
8578                        let project = project.read(cx);
8579                        let languages_affected = multibuffer
8580                            .read(cx)
8581                            .all_buffers()
8582                            .into_iter()
8583                            .filter_map(|buffer| {
8584                                let buffer = buffer.read(cx);
8585                                let language = buffer.language()?;
8586                                if project.is_local()
8587                                    && project.language_servers_for_buffer(buffer, cx).count() == 0
8588                                {
8589                                    None
8590                                } else {
8591                                    Some(language)
8592                                }
8593                            })
8594                            .cloned()
8595                            .collect::<HashSet<_>>();
8596                        if !languages_affected.is_empty() {
8597                            self.refresh_inlay_hints(
8598                                InlayHintRefreshReason::BufferEdited(languages_affected),
8599                                cx,
8600                            );
8601                        }
8602                    }
8603                }
8604            }
8605            multi_buffer::Event::ExcerptsAdded {
8606                buffer,
8607                predecessor,
8608                excerpts,
8609            } => {
8610                cx.emit(EditorEvent::ExcerptsAdded {
8611                    buffer: buffer.clone(),
8612                    predecessor: *predecessor,
8613                    excerpts: excerpts.clone(),
8614                });
8615                self.refresh_inlay_hints(InlayHintRefreshReason::NewLinesShown, cx);
8616            }
8617            multi_buffer::Event::ExcerptsRemoved { ids } => {
8618                self.refresh_inlay_hints(InlayHintRefreshReason::ExcerptsRemoved(ids.clone()), cx);
8619                cx.emit(EditorEvent::ExcerptsRemoved { ids: ids.clone() })
8620            }
8621            multi_buffer::Event::Reparsed => {
8622                cx.emit(ItemEvent::UpdateBreadcrumbs);
8623            }
8624            multi_buffer::Event::DirtyChanged => {
8625                cx.emit(ItemEvent::UpdateTab);
8626            }
8627            multi_buffer::Event::Saved
8628            | multi_buffer::Event::FileHandleChanged
8629            | multi_buffer::Event::Reloaded => {
8630                cx.emit(ItemEvent::UpdateTab);
8631                cx.emit(ItemEvent::UpdateBreadcrumbs);
8632            }
8633            multi_buffer::Event::DiffBaseChanged => cx.emit(EditorEvent::DiffBaseChanged),
8634            multi_buffer::Event::Closed => cx.emit(ItemEvent::CloseItem),
8635            multi_buffer::Event::DiagnosticsUpdated => {
8636                self.refresh_active_diagnostics(cx);
8637            }
8638            _ => {}
8639        };
8640    }
8641
8642    fn on_display_map_changed(&mut self, _: Model<DisplayMap>, cx: &mut ViewContext<Self>) {
8643        cx.notify();
8644    }
8645
8646    fn settings_changed(&mut self, cx: &mut ViewContext<Self>) {
8647        self.refresh_copilot_suggestions(true, cx);
8648        self.refresh_inlay_hints(
8649            InlayHintRefreshReason::SettingsChange(inlay_hint_settings(
8650                self.selections.newest_anchor().head(),
8651                &self.buffer.read(cx).snapshot(cx),
8652                cx,
8653            )),
8654            cx,
8655        );
8656    }
8657
8658    //     pub fn set_searchable(&mut self, searchable: bool) {
8659    //         self.searchable = searchable;
8660    //     }
8661
8662    //     pub fn searchable(&self) -> bool {
8663    //         self.searchable
8664    //     }
8665
8666    fn open_excerpts(&mut self, _: &OpenExcerpts, cx: &mut ViewContext<Self>) {
8667        let buffer = self.buffer.read(cx);
8668        if buffer.is_singleton() {
8669            cx.propagate();
8670            return;
8671        }
8672
8673        let Some(workspace) = self.workspace() else {
8674            cx.propagate();
8675            return;
8676        };
8677
8678        let mut new_selections_by_buffer = HashMap::default();
8679        for selection in self.selections.all::<usize>(cx) {
8680            for (buffer, mut range, _) in
8681                buffer.range_to_buffer_ranges(selection.start..selection.end, cx)
8682            {
8683                if selection.reversed {
8684                    mem::swap(&mut range.start, &mut range.end);
8685                }
8686                new_selections_by_buffer
8687                    .entry(buffer)
8688                    .or_insert(Vec::new())
8689                    .push(range)
8690            }
8691        }
8692
8693        self.push_to_nav_history(self.selections.newest_anchor().head(), None, cx);
8694
8695        // We defer the pane interaction because we ourselves are a workspace item
8696        // and activating a new item causes the pane to call a method on us reentrantly,
8697        // which panics if we're on the stack.
8698        cx.window_context().defer(move |cx| {
8699            workspace.update(cx, |workspace, cx| {
8700                let pane = workspace.active_pane().clone();
8701                pane.update(cx, |pane, _| pane.disable_history());
8702
8703                for (buffer, ranges) in new_selections_by_buffer.into_iter() {
8704                    let editor = workspace.open_project_item::<Self>(buffer, cx);
8705                    editor.update(cx, |editor, cx| {
8706                        editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
8707                            s.select_ranges(ranges);
8708                        });
8709                    });
8710                }
8711
8712                pane.update(cx, |pane, _| pane.enable_history());
8713            })
8714        });
8715    }
8716
8717    fn jump(
8718        &mut self,
8719        path: ProjectPath,
8720        position: Point,
8721        anchor: language::Anchor,
8722        cx: &mut ViewContext<Self>,
8723    ) {
8724        let workspace = self.workspace();
8725        cx.spawn(|_, mut cx| async move {
8726            let workspace = workspace.ok_or_else(|| anyhow!("cannot jump without workspace"))?;
8727            let editor = workspace.update(&mut cx, |workspace, cx| {
8728                workspace.open_path(path, None, true, cx)
8729            })?;
8730            let editor = editor
8731                .await?
8732                .downcast::<Editor>()
8733                .ok_or_else(|| anyhow!("opened item was not an editor"))?
8734                .downgrade();
8735            editor.update(&mut cx, |editor, cx| {
8736                let buffer = editor
8737                    .buffer()
8738                    .read(cx)
8739                    .as_singleton()
8740                    .ok_or_else(|| anyhow!("cannot jump in a multi-buffer"))?;
8741                let buffer = buffer.read(cx);
8742                let cursor = if buffer.can_resolve(&anchor) {
8743                    language::ToPoint::to_point(&anchor, buffer)
8744                } else {
8745                    buffer.clip_point(position, Bias::Left)
8746                };
8747
8748                let nav_history = editor.nav_history.take();
8749                editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
8750                    s.select_ranges([cursor..cursor]);
8751                });
8752                editor.nav_history = nav_history;
8753
8754                anyhow::Ok(())
8755            })??;
8756
8757            anyhow::Ok(())
8758        })
8759        .detach_and_log_err(cx);
8760    }
8761
8762    fn marked_text_ranges(&self, cx: &AppContext) -> Option<Vec<Range<OffsetUtf16>>> {
8763        let snapshot = self.buffer.read(cx).read(cx);
8764        let (_, ranges) = self.text_highlights::<InputComposition>(cx)?;
8765        Some(
8766            ranges
8767                .iter()
8768                .map(move |range| {
8769                    range.start.to_offset_utf16(&snapshot)..range.end.to_offset_utf16(&snapshot)
8770                })
8771                .collect(),
8772        )
8773    }
8774
8775    fn selection_replacement_ranges(
8776        &self,
8777        range: Range<OffsetUtf16>,
8778        cx: &AppContext,
8779    ) -> Vec<Range<OffsetUtf16>> {
8780        let selections = self.selections.all::<OffsetUtf16>(cx);
8781        let newest_selection = selections
8782            .iter()
8783            .max_by_key(|selection| selection.id)
8784            .unwrap();
8785        let start_delta = range.start.0 as isize - newest_selection.start.0 as isize;
8786        let end_delta = range.end.0 as isize - newest_selection.end.0 as isize;
8787        let snapshot = self.buffer.read(cx).read(cx);
8788        selections
8789            .into_iter()
8790            .map(|mut selection| {
8791                selection.start.0 =
8792                    (selection.start.0 as isize).saturating_add(start_delta) as usize;
8793                selection.end.0 = (selection.end.0 as isize).saturating_add(end_delta) as usize;
8794                snapshot.clip_offset_utf16(selection.start, Bias::Left)
8795                    ..snapshot.clip_offset_utf16(selection.end, Bias::Right)
8796            })
8797            .collect()
8798    }
8799
8800    fn report_copilot_event(
8801        &self,
8802        suggestion_id: Option<String>,
8803        suggestion_accepted: bool,
8804        cx: &AppContext,
8805    ) {
8806        let Some(project) = &self.project else { return };
8807
8808        // If None, we are either getting suggestions in a new, unsaved file, or in a file without an extension
8809        let file_extension = self
8810            .buffer
8811            .read(cx)
8812            .as_singleton()
8813            .and_then(|b| b.read(cx).file())
8814            .and_then(|file| Path::new(file.file_name(cx)).extension())
8815            .and_then(|e| e.to_str())
8816            .map(|a| a.to_string());
8817
8818        let telemetry = project.read(cx).client().telemetry().clone();
8819        let telemetry_settings = *TelemetrySettings::get_global(cx);
8820
8821        telemetry.report_copilot_event(
8822            telemetry_settings,
8823            suggestion_id,
8824            suggestion_accepted,
8825            file_extension,
8826        )
8827    }
8828
8829    #[cfg(any(test, feature = "test-support"))]
8830    fn report_editor_event(
8831        &self,
8832        _operation: &'static str,
8833        _file_extension: Option<String>,
8834        _cx: &AppContext,
8835    ) {
8836    }
8837
8838    #[cfg(not(any(test, feature = "test-support")))]
8839    fn report_editor_event(
8840        &self,
8841        operation: &'static str,
8842        file_extension: Option<String>,
8843        cx: &AppContext,
8844    ) {
8845        let Some(project) = &self.project else { return };
8846
8847        // If None, we are in a file without an extension
8848        let file = self
8849            .buffer
8850            .read(cx)
8851            .as_singleton()
8852            .and_then(|b| b.read(cx).file());
8853        let file_extension = file_extension.or(file
8854            .as_ref()
8855            .and_then(|file| Path::new(file.file_name(cx)).extension())
8856            .and_then(|e| e.to_str())
8857            .map(|a| a.to_string()));
8858
8859        let vim_mode = cx
8860            .global::<SettingsStore>()
8861            .raw_user_settings()
8862            .get("vim_mode")
8863            == Some(&serde_json::Value::Bool(true));
8864        let telemetry_settings = *TelemetrySettings::get_global(cx);
8865        let copilot_enabled = all_language_settings(file, cx).copilot_enabled(None, None);
8866        let copilot_enabled_for_language = self
8867            .buffer
8868            .read(cx)
8869            .settings_at(0, cx)
8870            .show_copilot_suggestions;
8871
8872        let telemetry = project.read(cx).client().telemetry().clone();
8873        telemetry.report_editor_event(
8874            telemetry_settings,
8875            file_extension,
8876            vim_mode,
8877            operation,
8878            copilot_enabled,
8879            copilot_enabled_for_language,
8880        )
8881    }
8882
8883    /// Copy the highlighted chunks to the clipboard as JSON. The format is an array of lines,
8884    /// with each line being an array of {text, highlight} objects.
8885    fn copy_highlight_json(&mut self, _: &CopyHighlightJson, cx: &mut ViewContext<Self>) {
8886        let Some(buffer) = self.buffer.read(cx).as_singleton() else {
8887            return;
8888        };
8889
8890        #[derive(Serialize)]
8891        struct Chunk<'a> {
8892            text: String,
8893            highlight: Option<&'a str>,
8894        }
8895
8896        let snapshot = buffer.read(cx).snapshot();
8897        let range = self
8898            .selected_text_range(cx)
8899            .and_then(|selected_range| {
8900                if selected_range.is_empty() {
8901                    None
8902                } else {
8903                    Some(selected_range)
8904                }
8905            })
8906            .unwrap_or_else(|| 0..snapshot.len());
8907
8908        let chunks = snapshot.chunks(range, true);
8909        let mut lines = Vec::new();
8910        let mut line: VecDeque<Chunk> = VecDeque::new();
8911
8912        let Some(style) = self.style.as_ref() else {
8913            return;
8914        };
8915
8916        for chunk in chunks {
8917            let highlight = chunk
8918                .syntax_highlight_id
8919                .and_then(|id| id.name(&style.syntax));
8920            let mut chunk_lines = chunk.text.split("\n").peekable();
8921            while let Some(text) = chunk_lines.next() {
8922                let mut merged_with_last_token = false;
8923                if let Some(last_token) = line.back_mut() {
8924                    if last_token.highlight == highlight {
8925                        last_token.text.push_str(text);
8926                        merged_with_last_token = true;
8927                    }
8928                }
8929
8930                if !merged_with_last_token {
8931                    line.push_back(Chunk {
8932                        text: text.into(),
8933                        highlight,
8934                    });
8935                }
8936
8937                if chunk_lines.peek().is_some() {
8938                    if line.len() > 1 && line.front().unwrap().text.is_empty() {
8939                        line.pop_front();
8940                    }
8941                    if line.len() > 1 && line.back().unwrap().text.is_empty() {
8942                        line.pop_back();
8943                    }
8944
8945                    lines.push(mem::take(&mut line));
8946                }
8947            }
8948        }
8949
8950        let Some(lines) = serde_json::to_string_pretty(&lines).log_err() else {
8951            return;
8952        };
8953        cx.write_to_clipboard(ClipboardItem::new(lines));
8954    }
8955
8956    pub fn inlay_hint_cache(&self) -> &InlayHintCache {
8957        &self.inlay_hint_cache
8958    }
8959
8960    pub fn replay_insert_event(
8961        &mut self,
8962        text: &str,
8963        relative_utf16_range: Option<Range<isize>>,
8964        cx: &mut ViewContext<Self>,
8965    ) {
8966        if !self.input_enabled {
8967            cx.emit(EditorEvent::InputIgnored { text: text.into() });
8968            return;
8969        }
8970        if let Some(relative_utf16_range) = relative_utf16_range {
8971            let selections = self.selections.all::<OffsetUtf16>(cx);
8972            self.change_selections(None, cx, |s| {
8973                let new_ranges = selections.into_iter().map(|range| {
8974                    let start = OffsetUtf16(
8975                        range
8976                            .head()
8977                            .0
8978                            .saturating_add_signed(relative_utf16_range.start),
8979                    );
8980                    let end = OffsetUtf16(
8981                        range
8982                            .head()
8983                            .0
8984                            .saturating_add_signed(relative_utf16_range.end),
8985                    );
8986                    start..end
8987                });
8988                s.select_ranges(new_ranges);
8989            });
8990        }
8991
8992        self.handle_input(text, cx);
8993    }
8994
8995    pub fn supports_inlay_hints(&self, cx: &AppContext) -> bool {
8996        let Some(project) = self.project.as_ref() else {
8997            return false;
8998        };
8999        let project = project.read(cx);
9000
9001        let mut supports = false;
9002        self.buffer().read(cx).for_each_buffer(|buffer| {
9003            if !supports {
9004                supports = project
9005                    .language_servers_for_buffer(buffer.read(cx), cx)
9006                    .any(
9007                        |(_, server)| match server.capabilities().inlay_hint_provider {
9008                            Some(lsp::OneOf::Left(enabled)) => enabled,
9009                            Some(lsp::OneOf::Right(_)) => true,
9010                            None => false,
9011                        },
9012                    )
9013            }
9014        });
9015        supports
9016    }
9017
9018    pub fn focus(&self, cx: &mut WindowContext) {
9019        cx.focus(&self.focus_handle)
9020    }
9021
9022    pub fn is_focused(&self, cx: &WindowContext) -> bool {
9023        self.focus_handle.is_focused(cx)
9024    }
9025
9026    fn handle_focus(&mut self, cx: &mut ViewContext<Self>) {
9027        cx.emit(EditorEvent::Focused);
9028
9029        if let Some(rename) = self.pending_rename.as_ref() {
9030            let rename_editor_focus_handle = rename.editor.read(cx).focus_handle.clone();
9031            cx.focus(&rename_editor_focus_handle);
9032        } else {
9033            self.blink_manager.update(cx, BlinkManager::enable);
9034            self.buffer.update(cx, |buffer, cx| {
9035                buffer.finalize_last_transaction(cx);
9036                if self.leader_peer_id.is_none() {
9037                    buffer.set_active_selections(
9038                        &self.selections.disjoint_anchors(),
9039                        self.selections.line_mode,
9040                        self.cursor_shape,
9041                        cx,
9042                    );
9043                }
9044            });
9045        }
9046    }
9047
9048    fn handle_blur(&mut self, cx: &mut ViewContext<Self>) {
9049        // todo!()
9050        // let blurred_event = EditorBlurred(cx.handle());
9051        // cx.emit_global(blurred_event);
9052        self.blink_manager.update(cx, BlinkManager::disable);
9053        self.buffer
9054            .update(cx, |buffer, cx| buffer.remove_active_selections(cx));
9055        self.hide_context_menu(cx);
9056        hide_hover(self, cx);
9057        cx.emit(EditorEvent::Blurred);
9058        cx.notify();
9059    }
9060
9061    pub fn register_action<A: Action>(
9062        &mut self,
9063        listener: impl Fn(&A, &mut WindowContext) + 'static,
9064    ) -> &mut Self {
9065        let listener = Arc::new(listener);
9066
9067        self.editor_actions.push(Box::new(move |cx| {
9068            let view = cx.view().clone();
9069            let cx = cx.window_context();
9070            let listener = listener.clone();
9071            cx.on_action(TypeId::of::<A>(), move |action, phase, cx| {
9072                let action = action.downcast_ref().unwrap();
9073                if phase == DispatchPhase::Bubble {
9074                    listener(action, cx)
9075                }
9076            })
9077        }));
9078        self
9079    }
9080}
9081
9082pub trait CollaborationHub {
9083    fn collaborators<'a>(&self, cx: &'a AppContext) -> &'a HashMap<PeerId, Collaborator>;
9084    fn user_participant_indices<'a>(
9085        &self,
9086        cx: &'a AppContext,
9087    ) -> &'a HashMap<u64, ParticipantIndex>;
9088}
9089
9090impl CollaborationHub for Model<Project> {
9091    fn collaborators<'a>(&self, cx: &'a AppContext) -> &'a HashMap<PeerId, Collaborator> {
9092        self.read(cx).collaborators()
9093    }
9094
9095    fn user_participant_indices<'a>(
9096        &self,
9097        cx: &'a AppContext,
9098    ) -> &'a HashMap<u64, ParticipantIndex> {
9099        self.read(cx).user_store().read(cx).participant_indices()
9100    }
9101}
9102
9103fn inlay_hint_settings(
9104    location: Anchor,
9105    snapshot: &MultiBufferSnapshot,
9106    cx: &mut ViewContext<'_, Editor>,
9107) -> InlayHintSettings {
9108    let file = snapshot.file_at(location);
9109    let language = snapshot.language_at(location);
9110    let settings = all_language_settings(file, cx);
9111    settings
9112        .language(language.map(|l| l.name()).as_deref())
9113        .inlay_hints
9114}
9115
9116fn consume_contiguous_rows(
9117    contiguous_row_selections: &mut Vec<Selection<Point>>,
9118    selection: &Selection<Point>,
9119    display_map: &DisplaySnapshot,
9120    selections: &mut std::iter::Peekable<std::slice::Iter<Selection<Point>>>,
9121) -> (u32, u32) {
9122    contiguous_row_selections.push(selection.clone());
9123    let start_row = selection.start.row;
9124    let mut end_row = ending_row(selection, display_map);
9125
9126    while let Some(next_selection) = selections.peek() {
9127        if next_selection.start.row <= end_row {
9128            end_row = ending_row(next_selection, display_map);
9129            contiguous_row_selections.push(selections.next().unwrap().clone());
9130        } else {
9131            break;
9132        }
9133    }
9134    (start_row, end_row)
9135}
9136
9137fn ending_row(next_selection: &Selection<Point>, display_map: &DisplaySnapshot) -> u32 {
9138    if next_selection.end.column > 0 || next_selection.is_empty() {
9139        display_map.next_line_boundary(next_selection.end).0.row + 1
9140    } else {
9141        next_selection.end.row
9142    }
9143}
9144
9145impl EditorSnapshot {
9146    pub fn remote_selections_in_range<'a>(
9147        &'a self,
9148        range: &'a Range<Anchor>,
9149        collaboration_hub: &dyn CollaborationHub,
9150        cx: &'a AppContext,
9151    ) -> impl 'a + Iterator<Item = RemoteSelection> {
9152        let participant_indices = collaboration_hub.user_participant_indices(cx);
9153        let collaborators_by_peer_id = collaboration_hub.collaborators(cx);
9154        let collaborators_by_replica_id = collaborators_by_peer_id
9155            .iter()
9156            .map(|(_, collaborator)| (collaborator.replica_id, collaborator))
9157            .collect::<HashMap<_, _>>();
9158        self.buffer_snapshot
9159            .remote_selections_in_range(range)
9160            .filter_map(move |(replica_id, line_mode, cursor_shape, selection)| {
9161                let collaborator = collaborators_by_replica_id.get(&replica_id)?;
9162                let participant_index = participant_indices.get(&collaborator.user_id).copied();
9163                Some(RemoteSelection {
9164                    replica_id,
9165                    selection,
9166                    cursor_shape,
9167                    line_mode,
9168                    participant_index,
9169                    peer_id: collaborator.peer_id,
9170                })
9171            })
9172    }
9173
9174    pub fn language_at<T: ToOffset>(&self, position: T) -> Option<&Arc<Language>> {
9175        self.display_snapshot.buffer_snapshot.language_at(position)
9176    }
9177
9178    pub fn is_focused(&self) -> bool {
9179        self.is_focused
9180    }
9181
9182    pub fn placeholder_text(&self) -> Option<&Arc<str>> {
9183        self.placeholder_text.as_ref()
9184    }
9185
9186    pub fn scroll_position(&self) -> gpui::Point<f32> {
9187        self.scroll_anchor.scroll_position(&self.display_snapshot)
9188    }
9189}
9190
9191impl Deref for EditorSnapshot {
9192    type Target = DisplaySnapshot;
9193
9194    fn deref(&self) -> &Self::Target {
9195        &self.display_snapshot
9196    }
9197}
9198
9199#[derive(Clone, Debug, PartialEq, Eq)]
9200pub enum EditorEvent {
9201    InputIgnored {
9202        text: Arc<str>,
9203    },
9204    InputHandled {
9205        utf16_range_to_replace: Option<Range<isize>>,
9206        text: Arc<str>,
9207    },
9208    ExcerptsAdded {
9209        buffer: Model<Buffer>,
9210        predecessor: ExcerptId,
9211        excerpts: Vec<(ExcerptId, ExcerptRange<language::Anchor>)>,
9212    },
9213    ExcerptsRemoved {
9214        ids: Vec<ExcerptId>,
9215    },
9216    BufferEdited,
9217    Edited,
9218    Reparsed,
9219    Focused,
9220    Blurred,
9221    DirtyChanged,
9222    Saved,
9223    TitleChanged,
9224    DiffBaseChanged,
9225    SelectionsChanged {
9226        local: bool,
9227    },
9228    ScrollPositionChanged {
9229        local: bool,
9230        autoscroll: bool,
9231    },
9232    Closed,
9233}
9234
9235pub struct EditorFocused(pub View<Editor>);
9236pub struct EditorBlurred(pub View<Editor>);
9237pub struct EditorReleased(pub WeakView<Editor>);
9238
9239// impl Entity for Editor {
9240//     type Event = Event;
9241
9242//     fn release(&mut self, cx: &mut AppContext) {
9243//         cx.emit_global(EditorReleased(self.handle.clone()));
9244//     }
9245// }
9246//
9247impl EventEmitter<EditorEvent> for Editor {}
9248
9249impl FocusableView for Editor {
9250    fn focus_handle(&self, cx: &AppContext) -> FocusHandle {
9251        self.focus_handle.clone()
9252    }
9253}
9254
9255impl Render for Editor {
9256    type Element = EditorElement;
9257
9258    fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
9259        let settings = ThemeSettings::get_global(cx);
9260        let text_style = match self.mode {
9261            EditorMode::SingleLine | EditorMode::AutoHeight { .. } => TextStyle {
9262                color: cx.theme().colors().text,
9263                font_family: settings.ui_font.family.clone(),
9264                font_features: settings.ui_font.features,
9265                font_size: rems(0.875).into(),
9266                font_weight: FontWeight::NORMAL,
9267                font_style: FontStyle::Normal,
9268                line_height: relative(1.).into(),
9269                background_color: None,
9270                underline: None,
9271                white_space: WhiteSpace::Normal,
9272            },
9273
9274            EditorMode::Full => TextStyle {
9275                color: cx.theme().colors().text,
9276                font_family: settings.buffer_font.family.clone(),
9277                font_features: settings.buffer_font.features,
9278                font_size: settings.buffer_font_size.into(),
9279                font_weight: FontWeight::NORMAL,
9280                font_style: FontStyle::Normal,
9281                line_height: relative(settings.buffer_line_height.value()),
9282                background_color: None,
9283                underline: None,
9284                white_space: WhiteSpace::Normal,
9285            },
9286        };
9287
9288        let background = match self.mode {
9289            EditorMode::SingleLine => cx.theme().system().transparent,
9290            EditorMode::AutoHeight { max_lines } => cx.theme().system().transparent,
9291            EditorMode::Full => cx.theme().colors().editor_background,
9292        };
9293
9294        EditorElement::new(
9295            cx.view(),
9296            EditorStyle {
9297                background,
9298                local_player: cx.theme().players().local(),
9299                text: text_style,
9300                scrollbar_width: px(12.),
9301                syntax: cx.theme().syntax().clone(),
9302                diagnostic_style: cx.theme().diagnostic_style(),
9303            },
9304        )
9305    }
9306}
9307
9308impl InputHandler for Editor {
9309    fn text_for_range(
9310        &mut self,
9311        range_utf16: Range<usize>,
9312        cx: &mut ViewContext<Self>,
9313    ) -> Option<String> {
9314        Some(
9315            self.buffer
9316                .read(cx)
9317                .read(cx)
9318                .text_for_range(OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end))
9319                .collect(),
9320        )
9321    }
9322
9323    fn selected_text_range(&mut self, cx: &mut ViewContext<Self>) -> Option<Range<usize>> {
9324        // Prevent the IME menu from appearing when holding down an alphabetic key
9325        // while input is disabled.
9326        if !self.input_enabled {
9327            return None;
9328        }
9329
9330        let range = self.selections.newest::<OffsetUtf16>(cx).range();
9331        Some(range.start.0..range.end.0)
9332    }
9333
9334    fn marked_text_range(&self, cx: &mut ViewContext<Self>) -> Option<Range<usize>> {
9335        let snapshot = self.buffer.read(cx).read(cx);
9336        let range = self.text_highlights::<InputComposition>(cx)?.1.get(0)?;
9337        Some(range.start.to_offset_utf16(&snapshot).0..range.end.to_offset_utf16(&snapshot).0)
9338    }
9339
9340    fn unmark_text(&mut self, cx: &mut ViewContext<Self>) {
9341        self.clear_highlights::<InputComposition>(cx);
9342        self.ime_transaction.take();
9343    }
9344
9345    fn replace_text_in_range(
9346        &mut self,
9347        range_utf16: Option<Range<usize>>,
9348        text: &str,
9349        cx: &mut ViewContext<Self>,
9350    ) {
9351        if !self.input_enabled {
9352            cx.emit(EditorEvent::InputIgnored { text: text.into() });
9353            return;
9354        }
9355
9356        self.transact(cx, |this, cx| {
9357            let new_selected_ranges = if let Some(range_utf16) = range_utf16 {
9358                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
9359                Some(this.selection_replacement_ranges(range_utf16, cx))
9360            } else {
9361                this.marked_text_ranges(cx)
9362            };
9363
9364            let range_to_replace = new_selected_ranges.as_ref().and_then(|ranges_to_replace| {
9365                let newest_selection_id = this.selections.newest_anchor().id;
9366                this.selections
9367                    .all::<OffsetUtf16>(cx)
9368                    .iter()
9369                    .zip(ranges_to_replace.iter())
9370                    .find_map(|(selection, range)| {
9371                        if selection.id == newest_selection_id {
9372                            Some(
9373                                (range.start.0 as isize - selection.head().0 as isize)
9374                                    ..(range.end.0 as isize - selection.head().0 as isize),
9375                            )
9376                        } else {
9377                            None
9378                        }
9379                    })
9380            });
9381
9382            cx.emit(EditorEvent::InputHandled {
9383                utf16_range_to_replace: range_to_replace,
9384                text: text.into(),
9385            });
9386
9387            if let Some(new_selected_ranges) = new_selected_ranges {
9388                this.change_selections(None, cx, |selections| {
9389                    selections.select_ranges(new_selected_ranges)
9390                });
9391            }
9392
9393            this.handle_input(text, cx);
9394        });
9395
9396        if let Some(transaction) = self.ime_transaction {
9397            self.buffer.update(cx, |buffer, cx| {
9398                buffer.group_until_transaction(transaction, cx);
9399            });
9400        }
9401
9402        self.unmark_text(cx);
9403    }
9404
9405    fn replace_and_mark_text_in_range(
9406        &mut self,
9407        range_utf16: Option<Range<usize>>,
9408        text: &str,
9409        new_selected_range_utf16: Option<Range<usize>>,
9410        cx: &mut ViewContext<Self>,
9411    ) {
9412        if !self.input_enabled {
9413            cx.emit(EditorEvent::InputIgnored { text: text.into() });
9414            return;
9415        }
9416
9417        let transaction = self.transact(cx, |this, cx| {
9418            let ranges_to_replace = if let Some(mut marked_ranges) = this.marked_text_ranges(cx) {
9419                let snapshot = this.buffer.read(cx).read(cx);
9420                if let Some(relative_range_utf16) = range_utf16.as_ref() {
9421                    for marked_range in &mut marked_ranges {
9422                        marked_range.end.0 = marked_range.start.0 + relative_range_utf16.end;
9423                        marked_range.start.0 += relative_range_utf16.start;
9424                        marked_range.start =
9425                            snapshot.clip_offset_utf16(marked_range.start, Bias::Left);
9426                        marked_range.end =
9427                            snapshot.clip_offset_utf16(marked_range.end, Bias::Right);
9428                    }
9429                }
9430                Some(marked_ranges)
9431            } else if let Some(range_utf16) = range_utf16 {
9432                let range_utf16 = OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end);
9433                Some(this.selection_replacement_ranges(range_utf16, cx))
9434            } else {
9435                None
9436            };
9437
9438            let range_to_replace = ranges_to_replace.as_ref().and_then(|ranges_to_replace| {
9439                let newest_selection_id = this.selections.newest_anchor().id;
9440                this.selections
9441                    .all::<OffsetUtf16>(cx)
9442                    .iter()
9443                    .zip(ranges_to_replace.iter())
9444                    .find_map(|(selection, range)| {
9445                        if selection.id == newest_selection_id {
9446                            Some(
9447                                (range.start.0 as isize - selection.head().0 as isize)
9448                                    ..(range.end.0 as isize - selection.head().0 as isize),
9449                            )
9450                        } else {
9451                            None
9452                        }
9453                    })
9454            });
9455
9456            cx.emit(EditorEvent::InputHandled {
9457                utf16_range_to_replace: range_to_replace,
9458                text: text.into(),
9459            });
9460
9461            if let Some(ranges) = ranges_to_replace {
9462                this.change_selections(None, cx, |s| s.select_ranges(ranges));
9463            }
9464
9465            let marked_ranges = {
9466                let snapshot = this.buffer.read(cx).read(cx);
9467                this.selections
9468                    .disjoint_anchors()
9469                    .iter()
9470                    .map(|selection| {
9471                        selection.start.bias_left(&*snapshot)..selection.end.bias_right(&*snapshot)
9472                    })
9473                    .collect::<Vec<_>>()
9474            };
9475
9476            if text.is_empty() {
9477                this.unmark_text(cx);
9478            } else {
9479                this.highlight_text::<InputComposition>(
9480                    marked_ranges.clone(),
9481                    HighlightStyle::default(), // todo!() this.style(cx).composition_mark,
9482                    cx,
9483                );
9484            }
9485
9486            this.handle_input(text, cx);
9487
9488            if let Some(new_selected_range) = new_selected_range_utf16 {
9489                let snapshot = this.buffer.read(cx).read(cx);
9490                let new_selected_ranges = marked_ranges
9491                    .into_iter()
9492                    .map(|marked_range| {
9493                        let insertion_start = marked_range.start.to_offset_utf16(&snapshot).0;
9494                        let new_start = OffsetUtf16(new_selected_range.start + insertion_start);
9495                        let new_end = OffsetUtf16(new_selected_range.end + insertion_start);
9496                        snapshot.clip_offset_utf16(new_start, Bias::Left)
9497                            ..snapshot.clip_offset_utf16(new_end, Bias::Right)
9498                    })
9499                    .collect::<Vec<_>>();
9500
9501                drop(snapshot);
9502                this.change_selections(None, cx, |selections| {
9503                    selections.select_ranges(new_selected_ranges)
9504                });
9505            }
9506        });
9507
9508        self.ime_transaction = self.ime_transaction.or(transaction);
9509        if let Some(transaction) = self.ime_transaction {
9510            self.buffer.update(cx, |buffer, cx| {
9511                buffer.group_until_transaction(transaction, cx);
9512            });
9513        }
9514
9515        if self.text_highlights::<InputComposition>(cx).is_none() {
9516            self.ime_transaction.take();
9517        }
9518    }
9519
9520    fn bounds_for_range(
9521        &mut self,
9522        range_utf16: Range<usize>,
9523        element_bounds: gpui::Bounds<Pixels>,
9524        cx: &mut ViewContext<Self>,
9525    ) -> Option<gpui::Bounds<Pixels>> {
9526        let text_layout_details = self.text_layout_details(cx);
9527        let style = &text_layout_details.editor_style;
9528        let font_id = cx.text_system().font_id(&style.text.font()).unwrap();
9529        let font_size = style.text.font_size.to_pixels(cx.rem_size());
9530        let line_height = style.text.line_height_in_pixels(cx.rem_size());
9531        let em_width = cx
9532            .text_system()
9533            .typographic_bounds(font_id, font_size, 'm')
9534            .unwrap()
9535            .size
9536            .width;
9537
9538        let snapshot = self.snapshot(cx);
9539        let scroll_position = snapshot.scroll_position();
9540        let scroll_left = scroll_position.x * em_width;
9541
9542        let start = OffsetUtf16(range_utf16.start).to_display_point(&snapshot);
9543        let x = snapshot.x_for_display_point(start, &text_layout_details) - scroll_left
9544            + self.gutter_width;
9545        let y = line_height * (start.row() as f32 - scroll_position.y);
9546
9547        Some(Bounds {
9548            origin: element_bounds.origin + point(x, y),
9549            size: size(em_width, line_height),
9550        })
9551    }
9552}
9553
9554trait SelectionExt {
9555    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize>;
9556    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point>;
9557    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint>;
9558    fn spanned_rows(&self, include_end_if_at_line_start: bool, map: &DisplaySnapshot)
9559        -> Range<u32>;
9560}
9561
9562impl<T: ToPoint + ToOffset> SelectionExt for Selection<T> {
9563    fn point_range(&self, buffer: &MultiBufferSnapshot) -> Range<Point> {
9564        let start = self.start.to_point(buffer);
9565        let end = self.end.to_point(buffer);
9566        if self.reversed {
9567            end..start
9568        } else {
9569            start..end
9570        }
9571    }
9572
9573    fn offset_range(&self, buffer: &MultiBufferSnapshot) -> Range<usize> {
9574        let start = self.start.to_offset(buffer);
9575        let end = self.end.to_offset(buffer);
9576        if self.reversed {
9577            end..start
9578        } else {
9579            start..end
9580        }
9581    }
9582
9583    fn display_range(&self, map: &DisplaySnapshot) -> Range<DisplayPoint> {
9584        let start = self
9585            .start
9586            .to_point(&map.buffer_snapshot)
9587            .to_display_point(map);
9588        let end = self
9589            .end
9590            .to_point(&map.buffer_snapshot)
9591            .to_display_point(map);
9592        if self.reversed {
9593            end..start
9594        } else {
9595            start..end
9596        }
9597    }
9598
9599    fn spanned_rows(
9600        &self,
9601        include_end_if_at_line_start: bool,
9602        map: &DisplaySnapshot,
9603    ) -> Range<u32> {
9604        let start = self.start.to_point(&map.buffer_snapshot);
9605        let mut end = self.end.to_point(&map.buffer_snapshot);
9606        if !include_end_if_at_line_start && start.row != end.row && end.column == 0 {
9607            end.row -= 1;
9608        }
9609
9610        let buffer_start = map.prev_line_boundary(start).0;
9611        let buffer_end = map.next_line_boundary(end).0;
9612        buffer_start.row..buffer_end.row + 1
9613    }
9614}
9615
9616impl<T: InvalidationRegion> InvalidationStack<T> {
9617    fn invalidate<S>(&mut self, selections: &[Selection<S>], buffer: &MultiBufferSnapshot)
9618    where
9619        S: Clone + ToOffset,
9620    {
9621        while let Some(region) = self.last() {
9622            let all_selections_inside_invalidation_ranges =
9623                if selections.len() == region.ranges().len() {
9624                    selections
9625                        .iter()
9626                        .zip(region.ranges().iter().map(|r| r.to_offset(buffer)))
9627                        .all(|(selection, invalidation_range)| {
9628                            let head = selection.head().to_offset(buffer);
9629                            invalidation_range.start <= head && invalidation_range.end >= head
9630                        })
9631                } else {
9632                    false
9633                };
9634
9635            if all_selections_inside_invalidation_ranges {
9636                break;
9637            } else {
9638                self.pop();
9639            }
9640        }
9641    }
9642}
9643
9644impl<T> Default for InvalidationStack<T> {
9645    fn default() -> Self {
9646        Self(Default::default())
9647    }
9648}
9649
9650impl<T> Deref for InvalidationStack<T> {
9651    type Target = Vec<T>;
9652
9653    fn deref(&self) -> &Self::Target {
9654        &self.0
9655    }
9656}
9657
9658impl<T> DerefMut for InvalidationStack<T> {
9659    fn deref_mut(&mut self) -> &mut Self::Target {
9660        &mut self.0
9661    }
9662}
9663
9664impl InvalidationRegion for SnippetState {
9665    fn ranges(&self) -> &[Range<Anchor>] {
9666        &self.ranges[self.active_index]
9667    }
9668}
9669
9670// impl Deref for EditorStyle {
9671//     type Target = theme::Editor;
9672
9673//     fn deref(&self) -> &Self::Target {
9674//         &self.theme
9675//     }
9676// }
9677
9678pub fn diagnostic_block_renderer(diagnostic: Diagnostic, is_valid: bool) -> RenderBlock {
9679    let mut highlighted_lines = Vec::new();
9680
9681    for (index, line) in diagnostic.message.lines().enumerate() {
9682        let line = match &diagnostic.source {
9683            Some(source) if index == 0 => {
9684                let source_highlight = Vec::from_iter(0..source.len());
9685                highlight_diagnostic_message(source_highlight, &format!("{source}: {line}"))
9686            }
9687
9688            _ => highlight_diagnostic_message(Vec::new(), line),
9689        };
9690        highlighted_lines.push(line);
9691    }
9692    let message = diagnostic.message;
9693    Arc::new(move |cx: &mut BlockContext| {
9694        let message = message.clone();
9695        let copy_id: SharedString = format!("copy-{}", cx.block_id.clone()).to_string().into();
9696        let write_to_clipboard = cx.write_to_clipboard(ClipboardItem::new(message.clone()));
9697
9698        // TODO: Nate: We should tint the background of the block with the severity color
9699        // We need to extend the theme before we can do this
9700        v_stack()
9701            .id(cx.block_id)
9702            .relative()
9703            .size_full()
9704            .bg(gpui::red())
9705            .children(highlighted_lines.iter().map(|(line, highlights)| {
9706                let group_id = cx.block_id.to_string();
9707
9708                h_stack()
9709                    .group(group_id.clone())
9710                    .gap_2()
9711                    .absolute()
9712                    .left(cx.anchor_x)
9713                    .px_1p5()
9714                    .child(HighlightedLabel::new(line.clone(), highlights.clone()))
9715                    .child(
9716                        div()
9717                            .border()
9718                            .border_color(gpui::red())
9719                            .invisible()
9720                            .group_hover(group_id, |style| style.visible())
9721                            .child(
9722                                IconButton::new(copy_id.clone(), Icon::Copy)
9723                                    .icon_color(Color::Muted)
9724                                    .size(ButtonSize::Compact)
9725                                    .style(ButtonStyle::Transparent)
9726                                    .on_click(cx.listener(move |_, _, cx| write_to_clipboard))
9727                                    .tooltip(|cx| Tooltip::text("Copy diagnostic message", cx)),
9728                            ),
9729                    )
9730            }))
9731            .into_any_element()
9732    })
9733}
9734
9735pub fn highlight_diagnostic_message(
9736    initial_highlights: Vec<usize>,
9737    message: &str,
9738) -> (String, Vec<usize>) {
9739    let mut message_without_backticks = String::new();
9740    let mut prev_offset = 0;
9741    let mut inside_block = false;
9742    let mut highlights = initial_highlights;
9743    for (match_ix, (offset, _)) in message
9744        .match_indices('`')
9745        .chain([(message.len(), "")])
9746        .enumerate()
9747    {
9748        message_without_backticks.push_str(&message[prev_offset..offset]);
9749        if inside_block {
9750            highlights.extend(prev_offset - match_ix..offset - match_ix);
9751        }
9752
9753        inside_block = !inside_block;
9754        prev_offset = offset + 1;
9755    }
9756
9757    (message_without_backticks, highlights)
9758}
9759
9760pub fn diagnostic_style(
9761    severity: DiagnosticSeverity,
9762    valid: bool,
9763    style: &DiagnosticStyle,
9764) -> Hsla {
9765    match (severity, valid) {
9766        (DiagnosticSeverity::ERROR, true) => style.error,
9767        (DiagnosticSeverity::ERROR, false) => style.error,
9768        (DiagnosticSeverity::WARNING, true) => style.warning,
9769        (DiagnosticSeverity::WARNING, false) => style.warning,
9770        (DiagnosticSeverity::INFORMATION, true) => style.info,
9771        (DiagnosticSeverity::INFORMATION, false) => style.info,
9772        (DiagnosticSeverity::HINT, true) => style.info,
9773        (DiagnosticSeverity::HINT, false) => style.info,
9774        _ => style.ignored,
9775    }
9776}
9777
9778pub fn styled_runs_for_code_label<'a>(
9779    label: &'a CodeLabel,
9780    syntax_theme: &'a theme::SyntaxTheme,
9781) -> impl 'a + Iterator<Item = (Range<usize>, HighlightStyle)> {
9782    let fade_out = HighlightStyle {
9783        fade_out: Some(0.35),
9784        ..Default::default()
9785    };
9786
9787    let mut prev_end = label.filter_range.end;
9788    label
9789        .runs
9790        .iter()
9791        .enumerate()
9792        .flat_map(move |(ix, (range, highlight_id))| {
9793            let style = if let Some(style) = highlight_id.style(syntax_theme) {
9794                style
9795            } else {
9796                return Default::default();
9797            };
9798            let mut muted_style = style;
9799            muted_style.highlight(fade_out);
9800
9801            let mut runs = SmallVec::<[(Range<usize>, HighlightStyle); 3]>::new();
9802            if range.start >= label.filter_range.end {
9803                if range.start > prev_end {
9804                    runs.push((prev_end..range.start, fade_out));
9805                }
9806                runs.push((range.clone(), muted_style));
9807            } else if range.end <= label.filter_range.end {
9808                runs.push((range.clone(), style));
9809            } else {
9810                runs.push((range.start..label.filter_range.end, style));
9811                runs.push((label.filter_range.end..range.end, muted_style));
9812            }
9813            prev_end = cmp::max(prev_end, range.end);
9814
9815            if ix + 1 == label.runs.len() && label.text.len() > prev_end {
9816                runs.push((prev_end..label.text.len(), fade_out));
9817            }
9818
9819            runs
9820        })
9821}
9822
9823pub fn split_words<'a>(text: &'a str) -> impl std::iter::Iterator<Item = &'a str> + 'a {
9824    let mut index = 0;
9825    let mut codepoints = text.char_indices().peekable();
9826
9827    std::iter::from_fn(move || {
9828        let start_index = index;
9829        while let Some((new_index, codepoint)) = codepoints.next() {
9830            index = new_index + codepoint.len_utf8();
9831            let current_upper = codepoint.is_uppercase();
9832            let next_upper = codepoints
9833                .peek()
9834                .map(|(_, c)| c.is_uppercase())
9835                .unwrap_or(false);
9836
9837            if !current_upper && next_upper {
9838                return Some(&text[start_index..index]);
9839            }
9840        }
9841
9842        index = text.len();
9843        if start_index < text.len() {
9844            return Some(&text[start_index..]);
9845        }
9846        None
9847    })
9848    .flat_map(|word| word.split_inclusive('_'))
9849    .flat_map(|word| word.split_inclusive('-'))
9850}
9851
9852trait RangeToAnchorExt {
9853    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor>;
9854}
9855
9856impl<T: ToOffset> RangeToAnchorExt for Range<T> {
9857    fn to_anchors(self, snapshot: &MultiBufferSnapshot) -> Range<Anchor> {
9858        snapshot.anchor_after(self.start)..snapshot.anchor_before(self.end)
9859    }
9860}