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