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