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