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