editor.rs

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