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